问题
How to modify a fact of a template in CLIPS using ClipsPy.
I have tried the reassigning slot value and sending modify in clips.build
routine, (see py_modify
function below) which did not work.
This is the .clp file
;; KB.clp
(deftemplate t
(slot s_1 (type SYMBOL)))
(defrule main-intent
(initial-fact)
=>
(assert (t (s_1 v_1)))
)
(defrule rule_1
?p<-(t (s_1 ?v))
=>
(printout t"BEFORE"crlf) (py_pfact)
(py_modify ?p)
(printout t"AFTER"crlf) (py_pfact)
)
This is the python file..
# run.py
import clips
clips_env = clips.Environment()
def py_pfact():
for fact in clips_env.facts():
print(fact)
def py_modify(p):
print("--modifying",p["s_1"])
p["s_1"] = "v_2" # Try 1
clips.build("(modify "+str(p.index)+ " (s_1 v_2)") #Try 2
clips_env.define_function(py_pfact)
clips_env.define_function(py_modify)
clips_env.load("KB.clp")
clips_env.reset()
clips_env.run()
The ouput is
BEFORE
(initial-fact)
(t (s_1 v_1))
--modifying v_1
AFTER
(initial-fact)
(t (s_1 v_1))
I expect s_1
slot to be modified to v_2
from v_1
, but it is not.
回答1:
The environment.build method is for building constructs (defrule
, deftemplate
, etc.) within the engine. To execute CLIPS code, you need to use environment.eval.
In CLIPS it's not possible to change a fact once asserted. Only way to do so is by retracting the old one 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()
CLIPS provides the modify
command which does the exact same: retracts the fact and asserts it with the new value. Nevertheless, it cannot be used via environment.eval
as fact indexes cannot be used via the API. If you want to modify a fact within a rule, you'd better use the modify
command directly.
(defrule rule_1
?p <- (t (s_1 ?v))
=>
(modify ?p (s_1 v_2)))
来源:https://stackoverflow.com/questions/53967519/programmatically-modify-a-fact-slot-using-clipspy