Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

RuleML2015 : Hybrid Relational and Graph Reasoning

1,412 views

Published on

RuleML2015 : Building a Hybrid Reactive Rule Engine for Relational and Graph Reasoning

Published in: Technology
  • As always Mark, tons of great information here. Do you have any reference materials to understand the back ground for RETE-OO and it's theoretical concepts? Some times the challenge to "think rules" and I wonder if you have any good refererences where someone could start learning the details of how rules can be executed, and how the engine actually works?
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

RuleML2015 : Hybrid Relational and Graph Reasoning

  1. 1. Building A Hybrid Reactive Rule Engine For Relational And Graph Reasoning Mark Proctor, Mario Fusco, István Ráth, Davide Sottara
  2. 2. The Problem
  3. 3. Student Plans String name Plan plan Student String code Student owner List<Exam> exams Plan Plan plan String course String code List<Grade> exams Exam Exam exam int attempt String value Grade 1 1 1 0..1 1 0..1
  4. 4. Student Plans public class Student {
 private String name;
 
 private Plan plan; } public class Plan {
 private String code;
 private Student owner; 
 private List<Exam> exams;
 } public class Exam { private String code; private String course; 
 private Plan plan; 
 private List<Grade> grades; } public class Grade {
 private String value; 
 private int attempt; private Exam exam; }
  5. 5. Student Plans public static Student student(String studentName, String planCode, Exam... exams) {
 Student student = new Student(studentName);
 Plan plan = new Plan(student, planCode);
 student.setPlan( plan );
 plan.setOwner( student );
 for ( Exam exam : exams ) {
 exam.setPlan( plan );
 plan.getExams().add ( exam );
 }
 return student;
 }
 
 public static Exam exam( String course, String... grades) {
 Exam exam = new Exam( course );
 int attempt = 1;
 for ( String letter : grades) {
 exam.getGrades().add(new Grade(exam, letter, attempt));
 attempt++;
 }
 return exam;
 }
  6. 6. Courses •Communication •Creed -The Jedi Code •Force •Jedi Studies •Meditation •Personal •Situational Awareness •Spirituality - Jedi Mythology •Warrior
  7. 7. Student Plans private static final String A = "A";
 private static final String B = "B";
 private static final String C = "C";
 private static final String D = "D";
 private static final String E = "E";
 private static final String F = "F";
  8. 8. Student Plans private static final String A = "A";
 private static final String B = "B";
 private static final String C = "C";
 private static final String D = "D";
 private static final String E = "E";
 private static final String F = "F"; public void create(KieSession ksession) {
 Student darth = student( "Darth", "dp2015",
 exam( "dpe01", "Jedi Studies", A),
 exam( "dpe02", "Force", B ),
 exam( "dpe03", "Meditation", D, C) );
 Student yoda = student( "Yoda", "yp2015",
 exam( "ype01", "Jedi Studies", A),
 exam( "ype02", "Force", A ),
 exam( "ype03", "Meditation", A) );
 Student luke = student( "Luke", "lp2015",
 exam( "lpe01", "Jedi Studies", C, B),
 exam( "lpe02", "Force", B ),
 exam( "lpe03", "Meditation", F, C) );
 }
  9. 9. Student Plans private static final String A = "A";
 private static final String B = "B";
 private static final String C = "C";
 private static final String D = "D";
 private static final String E = "E";
 private static final String F = "F"; public void create(KieSession ksession) {
 Student darth = student( "Darth", "dp2015",
 exam( "dpe01", "Jedi Studies", A),
 exam( "dpe02", "Force", B ),
 exam( "dpe03", "Meditation", D, C) );
 Student yoda = student( "Yoda", "yp2015",
 exam( "ype01", "Jedi Studies", A),
 exam( "ype02", "Force", A ),
 exam( "ype03", "Meditation", A) );
 Student luke = student( "Luke", "lp2015",
 exam( "lpe01", "Jedi Studies", C, B),
 exam( "lpe02", "Force", B ),
 exam( "lpe03", "Meditation", F, C) );
 
 ksession.insert( darth );
 ksession.insert( yoda );
 ksession.insert( luke );
 }
  10. 10. Student Plans • Email all the “Big Data” people their grades.
  11. 11. The Problem • The information provided is Object Oriented which is a form of graph and uses references. • Traditional Production Rule Systems are relational, they cannot see or use references. • Users must then map their model to a relational one.
  12. 12. Student Plans public class Student {
 private String name; 
 private String plan;
 } public class Plan {
 private String code; private String owner; }
  13. 13. Student Plans public class Student {
 private String name; 
 private String plan;
 } public class Plan {
 private String code; private String owner; } public class Student {
 private String name;
 
 private Plan plan; } public class Plan {
 private String code;
 private Student owner; 
 private List<Exam> exams;
 }
  14. 14. Student Plans public class Grade {
 private String value; 
 private int attempt; private String exam; } public class Exam { private String code; private String course;
 private String plan; }
  15. 15. Student Plans public class Grade {
 private String value; 
 private int attempt; private String exam; } public class Exam { private String code; private String course;
 private String plan; } public class Exam { private String code; private String course; 
 private Plan plan; 
 private List<Grade> grades; } public class Grade {
 private String value; 
 private int attempt; private Exam exam; }
  16. 16. Student Plans • Email all the “Big Data” people their grades. rule R1 when
 $student : Student ()
 $plan : Plan ( owner == $student.name )
 $exam : Exam( plan == $plan.code, course == ”Big Data” ) 
 $grade : Grade( exam == $exam.code ) then // RHS end
  17. 17. Rete AND AND OTN OTN OTN OTN Root GradeExamPlanStudent AND RTN
  18. 18. Rete public abstract class Node {
 protected Node childNode;
 
 public abstract void propagateLeft(Tuple tuple);
 
 public abstract void propagateRight(Object object);
 }
  19. 19. Rete public abstract class Node {
 protected Node childNode;
 
 public abstract void propagateLeft(Tuple tuple);
 
 public abstract void propagateRight(Object object);
 } public class AndNode extends Node {
 private LeftMemory leftMemory;
 private RightMemory rightMemory;
 private CompiledExpression expr;
 
 public void propagateLeftInsert(Tuple tuple) {
 leftMemory.addTuple(tuple);
 
 for ( Object object : rightMemory.getObjects() ) {
 if ( expr.eval(tuple, object) ) {
 childNode.propagateLeft(new Tuple(tuple, object));
 }
 }
 }
 
 public void propagateRightInsert(Object object) {
 rightMemory.addObject(object);
 
 for ( Tuple tuple : leftMemory.getTuples() ) {
 if ( expr.eval(tuple, object) ) {
 childNode.propagateLeft(new Tuple(tuple, object));
 }
 }
 }
 }
  20. 20. Rete AND OTN Root Student [“dp2015”, “yp2015”, “lp2015”] [“darth”, “yoda”, “luke”] [“darth”, “yoda”, “luke”] OTN Plan [“dp2015”, “yp2015”, “lp2015”] AND Exam
  21. 21. Rete AND OTN Root Student [“dp2015”, “yp2015”, “lp2015”] [“darth”, “yoda”, “luke”] [“darth”, “yoda”, “luke”] OTN Plan [“dp2015”, “yp2015”, “lp2015”] ANDPartial Match [[“darth”, “dp2015”], [“yoda”, “yp2015”], [“luke”, “yp2015”] ] Exam public class Tuple {
 private Tuple parent;
 private Object object; private List<Tuple> children; 
 
 public Tuple(Tuple parent, Object object) {
 parent = parent;
 this.object = object;
 }
 }
  22. 22. Rete AND OTN Root Student [“dp2015”, “yp2015”, “lp2015”] [“darth”, “yoda”, “luke”] [“darth”, “yoda”, “luke”] OTN Plan [“dp2015”, “yp2015”, “lp2015”] ANDPartial Match [[“darth”, “dp2015”], [“yoda”, “yp2015”], [“luke”, “yp2015”] ] OTN Exam [“dpe01”, “dpe02”, “dpe03”, “ype01”, “ype02”, “ype03”, “lpe01”, “lpe02”, “lpe03” ] public class Tuple {
 private Tuple parent;
 private Object object; private List<Tuple> children; 
 
 public Tuple(Tuple parent, Object object) {
 parent = parent;
 this.object = object;
 }
 }
  23. 23. Rete AND OTN Root Student [“dp2015”, “yp2015”, “lp2015”] [“darth”, “yoda”, “luke”] [“darth”, “yoda”, “luke”] OTN Plan [“dp2015”, “yp2015”, “lp2015”] AND [[“darth”, “dp2015”, “dpe01”], [“darth”, “dp2015”,“dpe02”],[“darth”, “dp2015”,“dpe03”], [“yoda”, “yp2015”, “ype01”], [“yoda”, “yp2015”, “ype02”], [“yoda”, “yp2015”, “ype03”], [“luke”, “lp2015”, “ype01”], [“luke”, “lp2015”, “ype02”], [“luke”, “lp2015”, “ype03”]] Partial Match [[“darth”, “dp2015”], [“yoda”, “yp2015”], [“luke”, “yp2015”] ] OTN Exam [“dpe01”, “dpe02”, “dpe03”, “ype01”, “ype02”, “ype03”, “lpe01”, “lpe02”, “lpe03” ] public class Tuple {
 private Tuple parent;
 private Object object; private List<Tuple> children; 
 
 public Tuple(Tuple parent, Object object) {
 parent = parent;
 this.object = object;
 }
 }
  24. 24. Rete [[“darth”, “dp2015”, “dpe01”], [“darth”, “dp2015”,“dpe02”],[“darth”, “dp2015”,“dpe03”], [“yoda”, “yp2015”, “ype01”], [“yoda”, “yp2015”, “ype02”], [“yoda”, “yp2015”, “ype03”], [“luke”, “lp2015”, “ype01”], [“luke”, “lp2015”, “ype02”], [“luke”, “lp2015”, “ype03”]] Darth dp2015 dpe01 dpe02 dpe03 t1 = new Tuple( null, “Darth” ) t2 = new Tuple( t1, “dp205” ) t3 = new Tuple( t2, “dpe01” ) t4 = new Tuple( t2, “dpe02” ) t5 = new Tuple( t2, “dpe03” ) Exam Plan Student [t1, t2, t3], [t1, t2, t4], [t1, t2, t5]
  25. 25. Requirements • Functionality • Access child objects via references • React to child objects • List comprehension • Iterate one to many relations • Support reactive and passive operations • Implementation • Syntax Extensions • Rete Extensions • Object integration
  26. 26. From • Implementation • Introduces one new keyword “from”. • Requires new Rete node. • Requires expression evaluation sub system. • Uses dot ‘.’ as reference accessor. • with type safe javascript like syntax (MVEL). • Functionality • Allows access to nested objects. • Dot ‘.’ accessor is access and return only. • It does not provide list comprehension. • List comprehension is performed by the node on the return result. • Is passive only, no reactivity. rule R2 when
 $student : Student ( $plan : plan )
 $exam: Exam( course == ”Big Data” ) from $plan.exams 
 $grade: Grade() from $exam.grades then
 /∗ RHS ∗/ 
 end
  27. 27. From rule R2 when
 $student : Student ( $plan : plan )
 $exam: Exam( course == ”Big Data” ) from $plan.exams 
 $grade: Grade() from $exam.grades then
 /∗ RHS ∗/ 
 end From From OTN Root Student RTN $student : Student ( $plan : plan ) // “from” the Working Memory $exam: Exam( course == ”Big Data” ) from $plan.exams $grade: Grade() from $exam.grades
  28. 28. From public void propagateLeft(Tuple tuple) {
 leftMemory.addTuple(tuple);
 for ( Object object : rightMemory.getObjects() ) {
 if ( expr.eval(tuple, object) ) {
 childNode.propagateLeft(new Tuple(tuple, object));
 }
 }
 }
  29. 29. From public void propagateLeftInsert(Tuple tuple) {
 leftMemory.addTuple(tuple);
 
 Object result = expr.equals( tuple.get(index));
 
 if ( result instanceof Collection) {
 for ( Object o : ((Collection)result)) {
 propagateLeftIfAllowed(tuple, o);
 }
 } else {
 propagateLeftIfAllowed(tuple, result);
 }
 }
 
 private void propagateLeftIfAllowed(Tuple tuple, Object o) {
 if ( isAllowed( tuple, o ) ) {
 childNode.propagateLeftInsert(new Tuple(tuple, o));
 }
 } public void propagateLeftInsert(Tuple tuple) {
 leftMemory.addTuple(tuple);
 for ( Object object : rightMemory.getObjects() ) {
 if ( expr.eval(tuple, object) ) {
 childNode.propagateLeft(new Tuple(tuple, object));
 }
 }
 }
  30. 30. From public class FromNode extends Node {
 private LeftMemory leftMemory;
 private CompiledExpression expr;
 private int index;
 
 public void propagateLeftInsert(Tuple tuple) {
 leftMemory.addTuple(tuple);
 
 Object result = expr.equals( tuple.get(index));
 
 if ( result instanceof Collection) {
 for ( Object o : ((Collection)result)) {
 propagateLeftIfAllowed(tuple, o);
 }
 } else {
 propagateLeftIfAllowed(tuple, result);
 }
 }
 
 private void propagateLeftIfAllowed(Tuple tuple, Object o) {
 if ( isAllowed( tuple, o ) ) {
 childNode.propagateLeftInsert(new Tuple(tuple, o));
 }
 } 
 public void propagateRightInsert(Object object) {
 // From has no right propagation 
 }
 }
  31. 31. Passive OOPath • Implementation • Re-use ‘from’ node • Introduces no Rete changes. • Requires expression evaluation sub system. • Uses forward slash ‘/’ as reference accessor. • Introduce XPath inspired syntax • Syntax change must be added to Patterns • Functionality • Allows access to nested objects. • forward slash ‘/’ accessor performs list comprehension
 for each visited reference. • List comprehension is also performed by the node on the return result. • Is passive only, no reactivity. rule R3 when
 Student( $grade: /plan/exams{course == ”Big Data”}/grades ) then /∗ RHS ∗/ end
  32. 32. R1, R2, R3 rule R1 when
 $student : Student ()
 $plan : Plan ( owner == $student.name )
 $exam : Exam( plan == $plan.code, course == ”Big Data” ) 
 $grade : Grade( exam == $exam.code ) then // RHS end rule R2 when
 $student : Student ( $plan : plan )
 $exam: Exam( course == ”Big Data” ) from $plan.exams 
 $grade: Grade() from $exam.grades then
 /∗ RHS ∗/ 
 end rule R3 when
 Student( $grade: /plan/exams{course == ”Big Data”}/grades ) then /∗ RHS ∗/ end
  33. 33. OOPath Syntax • Access by index • Inline cast for type safety • Indexed back reference • Variable back reference • Back tracking • Out of Pattern use Student( $grade : /plan/exams[0]{ course == ”Big Data”}/grades ) Student( $grade : /plan/exams{ #PracticalExam, lab == ”hazard safe”, 
 course == ”Material Explosions”}/grades ) A( $var: /b/c/d{ f1 == ../../f2}/e ) // the ../../ back references to the ‘b’ field access A( $var: /$b : b/c/d{ f1 == $b.f2}/e ) // the $b is inline bound for later use A( $var: /$b : b/c/d{ f1 == $b.f2}/$b/f2 ) // $var is bound to results of the f2 access $student : Student()
 $grade : /$student/plan/exams{course == ”Big Data”}/grades;
  34. 34. Advanced OOPath Usage • Use existing Drools syntax and functionality • Colon ‘:’ provides Pattern and field binding • Colon with equals ‘:=‘ provides unification • POSL-like support for position and slotted • Arguments can be named or positional. • Positional arguments must come first and be delimited with a semi colon ‘;’ at the end. • Positional arguments are always unified, compared to named arguments which can be bound ’:’ or unified ’:=’.
  35. 35. Advanced OOPath Usage • Transitive closure query isContainedIn ( Thing $x , Thing $y )
 /$y/$x := children ;
 or
 /$y/$z := children; and isContainedIn($x, $z;) ) 
 end
  36. 36. Advanced OOPath Usage • Transitive closure • Negation over transitive closure query isContainedIn ( Thing $x , Thing $y )
 /$y/$x := children ;
 or
 /$y/$z := children; and isContainedIn($x, $z;) ) 
 end query isNotContainedIn ( Thing $x , Thing $y ) 
 not( isContainedIn( $x, $y; ) ) 
 end
  37. 37. Advanced OOPath Usage • Transitive closure • Negation over transitive closure • Accumulation query isContainedIn ( Thing $x , Thing $y )
 /$y/$x := children ;
 or
 /$y/$z := children; and isContainedIn($x, $z;) ) 
 end query isNotContainedIn ( Thing $x , Thing $y ) 
 not( isContainedIn( $x, $y; ) ) 
 end query countItems ( Thing $y)
 acc( isContainedIn( $x, $y; ); 
 count( $x ); ) 
 end
  38. 38. Advanced OOPath Usage • Transitive closure • Negation over transitive closure • Accumulation • Structural Control query isContainedIn ( Thing $x , Thing $y )
 /$y/$x := children ;
 or
 /$y/$z := children; and isContainedIn($x, $z;) ) 
 end query isNotContainedIn ( Thing $x , Thing $y ) 
 not( isContainedIn( $x, $y; ) ) 
 end query countItems ( Thing $y)
 acc( isContainedIn( $x, $y; ); 
 count( $x ); ) 
 end query childrenOrderedByEdgeCount( Parent $x, Child $c0, int index ) 
 /$x/$c1 : children[index]{children.size <= $c0.children. size }; 
 childrenOrderedByEdgeCount ( $x , $c1 , index + 1; ) 
 end
  39. 39. Advanced OOPath Usage • Transitive closure • Negation over transitive closure • Accumulation • Structural Control • Combined Graph and Relational query isContainedIn ( Thing $x , Thing $y )
 /$y/$x := children ;
 or
 /$y/$z := children; and isContainedIn($x, $z;) ) 
 end query isNotContainedIn ( Thing $x , Thing $y ) 
 not( isContainedIn( $x, $y; ) ) 
 end query countItems ( Thing $y)
 acc( isContainedIn( $x, $y; ); 
 count( $x ); ) 
 end query childrenOrderedByEdgeCount( Parent $x, Child $c0, int index ) 
 /$x/$c1 : children[index]{children.size <= $c0.children. size }; 
 childrenOrderedByEdgeCount ( $x , $c1 , index + 1; ) 
 end query findChildrenWithMatchingEdgeCounts( Parent $x, Child $c0, int index )
 /$x/$c := children[index];
 // relational search
 exists( Thing( children . size == $c. children . size ) ) 
 findChildrenWithMatchingEdgeCounts( $x , $c1 , index + 1;) 
 end
  40. 40. Reactive OOPath • Implementation • New reactive ‘from’ node. • ReactiveObject Object integration. • List integration. • Functionality • Uses the OOPath syntax, but now all ‘/‘ are reactive.
  41. 41. Reactive OOPathpublic class ReactiveFromNode extends Node {
 private LeftMemory leftMemory;
 private CompiledExpression expr;
 private int index;
 
 public void propagateLeftInsert(Tuple tuple) {
 leftMemory.addTuple(tuple);
 
 Object result = expr.equals( tuple.get(index) );
 
 if ( result instanceof ObservableList) {
 ObservableList list = (ObservableList) result;
 ListObserver observer = new ListObserver(tuple);
 tuple.setObserver(observer);
 list.addObserver( observer );
 
 for ( Object o : list ) {
 propagateLeftIfAllowed(tuple, o);
 }
 } else {
 propagateLeftIfAllowed(tuple, result);
 }
 }
 
 public void propagateLeftIfAllowed(Tuple tuple, Object o) {
 ReactiveObject r = getReactiveObject(o);
 r.addTuple(tuple);
 
 if ( isAllowed( tuple, o ) ) {
 childNode.propagateLeftInsert(new Tuple(tuple, o));
 }
 }
 
 public void propagateChildLeftTupleDelete(Tuple tuple) {
 tuple.unlink();
 childNode.propagateLeftDelete(tuple);
 }
  42. 42. ReactiveObject public class ReactiveObject {
 private List<Tuple> tuples = new ArrayList<Tuple>();
 private Object object;
 
 public ReactiveObject(Object object) {
 this.object = object;
 }
 
 
 public void addTuple(Tuple tuple) {
 tuples.add(tuple);
 }
 
 public void removeTuple(Tuple tuple) {
 tuples.remove(tuple);
 }
 
 protected void notifyUpdate() {
 for ( Tuple tuple : tuples ) {
 ReactiveFromNode node = (ReactiveFromNode) tuple.getNode();
 for ( Tuple childTuple : tuple.getChildren() ) {
 if ( childTuple.getObject() == object ) {
 node.propagateChildLeftTupleDelete(childTuple);
 node.propagateLeftIfAllowed(tuple, object);
 break;
 }
 }
 }
 }
 }

  43. 43. ReactiveObject public class MyClass {
 private String name; private ReactiveObject delegate = new ReactiveObject(this);
 
 protected void setName(String name) { this.name = name; delegate.notifyUpdate()
 }
 } public class MyClass extends ReactiveObject {
 private String name; public void MyClass() { super(name);
 } 
 protected void setName(String name) { this.name = name; notifyUpdate()
 }
 }
  44. 44. Benchmark rule R1 when
 $student : Student ()
 $plan : Plan ( owner == $student.name )
 $exam : Exam( plan == $plan.code, course == ”Big Data” ) 
 $grade : Grade( exam == $exam.code ) then // RHS end rule R2 when
 $student : Student ( $plan : plan )
 $exam: Exam( course == ”Big Data” ) from $plan.exams 
 $grade: Grade() from $exam.grades then
 /∗ RHS ∗/ 
 end rule R3 when
 Student( $grade: /plan/exams{course == ”Big Data”}/grades ) then /∗ RHS ∗/ end
  45. 45. Benchmark
  46. 46. Benchmark • Visiting a tree with a relational strategy • Visiting a tree with an Object-Oriented strategy query findNodesWithValue( Node $from, int $value , List list ) 
 Edge( $n : to, $v : to.value ) from $from.outEdges
 eval( $v != $value || ( $v == $value && list .add( $n ) ) ) 
 findNodesWithValue ( $n , $value , list; ) 
 end query findNodesWithValue( int $id , int $value , List list ) $n: Node( id == $id, $v : value ) 
 eval( $v != $value || ( $v == $value && list .add( $n ) ) ) 
 Edge( fromId == $id , $toId : toId )
 findNodesWithValue ( $toId , $value , list; ) 
 end
  47. 47. Related Work • EMF-IncQuery • XPath • SPARQL • Gremlin • JXPath
  48. 48. Conclusion and Future Work • Integrated bytecode weavers for ReactiveObject • Externalise ReactiveObject • Use PropertyChangeListener • Make work with PropertyReactive

×