11

我正在尝试编写一个 Prolog (CLP) 谓词,该谓词将构建一个约束两个列表不等式的约束。

更正式地说,有两个列表A=[A1,...,AN], B=[B1,...,BN],约束被定义为(A1 #\= B1) #\/ (A2 #\= B2) #\/ ... #\/ (AN #\= BN)

给定两个任意长度的列表,我不确定如何构建此约束。这是我的尝试。我明白为什么它不起作用,但无法修复它。

any_different([], []).
any_different([H1|T1], [H2|T2]):-
    H1 #\= H2 #\/ any_different(T1, T2).
4

3 回答 3

9

您需要建立析取并通过第三个参数返回它:

any_different([], [], V) :-
    V #= 0.  % no differences between [] and []
any_different([H1|T1], [H2|T2], Disj) :-
    any_different(T1, T2, Disj0),
    Disj #<==> (H1 #\= H2) #\/ Disj0.

现在,调用any_different(List1, List2, AnyDiff)约束一个变量AnyDiff,您可以将其与其他变量一起传递给标签谓词。通过声明,AnyDiff #= 0您可以约束List1List2使其相等,而AnyDiff #= 1将导致它们不相等。

于 2012-12-22T13:12:57.047 回答
4

我认为,至少在 SWI-Prolog 中,谓词 dif/2 和 library(clpfd) 可以替代物化:

?- L=[X,Y,Z], L ins 1..3, dif(L,[1,2,3]), label(L).
L = [1, 1, 1],
X = Y, Y = Z, Z = 1 ;
L = [1, 1, 2],
X = Y, Y = 1,
Z = 2 ;
...
于 2012-12-23T11:33:59.260 回答
4

这是一个基于sum/3clpfd reification的实现(#<==>)/2

not_equals_reified(X, Y, B) :-
    X #\= Y #<==> B.

any_different(Xs, Ys) :-
    maplist(not_equals_reified, Xs, Ys, Bs), 
    sum(Bs, #>, 0).

通过使用 maplist/4,我们甚至不需要编写递归代码!

于 2015-04-09T09:09:00.443 回答