【问题标题】:Prolog understanding setof/3 with ^ markings [duplicate]Prolog 理解 setof/3 与 ^ 标记[重复]
【发布时间】:2020-04-13 15:59:36
【问题描述】:

有人可以向我解释一下这是做什么的吗?

(\+ setof((P1,C),P^R^Bag,PS) -> ...
otherwise ->...

我已经阅读了 setof 的文档;我的理解是第三个论点与事实统一起来。

但是,我无法理解上面的代码 sn-p。

完整的sn-p是:


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

【问题讨论】:

  • @DavidTonhofer。我发布了完整的 sn-p
  • @DavidTonhofer 我只是想知道 sn-p 在正常编程语义方面的含义

标签: prolog prolog-setof


【解决方案1】:

稍后更新:以下内容不太正确,最好转到父参考:What is the Prolog operator ^?

所以,只关注setof/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,bag,省略重复项。

所以在这种情况下,setof/3 将调用(将表达式提供给 Prolog 处理器来证明)search(P,P1,R,C),并且当调用成功时,收集结果值 P1,C 作为连词 (P1,C)(真的很特别,为什么不使用 2 元素列表?)并将所有内容放入 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). 

没有关于“单例变量”的编译器警告,而

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

会给你投诉:

Singleton variables: [P,R]

这是有原因的:PR 在“子句级别”可见。这里我们将PR 添加到头部,这样我们以后可以很好地打印输出。

封闭解决方案

我们能做的:

?- get_closed(Bag).
Bag = [[a, g], [a, j], [b, g], [b, h], [b, j]].

Bag 现在包含所有可能的解决方案 [X,Y] 用于:

search(P,X,P,Y)

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

[X,Y] 的替代解决方案由于 (P,R)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 处理器的查询是:

构造Bag,它是[X,Y] 的列表,这样:

[X,Y]: ∃P,∃R:search(P,X,R,Y) 是真的。

打开解决方案

?- 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.

在这种情况下,Bag 包含 fixed (P,R) 元组的所有解决方案,Prolog 允许您回溯可能的(P,R)setof/3 谓词级别。变量PRsetof/3 之外“可见”。

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

构造P,R 使得:

你可以构造Bag,这是一个[X,Y]的列表,这样

[X,Y]:search(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). 

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).

这也将明确发生了什么,因为变量不会导出到它们出现的子句之外。

【讨论】:

  • 感谢您的详细回复,这很有帮助。但是有一个问题,在这种情况下 ^ 在做什么?
  • @nz_21 添加了更多文本。希望我的解释正确。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-31
  • 2018-03-03
相关资源
最近更新 更多