POC of stepping through a decision tree one
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
src
.gitignore
LICENSE
README.md
pom.xml

README.md

stepwise_decision_trees

POC of stepping through a decision tree one

This project requires Neo4j 3.4.x or higher

Instructions

This project uses maven, to build a jar-file with the procedure in this project, simply package the project with maven:

mvn clean package

This will produce a jar-file, target/decision_trees_with_rules-1.0-SNAPSHOT.jar, that can be copied to the plugin directory of your Neo4j instance.

cp target/decision_trees_with_rules-1.0-SNAPSHOT.jar neo4j-enterprise-3.4.8/plugins/.

Download and Copy two additional files to your Neo4j plugins directory:

http://central.maven.org/maven2/org/codehaus/janino/commons-compiler/3.0.8/commons-compiler-3.0.8.jar
http://central.maven.org/maven2/org/codehaus/janino/janino/3.0.8/janino-3.0.8.jar

Restart your Neo4j Server.

Create the Schema by running this stored procedure:

CALL com.maxdemarzi.schema.generate

Create some test data:

CREATE (tree:Tree { id: 'bar entrance' })
CREATE (over21_rule:Rule { name: 'Over 21?', parameter_names: 'age', parameter_types:'int', expression:'age >= 21' })
CREATE (gender_rule:Rule { name: 'Over 18 and female', parameter_names: 'age,gender', parameter_types:'int,String', expression:'(age >= 18) && gender.equals(\"female\")' })
CREATE (answer_yes:Answer { id: 'yes'})
CREATE (answer_no:Answer { id: 'no'})
CREATE (tree)-[:HAS]->(over21_rule)
CREATE (over21_rule)-[:IS_TRUE]->(answer_yes)
CREATE (over21_rule)-[:IS_FALSE]->(gender_rule)
CREATE (gender_rule)-[:IS_TRUE]->(answer_yes)
CREATE (gender_rule)-[:IS_FALSE]->(answer_no)    
CREATE (age:Parameter {name:'age', type:'int', prompt:'How old are you?', expression:'(age > 0) &&  (age < 150)'})
CREATE (gender:Parameter {name:'gender', type:'String', prompt:'What is your gender?', expression: '\"male\".equals(gender) || \"female\".equals(gender)'} )
CREATE (over21_rule)-[:REQUIRES]->(age)
CREATE (gender_rule)-[:REQUIRES]->(age)
CREATE (gender_rule)-[:REQUIRES]->(gender)

Try it:

CALL com.maxdemarzi.stepwise.decision_tree('bar entrance', {});
CALL com.maxdemarzi.stepwise.decision_tree('bar entrance', {age:'20'});
CALL com.maxdemarzi.stepwise.decision_tree('bar entrance', {age:'24'}); 
CALL com.maxdemarzi.stepwise.decision_tree('bar entrance', {gender:'male', age:'20'});
CALL com.maxdemarzi.stepwise.decision_tree('bar entrance', {gender:'female', age:'19'});
CALL com.maxdemarzi.stepwise.decision_tree('bar entrance', {gender:'male', age:'23'});     

Create some more test data:

CREATE (tree:Tree { id: 'funeral' })
CREATE (good_man_rule:Rule { name: 'Was Lil Jon a good man?', parameter_names: 'answer_1', parameter_types:'String', script:'switch (answer_1) { case \"yeah\": return \"OPTION_1\"; case \"what\": return \"OPTION_2\"; case \"okay\": return \"OPTION_3\"; default: return \"UNKNOWN\"; }' })
CREATE (good_man_two_rule:Rule { name: 'I said, was he a good man?', parameter_names: 'answer_2', parameter_types:'String', script:'switch (answer_2) { case \"yeah\": return \"OPTION_1\"; case \"what\": return \"OPTION_2\"; case \"okay\": return \"OPTION_3\"; default: return \"UNKNOWN\"; }' })
CREATE (rest_in_peace_rule:Rule { name: 'May he rest in peace', parameter_names: 'answer_3', parameter_types:'String', script:'switch (answer_3) { case \"yeah\": return \"OPTION_1\"; case \"what\": return \"OPTION_2\"; case \"okay\": return \"OPTION_3\"; default: return \"UNKNOWN\"; } ' })
CREATE (answer_correct:Answer { id: 'correct'})
CREATE (answer_incorrect:Answer { id: 'incorrect'})
CREATE (answer_unknown:Answer { id: 'unknown'})
CREATE (tree)-[:HAS]->(good_man_rule)
CREATE (good_man_rule)-[:OPTION_1]->(answer_incorrect)
CREATE (good_man_rule)-[:OPTION_2]->(good_man_two_rule)
CREATE (good_man_rule)-[:OPTION_3]->(answer_incorrect)
CREATE (good_man_rule)-[:UNKNOWN]->(answer_unknown)    
CREATE (good_man_two_rule)-[:OPTION_1]->(rest_in_peace_rule)
CREATE (good_man_two_rule)-[:OPTION_2]->(answer_incorrect)
CREATE (good_man_two_rule)-[:OPTION_3]->(answer_incorrect)
CREATE (good_man_two_rule)-[:UNKNOWN]->(answer_unknown)    
CREATE (rest_in_peace_rule)-[:OPTION_1]->(answer_incorrect)
CREATE (rest_in_peace_rule)-[:OPTION_2]->(answer_incorrect)
CREATE (rest_in_peace_rule)-[:OPTION_3]->(answer_correct)
CREATE (rest_in_peace_rule)-[:UNKNOWN]->(answer_unknown)
CREATE (parameter1:Parameter {name:'answer_1', type:'String', prompt:'What is the first answer?', expression:'\"yeah\".equals(answer_1) || \"what\".equals(answer_1) || \"okay\".equals(answer_1) || \"\".equals(answer_1)'})
CREATE (parameter2:Parameter {name:'answer_2', type:'String', prompt:'What is the second answer?', expression:'\"yeah\".equals(answer_2) || \"what\".equals(answer_2) || \"okay\".equals(answer_2) || \"\".equals(answer_2)'})
CREATE (parameter3:Parameter {name:'answer_3', type:'String', prompt:'What is the third answer?', expression:'\"yeah\".equals(answer_3) || \"what\".equals(answer_3) || \"okay\".equals(answer_3) || \"\".equals(answer_3)'})
CREATE (good_man_rule)-[:REQUIRES]->(parameter1)
CREATE (good_man_two_rule)-[:REQUIRES]->(parameter2)
CREATE (rest_in_peace_rule)-[:REQUIRES]->(parameter3)

Try it:

CALL com.maxdemarzi.stepwise.decision_tree('funeral', {});
CALL com.maxdemarzi.stepwise.decision_tree('funeral', {answer_1:'what'});
CALL com.maxdemarzi.stepwise.decision_tree('funeral', {answer_1:'yeah', answer_2:'yeah', answer_3:'yeah'});    
CALL com.maxdemarzi.stepwise.decision_tree('funeral', {answer_1:'what', answer_2:'', answer_3:''});    
CALL com.maxdemarzi.stepwise.decision_tree('funeral', {answer_1:'what', answer_2:'yeah', answer_3:'okay'});

Validate Parameters:

CALL com.maxdemarzi.stepwise.validate('age', '20');
CALL com.maxdemarzi.stepwise.validate('age', '-45');
CALL com.maxdemarzi.stepwise.validate('age', 'cat');
CALL com.maxdemarzi.stepwise.validate('gender', 'attack helicopter');