0

我正在尝试使用 CLIPSPY 从 python 修改事实模板。它的行为很奇怪,因为它确实第一次修改了一个插槽,但是对于下一个插槽,它不会甚至将先前修改的插槽值重新修改为其他内容!

这是python文件。

# 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()

这是 clp 文件。

(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)
)

在 CLIPS shell 中运行相同的剪辑文件(将 py_modify 替换为(modify ?p (s_1,ABC)))会产生预期的结果。但是从 clipspy 运行我得到:

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.

请注意在触发后如何s_1包含一些垃圾值rule_2并且s_2不只修改。结果,rule_3永远不会被解雇。

4

1 回答 1

0

事实证明,一旦通过 C(以及 Python)API 断言,事实就无法修改。改变事实的唯一方法是收回原来的事实并断言新的事实。高级编程指南的章节4.4.22 EnvPutFactSlot

唯一可能的方法似乎是撤回旧事实并使用更新的值断言新事实。

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 论坛的讨论中提出了这个问题。

于 2019-01-01T23:15:36.123 回答