Fork me on GitHub
#clara
<
2018-11-02
>
wparker11:11:12

@eraserhd Agreed with @mikerod that the only facts which will be retracted are those that were provided before. Regarding the inefficiencies of accumulation with non-hash join conditions, I think that’s a more general problem than the :retract-fn actually. For example, I believe when a new fact matching the accumulation condition is added the previous facts will have the accumulator rerun on them in their entirety, whereas the simple case with no joins or only-hash based joins will store the previous result and add onto it. Contrast the following in AccumulateNode, the simple case: https://github.com/cerner/clara-rules/blob/master/src/main/clojure/clara/rules/engine.cljc#L1156 with the equivalent in AccumulateWithJoinFilterNode, the more complex case: https://github.com/cerner/clara-rules/blob/master/src/main/clojure/clara/rules/engine.cljc#L1525

wparker11:11:11

The tricky thing is that Clara’s memory is set up to store the elements (facts coming into the current condition) and tokens (facts from ancestor conditions) separately, but in the case of these complex accumulator joins you’d really want to store them together for maximum efficiency. I don’t think there is any fundamental reason why this couldn’t be done though, it

wparker11:11:40

would just be the work to do it and get it right/performant, plus durability changes probably if the memory structure changed

wparker12:11:22

Clara does avoid downstream thrash from the complex accumulators still when the result didn’t actually change - see https://github.com/cerner/clara-rules/issues/182 and the changes made there - but the internal calculation has some room for improvement perf-wise

wparker12:11:07

If you want to understand how the accumulator logic works, some basic terms:

wparker12:11:26

-right-activate: new facts matching the condition at hand

wparker12:11:46

-right-retract: removal of facts matching the condition at hand

wparker12:11:04

-left-activate: facts were added to ancestor conditions and need to be passed down the network

wparker12:11:39

left-retract: facts were removed from ancestor conditions and need to be passed down the network

wparker12:11:10

AccumulateNode - simple no-condition or hash-join-only accumulation conditions

wparker12:11:56

AccumulateWithjoinFilterNode - accumulation condition with arbitrary filter logic taking facts from ancestor conditions as input

wparker12:11:33

probably the best source of truth there is the code, fortunately it is a well commented area imo though i’m biased as i wrote many of those comments

wparker12:11:15

to be clear: when I say to understand how it works, i mean the algorithms at play - the docs should be sufficient for the behavior and if they’re not they should be improved

wparker12:11:28

hopefully this helps

wparker12:11:06

if you’re trying to get a case with complex accumulator joins to perform better, frankly my first reaction would be to use salience most likely

wparker12:11:02

if you’re using truth maintenance without side effects, the salience shouldn’t impact actual behavior so it doesn’t make the code harder to read/understand in that respect

eraserhd13:11:12

@wparker thanks! This is all good info.

eraserhd13:11:39

I'm guessing, in [Foo (= ?a a)] [?acc <- (acc/whatever) [Bar (= ?a a)]], Foo would be left and Bar would be right?

mikerod15:11:35

@eraserhd basically yes

mikerod15:11:47

left is the matched-token-so-far in a rule LHS

mikerod15:11:13

tokens consist of all facts involved in a match

mikerod15:11:26

In a LHS [A] [B] [C] if we were looking at the network node for the [C] condition, incoming C facts would be right-activate, left-activate to this node would be matched up A+`B`s - represented as a “token”

wparker17:11:35

And for the [B] condition, incoming B facts would be right-activate, left-activate would be tokens passed down from the [A] condition. For the [A] condition the right-activate would be incoming A facts, the left-activate would basically be a dummy placeholder. Does that make sense?