clara

http://www.clara-rules.org/
jdt 2018-05-23T15:51:32.000916Z

Hello all, I've been trying a bit of clara-rules to assess it for a project. I'm having some trouble with with-tracing though.

jdt 2018-05-23T15:52:13.000803Z

@dave.tenny uploaded a file: https://clojurians.slack.com/files/U7SGKB4LF/FAVQH9N22/-.clj

jdt 2018-05-23T15:52:54.000342Z

If I omit the with-tracing call fire-rules does its work. If I add with-tracing before it, fire-rules no longer works (none of my rules are fired).

jdt 2018-05-23T15:53:18.000763Z

If I move with-tracing before (insert ...) I get lots of traces.

jdt 2018-05-23T15:53:42.000277Z

What am I doing wrong?

jdt 2018-05-23T15:54:04.000677Z

I'm using [com.cerner/clara-rules "0.18.0"]

jdt 2018-05-23T15:54:14.000915Z

and clojure 1.9

jdt 2018-05-23T15:55:11.000365Z

I don't want to trace the rete activity on the initial insert, just the activities of fire-rules and the working memory alterations there.

2018-05-23T17:11:59.000771Z

@dave.tenny it’s an interesting point you bring up, but I don’t think it really makes sense to only “partially” have with-tracing enabled

2018-05-23T17:12:22.000737Z

All session interactions prior to fire-rules are susceptible to lazy evaluation and batching.

2018-05-23T17:12:52.000488Z

In general, I’d stress to not rely on any stateful information of a session that has had inserts/retracts performed on it, but no fire-rules

jdt 2018-05-23T17:13:19.000521Z

Heh, not sure I was trying to make a point. I didn't understand why fire-rules didn't work based on the placement of with-tracing. Since my rules weren't firing.

2018-05-23T17:13:22.000091Z

I’d actually rather it be the case that the API threw an exception if you tried to query or do something like with-tracing when it was in an inconsistent/lazy/batched state prior to fire-rules

jdt 2018-05-23T17:13:55.000781Z

Naively (since I am naive here), I just figured my session would be upgraded to do tracing.

2018-05-23T17:13:58.000259Z

It’s an interesting point regarding the limitations of with-tracing and lazy/batched insert/retract behavior I meant

2018-05-23T17:14:31.000655Z

I certainly haven’t dug into details to diagnose your specific issue, but I’d imaging the with-tracing added late, after the insert missed some listener information it needed

jdt 2018-05-23T17:14:33.000119Z

So how should I be using with-tracing here?

2018-05-23T17:14:58.000163Z

Only add it when you have a session that doesn’t have insert, insert-all, or retract calls possibly still pending on it

2018-05-23T17:15:10.000454Z

so either (a) right after your mk-session, or (b) right after a fire-rules

jdt 2018-05-23T17:15:50.000642Z

I'm doing insert! and retract! in my rule RHS's, but but the only insert was as shown, before the with-tracing call.

2018-05-23T17:15:53.000482Z

but you won’t get tracing “only for the fire-rules actions that took place, you’ll get a complete picture, you can looking into tracing details to find out specific things, like facts inserted due to rules firing etc (at least to some degree)

2018-05-23T17:18:49.000282Z

@dave.tenny you did this?

(-> (mk-session)
	(with-tracing)
	(insert ...)
	(fire-rules))

jdt 2018-05-23T17:19:26.000154Z

Yes, that way I get tracing, and fire-rules works as expected.

2018-05-23T17:19:52.000224Z

that’s the way to use it

jdt 2018-05-23T17:20:05.000293Z

ok, thanks

2018-05-23T17:20:20.000016Z

So I don’t know what your question is beyond that and beyond what I said about it being misleading in the API to let you add it at arbitrary points

jdt 2018-05-23T17:20:37.000234Z

I'm trying to get the network activity after the initial bulk load of facts.

2018-05-23T17:20:42.000002Z

I think it’d be better to reject an attempt to add it at the “wrong times”, enhancement

jdt 2018-05-23T17:20:55.000067Z

And when I do that, by moving the trace after the facts are loaded, my fire-rules don't work.

