Prolog 语句从不统一

Prolog statement never unifies

我有 3 个递归规则,但其中一个从未与我的查询统一。

checkCollisionDiagonal(QueenTarget,[],Qdist,0).
checkCollisionDiagonal(QueenTarget, [Q|QueenList], Qdist, X):-
    abs(QueenTarget - Q) =\= Qdist,
    NextQdist is Qdist + 1,
    checkCollisionDiagonal(QueenTarget, QueenList, NextQdist, X).
checkCollisionDiagonal(QueenTarget, [Q|QueenList], Qdist, X):-
    abs(QueenTarget - Q) = Qdist, 
    NextQdist is Qdist + 1,
    checkCollisionDiagonal(QueenTarget, QueenList, NextQdist, X1),
    X is X1+1.

绝对值与Qdist不同的语句工作正常,如果它不统一我的程序应该检查下一条语句(绝对值等于Qdist的语句),但是使用trace我注意到第二个永远不会评估语句 (abs = Qdist)。为什么会这样?

我的查询是 checkCollisionDiagonal(1, [2,1,4,1], 1, X).,预期结果应该是 2,但它总是 returns false

确实统一了,统一不是你想要的:

?- abs(5 - 2) = Qdist.
Qdist = abs(5-2)

它们不是函数,abs() 不做任何计算。换个词就更清楚了:

?- szz(5 $ / * foo) = Qdist.
Qdist = szz(5$(/)*foo)

变量 Qdist 与该项统一。

你需要 =:==\=is,它们都知道如何计算 abs(5 - 2):

  • Qdist is abs(5 - 2) 将右侧计算为算术表达式 (abs(5 - 2)) 并将结果与​​ Qdist.

    统一
  • Qdist =:= abs(5 - 2)将两边作为算术表达式求值,比较结果,相等则成功。

  • Qdist =\= abs(5 - 2)=:=/2的否定:将两边都作为算术表达式求值,比较结果,不相等则成功。

请参阅 arithmetic predicates 的文档。

为什么你的程序会失败?显然,您的程序(无论出于何种原因)过于专业化。因此,让我们概括您的程序,使其仍然失败但至少要小一些。为此,让我们使用 * 删除目标,从而概括程序。您的查询也可以通过用简单的下划线替换子列表 [1,4,1] 来概括。

:- op(950, fy, *).
* _. % the goal is just true instead

checkCollisionDiagonal(_QueenTarget,[],_Qdist,0).
checkCollisionDiagonal(QueenTarget, [Q|QueenList], Qdist, X):-
    abs(QueenTarget - Q) =\= Qdist,
    * NextQdist is Qdist + 1,
    * checkCollisionDiagonal(QueenTarget, QueenList, NextQdist, X).
checkCollisionDiagonal(QueenTarget, [Q|QueenList], Qdist, X):-
    abs(QueenTarget - Q) = Qdist, 
    * NextQdist is Qdist + 1,
    * checkCollisionDiagonal(QueenTarget, QueenList, NextQdist, X1),
    * X is X1+1.

?- checkCollisionDiagonal(1, [2|_/*,1,4,1*/], 1, X) ).
   false.

因为这个通用程序失败了,你原来的程序也失败了。所以现在你有一个更小的部分来找到有问题的错误(已经被另一个答案给出了)。