This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-10-25
Channels
- # babashka (65)
- # beginners (34)
- # biff (18)
- # calva (8)
- # clara (22)
- # clj-kondo (32)
- # clojure (24)
- # clojure-bay-area (4)
- # clojure-europe (135)
- # clojure-nl (3)
- # clojure-norway (9)
- # clojure-uk (1)
- # clojurescript (11)
- # clojutre (1)
- # core-async (8)
- # cursive (3)
- # datomic (31)
- # emacs (5)
- # fulcro (6)
- # graalvm (5)
- # graphql (3)
- # honeysql (1)
- # introduce-yourself (9)
- # kaocha (1)
- # lsp (65)
- # meander (5)
- # nbb (7)
- # nrepl (2)
- # off-topic (44)
- # rum (3)
- # shadow-cljs (23)
- # specter (1)
- # tools-deps (6)
- # vim (3)
- # xtdb (30)
Is there an typical approach to randomly applying rules? Say I want to fire a rule 30% of the time (ie 30% of object sI am creating with rules have some specific attribute), what is a good way to model this in rules ... or is that a bad idea. thx
@U066S7PQC, maybe just by adding the following LHS expressión: [:test (> 0.3 (rand))]
?
alternatively, if you want it to be deterministically repeatable, maybe you could hash the some attribute of the input (unless all the attributes are somehow the same). Simplistic idea using clojure’s hash:
[:test (> 3 (mod (hash INPUT) 10))]
I would highly recommend making it deterministic based on bound variables in the LHS. Clara’s Truth Maintenance relies on the repeatability of the logic in both the LHS and RHS of rules.
Agreed on making it deterministic.
I think the hashing idea is aligned to what I’d think too.
You could do that or have a first-class key-val you put on the fact that had some value, say between 1-100, that was based on some distribution. Then you could have rules that just do an inequality like (< x 30)
, where that key name is :x
.
The generation of this key’s probabilistic value though, should be done external to the rules - not within the fire-rules loop where it’d cause non-determinism in rule-reevaluation on the same facts.
Ok, thanks... that sounds like a great idea. I was worried that if I used a rand in the LHS the rules would be applied over and over again until they were satisfied (ie. probs would all tend towards 1), which is what I think @U0LK1552A is saying in the above reply.
The approach I was working on was to create an new object in working memory that recorded the state of random variable -ie. activated or not. The rule tests for object existence so inserting it keeps TMS happy etc
A hopefully basic question, we have recently split our rules into multiple namespaces to make them a bit more manageable, but I am getting a ClassNotFoundException from the mk-session call for my records (defined in a different name space) The class that is not found (in the exception) (ie. MyStruct) does not have the fully qualified classname ie. demo.my-records.MyStruct ... I am requiring and importing the record classes and the rules that I have written don't use the full classname. I am passing all of the namespaces that I split the rulebase into and the namespace for the record definitions to the mk-session call eg (mk-session 'demo.main 'demo.my-records ...). Is there something else that I need to do?
here is the full stack trace:
2. Unhandled clojure.lang.Compiler$CompilerException
Error compiling pdmct/config_rules_main.clj at (200:1)
#:clojure.error{:phase :execution,
:line 200,
:column 1,
:source "pdmct/config_rules_main.clj"}
Compiler.java: 7665 clojure.lang.Compiler/load
RT.java: 381 clojure.lang.RT/loadResourceScript
RT.java: 372 clojure.lang.RT/loadResourceScript
RT.java: 459 clojure.lang.RT/load
RT.java: 424 clojure.lang.RT/load
core.clj: 6161 clojure.core/load/fn
core.clj: 6160 clojure.core/load
core.clj: 6144 clojure.core/load
RestFn.java: 408 clojure.lang.RestFn/invoke
core.clj: 5933 clojure.core/load-one
core.clj: 5928 clojure.core/load-one
core.clj: 5975 clojure.core/load-lib/fn
core.clj: 5974 clojure.core/load-lib
core.clj: 5953 clojure.core/load-lib
RestFn.java: 142 clojure.lang.RestFn/applyTo
core.clj: 669 clojure.core/apply
core.clj: 6016 clojure.core/load-libs
core.clj: 6000 clojure.core/load-libs
RestFn.java: 137 clojure.lang.RestFn/applyTo
core.clj: 669 clojure.core/apply
core.clj: 6038 clojure.core/require
core.clj: 6038 clojure.core/require
RestFn.java: 408 clojure.lang.RestFn/invoke
REPL: 46 user/eval5790
REPL: 46 user/eval5790
Compiler.java: 7194 clojure.lang.Compiler/eval
Compiler.java: 7149 clojure.lang.Compiler/eval
core.clj: 3215 clojure.core/eval
core.clj: 3211 clojure.core/eval
interruptible_eval.clj: 87 nrepl.middleware.interruptible-eval/evaluate/fn/fn
AFn.java: 152 clojure.lang.AFn/applyToHelper
AFn.java: 144 clojure.lang.AFn/applyTo
core.clj: 667 clojure.core/apply
core.clj: 1990 clojure.core/with-bindings*
core.clj: 1990 clojure.core/with-bindings*
RestFn.java: 425 clojure.lang.RestFn/invoke
interruptible_eval.clj: 87 nrepl.middleware.interruptible-eval/evaluate/fn
main.clj: 437 clojure.main/repl/read-eval-print/fn
main.clj: 437 clojure.main/repl/read-eval-print
main.clj: 458 clojure.main/repl/fn
main.clj: 458 clojure.main/repl
main.clj: 368 clojure.main/repl
RestFn.java: 1523 clojure.lang.RestFn/invoke
interruptible_eval.clj: 84 nrepl.middleware.interruptible-eval/evaluate
interruptible_eval.clj: 56 nrepl.middleware.interruptible-eval/evaluate
interruptible_eval.clj: 152 nrepl.middleware.interruptible-eval/interruptible-eval/fn/fn
AFn.java: 22 clojure.lang.AFn/run
session.clj: 218 nrepl.middleware.session/session-exec/main-loop/fn
session.clj: 217 nrepl.middleware.session/session-exec/main-loop
AFn.java: 22 clojure.lang.AFn/run
Thread.java: 833 java.lang.Thread/run
1. Caused by java.lang.ClassNotFoundException
MyStruct
URLClassLoader.java: 445 java.net.URLClassLoader/findClass
DynamicClassLoader.java: 69 clojure.lang.DynamicClassLoader/findClass
ClassLoader.java: 587 java.lang.ClassLoader/loadClass
DynamicClassLoader.java: 77 clojure.lang.DynamicClassLoader/loadClass
ClassLoader.java: 520 java.lang.ClassLoader/loadClass
compiler.clj: 188 clara.rules.compiler/effective-type
compiler.clj: 183 clara.rules.compiler/effective-type
compiler.clj: 202 clara.rules.compiler/get-fields
compiler.clj: 191 clara.rules.compiler/get-fields
compiler.clj: 336 clara.rules.compiler/field-name->accessors-used
compiler.clj: 332 clara.rules.compiler/field-name->accessors-used
compiler.clj: 383 clara.rules.compiler/compile-condition
compiler.clj: 379 clara.rules.compiler/compile-condition
compiler.clj: 1358 clara.rules.compiler/eval12362/extract-exprs/fn/fn
PersistentVector.java: 343 clojure.lang.PersistentVector/reduce
core.clj: 6885 clojure.core/reduce
core.clj: 6868 clojure.core/reduce
compiler.clj: 1353 clara.rules.compiler/eval12362/extract-exprs/fn
compiler.clj: 1336 clara.rules.compiler/eval12362/extract-exprs
compiler.clj: 2033 clara.rules.compiler/eval12845/mk-session*/fn
compiler.clj: 2003 clara.rules.compiler/eval12845/mk-session*
compiler.clj: 2117 clara.rules.compiler/mk-session
compiler.clj: 2091 clara.rules.compiler/mk-session
config_rules_main.clj: 201 pdmct.config-rules-main/eval15700
config_rules_main.clj: 200 pdmct.config-rules-main/eval15700
Compiler.java: 7194 clojure.lang.Compiler/eval
Compiler.java: 7653 clojure.lang.Compiler/load
RT.java: 381 clojure.lang.RT/loadResourceScript
RT.java: 372 clojure.lang.RT/loadResourceScript
RT.java: 459 clojure.lang.RT/load
RT.java: 424 clojure.lang.RT/load
core.clj: 6161 clojure.core/load/fn
core.clj: 6160 clojure.core/load
core.clj: 6144 clojure.core/load
RestFn.java: 408 clojure.lang.RestFn/invoke
core.clj: 5933 clojure.core/load-one
core.clj: 5928 clojure.core/load-one
core.clj: 5975 clojure.core/load-lib/fn
core.clj: 5974 clojure.core/load-lib
core.clj: 5953 clojure.core/load-lib
RestFn.java: 142 clojure.lang.RestFn/applyTo
core.clj: 669 clojure.core/apply
core.clj: 6016 clojure.core/load-libs
core.clj: 6000 clojure.core/load-libs
RestFn.java: 137 clojure.lang.RestFn/applyTo
core.clj: 669 clojure.core/apply
core.clj: 6038 clojure.core/require
core.clj: 6038 clojure.core/require
RestFn.java: 408 clojure.lang.RestFn/invoke
REPL: 46 user/eval5790
REPL: 46 user/eval5790
Compiler.java: 7194 clojure.lang.Compiler/eval
Compiler.java: 7149 clojure.lang.Compiler/eval
core.clj: 3215 clojure.core/eval
core.clj: 3211 clojure.core/eval
interruptible_eval.clj: 87 nrepl.middleware.interruptible-eval/evaluate/fn/fn
AFn.java: 152 clojure.lang.AFn/applyToHelper
AFn.java: 144 clojure.lang.AFn/applyTo
core.clj: 667 clojure.core/apply
core.clj: 1990 clojure.core/with-bindings*
core.clj: 1990 clojure.core/with-bindings*
RestFn.java: 425 clojure.lang.RestFn/invoke
interruptible_eval.clj: 87 nrepl.middleware.interruptible-eval/evaluate/fn
main.clj: 437 clojure.main/repl/read-eval-print/fn
main.clj: 437 clojure.main/repl/read-eval-print
main.clj: 458 clojure.main/repl/fn
main.clj: 458 clojure.main/repl
main.clj: 368 clojure.main/repl
RestFn.java: 1523 clojure.lang.RestFn/invoke
interruptible_eval.clj: 84 nrepl.middleware.interruptible-eval/evaluate
interruptible_eval.clj: 56 nrepl.middleware.interruptible-eval/evaluate
interruptible_eval.clj: 152 nrepl.middleware.interruptible-eval/interruptible-eval/fn/fn
AFn.java: 22 clojure.lang.AFn/run
session.clj: 218 nrepl.middleware.session/session-exec/main-loop/fn
session.clj: 217 nrepl.middleware.session/session-exec/main-loop
AFn.java: 22 clojure.lang.AFn/run
Thread.java: 833 java.lang.Thread/run
most likely issue is you have a rule defined somewhere that uses that type without importing it
so https://github.com/cerner/clara-rules/blob/main/src/main/clojure/clara/rules/dsl.clj#L150 maybe-qualify is not finding the full class name
do I pass all of the namespaces where I have defined rules to the mk-session? or is it enough to require those namespaces in my main namespace and pass that?
but looking at the code I thing it is very unlikely your current error has anything to do with that
You should be sure to require the namespaces prior to referring to their names passed to mk-session. Beyond that it would seem like you are missing an :import
All symbols referenced in rules have to resolve in the namespace the rule is defined in.