Newbie in prolog: Simple Solve

2019-09-20 06:16发布

问题:

I am new to prolog, and I am trying to solve this:

It just returns false!

I have tried changing several parts of the code several times, as I said I'm a newbie in prolog and thus I don't know how to debug exactly..

livesIn(State):-
member(State,[california,georgia,delaware,iowa,kansas]).

sentGift(Gift):-
member(Gift,[rotisserie,salver,toaster,urn,vase]).

isHusband(Husband):-
member(Husband,[bill,doug,nick,tom,zack]).

solve(Z):-
Z=[[amber,Husband1,State1,Gift1],
   [emily,Husband2,State2,Gift2],
   [janet,Husband3,State3,Gift3],
   [maisie,Husband4,State4,Gift4],
   [patsy,Husband5,State5,Gift5]],

isHusband(Husband1), isHusband(Husband2), isHusband(Husband3), isHusband(Husband4), isHusband(Husband5),
Husband1 \== Husband2, Husband1 \== Husband3, Husband1 \== Husband4, Husband1 \== Husband5,
Husband2 \== Husband1, Husband2 \== Husband3, Husband2 \== Husband4, Husband2 \== Husband5,
Husband3 \== Husband1, Husband3 \== Husband2, Husband3 \== Husband4, Husband3 \== Husband5,
Husband4 \== Husband1, Husband4 \== Husband2, Husband4 \== Husband3, Husband4 \== Husband5,
Husband5 \== Husband1, Husband5 \== Husband2, Husband5 \== Husband3, Husband5 \== Husband4,

livesIn(State1), livesIn(State2), livesIn(State3), livesIn(State4), livesIn(State5),
State1 \== State2, State1 \== State3, State1 \== State4, State1 \== State5,
State2 \== State1, State2 \== State3, State2 \== State4, State2 \== State5,
State3 \== State1, State3 \== State2, State3 \== State4, State3 \== State5,
State4 \== State1, State4 \== State2, State4 \== State3, State4 \== State5,
State5 \== State1, State5 \== State2, State5 \== State3, State5 \== State4,

sentGift(Gift1), livesIn(Gift2), livesIn(Gift3), livesIn(Gift4), livesIn(Gift5),
Gift1 \== Gift2, Gift1 \== Gift3, Gift1 \== Gift4, Gift1 \== Gift5,
Gift2 \== Gift1, Gift2 \== Gift3, Gift2 \== Gift4, Gift2 \== Gift5,
Gift3 \== Gift1, Gift3 \== Gift2, Gift3 \== Gift4, Gift3 \== Gift5,
Gift4 \== Gift1, Gift4 \== Gift2, Gift4 \== Gift3, Gift4 \== Gift5,
Gift5 \== Gift1, Gift5 \== Gift2, Gift5 \== Gift3, Gift5 \== Gift4,

%Aunt Maisie's Husband is Uncle Nick
Husband4 = nick,

%Uncle Bill and Aunt Emily and their respective spouses sent the salver and the urn (in order)
Gift2 = salver,
member([_, bill, _, urn], Z),

%Aunt Amber and Uncle Doug live in Georgia
Husband1 = doug,
State1 = georgia,

%Aunt Patsy and her husband sent a toaster
Gift5 = toaster,

%The rotisserie came from the Delaware relatives
member([_, _, delaware, rotisserie], Z),

%Uncle Zack and his wife(don't live in Kansas) sent neither the salver nor the toaster
\+ member([_, zack, kansas, _], Z),
\+ member([_, zack, _, salver], Z),
\+ member([_, zack, _, toaster], Z),

%Aunt Janet and Uncle Bill live in California
Husband3 = bill,
State3 = california.

回答1:

Make it works

There are 2 typos in your code that prevents it from returning the correct result.

First typo

Uncle Bill and Aunt Emily and their respective spouses sent the salver and the urn (in order)

So instead of:

Gift2 = salver,
member([_, bill, _, urn], Z),

It should be:

Gift2 = urn,                       % Aunt Emily sent the urn
member([_, bill, _, salver], Z),   % Uncle Bill sent the salver

Second typo

I don't know how you can make this typo! Why livesIn a gift?

sentGift(Gift1), livesIn(Gift2), livesIn(Gift3), livesIn(Gift4), livesIn(Gift5),
Gift1 \== Gift2, Gift1 \== Gift3, Gift1 \== Gift4, Gift1 \== Gift5,

Should be:

sentGift(Gift1), sentGift(Gift2), sentGift(Gift3), sentGift(Gift4), sentGift(Gift5),
Gift1 \== Gift2, Gift1 \== Gift3, Gift1 \== Gift4, Gift1 \== Gift5,

After fixing the 2 typos above, the code will work correctly, but it will take very long time to reach the solution.

Make it fast

  1. Order the direct unification with an atom (e.g. Husband3 = bill, State1 = georgia) before the membership unification of the Gift, Husband and State variables via sentGift, isHusband and livesIn predicates.

    Actually, you can just plug them directly to Z. And instead of declaring all those inequality manually (e.g. Gift1 \== Gift2, Gift1 \== Gift3, Gift1 \== Gift4, Gift1 \== Gift5), it is cleaner to write a predicate instead.

  2. Order the membership unification (e.g. member([_, bill, _, urn], Z)) after the direct unification in part 1, but still before membership unification of the Gift, Husband and State variables.

    Note that this does not include \+ member([_, zack, _, toaster], Z), which asserts that membership unification CANNOT succeed. Before the membership unification of the Gift, Husband and State variables which constraint them to a small set of possible values, it might be possible to find a unification that satisfy the membership unification, which leads to the clause and thus the whole predicate failing.

The 2 tricks above will reduce the search space and therefore reduce the time needed to find a solution. Below is some sample skeleton code for you to fill in when you have read the text above.

% Aunt Maisie's Husband is Uncle Nick
Husband4 = nick,

%% TODO: Fill in the rest on your own ...

% Uncle Bill and Aunt Emily and their respective spouses sent the salver and the urn (in order)
Gift2 = urn,




member([_, bill, _, salver], Z),

% The rotisserie came from the Delaware relatives
member([_, _, delaware, rotisserie], Z),




sentGift(Gift1), sentGift(Gift2), sentGift(Gift3), sentGift(Gift4), sentGift(Gift5),
Gift1 \== Gift2, Gift1 \== Gift3, Gift1 \== Gift4, Gift1 \== Gift5,
Gift2 \== Gift1, Gift2 \== Gift3, Gift2 \== Gift4, Gift2 \== Gift5,

%% TODO: Fill in the rest on your own





% Uncle Zack and his wife(don't live in Kansas) sent neither the salver nor the toaster
\+ member([_, zack, kansas, _], Z),
\+ member([_, zack, _, salver], Z),
\+ member([_, zack, _, toaster], Z).


标签: prolog