子句头部的算术运算

时间:2015-12-12 17:01:01

标签: prolog logic-programming

我是一个Prolog谓词,它将笛卡尔坐标系中的某些点(myPosition(2,2))与邻域中的其他点进行比较。因此,它应该显示我们应该选择从myPosition(2,2)到那个点的方向(北,东,南,西)。以下是我的.pl文件的代码:

myPosition(2,2).

turn_to_east(X+1,Y) :-
    myPosition(X,Y),
    write('East.').

turn_to_west(X-1,Y) :-
    myPosition(X,Y),
    write('West.').

turn_to_north(X,Y+1) :-
    myPosition(X,Y),
    write('North.').

turn_to_south(X,Y-1) :-
    myPosition(X,Y),
    write('South.').

turn_to_the_point(X,Y) :- turn_to_east(X,Y).
turn_to_the_point(X,Y) :- turn_to_west(X,Y).
turn_to_the_point(X,Y) :- turn_to_north(X,Y).
turn_to_the_point(X,Y) :- turn_to_south(X,Y).

然后,当我将文件上传到SWI-Prolog并写下:

turn_to_the_point(1,2).

我得到了:

false.

为什么我不能得到答案'西方'。还是其他什么?

1 个答案:

答案 0 :(得分:2)

原因是默认情况下Prolog会不解释+- 和其他算术运算符。 1+1只是1+1(这是+(1,1)的语法糖),不是2 。如果您想要定义自己的表达式求值程序,并且看到+作为布尔求和,或者完全不同的话,那么这可能很有用。

然而,有一种方法可以崩溃这样的表达式,以便使用(is)/2谓词从2中导出1+1。例如:

turn_to_east(NX,Y) :-
    myPosition(X,Y),
    NX is X+1,
    write('East.').

鉴于您使用turn_to_east/2turn_to_east(1,2)查询NX = 1。现在,您获取myPosition/2数据:X = 2Y = 2。 Prolog在此期间进行等价检查,并发现turn_to_east/2的Y坐标与myPosition的Y坐标相同。接下来,它会将2+1折叠为3并看到这不等同于NX = 1,因此此谓词失败。但如果您查询过turn_to_east(3,1),它就会成功,从而写出East.

如果您使用上面讨论的概念修改整个理论,例如:

myPosition(2,2).

turn_to_east(NX,Y) :-
    myPosition(X,Y),
    NX is X+1,
    write('East.').

turn_to_west(NX,Y) :-
    myPosition(X,Y),
    NX is X-1,
    write('West.').

turn_to_north(X,NY) :-
    myPosition(X,Y),
    NY is Y+1,
    write('North.').

turn_to_south(X,NY) :-
    myPosition(X,Y),
    NY is Y-1,
    write('South.').

turn_to_the_point(X,Y) :- turn_to_east(X,Y).
turn_to_the_point(X,Y) :- turn_to_west(X,Y).
turn_to_the_point(X,Y) :- turn_to_north(X,Y).
turn_to_the_point(X,Y) :- turn_to_south(X,Y).

它正确回答了查询:

?- turn_to_the_point(1,2).
West.
true ;
false.

一般说明,谓词最好没有像write/1这样的副作用:这不仅适用于Prolog,几乎所有编程语言都建议将程序拆分为计算相互作用。也许更好的解决方法是将方向视为参数:

myPosition(2,2).

turn_to_point(NX,Y,east) :-
    myPosition(X,Y),
    NX is X+1.
turn_to_point(NX,Y,west) :-
    myPosition(X,Y),
    NX is X-1.

turn_to_point(X,NY,north) :-
    myPosition(X,Y),
    NY is Y+1.

turn_to_point(X,NY,south) :-
    myPosition(X,Y),
    NY is Y-1.

turn_to_the_point(X,Y) :-
    turn_to_point(X,Y,D),
    write(D).

在这种情况下,turn_to_the_point/2谓词显然是交互谓词,而其turn_to_the_point/3变体则进行计算。