How should I write this rule in CLIPS? - clips

Please, help me create the rules in CLIPS to resolve this tasks:
The goalkeeper has to move on the goal post line in that position where it can block the trajectory of the ball.
The defenders have to move so that to block the ball in its trajectory towards goal or to block the trajectory of an opponent player that moves towards the goal post that must be defended.
(deftemplate temp
(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)
)

First, create a pseudo rule to implement:
If the player position slot is goalkeeper and
the player x slot is not the same as the ball x slot
Then
modify the player x slot to the value of the ball x slot
Next, define the data structures needed to retrieve the slot values referenced by your pseudo rule:
CLIPS (6.4 2/9/21)
CLIPS>
(deftemplate ball
(slot x)
(slot y))
CLIPS>
(deftemplate player
(slot position)
(slot x)
(slot y))
CLIPS>
Then convert your pseudo rule to CLIPS syntax:
CLIPS>
(defrule move-goalkeeper
?p <- (player (position goalkeeper)
(x ?px))
(ball (x ?bx&~?px))
=>
(modify ?p (x ?bx)))
CLIPS>
Finally, test the rule to see that it works:
CLIPS> (assert (ball (x 3) (y 5)))
<Fact-1>
CLIPS> (assert (player (position goalkeeper) (x 4) (y 3)))
<Fact-2>
CLIPS> (agenda)
0 move-goalkeeper: f-2,f-1
For a total of 1 activation.
CLIPS> (run)
CLIPS> (facts)
f-1 (ball (x 3) (y 5))
f-2 (player (position goalkeeper) (x 3) (y 3))
For a total of 2 facts.
CLIPS>

Related

CLIPS: counting different products

I have some facts in the form of a list: (list day1 apple milk bread) (list day 2 bread milk) and I would like to count the different products in that facts for each day. How can I count them?
The result that I want is (list day1 3) (list day2 2)
CLIPS (6.4 2/9/21)
CLIPS>
(defrule list-count
(list ?day $?items)
=>
(assert (count ?day (length$ ?items))))
CLIPS>
(assert (list day1 apple milk bread)
(list day2 bread milk))
<Fact-2>
CLIPS> (agenda)
0 list-count: f-2
0 list-count: f-1
For a total of 2 activations.
CLIPS> (run)
CLIPS> (facts)
f-1 (list day1 apple milk bread)
f-2 (list day2 bread milk)
f-3 (count day2 2)
f-4 (count day1 3)
For a total of 4 facts.
CLIPS>

How can I get the sum of items in a multislot

I have a template like the one shown bellow. How can I get the sum of items in the multislot grades?
(deftemplate student
(multislot name)
(multislot grades)
)
Here's one way to do it. In the reg6 rule, the + function is given two arguments of 0 in addition to the grades to insure that the + function allows has at least 2 arguments; otherwise, if there were zero or one grades for the student you'd get an error.
CLIPS (6.31 2/3/18)
CLIPS>
(deftemplate student
(multislot name)
(multislot grades))
CLIPS>
(deftemplate sum
(multislot name)
(slot grade))
CLIPS>
(defrule reg6
(student (name $?name)
(grades $?grades))
=>
(assert (sum (name ?name)
(grade (+ 0 0 (expand$ ?grades))))))
CLIPS>
(assert (student (name David Green) (grades))
(student (name Sue Brown) (grades 90))
(student (name Frank Black) (grades 85 75)))
<Fact-3>
CLIPS> (run)
CLIPS> (facts)
f-0 (initial-fact)
f-1 (student (name David Green) (grades))
f-2 (student (name Sue Brown) (grades 90))
f-3 (student (name Frank Black) (grades 85 75))
f-4 (sum (name Frank Black) (grade 160))
f-5 (sum (name Sue Brown) (grade 90))
f-6 (sum (name David Green) (grade 0))
For a total of 7 facts.
CLIPS>
You can use the expand$ function. Check in the Basic Programming Guide the Multifield Expansion Function chapter to know more.
(deftemplate student
(multislot name)
(multislot grades))
(defrule grades-sum
(student (grades $?grades))
=>
(printout t "Student grades sum is " (+ (expand$ ?grades))))
(assert (student (grades (create$ 1 2 3 4 5))))
(student (name) (grades 1 2 3 4 5))
(run)
Student grades sum is 15

