Search code examples
prologinfinite-loopn-queensfailure-slice

Prolog - N-Queens quiz - infinite loop


This is about the 8-Queens problem. I'm trying to solve the more generic N-Queens problem.

The goal is to make this rule show me all the possible answers. For example:

solution(Sol,4).
X = [2, 4, 1, 3] ;
X = [3, 1, 4, 2] ;
false.

I managed to get all the answers right and everything but for some reason, my code enters an infinite loop after the last solution.

This is what I've written so far:

no_threat(Queen1, Queen2, Dist):-
    Queen1=\=Queen2,
    Queen1>0, Queen2>0,
    Dist=\=Queen2-Queen1,
    Dist=\=Queen1-Queen2,!.

queen_safe_aux(_, [], _):- true,!.
queen_safe_aux(Queen, [L|Ls], Dist):-
    no_threat(Queen, L, Dist),
    Dist2 is Dist+1,
    queen_safe_aux(Queen, Ls, Dist2).

queen_safe(Queen, L):- queen_safe_aux(Queen, L, 1).

legal_solution_aux([]):-true,!.
legal_solution_aux([L|Ls]):- queen_safe(L,Ls),legal_solution_aux(Ls).

legal_solution(L):-
    length(L, Length),
    range(1, Length, Sorted),
    permutation(Sorted, L),
    legal_solution_aux(L).

solution(L,N):-legal_solution(L),length(L,N1),N1=N.

This is the range rule I used for the solution (it is correct):

range(From, From, [From]):- true, !.
range(From, To, [From|Ls]):- From < To, From2 is From+1, range(From2, To, Ls).

I know this is probably not the best solution but I could use some help understanding what went wrong here.


Solution

  • Here is the relevant program fragment:

    solution(L,N):-
       legal_solution(L), false
       length(L,N1),
       N1=N.
    
    legal_solution(L):-
        length(L, Length), false,
        range(1, Length, Sorted),
        permutation(Sorted, L),
        legal_solution_aux(L).

    This fragment () already loops for a query like solution(L,4) and thus your entire program will loop as well. You need to modify something in the visible part. I'd suggest:

    solution(L, N) :-
       length(L, N),
       legal_solution(L).
    

    Otherwise, you are heavily using cuts which often limit the applicability of declarative debugging techniques. There is no need here.