Menu

OutOfMemory when loading complex rule

Help
vranoch
2018-02-28
2018-06-09
  • vranoch

    vranoch - 2018-02-28

    Hi Gary,

    I noticed another problem when trying to load a very complex rule. It just runs out of memory. It does not seem to fall into an infinite recursion, it just keeps allocating memory during the Reordering phase but seems to explode with growing number of CEs.

    Despite the fact that this specific rule may not be meaningful, I have the following 2 questions:

    1) Isn't there some memory leak causing to consume 10+ Gigs if allowed or is it just a correct behaviour?
    2) In case it is not a bug, what is a resonable amount of CEs that can be safely processed (approximately - to potentially check and limit complex rules)?

    Thanks Vranoch

    (defrule V_if ""
    (M ?m)
    (DD ?dd)
    (DR ?m KD ?kd)
    (LVAR var1 ?var1)
    (DR ?m RL K ?k)
    (exists 
        (or 
            (test (eq  ?kd "10"))
            (or 
                (test (eq  ?dd "02"))
                (test (eq  ?dd "99"))
            ) 
            (test (eq  ?var1 "P"))
            (test (eq  ?var1 "M"))
        ) 
        (or 
            (or 
                (test (eq  ?k "1"))
                (test (eq  ?k "2"))
            ) 
            (test (eq  ?kd "10"))
            (test (eq  ?var1 "P"))
            (test (eq  ?var1 "M"))
        ) 
        (or 
            (test (eq  ?var1 "H"))
            (test (eq  ?kd "10"))
            (test (eq  ?var1 "P"))
            (test (eq  ?var1 "M"))
        ) 
        (or 
            (or 
                (test (eq  ?dd "02"))
                (test (eq  ?dd "99"))
            ) 
            (test (eq  ?kd "10"))
            (not (test (eq  ?kd "14"))) 
            (test (eq  ?var1 "M"))
        ) 
        (or 
            (or 
                (test (eq  ?k "1"))
                (test (eq  ?k "2"))
            ) 
            (test (eq  ?kd "10"))
            (not (test (eq  ?kd "14"))) 
            (test (eq  ?var1 "M"))
        ) 
        (or 
            (test (eq  ?var1 "H"))
            (test (eq  ?kd "10"))
            (not (test (eq  ?kd "14"))) 
            (test (eq  ?var1 "M"))
        ) 
        (or 
            (not (test (eq  ?kd "14"))) 
            (or 
                (test (eq  ?k "1"))
                (test (eq  ?k "2"))
            ) 
            (or 
                (test (eq  ?dd "02"))
                (test (eq  ?dd "99"))
            ) 
            (test (eq  ?var1 "M"))
        ) 
    (or (not (test (eq  ?kd "14"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (test (eq  ?var1 "M"))
    ) 
    (or (not (test (eq  ?kd "14"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (test (eq  ?var1 "H"))
    (test (eq  ?var1 "M"))
    ) 
    (or (not (test (eq  ?kd "14"))
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?var1 "K"))
    (test (eq  ?var1 "O"))
    (test (eq  ?var1 "T"))
    (test (eq  ?var1 "U"))
    (test (eq  ?var1 "B"))
    ) 
    (or (test (eq  ?dd "02"))
    (test (eq  ?dd "99"))
    ) 
    (test (eq  ?var1 "M"))
    ) 
    (or (not (test (eq  ?kd "14"))
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?var1 "K"))
    (test (eq  ?var1 "O"))
    (test (eq  ?var1 "T"))
    (test (eq  ?var1 "U"))
    (test (eq  ?var1 "B"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (test (eq  ?var1 "M"))
    ) 
    (or (not (test (eq  ?kd "14"))
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?var1 "K"))
    (test (eq  ?var1 "O"))
    (test (eq  ?var1 "T"))
    (test (eq  ?var1 "U"))
    (test (eq  ?var1 "B"))
    ) 
    (test (eq  ?var1 "H"))
    (test (eq  ?var1 "M"))
    ) 
    (or (or (test (eq  ?dd "02"))
    (test (eq  ?dd "99"))
    ) 
    (test (eq  ?kd "10"))
    (not (test (eq  ?kd "13"))
    ) 
    (test (eq  ?var1 "M"))
    ) 
    (or (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (test (eq  ?kd "10"))
    (not (test (eq  ?kd "13"))
    ) 
    (test (eq  ?var1 "M"))
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?kd "10"))
    (not (test (eq  ?kd "13"))
    ) 
    (test (eq  ?var1 "M"))
    ) 
    (or (not (test (eq  ?kd "13"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (or (test (eq  ?dd "02"))
    (test (eq  ?dd "99"))
    ) 
    (test (eq  ?var1 "M"))
    ) 
    (or (not (test (eq  ?kd "13"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (test (eq  ?var1 "M"))
    ) 
    (or (not (test (eq  ?kd "13"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (test (eq  ?var1 "H"))
    (test (eq  ?var1 "M"))
    ) 
    (or (not (test (eq  ?kd "13"))
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?var1 "K"))
    (test (eq  ?var1 "O"))
    (test (eq  ?var1 "T"))
    (test (eq  ?var1 "U"))
    (test (eq  ?var1 "B"))
    ) 
    (or (test (eq  ?dd "02"))
    (test (eq  ?dd "99"))
    ) 
    (test (eq  ?var1 "M"))
    ) 
    (or (not (test (eq  ?kd "13"))
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?var1 "K"))
    (test (eq  ?var1 "O"))
    (test (eq  ?var1 "T"))
    (test (eq  ?var1 "U"))
    (test (eq  ?var1 "B"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (test (eq  ?var1 "M"))
    ) 
    (or (not (test (eq  ?kd "13"))
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?var1 "K"))
    (test (eq  ?var1 "O"))
    (test (eq  ?var1 "T"))
    (test (eq  ?var1 "U"))
    (test (eq  ?var1 "B"))
    ) 
    (test (eq  ?var1 "H"))
    (test (eq  ?var1 "M"))
    ) 
    (or (or (test (eq  ?dd "02"))
    (test (eq  ?dd "99"))
    ) 
    (test (eq  ?kd "10"))
    (not (test (eq  ?kd "12"))
    ) 
    (test (eq  ?var1 "M"))
    ) 
    (or (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (test (eq  ?kd "10"))
    (not (test (eq  ?kd "12"))
    ) 
    (test (eq  ?var1 "M"))
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?kd "10"))
    (not (test (eq  ?kd "12"))
    ) 
    (test (eq  ?var1 "M"))
    ) 
    (or (not (test (eq  ?kd "12"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (or (test (eq  ?dd "02"))
    (test (eq  ?dd "99"))
    ) 
    (test (eq  ?var1 "M"))
    ) 
    (or (not (test (eq  ?kd "12"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (test (eq  ?var1 "M"))
    ) 
    (or (not (test (eq  ?kd "12"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (test (eq  ?var1 "H"))
    (test (eq  ?var1 "M"))
    ) 
    (or (not (test (eq  ?kd "12"))
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?var1 "K"))
    (test (eq  ?var1 "O"))
    (test (eq  ?var1 "T"))
    (test (eq  ?var1 "U"))
    (test (eq  ?var1 "B"))
    ) 
    (or (test (eq  ?dd "02"))
    (test (eq  ?dd "99"))
    ) 
    (test (eq  ?var1 "M"))
    ) 
    (or (not (test (eq  ?kd "12"))
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?var1 "K"))
    (test (eq  ?var1 "O"))
    (test (eq  ?var1 "T"))
    (test (eq  ?var1 "U"))
    (test (eq  ?var1 "B"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (test (eq  ?var1 "M"))
    ) 
    (or (not (test (eq  ?kd "12"))
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?var1 "K"))
    (test (eq  ?var1 "O"))
    (test (eq  ?var1 "T"))
    (test (eq  ?var1 "U"))
    (test (eq  ?var1 "B"))
    ) 
    (test (eq  ?var1 "H"))
    (test (eq  ?var1 "M"))
    ) 
    (or (or (test (eq  ?dd "02"))
    (test (eq  ?dd "99"))
    ) 
    (test (eq  ?kd "10"))
    (not (test (eq  ?kd "03"))
    ) 
    (test (eq  ?var1 "P"))
    ) 
    (or (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (test (eq  ?kd "10"))
    (not (test (eq  ?kd "03"))
    ) 
    (test (eq  ?var1 "P"))
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?kd "10"))
    (not (test (eq  ?kd "03"))
    ) 
    (test (eq  ?var1 "P"))
    ) 
    (or (not (test (eq  ?kd "03"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (test (eq  ?var1 "P"))
    (or (test (eq  ?dd "02"))
    (test (eq  ?dd "99"))
    ) 
    ) 
    (or (not (test (eq  ?kd "03"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (test (eq  ?var1 "P"))
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    ) 
    (or (not (test (eq  ?kd "03"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (test (eq  ?var1 "P"))
    (test (eq  ?var1 "H"))
    ) 
    (or (not (test (eq  ?kd "03"))
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?var1 "K"))
    (test (eq  ?var1 "O"))
    (test (eq  ?var1 "T"))
    (test (eq  ?var1 "U"))
    (test (eq  ?var1 "B"))
    ) 
    (test (eq  ?var1 "P"))
    (or (test (eq  ?dd "02"))
    (test (eq  ?dd "99"))
    ) 
    ) 
    (or (not (test (eq  ?kd "03"))
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?var1 "K"))
    (test (eq  ?var1 "O"))
    (test (eq  ?var1 "T"))
    (test (eq  ?var1 "U"))
    (test (eq  ?var1 "B"))
    ) 
    (test (eq  ?var1 "P"))
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    ) 
    (or (not (test (eq  ?kd "03"))
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?var1 "K"))
    (test (eq  ?var1 "O"))
    (test (eq  ?var1 "T"))
    (test (eq  ?var1 "U"))
    (test (eq  ?var1 "B"))
    ) 
    (test (eq  ?var1 "P"))
    (test (eq  ?var1 "H"))
    ) 
    (or (or (test (eq  ?dd "02"))
    (test (eq  ?dd "99"))
    ) 
    (test (eq  ?kd "10"))
    (not (test (eq  ?kd "14"))
    ) 
    (not (test (eq  ?kd "03"))
    ) 
    ) 
    (or (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (test (eq  ?kd "10"))
    (not (test (eq  ?kd "14"))
    ) 
    (not (test (eq  ?kd "03"))
    ) 
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?kd "10"))
    (not (test (eq  ?kd "14"))
    ) 
    (not (test (eq  ?kd "03"))
    ) 
    ) 
    (or (not (test (eq  ?kd "14"))
    ) 
    (not (test (eq  ?kd "03"))
    ) 
    (or (test (eq  ?dd "02"))
    (test (eq  ?dd "99"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    ) 
    (or (not (test (eq  ?kd "14"))
    ) 
    (not (test (eq  ?kd "03"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    ) 
    (or (not (test (eq  ?kd "14"))
    ) 
    (not (test (eq  ?kd "03"))
    ) 
    (test (eq  ?var1 "H"))
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    ) 
    (or (not (test (eq  ?kd "14"))
    ) 
    (not (test (eq  ?kd "03"))
    ) 
    (or (test (eq  ?dd "02"))
    (test (eq  ?dd "99"))
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?var1 "K"))
    (test (eq  ?var1 "O"))
    (test (eq  ?var1 "T"))
    (test (eq  ?var1 "U"))
    (test (eq  ?var1 "B"))
    ) 
    ) 
    (or (not (test (eq  ?kd "14"))
    ) 
    (not (test (eq  ?kd "03"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?var1 "K"))
    (test (eq  ?var1 "O"))
    (test (eq  ?var1 "T"))
    (test (eq  ?var1 "U"))
    (test (eq  ?var1 "B"))
    ) 
    ) 
    (or (not (test (eq  ?kd "14"))
    ) 
    (not (test (eq  ?kd "03"))
    ) 
    (test (eq  ?var1 "H"))
    (or (test (eq  ?var1 "H"))
    (test (eq  ?var1 "K"))
    (test (eq  ?var1 "O"))
    (test (eq  ?var1 "T"))
    (test (eq  ?var1 "U"))
    (test (eq  ?var1 "B"))
    ) 
    ) 
    (or (or (test (eq  ?dd "02"))
    (test (eq  ?dd "99"))
    ) 
    (test (eq  ?kd "10"))
    (not (test (eq  ?kd "13"))
    ) 
    (not (test (eq  ?kd "03"))
    ) 
    ) 
    (or (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (test (eq  ?kd "10"))
    (not (test (eq  ?kd "13"))
    ) 
    (not (test (eq  ?kd "03"))
    ) 
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?kd "10"))
    (not (test (eq  ?kd "13"))
    ) 
    (not (test (eq  ?kd "03"))
    ) 
    ) 
    (or (not (test (eq  ?kd "13"))
    ) 
    (not (test (eq  ?kd "03"))
    ) 
    (or (test (eq  ?dd "02"))
    (test (eq  ?dd "99"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    ) 
    (or (not (test (eq  ?kd "13"))
    ) 
    (not (test (eq  ?kd "03"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    ) 
    (or (not (test (eq  ?kd "13"))
    ) 
    (not (test (eq  ?kd "03"))
    ) 
    (test (eq  ?var1 "H"))
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    ) 
    (or (not (test (eq  ?kd "13"))
    ) 
    (not (test (eq  ?kd "03"))
    ) 
    (or (test (eq  ?dd "02"))
    (test (eq  ?dd "99"))
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?var1 "K"))
    (test (eq  ?var1 "O"))
    (test (eq  ?var1 "T"))
    (test (eq  ?var1 "U"))
    (test (eq  ?var1 "B"))
    ) 
    ) 
    (or (not (test (eq  ?kd "13"))
    ) 
    (not (test (eq  ?kd "03"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?var1 "K"))
    (test (eq  ?var1 "O"))
    (test (eq  ?var1 "T"))
    (test (eq  ?var1 "U"))
    (test (eq  ?var1 "B"))
    ) 
    ) 
    (or (not (test (eq  ?kd "13"))
    ) 
    (not (test (eq  ?kd "03"))
    ) 
    (test (eq  ?var1 "H"))
    (or (test (eq  ?var1 "H"))
    (test (eq  ?var1 "K"))
    (test (eq  ?var1 "O"))
    (test (eq  ?var1 "T"))
    (test (eq  ?var1 "U"))
    (test (eq  ?var1 "B"))
    ) 
    ) 
    (or (or (test (eq  ?dd "02"))
    (test (eq  ?dd "99"))
    ) 
    (test (eq  ?kd "10"))
    (not (test (eq  ?kd "12"))
    ) 
    (not (test (eq  ?kd "03"))
    ) 
    ) 
    (or (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (test (eq  ?kd "10"))
    (not (test (eq  ?kd "12"))
    ) 
    (not (test (eq  ?kd "03"))
    ) 
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?kd "10"))
    (not (test (eq  ?kd "12"))
    ) 
    (not (test (eq  ?kd "03"))
    ) 
    ) 
    (or (not (test (eq  ?kd "12"))
    ) 
    (not (test (eq  ?kd "03"))
    ) 
    (or (test (eq  ?dd "02"))
    (test (eq  ?dd "99"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    ) 
    (or (not (test (eq  ?kd "12"))
    ) 
    (not (test (eq  ?kd "03"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    ) 
    (or (not (test (eq  ?kd "12"))
    ) 
    (not (test (eq  ?kd "03"))
    ) 
    (test (eq  ?var1 "H"))
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    ) 
    (or (not (test (eq  ?kd "12"))
    ) 
    (not (test (eq  ?kd "03"))
    ) 
    (or (test (eq  ?dd "02"))
    (test (eq  ?dd "99"))
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?var1 "K"))
    (test (eq  ?var1 "O"))
    (test (eq  ?var1 "T"))
    (test (eq  ?var1 "U"))
    (test (eq  ?var1 "B"))
    ) 
    ) 
    (or (not (test (eq  ?kd "12"))
    ) 
    (not (test (eq  ?kd "03"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?var1 "K"))
    (test (eq  ?var1 "O"))
    (test (eq  ?var1 "T"))
    (test (eq  ?var1 "U"))
    (test (eq  ?var1 "B"))
    ) 
    ) 
    (or (not (test (eq  ?kd "12"))
    ) 
    (not (test (eq  ?kd "03"))
    ) 
    (test (eq  ?var1 "H"))
    (or (test (eq  ?var1 "H"))
    (test (eq  ?var1 "K"))
    (test (eq  ?var1 "O"))
    (test (eq  ?var1 "T"))
    (test (eq  ?var1 "U"))
    (test (eq  ?var1 "B"))
    ) 
    ) 
    (or (or (test (eq  ?dd "02"))
    (test (eq  ?dd "99"))
    ) 
    (test (eq  ?kd "10"))
    (test (eq  ?k "3"))
    ) 
    (or (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (test (eq  ?kd "10"))
    (test (eq  ?k "3"))
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?kd "10"))
    (test (eq  ?k "3"))
    ) 
    (or (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (or (test (eq  ?dd "02"))
    (test (eq  ?dd "99"))
    ) 
    (test (eq  ?var1 "P"))
    (test (eq  ?var1 "M"))
    ) 
    (or (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (test (eq  ?var1 "P"))
    (test (eq  ?var1 "M"))
    ) 
    (or (test (eq  ?var1 "H"))
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (test (eq  ?var1 "P"))
    (test (eq  ?var1 "M"))
    ) 
    (or (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?var1 "K"))
    (test (eq  ?var1 "O"))
    (test (eq  ?var1 "T"))
    (test (eq  ?var1 "U"))
    (test (eq  ?var1 "B"))
    ) 
    (test (eq  ?var1 "P"))
    (test (eq  ?var1 "M"))
    ) 
    (or (or (test (eq  ?dd "02"))
    (test (eq  ?dd "99"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (test (eq  ?k "3"))
    ) 
    (or (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (test (eq  ?k "3"))
    ) 
    (or (test (eq  ?var1 "H"))
    (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (test (eq  ?k "3"))
    ) 
    (or (or (test (eq  ?dd "02"))
    (test (eq  ?dd "99"))
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?var1 "K"))
    (test (eq  ?var1 "O"))
    (test (eq  ?var1 "T"))
    (test (eq  ?var1 "U"))
    (test (eq  ?var1 "B"))
    ) 
    (test (eq  ?k "3"))
    ) 
    (or (or (test (eq  ?k "1"))
    (test (eq  ?k "2"))
    ) 
    (or (test (eq  ?var1 "H"))
    (test (eq  ?var1 "K"))
    (test (eq  ?var1 "O"))
    (test (eq  ?var1 "T"))
    (test (eq  ?var1 "U"))
    (test (eq  ?var1 "B"))
    ) 
    (test (eq  ?k "3"))
    ) 
    (or (test (eq  ?var1 "H"))
    (or (test (eq  ?var1 "H"))
    (test (eq  ?var1 "K"))
    (test (eq  ?var1 "O"))
    (test (eq  ?var1 "T"))
    (test (eq  ?var1 "U"))
    (test (eq  ?var1 "B"))
    ) 
    (test (eq  ?k "3"))
    ) 
    (or (test (eq  ?var1 "P"))
    (test (eq  ?var1 "M"))
    (or (test (eq  ?var1 "H"))
    (test (eq  ?var1 "K"))
    (test (eq  ?var1 "O"))
    (test (eq  ?var1 "T"))
    (test (eq  ?var1 "U"))
    (test (eq  ?var1 "B"))
    ) 
    (or (test (eq  ?dd "02"))
    (test (eq  ?dd "99"))
    ) 
    ) 
    (or (test (eq  ?var1 "H"))
    (or (test (eq  ?var1 "H"))
    (test (eq  ?var1 "K"))
    (test (eq  ?var1 "O"))
    (test (eq  ?var1 "T"))
    (test (eq  ?var1 "U"))
    (test (eq  ?var1 "B"))
    ) 
    (test (eq  ?var1 "P"))
    (test (eq  ?var1 "M"))
    ) 
    )
    
    =>
    
    )
    
     
  • vranoch

    vranoch - 2018-02-28

    The explosion actually starts MUCH earlier than for such a huge rule. See the following simplified rule. If You start uncomenting the commented-out ORs, You first get a significant memory increase and then a StackOverflow.

    Thanks Vranoch

    (defrule V_if ""
    (M ?m)
    (DD ?dd)
    (DR ?m KD ?kd)
    (LVAR var1 ?var1)
    (DR ?m RL K ?k)
    (exists 
        (or 
            (test (eq  ?kd "10"))
            (or 
                (test (eq  ?dd "02"))
                (test (eq  ?dd "99"))
            ) 
            (test (eq  ?var1 "P"))
            (test (eq  ?var1 "M"))
        ) 
        (or 
            (or 
                (test (eq  ?k "1"))
                (test (eq  ?k "2"))
            ) 
            (test (eq  ?kd "10"))
            (test (eq  ?var1 "P"))
            (test (eq  ?var1 "M"))
        ) 
        (or 
            (test (eq  ?var1 "H"))
            (test (eq  ?kd "10"))
            (test (eq  ?var1 "P"))
            (test (eq  ?var1 "M"))
        ) 
        (or 
            (or 
                (test (eq  ?dd "02"))
                (test (eq  ?dd "99"))
            ) 
            (test (eq  ?kd "10"))
            (not (test (eq  ?kd "14"))) 
            (test (eq  ?var1 "M"))
        ) 
        ; (or 
            ; (or 
                ; (test (eq  ?k "1"))
                ; (test (eq  ?k "2"))
            ; ) 
            ; (test (eq  ?kd "10"))
            ; (not (test (eq  ?kd "14"))) 
            ; (test (eq  ?var1 "M"))
        ; ) 
    
        ; (or 
            ; (test (eq  ?var1 "H"))
            ; (test (eq  ?kd "10"))
            ; (not (test (eq  ?kd "14"))) 
            ; (test (eq  ?var1 "M"))
        ; ) 
    
        ; (or 
            ; (not (test (eq  ?kd "14"))) 
            ; (or 
                ; (test (eq  ?k "1"))
                ; (test (eq  ?k "2"))
            ; ) 
            ; (or 
                ; (test (eq  ?dd "02"))
                ; (test (eq  ?dd "99"))
            ; ) 
            ; (test (eq  ?var1 "M"))
        ; ) 
    )
    =>
    )
    
     
  • Gary Riley

    Gary Riley - 2018-03-04

    The 'or' conditional element is processed by generating all possible permutations. So a rule such as this:

    (defrule example
       (or (a) (b))
       (or (c) (d))
       =>)
    

    is converted to this:

    (defrule example
       (or (and (a) (c))
           (and (a) (d))
           (and (b) (c))
           (and (b) (d)))
       =>)
    

    Once in this new form, each conditional element within the single 'or' conditional element creates a separate rule (which are collectively presented to the user as a single rule). Because of the way the rete algorithm constructs the rule network this is the most straightforward way to implement an 'or' conditional element (and I've not seen any alternative implementations).

    The downside of this approach is that you can get multiple activations from the 'or' conditional element if more than one of the conditional elements is matched, but there's really no alternative to this when matching fact/instances unless you explicit write separate rules to prevent this.

    In the case of the V_if rule, the use of the 'or' conditional elements generates roughly 60,000 permutations. In this case, however, it's important to note that

    (or (test (eq ?dd "02")) 
        (test (eq ?dd "99"))
    

    is not equivalent to

    (test (or (eq ?dd "02")
              (eq ?dd "99")))
    

    In the first case, the 'or' conditional element will create permutations in conjunction with the other conditional elements in the rule, whereas in the second case, you're making a call to the 'or' boolean function.

    The most efficient way to write your original rule is:

    (defrule V_if ""
    (M ?m)
    (DD ?dd)
    (DR ?m KD ?kd)
    (LVAR var1 ?var1)
    (DR ?m RL K ?k)
        (test 
            (or (eq  ?kd "10")
                (or (eq  ?dd "02") 
                    (eq  ?dd "99"))
                (eq  ?var1 "P")
                (eq  ?var1 "M")))
        (test 
            (or (or (eq  ?k "1") 
                    (eq  ?k "2"))
                (eq  ?kd "10")
                (eq  ?var1 "P")
                (eq  ?var1 "M")))
        (test 
            (or (eq  ?var1 "H")
                (eq  ?kd "10")
                (eq  ?var1 "P")
                (eq  ?var1 "M")))
        (test 
            (or (or (eq  ?dd "02") 
                    (eq  ?dd "99"))
                (eq  ?kd "10")
                (not (eq  ?kd "14")) 
                (eq  ?var1 "M")))
         (test 
             (or (or (eq  ?k "1") 
                     (eq  ?k "2")) 
                 (eq  ?kd "10")
                 (not (eq  ?kd "14")) 
                 (eq  ?var1 "M")))
    
         (test 
             (or (eq  ?var1 "H")
                 (eq  ?kd "10")
                 (not (eq  ?kd "14")) 
                 (eq  ?var1 "M")))
    
         (test 
             (or (not (eq  ?kd "14")) 
                 (or (eq  ?k "1") 
                     (eq  ?k "2"))
                 (or (eq  ?dd "02") 
                     (eq  ?dd "99"))
                 (eq  ?var1 "M"))) 
    =>
    )
    
     

    Last edit: Gary Riley 2018-03-04
  • vranoch

    vranoch - 2018-03-04

    Hi Gary,

    Thanks for the clarification. This construction comes from a logical expression optimizer whose purpose is to reduce the risk of runtime complexity of rules (result of my former post). It converts the original expression to DNF (Disjunctive Normal Form) - (AND (OR) (OR) (OR)) so that it is flat and then tries to reorder individial OR groups and expressions within each OR group and respective catching of facts in such a way that each group is preceded only by necessary facts reducing the risk of producing a carthesian product of partial matches at the runtime. It results in interleaving conditional expressions and facts. e.g.

    (defrule XY
        (M ?m)
        (X ?x)
        (or
            (test (eq ?m "19"))
            (test (eq ?x "AB"))
        )
        (A ?a)
        (or
            (test (eq ?m "20"))
            (test (eq ?a "CD"))
        )
    =>
    )
    

    So I have couple of questions:
    1) Do You see any other way how to with a general algorithm optimize the rules to prevent their runtime demands? (generting unnecessary carthesian product of partial matches)?
    2) How to quantify/estimate the complexity of DNF and how to decide what complexity is still OK and which is already exhausting?
    3) In case the complexity of the DNF is already exhausting, I can try to transform it in the You described. In this case:
    a) what is the purpose of the (exists ) over partial (test ) calls?
    4) Is it possible to use also the CNF (OR (AND) (AND) (AND)) form for the purpose of optimizing the runtime complexity of rules, namely how to iterleave (AND) groups with catching of facts - fatching of facts is not allowed within the (or) function, e.g.

    (defrule XY
    (test (or
        (M ?m)
        (X ?x)
        (and
            (test (eq ?m "19"))
            (test (eq ?x "AB"))
        )
        (A ?a)
        (and
            (test (eq ?m "20"))
            (test (eq ?a "CD"))
        )
    ))
    =>
    )
    

    Thanks Vranoch

     
  • Gary Riley

    Gary Riley - 2018-03-06

    If you want to improve performance, you're going to have to do something with all of the or/test conditional elements being generated for comparing values to constants. If you place the constant comparisons within the fact patterns, you'll cut down on the number of partial matches being processed by the rule network. For a large number of facts, I see orders of magnitude improved performance:

    CLIPS> (clear)
    CLIPS> 
    (defrule XY-1
        (M ?m)
        (X ?x)
        (or (test (eq ?m "19"))
            (test (eq ?x "AB")))
        (A ?a)
        (or (test (eq ?m "20"))
            (test (eq ?a "CD")))
       =>)
    CLIPS> (timer (assert (M "19") (M "20") (X "AB") (A "CD"))(loop-for-count (?i 5000) (assert (M ?i) (X ?i) (A ?i))))
    22.0732859999989
    CLIPS> (reset)
    CLIPS> (release-mem)
    13917635
    CLIPS> (timer (loop-for-count (?i 5000) (assert (M ?i) (X ?i) (A ?i))))
    5.28450999999768
    CLIPS> (clear)
    CLIPS> (release-mem)
    7608742
    CLIPS> 
    (defrule XY-2
      (or (and (M "19")
               (A "CD")
               (X ?))
          (and (M "20")
               (X "AB")
               (A ?))
          (and (X "AB")
               (A "CD")
               (M ?)))
       =>)   
    CLIPS> (timer (assert (M "19") (M "20") (X "AB") (A "CD"))(loop-for-count (?i 5000) (assert (M ?i) (X ?i) (A ?i))))
    0.0241910000040662
    CLIPS> (reset)
    CLIPS> (release-mem)
    9439848
    CLIPS> (timer (loop-for-count (?i 5000) (assert (M ?i) (X ?i) (A ?i))))
    0.0165890000062063
    CLIPS> (/ 22.0732859999989 0.0241910000040662)
    912.458600152481
    CLIPS> (/ 5.28450999999768 0.0165890000062063)
    318.555066491086
    CLIPS>
    
     
  • vranoch

    vranoch - 2018-03-14

    Hi Gary,

    could You give me some rough idea how to estimate the expected complexity of the constructed rule to decide whether it is feasible to load in the given form or whether it already exceeds some limit and it should be written in some other way. Namely how to estimate the complexity of nested ORs, EXISTSs and TESTs.

    Thanks Vranoch

    (defrule V_if ""
    (M ?m)
    (DD ?dd)
    (DR ?m KD ?kd)
    (LVAR var1 ?var1)
    (DR ?m RL K ?k)
    (exists 
        (or 
            (test (eq  ?kd "10"))
            (or 
                (test (eq  ?dd "02"))
                (test (eq  ?dd "99"))
            ) 
            (test (eq  ?var1 "P"))
            (test (eq  ?var1 "M"))
        ) 
        (or 
            (test
                (or 
                    (eq  ?k "1")
                    (eq  ?k "2")
                )
            )
            (test (eq  ?kd "10"))
            (test (eq  ?var1 "P"))
            (test (eq  ?var1 "M"))
        ) 
        (or 
            (test (eq  ?var1 "H"))
            (exists
                (test 
                    (or
                        (eq  ?kd "10")
                        (eq  ?var1 "P")
                        (eq  ?var1 "X")
                        (eq  ?var1 "M")
                    )
                )
                (or
                    (test (eq  ?kd "11"))
                    (test (eq  ?var1 "P1"))
                    (test (eq  ?var1 "X1"))
                    (test (eq  ?var1 "M1"))
                )
            )
        ) 
        (or 
            (or 
                (test (eq  ?dd "02"))
                (test (eq  ?dd "99"))
            ) 
            (test (eq  ?kd "10"))
            (not (test (eq  ?kd "14"))) 
            (test (eq  ?var1 "M"))
        ) 
        (or 
            (or 
                (test (eq  ?k "1"))
                (test (eq  ?k "2"))
            ) 
            (test (eq  ?kd "10"))
            (not (test (eq  ?kd "14"))) 
            (test (eq  ?var1 "M"))
            (test (eq  ?kd "11"))
        ) 
    )
    =>
    )
    
     
    • Gary Riley

      Gary Riley - 2018-03-14

      Use the number of permutations caused by the or CEs to determine complexity. First, strip out anything inside the test CEs:

      (exists 
          (or 
              (test)
              (or 
                  (test)
                  (test)
              ) 
              (test)
              (test)
          ) 
          (or 
              (test)
              (test)
              (test)
              (test)
          ) 
          (or 
              (test)
              (exists
                  (test)
                  (or
                      (test)
                      (test)
                      (test)
                      (test)
                  )
              )
          ) 
          (or 
              (or 
                  (test)
                  (test)
              ) 
              (test)
              (not (test)) 
              (test)
          ) 
          (or 
              (or 
                  (test)
                  (test)
              ) 
              (test)
              (not (test)) 
              (test)
              (test)
          ) 
      )
      

      Next, collapse any or CE contained within another or CE:

      (exists 
          (or 
              (test)
              (test)
              (test) 
              (test)
              (test)
          ) 
          (or 
              (test)
              (test)
              (test)
              (test)
          ) 
          (or 
              (test)
              (exists
                  (test)
                  (or
                      (test)
                      (test)
                      (test)
                      (test)
                  )
              )
          ) 
          (or 
              (test)
              (test)
              (test)
              (not (test)) 
              (test)
          ) 
          (or 
              (test)
              (test)
              (test)
              (not (test)) 
              (test)
              (test)
          ) 
      )
      

      Next, count the number of CEs within each or CE:

      (exists 
          (or 5 CEs) 
          (or 4 CEs) 
          (or 2 CEs
              (test)
              (exists
                  (test)
                  (or 4 CEs)
              )
          ) 
          (or 5 CEs) 
          (or 6 CEs) 
      )
      

      Next, compute the number of permutations for each grouping of or CEs. The inner exists CE has 4 permutations. The outer exists CE has 1200 permutations.

      Load times become noticeable once you start exceeding 10,000 permutations. The rule at the beginning of the thread is easily generating trillions of trillions of permutations.

       

Log in to post a comment.