gpt4 book ai didi

PROLOG 规则仅返回第一个匹配项

转载 作者:行者123 更新时间:2023-12-02 11:56:03 24 4
gpt4 key购买 nike

我正在尝试在 Prolog 中实现 findall 谓词(是的,我知道它是内置的,这是为了赋值)。

写法如下:

my_findall(N,P,Pred,L) :- Pred, not(new(N,P)), !, assert(new(N,P)), my_findall(N1,P1,Pred,L1), L=[N,P,L1], retract(new(N,P)).
my_findall(_,_,_, []).

由于某种原因,它只给了我第一个解决方案并停在那里,就好像对 my_findall 的第二次调用失败一样。据我了解,回溯机制应该遍历所有可能的选项,其中应该包括调用 Pred(N,P) 的所有选项,因此即使第二次调用在第一次尝试时失败(为 Pred 尝试的第一个选项已经已断言),它应该在放弃并转到 my_findall((,),_, []) 之前首先尝试所有其他选项。

如果这不是它的工作原理,有没有办法在不完全重写解决方案的情况下强制这种行为?

最佳答案

您的 Pred 包含未绑定(bind)的变量。当您在第一次迭代中调用 Pred 时,这些变量将绑定(bind)到第一个可能的值。在递归步骤中,Pred 已经绑定(bind)了变量,并且它们无法更改值。所以...这个解决方案行不通。

来自 SWI-Prolog 的跟踪(由于某些原因,我不得不将 new/2 重命名为 item/2):

第一级(调用:my_findall(A,B,member(p(A,B), [p(1,2), p(3,4)]), L)。)。

   Call: (7) my_findall(_G819, _G820, member(p(_G819, _G820), [p(1, 2), p(3, 4)]), _G840) ? creep
Call: (8) lists:member(p(_G819, _G820), [p(1, 2), p(3, 4)]) ? creep
Exit: (8) lists:member(p(1, 2), [p(1, 2), p(3, 4)]) ? creep

我们得到 p(A,B) = p(1,2)。此时A绑定(bind)为1,B绑定(bind)为2。

^  Call: (8) not(item(1, 2)) ? creep
Call: (9) item(1, 2) ? creep
Fail: (9) item(1, 2) ? creep
^ Exit: (8) not(item(1, 2)) ? creep

好的,数据库中没有项目(1,2)。

^  Call: (8) assert(item(1, 2)) ? creep
^ Exit: (8) assert(item(1, 2)) ? creep

现在第(1,2)项为真。递归调用:

   Call: (8) my_findall(_L215, _L216, member(p(1, 2), [p(1, 2), p(3, 4)]), _L199) ? creep

让 Pred 得到另一个解决方案:

   Call: (9) lists:member(p(1, 2), [p(1, 2), p(3, 4)]) ? creep
^^^^^^^

看到下划线部分了吗?

要使此技术发挥作用,您可能应该复制 Pred,递归地将 N 和 P 更改为新变量。对于每次迭代,您都必须“创建”新的 N 和 P 对。检查 copy_term/2 ( http://www.swi-prolog.org/pldoc/doc_for?object=copy_term%2f2 )。

关于PROLOG 规则仅返回第一个匹配项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1098542/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com