OR conditional element behavior

vranoch
2012-01-04
2013-05-28
  • vranoch
    vranoch
    2012-01-04

    Hello,

    After quite a long time dealing with Clips I met a surprising behavior (which I finally found in the Basic guide as probably being a feature) ;-)

    let's have facts A and B and an action which should be performed IF A or B exist. Natural understanding is that the action should be performed if:
    -  A is present,
    - B is present,
    - both A and B are present
    and it should be performed ONLY ONCE if at all.

    However, CLIPS behavior in the case that BOTH A and B exist is that action is performed twice with identical facts:

    (deffacts xxx
       (SAD H "AE")
       (SAD G "AE")
    )

    (defrule condition
    (SAD H ?x)
    (SAD G ?y)
    (or (test (eq ?x "AE")) (test (eq ?y "AE")))
    =>
    (printout t "FIRED " crlf)
    )


    (watch facts)
    (watch activations)
    (load k)
    $*
    TRUE
    (reset)
    <== f-0     (initial-fact)
    ==> f-0     (initial-fact)
    ==> f-1     (SAD H "AE")
    ==> f-2     (SAD G "AE")
    ==> Activation 0      condition: f-1,f-2
    ==> Activation 0      condition: f-1,f-2
    (run)
    FIRED
    FIRED

    After the (reset) command, the "conditions" rule is activated twice with identical combinations of facts (and consequently twice fired).

    My questions are:

    1) is there any correct way to get the "natural" behavior? 

    2) If not, can it be achieved when executing the rule to scan the agenda (GetNextActivation) and find and delete (DeleteActivation) any other activations with identical list of partial matches as currently fired rule (further questions are:

    3) how to determine list of partial matches of currently fired rule

    4) how to compare it to agenda enties - is GetActivationPPForm enough)?

    Thanks a lot for a hint

    Vranoch

     
  • Gary Riley
    Gary Riley
    2012-01-05

    Use a single test conditional function that calls the 'or' function rather than an 'or' conditional element with multiple test conditional elements. The 'or' conditional element works by splitting a single rule into multiple rules and typically you'd have at least one conditional element within it that matches a fact or instance. It's a syntactic shortcut that can be quite convenient, but in this case it's not what you want to do.

    (defrule condition
        (SAD H ?x)
        (SAD G ?y)
        (test (or (eq ?x "AE") (eq ?y "AE")))
    =>
        (printout t "FIRED " crlf)
    )
    
     
  • vranoch
    vranoch
    2012-01-23

    Thanks Gary, this works. However, what is a problem in nesting (test ) functions (e.g.

     (test (and (test (< 1 5)) (test (>20 10))))
    

    ) ? It says that "test" function is not defined in this case.
    I know that the nested (test ) is not necessary in this case but my CLIPS code is generated and it is not so easy to change the generator.

    thanks Vranoch

     
  • Gary Riley
    Gary Riley
    2012-01-29

    Predefine a test deffunction that uses it's input argument as it's output value:

    CLIPS> (deffunction test (?x) ?x)
    CLIPS> 
    (defrule example
       (test (and (test (< 1 5)) (test (> 20 10))))
       =>)
    CLIPS> (reset)
    CLIPS> (agenda)
    0      example: *
    For a total of 1 activation.
    CLIPS>
    
     
  • vranoch
    vranoch
    2012-01-30

    Yes, that helped, but only for a while. I sometimes have to combine standard CEs with quantifiers (exists ):

    (deffacts xxx
       (SAD H "AE")
       (SAD G "AE")
       (SAD X 1 1)
       (SAD X 2 10)
       
    )
    (deffunction test (?x) ?x)
    (defrule condition
        (SAD H ?x)
        (SAD G ?y)
        (test (or (test (eq ?x "AE")) (exists (SAD X ?ix ?val) (> ?val 5))))
    =>
        (printout t "FIRED " crlf)
    )
    

    … again, it says

    [EXPRNPSR3] Missing function declaration for exists.
    

    is there any way how to work this around? And what is the problem, that some standard functions are not visible within the (test ) function?

    thanks Vranoch 

     
  • Gary Riley
    Gary Riley
    2012-01-31

    test/exists/and/or/not are conditional elements (CEs) that have a specific purpose when used on the LHS of a rule.  and/or/not also happen to be functions which can be used in certain places on the LHS of a rule as well as the RHS of a rule and in deffunctions, defmethods, defmessage-handlers, and other constructs. Within a test CE, you can place a function call including other nested function calls. The test and exists conditional elements are not functions so they can't be placed within the test CE. For the test CE you can get around this restriction by defining a deffunction called test, but there is no way to do this for the exists CE without rewriting the CLIPS parser to handle this syntax. In both examples you've listed, the rule would be syntactically correct if you just removed the outermost test CE. In both cases, the inner and/or function would then be interpreted as an and/or CE. Your other option is to generate valid syntax.

     
  • vranoch
    vranoch
    2012-01-31

    Thanks for explanation, but when I remove the outermost OR, I get to the initial situation (multiple firing of the rule). I can of course modify my generator, but I have to find out, what should be generated. Can You advice me, how to correctly (i.e. syntactically and semantically - firing only once) rewrite the following condition which I can't omit?

    (defrule condition
        (SAD H ?x)
        (SAD G ?y)
        (or (test (or (eq ?x "AE") (eq ?y "AE"))) (exists (SAD X ?ix ?val) (test (> ?val 5))))
    =>
        (printout t "FIRED " crlf)
    )
    

    I already tried many combinations but I did not succeed  so far.
    thanks a lot Vranoch

     
  • Gary Riley
    Gary Riley
    2012-02-02

    (defrule condition
       (SAI H ?x)
       (SAD G ?y)
       (or (and (not (and (SAD X ?ix ?val) (test (> ?val 5))))
                (test (or (eq ?x "AE") (eq ?y "AE"))))
           (exists (SAD X ?ix ?val) (test (> ?val 5))))
    =>
    (printout t "FIRED " crlf)
    )

     
    • Christine DG
      Christine DG
      2013-05-28

      A little error :

      (defrule condition
      (SAD H ?x) ; not SAI !
      (SAD G ?y)
      (or (and (not (and (SAD X ?ix ?val) (test (> ?val 5))))
      (test (or (eq ?x "AE") (eq ?y "AE"))))
      (exists (SAD X ?ix ?val) (test (> ?val 5))))
      =>
      (printout t "FIRED " crlf)
      )