Get facts and print parameters in CLIPS - rules

I would like to print all the datas of the facts with a rule. Here are the facts :
(deffacts datas
(pile name 1 blocks A B C A B)
(pile name 2 blocks B A)
(pile name 3 blocks A B)
(pile name 4 blocks A))
And here are the printing I want to see :
pile 1 : A B C A B
pile 2 : B A
pile 3 : A B
pile 4 : A
Does somebody has an idea how to do it ?
Thank you for your help !

If the order in which the piles are printed doesn't matter, you can do it this way:
CLIPS> (clear)
CLIPS>
(deffacts datas
(pile name 1 blocks A B C A B)
(pile name 2 blocks B A)
(pile name 3 blocks A B)
(pile name 4 blocks A))
CLIPS>
(defrule print
(pile name ?name blocks $?blocks)
=>
(printout t pile " " ?name " : " (implode$ ?blocks) crlf))
CLIPS> (reset)
CLIPS> (run)
pile 4 : A
pile 3 : A B
pile 2 : B A
pile 1 : A B C A B
CLIPS> (clear)
CLIPS>
(deftemplate pile
(slot name)
(multislot blocks))
CLIPS>
(deffacts datas
(pile (name 1) (blocks A B C A B))
(pile (name 2) (blocks B A))
(pile (name 3) (blocks A B))
(pile (name 4) (blocks A)))
CLIPS>
(defrule print
(pile (name ?name) (blocks $?blocks))
=>
(printout t pile " " ?name " : " (implode$ ?blocks) crlf))
CLIPS> (reset)
CLIPS> (run)
pile 4 : A
pile 3 : A B
pile 2 : B A
pile 1 : A B C A B
CLIPS>
If the order is important, you can do it using facts in the following manners, but this is either destructive in the first case or requires cleanup in the second case:
CLIPS> (clear)
CLIPS>
(deftemplate pile
(slot name)
(multislot blocks))
CLIPS>
(deffacts datas
(pile (name 1) (blocks A B C A B))
(pile (name 2) (blocks B A))
(pile (name 3) (blocks A B))
(pile (name 4) (blocks A)))
CLIPS>
(defrule print
?pile <- (pile (name ?name) (blocks $?blocks))
(not (pile (name ?name2&:(< ?name2 ?name))))
=>
(retract ?pile)
(printout t pile " " ?name " : " (implode$ ?blocks) crlf))
CLIPS> (reset)
CLIPS> (run)
pile 1 : A B C A B
pile 2 : B A
pile 3 : A B
pile 4 : A
CLIPS> (facts)
f-0 (initial-fact)
For a total of 1 fact.
CLIPS> (clear)
CLIPS>
(deftemplate pile
(slot name)
(multislot blocks))
CLIPS>
(deffacts datas
(pile (name 1) (blocks A B C A B))
(pile (name 2) (blocks B A))
(pile (name 3) (blocks A B))
(pile (name 4) (blocks A)))
CLIPS>
(defrule print
(pile (name ?name) (blocks $?blocks))
(not (and (pile (name ?name2&:(< ?name2 ?name)))
(not (pile-printed ?name2))))
=>
(assert (pile-printed ?name))
(printout t pile " " ?name " : " (implode$ ?blocks) crlf))
CLIPS> (reset)
CLIPS> (run)
pile 1 : A B C A B
pile 2 : B A
pile 3 : A B
pile 4 : A
CLIPS> (facts)
f-0 (initial-fact)
f-1 (pile (name 1) (blocks A B C A B))
f-2 (pile (name 2) (blocks B A))
f-3 (pile (name 3) (blocks A B))
f-4 (pile (name 4) (blocks A))
f-5 (pile-printed 1)
f-6 (pile-printed 2)
f-7 (pile-printed 3)
f-8 (pile-printed 4)
For a total of 9 facts.
CLIPS>
Finally, you can use the fact query functions to retrieve all the piles facts and then sort them to get the desired order:
CLIPS> (clear)
CLIPS>
(deffunction pile-sort (?f1 ?f2)
(> (fact-slot-value ?f1 name)
(fact-slot-value ?f2 name)))
CLIPS>
(deftemplate pile
(slot name)
(multislot blocks))
CLIPS>
(deffacts datas
(pile (name 1) (blocks A B C A B))
(pile (name 2) (blocks B A))
(pile (name 3) (blocks A B))
(pile (name 4) (blocks A)))
CLIPS>
(defrule print
=>
(bind ?facts (find-all-facts ((?f pile)) TRUE))
(bind ?facts (sort pile-sort ?facts))
(progn$ (?f ?facts)
(printout t pile " " (fact-slot-value ?f name) " : "
(implode$ (fact-slot-value ?f blocks)) crlf)))
CLIPS> (reset)
CLIPS> (run)
pile 1 : A B C A B
pile 2 : B A
pile 3 : A B
pile 4 : A
CLIPS>

Related

clips - same slot in pattern and action

