Prolog理解setof/3,带有^标记

Prolog理解setof/3,带有^标记,prolog,prolog-setof,Prolog,Prolog Setof,有人能给我解释一下这是怎么回事吗 (\+ setof((P1,C),P^R^Bag,PS) -> ... otherwise ->... 我已经阅读了setof的文件;我的理解是,第三个论点与事实相一致 然而,我无法理解上面的代码片段 完整的代码片段是: solve_task_bt(go(Target),Agenda,ClosedSet,F,G,NewPos,RR,BackPath) :- Agenda = [Current|Rest], Current = [c(F,G

有人能给我解释一下这是怎么回事吗

(\+ setof((P1,C),P^R^Bag,PS) -> ...
otherwise ->...
我已经阅读了setof的文件;我的理解是,第三个论点与事实相一致

然而,我无法理解上面的代码片段

完整的代码片段是:


solve_task_bt(go(Target),Agenda,ClosedSet,F,G,NewPos,RR,BackPath) :-
  Agenda = [Current|Rest],
  Current = [c(F,G,P)|RPath],
  NewAgenda = Rest,
  Bag = search(P,P1,R,C),
  (\+ setof((P1,C),P^R^Bag,PS) -> solve_task_bt(go(Target),Rest,[Current|ClosedSet],F,G,NewPos,RR,BackPath);
    otherwise -> 
    setof((P1,C),P^R^Bag,PS),
    addChildren(PS,RPath,Current,NewAgenda,Target,Result),
    NewClosedSet = [Current|ClosedSet],
    NewestAgenda = Result,
    solve_task_bt(go(Target),NewestAgenda,NewClosedSet,F1,G1,Pos,P|RPath,BackPath)
    ).  % backtrack search

稍后更新:以下内容不太正确,最好转到父参考:

因此,只需关注
集合/3

setof((P1,C),P^R^Bag,PS) 
让我们将
Bag
替换为其语法等价物,并在前面设置一行:

setof((P1,C),P^R^search(P,P1,R,C),PS) 
setof/3
的描述说明

  • 以论点2为目标
  • 根据参数1(模板)收集解决方案
  • 将模板化的结果放入参数3中,即包中,去掉重复项
因此在这种情况下,
setof/3
将调用(将表达式提供给Prolog处理器以证明)
搜索(p,P1,R,C)
,当搜索成功时,收集结果值
P1
C
作为连词
(P1,C)
(这真的很特别,为什么不使用两元素列表?)并将所有内容放入
PS

让我们尝试一个类似于上述的可运行示例,使用列表而不是连词,并使用不同的名称:

search(1,a,n,g).
search(2,a,m,g).

search(2,a,m,j).
search(1,a,m,j).
search(3,a,w,j).
search(3,a,v,j).

search(2,b,v,g).
search(3,b,m,g).
search(5,b,m,g).

search(1,b,m,j).
search(1,b,v,j).

search(2,b,w,h).

get_closed(Bag)   :- setof([X,Y],P^R^search(P,X,R,Y),Bag). 
get_open(Bag,P,R) :- setof([X,Y],    search(P,X,R,Y),Bag).
注意,你可以写

get_closed(Bag) :- setof([X,Y],P^R^search(P,X,R,Y),Bag). 
没有关于“单例变量”的编译器警告

将向您投诉:

Singleton variables: [P,R]
这是有原因的:
p
R
在“子句级别”可见。在这里,我们将
P
R
添加到头部,这为我们以后提供了良好的打印输出

封闭溶液 我们可以做的主要工作是:

?- get_closed(Bag).
Bag = [[a, g], [a, j], [b, g], [b, h], [b, j]].
Bag
现在包含所有可能的解决方案
[X,Y]

search(P,X,P,Y)
我们不关心内部目标之外(
p
R
)元组的值。
P
R
的值在
setof/3
调用的目标之外是不可见的,回溯保持“内部”

由于不同(
p
R
)而导致的
[X,Y]
的替代解决方案被
setof/3
折叠。如果使用的是
bagof/3

?- bagof([X,Y],P^R^search(P,X,R,Y),Bag).
Bag = [[a, g], [a, g], [a, j], [a, j], [a, j], [a, j], [b, g], ....
实际上,对Prolog处理器的查询是:

构建
,它是
[X,Y]
的列表,以便:

∀ <代码>[X,Y]:∃<代码>P,∃<代码>R:
搜索(P,X,R,Y)
为真

开放解 在这种情况下,
Bag
包含固定(
p
R
)元组的所有解决方案,Prolog允许您在
setof/3
谓词级别回溯可能的(
p
R
)。变量
P
R
setof/3
外部可见

实际上,对Prolog处理器的查询是:

构造
p
R
,以便:

您可以构造
Bag
,它是
[X,Y]
的列表,以便

∀ <代码>[X,Y]:
搜索(P,X,R,Y)
为真

记法问题 如果Prolog有一个Lambda操作符来指示跨级别附加点(即元谓词和谓词之间)的位置,这将更加清楚。假设
setof/3
中的内容保持在
setof/3
中(Prolog的相反态度),则可以编写:

get_closed(Bag) :- setof([X,Y],λX.λY.search(P,X,R,Y),Bag). 

或者你可以简单地写
这也将清楚地表明,变量不会导出到它们出现在的子句之外。

@DavidTonhofer。我发布了完整的snippet@DavidTonhofer我只是想知道这个代码片段在正常编程语义方面意味着什么,感谢详细的响应,这很有帮助。但有一个问题是,^在这种情况下做了什么?@nz_21添加了更多文本。我希望我的解释是正确的。
?- get_open(Bag,P,R).
Bag = [[a, j], [b, j]],
P = 1,
R = m ;
Bag = [[a, g]],
P = 1,
R = n ;
Bag = [[b, j]],
P = 1,
R = v ;
Bag = [[a, g], [a, j]],
P = 2,
R = m ;
Bag = [[b, g]],
P = 2,
R = v ;
Bag = [[b, h]],
P = 2,
R = w ;
Bag = [[b, g]],
P = 3,
R = m ;
Bag = [[a, j]],
P = 3,
R = v ;
Bag = [[a, j]],
P = 3,
R = w ;
Bag = [[b, g]],
P = 5,
R = m.
get_closed(Bag) :- setof([X,Y],λX.λY.search(P,X,R,Y),Bag). 
get_closed(Bag) :- setof([X,Y],search(P,X,R,Y),Bag). 
get_open(Bag)   :- λP.λR.setof([X,Y],search(P,X,R,Y),Bag).
get_closed(Bag) :- setof([X,Y],search_closed(X,Y),Bag). 

search_closed(X,Y) :- search(_,X,_,Y).