使用不带 CLP(FD) 的 Prolog 表达数值约束

Expressing numerical constraints using Prolog without CLP(FD)

ordering(A, B, C) :-
    integer(A),
    integer(B),
    integer(C),
    A > B,
    B > C,
    A > 0,
    10 > C.

ordering(3,2,1). 感到满意。但是当我将一个或多个作为变量 ordering(3,X,1). 时,它的计算结果为 false.

我错过了什么?

更新:感谢所有详尽的回答。我从他们身上都学到了一些东西。

如果参数不是整数,

integer/1 将失败,例如,如果您传递一个未绑定的变量。 我相信您应该使用 CLP(FD) 来完成这类任务。否则,您可以在某个整数范围内手动 bind/test 变量,使用 between/3 设置该范围。

例如:

ordering(A, B, C) :-
   between(0, 100, A),  % A is an integer in the range [0,100]
   between(0, 100, B),  % same for B
   between(0, 100, C),  % and C
   A > B,
   B > C,
   A > 0,
   10 > C.

样本运行:

?- ordering(3,X,1).
X = 2 ;
false.

这并不奇怪。

显然 integer(X)X 未绑定将立即失败。在这方面是非常“势在必行”的。

此外,由于 10 > C.

,谓词将失败并显示 C 未绑定

最好你可以写一个谓词can_be/2,这样当未绑定变量X“仍然可以成为整数”时can_be(integer,X)成功,否则失败。

通过扩展会有一个 can_be_ordered(A, B, C),如果确定 [A,B,C] 由于它们已经表示的值而永远不能被排序,则失败,或者如果 [A,B,C] 可以成功仍然根据其中任何未绑定变量在未来采用的值进行排序。

真值具体化就更好了:

ordering(List,Result)

其中 Result

  • true:是的,已订购并将保持订购状态。
  • false: 肯定没订,也不会变。
  • unknown/maybe:没有明确证据表明是无序还是有序

然后您还可以将 ordering(List,Result) 附加到未绑定变量,只要其中一个变量绑定,就会重新检查顺序,使用 freeze/2。这基本上就是在做 CLP(FD) 的工作。

您可以延迟比较直到变量初始化:

ordering(A, B, C) :-
    greater(A, B),
    greater(B, C).

greater(X, Y) :-
    when((nonvar(X), nonvar(Y)), X > Y).

测试:

?- greater(3, 2).
true.

?- ordering(3, 2, 1).
true.

?- ordering(3, 2, 2).
false.

?- ordering(3, X, 1).
when(nonvar(X), 3>X),
when(nonvar(X), X>1).