序言中的等价关系

问题描述

我想在Prolog代码中实现一个简单的 if and only if 关系。这是我想要的简单示例:

?- a_iff_b(a,b).
true.

?- a_iff_b(x,x).
true.

?- a_iff_b(a,x).
false.

?- a_iff_b(x,b).
false.

您明白了—如果第一个参数是a且第二个参数是b或第一个参数a或第二个参数都不是,则谓词应为true b。我希望这是有道理的。从数学上讲,X = a <==> Y = b

这是我的尝试:

a_iff_b(X,Y) :-
        X = a,Y = b;
        X \= a,Y \= b.

但是此代码引入了一个选择点:

?- a_iff_b(a,b).
true ;
false.

为什么?看来以下作品有效,我的意思是它没有介绍选择点:

a_iff_b(X,Y) :- (X = a -> Y = b; Y \= b).

但是,我发现它的可读性较差,特别是因为在我的实际谓词中,等价性的两侧更加复杂(这也是谓词)。

解决方法

您的代码引入了一个选择点,因为它包含了;运算符引入的选择。您可能会认为它是“逻辑或”运算符,在某种程度上来说是这样。但是在程序上,它是“在此处引入一个选择点,并且在回溯时,也探索第二个分支”运算符。

确实,功能强大的Prolog Compiler™可能会认识到这里的两个分支是互斥的,但是您的Prolog系统似乎没有那么强大。如果您可以免费获得任何Prolog能够在没有选择点的情况下做到这一点,我至少会感到有点惊讶。如您所说,尤其是当您的实际情况更复杂时。

如果您希望此内容更具可读性,请提示:

  • 通常,从不在行尾使用;,就好像它只是,的变体一样。太容易错过了,因为人们普遍期望行以,结尾。尝试以某种确实能使;突出的方式格式化代码(请参见下面的示例)。

  • 通常,如果要使用;(而不是_ -> _ ; _),尤其是作为子句中的单个顶级目标,请考虑改用单独的子句:

      a_iff_b(a,b).
      a_iff_b(X,Y) :-
          X \= a,Y \= b.
    

在任何情况下,以下所有方法都是取消选择的可能方法:

a_iff_b_1(a,b) :-
    !.
a_iff_b_1(X,Y) :-
    X \= a,Y \= b.

a_iff_b_2(X,Y) :-
    (   X = a,Y = b
    ->  true
    ;   X \= a,Y \= b ).

a_iff_b_3(X,Y = b,!
    ;   X \= a,Y \= b ).

a_iff_b_4(X,Y = b
    ;   X \= a,Y \= b ),!.

a_iff_b_5(X,Y) :-
    once(( X = a,Y = b
         ; X \= a,Y \= b )).

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...