How to automatically add many variables in a loop-for-count in CLIPS? - clips

I want to use a loop-for-count to loop many different variables to let user input and let CLIPS read the variables.
For example:
Question: "How many dependent you wish to add?"
Answer: 5.
Then the CLIPS should create the variables like:
name1
name2
name3
name4
name5
Here is my code:
(printout t "How many dependent you wish to add? (Must have atleast 1): ")
(bind ?DepNo (read))
(assert (DepNo ?DepNo))
(loop-for-count (?DepNo 1 ?DepNo) do
(printout t "Name: ")
(bind $?DepName (explode$ (readline)))
(assert (DepName $?DepName))
)

Create a multifield value to hold all of the dependent names:
CLIPS (6.31 6/12/19)
CLIPS>
(defrule get-dependents
=>
(printout t "How many dependent you wish to add? (Must have at least 1): ")
(bind ?DepNo (read))
(bind ?depNames (create$))
(loop-for-count ?DepNo
(printout t "Name: ")
(bind ?depNames (create$ ?depNames (readline))))
(assert (DepNames ?depNames)))
CLIPS>
(defrule print-names
(DepNames $?depNames)
=>
(printout t "Dependents are: ")
(foreach ?d ?depNames
(printout t " " ?d crlf)))
CLIPS> (reset)
CLIPS> (run)
How many dependent you wish to add? (Must have at least 1): 3
Name: Sally Jones
Name: Fred Jones
Name: David Jones
Dependents are:
Sally Jones
Fred Jones
David Jones
CLIPS> (facts)
f-0 (initial-fact)
f-1 (DepNames "Sally Jones" "Fred Jones" "David Jones")
For a total of 2 facts.
CLIPS>

Related

How to use user input using CLIPS

