Prolog-创建简单函数

Prolog-创建简单函数,prolog,Prolog,我有一个使用4个参数的函数,叫做tile。其设计工作方式如下: tile(?E, ?S, ?W, ?N, ?ID) 我想要一个getter函数,它在给定ID时返回前4个参数:E、S、W和N。 我试过这样的方法: coordonates(tile(E,S,W,N,L), (E,S,W,N)). 但它不返回实际值,只返回true。 如果我在终端中键入tile(E,S,W,N,#1),我会得到所需的结果,但我不知道返回的是什么(可能是列表?)您必须声明“E,S,W和N”,以便prolog可以在进行

我有一个使用4个参数的函数,叫做
tile
。其设计工作方式如下:

tile(?E, ?S, ?W, ?N, ?ID)
我想要一个getter函数,它在给定ID时返回前4个参数:
E、S、W
N
。 我试过这样的方法:

coordonates(tile(E,S,W,N,L), (E,S,W,N)).
但它不返回实际值,只返回
true

如果我在终端中键入
tile(E,S,W,N,#1)
,我会得到所需的结果,但我不知道返回的是什么(可能是列表?)

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

查询:

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

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

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

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

查询:

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

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

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

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

tile(p1,p2,p3,p4,id1).
tile(q1,q2,q3,q4,id2).
tile(r1,r2,r3,r4,id3).
coordonates(id1, t(p1, p2, p3, p4)).
coordonates(id2, t(q1, q2, q3, q4)).
coordonates(id3, t(r1, r2, r3, r4)).
?- coordonates(id2,X).
X = t(q1, q2, q3, q4).
coordonates( ... ) :-
  % ...
  tile(E,S,W,N,I).
在这方面,我们有有限的事实。可通过最通用的
平铺查询来检查:

?- 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
可按如下方式查询
id2

tile(p1,p2,p3,p4,id1).
tile(q1,q2,q3,q4,id2).
tile(r1,r2,r3,r4,id3).
coordonates(id1, t(p1, p2, p3, p4)).
coordonates(id2, t(q1, q2, q3, q4)).
coordonates(id3, t(r1, r2, r3, r4)).
?- coordonates(id2,X).
X = t(q1, q2, q3, q4).
coordonates( ... ) :-
  % ...
  tile(E,S,W,N,I).
我使用函子
t
对解决方案进行分组,以明确它不是我们前面定义的谓词
tile
。这个定义中也有很多重复,这已经暗示了我们可以做得更好。我们所寻找的是一条规则,它告诉我们,如果我们对
tile
有一个答案,我们如何描述
合作伙伴。从逻辑上讲,这是作为一种形式的暗示:目标1∧ ... ∧ 果仁→ 头。这意味着“假设我知道goal1到goalN是真的,那么我也知道head是真的。”在序言中,这是倒写的:

head :-
  goal1,
  % ...
  goalN.
让我们回到我们的任务:我们了解一些关于瓷砖的知识,我们想描述投影的样子。这意味着,我们的代码如下所示:

tile(p1,p2,p3,p4,id1).
tile(q1,q2,q3,q4,id2).
tile(r1,r2,r3,r4,id3).
coordonates(id1, t(p1, p2, p3, p4)).
coordonates(id2, t(q1, q2, q3, q4)).
coordonates(id3, t(r1, r2, r3, r4)).
?- coordonates(id2,X).
X = t(q1, q2, q3, q4).
coordonates( ... ) :-
  % ...
  tile(E,S,W,N,I).
主体
tile(E,S,W,N,I)
是我们可以编写的最通用的形式(参见上面的查询),可以理解为“假设我在坐标E,S,W,N处有任何tile,id为I”。现在我们只需要填写
coordonates
应该是什么样子。我们知道它有两个参数,因为它将id与其他四个元素相关联。让我们给他们起名字,比如说
Id
Coords

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
,而不是编写
Id=I
。这同样适用于
Coords
t(E,S,W,N)


它不能短得多:-)

让我们假设我们描述
瓷砖的事实如下所示:

tile(p1,p2,p3,p4,id1).
tile(q1,q2,q3,q4,id2).
tile(r1,r2,r3,r4,id3).
coordonates(id1, t(p1, p2, p3, p4)).
coordonates(id2, t(q1, q2, q3, q4)).
coordonates(id3, t(r1, r2, r3, r4)).
?- coordonates(id2,X).
X = t(q1, q2, q3, q4).
coordonates( ... ) :-
  % ...
  tile(E,S,W,N,I).
在这方面,我们有有限的事实。可通过最通用的
平铺查询来检查:

?- 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
可按如下方式查询
id2

tile(p1,p2,p3,p4,id1).
tile(q1,q2,q3,q4,id2).
tile(r1,r2,r3,r4,id3).
coordonates(id1, t(p1, p2, p3, p4)).
coordonates(id2, t(q1, q2, q3, q4)).
coordonates(id3, t(r1, r2, r3, r4)).
?- coordonates(id2,X).
X = t(q1, q2, q3, q4).
coordonates( ... ) :-
  % ...
  tile(E,S,W,N,I).
我使用函子
t
对解决方案进行分组,以明确它不是我们前面定义的谓词
tile
。这个定义中也有很多重复,这已经暗示了我们可以做得更好。我们所寻找的是一条规则,它告诉我们,如果我们对
tile
有一个答案,我们如何描述
合作伙伴。从逻辑上讲,这是作为一种形式的暗示:目标1∧ ... ∧ 果仁→ 头。这意味着“假设我知道goal1到goalN是真的,那么我也知道head是真的。”在序言中,这是倒写的:

head :-
  goal1,
  % ...
  goalN.
让我们回到我们的任务:我们了解一些关于瓷砖的知识,我们想描述投影的样子。这意味着,我们的代码如下所示:

tile(p1,p2,p3,p4,id1).
tile(q1,q2,q3,q4,id2).
tile(r1,r2,r3,r4,id3).
coordonates(id1, t(p1, p2, p3, p4)).
coordonates(id2, t(q1, q2, q3, q4)).
coordonates(id3, t(r1, r2, r3, r4)).
?- coordonates(id2,X).
X = t(q1, q2, q3, q4).
coordonates( ... ) :-
  % ...
  tile(E,S,W,N,I).
主体
tile(E,S,W,N,I)
是我们可以编写的最通用的形式(参见上面的查询),可以理解为“假设我在坐标E,S,W,N处有任何tile,id为I”。现在我们只需要填写
coordonates
应该是什么样子。我们知道它有两个参数,因为它将id与其他四个元素相关联。让我们给他们起名字,比如说
Id
Coords

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
,而不是编写
Id=I
。这同样适用于
Coords
t(E,S,W,N)

不能再短了:-)

我有一个使用4个参数的函数。。。实际上,有一个谓词有5个参数。如果我在终端中键入
tile(E,S,W,N,#1)
,我会得到所需的结果,但我不知道返回的确切内容。请注意,谓词(它们不是函数!)不返回值。他们只会成功或失败。一个
true
响应意味着它成功了。@潜伏者“一个真正的响应意味着它成功了”。。。错误的回答是什么意思?错误的响应意味着它无法找到任何进一步的解决方案。在找到一个或多个解决方案后,可能会出现错误或无响应,但如果存在剩余的选择点,并且没有更多的解决方案可供找到,则可以得到错误或无响应。换句话说,您可以调用谓词,它可能会在没有任何解决方案的情况下失败,或者它可能会成功地生成一个或多个解决方案,然后最终无法再寻找更多的解决方案。这是一个基本原则