clara

http://www.clara-rules.org/
eraserhd 2018-11-01T14:21:31.055Z

OK, so we've just found something really weird with accumulators: retract-fn is never used, though documented in acc/accum.

eraserhd 2018-11-01T14:21:47.055400Z

Because retract-fn does not appear in the Accumulator record.

eraserhd 2018-11-01T14:21:57.055700Z

I'm going to guess this is not how it's supposed to work?

2018-11-01T14:35:42.056400Z

@eraserhd odd that it isn’t on the record definition, not sure I know why there, but it is called when provided (well expected to be)

2018-11-01T14:35:51.056700Z

do you have a custom accumulator you are trying to work with?

2018-11-01T14:36:09.057300Z

or did you try to add this to the existing acc/accum

eraserhd 2018-11-01T14:36:36.058Z

We are getting ready to build an accumulator with accum, and I was looking for how to extract those functions again so we can test drive it, and I found that retract-fn gets lost.

eraserhd 2018-11-01T14:38:50.058600Z

uhhh, whoa. I had no idea that you could add arbitrary fields to a defrecord with map->X.

2018-11-01T14:39:13.058900Z

you are using clara.rules.accumulators/accum to build an accumulator?

eraserhd 2018-11-01T14:39:32.059400Z

No, doing nothing but research at this point.

2018-11-01T14:40:00.060100Z

yeah, defrecord in clj is often considered more of a perf optimization for a common group of fields you access, they work as regular maps in many cases, and having any number of keys is one of them. the keys not defined on the record are just accessed slower on the impl side

2018-11-01T14:40:08.060300Z

and you can’t reflect for them etc

2018-11-01T14:40:32.060600Z

clara.rules.accumulators/accum supports passing the :retract-fn in

2018-11-01T14:40:58.060900Z

have to be a bit careful on how you do retraction though if I recall correct

2018-11-01T14:41:13.061300Z

if you don’t provide one, Clara will default to rebuilding things minus the facts retracted

2018-11-01T14:41:31.061700Z

:retract-fn is meant for when you know how to more efficiently remove a retracted fact from your reduced structure

2018-11-01T14:42:30.062300Z

If you had an example situation where you think :retract-fn wasn’t used though, that’d be easier to look at and walk through

2018-11-01T14:43:58.062600Z

ohhhh, there may be cases where it isn’t used at all

2018-11-01T14:44:05.062800Z

checking, I’m forgetting things

eraserhd 2018-11-01T14:44:57.063700Z

We have the ability to do more efficient retraction and combining, so we're writing a custom accumulator to get around the thrashing from yesterday. It also allows us to get rid of some intermediate facts that are frequently retracted.

2018-11-01T14:47:48.064100Z

when you use the accumulator

2018-11-01T14:47:52.064300Z

what sort of form does it have

2018-11-01T14:48:08.064700Z

[?acc <- custom-acc :from [<this part>]]

2018-11-01T14:49:03.065600Z

Are you using some joining conditions there like [X (test-something ?y z)], or just [X], or equality based join, like [X (= ?y z)]?

2018-11-01T14:49:32.066400Z

The point is there are 2 variants of accumulate nodes in the rules engine, one for the simpler join cases using = or no joining at all

2018-11-01T14:49:50.066900Z

that one is optimized for those cases because they can be done better

2018-11-01T14:50:08.067300Z

the other variant handles the rest, which are arbitrary other joining criteria

2018-11-01T14:51:38.068700Z

At this point, if I recall all the impl details correctly, providing your own :retract-fn is only a potential perf optimization. If you use the optimized, easier variant of an accumulator, it will be used, otherwise, it is ignored because it can’t be used from within the more generalized case

2018-11-01T14:51:57.069100Z

or really, it can’t be used to help in the more general case, it would only be slower

ProbablyJody 2018-11-01T15:10:23.071600Z

Does the accumulator maintain the reduced value before being passed to the :convert-return-fn for the purposes of handing it to the :retract-fn?

ProbablyJody 2018-11-01T15:10:46.071900Z

(assuming both are defined)

ProbablyJody 2018-11-01T15:12:11.072900Z

To rephrase, should the :retract-fn expect the output of the :reduce-fn or the :convert-return-fn?

2018-11-01T15:18:22.073300Z

@jody > To rephrase, should the :retract-fn expect the output of the :reduce-fn or the :convert-return-fn? It should expect the output of :reduce-fn

2018-11-01T15:19:06.074Z

it’s part of the “reducing phase”, :convert-return-fn is only done after everything else

2018-11-01T15:19:49.074700Z

Under the current implementation (would have to double check), I don’t think working memory for the accumulate node ever maintains the :convert-return-fn value actually, just the :reduce-fn/`:retract-fn` returned value state

2018-11-01T15:20:35.075200Z

the reason is that the :convert-return-fn value is not considered useful to use for any subsequent changes

2018-11-01T15:20:44.075500Z

the reducing state is

eraserhd 2018-11-01T19:31:03.077100Z

Is it possible for an accumulator to get a net negative, e.g. more retractions than insertions. I'm wondering because maybe this is implied by the "combine" function?

ProbablyJody 2018-11-01T20:03:28.078800Z

I believe the combine function is just a performance optimizer for the reduce phase. I’d expect a net-negative to represent a bug in truth maintenance. I might be mis-understanding the question though.

eraserhd 2018-11-01T20:48:44.080600Z

I mean, obviously, if you combine all batches, you can't have more retractions than insertions. But depending on how you are batching, you could have one batch with, say three insertions and another batch with two retractions. That would mean that two retractions were applied to the initial value in that case.

eraserhd 2018-11-01T20:50:57.082300Z

Alternately, you could say that Clara enforces that retractions occur in the same batch as insertions. I'm not sure how it could, though I don't understand how this is being called.

eraserhd 2018-11-01T20:56:34.083700Z

I guess one possibility is that Clara only uses this for joins where each reduced value is a selection of attributes, such that insertions and retractions are always sorted into the same batch. That actually makes the most sense.

2018-11-01T21:39:58.084400Z

@eraserhd when retracting facts, with respect to an accumulator, the accumulator is only re-ran on facts that were retracted and were found to have previous matches

2018-11-01T21:40:26.085Z

so the facts retracted and processed by an accumulator, should only be facts that were processed by the same accumulator before, when they were inserted

2018-11-01T21:41:02.085600Z

if you batched up retracts of facts that were not inserted yet, the accumulator wouldn’t need to retract anything

2018-11-01T21:41:22.085800Z

and it wouldn’t try

2018-11-01T21:41:57.086100Z

facts are considered the “same” via =

2018-11-01T21:42:05.086300Z

but respecting cardinality of them

2018-11-01T21:42:21.086600Z

ie insert 2 = objects, retract 1, you still have 1 left

2018-11-01T21:42:51.087300Z

if the retracted is identical? to 1 of = instances, that’d like be the one removed - but I think that’s more due to perf optimizations than anything

eraserhd 2018-11-01T22:12:47.087700Z

@mikerod OK, that makes sense. Thanks!