defrule never makes it in the agenda | CLIPS

I want to build an expert system in which in a case of emergency at a building with some floors (it needs to work for any amount of floors) the elevator should take the people into the ground.
The thing is, that the defrule to send the elevator at any floor never makes it in the agenda, so the system just does nothing. The correct action should be to fire the rule and then another rule that takes the people from the floor.
The code for the defrule is this:
(defrule move_to_floor "elevator moves to any floor "
?i <- (elevator is_at floor ?x has ?y adults and ?z minors)
(floor ?fl&~?x has ?n adult and ?m minor people)
(test (> (+ ?n ?m) 0))
=>
(retract ?i)
(assert (elevator is_at floor ?fl has ?y adults and ?z minors))
)
The facts as they have been initialized from the user in another defrule above are these:
f-0 (initial-fact)
f-1 (elevator is_at 0 has 0 adults and 0 minors)
f-3 (capacity 4)
f-4 (floors 3)
f-5 (initCanEnter 0) ;At 0 this prevents from entering the init_defrule again
f-6 (floor 3 has 2 adult and 1 minor people)
f-7 (floor 2 has 4 adult and 5 minor people)
f-8 (floor 1 has 1 adult and 2 minor people)
I can't seem to find the solution. Also, I'm using deffacts and not deftemplate as I have seen many people using on the internet.
You can use the matches command to see which patterns in a rule are matched.
CLIPS (6.31 2/3/18)
CLIPS>
(defrule move_to_floor "elevator moves to any floor "
?i <- (elevator is_at floor ?x has ?y adults and ?z minors)
(floor ?fl&~?x has ?n adult and ?m minor people)
(test (> (+ ?n ?m) 0))
=>
(retract ?i)
(assert (elevator is_at floor ?fl has ?y adults and ?z minors)))
CLIPS>
(deffacts initial
(elevator is_at 0 has 0 adults and 0 minors)
(capacity 4)
(floors 3)
(initCanEnter 0) ;At 0 this prevents from entering the init_defrule again
(floor 3 has 2 adult and 1 minor people)
(floor 2 has 4 adult and 5 minor people)
(floor 1 has 1 adult and 2 minor people))
CLIPS> (reset)
CLIPS> (matches move_to_floor)
Matches for Pattern 1
None
Matches for Pattern 2
f-5
f-6
f-7
Partial matches for CEs 1 - 2
None
Activations
None
(3 0 0)
CLIPS>
In this case, the first pattern is not matched. That's because your pattern expects is_at floor ?x but your fact contains is_at 0 (the symbol floor is missing in your fact). If you correct this issue, the rule will be placed on the agenda.
CLIPS>
(deffacts initial
(elevator is_at floor 0 has 0 adults and 0 minors)
(capacity 4)
(floors 3)
(initCanEnter 0) ;At 0 this prevents from entering the init_defrule again
(floor 3 has 2 adult and 1 minor people)
(floor 2 has 4 adult and 5 minor people)
(floor 1 has 1 adult and 2 minor people))
CLIPS> (reset)
CLIPS> (agenda)
0 move_to_floor: f-1,f-7
0 move_to_floor: f-1,f-6
0 move_to_floor: f-1,f-5
For a total of 3 activations.
CLIPS>
If you issue a (run) command at this point, the rules will endlessly fire in a loop moving from floor to floor, so that's something you'll need to address next.
If you use deftemplate facts rather than ordered facts, you'll get an error if you misspell slot names, so it's better to use these if you have a fact with multiple attributes.
CLIPS> (clear)
CLIPS>
(deftemplate elevator
(slot at_floor (type INTEGER))
(slot adults (type INTEGER))
(slot minors (type INTEGER)))
CLIPS>
(deftemplate floor
(slot # (type INTEGER))
(slot adults (type INTEGER))
(slot minors (type INTEGER)))
CLIPS>
(deffacts initial
(elevator (at_floor 0))
(capacity 4)
(floors 3)
(initCanEnter 0)
(floor (# 3) (adults 2) (minors 1))
(floor (# 2) (adults 4) (minors 5))
(floor (# 1) (adults 1) (minors 2)))
CLIPS>
(defrule move_to_floor
?i <- (elevator (at_floor ?x))
(floor (# ?fl&~?x) (adults ?n) (minors ?m))
(test (> (+ ?n ?m) 0))
=>
(modify ?i (at_floor ?fl)))
CLIPS> (reset)
CLIPS> (facts)
f-0 (initial-fact)
f-1 (elevator (at_floor 0) (adults 0) (minors 0))
f-2 (capacity 4)
f-3 (floors 3)
f-4 (initCanEnter 0)
f-5 (floor (# 3) (adults 2) (minors 1))
f-6 (floor (# 2) (adults 4) (minors 5))
f-7 (floor (# 1) (adults 1) (minors 2))
For a total of 8 facts.
CLIPS> (agenda)
0 move_to_floor: f-1,f-7
0 move_to_floor: f-1,f-6
0 move_to_floor: f-1,f-5
For a total of 3 activations.
CLIPS>

How to printout all matches facts in a rule

I have a rule like below and I want to print all facts(here objct) that are compatible to this rule. I have a fact objct and there are some of these "objct"s that follow the rule. how I can do it? The printout below just prints the latest objct that player got. However I want to printout all of them. Any idea?
(defrule have_objcts
?input <- (input have|possession)
(objct (name ?n) (location player) (used 0))
=>
;WHAT SHOULD I WRITE HERE TO PRINTOUT those OBJCT's BELONG TO
PALYER???????????
(printout t crlf ?n)
(retract ?input))
Use the matches command:
CLIPS>
(deftemplate objct
(slot name)
(slot location)
(slot used))
CLIPS>
(deffacts initial
(objct (name x) (location player) (used 0))
(objct (name y) (location elsewhere) (used 1))
(objct (name z) (location player) (used 0))
(input have)
(input want)
(input possession)
(input thing))
CLIPS>
(defrule have_objcts
?input <- (input have|possession)
(objct (name ?n) (location player) (used 0))
=>
(retract ?input))
CLIPS> (reset)
CLIPS> (matches have_objcts)
Matches for Pattern 1
f-4
f-6
Matches for Pattern 2
f-1
f-3
Partial matches for CEs 1 - 2
f-6,f-3
f-6,f-1
f-4,f-3
f-4,f-1
Activations
f-6,f-3
f-6,f-1
f-4,f-3
f-4,f-1
(4 4 4)
CLIPS> (run)
CLIPS> (matches have_objcts)
Matches for Pattern 1
None
Matches for Pattern 2
f-1
f-3
Partial matches for CEs 1 - 2
None
Activations
None
(2 0 0)
CLIPS>

CLIPS defrules compare the value of two variables

I want to write a rule that says the following
if x > y => assert x
where x and y are variables and their values are given as facts.
How do I do it?
If x already exists as a fact, then asserting it again from the actions of the rule would be unnecessary, but if you want to assert a fact indicating that x is greater than y then you could do it this way:
CLIPS>
(defrule greater-than
(x ?x)
(y ?y)
(test (> ?x ?y))
=>
(assert (x-is-greater-than-y)))
CLIPS> (assert (x 4))
<Fact-1>
CLIPS> (assert (y 1))
<Fact-2>
CLIPS> (agenda)
0 greater-than: f-1,f-2
For a total of 1 activation.
CLIPS> (run)
CLIPS> (facts)
f-0 (initial-fact)
f-1 (x 4)
f-2 (y 1)
f-3 (x-is-greater-than-y)
For a total of 4 facts.
CLIPS>

Resources