Prolog - 创建简单的功能

时间:2017-05-23 12:27:31

标签: prolog

我有一个使用4个参数的函数,称为tile。它旨在以下列方式工作:

tile(?E, ?S, ?W, ?N, ?ID)

我想要一个给定ID的getter函数,它返回前4个参数:E, S, WN。 我尝试过类似的东西:

coordonates(tile(E,S,W,N,L), (E,S,W,N)).

但它不会返回实际值,只会返回true。 如果我在终端中键入tile(E, S, W, N, #1),我会得到所需的结果,但我不知道究竟返回了什么(列表可能?)。

2 个答案:

答案 0 :(得分:3)

让我们假设我们描述tile的事实如下:

tile(p1,p2,p3,p4,id1).
tile(q1,q2,q3,q4,id2).
tile(r1,r2,r3,r4,id3).

在这里,我们有一些有限的事实。可以通过tile的最常规查询来检查:

?- tile(E,S,W,N,I).
E = p1,
S = p2,
W = p3,
N = p4,
I = id1 ;             % <---- user input ; to continue
E = q1,
S = q2,
W = q3,
N = q4,
I = id2 ;             % <---- user input ; to continue
E = r1,
S = r2,
W = r3,
N = r4,
I = id3.              % <---- toplevel outputs . -- we're done

所以从理论上讲,我们可以按如下方式定义coordonates

coordonates(id1, t(p1, p2, p3, p4)).
coordonates(id2, t(q1, q2, q3, q4)).
coordonates(id3, t(r1, r2, r3, r4)).

可以查询id2,如下所示:

?- coordonates(id2,X).
X = t(q1, q2, q3, q4).

我使用仿函数t对解决方案进行分组,以明确它不是我们之前定义的谓词tile。这个定义中还有很多重复,这已经是一个暗示,我们可以做得更好。我们正在寻找的是一条规则,告诉我们如果我们得到tile的答案,我们可以描述coordonates。从逻辑上讲,这是作为形式的含义写的:goal1∧...∧目标N→头。这意味着“假设我知道goalN的goal1是真的,那么我也知道头是真的。”在Prolog中,这是向后写的:

head :-
  goal1,
  % ...
  goalN.

让我们回到我们的任务:我们对瓷砖有所了解,我们想要描述投影的样子。这意味着,我们的代码如下所示:

coordonates( ... ) :-
  % ...
  tile(E,S,W,N,I).

正文tile(E,S,W,N,I)是我们可以编写的最通用的形式(参见上面的查询),并且可以读作“假设我在坐标E S W N处有任何具有id I的图块”。现在我们只需要填写coordonates应该是什么样子。我们知道它有两个参数,因为它将id与其他四个元素联系起来。让我们给他们起名字,比如IdCoords

coordonates(Id, Coords) :-
  % ...
  tile(E,S,W,N,I).

现在我们只需要找出如何将E,S,E,N和I与Id和Coords联系起来。一个很简单:Id只是I。另一个也不太难,我们只需要将坐标分组为一个术语。我们可以选择任意一个,但已经决定采用t,所以我们会坚持下去:

coordonates(Id, Coords) :-
  Id = I,
  Coords = t(E,S,W,N),
  tile(E,S,W,N,I).

这已经按照我们的预期运作了:

?- coordonates(X,Y).
X = id1,
Y = t(p1, p2, p3, p4) ;
X = id2,
Y = t(q1, q2, q3, q4) ;
X = id3,
Y = t(r1, r2, r3, r4).

现在我们可以做一个观察:如果两个术语相等,我们可以使用一个而不是另一个。因此,我们可以重用Id = I而不是撰写IdCoordst(E,S,W,N)

也是如此
coordonates(I, t(E,S,W,N)) :-
    tile(E,S,W,N,I).

它不能短得多: - )

答案 1 :(得分:0)

您必须声明'E,S,W和N',以便prolog可以在您进行查询时将这些参数与输入统一起来。像(在最基本的情况下):

tile(['cordE1','cordS1','cordW1','cordN1'],1).
tile(['cordE2','cordS2','cordW2','cordN2'],2).
tile(['cordE3','cordS3','cordW3','cordN3'],3).

查询:

?- tile(C,2).
C = [cordE2, cordS2, cordW2, cordN2].

?- tile(C,1).
C = [cordE1, cordS1, cordW1, cordN1].

?- tile(C,3).
C = [cordE3, cordS3, cordW3, cordN3].