> The difference is that the invisible (not) CE for this rule is
> different, because it specifies the exact subgoal2's it can generate -
> i.e., it will only be activated/deactivated with regard to the exact
> facts (need-subgoal2 bird) or (need-subgoal2 dog) whereas your other rules would
> also fire for (need-subgoal2 chicken), even though neither of them
> could cons up a chicken even if they wanted to. The bogus subgoal2
> thus generated could possibly block a desired one from being
> asserted. Again, use ppdefrule to see the difference.

Okay, I see this, but are we agreed that even this reformulation
doesn't solve my problem?

What happenned here was my misunderstanding of something in
the manual, viz. the placement of 'nil' in certain slots in the
Jess-generated (need-X) fact. As I realize now, and as is
the only sensible thing, Jess puts 'nil' in any slot that is not
yet bound, but it uses any already bound values as they appear in
the LHS that triggered the backchaining.

Looking at the ppdefrule, or just thinking clearly about the documentation,
would have made this obvious. However, for the benefit of those of us 
who read the manual in a bleary-eyed state at 3am after a long day of 
hacking, maybe it would be good to state this explicitly <g>.
(Something like: "Jess places a 'nil' in those slots that are not 
currently bound..." or something like that). 

See, my misinterpretation (with reasoning only possible at 3am)
was along the lines of: "Okay, Jess generates a need-X fact and
it sticks 'nil' in the fact's slots; so there must not be
any relationship between the values of those slots in the fact
that the rule (with need-X on the LHS) asserts, and the need-X
condition itself. Weird, yes, but maybe it was convenient to
do it that way." 

Sigh. My mind is capable of extraordinary flights sometimes.


> More or less, but there is a subtle difference. It's perfectly fine to
> have 27 rules that all respond to (need-subgoal2 ?). But if one of
> them sees (need-subgoal2 chicken) it's buggy if it asserts (subgoal2
> cat); this is what's wrong with boath ground3 and ground4. They need
> to be sure to assert only the fact that was requested. Alternatively,
> the 27 cases can only match specific need-subgoal2 facts, and again,
> can thereby do the right thing as well. Do you understand what I'm
> saying?

I do. You're saying that the correct way to express the "ground"
cases is to enumerate them in the (need-X ...) CE. From a Prolog
point of view this seems strange, but it is a consequence of
the mechanism that uses a LHS CE as the backchaining flag. I'm
okay with that.

But I'm still confused about the role of the 'nil's, and their
relation to the automatically generated (not...) CE.

My revised understanding is that a condition of the form "(need-X nil)" 
is intended to indicate the need for a fact with head X and some (any)
value in the next slot.

If that interpretation is correct, then what I meant to say was:

(do-backward-chaining the-goal)
(do-backward-chaining subgoal1)
(do-backward-chaining subgoal2)
 
(defrule main 
        (the-goal ?a) 
=>
        (printout t "You won!" crlf) 
) 
 
 
(defrule support 
        (need-the-goal nil)
        (subgoal1 ?animal) 
        (subgoal2 ?animal) 
=> 
        (the-goal ?animal) 
) 
 
(defrule ground1
        (need-subgoal1 nil)
=>
        (assert (subgoal1 bird))
)
 
(defrule ground2 
        (need-subgoal1 nil)
=> 
        (assert (subgoal1 cat ))
)
 
(defrule ground3
        (need-subgoal2 nil)
=>
        (assert (subgoal2 bird))
)
 
(defrule ground4 
        (need-subgoal2 nil)
=>
        (assert (subgoal2 dog))
)

But note that in this case, the automatically added 'not' CE
is of the form (for example)

        (not (need-subgoal1 nil))

which doesn't serve the purpose of ensuring only one firing:

Jess> (reset)
 ==> f-0 (initial-fact)
 ==> f-1 (need-the-goal nil)
 ==> f-2 (need-subgoal1 nil)
==> Activation: ground1 :  f-2,
==> Activation: ground2 :  f-2,
TRUE
Jess> (run)
FIRE 1 ground2 f-2,
 ==> f-3 (subgoal1 cat)
 ==> f-4 (need-subgoal2 cat)
FIRE 2 ground1 f-2,
 ==> f-5 (subgoal1 bird)
 ==> f-6 (need-subgoal2 bird)
2
Jess> 

Plus, the chaining to rules ground3 and ground4 doesn't occur.

Similarly, if I use the formulation you suggested, namely:

(defrule main
        (the-goal ?a)
=>
        (printout t "You won!" crlf)
)

(defrule support
        (need-the-goal ?animal)
        (subgoal1 ?animal)
        (subgoal2 ?animal)
=>
        (the-goal ?animal)
)
 
(defrule ground1and2
        (need-subgoal1 ?x&bird|cat)
=>
        (assert (subgoal1 ?x))
)
 
(defrule ground3and4
        (need-subgoal2 ?x&bird|dog)
=>
        (assert (subgoal2 ?x))
)
 
the following (nothing) happens:

Jess> (reset)
 ==> f-0 (initial-fact)
 ==> f-1 (need-the-goal nil)
 ==> f-2 (need-subgoal1 nil)
TRUE
Jess> (run)
0

So I remain confused about the nils.

(None of which has anything to do with a way of providing backtracking,
but I want to make sure I understand the way backchaining currently
works.)

Sidney


Sidney Bailin
Knowledge Evolution, Inc.

 
---------------------------------------------------------------------
To unsubscribe, send the words 'unsubscribe jess-users [EMAIL PROTECTED]'
in the BODY of a message to [EMAIL PROTECTED], NOT to the
list (use your own address!) List problems? Notify [EMAIL PROTECTED]
---------------------------------------------------------------------

Reply via email to