When we are defining a rule , can we have same slot names in the in the pattern and in the action area ( where assert is) ? I'm giving example with code below :
(deftemplate b1
(slot s1)
(slot s2))
(deftemplate b2
(slot s1)
(slot s2))
(deftemplate b3
(slot r1)
(slot r2))
(deftemplate b4
(slot r1)
(slot r2))
; Facts
(deffacts F
(b1 (s1 2)(s2 5))
(b2 (s1 7)(s2 9)))
; Rules
(defrule R1
(b1 (s1 ?x1)(s2 ?y1))
(b2 (s1 ?x2)(s2 ?y2))
=>
(assert (b4(r1 (* ?x1 ?x2))(r2 (* ?y1 ?y2))))
(printout t)
)
(defrule R2
(b2 (s1 ?x1)(s2 ?y1))
(b3 (r1 ?x2)(r2 ?y2))
=>
(assert (b3(r1 (* ?x1 ?x2))(r2 (* ?y1 ?y2))))
(printout s)
)
The situation I described is located in the R2 rule of the code . When I run the program , I see that only rule R1 is executed . is this because of this line ?
(b3 (r1 ?x2)(r2 ?y2))
=>
(assert (b3(r1 (* ?x1 ?x2))(r2 (* ?y1 ?y2))))
because we have r1 used two times , like I said before .
Rule R2 will execute only if both a b2 and a b3 fact exist. The assertion of a b3 fact from the actions of rule R2 will only happen if the rule is activated by a different b3 fact. Using the same slot in both the conditions and actions of a rule does not prevent the activation of that rule.

asserting string in clips

