0

I'm using the clips framework to build an expert system. However I'm having trouble with memory usage atm, which would make it unsuitable for my task. So here is the problem:

It generates 144 of the SpinWave facts as its supposed to, with a total of around 150 facts. Each fact should not hold more than a bunch of integers (roughly 15). CLIPS consumes 1GB of memory with roughly 6mio memory requests made. I'm kind of baffled why it allocates that much memory... Can someone point me into the right direction or give an explanation. The code I'm using is below. Thanks in advance!

Steve

; define helicity wave final or initial state template
(deftemplate SpinWaveMultiplet
    (slot unique_id (type INTEGER))
    (slot charge (type INTEGER))
    (slot isospin_num (type INTEGER))
    (slot isospin_denom (type INTEGER))
    (slot isospin_z_num (type INTEGER))
    (slot spin_num (type INTEGER))
    (slot spin_denom (type INTEGER))
    ; we have multislot of spin z to allow for specific components
    ; in the initial or final state
    (multislot spin_z_num)
    (slot parity (type INTEGER))
    (slot cparity (type INTEGER))
)

; define spin wave  
(deftemplate SpinWave
    (slot unique_id (type INTEGER))
    (slot charge (type INTEGER))
    (slot isospin_num (type INTEGER))
    (slot isospin_denom (type INTEGER))
    (slot isospin_z_num (type INTEGER))
    (slot spin_num (type INTEGER))
    (slot spin_denom (type INTEGER))
    (slot spin_z_num (type INTEGER))
    (slot parity (type INTEGER))
    (slot cparity (type INTEGER))
)

; allowed intermediate state spins
(deffacts user-conditions
    (AllowedQN
        (spin_nums 0 1 2) (spin_denom 1 ) (isospin_nums 0 1) (isospin_denom 1)
        (charge 0) (parity -1 1) (cparity -1 1)
    )
)


(deffacts initial-state
    (SpinWaveMultiplet (unique_id 0) (spin_num 1) (spin_denom 1) (spin_z_num -1 1)
        (isospin_num 0) (isospin_denom 1) (isospin_z_num 0)
    )
)

(deffacts final-state-list
    (SpinWaveMultiplet (unique_id 1) (spin_num 1) (spin_denom 1) (spin_z_num -1 1)
        (isospin_num 0) (isospin_denom 1) (isospin_z_num 0)
    )
    (SpinWaveMultiplet (unique_id 2) (spin_num 0) (spin_denom 1) (spin_z_num 0)
        (isospin_num 1) (isospin_denom 1) (isospin_z_num 0)
)
    (SpinWaveMultiplet (unique_id 3) (spin_num 0) (spin_denom 1) (spin_z_num 0)
        (isospin_num 1) (isospin_denom 1) (isospin_z_num 0)
    )
)

; create all spin waves
(defrule create-initial-spin-waves
    (AllowedQN
        (spin_nums $?spin_nums) (spin_denom ?spin_denom) 
        (isospin_nums $?isospin_nums) (isospin_denom ?isospin_denom)
        (charge $?charges)
        (parity $?parities)
        (cparity $?cparities)
    )
    =>
    (foreach ?charge ?charges
    (foreach ?parity ?parities
    (foreach ?cparity ?cparities

    (foreach ?isospin_num ?isospin_nums
        (bind ?isospin_z_num (* -1 ?isospin_num))
        (while (<= ?isospin_z_num ?isospin_num)
            (foreach ?spin_num ?spin_nums
                (bind ?spin_z_num (* -1 ?spin_num))
                (while (<= ?spin_z_num ?spin_num) 
                    (assert
                        (SpinWave (unique_id ?*total_unique_id_counter*) 
                        (spin_num ?spin_num) (spin_denom ?spin_denom) (spin_z_num ?spin_z_num)
                        (isospin_num ?isospin_num) (isospin_denom ?isospin_denom) (isospin_z_num ?isospin_z_num)
                        (charge ?charge) (parity ?parity) (cparity ?cparity)
                        )
                    )
                    (bind ?*total_unique_id_counter* (+ ?*total_unique_id_counter* 1))
                    (bind ?spin_z_num (+ ?spin_z_num ?spin_denom))
                )
            )
            (bind ?isospin_z_num (+ ?isospin_z_num ?isospin_denom))
        )
    )

    )
    )
    )
)
4

