Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

Matching distinct facts in a rule

Help
2012-12-14
2013-01-20
  • ahmedkhalaf92
    ahmedkhalaf92
    2012-12-14

    Hi,

    Suppose I have the following fact template:

    (deftemplate student
    (slot name)
    )

    and suppose I have the following facts asserted:

    (student (name jim))
    (student (name joe))

    and suppose I have the following rule:

    (defrule some-rule
    ?fact1 <- (student (name ?n1))
    ?fact2 <- (student (name ?n2))
    =>
    ; do something
    )

    The problem is, ?fact1 and ?fact2 can point to the same fact!

    How can I prevent this to happen?

    I know I can check if the indices of the two facts are not the same, but this is tedious for a larger number of facts to match.

    Many Thanks.

     
  • Gary Riley
    Gary Riley
    2013-01-20

    There's not a non-trivial way to do this. The preferable solution would be something like:

    (defrule some-rule
       (distinct (student (name ?n1))
                 (student (name ?n2)))
       =>)
    

    Where the distinct conditional element (if it existed) requires each pattern contained within to match to a different fact or instance.

    On the LHS what you've described is the minimal way to insure the facts are distinct (note however, that you only need a single test within the LHS of the rule to determine that the facts are distinct):

    (defrule some-rule
       ?fact1 <- (student (name ?n1))
       ?fact2 <- (student (name ?n2))
       ?fact3 <- (student (name ?n3))
       ?fact4 <- (student (name ?n4))
       (test (neq ?fact1 ?fact2 ?fact3 ?fact4))
       =>)
    

    When you match in this manner, however, you'll still get multiple activations of the rule. For example if s1=student1, s2=student2, s3=student3, and s4=student4, you'll get an activation for ?fact1=s1, ?fact2=s2, ?fact3=s3, and ?fact4=s4, but also every other permutation (such as ?fact1=s4, ?fact2=s3, ?fact3=s2, and ?fact4=s1).

    If you want to iterate over each student performing an action, you're better off using the fact query functions to do this since you'll address both the issue of distinctness and the issue of a single ordering:

    (defrule some-rule
       (exists (student))
       =>
       (do-for-all-facts ((?f student)) TRUE
          (printout t ?f:name crlf)))