SWI-Prolog中的catch/3和call_with_time_limit/2谓词

Moc*_*ird 8 timeout prolog swi-prolog

我想用

catch(:Goal, +Catcher, :Recover)
Run Code Online (Sandbox Code Playgroud)

目标在哪里

call_with_time_limit(+Time, :Goal)
Run Code Online (Sandbox Code Playgroud)

它搞砸了,我无法找到正确的方法来了解上述情况之一发生时间:

1)由于超时,目标停止了.

2)目标失败(有时候会失败).

我试过了:

(catch(call_with_time_limit(Time, Goal), Catcher, Recover) ->
(ground(Catcher), Catcher = time_limit_exceeded), **TIMEOUT ACTIONS**)
;
(**SUCCESS ACTIONS**))
;
**FAILURE ACTIONS**
)
Run Code Online (Sandbox Code Playgroud)

*编辑*

图案:

我使用以下模式:

((catch(call_with_time_limit(6,goal),
    Exception,
    true),(var(Exception);Exception=time_limit_exceeded))
->
    (var(Exception) -> writeln(succ) ; writeln(timeout))
;
    writeln(fail)
).
Run Code Online (Sandbox Code Playgroud)

该模式在4秒或更长时间内不起作用 - 它只是忽略了超时请求.

fal*_*lse 6

您的问题涉及两个不同的部分.首先,如何catch/3用来处理这种情况的方式.然后是超时机制本身.

捕获错误和异常 catch/3

一般来说,最惯用的方式catch/3是这样的:

   ...,
   catch((R = success, Goal), Pat, R = error(Pat)),
   ...
Run Code Online (Sandbox Code Playgroud)

但是,捕获所有错误/异常通常会导致容易出错的程序,因为可能会掩盖严重的意外错误.

在您的特定情况下,您只想捕获一个模式,因此:

   ...,
   catch((R = success, call_with_time_limit(Time,Goal)),
          time_limit_exceeded,
          R = timeout ),
   ...
Run Code Online (Sandbox Code Playgroud)

请注意,使用未经实例化的变量进行测试var(Pat)可能是一个容易错过的错误来源.

处理超时

各种系统提供了几种接口.但最根本的问题是你真正想要实现的目标.您想限制实时,CPU时间还是资源?

time_out/3in library(timeout)可能是最先进的,最初是为SICStus Prolog开发的,大约在1992年.在SWI和YAP中有一些兼容的实现.但是,SWI和YAP无法处理嵌套案例.并且SWI不限制CPU时间.界面是:

time_out(:Goal_0, +TimeMs, -Result)
Run Code Online (Sandbox Code Playgroud)

call_with_time_limit/3是一个相当特殊的SWI内置,它不符合内置命令的常见约定.此外,它仅仅将其目标称为once(Goal_0).我宁愿不.

call_with_inference_limit/3目前仅在最新版本的SWI中出现,并使用类似的约定time_out/3.它限制了推理的数量而不是CPU时间.因此它非常适合检测程序员的循环,但可能不适合您的任务.

wait_for_input/3 如果您的超时仅与阅读数据相关,则可能是您的选择.