lam*_*y.x 7 prolog meta-predicate
我试图定义一个callto_status(Goal, Status)总是成功的关系,并根据调用的结果统一Status Goal(换句话说,我想实现一个改进版本call_with_inference_limit/3).我的实现使用的SWI call_with_inference_limit/3具有相同的接口call_with_time_limit/3(在这种情况下也应该使它工作).实施call_with_..._limit并没有回溯,所以我认为最好不要给人一种报告目标答案替代的印象.
我介绍了辅助谓词derivable_st的可读性.它处理成功和超时的情况,但否则失败.
% if Goal succeeds, succeed with Status = true,
% if Goal times out, succeed with Status = timeout
% if Goal fails, fail
derivable_st(Goal, Status) :-
T = 10000, % set inference limit
% copy_term(Goal, G), % work on a copy of Goal, we don't want to report an answer substitution
call_with_inference_limit(G, T, R), % actual call to set inference limit
( R == !
-> Status = true % succeed deterministically, status = true
; R == true
-> Status = true % succeed non-deterministically, status = true
; ( R == inference_limit_exceeded % timeout
-> (
!, % make sure we do not backtrack after timeout
Status = timeout % status = timeout
)
; throw(unhandled_case) % this should never happen
)
).
Run Code Online (Sandbox Code Playgroud)
主谓词包围derivable_st并处理失败案例和可能抛出的异常(如果有的话).我们可能想要挑出堆栈溢出(在推理限制太高的情况下发生)但是现在我们只报告任何异常.
% if Goal succeeds, succeed with Status = true,
% if Goal times out, succeed with Status = timeout
% if Goal fails, succeed with Status = false
% if Goal throws an error, succeed with Status = exception(The_Exception)
% Goal must be sufficiently instantiated for call(Goal) but will stay unchanged
callto_status(Goal, Status) :-
catch(( derivable_st(Goal, S) % try to derive Goal
-> Status = S % in case of success / timeout, pass status on
; Status = false % in case of failure, pass failure status on, but succeed
),
Exception,
Status = exception(Exception) % wrap the exception into a status term
).
Run Code Online (Sandbox Code Playgroud)
谓词适用于一些简单的测试用例:
?- callto_reif( length(N,X), Status).
Status = true.
?- callto_reif( false, Status).
Status = false.
?- callto_reif( (length(N,X), false), Status).
Status = timeout.
Run Code Online (Sandbox Code Playgroud)
我现在的问题有点模糊:这个谓词做了我声称的吗?你看到任何错误/改进点吗?我很感激任何输入!
编辑:根据@false的建议,注释掉 copy_term/2
小智 1
这是一个更短的解决方案:
callto_status(Goal, Status) :-
call_with_inference_limit(Goal, 10000, Status0),
(Status0 = ! -> !, Status = true; Status = Status0).
callto_status(_, false).
Run Code Online (Sandbox Code Playgroud)
你看原来有多有用!status 是为了避免不必要的选择点:
?- callto_status(member(X,[1,2,3]), Y).
X = 1,
Y = true
X = 2,
Y = true
X = 3,
Y = true.
?- callto_status(fail, Y).
Y = false.
Run Code Online (Sandbox Code Playgroud)
当然你也可以替换Status0 = ! -> !, Status = true为Status0 = ! -> Status = trueonly。然后你总是会得到一个剩余的选择点:
?- callto_status(member(X,[1,2,3]), Y).
X = 1,
Y = true
X = 2,
Y = true
X = 3,
Y = true
Y = false.
Run Code Online (Sandbox Code Playgroud)
从这个问题并不清楚你到底想要什么。
| 归档时间: |
|
| 查看次数: |
111 次 |
| 最近记录: |