[EMAIL PROTECTED] writes:
> The message
>
> "Message: Bad index 1 in call to get() on this vector:
> (MAIN::__query-trigger-equivs-of-type segment-side). "
>
> looks as though it means that there's a mismatch between the number of
> arguments you supply to a run-query call and the number of external
> variables the query "equivs-of-type" is declared to accept; in
> particular, your query may have been declared to take at least two
> variables, and you're calling it with only one argument, whose value
> is "segment-side".
>
> It also looks as though you're executing the same query many times
> recursively, which won't work. I've spoken up several times on this
> mailing list regarding the evils of using queries on rule LHSs;
> because it appears to have some genuine utility, I haven't done
> anything to prevent it. But the awe-inspiring stack trace below
> suggests that you've got a query which, when run on a LHS, causes a
> few more rules to fire, which assert facts, which cause the query to
> fire again, etc. This is simply not going to work. Use queries on rule
> LHS very sparingly, and then only in situations where this kind of
> cascade isn't going to happen. It's quite possible that the error
> you're seeing is occurring just because the Rete network is getting
> all fouled up by this recursive querying.
It occurred to me that I could move the test performed by that query
to the right hand side of the rule and only conditionally make the
associated assertions when the rule fires. I don't know if I've
defined the query properly though. I'm still confused about when to
prefix a variable with a dollar sign.
;;; Fact ordering test to prevent redundant firing of symetric
;;; rules.
(deffunction fact-ordering-predicate (?fact1 ?fact2)
(< (call ?fact1 getFactId)
(call ?fact2 getFactId)))
(deftemplate equiv
(slot type)
(multislot set))
;;; Testing equivalence
;;; We either need the EQ test or need to assert an equivalence for
;;; each single object, to obtain reflexivity.
; (or (test (eq ?thing1 ?thing2))
; (and (equiv (type ?type) (set $?set))
; (test (and (member$ ?thing1 $?set)
; (member$ ?thing2 $?set)))))
(defquery equiv-p
;; Is there an equiv fact containing all the specified things?
(declare (variables ?type ?things))
(equiv (type ?type) (set $?set))
(test (= (length$ (intersection$ ?things $?set))
(length$ $?things))))
(deffunction assert-equiv (?type $?items)
;; Assert that the specified items are equivalent to one another.
(bind ?new-set (union$ $?items)) ; remove duplicates
;; but only do so if we didn't already know they were equivalent.
(if (and (> (length$ ?new-set) 1)
;; does this work?
(= 0 (count-query-results equiv-p ?type ?new-set)))
then
(assert (equiv (type ?type)
(set ?new-set)))))
(defrule equiv-equiv-merge
(declare (salience 100))
?fact1 <- (equiv (type ?type) (set $?set1))
?fact2 <- (equiv (type ?type) (set $?set2))
(test (fact-ordering-predicate ?fact1 ?fact2))
(test (> (length$ (intersection$ $?set1 $?set2)) 0))
(test (> (length$ (union$ $?set1 $?set2))
(max (length$ $?set1) (length$ $?set2))))
=>
(retract ?fact1)
(retract ?fact2)
(assert (equiv (type ?type)
(set (union$ $?set1 $?set2)))))
The function assert-equiv is called wherever an equiv is to be
asserted. It checks to make sure such an equiv doesn't already exist
before asserting one. I need to do this because otherwise I get a
rule firing loop.
The salience declaration is to ensure that equiv-equiv-merge has
priority over all other rules. I'm not sure this is having the effect
I expect though. Would the retractions in the right hand side prevent
already triggered rules from firing?
I'd like to keep doing equivalence the way I am because it makes it
easy when debugging the rules to see what things have been determined
to be the same. I fear that I might have to change my approach though
if I can't get this working properly. That would mean alot of editing
since there doesn't appear to be a way to abstract the assertions and
tests away from the representation.
--------------------------------------------------------------------
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]
--------------------------------------------------------------------