2

I am studying Prolog on Ivan Bratko book: Programming for Artificial Intelligence and on the book I have found this version of 8 Queens problem that use a space state "graph" to solve the problem:

s(Queens, [Queen|Queens]) :- member(Queen, [1,2,3,4,5,6,7,8]),
                             noattack(Queen, Queens).

goal([_,_,_,_,_,_,_,_]).

noattack(_,[],_).

noattack(Y,[Y1|Ylist],Xdist) :-
                                  Y1-Y =\= Xdist,
                      Y-Y1 =\= Xdist,
                                  Dist1 is Xdist + 1,
                                  noattack(Y,Ylist,Dist1).

solve(N,[N]) :- goal(N).

solve(N, [N|Sol1]) :- s(N,N1),
                      solve(N1,Sol1).

It combines the 8 Queens problem solution based on permutation (use its noattack/3 relation) and the s/2 predicate that I think that build the possible successor states state (the nodes of my graph). So I have something like:

s(ActualState, SuccessorState)

The goal/1 predicate I think that only specify that I have to place exactly 8 queens.

On the book say me that executing this query: solve([],Solution) it will produce a list of board positions with increasing number of queens and that this list will end with a safe configuration of the eight queens.

But if I try to execute this query don't work and I will obtain this output:

?- solve([],Solution).
ERROR: s/2: Undefined procedure: noattack/2
ERROR:   However, there are definitions for:
ERROR:         noattack/3

Because,rightly, the noattack predicate called in the line 2 take only 2 parameters but the noattack predicate must have 3 parameters...bue on the book is given in this wrong way and I don't know how solve this problem...

Why? What am I missing?

false
  • 10,264
  • 13
  • 101
  • 209
AndreaNobili
  • 40,955
  • 107
  • 324
  • 596
  • 1
    There is a whole bunch of compile-time warnings in this program, are you sure you typed it in correctly? (I am almost sure you did not) –  May 08 '13 at 12:17
  • I have correct the TYPO error but now I have some others problem...unfortunately it seems that the solution given in the book is wrong or not complete – AndreaNobili May 08 '13 at 12:35

1 Answers1

3

few bugs:

s(Queens, [Queen|Queens]) :- member(Queen, [1,2,3,4,5,6,7,8]),
                             noattack(Queen, Queens, 1).

noattack(_,[],_) :- !.
noattack(Y,[Y1|Ylist],Xdist) :-   Y =\= Y1,
                                  Y1-Y =\= Xdist,
                                  Y-Y1 =\= Xdist,
                                  Dist1 is Xdist + 1,
                                  noattack(Y,Ylist,Dist1).

Then,

18 ?- solve([],_X), last(_X,S).
S = [4, 2, 7, 3, 6, 8, 5, 1] ;
S = [5, 2, 4, 7, 3, 8, 6, 1] ;
S = [3, 5, 2, 8, 6, 4, 7, 1] ;
S = [3, 6, 4, 2, 8, 5, 7, 1] ;
S = [5, 7, 1, 3, 8, 6, 4, 2] ;
S = [4, 6, 8, 3, 1, 7, 5, 2]

and,

25 ?- findall( X, solve([],X), _S), length(_S,N).
N = 92.
Will Ness
  • 70,110
  • 9
  • 98
  • 181
  • Ok, tnx so much as usual your intervention gave me a great help (unfortunately I have not been able to follow this course last semester because I was at work and sometimes studying Prolog alone I find it hard...) Now I will try to understand deeply this code. For now I have only a general purposte question for you about it. In the previous example the program explore by a DFS visit the space state "graph". Every node of the graph rappresent a valid state so: 1) In this case a valid state is a 8 queen configuration where are there no attack? – AndreaNobili May 08 '13 at 14:17
  • 2) I have never explictly declared the graph, can I see it as automatically build by the s/2 predicate that bring me from a valid state to another valide state with some moves? If you can give me some hints to understand well this situation I will be very grateful to you :-) Tnx – AndreaNobili May 08 '13 at 14:19
  • not exactly. notice, in `s(X,Y)`, Y is always a list 1 element longer than X (also, a list). So `s/2` represents a "move" of say, a player placing one queen on chess board so that it doesn't attack those queens already there. – Will Ness May 08 '13 at 14:21
  • `s/2` *is* a move; but we try new combinations through backtracking, so previous assignments are undone (forgotten). You'd have to change it: find all possible moves, in a list - then this list holds all the nodes to explore. BTW this particular solution is inefficient - it tries all queens from 1 to 8 on each move. but we don't need to try those that we already placed before. Bratko develops this insight into very nice and efficient 4D solution, a few pages later IIRC. – Will Ness May 08 '13 at 14:22
  • and the last state, after the last move, is the solution. (that's why I had to call `last/2`). try just `solve([],X), write(X),nl`, you'll see it. – Will Ness May 08 '13 at 14:27