Menu

NOTANY clause does not work as advertised

Help
2014-12-25
2014-12-25
  • westofpluto

    westofpluto - 2014-12-25

    I am trying out some forward chaining rules on some simple family relations, and it looks to me like NOTANY does not work the way one would think it would work. I assumed that the following clause only succeeds if none of the embedded premises are true:

    notany
        premise1
        premise2
        premise3
    

    However, this does not seem to be the case. It appears that notany works fine to negate a single premise but cannot handle multiple premises properly. For example, the following is my knowledgebase and rulebase. Even though the KB asserts dead(jon), the rulebase still asserts cousins_of_living_uncles(marc, will) which is wrong.

    What am I doing wrong? Or is this a bug?

    ###################################################################
    # Knowledge Base for dummy test
    #
    ###################################################################
    
    dead(jon)
    son_of(marc, william_david)
    son_of(william_david, berle)
    son_of(berle, william_frankenberger)
    son_of(william_frankenberger, david_moser)
    son_of(will, jon)
    son_of(jon, berle)
    
    ##############################################################
    # dummy rules for testing
    ##############################################################
    
    direct_father_son
        foreach
            dummy.son_of($son, $father)
        assert
            dummy.father_son($father, $son, ())
    
    grand_father_son
        foreach
            dummy.father_son($father, $grand_son, ())
            dummy.father_son($grand_father, $father, ())
        assert
            dummy.father_son($grand_father, $grand_son, (grand))
    
    great_grand_father_son
        foreach
            dummy.father_son($father, $gg_son, ())
            dummy.father_son($gg_father, $father, ($prefix1, *$rest_prefixes))
        assert
            dummy.father_son($gg_father, $gg_son,
                                (great, $prefix1, *$rest_prefixes))
    
    cousins_of_living_uncles
        foreach
            dummy.son_of($son1, $father1)
            dummy.son_of($son2, $father2)
            dummy.son_of($father1, $grandfather)
            dummy.son_of($father2, $grandfather)
            notany
                dummy.dead($father1)
                dummy.dead($father2)
            check $father1 != $father2
        assert
            dummy.cousins_of_living_uncles($son1, $son2)
    

    NOTE: If instead of

    notany
        dummy.dead($father1)
        dummy.dead($father2)
    

    I use

    notany
        dummy.dead($father1)
    notany
        dummy.dead($father2)
    

    then it seems to work for this example. But it seems to me to be highly misleading that notany only works properly with one embedded premise!

    What am I missing here?

     
  • westofpluto

    westofpluto - 2014-12-25

    Ok this really looks like a bug. The notany premise really behaves instead like a "notall". In other words, at least in forward chainging, notall will only succeed if ALL of the embedded premises fail. One would think from the ord "notall" that it would only take one embedded premise for the whole thing to fail, but in fact it takes ALL the embedded premises to fail! You can see this in my example by setting both dead(jon) and dead(william_david). That is the only way to make dummy.cousins_of_living_uncles not get asserted.

     
    • Bruce Frederiksen

      No, it is working as advertised
      http://pyke.sourceforge.net/pyke_syntax/krb_syntax/compound_premise.html#notany-premise.
      It only succeeds if there is not any solution to the nested premises (which
      would be AND-ed, as lists of premises always are). Thus there is not any
      solution to:

      dummy.dead($father1) AND dummy.dead($father2)

      Since a solution requires proving both premises simultaneously, failing
      to prove either premise would suffice for the notany to succeed. By
      "simultaneously", Pyke will backtrack from the second premise back to the
      first to look for all combinations of solutions before it declares the pair
      un-provable. Thus, not any of the possible combinations succeed.

      As you've already pointed out; if you want to check that both premises fail
      independently of each other (i.e., neither succeeds by itself), you should
      use two independent notany clauses. Then the two notany clauses would be
      AND-ed: (notany dummy.dead($father1)) AND (notany dummy.dead($father2)).

      Here is an example where notany requires the use of multiple premises. I
      want to produce sons that have no brothers:

      only_son
      foreach
      dummy.son_of($son, $father)
      notany
      dummy.son_of($brother, $father)
      check $son != $brother
      assert
      dummy.only_son($son, $father)

      Hope this helps!

      -Bruce

      On Wed, Dec 24, 2014 at 7:20 PM, westofpluto westofpluto@users.sf.net
      wrote:

      Ok this really looks like a bug. The notany premise really behaves instead
      like a "notall". In other words, at least in forward chainging, notall will
      only succeed if ALL of the embedded premises fail. One would think from the
      ord "notall" that it would only take one embedded premise for the whole
      thing to fail, but in fact it takes ALL the embedded premises to fail! You
      can see this in my example by setting both dead(jon) and
      dead(william_david). That is the only way to make
      dummy.cousins_of_living_uncles not get asserted.


      NOTANY clause does not work as advertised
      https://sourceforge.net/p/pyke/discussion/744447/thread/ea5fc057/?limit=25#e5a3


      Sent from sourceforge.net because you indicated interest in
      https://sourceforge.net/p/pyke/discussion/744447/

      To unsubscribe from further messages, please visit
      https://sourceforge.net/auth/subscriptions/

       
  • westofpluto

    westofpluto - 2014-12-25

    Well, ok, maybe I understand it now. The word 'notany' really refers to 'not any variable binding will make the following premise (or premises) true'. Any set of embedded premises in a notany clause will be AND-ed together to determine the overall truth or falsehood of the embedded set. So having an embedded set of premises for notany really means 'no variable bindings will make this embedded set all true.' So, to see if any premise (ie one or more) from a given set of premises is true, and fail if that is the case, one really needs to specify notany for each premise in the set one at a time.

    Did I get this right? That seems to be the way it actually works in my tests.

     
    • Bruce Frederiksen

      On Wed, Dec 24, 2014 at 7:37 PM, westofpluto westofpluto@users.sf.net
      wrote:

      Well, ok, maybe I understand it now. The word 'notany' really refers to
      'not any variable binding will make the following premise (or premises)
      true'. Any set of embedded premises in a notany clause will be AND-ed
      together to determine the overall truth or falsehood of the embedded set.
      So having an embedded set of premises for notany really means 'no variable
      bindings will make this embedded set all true.' So, to see if any premise
      (ie one or more) from a given set of premises is true, and fail if that is
      the case, one really needs to specify notany for each premise in the set
      one at a time.

      Did I get this right? That seems to be the way it actually works in my
      tests.

      That is right. My prior email and your here crossed paths...

       

Log in to post a comment.