2018-05-23T17:21:04.000155Z

yeah, it doesn’t work on that principle

jdt 2018-05-23T17:21:13.000238Z

ok, good to know, still learning

jdt 2018-05-23T17:22:43.000224Z

That begs the question of when it is safe to use it. Say I make a session, load data, run rules, query results. Then I want to change the data in the session and run it again with tracing. Will it work then? Or is it always safe to use with-tracing after fire-rules calls?

2018-05-23T17:22:54.000044Z

I’m not actually sure there is a way to look at the listener information and know the different between a fact inserted externally, via insert and a fact inserted from a RHS, via insert!. I don’t know of one off hand.

2018-05-23T17:23:52.000202Z

> Or is it always safe to use with-tracing after fire-rules calls? I think so and expect so. If it has issues, it’d be interesting to discuss them. Also, I don’t have any reason to think that it should ever change the semantics of the rules, you may just get bad/invalid tracing results

2018-05-23T17:24:07.000159Z

Earlier you said it caused your rules to not fire correctly, I’m skeptical on that

2018-05-23T17:24:18.000116Z

the tracing may not have accurately reported the rule firings, but they probably still fired

2018-05-23T17:24:36.000038Z

you can test that assumption, by adding a defquery to your session

jdt 2018-05-23T17:24:45.000155Z

re: firing, my rules had printlnin them, which didn't print when the with-tracing was done after the insert.

2018-05-23T17:24:48.000388Z

and then using a query on the RHS insert! facts that you think didn’t get inserted

2018-05-23T17:25:04.000122Z

Yeah, if you can reproduce that case at all, that’d be valuable

jdt 2018-05-23T17:25:15.000317Z

Okay, well it's pretty simple, I'll see what I can do.

2018-05-23T17:25:23.001047Z

I don’t expect with-tracing to be able to interfere with evaluation in that way

2018-05-23T17:26:39.000930Z

@dave.tenny found it

2018-05-23T17:26:51.001045Z

yeah, so with-tracing does appear to wipe out pending work

1
1
2018-05-23T17:27:04.000015Z

so you’re right, it’d cause trouble like you saw

2018-05-23T17:27:14.000455Z

after fire-rules should be safe - there is no pending work

2018-05-23T17:28:40.000318Z

it may be a “good thing” that with-tracing wipes out pending work since it makes a session that it can actually trace

2018-05-23T17:29:05.000878Z

well, idk about that, it’s just a weird situation hah - either needs docs or to throw an exception or something I think 🙂

jdt 2018-05-23T17:29:14.000543Z

Sounds like the documentation should be a bit clearer about restrictions though to avoid noob run-ins like mine.

2018-05-23T17:29:21.000111Z

Yes, it is too mysterious

jdt 2018-05-23T17:33:30.000579Z

I'm just trying to wrap my head around other things, like the Truth Maintenance capabilities that may or may not have been present in the OPS5 systems I was using 30 years ago. I'm pretty rusty at this. Retracting the preconditions that led to the state of the RHS doing the retraction seems to mean I need to fire rules, query my reults on the session afterward, make changes, then rinse-lather-repeat, where it used to be I'd do more stuff in the RHS clauses. Thus my attempts at ... modular ... tracing.

jdt 2018-05-23T17:35:42.000627Z

So a bit of catching up for me. I'm investigating clara for the job dispatch logic of a new scheduler I'm writing.

jdt 2018-05-23T17:35:59.000421Z

Meanwhile thanks for the help.

2018-05-23T17:37:36.000220Z

sure

2018-05-23T17:38:12.000233Z

@alex-dixon has done a lot with Clara’s tracing by extending it for his own purposes in the #precept library. Perhaps you can find some inspiration there.

2018-05-23T17:38:32.000053Z

https://github.com/CoNarrative/precept

alex-dixon 2018-05-23T17:43:54.000001Z

I think I ended up using the listeners namespace only. I forget at the moment how it relates to clara’s tracing

2018-05-23T17:44:22.000204Z

@alex-dixon oh, tracing just organizes the data coming from listeners I believe

2018-05-23T17:45:08.000818Z

