我如何模拟soft cut I *-> T;在ISO Prolog中是E?我有副作用,所以我不能多次称呼它。

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

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

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

最佳答案

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

关于prolog - 如何在Prolog中模拟软切?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40620465/

10-16 14:20