Something like OR operator in CLIPS (CLIPS Rule Based Programming Language) - conditional-statements

I need help with this program, I couldn't find out how to do that a user can input a yes/no for characters and I have defined a type of animal-like mammal - for mammal applies that milk character must be yes and legs(number of legs) can be 2 or 4 and another character can be yes or no like for example -
mammal - milk yes, legs 2 or 4, but backbone can yes or no, predator yes or no .... but I don't know how to do it (OR condition or idk something like that), user can input one of these its find out the type of animal which is defined in effects, thanks for help :)
;*********** DEFTEMPLATE ***********;
(deftemplate animal_type
(slot type (type SYMBOL) (allowed-symbols mammal bird fish))
(slot milk (type SYMBOL) (allowed-symbols yes no))
(slot feathers (type SYMBOL) (allowed-symbols yes no))
(slot fins (type SYMBOL) (allowed-symbols yes no))
(slot backbone (type SYMBOL) (allowed-symbols yes no))
(slot fly (type SYMBOL) (allowed-symbols yes no))
(slot predator (type SYMBOL) (allowed-symbols yes no))
(multislot legs (type INTEGER) (allowed-integers 0 2 4 6 8))
)
(deftemplate finding_type
(slot milk (type SYMBOL) (allowed-symbols yes no))
(slot feathers (type SYMBOL) (allowed-symbols yes no))
(slot fins (type SYMBOL) (allowed-symbols yes no))
(slot backbone (type SYMBOL) (allowed-symbols yes no))
(slot fly (type SYMBOL) (allowed-symbols yes no))
(slot predator (type SYMBOL) (allowed-symbols yes no))
(multislot legs (type INTEGER) (allowed-integers 0 2 4 6 8))
)
;*********** DEFFACTS ***********;
(deffacts characters_type
(animal_type (typ mammal) (milk yes) (legs 2 4))
(animal_type (typ bird) (milk no) (feathers yes) (fly yes))
(animal_type (typ fish) (milk no) (feathers no) (fins yes) (legs 0))
)     
;something like this (animal_type (typ mammal) (milk yes) (backbone or(yes no)) ... (legs 2 4))
(deffacts temp_fact
(next_search)
)
(defrule input_characters
?gone<-(next_search)
=> (retract ?gone)
(printout t " " crlf)
(printout t "Enter - yes/no, legs - 0/2/4/6/8" crlf)
(printout t "==================================================================" crlf)
(printout t "Milk:")
(bind ?o1 (read))
(printout t "Feathers:")
(bind ?o2 (read))
(printout t "Fins:")
(bind ?o3 (read))
(printout t "Backbone:")
(bind ?o4 (read))
(printout t "Fly:")
(bind ?o5 (read))
(printout t "Predator:")
(bind ?o6 (read))
(printout t "Legs:")
(bind ?o7 (read))
(assert (finding_type (milk ?o1) (feathers ?o2) (fins ?o3) (backbone ?o4) (fly ?o5) (predator ?o6) (legs ?o7)) )
)
(defrule find_out_type
(finding_type (milk ?o1) (feathers ?o2) (fins ?o3) (backbone ?o4) (fly ?o5) (predator ?o6) (legs ?o7))
(animal_type (type ?type) (milk ?o1) (feathers ?o2) (fins ?o3) (backbone ?o4) (fly ?o5) (predator ?o6) (legs ?o7))
=>
(printout t " " crlf)
(printout t "Type of animal is: " ?type crlf)
)
(defrule not_found
(finding_type (milk ?o1) (feathers ?o2) (fins ?o3) (backbone ?o4) (fly ?o5) (predator ?o6) (legs ?o7))
(not (animal_type (type ?type) (milk ?o1) (feathers ?o2) (fins ?o3) (backbone ?o4) (fly ?o5) (predator ?o6) (legs ?o7)) )
=>
(printout t " " crlf)
(printout t "Nothing found!" crlf)
)
(defrule cancel (declare (salience -10))
?gone<-(finding_type (milk ?o1) (feathers ?o2) (fins ?o3) (backbone ?o4) (fly ?o5) (predator ?o6) (legs ?o7))
=>
(retract ?gone)
)

