49
Building A Hybrid Reactive Rule Engine For Relational And Graph Reasoning Mark Proctor, Mario Fusco, István Ráth, Davide Sottara

RuleML2015 : Hybrid Relational and Graph Reasoning

Embed Size (px)

Citation preview

Page 1: RuleML2015 : Hybrid Relational and Graph Reasoning

Building A Hybrid Reactive Rule Engine

For Relational And Graph

ReasoningMark Proctor, Mario Fusco, István Ráth, Davide Sottara

Page 2: RuleML2015 : Hybrid Relational and Graph Reasoning
Page 3: RuleML2015 : Hybrid Relational and Graph Reasoning

The Problem

Page 4: RuleML2015 : Hybrid Relational and Graph Reasoning

Student PlansString namePlan plan

Student

String codeStudent ownerList<Exam> exams

Plan

Plan planString courseString codeList<Grade> exams

ExamExam examint attemptString value

Grade

1

1

1

0..11 0..1

Page 5: RuleML2015 : Hybrid Relational and Graph Reasoning

Student Planspublic 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; }

Page 6: RuleML2015 : Hybrid Relational and Graph Reasoning

Student Planspublic 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;}

Page 7: RuleML2015 : Hybrid Relational and Graph Reasoning

Courses •Communication •Creed - The Jedi Code•Force •Jedi Studies •Meditation •Personal •Situational Awareness•Spirituality - Jedi Mythology•Warrior

Page 8: RuleML2015 : Hybrid Relational and Graph Reasoning

Student Plansprivate 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";

Page 9: RuleML2015 : Hybrid Relational and Graph Reasoning

Student Plansprivate 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) );}

Page 10: RuleML2015 : Hybrid Relational and Graph Reasoning

Student Plansprivate 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 );}

Page 11: RuleML2015 : Hybrid Relational and Graph Reasoning

Student Plans• Email all the “Big Data” people their grades.

Page 12: RuleML2015 : Hybrid Relational and Graph Reasoning

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.

Page 13: RuleML2015 : Hybrid Relational and Graph Reasoning

Student Plans

public class Student { private String name; private String plan;

}

public class Plan { private String code;

private String owner; }

Page 14: RuleML2015 : Hybrid Relational and Graph Reasoning

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;

}

Page 15: RuleML2015 : Hybrid Relational and Graph Reasoning

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; }

Page 16: RuleML2015 : Hybrid Relational and Graph Reasoning

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; }

Page 17: RuleML2015 : Hybrid Relational and Graph Reasoning

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

Page 18: RuleML2015 : Hybrid Relational and Graph Reasoning

Rete

AND

AND

OTN OTN OTN OTN

Root

GradeExamPlanStudent

ANDRTN

Page 19: RuleML2015 : Hybrid Relational and Graph Reasoning

Retepublic abstract class Node { protected Node childNode; public abstract void propagateLeft(Tuple tuple); public abstract void propagateRight(Object object);}

Page 20: RuleML2015 : Hybrid Relational and Graph Reasoning

Retepublic 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)); } } }}

Page 21: RuleML2015 : Hybrid Relational and Graph Reasoning

Rete

AND

OTN

Root

Student [“dp2015”, “yp2015”, “lp2015”]

[“darth”, “yoda”, “luke”]

[“darth”, “yoda”, “luke”]

OTN

Plan

[“dp2015”, “yp2015”, “lp2015”]

AND

Exam

Page 22: RuleML2015 : Hybrid Relational and Graph Reasoning

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; }}

Page 23: RuleML2015 : Hybrid Relational and Graph Reasoning

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; }}

Page 24: RuleML2015 : Hybrid Relational and Graph Reasoning

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; }}

Page 25: RuleML2015 : Hybrid Relational and Graph Reasoning

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]

Page 26: RuleML2015 : Hybrid Relational and Graph Reasoning

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

Page 27: RuleML2015 : Hybrid Relational and Graph Reasoning

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

Page 28: RuleML2015 : Hybrid Relational and Graph Reasoning

Fromrule 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

Page 29: RuleML2015 : Hybrid Relational and Graph Reasoning

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)); } } }

Page 30: RuleML2015 : Hybrid Relational and Graph Reasoning

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)); } } }

Page 31: RuleML2015 : Hybrid Relational and Graph Reasoning

Frompublic 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 } }

Page 32: RuleML2015 : Hybrid Relational and Graph Reasoning

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

Page 33: RuleML2015 : Hybrid Relational and Graph Reasoning

R1, R2, R3rule 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

Page 34: RuleML2015 : Hybrid Relational and Graph Reasoning

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;

Page 35: RuleML2015 : Hybrid Relational and Graph Reasoning

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 ’:=’.

Page 36: RuleML2015 : Hybrid Relational and Graph Reasoning

Advanced OOPath Usage• Transitive closurequery isContainedIn ( Thing $x , Thing $y ) /$y/$x := children ; or /$y/$z := children; and isContainedIn($x, $z;) ) end

Page 37: RuleML2015 : Hybrid Relational and Graph Reasoning

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

Page 38: RuleML2015 : Hybrid Relational and Graph Reasoning

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

Page 39: RuleML2015 : Hybrid Relational and Graph Reasoning

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

Page 40: RuleML2015 : Hybrid Relational and Graph Reasoning

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

Page 41: RuleML2015 : Hybrid Relational and Graph Reasoning

Reactive OOPath• Implementation

• New reactive ‘from’ node.• ReactiveObject Object integration.• List integration.

• Functionality• Uses the OOPath syntax, but now all ‘/‘ are reactive.

Page 42: RuleML2015 : Hybrid Relational and Graph Reasoning

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); }

Page 43: RuleML2015 : Hybrid Relational and Graph Reasoning

ReactiveObjectpublic 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; } } } }}

Page 44: RuleML2015 : Hybrid Relational and Graph Reasoning

ReactiveObjectpublic 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() }}

Page 45: RuleML2015 : Hybrid Relational and Graph Reasoning

Benchmarkrule 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

Page 46: RuleML2015 : Hybrid Relational and Graph Reasoning

Benchmark

Page 47: RuleML2015 : Hybrid Relational and Graph Reasoning

Benchmark• Visiting a tree with a relational strategy

• Visiting a tree with an Object-Oriented strategyquery 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

Page 48: RuleML2015 : Hybrid Relational and Graph Reasoning

Related Work• EMF-IncQuery• XPath• SPARQL• Gremlin• JXPath

Page 49: RuleML2015 : Hybrid Relational and Graph Reasoning

Conclusion and Future Work• Integrated bytecode weavers for ReactiveObject• Externalise ReactiveObject

• Use PropertyChangeListener• Make work with PropertyReactive