Hi Wolfgang,
First, your rules work...
But for the second rule, I replaced the first Reachable() in the when
clause to Link(), and the result is still correct. Only if I remove
"no-loop true", the issue I had appeared.
My statement about avoiding a mix of given and derived facts was
definitely exaggerating matters. But the representation of Link vs.
Reachable merits some consideration.
So, I understand how "no-loop true" in this case helps to make the
result correct. But, do you see any scenarios where "no-loop" can
cause incorrect results? For example, not enough number of recursions?
No-loop is almost never satisfactory.
It's necessary to avoid duplications of Reachable. You can't add a "not" CE to
block this, but it's possible to configure against the insertion of equal facts.
For this, equals() and hashCode() must be implemented properly, and the
AssertBehaviorOption.EQUALITY must be set.
I have found this to work quite well:
public class Reachable {
private String src;
private String tgt;
//...
public boolean equals(Object obj) {
if (this == obj) return true;
if( ! (obj instanceof Reachable)) return false;
Reachable other = (Reachable) obj;
return other.src.equals( src ) && other.tgt.equals( tgt );
}
}
public class Link extends Reachable {
public Link( String src, String tgt ){
super(src, tgt);
}
}
Notice that this subclassing avoids the creation of Reachable for each Link. And I still think that computing the closure should be done by using Reachable only. Note the absence of no-loop!
rule deriveReachReach
when
Reachable( $src: src, $mid: tgt )
Reachable( src == $mid, $tgt: tgt != $src )
then
insertLogical( new Reachable( $src, $tgt ));
end
kbConfig.setOption( AssertBehaviorOption.EQUALITY ); // identical and equal not inserted
kBase = KnowledgeBaseFactory.newKnowledgeBase( kbConfig );
Cheers
-W
Thanks.
-Simon