I am a beginner in CLIPS and cannot figure out how to get the above code to work right despite spending hours on it. Any help would be appreciated.Thank you.
(deftemplate gem
(players <number_robots>)
(Goal_posts <number_goal_posts>)
(Field <dimension>)
(players goalkeeper <number_goalkeepers> <goalkeeper_linear_speed> <goalkeeper_angular_speed> {static, running})
(players defenders <number_defenders> <defender_linear_speed> <defender_angular_speed> {static, running})
(players midfielder <number_midfielders> <midfielder_linear_speed> <midfielder_angular_speed> {static, running})
(players striker <number_strikers> <striker_linear_speed> <striker_angular_speed> {static, running})
(ball <poz_x> <poz_y)
(oponents <nume> <poz_oponents_x> <poz_oponents_y>))
(deffacts initial-state
(player goalkeeper 1 10 6 static)
(player defenders number_defenders 15 10 running)
(player midfielders number_midfielders 17 12 running)
(player strikers number_strikers 9 10 running)
(ball 5 5)
(oponents Robot1 1 2)
(oponents Robot2 2 4)
(oponents Robot3 7 2)
(oponents Robot4 10 20)
(oponents Robot5 11 8)
(oponents Robot6 20 10)
(oponents Robot7 5 9)
)
;The number of robots per team must be variable and the user has to be able to set or adjust it.
(defrule number_of_robots
=>
(printout t "Type the number of robots per team"
crlf)
(assert (number_robots (read)))
(printout t "Type the number of goal posts" crlf)
(assert (number_goal_posts (read))))
(defrule check-input
?number_robots <-
(number ?number_robots)
(test (integerp ?number_robots))
=>
(retract ?number_robots)
(printout t "Correct number of robots" crlf))
(defrule check-input1
?number_goal_posts <-
(number ?number_goal_posts)
(test (integerp ?number_goal_posts))
=>
(retract ?number_goal_posts)
(printout t "Correct number of goal posts" crlf))
;The user will initially input data on the dimension of the fotball field and goal post.
(defrule dimension_field
=>
(printout t "Type the football field dimension" crlf)
(assert (dimension (read))))
(defrule check-input1
?dimension <-
(number ?dimension)
(test (integerp ?dimension))
=>
(retract ?dimension)
(printout t "Correct dimension of footbal field" crlf))
;Each team must have a goalkeeper, while the number of defenders, midfielders and strikers is to be set by the user to match the stated number of players
(defrule reading-input
=>
printout t "Type the number of defenders" crlf
(assert (number_defenders(read)))
printout t "Type the number of midfielders" crlf
(assert (number_midfielders(read)))
printout t "Type the number of strikers" crlf
(assert (number_strikers(read)))
)
(defrule check-input2
?number_defenders <-
(number ?number_defenders)
(test (integerp ?number_defenders))
=>
(retract ?number_defenders)
(printout t "Correct number of defenders " crlf))
(defrule check-input3
?number_midfielders <-
(number ?number_midfielders)
(test (integerp ?number_midfielders))
=>
(retract ?number_midfielders)
(printout t "Correct number of midfielders " crlf))
(defrule check-input4
?number_strikers <-
(number ?number_strikers)
(test (integerp ?number_strikers))
=>
(retract ?number_strikers)
(printout t "Correct number of strikers " crlf))
)
My errors after running the code are:
[PRNTUTIL2] Syntax Error: Check appropriate syntax for deftemplate.
ERROR:
(deftemplate MAIN::gem
(players
[CSTRCPSR1] WARNING: Redefining deffacts: initial-state
[CSTRCPSR1] WARNING: Redefining defrule: number_of_robots +j Defining
defrule: check-input =j+j
[CSTRCPSR1] WARNING: Redefining defrule: check-input1 =j+j
[CSTRCPSR1] WARNING: Redefining defrule: dimension_field +j
[CSTRCPSR1] WARNING: Redefining defrule: check-input1 =j+j
[CSTRCPSR1] WARNING: Redefining defrule: reading-input +j
[CSTRCPSR1] WARNING: Redefining defrule: check-input2 =j+j
[CSTRCPSR1] WARNING: Redefining defrule: check-input3 =j+j
[CSTRCPSR1] WARNING: Redefining defrule: check-input4 =j+j
[CSTRCPSR1] Expected the beginning of a construct.
CLIPS>
(defrule number_of_robots
=>
(printout t "Type the number of robots per team: ")
(assert (number_robots (read)))
(printout t "Type the number of goal posts: ")
(assert (number_goal_posts (read))))
CLIPS>
(defrule check-robots
?number <- (number_robots ?number_robots)
(test (not (integerp ?number_robots)))
=>
(retract ?number)
(printout t "Correct number of robots." crlf))
CLIPS>
(defrule check-goal-posts
?number <- (number_goal_posts ?number_goal_posts)
(test (not (integerp ?number_goal_posts)))
=>
(retract ?number)
(printout t "Correct number of goal posts." crlf))
CLIPS>
(defrule dimension_field
=>
(printout t "Type the football field dimension: ")
(assert (dimension (read))))
CLIPS>
(defrule check-dimension
?dim <- (dimension ?dimension)
(test (not (integerp ?dimension)))
=>
(retract ?dim)
(printout t "Correct dimension of football field." crlf))
CLIPS>
(defrule reading-input
=>
(printout t "Type the number of defenders: ")
(assert (number_defenders (read)))
(printout t "Type the number of midfielders: ")
(assert (number_midfielders (read)))
(printout t "Type the number of strikers: ")
(assert (number_strikers (read))))
CLIPS>
(defrule check-defenders
?number <- (number_defenders ?number_defenders)
(test (not (integerp ?number_defenders)))
=>
(retract ?number)
(printout t "Correct number of defenders." crlf))
CLIPS>
(defrule check-midfielders
?number <- (number_midfielders ?number_midfielders)
(test (not (integerp ?number_midfielders)))
=>
(retract ?number)
(printout t "Correct number of midfielders." crlf))
CLIPS>
(defrule check-strikers
?number <- (number_strikers ?number_strikers)
(test (not (integerp ?number_strikers)))
=>
(retract ?number)
(printout t "Correct number of strikers." crlf))
CLIPS> (reset)
CLIPS> (run)
Type the number of robots per team: 1
Type the number of goal posts: 2
Type the football field dimension: 3
Type the number of defenders: 4
Type the number of midfielders: 5
Type the number of strikers: 6
CLIPS> (reset)
CLIPS> (run)
Type the number of robots per team: a
Type the number of goal posts: b
Correct number of goal posts.
Correct number of robots.
Type the football field dimension: c
Correct dimension of football field.
Type the number of defenders: d
Type the number of midfielders: e
Type the number of strikers: f
Correct number of strikers.
Correct number of midfielders.
Correct number of defenders.
CLIPS>

Is there a way to define CLIPS rules in order to search text?

I'm trying to define some rules with CLIPS for searching pieces of text in paragraphs or documents (e.g. filter the words that contain the letter 'a' or search for words that appear more than once), but I cannot find any example. Where can I find some examples for my problem?
Within your rule patterns you'd place constraints either on multiple words from your paragraph (such as to see if the same words appears more than once):
CLIPS>
(deftemplate paragraph
(multislot words))
CLIPS>
(defrule more-than-once
(paragraph (words $? ?w $? ?w $?))
=>
(assert (more-than-once ?w)))
CLIPS>
(defrule print-more-than-once
(more-than-once ?w)
=>
(printout t "'" ?w "' appears more than once." crlf))
CLIPS>
(assert (paragraph (words the quick brown fox jumped over the lazy dogs)))
<Fact-1>
CLIPS> (run)
'the' appears more than once.
CLIPS>
Or you'd place them on a single word:
CLIPS>
(defrule contains-e
(paragraph (words $? ?w&:(str-index "e" ?w) $?))
=>
(assert (contains ?w e)))
CLIPS>
(defrule print-contains
(contains ?w ?l)
=>
(printout t "'" ?l "' is contained in '" ?w "'." crlf))
CLIPS> (run)
'e' is contained in 'the'.
'e' is contained in 'jumped'.
'e' is contained in 'over'.
CLIPS>

How to compare symbols between 2 multifield-variable in CLIPS

The problem is to compare between two multifield-variable of type SYMBOL.
Here an example of the code I try to develop.
CLIPS>(defrule r
=>
(printout t "Input A: ")
(bind $?A (explode$ (readline)))
(printout t "Input B: ")
(bind $?B (explode$ (readline)))
(if (member$ $?A $?B) then (printout t " Something ..." crlf)))
CLIPS> (run)
Input A: 1 2 3 4 5
Input B: 7 3 2 1 6
CLIPS>
I want to compare each argument (or value) of $?A with each argument of $?B and if at least one argument of both is in the $?A or $?B, the if test becomes TRUE.
You can write a function to test for the intersection of two multifield values:
CLIPS>
(deffunction intersectionp (?m1 ?m2)
(foreach ?i1 ?m1
(foreach ?i2 ?m2
(if (eq ?i1 ?i2)
then (return TRUE))))
(return FALSE))
CLIPS>
(defrule r
=>
(printout t "Input A: ")
(bind ?A (explode$ (readline)))
(printout t "Input B: ")
(bind ?B (explode$ (readline)))
(if (intersectionp ?A ?B) then (printout t " Something ..." crlf)))
CLIPS> (run)
Input A: 1 2 3 4 5
Input B: 7 3 2 1 6
Something ...
CLIPS> (reset)
CLIPS> (run)
Input A: 1 2 3
Input B: 4 5 6
CLIPS>
Alternately you can use pattern matching to test for an intersection:
CLIPS> (clear)
CLIPS>
(defrule r
=>
(printout t "Input A: ")
(bind ?A (explode$ (readline)))
(assert (A ?A))
(printout t "Input B: ")
(bind ?B (explode$ (readline)))
(assert (B ?B)))
CLIPS>
(defrule intersect
(exists (A $? ?v $?)
(B $? ?v $?))
=>
(printout t " Something ..." crlf))
CLIPS> (reset)
CLIPS> (run)
Input A: 1 2 3 4 5
Input B: 7 3 2 1 6
Something ...
CLIPS> (reset)
CLIPS> (run)
Input A: 1 2 3
Input B: 4 5 6
CLIPS>

CLIPS Validate Text Entry

Morning, Excuse the silly question but I am busy building a expert system much like the "21 Questions" game that uses questions asked to the user in order to determine the right dog for them. The expert system is coded in CLIPS / .CPS language and one of the requirements I am looking to include is that when the user is asked a yes/no question they are required to input "y" or "n".
In all the resources we have been taught we have only been tough number validation and not a specific character validation and I cannot find any resources that do this either.
This is an example of the number validation I did in order to ensure they input a valid number on one of my questions
(defrule test-integer
(number-in ?number&:(integerp ?number))
=>
(printout t ?number "is valid"
(defrule test-non-int
?number-address <- (number-in ?number&:(not (integerp ?number)))
=>
(printout t ?number " not valid int" crlf)
(retract ?number-address))
This is how you'd do it using rules:
CLIPS>
(defrule test-response
(response-in ?response&y|n)
=>
(printout t ?response " is valid" crlf))
CLIPS>
(defrule test-non-response
?response-address <- (response-in ?response&~y&~n)
=>
(printout t ?response " not valid response" crlf)
(retract ?response-address))
CLIPS> (assert (response-in xyz))
<Fact-1>
CLIPS> (run)
xyz not valid response
CLIPS> (assert (response-in n))
<Fact-2>
CLIPS> (run)
n is valid
CLIPS>
I'd suggest using a function that only accepts correct responses:
CLIPS>
(deffunction ask-question (?question $?allowed-values)
(printout t ?question)
(bind ?answer (read))
(if (lexemep ?answer)
then (bind ?answer (lowcase ?answer)))
(while (not (member ?answer ?allowed-values)) do
(printout t ?question)
(bind ?answer (read))
(if (lexemep ?answer)
then (bind ?answer (lowcase ?answer))))
?answer)
CLIPS> (ask-question "Continue? " y n yes no)
Continue? k
Continue? l
Continue? ye
Continue? YeS
yes
CLIPS>
What i figured out was to link the answer from the one defrule to that of another defrule first to check if the answer was valid and then again if that answer was valid to link it to the correct defrule then that will proceed with the next question.
Code is from my own Expert System:
(defrule Small-CoatType-Full
(Small-Coat f)
(person (name ?name))
=>
(open "result.txt" result "a")
(printout result ?name " Likes Smaller, Fury Dogs" crlf)
(close result)
(printout t "Would you like a low energetic(l) or high energetic(h) breed?" crlf)
(assert (Small-Energy-Level(lowcase(read)))))
(defrule Small-Energy-Level-Wrong
(Small-Energy-Level ?var &~l&~h)
=>
(printout t crlf "Plesae Only Choose (l) or (h)")
(assert (Small-Energy-Level (lowcase(read)))))`

Obtain ID of fact I just asserted

Is there a way for me to get the fact ID of a fact that I just asserted in the RHS of a rule? Something along the lines of
?f <- (assert (new-fact))
CLIPS>
(defrule example
=>
(bind ?f (assert (new-fact)))
(bind ?i (fact-index ?f))
(printout t "The fact index is " ?i crlf))
CLIPS> (reset)
CLIPS> (run)
The fact index is 1
CLIPS> (facts)
f-0 (initial-fact)
f-1 (new-fact)
For a total of 2 facts.
CLIPS>

Resources