首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具体化的call_with_time_limit / call_with_inference_limit

具体化的call_with_time_limit / call_with_inference_limit
EN

Stack Overflow用户
提问于 2019-02-14 03:48:51
回答 1查看 138关注 0票数 6

我正在尝试定义一个总是成功的关系callto_status(Goal, Status),并根据调用Goal的结果统一状态(换句话说,我想实现call_with_inference_limit/3的一个具体化版本)。我的实现使用的是SWI的call_with_inference_limit/3,它具有与call_with_time_limit/3相同的接口(这应该也能使它在这种情况下工作)。call_with_..._limit的实现不会走回头路,所以我认为最好不要给人一种报告替代目标的答案的印象。

为了提高可读性,我引入了辅助谓词derivable_st。它处理成功和超时的情况,否则会失败。

代码语言:javascript
复制
% 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
       )
    ).

主谓词包装在derivable_st周围,并处理失败情况和可能抛出的异常(如果有)。我们可能想要挑出堆栈溢出(在推理限制太高的情况下发生),但现在我们只报告任何异常。

代码语言:javascript
复制
% 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
    ).

该谓词适用于一些简单的测试用例:

代码语言:javascript
复制
?- callto_reif( length(N,X), Status).
Status = true.

?- callto_reif( false, Status).
Status = false.

?- callto_reif( (length(N,X), false), Status).
Status = timeout.

我现在的问题有点模糊:这个谓词是否如我所说的那样做?你看到任何错误/改进点了吗?我非常感谢您的任何意见!

编辑:根据@false的建议,注释掉了copy_term/2

EN

回答 1

Stack Overflow用户

发布于 2019-07-27 20:57:15

这是一个较短的解决方案:

代码语言:javascript
复制
callto_status(Goal, Status) :-
    call_with_inference_limit(Goal, 10000, Status0),
    (Status0 = ! -> !, Status = true; Status = Status0).
callto_status(_, false).

你看到原来的有多有用了吧!状态是为了避免不必要的选择点:

代码语言:javascript
复制
?- 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.

当然,您也可以仅将Status0 = ! -> !, Status = true替换为Status0 = ! -> Status = true。然后,您将始终获得剩余的选择点:

代码语言:javascript
复制
?- callto_status(member(X,[1,2,3]), Y).
X = 1,
Y = true 
X = 2,
Y = true 
X = 3,
Y = true 
Y = false.

从这个问题看,你到底想要什么并不清楚。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54678295

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档