findall/3在其结果列表中创建新的,不相关的变量

Fat*_*ize 8 prolog prolog-findall

?- permutation([A,B,C],Z).
Z = [A, B, C] ;
Z = [A, C, B] ;
Z = [B, A, C] ;
Z = [B, C, A] ;
Z = [C, A, B] ;
Z = [C, B, A] ;
false.
Run Code Online (Sandbox Code Playgroud)

说得通.我可以处理排列,[A,B,C]并且排列包含与in相同的元素[A,B,C],因此我对这些元素所做的一切都将应用于我的原始列表.

现在:

?- findall(X, permutation([A,B,C], X), Z).
Z = [[_G1577, _G1580, _G1583], [_G1565, _G1568, _G1571], [_G1553, _G1556, _G1559], [_G1541, _G1544, _G1547], [_G1529, _G1532, _G1535], [_G1517, _G1520, _G1523]].
Run Code Online (Sandbox Code Playgroud)

为什么??为什么findall/3给我列出包含完全不相关的变量的列表,而不是A,B,C?这些列表Z甚至没有相互关联,所以我得到的结果实际上只有6个长度为3的随机列表,这完全不是我所查询的.

有了这种行为,我们得到如下荒谬的结果:

?- findall(X, permutation([A,B,C],X), Z), A = 1.
A = 1,
Z = [[_G1669, _G1672, _G1675], [_G1657, _G1660, _G1663], [_G1645, _G1648, _G1651], [_G1633, _G1636, _G1639], [_G1621, _G1624, _G1627], [_G1609, _G1612, _G1615]].
Run Code Online (Sandbox Code Playgroud)

从逻辑的角度来看,这没有任何意义.

我理解这findall/3不是一个真正的关系,纯粹的逻辑谓词,但我不知道这如何证明这里显示的行为是正确的.

因此,我的问题是:

  • 为什么为谓词选择了这种行为?

  • 是否存在这种行为实际上比我想要的更好的常见情况?

  • 如何实现findall/3我想要的行为版本?

fal*_*lse 10

为什么为谓词选择了这种行为?

findall/3 是一个非常原始的内置谓词,相对容易实现,并没有解决你感兴趣的所有细节.至少它是可重入的 - 因此可以递归使用.

从历史上看,DEC10 Prolog没有记录findall/3.也就是说,无论是1978年还是1984年.1984年的版本确实提供setof/3了内部使用类似于findall的谓词.在ISO-Prolog中实现它(没有findall/3)是相对棘手的,因为你必须处理错误和嵌套.许多实现依赖于特定于实现的原语.

是否存在这种行为实际上比我想要的更好的常见情况?

的FindAll成功,如果没有解决,而这两个setof/3bagof/3简单的失败.这可能是喜欢它的原因.至少有一些比那些更复杂的结构,这些结构很可能是基于findall构建的.

在存在约束的情况下它变得相当混乱.事实上,它是如此混乱,从目前的时间点来看,我仍然没有意识到在这种情况下会以合理的方式处理clpfd约束的实现.考虑到:

?- findall(A, (A in 1..3 ; A in 5..7), As).
Run Code Online (Sandbox Code Playgroud)

这里,SWI复制约束,其中SICStus不复制它们,从而允许您将其用作构建块以用于更复杂的实现.

如何用我想要的行为实现findall/3的版本?

首先,考虑setof/3bagof/3(这里).也许你已经满意了 - 只要不涉及任何限制......


Yas*_*sel 3

?- findall(X, permutation([A,B,C],X), Z), A = 1.
Run Code Online (Sandbox Code Playgroud)

在此查询中,Prolog 将查找列表 [A,B,C] 上元素的所有排列,但由于 Prolog 无法实例化变量 A、B、C,因此结果将是您得到的匿名变量:

Z = [[_G1669, _G1672, _G1675], [_G1657, _G1660, _G1663], [_G1645, _G1648, _G1651], [_G1633, _G1636, _G1639], [_G1621, _G1624, _G1627], [_G1609, _G1612, _G1615]].
Run Code Online (Sandbox Code Playgroud)

另一方面,如果你首先实例化变量 A、B 和 C,你将得到不同的结果:

?- A=1, B=2, C=3, findall(X, permutation([A,B,C],X), Z).
A = 1,
B = 2,
C = 3,
Z = [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
Run Code Online (Sandbox Code Playgroud)

这在您的查询中之前没有发生过,findall(X, permutation([A,B,C],X), Z), A = 1.因为 Prolog 将首先尝试解决条件findall(X, permutation([A,B,C],X), Z),然后A = 1