Fork me on GitHub
#clara
<
2018-11-01
>
eraserhd14:11:31

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

eraserhd14:11:47

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

eraserhd14:11:57

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

mikerod14:11:42

@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)

mikerod14:11:51

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

mikerod14:11:09

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

eraserhd14:11:36

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.

eraserhd14:11:50

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

mikerod14:11:13

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

eraserhd14:11:32

No, doing nothing but research at this point.

mikerod14:11:00

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

mikerod14:11:08

and you can’t reflect for them etc

mikerod14:11:32

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

mikerod14:11:58

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

mikerod14:11:13

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

mikerod14:11:31

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

mikerod14:11:30

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

mikerod14:11:58

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

mikerod14:11:05

checking, I’m forgetting things

eraserhd14:11:57

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.

mikerod14:11:48

when you use the accumulator

mikerod14:11:52

what sort of form does it have

mikerod14:11:08

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

mikerod14:11:03

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

mikerod14:11:32

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

mikerod14:11:50

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

mikerod14:11:08

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

mikerod14:11:38

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

mikerod14:11:57

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

ProbablyJody15:11:23

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?

ProbablyJody15:11:46

(assuming both are defined)

ProbablyJody15:11:11

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

mikerod15:11:22

@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

mikerod15:11:06

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

mikerod15:11:49

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

mikerod15:11:35

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

mikerod15:11:44

the reducing state is

eraserhd19:11:03

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?

ProbablyJody20:11:28

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.

eraserhd20:11:44

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.

eraserhd20:11:57

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.

eraserhd20:11:34

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.

mikerod21:11:58

@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

mikerod21:11:26

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

mikerod21:11:02

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

mikerod21:11:22

and it wouldn’t try

mikerod21:11:57

facts are considered the “same” via =

mikerod21:11:05

but respecting cardinality of them

mikerod21:11:21

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

mikerod21:11:51

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

eraserhd22:11:47

@mikerod OK, that makes sense. Thanks!