1 回答 1

3

您发布的代码片段不会消耗大量内存(小于 17 MB)。CLIPS 使用 rete 算法保存规则的部分匹配状态,因此您可能有一个或多个规则匹配生成大量部分匹配的 SpinWave 事实。

您可以使用 matches 命令获取每个规则使用的部分匹配数量的快照,并使用 join-activity 命令获取可能存在性能问题的规则的总体快照。

例如,在运行礼仪基准后,我可以使用这些命令看到 find_seating 和 make_path 规则是我应该检查性能问题的规则。

CLIPS> (batch "manners128.bat")
TRUE
CLIPS> (clear)
CLIPS> (unwatch compilations)
CLIPS> (watch statistics)
CLIPS> (set-strategy depth)
depth
CLIPS> (load manners.clp)
:%%%%%%%********
TRUE
CLIPS> (reset)
CLIPS> (load-facts manners128.fct)
TRUE
CLIPS> (run)
8639 rules fired        Run time is 2.39572899999621 seconds.
3606.00051174973 rules per second.
4762 mean number of facts (8953 maximum).
1 mean number of instances (1 maximum).
138 mean number of activations (9490 maximum).
CLIPS> 
(progn$ 
   (?r (get-defrule-list)) 
   (printout t ?r ": " (join-activity ?r terse) crlf))
assign_first_seat: (1314 1315 1315)
find_seating: (5847660 7067211 7067211)
make_path: (49549 16510 16510)
path_done: (127 254 254)
are_we_done: (128 255 255)
continue: (0 127 127)
print_results: (257 258 128)
all_done: (0 1 0)
CLIPS> 
(progn$ 
   (?r (get-defrule-list)) 
   (printout t ?r ": " (matches ?r terse) crlf))
assign_first_seat: (439 0 0)
find_seating: (9260 0 0)
make_path: (16256 0 0)
path_done: (0 0 0)
are_we_done: (129 0 0)
continue: (0 0 0)
print_results: (8258 129 0)
all_done: (1 0 0)
CLIPS> 

根据您的评论,这是您提到的导致问题的规则之一:

(defrule check-charge 
   ?mymother <- (SpinWave (charge ?charge_mother)) 
   ?mydaughter1 <- (SpinWave (charge ?charge_daughter1)) 
   ?mydaughter2 <- (SpinWave (charge ?charge_daughter2)) 
   =>)

没有一个模式具有限制与其他模式匹配的事实数量的条件,因此该规则基本上匹配三个 SpinWave 事实的所有组合。由于有 144 个事实与三个模式中的每一个匹配,因此将有 2,985,984 (144 * 144 * 144) 次激活规则。因此,即使 CLIPS 没有为前两个模式生成部分匹配,仍然会有数百万个激活消耗内存,随着每个规则激活被允许执行,这些内存最终会被释放。

在不知道规则应该做什么或 SpinWave 事实之间的关系的情况下,很难具体说明如何使规则更有效,但通常您希望模式被限制在与变量匹配的事实数量上来自上述模式的绑定。

因此,如果事实之间存在父/子关系,您可以为 SpinWave 事实添加和填充父槽,并使用它来减少生成的部分匹配/激活的数量:

(defrule check-charge 
   ?mymother <- (SpinWave (charge ?charge_mother) (unique_id ?id)) 
   ?mydaughter1 <- (SpinWave (charge ?charge_daughter1) (parent ?id)) 
   ?mydaughter2 <- (SpinWave (charge ?charge_daughter2) (parent ?id)) 
   =>)
于 2016-01-05T17:30:15.810 回答