2012-12-22 10 views
11

Ich versuche, ein Prolog (CLP) Prädikat zu schreiben, die eine Einschränkung erstellen würde, die Ungleichheit von zwei Listen einschränkt.List Ungleichheit Einschränkung

Formaler, mit zwei Listen A=[A1,...,AN], B=[B1,...,BN] die Einschränkung ist definiert als (A1 #\= B1) #\/ (A2 #\= B2) #\/ ... #\/ (AN #\= BN).

Ich bin nicht sicher, wie diese Einschränkung bei zwei Listen beliebiger Länge erstellt wird. Das ist mein Versuch. Ich verstehe, warum es nicht funktioniert, kann es aber nicht beheben.

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

Antwort

9

Sie wollen die Disjunktion aufzubauen und bringt sie durch ein drittes 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. 

Nun ruft any_different(List1, List2, AnyDiff) contrains eine Variable AnyDiff, die Sie auf die Kennzeichnung Prädikat passieren kann zusammen mit Ihrem andere Variablen. Wenn Sie AnyDiff #= 0 angeben, können Sie List1 und List2 als gleich festlegen, während AnyDiff #= 1 dazu führt, dass sie ungleich sind.

+1

Vielen Dank. Das ist das Idiom, nach dem ich gesucht habe. – mscavnicky

4

Ich denke, dass, zumindest in SWI-Prolog, das Prädikat dif/2 und Bibliothek (clpfd) eine Alternative zur Verdinglichung sein könnte:

?- 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 ; 
... 
4

Hier ist eine Implementierung auf Basis von sum/3 und clpfd Verdinglichung (#<==>)/2 :

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

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

Durch die Verwendung von maplist/4 wir müssen nicht einmal rekursiven Code schreiben!