Menu

examples: a rule for 5 of 7 tests passing

Help
2008-01-30
2013-05-17
  • Michael Cariaso

    Michael Cariaso - 2008-01-30

    while the pyke documentation is extensive, it seems a bit light on examples. Can anyone show me a PyKE analog for this topic from the CLIPS forum?
    http://groups.google.com/group/CLIPSESG/browse_thread/thread/211d246a12fae3cb

    Short version: I need a rule that lets me ask if at least X of these Y tests pass. The tests are all simple 'is this fact true'.

     
    • Bruce Frederiksen

      Here's a way to do it with backward chaining:

      ---------- cut here ----------------
      # rules.krb
      #
      # This creates a rule base called 'rules' (filename, minus the .krb suffix).

      have_at_least:
          # This rule just provides a simplier interface to have_at_least_excluding.
          use have_at_least($n)
          when
              have_at_least_excluding($n, ())

      have_at_lease_excluding_0:
          # We always have at least 0 students!
          use have_at_least_excluding(0, $_)
          # Without a 'when' clause, this rule succeeds if the 'use' pattern can
          # be matched.

      have_at_least_excluding_n:
          # To prove whether we have at least $n students, excluding $exclude_list,
          use have_at_least_excluding($n, $exclude_list)
          when
              # Find a student
              fact.student($name)
              # That is not already in the $exclude_list
              check $name not in $exclude_list
              # And prove that there are $n - 1 students, excluding this one and
              # the ones in $exclude_list.  The pattern "($name, *$exclude_list)"
              # is a tuple whose first element is $name, with the rest of the
              # elements being the $exclude_list tuple.
              $n_1 = $n - 1
              have_at_least_excluding($n_1, ($name, *$exclude_list))

      --------- end cut ---------------

      You can run this with:

      ---------- cut here -------------
      # run.py

      import pyke

      # Add our 'student' facts.  We'll put these facts in the 'fact' fact base.
      pyke.add_universal_fact('fact', 'student', ('Alice',))
      pyke.add_universal_fact('fact', 'student', ('Bob',))
      pyke.add_universal_fact('fact', 'student', ('Charles',))
      pyke.add_universal_fact('fact', 'student', ('Dave',))

      # Load the .krb files.  Defaults to looking recursively in the current
      # directory.  Will place the compiled .py files in a (new) ./compiled_krb
      # directory.
      pyke.load()

      # Activate the 'rules' rule base.
      pyke.activate('rules')

      def have_at_least(n):
          '''
              The python function to call the pyke rule.

              >>> have_at_least(3)
              True
              >>> have_at_least(4)
              True
              >>> have_at_least(5)
              False
          '''
          try:
              pyke.prove_1('rules', 'have_at_least', (n,), 0)
              return True
          except pyke.CanNotProve:
              return False

      def test():
          import doctest
          import sys
          sys.exit(doctest.testmod()[0])

      if __name__ == "__main__":
          test()

      ------------ end cut --------------------

      Run:

         $ python run.py

      to run the doctests.  Note that it creates the ./compiled_krb/rules_bc.py the first time it is run, but not the second (unless you change the rules.krb file).

      Hope this helps!

       
      • Bruce Frederiksen

        Oops!  The sourceforge forum destroyed the indenting.  Let's try it again.  You'll have to delete the first character on each line here...

        -------------- cut here ----------------
        |# rules.krb
        |#
        |# This creates a rule base called 'rules' (filename, minus the .krb suffix).
        |
        |have_at_least:
        |    # This rule just provides a simplier interface to have_at_least_excluding.
        |    use have_at_least($n)
        |    when
        |        have_at_least_excluding($n, ())
        |
        |have_at_lease_excluding_0:
        |    # We always have at least 0 students!
        |    use have_at_least_excluding(0, $_)
        |    # Without a 'when' clause, this rule succeeds if the 'use' pattern can
        |    # be matched.
        |
        |have_at_least_excluding_n:
        |    # To prove whether we have at least $n students, excluding $exclude_list,
        |    use have_at_least_excluding($n, $exclude_list)
        |    when
        |        # Find a student
        |        fact.student($name)
        |        # That is not already in the $exclude_list
        |        check $name not in $exclude_list
        |        # And prove that there are $n - 1 students, excluding this one and
        |        # the ones in $exclude_list.  The pattern "($name, *$exclude_list)"
        |        # is a tuple whose first element is $name, with the rest of the
        |        # elements being the $exclude_list tuple.
        |        $n_1 = $n - 1
        |        have_at_least_excluding($n_1, ($name, *$exclude_list))

        --------------- second cut -------------------
        |# run.py
        |
        |import pyke
        |
        |# Add our 'student' facts.  We'll put these facts in the 'fact' fact base.
        |pyke.add_universal_fact('fact', 'student', ('Alice',))
        |pyke.add_universal_fact('fact', 'student', ('Bob',))
        |pyke.add_universal_fact('fact', 'student', ('Charles',))
        |pyke.add_universal_fact('fact', 'student', ('Dave',))
        |
        |# Load the .krb files.  Defaults to looking recursively in the current
        |# directory.  Will place the compiled .py files in a (new) ./compiled_krb
        |# directory.
        |pyke.load()
        |
        |# Activate the 'rules' rule base.
        |pyke.activate('rules')
        |
        |def have_at_least(n):
        |    '''
        |        The python function to call the pyke rule.
        |
        |        >>> have_at_least(3)
        |        True
        |        >>> have_at_least(4)
        |        True
        |        >>> have_at_least(5)
        |        False
        |    '''
        |    try:
        |        pyke.prove_1('rules', 'have_at_least', (n,), 0)
        |        return True
        |    except pyke.CanNotProve:
        |        return False
        |
        |def test():
        |    import doctest
        |    import sys
        |    sys.exit(doctest.testmod()[0])
        |
        |if __name__ == "__main__":
        |    test()

         
        • Bruce Frederiksen

          Nope that didn't work either...

          Third time's a charm (I hope)!  You'll have to pipe this through "sed 's/^/ /g'"...

          -------- cut here --------------
          # rules.krb
          #
          # This creates a rule base called 'rules' (filename, minus the .krb suffix).

          have_at_least:
          ^^^^# This rule just provides a simplier interface to have_at_least_excluding.
          ^^^^use have_at_least($n)
          ^^^^when
          ^^^^^^^^have_at_least_excluding($n, ())

          have_at_lease_excluding_0:
          ^^^^# We always have at least 0 students!
          ^^^^use have_at_least_excluding(0, $_)
          ^^^^# Without a 'when' clause, this rule succeeds if the 'use' pattern can
          ^^^^# be matched.

          have_at_least_excluding_n:
          ^^^^# To prove whether we have at least $n students, excluding $exclude_list,
          ^^^^use have_at_least_excluding($n, $exclude_list)
          ^^^^when
          ^^^^^^^^# Find a student
          ^^^^^^^^fact.student($name)
          ^^^^^^^^# That is not already in the $exclude_list
          ^^^^^^^^check $name not in $exclude_list
          ^^^^^^^^# And prove that there are $n - 1 students, excluding this one and
          ^^^^^^^^# the ones in $exclude_list.  The pattern "($name, *$exclude_list)"
          ^^^^^^^^# is a tuple whose first element is $name, with the rest of the
          ^^^^^^^^# elements being the $exclude_list tuple.
          ^^^^^^^^$n_1 = $n - 1
          ^^^^^^^^have_at_least_excluding($n_1, ($name, *$exclude_list))
          ------------------ second cut ---------------------
          # run.py

          import pyke

          # Add our 'student' facts.  We'll put these facts in the 'fact' fact base.
          pyke.add_universal_fact('fact', 'student', ('Alice',))
          pyke.add_universal_fact('fact', 'student', ('Bob',))
          pyke.add_universal_fact('fact', 'student', ('Charles',))
          pyke.add_universal_fact('fact', 'student', ('Dave',))

          # Load the .krb files.  Defaults to looking recursively in the current
          # directory.  Will place the compiled .py files in a (new) ./compiled_krb
          # directory.
          pyke.load()

          # Activate the 'rules' rule base.
          pyke.activate('rules')

          def have_at_least(n):
          ^^^^'''
          ^^^^^^^^The python function to call the pyke rule.

          ^^^^^^^^>>> have_at_least(3)
          ^^^^^^^^True
          ^^^^^^^^>>> have_at_least(4)
          ^^^^^^^^True
          ^^^^^^^^>>> have_at_least(5)
          ^^^^^^^^False
          ^^^^'''
          ^^^^try:
          ^^^^^^^^pyke.prove_1('rules', 'have_at_least', (n,), 0)
          ^^^^^^^^return True
          ^^^^except pyke.CanNotProve:
          ^^^^^^^^return False

          def test():
          ^^^^import doctest
          ^^^^import sys
          ^^^^sys.exit(doctest.testmod()[0])

          if __name__ == "__main__":
          ^^^^test()

           
    • Michael Cariaso

      Michael Cariaso - 2008-02-16

      Thanks Bruce,

      The example needed a few tweaks to work for me. I've posted the updated version at
      http://www.runblast.com/wiki/index.php?title=Pyke_example

      mike

      http://www.cariaso.com

       

Log in to post a comment.