I am trying to assert the value of name into a variable but when i assert it the value is coming in quotes and also with an extra space at the end.
(defrule discount_amt_group
(exists (Student (age 14)(marks ?q&:(> ?q 40))))
=>
(bind ?name "")
(do-for-all-facts ((?p Student))
(or (eq ?p:marks 80)
(eq ?p:marks 75)
(eq ?p:marks 90))
(bind ?name (str-cat ?name ?p:name " "))
(bind ?totalMarks (+ ?totalMarks ?p:marks)))
(assert (StudOut(names ?name)))
the expected value will be (name Harry Ron Ginger) but now its coming as (name "Harry Ron Ginger ")
please suggest.
Represent the names as a multifield value rather than a string. You can use the create$ function to initially create an empty multifield value and then again to append values to it.
CLIPS (6.31 6/12/19)
CLIPS>
(deftemplate Student
(slot name)
(slot age)
(slot marks))
CLIPS>
(deftemplate StudOut
(multislot names)
(slot totalMarks))
CLIPS>
(deffacts Students
(Student (name Harry) (age 14) (marks 80))
(Student (name Ron) (age 15) (marks 75))
(Student (name Ginger) (age 14) (marks 90))
(Student (name Sally) (age 12) (marks 95)))
CLIPS>
(defrule discount_amt_group
(exists (Student (age 14)(marks ?q&:(> ?q 40))))
=>
(bind ?name (create$))
(bind ?totalMarks 0)
(do-for-all-facts ((?p Student))
(or (eq ?p:marks 80)
(eq ?p:marks 75)
(eq ?p:marks 90))
(bind ?name (create$ ?name ?p:name))
(bind ?totalMarks (+ ?totalMarks ?p:marks)))
(assert (StudOut (names ?name)
(totalMarks ?totalMarks))))
CLIPS> (reset)
CLIPS> (run)
CLIPS> (facts)
f-0 (initial-fact)
f-1 (Student (name Harry) (age 14) (marks 80))
f-2 (Student (name Ron) (age 15) (marks 75))
f-3 (Student (name Ginger) (age 14) (marks 90))
f-4 (Student (name Sally) (age 12) (marks 95))
f-5 (StudOut (names Harry Ron Ginger) (totalMarks 245))
For a total of 6 facts.
CLIPS>

storing values in clips into variable

I am having a template of
(deftemplate Product
(slot productId (type INTEGER))
(slot uom (default EA))
(slot quantity (type INTEGER))
(slot amount))
I'm using the code for
(defrule sum_of_quantity
(exists (Product (productId 1 | 2 | 3)(amount ?amount)))
=>
(bind ?totalQuantity 0)
(do-for-all-facts ((?p Product))
(or (eq ?p:productNumber 1)
(eq ?p:productNumber 2)
(eq ?p:productNumber 3))
(bind ?totalQuantity (+ ?totalQuantity ?p:quantity)))
(if (>= ?amount 5000) then
(printout t "TotalQuantity is " ?totalQuantity crlf)))
Here i am getting an error saying that:
Undefined variable amount referenced in RHS of defrule.
I have to check if the amount of each product is greater than 5000. How do we do that.
A simple fact pattern that can be matched by several different facts can cause multiple activations of a rule:
CLIPS>
(deftemplate product
(slot id)
(slot amount))
CLIPS>
(deffacts products
(product (id 1) (amount 1000))
(product (id 2) (amount 3000))
(product (id 3) (amount 6000)))
CLIPS>
(defrule print-amount
(product (id ?id) (amount ?amount))
=>
(printout t ?id ": " ?amount crlf))
CLIPS> (reset)
CLIPS> (agenda)
0 print-amount: f-3
0 print-amount: f-2
0 print-amount: f-1
For a total of 3 activations.
CLIPS> (run)
3: 6000
2: 3000
1: 1000
CLIPS>
When each activation is allowed to executed, the variable amount is retrieved from the product fact associated with activation. So there are three rule firings where amount is 6000, 3000, and 1000 respectively.
An exists conditional element is matched just once regardless of the number of time the fact patterns it contains are matched:
CLIPS>
(defrule exists
(exists (product (id ?id) (amount ?amount)))
=>)
CLIPS> (agenda)
0 exists: *
For a total of 1 activation.
CLIPS>
When the agenda is listed, an * is displayed indicating that the pattern is matched, but not by a specific fact. If you tried accessing the variable amount in the actions of the rule, you'd get an error. This is because the variable amount has no meaning outside of the pattern because it has no specific value. You'd get unpredictable behavior if one of the facts matching the fact pattern was arbitrarily chosen to provide the value for amount.
The simplest way to rewrite your rule is to move the amount check from the actions of the rule to the exists pattern:
(defrule sum_of_quantity
(exists (Product (productId 1 | 2 | 3)
(amount ?amount&:(>= ?amount 5000))))
=>
(bind ?totalQuantity 0)
(do-for-all-facts ((?p Product))
(or (eq ?p:productId 1)
(eq ?p:productId 2)
(eq ?p:productId 3))
(bind ?totalQuantity (+ ?totalQuantity ?p:quantity)))
(printout t "TotalQuantity is " ?totalQuantity crlf))
Your do-for-all-facts query was also referencing productNumber rather than productId.

CLIPS Error: Illegal use of the module specifier when defrule

I want to define some module-rules to assert module-facts, and then batch get a group of facts list by get-fact-list, but an error occurred!
CLIPS (6.31 6/12/19)
CLIPS> (defmodule M)
CLIPS> (deftemplate M::T (slot k1))
CLIPS> (defrule M::T (testvalue 1) => (assert (M::T (k1 "v1"))))
[MODULDEF1] Illegal use of the module specifier.
ERROR:
(defrule M::T
(testvalue 1)
=>
(assert (M::T
CLIPS>
expected:
CLIPS> (defmodule M)
CLIPS> (deftemplate M::T (slot k1))
CLIPS> (defrule M::T (testvalue 1) => (assert (M::T (k1 "v1"))))
CLIPS> (assert (testvalue 1))
CLIPS> (get-fact-list M)
;; return the facts that M::rulexx assert
Why is the sytax error? How can I do it for the defrule of module?
Don't use M::T in your assert command. Since the defrule is contained in module M, all deftemplates visible to M can be referenced without using a module specifier.
CLIPS (6.31 6/12/19)
CLIPS> (defmodule M)
CLIPS> (deftemplate M::T (slot k1))
CLIPS> (defrule M::T (testvalue 1) => (assert (T (k1 "v1"))))
CLIPS> (assert (testvalue 1))
<Fact-1>
CLIPS> (get-fact-list M)
(<Fact-1>)
CLIPS>

CLIPS: asserting facts from within a function does not respect template constraints

I have a single-slot deftemplate definition with a constraint on the allowed symbols. If I directly assert a fact from the top level, the constraints work as expected (i.e. I can only use one of the allowed symbols). However, if I do it from within a deffunction, the constraint is effectively non-existent (see code output below). How do I enforce the constraint from within my function?
CLIPS> (clear)
CLIPS> (deftemplate test-template (slot myslot (type SYMBOL) (allowed-symbols A B C)))
CLIPS> (deffunction test-function (?s) (assert (test-template (myslot ?s))))
CLIPS> (assert (test-template (myslot X)))
[CSTRNCHK1] A literal slot value found in the assert command
does not match the allowed values for slot myslot.
CLIPS> (test-function X)
<Fact-1>
CLIPS> (facts)
f-0 (initial-fact)
f-1 (test-template (myslot X))
For a total of 2 facts.
CLIPS>
Static constraint checking (which occurs during parsing) is enabled by default. Dynamic constraint checking (which occurs during code execution) is not (see section 11 of the Basic Programming Guide). If you enable it you'll get a constraint violation in your example (although you need to assert a fact with a slot value other than X--duplicate facts are not allowed and during execution this check will occur before the constraint check).
CLIPS> (clear)
CLIPS> (deftemplate test-template (slot myslot (type SYMBOL) (allowed-symbols A B C)))
CLIPS> (deffunction test-function (?s) (assert (test-template (myslot ?s))))
CLIPS> (assert (test-template (myslot X)))
[CSTRNCHK1] A literal slot value found in the assert command
does not match the allowed values for slot myslot.
CLIPS> (test-function Y)
<Fact-1>
CLIPS> (set-dynamic-constraint-checking TRUE)
FALSE
CLIPS> (test-function Z)
[CSTRNCHK1] Slot value Z found in fact f-2
does not match the allowed values for slot myslot.
[PRCCODE4] Execution halted during the actions of deffunction test-function.
<Fact-2>
CLIPS>

Resources