Eight Queens Puzzle in CLIPS

219 views Asked by At

I'm trying to develop an solver for the eight queens problem (https://en.wikipedia.org/wiki/Eight_queens_puzzle) in CLIPS, but I'm a newbie in this language. First of all, I was trying to make a rule to verify a new assertion comparing column/line of previous assertions. Its working when is inserted a duplicated line, however when inserted a duplicated column, it doesn't detect it. What's wrong with this code?

(defrule verificaAssercaoDamas ; verifica se atende as regras
   ?novaPosicao <- (d ?line ?column) 
   ?posicao <- (d ?line2 ?column2)
   (test (neq ?posicao ?novaPosicao))
   (test (or (eq ?line2 ?line) (eq ?column column2))  )
   =>
   (retract ?novaPosicao)
   (if (< (+ ?column 1) 9)
       then (assert (d ?line (+ ?column 1) ))
)
CLIPS> (assert(d 0 0))
<Fact-1>
CLIPS> (assert(d 1 0))
<Fact-2>
CLIPS> (assert(d 0 1))
<Fact-3>
CLIPS> (agenda)
0       cerificaAssercaoDamas: f-3, f-1
0       cerificaAssercaoDamas: f-1, f-3
For a total of 2 activations.
CLIPS>
1

There are 1 answers

0
Gary Riley On

You're using the expression (eq ?column column2) which is comparing the variable ?column to the symbol column2. You need to compare it to the variable ?column2.

CLIPS> (clear)
CLIPS> 
(defrule verificaAssercaoDamas 
   ?novaPosicao <- (d ?line ?column) 
   ?posicao <- (d ?line2 ?column2)
   (test (neq ?posicao ?novaPosicao))
   (test (or (eq ?line2 ?line) (eq ?column ?column2)))
   =>
   (retract ?novaPosicao)
   (if (< (+ ?column 1) 9)
       then (assert (d ?line (+ ?column 1)))))
CLIPS> (assert (d 0 0))
<Fact-1>
CLIPS> (assert (d 1 0))
<Fact-2>
CLIPS> (assert (d 0 1))
<Fact-3>
CLIPS> (agenda)
0      verificaAssercaoDamas: f-3,f-1
0      verificaAssercaoDamas: f-1,f-3
0      verificaAssercaoDamas: f-2,f-1
0      verificaAssercaoDamas: f-1,f-2
For a total of 4 activations.
CLIPS> 

If you're testing equality/inequality of numbers, you should use the = and != (or <>) functions as these will throw errors for non-numeric arguments:

CLIPS> (clear)
CLIPS> 
(defrule verificaAssercaoDamas 
   ?novaPosicao <- (d ?line ?column) 
   ?posicao <- (d ?line2 ?column2)
   (test (neq ?posicao ?novaPosicao))
   (test (or (= ?line2 ?line) (= ?column column2)))
   =>
   (retract ?novaPosicao)
   (if (< (+ ?column 1) 9)
       then (assert (d ?line (+ ?column 1)))))
[ARGACCES5] Function = expected argument #2 to be of type integer or float

ERROR:
(defrule MAIN::verificaAssercaoDamas
   ?novaPosicao <- (d ?line ?column)
   ?posicao <- (d ?line2 ?column2)
   (test (neq ?posicao ?novaPosicao))
   (test (or (= ?line2 ?line) (= ?column column2)
CLIPS> 

You can also remove the duplicate activations by checking that the fact index of ?novaPosicao is greater than the one for ?posicao:

CLIPS> (clear)
CLIPS> 
(defrule verificaAssercaoDamas 
   ?novaPosicao <- (d ?line ?column) 
   ?posicao <- (d ?line2 ?column2)
   (test (< (fact-index ?posicao) (fact-index ?novaPosicao)))
   (test (or (= ?line2 ?line) (= ?column ?column2)))
   =>
   (retract ?novaPosicao)
   (if (< (+ ?column 1) 9)
       then (assert (d ?line (+ ?column 1)))))
CLIPS> (assert (d 0 0))
<Fact-1>
CLIPS> (assert (d 1 0))
<Fact-2>
CLIPS> (assert (d 0 1))
<Fact-3>
CLIPS> (agenda)
0      verificaAssercaoDamas: f-3,f-1
0      verificaAssercaoDamas: f-2,f-1
For a total of 2 activations.
CLIPS>