Drools version: 6.5.0
A rule flow sequence which takes (Start -> A -> B -> End) route, the expectation is all the rules in A (RuleflowGroup: A) will be executed first before all the rules in B (RuleflowGroup: B). But the result it produces from the implementation of the AgendaEventListener methods (i.e., beforeMatchFired, afterMatchFired) follows the reverse order. Rules associated with B are executed first before rules associated with A.
Any explanation would be very helpful.
Please find the rule flow diagram below.
If it is the same with version 7.x that i am currently using, it is because is a bit more complicated than you think. It is not just a flow. (A->B->C), is a stack.
So it is A then B/A then C/B/A. And when C finishes executing is returning back to B/A and then A.
If you want to get rid of that you can add a rule at last level, with lowest priority and
eval (true) in the when part and halt() in the then part to end the session before it returns to previous ruleflow group.
Related
Let's say we have the following component script
let x = 0;
function increase() {
x += 1;
}
$: console.log(x)
$: if (x == 4) {
x = 0;
}
https://svelte.dev/repl/2bca979673114afea9fc6b37434653a3?version=3.29.0
Intuitively I would expect from cotinually calling increase, is to have the values 0,1,2,3,4,1,2,3,4,... logged to the console. But this is not the case. Instead, the second reactive statement runs first, and 4 is never logged; it is 0. Switching the order of the reactive statements has no effect.
How do you make the logging statement execute before the other one and what is the reason that it runs second, in the first place?
The order in which reactive statements that depends on the same variables are run is not specified / guaranteed by Svelte. You have to build your components with the expectation that they can be run in any order, and make sure that your code doesn't depend on any specific order.
You must not rely on a given order you observe in a specific case either -- it can change following a change in Svelte's internal implementation (e.g. new optimisations), or when the code of your own component changes (causing a different compiler output, that can change the order of reactive blocks for hard-to-anticipate reasons).
The reasons why this happens are highly technical (i.e. I don't really know), but they boil down to ease of implementation / optimization of the compiler. Reactive statements are a kind of async operations, that typically can't guarantee order of execution.
If you really need 2 operations to happen in a specific order then, for peace of mind, you need them in the same reactive block.
$: {
console.log(x) // op 1
if (x == 4) x = 0 // op 2
}
Let be a job that contains two phases that (for convenience) cannot be merged. Let's call A the first step and B the second step. Hence, we always need to do A then B.
Workflow
start new cluster with a job A
build MyOutput
count(MyOutput) = 2000 (*)
write(MyOutput)
start new cluster with a job B
read(MyOutput)
count(MyOutput) = 1788 (**).
Precisions
A provides an output which is an RDD[MyObject], namely MyOutput. To write MyOutput, here is what I do: MyOutput.saveAsObjectFile("...")
Then B uses MyOutput as an input, reading the previously written file. Here is what I do: val MyOutput: RDD[MyObject] = sc.objectFile("...")
A and B happen on two separate clusters.
Problem
The main point is that the problem does not ALWAYS happen but when this problem appears, (*) < (**) -- it seems we lost some data whereas we should not have any differences between these data. Obvisously something is wrong.
Do you know what happens here? How to solve that?
I'm wondering if there is anything in drools that can be used to determine how close a rule is (or has been) to being activated?
From all that I can tell, the standard drools doesn't support anything like it, I just wondered if I might have missed something.
I glanced at Drools Chance (https://github.com/droolsjbpm/drools-chance), but it seems that it hasn't been developed a lot anymore recently and doesn't seem ready for Drools 6.x.
I know that AgendaEventListeners can be used to intercept when a rule has fired but it doesn't look like there is anything to intercept if a single condition of a rule has been evaluated to true.
Am I missing something or is this a current limitation of drools to not have any support for this kind of thing?
Thanks!
Perhaps you could use a work around. Construct a set of extra rules that write metrics for when they fire depending on your definition of close--that could be 1..n parts of the LHS for the rule of interest and/or thresholds for nearness to any part of the LHS (say you want to know when a value approaches to with 90% of another value). For complex conditionals in source code (not Drools related), I've used approaches like the below to trace complicated and nested logic:
boolean a1 = property1 > property2
boolean a2 = (!isHigh || isMedium)
boolean a3 = property 4 == property5
System.out.println ("rule2: " + a1 + " " + a2 + " " + a3);
if (a1 && a2 && a3) {
...do something
}
This is related what I called "learning the reason for failure". Consider that you have to pass n qualifications. Rather than being told that you have failed you'd like to have a list of the "pass" (and "fail") criteria.
One rule evaluating all of this in a lump sum is no good. You have to write one rule for each of the n criteria and collect the positives with the fact holding the properties under survey. Finally, one low-priority rule can check whether you have all n ("hooray") and another one can tell you "sorry, no", but it can give you a list what succeeded (and what not).
Lots of effort, but good information is always costly.
I'm trying to use Drools backward chaining to find out which facts are needed to get an object inserted in the working memory.
In the following example, I expect to get the fact "go2".
rule "ins a"
when
String( this == "go2" )
then
insert(new A());
end
rule "Run"
when
then
insert(new String("go1"));
end
rule "Test isThereAnyA"
when
String( this == "go1" )
isThereAnyA(a;)
then
System.out.println( "you can get " + a );
end
query isThereAnyA (A a)
a := A()
end
I've been looking at examples in the official documentation
http://docs.jboss.org/drools/release/6.1.0.Final/drools-docs/html_single/index.html#d0e21289
but they show a different situation (the rules in those examples doesn't creates new fact)
From the chart
http://docs.jboss.org/drools/release/6.1.0.Final/drools-docs/html_single/index.html#d0e21240
I think it should work but I haven't found a way to specify a query that gives me the expected results.
Thank you in advance.
Short answer:
Unfortunately backward chaining can not be used for this purpose.
It will not give you "go2" in this case.
Long answer:
In Drools, Backward chaining (BC) is a way to query the WM in a goal-driven fashion, not a way to trace back the derivation graph of a normal forward chaining inference process.
BC allows rule "Test" to retrieve As through the query "isThereAnyA", and possibly invoke other queries, but will not allow to find the "production" link between "A" and "go2". The reason is that "when..then..insert.." does not create any link between the triggering facts and the asserted conclusion, and backward chaining will not change it.
What you could do with BC is this:
query isThereAnyA_InPresenceOfA_String( A a )
isThereAnyString( $s ; )
a := A()
end
query isThereAnyString( String $s )
$s := String( this == "go2" )
end
This will pick up As only if a String "go2" is (still) present. However you'll notice that the connection between a particular instance of A and a the particular String which led to its assertion is still missing.
To know exactly which objects led to the assertion of another object you may need a different approach. Options include:
make the connection explicit : new A( $s ) // $s bound to "go2"
use "insertLogical" to establish a dependency between "go2" and A, then query the TruthMaintenanceSystem
The TMS-based one would be my tentative choice, but it also depends on your exact requirements.
This use case is common, there may be other options, including a few which are experimental as they are being developed in 6.3, but I'd rather ask a few questions first.
That is: when do you need exactly to discover the facts - during the execution of the rules, or "offline"? Is it purely for auditing purposes, or does it impact your business logic? Can you have multiple rules asserting the "same" object?
Hope this helps
Davide
What is the definition of a "glitch" in the context of Functional Reactive Programming?
I know that in some FRP frameworks "glitches" can occur while in others not. For example RX is not glitch free while ReactFX is glitch free [1].
Could someone give a very simple example demonstrating how and when glitches can occur when using RX and show on the same example how and why the corresponding ReactFX solution is glitch free.
Thanks for reading.
Definition
My (own) favorite definition:
A glitch is a temporary inconsistency in the observable state.
Definition from Scala.Rx:
In the context of FRP, a glitch is a temporary inconsistency in the dataflow graph. Due to the fact that updates do not happen instantaneously, but instead take time to compute, the values within an FRP system may be transiently out of sync during the update process. Furthermore, depending on the nature of the FRP system, it is possible to have nodes be updated more than once in a propagation.
Example
Consider integer variables a, b. Define sum and prod such that
sum := a + b,
prod := a * b.
Let's rewrite this example to JavaFX:
IntegerProperty a = new SimpleIntegerProperty();
IntegerProperty b = new SimpleIntegerProperty();
NumberBinding sum = a.add(b);
NumberBinding prod = a.multiply(b);
Now let's write a little consistency check:
InvalidationListener consistencyCheck = obs -> {
assert sum.intValue() == a.get() + b.get();
assert prod.intValue() == a.get() * b.get();
};
sum.addListener(consistencyCheck);
prod.addListener(consistencyCheck);
a.set(1);
b.set(2);
This code fails with an assertion error on the last line, because:
b is updated (to 2)
sum is updated (to 3)
`consistencyCheck` is triggered, `a == 1`, `b == 2`, but `prod == 0`, because `prod` has not been updated yet
This is a glitch — prod is temporarily inconsistent with a and b.
Glitch Elimination Using ReactFX
First note that ReactFX is not "glitch free" out of the box, but it gives you tools to eliminate glitches. Unless you take some conscious effort to use them, ReactFX is not more glitch-free than RX (e.g. rxJava).
The techniques to eliminate glitches in ReactFX rely on the fact that event propagation is synchronous. On the other hand, event propagation in RX is always asynchronous, thus these techniques cannot be implemented in an RX system.
In the example above, we want to defer listener notifications until both sum and prod have been updated. This is how to achieve this with ReactFX:
import org.reactfx.Guardian;
import org.reactfx.inhibeans.binding.Binding;
IntegerProperty a = new SimpleIntegerProperty();
IntegerProperty b = new SimpleIntegerProperty();
Binding<Number> sum = Binding.wrap(a.add(b)); // Binding imported from ReactFX
Binding<Number> prod = Binding.wrap(a.multiply(b)); // Binding imported from ReactFX
InvalidationListener consistencyCheck = obs -> {
assert sum.getValue().intValue() == a.get() + b.get();
assert prod.getValue().intValue() == a.get() * b.get();
};
sum.addListener(consistencyCheck);
prod.addListener(consistencyCheck);
// defer sum and prod listeners until the end of the block
Guardian.combine(sum, prod).guardWhile(() -> {
a.set(1);
b.set(2);
});
Short answer : glitch = inonconsistent/illegal/meaningless state.
Here is a relevant link : https://social.msdn.microsoft.com/Forums/en-US/bc2c4b71-c97b-428e-ad71-324055a3cd03/another-discussion-on-glitches-and-rx?forum=rx
Also, see the 29th minute of Sodium's author talk for another answer : http://youtu.be/gaG3tIb3Lbk.
And a relevant SOF answer : how to avoid glitches in Rx
So here is my understanding of what a glitch is based on Tomas' answer.
There is a dataflow graph, with 3 nodes : A, B, C
A->B
A->C
In this simple example, a glitch happens if I change A and that causes to change B but C has not been updated yet. This is a glitch.
C is not consistent with B.
Say B=2*A, C=2*A.
Then if B is not equal C then that is a glitch.
Here is an extremely short and theoretical example of a fatal "glitch" situation in C# RX
var t = Observable
.Interval(TimeSpan.FromSeconds(1))
.Publish()
.RefCount();
var s = t.CombineLatest(t, (t1,t2) => 1/(1-(t1-t2));
Since t1 and t2 both represent the latest value of the hot observable t, one would assume t1-t2 to always be 0. So s should always be 1.
But when subscribing to s, we indeed get 1 as the first observed value, but then we get a division by zero exception. In RxJS we would get NaN.
The reason is simple: a.CombineLatest(b, f) will react when either a or b produces a value, combining this new value and the last observed value of the other observable. This is by design, but from my experience, people using RX sometimes consider these to be glitches, especially when coming from other FRP libraries that have a different notion of "latest".
This is of course a contrived example, just meant to illustrate a misconception about CombineLatest.
Maybe CombineLatest should have been called WhenAny as in the ReactiveUI library, this would clarify the operational semantics?