wait no, tracing is a default impl over listeners

alex-dixon 2018-05-23T17:45:14.000506Z

Ah ok. That what I seem to remember but thought I may have been confusing it with explanations

2018-05-23T17:45:19.000496Z

(sort of the same as I said)

2018-05-23T17:45:29.000667Z

yeah, explanations/inspect are above all that

alex-dixon 2018-05-23T17:46:32.000662Z

Yet listeners is very user friendly imho. Though I may have ran into some private things I wanted public

alex-dixon 2018-05-23T17:48:44.000388Z

It is nice to have it boxed up and ready to use just at the same time the listeners ns is highly usable in and of itself I mean

alex-dixon 2018-05-23T18:08:52.000650Z

@dave.tenny If you end up poking around Precept at all I’d recommend the issue 19 branch

9️⃣ 2
1️⃣ 2
jdt 2018-05-23T18:09:51.000191Z

Will keep that in mind, so far have only looked at Clara-rules.

👍 2
jdt 2018-05-23T19:18:28.000386Z

(defquery my-query ...) followed by a what is typically another function wrapping the query with a call to (query session my-query) gets old. Is there w away to do a lexical defquery equivalent at the point I'd call query?

zylox 2018-05-23T19:24:57.000411Z

defquery more or less sets up an endpoint in your rules network, it needs to be known before hand

👍 1
zylox 2018-05-23T19:25:34.000757Z

query goes and grabs the list it generates at when things are fired, it doesnt go calculate it then (to my knowlege)

👍 1
zylox 2018-05-23T19:37:21.000353Z

you can, and i would not reccomend this outside of development, create a defquery for Object that just grabs everything in the session and then filter that as you see fit.

👍 2
2018-05-23T20:35:35.000526Z

@dave.tenny I’ve only partially read your example so far, but one immediate piece of feedback, don’t query until after fire-rules

2018-05-23T20:35:53.000106Z

think of query the same as with-tracing earlier, you have to only do it on “consistent” states of a session

2018-05-23T20:36:30.000610Z

Clara does some delayed evaluation for performance reasons. Any inserts/retracts that occur prior to a fire-rule cannot be relied upon and I’d consider the session to be in an “undefined” state

2018-05-23T20:37:41.000276Z

I’d actually prefer Clara to change for query to either (a) throw exception if called prior to a fire-rules or return something that indicates it is not ready yet.

2018-05-23T20:38:50.000808Z

Clara takes advantaged of batched insertion and also potentially a few other things, so it does not eagerly perform things like insert or retract. The evaluation is typically pushed to batch up the facts propagating through the network. This can play a major role in performance.

2018-05-23T20:39:49.000230Z

You mentioned OPS5, which you likely wouldn’t have seen behavior like this long ago. It is more common now. Drools is a popular JVM-based rules engine and it similarly has delayed evaluation of things prior to rule firing due to similar concerns.

2018-05-23T20:40:27.000423Z

This issue seems to somewhat often trip people up though. So I don’t think it is clear enough.

2018-05-23T20:41:13.000373Z

For your second question > ;why are my counters still there, I retracted them? I think it is because (query % counters) doesn’t return what you are thinking it does

2018-05-23T20:41:52.000041Z

It doesn’t return the bare counter fact, instead it returns a bindings map from the query, so it returns something like:

{:?counter <the counter fact>}

2018-05-23T20:42:32.000415Z

so you’d probably have to do something like

(#(apply retract % (map :?counter (query % counters))))

jdt 2018-05-23T20:42:36.000178Z

Oh sorry, forgot to include the output

jdt 2018-05-23T20:42:40.000300Z

It works, just not as expected

jdt 2018-05-23T20:42:43.000286Z

Here comes the output

2018-05-23T20:43:58.000182Z

that output looks consistent with the explanation I just gave

2018-05-23T20:44:03.000266Z

so try to apply the things I mentioned

jdt 2018-05-23T20:45:17.000628Z

Ah, that fixes it

jdt 2018-05-23T20:45:26.000127Z

(map :?counter ...)

2018-05-23T20:45:51.000626Z

🎉