Load Rules and Facts From File
Introduction
Loading facts and rules from files is crucial for practical PyReason usage. It provides scalability for large rule sets, reusability across projects, and allows non-programmers to edit domain knowledge without touching Python code.
In this tutorial, we will focus on four functions that load facts and rules
from CSV or JSON files: add_fact_from_csv, add_fact_from_json,
add_rule_from_csv, and add_rule_from_json.
Note
Find the full, executable code here
Graph
Let’s build a simple student-major-department knowledge graph. Alice, Bob, and Mary are students — Alice and Bob enroll in the math major, while Mary enrolls in CS. Each major belongs to a department: math belongs to the math department, and CS belongs to the CS department.
The enrollment relationships are defined as graph edges. The in_department
and scholarship relationships are loaded from external files as facts instead.
import networkx as nx
g = nx.DiGraph()
g.add_nodes_from(['alice', 'bob', 'mary']) # students
g.add_nodes_from(['math', 'cs']) # majors
g.add_nodes_from(['math_dept', 'cs_dept']) # departments
g.add_edge('alice', 'math', enroll=1)
g.add_edge('bob', 'math', enroll=1)
g.add_edge('mary', 'cs', enroll=1)
Load Rules from CSV
Rules can be loaded from a CSV file. Each row has four columns:
rule_text, name, infer_edges, set_static.
rule_text,name,infer_edges,set_static
"under_department(X,Y) <-0 enroll(X,Z), in_department(Z,Y)",under_department_rule,true,false
"eligible(X) <-1 under_department(X,Y), scholarship(Y)",eligible_scholarship_rule,false,false
Note: when the rule text contains a comma, wrap the whole field in quotes.
Then load the file using:
import pyreason as pr
pr.add_rule_from_csv('examples/rules.csv')
Load Rules from JSON
Rules can also be loaded from a JSON file. The JSON should be array of objects. Example:
[
{
"rule_text": "under_department(X,Y) <-0 enroll(X,Z), in_department(Z,Y)",
"name": "under_department_rule",
"infer_edges": true,
"set_static": false
},
{
"rule_text": "eligible(X) <-1 under_department(X,Y), scholarship(Y)",
"name": "eligible_scholarship_rule",
"infer_edges": false,
"set_static": false
}
]
Then load the file using:
pr.add_rule_from_json('examples/rules.json')
Loading Facts from CSV
Facts can be loaded from a CSV file. Each row should have up to 5 comma-separated values in this order: fact_text, name, start_time, end_time, static.
fact_text,name,start_time,end_time,static
scholarship(math_dept),scholarship_math_dept,0,2,False
"in_department(math,math_dept)",math_in_math_department,0,2,False
"in_department(cs,cs_dept)",cs_in_cs_department,0,2,False
Note: when the fact text contains a comma, wrap the whole field in quotes.
Then load the file using:
pr.add_fact_from_csv('examples/facts.csv')
Loading Facts from JSON
Facts can also be loaded from a JSON file. The JSON should be an array of objects. Example:
[
{
"fact_text": "scholarship(math_dept)",
"name": "scholarship_math_dept",
"start_time": 0,
"end_time": 2,
"static": false
},
{
"fact_text": "in_department(math,math_dept)",
"name": "math_in_math_department",
"start_time": 0,
"end_time": 2,
"static": false
},
{
"fact_text": "in_department(cs,cs_dept)",
"name": "cs_in_cs_department",
"start_time": 0,
"end_time": 2,
"static": false
}
]
Then load the file using:
pr.add_fact_from_json('examples/facts.json')
Running PyReason
After loading the graph, rules, and facts using any combination of the four loading functions above, run the reasoning:
interpretation = pr.reason(timesteps=2)
dataframes = pr.filter_and_sort_nodes(interpretation, ['eligible'])
for t, df in enumerate(dataframes):
print(f'TIMESTEP - {t}')
print(df)
print()
Expected Output
TIMESTEP - 0
Empty DataFrame
Columns: [component, eligible]
Index: []
TIMESTEP - 1
component eligible
0 alice [1.0, 1.0]
1 bob [1.0, 1.0]
TIMESTEP - 2
component eligible
0 alice [1.0, 1.0]
1 bob [1.0, 1.0]
At timestep 1, alice and bob become eligible because they are in
math_dept and math_dept has a scholarship. mary is not eligible
because cs_dept has no scholarship fact.
Further Details
For a complete description of parameters and advanced features, see the full API reference in pyreason.py.