简体   繁体   中英

How can I limit the possible integers used in my solutions in prolog?

I have been trying to learn prolog but I am having issues with limiting the possible integers that can be used in my solutions. For example, In my SWI terminal, I ran

[X,Y,Z] ins 0..1,X #\= Y, Y #\= Z, Z#\= Y.

and as output I got

X in 0..1,
X#\=Y,
Y in 0..1,
Z#\=Y,
Y#\=Z,
Z in 0..1.

when I wanted to get false.

This is just an instance of an issue I have been having. I am working on a project that involves comparing permutations of lists of length 4. My code there is

:- use_module(library(clpfd)).

peice(Ps) :-
    length(Ps,4),
    Ps ins -2..2.

rotate(peice(X),peice(Y)) :-
    X = [A,B,C,D],
    Y = [B,C,D,A].

onedifrent(peice([A1,_,_,_]),peice([A2,_,_,_])) :- A1 #\= A2.
onedifrent(peice([_,B1,_,_]),peice([_,B2,_,_])) :- B1 #\= B2.
onedifrent(peice([_,_,C1,_]),peice([_,_,C2,_])) :- C1 #\= C2.
onedifrent(peice([_,_,_,D1]),peice([_,_,_,D2])) :- D1 #\= D2.

notequiv(peice(X),peice(Y)) :-
    peice(X),
    peice(Y),
    rotate(peice(X),peice(X1)),
    rotate(peice(X1),peice(X2)),
    rotate(peice(X2),peice(X3)),
    onedifrent(peice(X),peice(Y)),
    onedifrent(peice(X1),peice(Y)),
    onedifrent(peice(X2),peice(Y)),
    onedifrent(peice(X3),peice(Y)).

notin(_,Ls) :- Ls = [].
notin(peice(X),[peice(Y)|Ls]) :-
    notequiv(peice(X),peice(Y)),
    notin(peice(X),Ls).

alldifrent(Ls) :- Ls = [].
alldifrent([peice(X)|Ls]) :-
    notin(peice(X),Ls),
    alldifrent(Ls).

From combinatorics, the longest list of all different peices should have a length 165. However, nothing stops prolog from creating impossible solutions and creating longer lists.

Your first snippet of code: [X,Y,Z] ins 0..1,X #\= Y, Y #\= Z, Z#\= Y. does have two possible assignments. Use label/1 to get the assignments:

?- [X,Y,Z] ins 0..1,X #\= Y, Y #\= Z, Z#\= Y, label([X,Y,Z]).
X = Z, Z = 0,
Y = 1 ;
X = Z, Z = 1,
Y = 0.

Note that the two last constraints are equivalent (Y different than Z).

Maybe you meant to write this instead:

?- [X,Y,Z] ins 0..1,X #\= Y, Y #\= Z, Z#\= X, label([X,Y,Z]).
false.

To get permutations with different numbers you may use all_distinct/1 :

peice(Ps) :-
    length(Ps,4),
    Ps ins -2..2,
    all_distinct(Ps).

Sample run:

?- peice(Ps), findall(Ps, label(Ps), LPs), length(LPs, NumberSols).
Ps = [_A, _B, _C, _D],
LPs = [[-2, -1, 0, 1], [-2, -1, 0, 2], [-2, -1, 1, 0], [-2, -1, 1, 2], [-2, -1, 2, 0], [-2, -1, 2|...], [-2, 0|...], [-2|...], [...|...]|...],
NumberSols = 120,
_A in -2..2,
all_distinct([_A, _B, _C, _D]),
_B in -2..2,
_C in -2..2,
_D in -2..2.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM