Is Prolog suitable for this kind of project? - prolog

I am working on a project where I have to build an engine that is able to generate a bunch of premises and, given a true fact, tell what else can be deduced. Example given:
If John plays football then Mary makes cookies.
If Eric listens to rock then john doesn't play Football.
If Eric doesn't listen to rock then john plays Football.
Either Eric listens to rock or Luiza listens to rock.
When the given true fact is "Luiza listens to rock", then the solution should be:
Eric listens to rock = false
John plays football = true
Mary makes cookies = true
When the true fact is "Eric listens to rock", then the solution should be:
Luiza listens to rock = false
Jonh plays football = false
Mary makes cookies = (can't solve)
When the true fact is "John plays football", then the solution should be:
Mary makes cookies = true
Luiza listens to rock = (can't solve)
Jonh plays football = (can't solve)
Question: is Prolog the correct tool for solving this kind of problem? Code examples are appreciated.

Yes, Prolog would be awesome for this.
Here's an example of a similar problem:
/*
1. Mr. K made his sighting at some point earlier in the week than the one who saw the balloon, but at some point later in the week, than the one who spotted the Kite ( who isn't Ms. G ).
2. Friday's sighting was made by either Ms. Barn or the one who saw a plane ( or both ).
3. Mr. Nik did not make his sighting on Tuesday.
4. Mr. K isn't the one whose object turned out to be a telephone pole.
*/
?-
% Set up a list of lists to be the final solution
Days = [[tuesday,_,_],[wednesday,_,_],[thursday,_,_],[friday,_,_]],
/* 1 */ before([_,mr_k,_],[_,_,balloon],Days),
/* 1 */ before([_,_,kite],[_,mr_k,_],Days),
/* 2 */ (member([friday,ms_barn,_],Days);
member([friday,_,plane],Days);
member([friday,ms_barn,plane],Days)),
% Fill in the rest of the people
members([[_,mr_k,_],[_,ms_barn,_],[_,ms_g,_],[_,mr_nik,_]],Days),
% Fill in the rest of the objects
members([[_,_,balloon],[_,_,kite],[_,_,plane],[_,_,tele_pole]],Days),
% Negations should be done after the solution is populated
/* 1 */ member([_,NOT_ms_g,kite],Days), NOT_ms_g \= ms_g,
/* 3 */ member([tuesday,NOT_mr_nik,_],Days), NOT_mr_nik \= mr_nik,
/* 4 */ member([_,NOT_mr_k,tele_pole],Days), NOT_mr_k \= mr_k,
write(Days),
nl,
fail.
% Checks that `X` comes before `Y`
% in the list `Ds`
before(X,Y,Ds) :-
remainder(X,Ds,Rs),
member(Y,Rs).
% Finds a member of a list and
% unifies the third parameter such
% that it is the remaining elements in
% the list after the found member
remainder(X,[X|Ds],Ds).
remainder(X,[_|Ds],Rs) :- remainder(X,Ds,Rs).
% An extended version of `member` that
% checks if the members of the first list
% are all members of the second
members([],_).
members([X|Xs],Ds) :-
member(X,Ds),
members(Xs,Ds).
It produces the following result:
[[tuesday, ms_g, tele_pole], [wednesday, mr_nik, kite], [thursday, mr_k, plane], [friday, ms_barn, balloon]]

Related

Checking if a child has at least 3 parents in Prolog

I attempted to solve a problem where you are given a list of facts like:
parent(a,b).
where b is the parent of a,
and I needed to write a clause that determines if someone has at least 3 parents.
Here's my attempt
has3Parent(A) :- parent(A,B), parent(A,C), parent(A,D).
With my attempt,
if A has 1 parent, it will return true once,
if A has 2 parents, it will return true 8 times,
and if A has 3 parents, it will return true 27 times.
I'm rather new to Prolog and I cannot wrap my head around as to why this could be, so any help would be much appreciated.
Because you never assured that B, C and D were different people, you will always get true as long as A has even a single parent.
So the situation with 1 parent is simple; with 2, you have these eight combinations:
A = jane, B = jane, C = jane
A = jane, B = jane, C = john
A = jane, B = john, C = jane
A = jane, B = john, C = john
A = john, B = jane, C = jane
A = john, B = jane, C = john
A = john, B = john, C = jane
A = john, B = john, C = john
Even if you just say they're not equal, you'll get false for less than 3 and true for 3 or more; but you'll still be getting multiple solutions, because order will matter.
Ideally you'd use findall/3 to get the set of parents and count it, which will give you a singular solution. Something like:
has3Parent(A) :- findall(P, parent(A, P), Ps), length(Ps, 3).
(Also note that unlike the previous, this tests whether A has exactly 3 parents, not at least 3 parents. In order to get the previous idea to test for exactly 3 parents, you would have to say that besides B, C and D being different, there also does not exist E different from all of them that is also a parent. The findall solution though is easy to adapt for different kinds of comparison, since you are dealing with a number, not a bunch of unruly variables.)
First a minor remark: You are using a relation parent/2 with arguments like parent(Child, Parent). There are many who use this name with exchanged arguments, thus parent(Parent, Child). For this reason it is much safer to clarify which order you want directly in the name. Thus child_parent(Child, Parent) is a better name, or for short child_of(Child, Parent).
Whenever you are attempting to define a predicate, first consider how this predicate will behave when definitions it depends upon change. In your case, what happens if further facts are added to child_of/2?
You originally asked for having at least 3 parents, let's call this relation has3parentsminimum/1. Then a definition with exactly 3 parents has3parents/1 and then #Amadan's definition has3parentsA/1.
Lets compare the set of solutions before and after adding facts to child_of/2.
has3parentsminimum/1: the set of solutions increases or stays the same. It increases should a further child now have 3 or more parents.
has3parents/1: the set of solutions may increase or decrease or both (thus just change). Since some children may now have four or more parents and others have now three.
has3parentsA/1: like has3parents/1 but additionally, the set of solutions may also change if a redundant fact is added.
So has3parentsminimum/1 is quite stable when adding further facts. This is known as monotonicity: When adding new clauses, everything you knew was true before stays true. Staying in the monotonic subset of Prolog as long as possible is a very good idea, since it is in this part where you can learn a lot about relations. (And that is probably the reason why you got this exercise.)
The most natural definition for has3parentsminimum/1 is to use dif/2:
has3parentsminimum(Ch) :-
dif(P1,P2), dif(P1,P3), dif(P2, P3), % all parents are different
child_of(Ch, P1),
child_of(Ch, P2),
child_of(Ch, P3).
That's probably as far as you need to go. Yes, you will get 3! = 6 redundant solutions for each child with exactly three parents, and even more so for children with more than 3 parents, but the set of solutions is fine.
But there are further improvements possible (that come at a certain price). Provided that child_of/2 contains ground facts only, you can write:
has3parentsminimum(Ch) :-
setof(P, child_of(Ch, P), [_,_,_|_]).

Querying a Prolog knowledge base

% A quiz team structure takes the form:
% team(Captain, Vice_captain, Regular_team_members).
% Captain and Vice_captain are player structures;
% Regular_team_members is a list of player structures.
% player structures take the form:
% player(First_name, Surname, details(Speciality,Recent_score)).
I've been given the following Prolog database:
team(player(niall,elliott,details(history,11)),
player(michelle,cartwright,details(fashion,19)),
[player(peter,lawlor,details(science,12)),
player(louise,boyle,details(current_affairs,17))
]
).
What would be the code needed to get the firstname and the recent score of all players whose recent score is above 15?
I've tried using exists but it keeps giving me errors.
Second question:
I need to get the surname of any vice-captain whose team includes a captain or a regular team member whose speciality is science.
I can get the surname of the vice-captains by using the first line below, but the second part is more tricky.
part_two(Surname):-
team(_,player(_,Surname,_),_),
Regular_player = team(_,_,player(_,_,details(science,_))),
Captain = team(player(_,_,details(science,_),_,_)).
A more detailed description of what you tried and how it didn't work would be better because (a) some people are reluctant to do your homework for you, and (b) we can better clear up your misunderstandings if we know what those misunderstandings are.
Anyway, Prolog programming is all about decomposing problems.
The first problem is to find out which players exist at all. A player is a team captain or a team vice captain or a regular team member. This definition has three parts separated by "or", which suggests that we need a predicate composed of three clauses:
player(Captain) :-
team(Captain, _, _).
player(Vice_captain) :-
team(_, Vice_captain, _).
player(Regular_player) :-
team(_, _, Regular_members),
member(Regular_player, Regular_members).
We can test this:
?- player(P).
P = player(niall, elliott, details(history, 11)) ;
P = player(michelle, cartwright, details(fashion, 19)) ;
P = player(peter, lawlor, details(science, 12)) ;
P = player(louise, boyle, details(current_affairs, 17)).
Now we want to identify "good players". You wrote that you have "tried using exists". There is no exists in Prolog, and it isn't needed. In order to express something like "there exists a player P such that ...", we just define a predicate containing the goal player(P) and some other goals expressing the property we are interested in. This leads to a definition like this:
good_player(First_name, Recent_score) :-
player(P),
P = player(First_name, _, details(_, Recent_score)),
Recent_score > 15.
You can read this as "there is a player P with first name First_name and recent score Recent_score such that the recent score is greater than 15".
?- good_player(F, S).
F = michelle,
S = 19 ;
F = louise,
S = 17.

Solving a puzzle in Prolog

I am new to prolog and I am trying to solve this puzzle problem. I did a couple tutorials on youtube on the basics of prolog, but I need some help solving the puzzle below.
Two weeks ago, four enthusiasts made sightings of objects in the sky in their neighborhood. Each of the four reported his or her sightings on a different day. The FBI came and was able to give each person a different explanation of what he or she had "really" seen. Can you determine the day ( Tuesday through Friday ) each person sighted the object, as well as the object that it turned out to be?
Mr. K made his sighting at some point earlier in the week than the one who saw the balloon, but at some point later in the week, than the one who spotted the Kite ( who isn't Ms. G ).
Friday's sighting was made by either Ms. Barn or the one who saw a plane ( or both ).
Mr. Nik did not make his sighting on Tuesday.
Mr. K isn't the one whose object turned out to be a telephone pole.
I have my set my rules up correctly, but I can't seem to get the logic down pack. I am looking for guidance not direct answers. On the far right, I have listed the number to each question i am attempting to answer
enthu(mr_k).
enthu(ms_barn).
enthu(ms_g).
enthu(mr_nik).
object(ballon).
object(kite).
object(plane).
object(tele_pole).
day(tuesday).
day(wednesday).
day(thursday).
day(friday).
sight(X,ballon).
sighting(mr_k):- 1
day(X),
sight(X,Y),
didntc_kite(ms_g).
friday_sight:- enthu(ms_barn); 2
saw(X,plane);
both(ms_barn,X).
nosight_tuesday(mr_nik,X). 3
no_telepole(mr_k,Y). 4
I know you didn't ask for a solution, but I find it hard to describe what to do without a working solution. I apologise for that.
Here's what I would do:
/*
1. Mr. K made his sighting at some point earlier in the week than the one who saw the balloon, but at some point later in the week, than the one who spotted the Kite ( who isn't Ms. G ).
2. Friday's sighting was made by either Ms. Barn or the one who saw a plane ( or both ).
3. Mr. Nik did not make his sighting on Tuesday.
4. Mr. K isn't the one whose object turned out to be a telephone pole.
*/
?-
% Set up a list of lists to be the final solution
Days = [[tuesday,_,_],[wednesday,_,_],[thursday,_,_],[friday,_,_]],
/* 1 */ before([_,mr_k,_],[_,_,balloon],Days),
/* 1 */ before([_,_,kite],[_,mr_k,_],Days),
/* 2 */ (member([friday,ms_barn,_],Days);
member([friday,_,plane],Days);
member([friday,ms_barn,plane],Days)),
% Fill in the rest of the people
members([[_,mr_k,_],[_,ms_barn,_],[_,ms_g,_],[_,mr_nik,_]],Days),
% Fill in the rest of the objects
members([[_,_,balloon],[_,_,kite],[_,_,plane],[_,_,tele_pole]],Days),
% Negations should be done after the solution is populated
/* 1 */ member([_,NOT_ms_g,kite],Days), NOT_ms_g \= ms_g,
/* 3 */ member([tuesday,NOT_mr_nik,_],Days), NOT_mr_nik \= mr_nik,
/* 4 */ member([_,NOT_mr_k,tele_pole],Days), NOT_mr_k \= mr_k,
write(Days),
nl,
fail.
% Checks that `X` comes before `Y`
% in the list `Ds`
before(X,Y,Ds) :-
remainder(X,Ds,Rs),
member(Y,Rs).
% Finds a member of a list and
% unifies the third parameter such
% that it is the remaining elements in
% the list after the found member
remainder(X,[X|Ds],Ds).
remainder(X,[_|Ds],Rs) :- remainder(X,Ds,Rs).
% An extended version of `member` that
% checks if the members of the first list
% are all members of the second
members([],_).
members([X|Xs],Ds) :-
member(X,Ds),
members(Xs,Ds).
That gives me:
[[tuesday, ms_g, tele_pole],
[wednesday, mr_nik, kite],
[thursday, mr_k, plane],
[friday, ms_barn, balloon]]

Prolog: simulate disjunctive facts

I've got a logic problem that I'd like to solve, so I thought, "I know, I'll try Prolog!"
Unfortunately, I'm running into a brick wall almost immediately. One of the assumptions involved is a disjunctive fact; either A, B or C is true (or more than one), but I do not know which. I've since learned that this is something Prolog does not support.
There's a lot of documentation out there that seems to address the subject, but most of it seems to immediately involve more intricate concepts and solves more advanced problems. What I'm looking for is an isolated way to simulate defining the above fact (as defining it straight away is, by limitations of Prolog, not possible).
How could I address this? Can I wrap it in a rule somehow?
EDIT: I realise I have not been very clear. Given my lack of familiarity with Prolog, I did not want to get caught up in a syntax error when trying to convey the problem, and instead went with natural language. I guess that did not work out, so I'll give it a shot in pseudo-Prolog anyway.
Intuitively, what I would want to do would be something like this, to declare that either foo(a), foo(b) or foo(c) holds, but I do not know which:
foo(a); foo(b); foo(c).
Then I would expect the following result:
?- foo(a); foo(b); foo(c).
true
Unfortunately, the fact I'm trying to declare (namely foo(x) holds for at least one x \in {a, b, c}) cannot be defined as such. Specifically, it results in No permission to modify static procedure '(;)/2'.
Side-note: after declaring the disjunctive fact, the result of ?- foo(a). would be a bit unclear to me from a logical perspective; it is clearly not true, but false does not cover it either -- Prolog simply does not have sufficient information to answer that query in this case.
EDIT 2: Here's more context to make it more of a real-world scenario, as I might have over-simplified and lost details in translation.
Say there are three people involved. Alice, Bob and Charlie. Bob holds two cards out of the set {1, 2, 3, 4}. Alice asks him questions, in response to which he shows her one card that Charlie does not see, or shows no cards. In case more cards are applicable, Bob shows just one of them. Charlie's task is to learn what cards Bob is holding. As one might expect, Charlie is an automated system.
Alice asks Bob "Do you have a 1 or a 2?", in response to which Bob shows Alice a card. Charlie now learns that Bob owns a 1 or a 2.
Alice then asks "Do you have a 2 or a 3", to which Bob has no cards to show. Clearly, Bob had a 1, which he showed Alice previously. Charlie should now be able to derive this, based on these two facts.
What I'm trying to model is the knowledge that Bob owns a 1 or a 2 (own(Bob, 1) \/ own(Bob, 2)), and that Bob does not own a 2 or a 3 (not (own(Bob, 2) \/ own(Bob, 3))). Querying if Bob owns a 1 should now be true; Charlie can derive this.
The straight-forward answer to your question:
if you can model your problem with constraint logic programming over finite domains, then, an "exclusive or" can be implemented using #\ as follows:
Of the three variables X, Y, Z, exactly one can be in the domain 1..3.
D = 1..3, X in D #\ Y in D #\ Z in D
To generalize this, you can write:
disj(D, V, V in D #\ Rest, Rest).
vars_domain_disj([V|Vs], D, Disj) :-
foldl(disj(D), Vs, Disj, V in D #\ Disj).
and use it as:
?- vars_domain_disj([X,Y,Z], 2 \/ 4 \/ 42, D).
D = (Y in 2\/4\/42#\ (Z in 2\/4\/42#\ (X in 2\/4\/42#\D))).
If you don't use CLP(FD), for example you can't find a nice mapping between your problem and integers, you can do something else. Say your variables are in a list List, and any of them, but exactly one, can be foo, and the rest cannot be foo, you can say:
?- select(foo, [A,B,C], Rest), maplist(dif(foo), Rest).
A = foo,
Rest = [B, C],
dif(B, foo),
dif(C, foo) ;
B = foo,
Rest = [A, C],
dif(A, foo),
dif(C, foo) ;
C = foo,
Rest = [A, B],
dif(A, foo),
dif(B, foo) ;
false.
The query reads: in the list [A,B,C], one of the variables can be foo, then the rest must be different from foo. You can see the three possible solutions to that query.
Original answer
It is, sadly, often claimed that Prolog does not support one thing or another; usually, this is not true.
Your question is not exactly clear at the moment, but say you mean that, with this program:
foo(a).
foo(b).
foo(c).
You get the following answer to the query:
?- foo(X).
X = a ;
X = b ;
X = c.
Which you probably interpreted as:
foo(a) is true, and foo(b) is true, and foo(c) is true.
But, if I understand your question, you want a rule which says, for example:
exactly one of foo(a), foo(b), and foo(c) can be true.
However, depending on the context, that it, the rest of your program and your query, the original solution can mean exactly that!
But you really need to be more specific in your question, because the solution will depend on it.
Edit after edited question
Here is a solution to that particular problem using constraint programming over finite domains with the great library(clpfd) by Markus Triska, available in SWI-Prolog.
Here is the full code:
:- use_module(library(clpfd)).
cards(Domain, Holds, QAs) :-
all_distinct(Holds),
Holds ins Domain,
maplist(qa_constraint(Holds), QAs).
qa_constraint(Vs, D-no) :-
maplist(not_in(D), Vs).
qa_constraint([V|Vs], D-yes) :-
foldl(disj(D), Vs, Disj, V in D #\ Disj).
not_in(D, V) :- #\ V in D.
disj(D, V, V in D #\ Rest, Rest).
And two example queries:
?- cards(1..4, [X,Y], [1 \/ 2 - yes, 2 \/ 3 - no]), X #= 1.
X = 1,
Y = 4 ;
false.
If the set of cards is {1,2,3,4}, and Bob is holding two cards, and when Alice asked "do you have 1 or 2" he said "yes", and when she asked "do you have 2 or 3" he said no, then: can Charlie know if Bob is holding a 1?
To which the answer is:
Yes, and if Bob is holding a 1, the other card is 4; there are no further possible solutions.
Or:
?- cards(1..4, [X,Y], [1 \/ 2 - yes, 2 \/ 3 - no]), X #= 3.
false.
Same as above, can Charlie know if Bob is holding a 3?
Charlie knows for sure that Bob is not holding a three!
What does it all mean?
:- use_module(library(clpfd)).
Makes the library available.
cards(Domain, Holds, QAs) :-
all_distinct(Holds),
Holds ins Domain,
maplist(qa_constraint(Holds), QAs).
This defines the rule we can query from the top level. The first argument must be a valid domain: in your case, it will be 1..4 that states that cards are in the set {1,2,3,4}. The second argument is a list of variables, each representing one of the cards that Bob is holding. The last is a list of "questions" and "answers", each in the format Domain-Answer, so that 1\/2-yes means "To the question, do you hold 1 or 2, the answer is 'yes'".
Then, we say that all cards that Bob holds are distinct, and each of them is one of the set, and then we map each of the question-answer pairs to the cards.
qa_constraint(Vs, D-no) :-
maplist(not_in(D), Vs).
qa_constraint([V|Vs], D-yes) :-
foldl(disj(D), Vs, Disj, V in D #\ Disj).
The "no" answer is easy: just say that for each of the cards Bob is holding, it is not in the provided domain: #\ V in D.
not_in(D, V) :- #\ V in D.
The "yes" answer means that we need an exclusive or for all cards Bob is holding; 2\/3-yes should result in "Either the first card is 2 or 3, or the second card is 2 or 3, but not both!"
disj(D, V, V in D #\ Rest, Rest).
To understand the last one, try:
?- foldl(disj(2\/3), [A,B], Rest, C in 2\/3 #\ Rest).
Rest = (A in 2\/3#\ (B in 2\/3#\ (C in 2\/3#\Rest))).
A generate-and-test solution in vanilla Prolog:
card(1). card(2). card(3). card(4).
owns(bob, oneof, [1,2]). % i.e., at least one of
owns(bob, not, 2).
owns(bob, not, 3).
hand(bob, Hand) :-
% bob has two distinct cards:
card(X), card(Y), X < Y, Hand = [X, Y],
% if there is a "oneof" constraint, check it:
(owns(bob, oneof, S) -> (member(A,S), member(A, Hand)) ; true),
% check all the "not" constraints:
((owns(bob, not, Card), member(Card,Hand)) -> false; true).
Transcript using the above:
$ swipl
['disjunctions.pl'].
% disjunctions.pl compiled 0.00 sec, 9 clauses
true.
?- hand(bob,Hand).
Hand = [1, 4] ;
;
false.
Note that Prolog is Turing complete, so generally speaking, when someone says "it can't be done in Prolog" they usually mean something like "it involves some extra work".
Just for the sake of it, here is a small program:
card(1). card(2). card(3). card(4). % and so on
holds_some_of([1,2]). % and so on
holds_none_of([2,3]). % and so on
holds_card(C) :-
card(C),
holds_none_of(Ns),
\+ member(C, Ns).
I have omitted who owns what and such. I have not normalized holds_some_of/1 and holds_none_of/1 on purpose.
This is actually enough for the following queries:
?- holds_card(X).
X = 1 ;
X = 4.
?- holds_card(1).
true.
?- holds_card(2).
false.
?- holds_card(3).
false.
?- holds_card(4).
true.
which comes to show that you don't even need the knowledge that Bob is holding 1 or 2. By the way, while trying to code this, I noticed the following ambiguity, from the original problem statement:
Alice asks Bob "Do you have a 1 or a 2?", in response to which Bob shows Alice a card. Charlie now learns that Bob owns a 1 or a 2.
Does that now mean that Bob has exactly one of 1 and 2, or that he could be holding either one or both of the cards?
PS
The small program above can actually be reduced to the following query:
?- member(C, [1,2,3,4]), \+ member(C, [2,3]).
C = 1 ;
C = 4.
(Eep, I just realized this is 6 years old, but maybe it's interesting to introduce logic-programming languages with probabilistic choices for the next stumbler )
I would say the accepted answer is the most correct, but if one is interested in probabilities, a PLP language such as problog might be interesting:
This example assumes we don't know how many cards bob holds. It can be modified for a fixed number of cards without much difficulty.
card(C):- between(1,5,C). % wlog: A world with 5 cards
% Assumption: We don't know how many cards bob owns. Adapting to a fixed number of cards isn't hard either
0.5::own(bob, C):-
card(C).
pos :- (own(bob,1); own(bob,2)).
neg :- (own(bob,2); own(bob,3)).
evidence(pos). % tells problog pos is true.
evidence(\+neg). % tells problog neg is not true.
query(own(bob,Z)).
Try it online: https://dtai.cs.kuleuven.be/problog/editor.html#task=prob&hash=5f28ffe6d59cae0421bb58bc892a5eb1
Although the semantics of problog are a bit harder to pick-up than prolog, I find this approach an interesting way of expressing the problem. The computation is also harder, but that's not necessarily something the user has to worry about.

Prolog riddle solving

The statement :
Four couples in all
Attended a costume ball.
2
The lady dressed as a cat
Arrived with her husband Matt.
3
Two couples were already there,
One man dressed like a bear.
4
First to arrive wasn't Vince,
But he got there before the Prince.
5
The witch (not Sue) is married to Chuck,
Who was dressed as Donald Duck.
6
Mary came in after Lou,
Both were there before Sue.
7
The Gipsy arrived before Ann,
Neither is wed to Batman.
8
If Snow White arrived after Tess,
Then how was each couple dressed?
My code is here , but it returns false :
sol(S):-
S=[[1,L1,M1,LD1,MD1],
[2,L2,M2,LD2,MD2],
[3,L3,M3,LD3,MD3],
[4,L4,M4,LD4,MD4]],
member([_,_,matt,cat,_],S),
member([ALR,_,_,_,bear],S),
(ALR =:= 1 ; ALR =:= 2),
not(member([1,_,vince,_,_],S)),
member([VN,_,vince,_,_],S),
member([PS,_,_,_,prince],S),
VN < PS ,
member([_,_,chuck,witch,donald],S),
not(member([_,sue,_,witch,_],S)),
member([MRY,mary,_,_,_],S),
member([LOU,_,lou,_,_],S),
member([SUE,sue,_,_,_],S),
MRY > LOU,
MRY < SUE,
member([GPS,_,_,gipsy,_],S),
member([ANN,ann,_,_,_],S),
GPS < ANN ,
not(member([_,_,_,gipsy,batman],S)),
not(member([_,ann,_,_,batman],S)),
member([SW,_,_,snowwhite,_],S),
member([TS,tess,_,_,_],S),
SW > TS ,
perm([sue,mary,ann,tess],[L1,L2,L3,L4]),
perm([matt,lou,vince,chuck],[M1,M2,M3,M4]),
perm([cat,witch,gipsy,snowwhite],[LD1,LD2,LD3,LD4]),
perm([donald,prince,batman,bear],[MD1,MD2,MD3,MD4]).
takeout(X,[X|R],R).
takeout(X,[F|R],[F|S]) :- takeout(X,R,S).
perm([],[]).
perm([X|Y],Z) :- perm(Y,W), takeout(X,Z,W).
Any solution ?
You should move all your not(...) goals to the very end of the predicate.
not(G) means, "G is impossible to satisfy right now". When tried too early, with many still non-instantiated variables in the lists, it is in fact very often possible to satisfy a goal, and the whole not(...) call will fail right away.
Alternatively, delay the checking of the inequality on a variable until it is instantiated, e.g. in SWI Prolog with freeze/2 (as seen e.g. in this answer).

Resources