We are working on our library to compute the results of pull expressions in Clara Rules, and we are bumping up against the fact that we can't accumulate over tokens (e.g. :and/:or).
We have a way to do it, but it seems terribly inefficient, since we'd need to add a fact for every entity+attribute in the system. Hmm, or at least the ones where the attribute can have multiple values.
@eraserhd > we are bumping up against the fact that we can’t accumulate over tokens (e.g. :and/:or). I don’t understand this part clearly enough to follow.
We would like to do, e.g. ?result <- (acc/all ?foo) :from [:and [Foo (= value ?foo) (= field ?x)] [Bar (= field ?x)]]
Is Clara good at sharing the beta network, if I have a bunch of rules that start with the same set of expressions, for example? If so, this might be a non issue.
@eraserhd Ok, I understand the accumulate part now, and the answer would be to accumulate on an intermediate fact
But perhaps, that’s what you were saying was a lot for you to explicitly include?
> Is Clara good at sharing the beta network Good at sharing hmm. I don’t know that I follow
Accumulating something like you had.
I mean, if I say (defrule one cond_1 cond_2 ... cond_10 bar => rhs)
and (defrule two cond_1 cond_2 ... cond_10 baz => rhs2)
, where cond_1 through cond_10 are identical, will the beta network contain 12 or 22 nodes?
I ask, because if so, it shouldn't be a problem for me to use intermediate facts, and copy all the preamble logic from the main rule to the sub-rules. But if it isn't the case, then there would be an explosion in the work Clara does to support this.
@eraserhd in most cases, I’d expect the cond_1 through cond_10 to be represented within the network as the same nodes - when the engine is compiled there is an attempt to node-share where possible
You could however, always write a rule that did
(defrule preamble cond_1 ... cond_10 => result-for-1-to-10)
(defrule one <use> result-for-1-to-10 bar => rhs)
(defrule two <use> result-for-1-to-10 baz => rhs)
if for some reason the nodes weren’t shared or the propagation was repeating for some reason
I’d tend to avoid long lists of conditions within the same rule though
if they are beta-graph oriented - aka doing joins
It may cause unwanted thrash I believe
if you have cond_1 ... cond_10
and cond_1
is changing often, but no change happens after cond_5
, it may still ripple through to cond_10
each time - but now that I say this, I think I’d have to look a bit more
There is at least some attempt in the engine to avoid propagating “no change”
I just can’t remember if it applies to all types of nodes
It may be good enough to mean what I just said was irrelevant though
This is for the mechanical, recursive transformation of a pull expression to clara rules in a macro, which is why it is getting complicated. Each nesting level needs the context of everything above it. Breaking out result-1-to-10 is possible, I guess, but it makes the macro harder to write.
hmm I see
OK, so I think the naive solution is actually not bad, then. Intermediate facts, and copying all the parent logic into each rule.
well, I think you can fairly reliably get node sharing
I say fairly reliable, just because there may be edge case. Node sharing is an optimization that isn’t required for “correctness”, so it may have edge cases
in most cases though, I think it works out ok
You could mess around and look at the rule network node count for your case
and see if it seems to not be duplicating nodes
by looking at the “rulebase” of the session
@eraserhd If all of the conditions up to a point are equal as in the case you describe I’d expect the nodes to be shared - if you find that that isn’t the case when inspecting the rulebase please log an issue. Regarding the avoidance of propagating “no change” I’m guessing @mikerod is referring to the suppression of changes to accumulation and negations that make no difference. So for example, if you’re finding the minimum of some numeric field on a fact type and you have [-5 0 5] already and a new fact with a value of 10 comes in, a min accumulator shouldn’t trigger any downstream work. There are similar optimizations on negation nodes. If you’re interested in the specifics see https://github.com/cerner/clara-rules/issues/182 for accumulators and https://github.com/cerner/clara-rules/issues/231 for negations. Any questions feel free to ask, I’m headed to bed for tonight though. 🙂