Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List inequality constraint

Tags:

prolog

clpfd

I am trying to write a Prolog (CLP) predicate that would build a constraint constraining inequality of two lists.

More formally, having two lists A=[A1,...,AN], B=[B1,...,BN] the constraint is defined as (A1 #\= B1) #\/ (A2 #\= B2) #\/ ... #\/ (AN #\= BN).

I am unsure how to build this constraint given two lists of arbitrary length. This is my attempt. I understand why it does not work, but can not fix it.

any_different([], []).
any_different([H1|T1], [H2|T2]):-
    H1 #\= H2 #\/ any_different(T1, T2).
like image 252
mscavnicky Avatar asked Dec 22 '12 10:12

mscavnicky


2 Answers

You'll want to build up the disjunction and return it through a third argument:

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.

Now, calling any_different(List1, List2, AnyDiff) contrains a variable AnyDiff that you can pass to the labeling predicate along with your other variables. By stating AnyDiff #= 0 you can constrain List1 and List2 to be equal, while AnyDiff #= 1 will cause them to be unequal.

like image 113
Fred Foo Avatar answered Sep 28 '22 02:09

Fred Foo


I think that, at least in SWI-Prolog, the predicate dif/2 and library(clpfd) could be an alternative to the reification:

?- 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 ;
...
like image 41
CapelliC Avatar answered Sep 28 '22 02:09

CapelliC