I\'ve started to learn Prolog recently and I can\'t solve how to make union of three lists.
I was able to make union of 2 lists :
%element
element(X,
Using only predicates with an extra argument such as memberd_t/3 leads only to weak reification. For strong reification we also need to generate constraints. Strong reification is a further approach to eliminate non-determinism.
But strong reification is difficult, a possible way to archive this is to use a CLP(*)
instance which has also reified logical operators. Here is an example if using CLP(FD)
for the union problem. Unfortunately this covers only the domain Z
:
Strong Reification Code:
member(_, [], 0).
member(X, [Y|Z], B) :-
(X #= Y) #\/ C #<==> B,
member(X, Z, C).
union([], X, X).
union([X|Y], Z, T) :-
freeze(B, (B==1 -> T=R; T=[X|R])),
member(X, Z, B),
union(Y, Z, R).
The above doesn't suffer from unnecessary choice points. Here are some example that show that this isn't happening anymore:
Running a Ground Example:
?- union([1,2],[2,3],X).
X = [1, 2, 3].
Also the above example even doesn't create choice points, if we use variables somewhere. But we might see a lot of constraints:
Running a Non-Ground Example:
?- union([1,X],[X,3],Y).
X#=3#<==>_G316,
1#=X#<==>_G322,
_G316 in 0..1,
freeze(_G322, (_G322==1->Y=[X, 3];Y=[1, X, 3])),
_G322 in 0..1.
?- union([1,X],[X,3],Y), X=2.
X = 2,
Y = [1, 2, 3].
Since we didn't formulate some input invariants, the interpreter isn't able to see that producing constraints in the above case doesn't make any sense. We can use the all_different/1
constraint to help the interpreter a little bit:
Providing Invariants:
?- all_different([1,X]), all_different([X,3]), union([1,X],[X,3],Y).
Y = [1, X, 3],
X in inf..0\/2\/4..sup,
all_different([X, 3]),
all_different([1, X]).
But we shouldn't expect too much from this singular example. Since the CLP(FD)
and the freeze/2
is only an incomplete decision procedure for propositions and Z equations, the approach might not work as smooth as here in every situation.
Bye