Modify the animal_type pattern in your rules to use multifield wildcards to match extraneous values to the left and right of the specified number of legs. As your rules are currently the animal_type patterns will only be matched by facts containing exactly one value in the legs slot.
(animal_type (type ?type)
(milk ?o1)
(feathers ?o2)
(fins ?o3)
(backbone ?o4)
(fly ?o5)
(predator ?o6)
(legs $? ?o7 $?))

Related

Clips not printing anything

I tried to write the following code in CLIPS for a school project (even though I don't understand why AI is done in this language):
(deftemplate blood
(slot bt)
(multislot acc))
(deffacts acceptance
(blood (bt 0) (acc 0 0))
(blood (bt A) (acc 0 A))
(blood (bt B) (acc 0 B))
(blood (bt AB) (acc 0 A B AB)))
(defrule reading-input
=>
(printout t "Bloodtype of patient? ")
(assert (patient (read)))
(printout t "Bloodtype of donor? ")
(assert (donor (read))))
(defrule check-acceptance
(patient ?patient)
(donor ?donor)
(blood (bt ?bt1) (acc ?acc1))
(test (member$ ?donor ?acc1))
=>
(printout t "Transfusion is safe" crlf))
For some reason it wouldn't print anything for inputs A and A or anything else. I also tried this with a if then else statement, but same result.
[prev code]
(blood (bt ?bt1) (acc ?acc1))
=>
(if (eq ?patient ?bt1)
then
(printout t ?bt1)
else
(printout t ?donor)))
The idea is to write a program that prints whether blood transfusion is safe or not.
Modify your blood pattern so that the bt slot is restricted to the blood type of the patient and change the variable acc1 to a multifield variable so that it will bind to all of the values in the acc slot:
(defrule check-acceptance
(patient ?patient)
(donor ?donor)
(blood (bt ?patient) (acc $?acc1))
(test (member$ ?donor ?acc1))
=>
(printout t "Transfusion is safe" crlf))

Eight Queens Puzzle in CLIPS

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>
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>

First CLIPS code doesnt work

