如何在Prolog中模拟软切割?

时间:2016-11-15 21:58:05

标签: prolog iso-prolog xsb

如何模拟soft cut I * - >吨; E在ISO Prolog中?我有副作用,所以我可以多次调用它。

除了最后一项要求外,我认为以下定义有效:

if_(I, T, E) :-
    not(not(I)) ->
    call((I, T));
    call((not(I), E)).

(我实际上正在使用XSB prolog; XSB的解决方案对我也很有用。)

4 个答案:

答案 0 :(得分:4)

好吧,让我们发挥创意......你基本上需要一种方法来记住(跨越回溯)If-condition至少有一个解决方案。动态谓词对我来说是禁忌,但还有其他选择吗?好吧,ISO-Prolog定义了一种匿名对象, stream-term ,它可以(ab)用于以这种相当优雅的方式实现非可回溯标志:

if(If, Then, Else) :-
    open(., read, S),
    (
        If,
        close(S, [force(true)]),
        Then
    ;
        catch(close(S), error(existence_error(stream,_),_), fail),   % fail if already closed
        Else
    ).

我们关闭流以指示If有一个解决方案,然后通过else分支中的close-attempt来检测。这在ECLiPSe之类的系统中完美无泄漏。但是,许多系统(包括XSB)重新使用封闭流的标识符(ISO不禁止),使得此解决方案不可移植。

但是等等,流有一个位置属性,可以设置,并保留其值回溯!使用此技巧,以下内容适用于XSB

if(If, Then, Else) :-
    % open('ReadableAndNonemptyFile', read, S),      % general ISO
    open(atom(a), read, S),                          % XSB (needs no file)
    stream_property(S, position(Zero)),
    get_char(S, _),
    (
        catch(If, Ball, (close(S),throw(Ball))),
        set_stream_position(S, Zero),
        Then

    ; stream_property(S, position(Zero)) ->
        close(S),
        fail
    ;
        close(S),
        Else
    ).

可悲的是,open(atom(...),...)功能是特定于XSB的,对于严格的ISO-Prolog,您需要一个虚拟文件......

答案 1 :(得分:3)

Yes, we can在ISO Prolog中甚至在XSB中实现这一点,但效率不高。为了提高效率,你需要一些“选择性切割”。此外,XSB不实现ISO符合整数,因此必须单独处理溢出。

:- dynamic(if_counter/1).

if_counter(0).

:- dynamic(no_if_answer/1).
if(If_0, Then_0, Else_0) :-
   once(if_counter(Id)),
   Idx is Id+1,
   (  Idx > Id -> true
   ;  throw(error(representation_error(max_integer),
               'XSB misses ISO conforming integers'))
   ),
   retractall(if_counter(_)),
   asserta(if_counter(Idx)),
   asserta(no_if_answer(Id)),
   (  If_0,
      retractall(no_if_answer(Id)),
      Then_0
   ;  retract(no_if_answer(Id)) ->
      Else_0
   ).

效率低下的主要原因是,对于确定条件If_0,仍然有一个选择点。可靠的接下来是不可想象的,一旦执行retract(no_if_answer(Id)),实现可以得出结论retractall(no_if_answer(Id))将始终失败,但我怀疑实施者是否会投资于此类优化。编辑:这似乎非常不可能的原因是一个实现必须保证断言的数字总是上升。

请注意,软切割会以与切割相同的方式产生不完整性。考虑:

| ?- if(X = a, T = equal, T = not_equal).

X = a
T = equal;

no

这显然错过了一个答案!要了解原因,请X = b

| ?- X = b, if(X = a, T = equal, T = not_equal).

X = b
T = not_equal;

no
| ?- if(X = a, T = equal, T = not_equal), X = b.

no % bad!!

连词应该是可交换的(模数不终止,错误,副作用)。

如果您对声明性良好的条件感兴趣,这些条件也非常有效并且通常比其不纯的对应物更快,请考虑if_/3。有关SICStus的信息,请参阅library(reif),其中包含所有正确答案:

| ?- if_(X = a, T = equal, T = not_equal).
X = a,
T = equal ? ;
T = not_equal,
prolog:dif(X,a) ? ;
no

答案 2 :(得分:2)

您的定义未实现 soft-cut 语义:当测试成功时,您可以回溯到它。这是一个有用的控制结构(我用它来实现Logtalk中的共同诱导)但遗憾的是不能在Prolog级别以可移植方式实现,当然也不能在ISO Prolog标准的限制范围内实现。好消息是越来越多的Prolog系统实现了这种控制结构。这些包括SWI-Prolog,YAP,SICStus Prolog,GNU Prolog,CxProlog,ECLiPSe,Jekejeke Prolog和Ciao,没有特别的顺序。但请注意,虽然有些系统使用*->/2运算符,但有少数(SICStus Prolog和Ciao)使用if/3谓词(YAP同时使用)。此外,语义在极端情况下也有所不同(Logtalk发行版包括一个也检查*->/2变体的Prolog一致性套件)。

答案 3 :(得分:1)

问题是,软剪切应该相当聪明,而不应该 当其参数没有离开选择点时离开选择点。

SWI-Prolog中没有选择点:

   Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.4)

   ?- X=1 *-> Y=1; true.
   X = Y, Y = 1.
   ?- 

Jekejeke Prolog中没有选择点:

   Jekejeke Prolog 3, Runtime Library 1.3.6

   ?- X=1 *-> Y=1; true.
   X = 1,
   Y = 1
   ?- 

到目前为止,这里没有任何公认的创造性解决方案可以存档,因此它们都不能有效地替换本机实现。

Jekejeke Prolog做determinism check,然后 删除析取选择点。否则,它标志着 析取选择点。来自模块“逻辑”:

:- set_predicate_property(;/2, sys_nobarrier).
A *-> B; C :- sys_local_cut, sys_soft_cond(A, B, C).

:- set_predicate_property(sys_soft_cond/3, sys_nobarrier).
sys_soft_cond(A, B, _) :- sys_safe(A), sys_soft_local_cut, B.                        
sys_soft_cond(_, _, C) :- C.