Reputation: 414
I am trying to modify a fact template from python using CLIPSPY. It behaves strangely as it does modify a slot for the first time, but then for next slot, it does not and even re-modify the previous modified slot value to something else itself!!
This is the python file.
# run.py
import clips
clips_env = clips.Environment()
def py_modify_s1(p):
p.retract()
p["s_1"] = clips.Symbol("ABC")
p.assertit()
def py_modify_s2(p):
p.retract()
p["s_2"] = clips.Symbol("DEF")
p.assertit()
clips_env.define_function(py_modify_s1)
clips_env.define_function(py_modify_s2)
clips_env.load("KB.clp")
clips_env.reset()
clips_env.run()
This is the clp file.
(deftemplate t
(slot s_1 (type SYMBOL) (default none))
(slot s_2 (type SYMBOL) (default none))
)
(defrule rule_0
(initial-fact)
=>
(assert (t))
)
(defrule rule_1
?p<-(t (s_1 none) (s_2 none))
=>
(py_modify_s1 ?p)
(facts)
)
(defrule rule_2
?p <- (t (s_1 ?x&~none) (s_2 none))
=>
(py_modify_s2 ?p)
(facts)
)
(defrule rule_3
?p <- (t (s_1 ?x&~none) (s_2 ?y&~none))
=>
(printout t "All set")
(facts)
)
Running the same clip file in CLIPS shell (replacing py_modify with (modify ?p (s_1,ABC))
) produces expected result. But running from clipspy I get:
f-0 (initial-fact)
f-2 (t (s_1 ABC) (s_2 none))
For a total of 2 facts.
f-0 (initial-fact)
f-2 (t (s_1 ▒▒▒3wU) (s_2 none))
For a total of 2 facts.
Notice how s_1
is containing some garbage value after firing of rule_2
and s_2
is not modified only. As a result, rule_3
never gets fired.
Upvotes: 0
Views: 285
Reputation: 15060
It turns out facts cannot be modified once asserted via the C (and therefore Python) API. Only way to change a fact is retract the original one and assert a new one. Chapter 4.4.22 EnvPutFactSlot
of the Advanced Programming Guide.
The only way possible seems to be retracting the old fact and asserting a new one with updated values.
def modify_fact(fact):
"""Modify a template fact."""
fact.retract()
new_fact = fact.template.new_fact()
new_fact.update(dict(fact)) # copy over old fact slot values
new_fact["s_1"] = clips.Symbol("v_2")
new_fact.assertit()
I raised this issue in a discussion on the CLIPS forum as well.
Upvotes: 0