I wrote my first CLIPS code for a school project but I am not familiar with CLIPS (I use C# and python as main languages).
This is my code and the errors I am gettin:
(defrule determine-closing-date
(not (day-to-close ?))
(billing-size ?)
(unpaid-invoices-number ?)
=>
(if
(or
(< billing-size 1000000)
(< unpaid-invoices-number 1000000)
)
then (assert (day-to-close MtTh))
else (assert (day-to-close friday))
)
(defrule determine-billing-size ""
(not (billing-size ?))
(not (day-to-close ?))
=>
(printout t "¿Cuál es el tamaño de la facturacion?")
(assert (billing-size ?size (read))))
(defrule determine-unpaid-invoices-number ""
(not (unpaid-invoices-number ?))
(not (day-to-close ?))
=>
(printout t "¿Cuál es la cantidad de facturas no pagadas")
(assert (unpaid-invoices-number ?size (read))))
(defrule determine-friday-load ""
(day-to-close friday)
(not (friday-load ?))
=>
(printout t "¿Cuál es la carga de cierres para el viernes?")
(assert (friday-load ?load (read))))
(defrule determine-saturday-closing ""
(day-to-close friday)
(not(< friday-load 1000000))
=>
(assert (day-to-close saturday)))
(defrule day-to-close-conclulssion ""
(day-to-close ?)
=>
(if (eq day-to-close MtTh)
then (printout t "Se puede cerrar de Lunes a Jueves")
else (
if (eq day-to-close friday)
then (printout t "Se debe cerrar viernes.")
else (printout t "Se debe cerrar sabado.")
)
))
The errores are:
[ARGACCES5] Function < expected argument #1 to be of type integer or float
[PRCCODE3] Undefined variable size referenced in RHS of defrule.
[CSTRCPSR1] WARNING: Redefining defrule: determine-saturday-closing +j+j+j
[CSTRCPSR1] WARNING: Redefining defrule: day-to-close-conclulssion +j+j
Some suggest revisions:
(defrule determine-closing-date
(not (day-to-close ?))
(billing-size ?billing-size)
(unpaid-invoices-number ?unpaid-invoices-number)
=>
(if (or (< ?billing-size 1000000)
(< ?unpaid-invoices-number 1000000))
then (assert (day-to-close MtTh))
else (assert (day-to-close friday))))
(defrule determine-billing-size ""
(not (billing-size ?))
(not (day-to-close ?))
=>
; What is the size of the billing?
(printout t "¿Cuál es el tamaño de la facturacion? ")
(bind ?size (read))
(assert (billing-size ?size)))
(defrule determine-unpaid-invoices-number ""
(not (unpaid-invoices-number ?))
(not (day-to-close ?))
=>
; What is the amount of unpaid bills?
(printout t "¿Cuál es la cantidad de facturas no pagadas? ")
(bind ?size (read))
(assert (unpaid-invoices-number ?size)))
(defrule determine-friday-load ""
(day-to-close friday)
(not (friday-load ?))
=>
; What is the burden of closures for Friday?
(printout t "¿Cuál es la carga de cierres para el viernes? ")
(bind ?load (read))
(assert (friday-load ?load)))
(defrule determine-saturday-closing ""
?dtc <- (day-to-close friday)
(friday-load ?load&:(< ?load 1000000))
=>
(retract ?dtc)
(assert (day-to-close saturday)))
(defrule day-to-close-conclusion ""
(declare (salience -10))
(day-to-close ?day-to-close)
=>
(switch ?day-to-close
(case MtTh
; Can be closed from Monday to Thursday.
then (printout t "Se puede cerrar de Lunes a Jueves." crlf))
(case friday
; Must be closed Fridays.
then (printout t "Se debe cerrar viernes." crlf))
(default
; Must be closed Saturday.
then (printout t "Se debe cerrar sabado." crlf))))
And the output it produces:
CLIPS> Loading Buffer...
******
CLIPS> (reset)
CLIPS> (run)
¿Cuál es el tamaño de la facturacion? 10
¿Cuál es la cantidad de facturas no pagadas? 10
Se puede cerrar de Lunes a Jueves.
CLIPS> (reset)
CLIPS> (run)
¿Cuál es el tamaño de la facturacion? 3000000
¿Cuál es la cantidad de facturas no pagadas? 3000000
¿Cuál es la carga de cierres para el viernes? 10
Se debe cerrar sabado.
CLIPS> (reset)
CLIPS> (run)
¿Cuál es el tamaño de la facturacion? 3000000
¿Cuál es la cantidad de facturas no pagadas? 3000000
¿Cuál es la carga de cierres para el viernes? 3000000
Se debe cerrar viernes.
CLIPS>

CLIPS: slots within multislots

I am currently working in CLIPS and I am new to it. I am trying to replicate the following information in a CLIPS deftemplate:
[Person, [Class,Class],[[M 9,11],[F,9,11]]]
It has a person, multiple classes that they can take and the times that they can take the class. I try to replicate this information in the following deftemplate:
(deftemplate person
(slot Name)
(multislot Class)
(multislot Available))
My problem is I do not understand what I am supposed to do in the available multislot because it has three inputs. Is there a way that I can make slots within a multislot? I have looked online for ways to do this but have not been able to correctly solve this problem.
Here are four different approaches. I would suggest something similar to approach 3 or 4 since these involve simple linkages between facts/instances.
CLIPS> (clear) ; Approach 1
CLIPS>
(deftemplate person
(slot Name)
(multislot Class)
(multislot Available))
CLIPS>
(deffacts people
(person (Name Frank)
(Class Biology Calculus)
(Available M 9 11 F 9 11)))
CLIPS>
(deffunction #-of-triplets (?mf)
(div (length$ ?mf) 3))
CLIPS>
(deffunction nth-triplet (?mf ?n)
(subseq$ ?mf (+ 1 (* (- ?n 1) 3))(* ?n 3)))
CLIPS>
(defrule print-availability
(person (Name ?name)
(Available $?a))
=>
(loop-for-count (?i (#-of-triplets ?a))
(bind ?triplet (nth-triplet ?a ?i))
(bind ?d (nth$ 1 ?triplet))
(bind ?b (nth$ 2 ?triplet))
(bind ?e (nth$ 3 ?triplet))
(printout t ?name " " ?d " " ?b " " ?e crlf)))
CLIPS> (reset)
CLIPS> (run)
Frank M 9 11
Frank F 9 11
CLIPS> (clear) ; Approach 2
CLIPS>
(deftemplate person
(slot Name)
(multislot Class)
(multislot Available-Weekday)
(multislot Available-Begin)
(multislot Available-End))
CLIPS>
(deffacts people
(person (Name Frank)
(Class Biology Calculus)
(Available-Weekday M F)
(Available-Begin 9 9)
(Available-End 11 11)))
CLIPS>
(defrule print-availability
(person (Name ?name)
(Available-Weekday $?f1 ?d $?)
(Available-Begin $?f2 ?b $?)
(Available-End $?f3 ?e $?))
(test (= (length$ ?f1)
(length$ ?f2)
(length$ ?f3)))
=>
(printout t ?name " " ?d " " ?b " " ?e crlf))
CLIPS> (reset)
CLIPS> (run)
Frank M 9 11
Frank F 9 11
CLIPS> (clear) ; Approach 3
CLIPS>
(deftemplate person
(slot Name)
(slot ID)
(multislot Class))
CLIPS>
(deftemplate availability
(slot owner-ID)
(slot Weekday)
(slot Begin)
(slot End))
CLIPS>
(deffacts information
(person (Name Frank) (ID 1)
(Class Biology Calculus))
(availability (owner-ID 1) (Weekday M) (Begin 9) (End 11))
(availability (owner-ID 1) (Weekday F) (Begin 9) (End 11)))
CLIPS>
(defrule print-availability
(person (Name ?name) (ID ?id))
(availability (owner-ID ?id) (Weekday ?d) (Begin ?b) (End ?e))
=>
(printout t ?name " " ?d " " ?b " " ?e crlf))
CLIPS> (reset)
CLIPS> (run)
Frank F 9 11
Frank M 9 11
CLIPS> (clear) ; Approach 4
CLIPS>
(defclass PERSON
(is-a USER)
(slot Name)
(multislot Class)
(multislot Available))
CLIPS>
(defclass AVAILABILITY
(is-a USER)
(slot Weekday)
(slot Begin)
(slot End))
CLIPS>
(definstances information
(of PERSON (Name Frank)
(Class Biology Calculus)
(Available (make-instance of AVAILABILITY (Weekday M) (Begin 9) (End 11))
(make-instance of AVAILABILITY (Weekday F) (Begin 9) (End 11)))))
CLIPS>
(defrule print-availability
(object (is-a PERSON) (Name ?name) (Available $? ?a $?))
(object (is-a AVAILABILITY) (name ?a))
=>
(printout t ?name " " (send ?a get-Weekday)
" " (send ?a get-Begin)
" " (send ?a get-End) crlf)))
CLIPS> (reset)
CLIPS> (run)
Frank F 9 11
Frank M 9 11
CLIPS>

chess: bishop move with CLIPS

I'm trying to implement the possible moves of a bishop on a chess table, which can have other pieces on random cells. I've been able to make a sketch of an answer, but it doesn't detect other pieces.
Previously to this rule I've written some code that creates a fact like the following for each cell of the table, indicating its contents:
(cell-info (coor {i} {j}) (contents {empty|black|white}))
and a fact that shows the position of a piece:
(piece (row {r}) (column {c}) (type {t}) (color {col}))
And here's my rule so far (probably it's also not too efficient):
(defrule bishop-moves
(declare (salience 30))
(piece (row ?rb) (column ?cb) (type bishop) (color black))
(cell-info (coor ?i ?j) (contents empty|white))
=>
(loop-for-count (?n 1 8)
(if (or (and (= ?i (+ ?rb ?n)) (= ?j (+ ?cb ?n)))
(and (= ?i (- ?rb ?n)) (= ?j (- ?cb ?n)))
(and (= ?i (+ ?rb ?n)) (= ?j (- ?cb ?n)))
(and (= ?i (- ?rb ?n)) (= ?j (+ ?cb ?n))))
then (assert (movement-allowed
(destination-cell ?i ?j)
(type bishop)
(start-cell ?rb ?cb))))))
Does anybody now what could I do? Thanks in advance.
;;; Added deftemplates and deffacts
;;; Replaced rule variable ?i with ?r and ?j with ?c.
;;; Made rule applicable for both black or white bishop
;;; Moved diagonal logic from actions of rule to conditions
;;; Added logic to rule for intervening pieces
(deftemplate piece (slot row) (slot column) (slot type) (slot color))
(deftemplate cell-info (multislot coor) (slot contents))
(deftemplate movement-allowed (multislot destination-cell) (slot type) (multislot start-cell))
(deffacts test-data
(piece (row 1) (column 1) (type pawn) (color black))
(cell-info (coor 1 1) (contents black)) ; Invalid - friendly piece
(cell-info (coor 1 2) (contents empty)) ; Invalid - not on diagonal
(cell-info (coor 1 3) (contents empty)) ; Valid
(piece (row 2) (column 2) (type bishop) (color black))
(cell-info (coor 2 2) (contents black)) ; Invalid - friendly piece
(cell-info (coor 2 8) (contents empty)) ; Invalid - not on diagonal
(cell-info (coor 3 1) (contents empty)) ; Valid
(cell-info (coor 3 3) (contents empty)) ; Valid
(cell-info (coor 4 4) (contents empty)) ; Valid
(cell-info (coor 5 5) (contents empty)) ; Valid
(piece (row 6) (column 6) (type pawn) (color white))
(cell-info (coor 6 6) (contents white)) ; Valid
(cell-info (coor 7 7) (contents empty)) ; Invalid - blocked by pawn
(piece (row 8) (column 8) (type pawn) (color white))
(cell-info (coor 8 8) (contents white))) ; Invalid - blocked by pawn
(defrule bishop-moves
(declare (salience 30))
(piece (row ?rb) (column ?cb) (type bishop) (color ?color))
;; The destination cell must be empty or contain
;; an opposing piece
(cell-info (coor ?r ?c) (contents empty | ~?color))
;; If the cell and piece are on the same diagonal, the
;; absolute difference between the two should be the same
(test (= (abs (- ?r ?rb)) (abs (- ?c ?cb))))
;; Check that there is not another piece that is within
;; the rectangle formed by the bishop and the destination
;; cell and is also on the same diagonal as the bishop
(not (and (piece (row ?ro) (column ?co))
(test (and (or (< ?rb ?ro ?r) (< ?r ?ro ?rb))
(or (< ?cb ?co ?c) (< ?c ?co ?cb))))
(test (= (abs (- ?ro ?rb)) (abs (- ?co ?cb))))))
=>
(assert (movement-allowed
(destination-cell ?r ?c)
(type bishop)
(start-cell ?rb ?cb))))