“如果”在序言中?

有没有办法在 prolog 中执行 if,例如,如果一个变量为0,那么执行一些操作(向终端写入文本)。甚至不需要 else,但我找不到任何关于 if 的文档。

248092 次浏览

Prolog 程序实际上是“如果”和“那么”的大条件,后者打印“目标已达到”,而后者打印“没有找到解决方案”。A, B表示“ A 为真,B 为真”,如果不能到达“ A”,大多数 prolog 系统将不会尝试满足“ B”(例如,当 X = 3时,X=3, write('X is 3'),nl将打印“ X 为3”,如果 X = 2则什么也不做)。

标准的 prolog 谓词将执行此操作。

   isfive(5).

如果用5调用它,它的值将为 true; 如果用其他方法运行它,则返回 false。对于不等于你使用 =

isNotEqual(A,B):- A\=B.

技术上它是不统一的,但它类似于不平等。

现在学习 Prolog 是一个很好的学习 Prolog 的网站。

编辑: 添加另一个示例。

isEqual(A,A).

是的,在 ISO Prolog 中有这样一个控制结构,叫做 ->。你可以这样使用它:

( condition -> then_clause ; else_clause )

下面是一个使用 else-if-子句链的示例:

(   X < 0 ->
writeln('X is negative.  That's weird!  Failing now.'),
fail
;   X =:= 0 ->
writeln('X is zero.')
;   writeln('X is positive.')
)

注意,如果省略 else 子句,则条件失败将意味着整个 if 语句将失败。因此,我建议总是包含 else-子句(即使它只是 true)。

Prolog 谓词“ unify”-

所以,我会用命令式语言写

function bazoo(integer foo)
{
if(foo == 5)
doSomething();
else
doSomeOtherThing();
}

我会用 Prolog 写

bazoo(5) :-  doSomething.
bazoo(Foo) :- Foo =/= 5, doSomeOtherThing.

当你了解这两种风格的时候,你就会更清楚了。
“当 foo 是5的时候,我对特殊情况很不满意”
“当 foo 不是5的时候,我对正常情况很不满意”

我发现这对在规则中使用 如果语句很有帮助。

max(X,Y,Z) :-
(  X =< Y
-> Z = Y
;  Z = X
).

多亏了 http://cs.union.edu/~striegnk/learn-prolog-now/html/node89.html

最好的方法是使用所谓的 cuts,它的符号是 !

if_then_else(Condition, Action1, Action2) :- Condition, !, Action1.
if_then_else(Condition, Action1, Action2) :- Action2.

以上是条件函数的基本结构。

例如,下面是 max函数:

max(X,Y,X):-X>Y,!.
max(X,Y,Y):-Y=<X.

我建议阅读更多关于削减的文档,但一般来说,它们就像断点一样。 例如: 如果第一个 max函数返回一个真值,则不验证第二个函数。

附言: 我刚到 Prolog,但这是我发现的。

(  A == B ->
writeln("ok")
;
writeln("nok")
),

其他部分是必需的

首先,让我们回想一些经典的一阶逻辑:

如果 P 那么 Q 别的 R”相当于“(P 还有 Q) 或者(non _ P 还有 R)”。


在 Prolog,我们如何表达“如果-那么-否则”?

让我们举一个具体的例子:

如果 X是列表 [1,2] 那么 X = 2 别的 X = 4的成员。

我们可以匹配上述模式(“ 如果 P 那么 Q 别的 R”) ,如果..。

  • 条件 Plist_member([1,2],X),
  • 否定条件 non_Pnon_member([1,2],X),
  • 结果 QX=2
  • 选择 RX=4

为了以一种纯粹的方式表示列表(非)成员,我们定义:

list_memberd([E|Es],X) :-
(  E = X
;  dif(E,X),
list_memberd(Es,X)
).


non_member(Es,X) :-
maplist(dif(X),Es).

让我们看看在 Prolog 中表达“ if-then-else”的不同方式!

  1. (P,Q ; non_P,R)

    ?-      (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4).
    X = 2 ; X = 4.
    ?- X=2, (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=2.
    X = 2 ; false.
    ?-      (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=2.
    X = 2 ; false.
    ?- X=4, (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=4.
    X = 4.
    ?-      (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=4.
    X = 4.
    

    正确率5/5效率3/5。

  2. (P -> Q ; R)

    ?-      (list_memberd([1,2],X) -> X=2 ; X=4).
    false.                                                % WRONG
    ?- X=2, (list_memberd([1,2],X) -> X=2 ; X=4), X=2.
    X = 2.
    ?-      (list_memberd([1,2],X) -> X=2 ; X=4), X=2.
    false.                                                % WRONG
    ?- X=4, (list_memberd([1,2],X) -> X=2 ; X=4), X=4.
    X = 4.
    ?-      (list_memberd([1,2],X) -> X=2 ; X=4), X=4.
    false.                                                % WRONG
    

    正确率2/5效率2/5。

  3. (P *-> Q ; R)

    ?-      (list_memberd([1,2],X) *-> X=2 ; X=4).
    X = 2 ; false.                                        % WRONG
    ?- X=2, (list_memberd([1,2],X) *-> X=2 ; X=4), X=2.
    X = 2 ; false.
    ?-      (list_memberd([1,2],X) *-> X=2 ; X=4), X=2.
    X = 2 ; false.
    ?- X=4, (list_memberd([1,2],X) *-> X=2 ; X=4), X=4.
    X = 4.
    ?-      (list_memberd([1,2],X) *-> X=2 ; X=4), X=4.
    false.                                                % WRONG
    

    正确率3/5效率1/5。


(初步)摘要:

  1. (P,Q ; non_P,R)是正确的,但是需要一个离散的 non_P实现。

  2. 当实例化不足时,(P -> Q ; R)会丢失声明性语义。

  3. (P *-> Q ; R)(P -> Q ; R)“少”不完整,但仍有类似的问题。


幸运的是,我们有 替代品: 输入逻辑单调控制结构 if_/3

我们可以将 if_/3与具体化的列表成员谓词 memberd_t/3一起使用,如下所示:

?-      if_(memberd_t(X,[1,2]), X=2, X=4).
X = 2 ; X = 4.
?- X=2, if_(memberd_t(X,[1,2]), X=2, X=4), X=2.
X = 2.
?-      if_(memberd_t(X,[1,2]), X=2, X=4), X=2.
X = 2 ; false.
?- X=4, if_(memberd_t(X,[1,2]), X=2, X=4), X=4.
X = 4.
?-      if_(memberd_t(X,[1,2]), X=2, X=4), X=4.
X = 4.

正确率5/5效率4/5。

在 Prolog,类似 if-then-else 这样的表达方式基本上有三种。为了比较它们,考虑 char_class/2。对于 ab,所有其他学期的课程应该是 abother。人们可以这样笨拙地写:

char_class(a, ab).
char_class(b, ab).
char_class(X, other) :-
dif(X, a),
dif(X, b).


?- char_class(Ch, Class).
Ch = a, Class = ab
;  Ch = b, Class = ab
;  Class = other,
dif(Ch, a), dif(Ch, b).

为了更紧凑地编写内容,需要使用 if-then-else 结构:

?- ( ( Ch = a ; Ch = b ) -> Class = ab ; Class = other ).
Ch = a, Class = ab.

虽然这个答案是合理的,但它是不完整的。只给出了 ( Ch = a ; Ch = b )的第一个答案。其他的答案都被砍掉了。没什么关系。

一个更好的结构,通常被称为“软切割”(不要相信这个名字,一个切割就是一个切割) ,给出稍微好一点的结果(这是在 YAP 中) :

?- ( ( Ch = a ; Ch = b ) *-> Class = ab ; Class = other ).
Ch = a, Class = ab
;  Ch = b, Class = ab.

另外,SICStus 的 if/3具有非常相似的语义:

?- if( ( Ch = a ; Ch = b ), Class = ab , Class = other ).
Ch = a, Class = ab
;  Ch = b, Class = ab.

因此最后一个答案仍然被抑制。现在为 SICStus是啊SWI输入 library(reif)。安装它并说:

?- use_module(library(reif)).


?- if_( ( Ch = a ; Ch = b ), Class = ab , Class = other ).
Ch = a, Class = ab
;  Ch = b, Class = ab
;  Class = other,
dif(Ch, a), dif(Ch, b).

注意,所有的 if_/3都被编译成一个广泛嵌套的 if-then-else for

char_class(Ch, Class) :-
if_( ( Ch = a ; Ch = b ), Class = ab , Class = other ).

它在 YAP 6.3.4中扩展到:

char_class(A,B) :-
( A\=a
->
( A\=b
->
B=other
;
( A==b
->
B=ab
)
;
A=b,
B=ab
;
dif(A,b),
B=other
)
;
( A==a
->
B=ab
)
;
A=a,
B=ab
;
dif(A,a),
( A\=b
->
B=other
;
( A==b
->
B=ab
)
;
A=b,
B=ab
;
dif(A,b),
B=other
)
).

你应该阅读 现在就学习 Prolog! 第10.2章使用 Cut,它提供了一个例子:

Max (X,Y,Z) :-X = < Y,! ,Y = Z.

应该说,

Z等于 Y 如果 !是真(它总是如此) 还有 X<= Y