### Install Project Requirements Source: https://github.com/lab-v2/pyreason/blob/main/contributing.md Installs the necessary dependencies for the project. Run this after cloning the repository. ```bash pip install -r requirements.txt ``` -------------------------------- ### Install PyReason Source: https://github.com/lab-v2/pyreason/blob/main/docs/pyreason_library.md Install the PyReason library using pip and import it into your Python session. Initializing PyReason may take a few minutes. ```bash pip install pyreason python import pyreason ``` -------------------------------- ### Install Testing Dependencies Source: https://github.com/lab-v2/pyreason/blob/main/contributing.md Installs dependencies required for running the test suites. ```bash make install-deps ``` -------------------------------- ### Running the Counterfactual Tutorial Example Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/tutorials/counterfactual_tutorial.md Executes the Python script that runs all counterfactual demos and prints the resulting trace differences. CSV traces are saved to the working directory. ```python python examples/counterfactual_tutorial_ex.py ``` -------------------------------- ### Install Python Version using pyenv Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/tutorials/installation.md Installs a specific Python version (e.g., 3.8) using pyenv. Ensure you have the necessary build dependencies installed. ```bash pyenv install 3.8 ``` -------------------------------- ### Install PyReason Source: https://github.com/lab-v2/pyreason/blob/main/README.md Install the PyReason library using pip. This command is used to add the library to your Python environment. ```bash pip install pyreason ``` -------------------------------- ### Example PyReason Facts and Rules Output Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/tutorials/natural_language_to_pyreason.md This is an example of the output generated by the LLM after processing the prompt. It shows the conversion of English statements into PyReason's fact and rule syntax, adhering to the specified constraints. ```default Facts: lawyer(carlos):[1,1] lawyer(emma):[1,1] wins_cases_regularly(emma):[1,1] wins_cases_regularly(carlos):[0,0] Rules: strong_reputation(X):[0.8,1] <- lawyer(X), wins_cases_regularly(X) attract_high_profile_clients(X):[0.8,1] <- strong_reputation(X) ``` -------------------------------- ### Nodes Trace Example Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/user_guide/6_pyreason_output.md Displays the structure of the nodes trace output, showing time, operation, node, and reasons for changes. Useful for understanding individual node state evolution. ```text Time Fixed-Point-Operation Node ... Occurred Due To Clause-1 Clause-2 0 0 0 popular-fac ... popular(customer_0) None None 1 1 2 popular-fac ... popular(customer_0) None None 2 1 2 customer_4 ... cool_car_rule [(customer_4, Car_4)] [Car_4] 3 1 2 customer_6 ... cool_car_rule [(customer_6, Car_4)] [Car_4] 4 1 2 customer_3 ... cool_pet_rule [(customer_3, Pet_2)] [Pet_2] 5 1 2 customer_4 ... cool_pet_rule [(customer_4, Pet_2)] [Pet_2] 6 1 3 customer_4 ... trendy_rule [customer_4] [customer_4] 7 2 4 popular-fac ... popular(customer_0) None None 8 2 4 customer_4 ... cool_car_rule [(customer_4, Car_4)] [Car_4] 9 2 4 customer_6 ... cool_car_rule [(customer_6, Car_4)] [Car_4] 10 2 4 customer_3 ... cool_pet_rule [(customer_3, Pet_2)] [Pet_2] 11 2 4 customer_4 ... cool_pet_rule [(customer_4, Pet_2)] [Pet_2] 12 2 5 customer_4 ... trendy_rule [customer_4] [customer_4] 13 3 6 popular-fac ... popular(customer_0) None None 14 3 6 customer_4 ... cool_car_rule [(customer_4, Car_4)] [Car_4] 15 3 6 customer_6 ... cool_car_rule [(customer_6, Car_4)] [Car_4] 16 3 6 customer_3 ... cool_pet_rule [(customer_3, Pet_2)] [Pet_2] 17 3 6 customer_4 ... cool_pet_rule [(customer_4, Pet_2)] [Pet_2] 18 3 7 customer_4 ... trendy_rule [customer_4] [customer_4] 19 4 8 popular-fac ... popular(customer_0) None None 20 4 8 customer_4 ... cool_car_rule [(customer_4, Car_4)] [Car_4] 21 4 8 customer_6 ... cool_car_rule [(customer_6, Car_4)] [Car_4] 22 4 8 customer_3 ... cool_pet_rule [(customer_3, Pet_2)] [Pet_2] 23 4 8 customer_4 ... cool_pet_rule [(customer_4, Pet_2)] [Pet_2] 24 4 9 customer_4 ... trendy_rule [customer_4] [customer_4] 25 5 10 popular-fac ... popular(customer_0) None None 26 5 10 customer_4 ... cool_car_rule [(customer_4, Car_4)] [Car_4] 27 5 10 customer_6 ... cool_car_rule [(customer_6, Car_4)] [Car_4] 28 5 10 customer_3 ... cool_pet_rule [(customer_3, Pet_2)] [Pet_2] 29 5 10 customer_4 ... cool_pet_rule [(customer_4, Pet_2)] [Pet_2] 30 5 11 customer_4 ... trendy_rule [customer_4] [customer_4] ``` -------------------------------- ### PyReason Basic Example Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/examples_rst/basic_example.md This snippet demonstrates the core workflow of PyReason: graph creation, rule addition, fact assertion, and reasoning execution. It's useful for understanding the fundamental steps involved in applying PyReason to a knowledge graph. ```python # Test if the simple hello world program works import pyreason as pr import faulthandler import networkx as nx # Reset PyReason pr.reset() pr.reset_rules() pr.reset_settings() # ================================ CREATE GRAPH==================================== # Create a Directed graph g = nx.DiGraph() # Add the nodes g.add_nodes_from(['John', 'Mary', 'Justin']) g.add_nodes_from(['Dog', 'Cat']) # Add the edges and their attributes. When an attribute = x which is <= 1, the annotation # associated with it will be [x,1]. NOTE: These attributes are immutable # Friend edges g.add_edge('Justin', 'Mary', Friends=1) g.add_edge('John', 'Mary', Friends=1) g.add_edge('John', 'Justin', Friends=1) # Pet edges g.add_edge('Mary', 'Cat', owns=1) g.add_edge('Justin', 'Cat', owns=1) g.add_edge('Justin', 'Dog', owns=1) g.add_edge('John', 'Dog', owns=1) # Modify pyreason settings to make verbose pr.settings.verbose = True # Print info to screen # pr.settings.optimize_rules = False # Disable rule optimization for debugging # Load all the files into pyreason pr.load_graph(g) pr.add_rule(pr.Rule('popular(x) <-1 popular(y), Friends(x,y), owns(y,z), owns(x,z)', 'popular_rule')) pr.add_fact(pr.Fact('popular(Mary)', 'popular_fact', 0, 2)) # Run the program for two timesteps to see the diffusion take place faulthandler.enable() interpretation = pr.reason(timesteps=2) # Display the changes in the interpretation for each timestep dataframes = pr.filter_and_sort_nodes(interpretation, ['popular']) for t, df in enumerate(dataframes): print(f'TIMESTEP - {t}') print(df) print() assert len(dataframes[0]) == 1, 'At t=0 there should be one popular person' assert len(dataframes[1]) == 2, 'At t=1 there should be two popular people' assert len(dataframes[2]) == 3, 'At t=2 there should be three popular people' # Mary should be popular in all three timesteps assert 'Mary' in dataframes[0]['component'].values and dataframes[0].iloc[0].popular == [1, 1], 'Mary should have popular bounds [1,1] for t=0 timesteps' assert 'Mary' in dataframes[1]['component'].values and dataframes[1].iloc[0].popular == [1, 1], 'Mary should have popular bounds [1,1] for t=1 timesteps' assert 'Mary' in dataframes[2]['component'].values and dataframes[2].iloc[0].popular == [1, 1], 'Mary should have popular bounds [1,1] for t=2 timesteps' # Justin should be popular in timesteps 1, 2 assert 'Justin' in dataframes[1]['component'].values and dataframes[1].iloc[1].popular == [1, 1], 'Justin should have popular bounds [1,1] for t=1 timesteps' assert 'Justin' in dataframes[2]['component'].values and dataframes[2].iloc[2].popular == [1, 1], 'Justin should have popular bounds [1,1] for t=2 timesteps' # John should be popular in timestep 3 assert 'John' in dataframes[2]['component'].values and dataframes[2].iloc[1].popular == [1, 1], 'John should have popular bounds [1,1] for t=2 timesteps' ``` -------------------------------- ### Example Rule Structure Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/user_guide/3_pyreason_rules.md Illustrates the textual format of a PyReason rule, including head, body, timestep, and bounds. ```text head(x) : [1,1] <-1 clause1(y) : [1,1] , clause2(x,y) : [1,1] , clause3(y,z) : [1,1] , clause4(x,z) : [1,1] ``` ```text head(x) <-1 clause1(y), clause2(x,y), clause3(y,z), clause4(x,z) ``` -------------------------------- ### Edges Trace Example Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/user_guide/6_pyreason_output.md Illustrates the format of the edges trace output, detailing time and the clauses that led to edge state changes. Useful for analyzing relationship dynamics. ```text Time ... Clause-2 0 0 ... [(customer_1, Car_0), (customer_1, Car_8)] 1 0 ... [(customer_1, Car_0), (customer_1, Car_8)] 2 0 ... [(customer_2, Car_1), (customer_2, Car_3), (cu... 3 0 ... [(customer_1, Car_0), (customer_1, Car_8)] 4 0 ... [(customer_1, Car_0), (customer_1, Car_8)] .. ... ... ... 61 5 ... [(customer_0, Car_2), (customer_0, Car_7)] 62 5 ... [(customer_5, Car_5), (customer_5, Car_2)] 63 5 ... [(customer_3, Car_3), (customer_3, Car_0), (cu... 64 5 ... [(customer_6, Car_6), (customer_6, Car_4)] 65 5 ... [(customer_0, Car_2), (customer_0, Car_7)] ``` -------------------------------- ### Configure Model Interface Options Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/user_guide/9_machine_learning_integration.md Set up options for integrating model predictions into PyReason, including threshold, bounds, and snap value. This example configures to process probabilities above 0.5 and set the lower bound to 1.0. ```python interface_options = pr.ModelInterfaceOptions( threshold=0.5, # Only process probabilities above 0.5 set_lower_bound=True, # Modify the lower bound. set_upper_bound=False, # Keep the upper bound unchanged at 1.0. snap_value=1.0 # Use 1.0 as the snap value. ) ``` -------------------------------- ### Valid Fact Text Examples Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/user_guide/2_pyreason_facts.md These examples show different ways to format the fact_text parameter, including specifying bounds and negation. ```text 1. 'pred(x,y) : [0.2, 1]' 2. 'pred(x,y)' 3. '~pred(x,y)' ``` -------------------------------- ### Install pyenv and Dependencies on Linux/Unix/macOS Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/tutorials/installation.md Installs pyenv using Homebrew and essential build dependencies for Python on Linux/Unix/macOS systems. Ensure your system has the necessary prerequisites before running. ```bash brew update brew install pyenv sudo apt-get update sudo apt-get install make build-essential libssl-dev zlib1g-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev liblzma-dev python-openssl git curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash ``` -------------------------------- ### Example Extracted Facts and Rules Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/tutorials/natural_language_to_pyreason.md This is the output generated by the LLM after processing the example paragraph using the extraction prompt. It shows the structured facts and rules in English. ```text Facts: - Carlos is a lawyer - Emma is a lawyer - Emma wins cases regularly - Carlos does not win cases regularly Rules: - All lawyers who win cases regularly tend to build a strong reputation - Anyone with a strong reputation is likely to attract high-profile clients ``` -------------------------------- ### Inconsistent Predicate List Example Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/tutorials/understanding_logic.md This example demonstrates an inconsistent logic program where two rules contradict each other, leading to an impossible state. ```default r1: grass_wet <- rained, r2: ~ grass_wet <- rained, f1: rained <- ``` -------------------------------- ### Example Node Trace Output Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/user_guide/6_pyreason_output.md This is a sample of the CSV output for a node trace, showing changes in node bounds over time. It includes details like the time, operation, node, label, and the reason for the change. ```text Time,Fixed-Point-Operation,Node,Label,Old Bound,New Bound,Occurred Due To 0,0,Amsterdam_Airport_Schiphol,Amsterdam_Airport_Schiphol,"[0.0,1.0]","[1.0,1.0]",graph-attribute-fact 0,0,Riga_International_Airport,Riga_International_Airport,"[0.0,1.0]","[1.0,1.0]",graph-attribute-fact 0,0,Chișinău_International_Airport,Chișinău_International_Airport,"[0.0,1.0]","[1.0,1.0]",graph-attribute-fact 0,0,Yali,Yali,"[0.0,1.0]","[1.0,1.0]",graph-attribute-fact 0,0,Düsseldorf_Airport,Düsseldorf_Airport,"[0.0,1.0]","[1.0,1.0]",graph-attribute-fact 0,0,Pobedilovo_Airport,Pobedilovo_Airport,"[0.0,1.0]","[1.0,1.0]",graph-attribute-fact 0,0,Dubrovnik_Airport,Dubrovnik_Airport,"[0.0,1.0]","[1.0,1.0]",graph-attribute-fact 0,0,Hévíz-Balaton_Airport,Hévíz-Balaton_Airport,"[0.0,1.0]","[1.0,1.0]",graph-attribute-fact 0,0,Athens_International_Airport,Athens_International_Airport,"[0.0,1.0]","[1.0,1.0]",graph-attribute-fact 0,0,Vnukovo_International_Airport,Vnukovo_International_Airport,"[0.0,1.0]","[1.0,1.0]",graph-attribute-fact ``` -------------------------------- ### Validate Test Runner Setup Source: https://github.com/lab-v2/pyreason/blob/main/contributing.md Executes a script to validate the test runner's configuration. ```python python test_runner_validation.py ``` -------------------------------- ### Animals Domain Example Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/tutorials/natural_language_to_pyreason.md Extracts facts and rules from an animal-themed paragraph. This tests the pipeline's ability to generalize across different subjects. ```text Rex and Bella are both dogs. All dogs that exercise daily tend to stay healthy. Bella exercises daily. Any dog that stays healthy is likely to live long. Rex does not exercise daily. ``` -------------------------------- ### Prompt for Converting English to PyReason Syntax Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/tutorials/natural_language_to_pyreason.md This prompt guides an LLM to convert English facts and rules into PyReason syntax, including detailed explanations of fact and rule syntax, variable usage, negation, and naming conventions. It also specifies output constraints like no markdown and only two sections: Facts and Rules. ```python PROMPT_CONVERT = f"""Convert the facts and rules below into PyReason syntax. FACT syntax and examples: predicate(node):[l,u] predicate(node):[1,1] ([1,1] means completely true) e.g. student(alice):[1,1] (Alice is a student) predicate(node):[0,0] ([0,0] means completely false) e.g. student(marie):[0,0] (Marie is not a student) predicate(node):[0.8,1] ([0.8,1] means likely, "tend to", "usually") e.g. doctor(bob):[0.8,1] (Bob is likely a doctor) predicate(node1,node2):[1,1] e.g. enrolled_in(ryan,cs):[1,1] (Ryan enrolled in cs major) RULE syntax: head(X):[bound] <- condition1(X), condition2(X,Y) Use variables X, Y (never specific names): example: grandparent(X,Y) <- parent(X,Z), parent(Z,Y) Include ALL conditions from the English rule, even if they seem redundant. Constraints: 1. Predicate names: lowercase_with_underscores, no spaces, no capital letters. 2. Rule's head name describes WHAT, bound [l,u] describes HOW CERTAIN. Don't use uncertain name for rule's head. 3. Facts use specific names (john, mary) lower case is prefered in specific name. Rules use variables (X, Y). 4. Negation in facts: use [0,0] on the SAME predicate, never invent a new predicate. e.g. "Alice is not student" -> student(alice):[0,0] NOT not_student(alice):[1,1] 5. Rules with one condition use only X: good_grade(X) <- study_hard(X) Only introduce Y or Z when two different entities are involved. ### No markdown, no code blocks, no comments. Output ONLY the two sections. Facts and rules to convert: {{english_output}} Facts: Rules: """ ``` -------------------------------- ### Example Edge Trace Output Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/user_guide/6_pyreason_output.md This is a sample of the CSV output for an edge trace, detailing changes in edge relationships over time. It includes information on the time, operation, edge, label, bounds, and the clauses that triggered the changes. ```text Time,Fixed-Point-Operation,Edge,Label,Old Bound,New Bound,Occurred Due To,Clause-1,Clause-2,Clause-3 0,0,"('Amsterdam_Airport_Schiphol', 'Yali')",isConnectedTo,"[0.0,1.0]","[1.0,1.0]",graph-attribute-fact,,, 0,0,"('Riga_International_Airport', 'Amsterdam_Airport_Schiphol')",isConnectedTo,"[0.0,1.0]","[1.0,1.0]",graph-attribute-fact,,, 0,0,"('Riga_International_Airport', 'Düsseldorf_Airport')",isConnectedTo,"[0.0,1.0]","[1.0,1.0]",graph-attribute-fact,,, 0,0,"('Chișinău_International_Airport', 'Riga_International_Airport')",isConnectedTo,"[0.0,1.0]","[1.0,1.0]",graph-attribute-fact,,, 0,0,"('Düsseldorf_Airport', 'Dubrovnik_Airport')",isConnectedTo,"[0.0,1.0]","[1.0,1.0]",graph-attribute-fact,,, 0,0,"('Pobedilovo_Airport', 'Vnukovo_International_Airport')",isConnectedTo,"[0.0,1.0]","[1.0,1.0]",graph-attribute-fact,,, 0,0,"('Dubrovnik_Airport', 'Athens_International_Airport')",isConnectedTo,"[0.0,1.0]","[1.0,1.0]",graph-attribute-fact,,, 0,0,"('Vnukovo_International_Airport', 'Hévíz-Balaton_Airport')",isConnectedTo,"[0.0,1.0]","[1.0,1.0]",graph-attribute-fact,,, 1,1,"('Vnukovo_International_Airport', 'Riga_International_Airport')",isConnectedTo,"[0.0,1.0]","[1.0,1.0]",connected_rule_1,"[('Riga_International_Airport', 'Amsterdam_Airport_Schiphol')]",['Amsterdam_Airport_Schiphol'],['Vnukovo_International_Airport'] ``` -------------------------------- ### Run PyReason with ML Facts and Get Trace Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/user_guide/9_machine_learning_integration.md Enable ground rules and atom tracing in PyReason settings to allow reasoning over classifier prediction facts. Execute the reasoning engine and retrieve the rule trace for analysis. ```python # Run the reasoning engine to allow the investigation flag to propagate through the network. pr.settings.allow_ground_rules = True # The ground rules allow us to use the classifier prediction facts pr.settings.atom_trace = True interpretation = pr.reason() trace = pr.get_rule_trace(interpretation) print(f"RULE TRACE: \n\n{trace[0]}\n") ``` -------------------------------- ### Create and Load Graph Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/tutorials/custom_thresholds.md Initializes a NetworkX graph with nodes and edges, then loads it into PyReason. ```python import networkx as nx # Create an empty graph G = nx.Graph() # Add nodes nodes = ["TextMessage", "Zach", "Justin", "Michelle", "Amy"] G.add_nodes_from(nodes) # Add edges with attribute 'HaveAccess' edges = [ ("Zach", "TextMessage", {"HaveAccess": 1}), ("Justin", "TextMessage", {"HaveAccess": 1}), ("Michelle", "TextMessage", {"HaveAccess": 1}), ("Amy", "TextMessage", {"HaveAccess": 1}) ] G.add_edges_from(edges) ``` ```python import pyreason as pr pr.load_graph(G) ``` -------------------------------- ### Initialize Customer Data Source: https://github.com/lab-v2/pyreason/blob/main/docs/advanced_graph.ipynb Creates a dictionary mapping customer index to their details (name, gender, origin city, origin state). ```python customers = ['John', 'Mary', 'Justin', 'Alice', 'Bob', 'Eva', 'Mike'] customer_details = [ ('John', 'M', 'New York', 'NY'), ('Mary', 'F', 'Los Angeles', 'CA'), ('Justin', 'M', 'Chicago', 'IL'), ('Alice', 'F', 'Houston', 'TX'), ('Bob', 'M', 'Phoenix', 'AZ'), ('Eva', 'F', 'San Diego', 'CA'), ('Mike', 'M', 'Dallas', 'TX') ] customer_dict = {i: customer for i, customer in enumerate(customer_details)} customer_dict ``` -------------------------------- ### Set Up Pre-Commit Hooks Source: https://github.com/lab-v2/pyreason/blob/main/contributing.md Enables pre-commit and pre-push hooks to ensure code quality and consistency before commits and pushes. ```bash pre-commit install --hook-type pre-commit --hook-type pre-push ``` -------------------------------- ### Basic PyReason Usage Source: https://github.com/lab-v2/pyreason/blob/main/docs/pyreason_library.md Demonstrates the basic workflow for using PyReason: loading a graph, adding rules and facts, setting verbose mode, and initiating the reasoning process. Load graphs and rules before reasoning. Facts and labels are optional but recommended. ```python import pyreason as pr pr.load_graph(some_networkx_graph) pr.add_rule(rule_written_in_pyreason_format) pr.add_fact(pr.Fact(...)) pr.settings.verbose = True interpretation = pr.reason() ``` -------------------------------- ### Example PyReason Rule Validation Output Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/tutorials/natural_language_to_pyreason.md This output shows the result of validating the example PyReason rules. It indicates that both rules passed the validation process, meaning they are syntactically correct according to the pyreason parser. ```default Validating rules... Rule passed strong_reputation(X):[0.8,1] <- lawyer(X), wins_cases_regularly(X) Rule passed attract_high_profile_clients(X):[0.8,1] <- strong_reputation(X) ``` -------------------------------- ### Check System Status and Dependencies Source: https://github.com/lab-v2/pyreason/blob/main/contributing.md Runs utility commands to check system status and verify dependencies. ```bash make info ``` ```bash make check-deps ``` -------------------------------- ### Add Rules from File Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/user_guide/3_pyreason_rules.md Loads multiple rules from a .txt file, ignoring comments. Each rule should be on a new line. ```text # This is a comment and will be ignored head1(x) <-1 body(y), body2(x,y), body3(y,z), body4(x,z) head2(x) <-1 body(y), body2(x,y), body3(y,z), body4(x,z) ``` ```python import pyreason as pr pr.add_rules_from_file('rules.txt') ``` -------------------------------- ### Get and Display Interpretation Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/examples_rst/advanced_example.md Retrieves the interpretation as a dictionary and prints it. This is useful for inspecting the raw interpretation data. ```python interpretations_dict = interpretation.get_dict() pprint(interpretations_dict) ``` -------------------------------- ### Initialize Car Data Source: https://github.com/lab-v2/pyreason/blob/main/docs/advanced_graph.ipynb Creates a dictionary mapping car index to their details (model, color). ```python # Separate lists for car models and colors car_details = [ ('Toyota Camry', 'Red'), ('Honda Civic', 'Blue'), ('Ford Focus', 'Red'), ('BMW 3 Series', 'Black'), ('Tesla Model S', 'Red'), ('Chevrolet Bolt EV', 'White'), ('Ford Mustang', 'Yellow'), ('Audi A4', 'Silver'), ('Mercedes-Benz C-Class', 'Grey'), ('Subaru Outback', 'Green'), ('Volkswagen Golf', 'Blue'), ('Porsche 911', 'Black') ] car_dict = {i: car for i, car in enumerate(car_details)} car_dict ``` -------------------------------- ### Get and Save Rule Trace Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/tutorials/cybersecurity_inconsistency.md Retrieves the node and edge traces from a PyReason interpretation and saves the full rule trace for inspection. ```python node_trace, edge_trace = pr.get_rule_trace(interpretation) pr.save_rule_trace(interpretation) ``` -------------------------------- ### Build Initial Graph Structure Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/tutorials/load_rules_facts_from_file.md Initializes a directed graph and adds nodes and edges representing student enrollments. ```python 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) ``` -------------------------------- ### Initialize Travel Data Source: https://github.com/lab-v2/pyreason/blob/main/docs/advanced_graph.ipynb Sets up a list of tuples representing travel details, including traveler, origin, destination, and duration. ```python travels = [ ('John', 'Los Angeles', 'CA', 'New York', 'NY', 2), ('Alice', 'Houston', 'TX', 'Phoenix', 'AZ', 5), ('Eva', 'San Diego', 'CA', 'Dallas', 'TX', 1), ('Mike', 'Dallas', 'TX', 'Chicago', 'IL', 3) ] ``` -------------------------------- ### Medical Domain Example Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/tutorials/natural_language_to_pyreason.md Extracts facts and rules from a medical-themed paragraph. This serves as a basic test case for the natural language processing pipeline. ```text Tom and Lisa are both nurses. All nurses who work night shifts tend to experience fatigue. Lisa works night shifts. Anyone who experiences fatigue is likely to make errors. Tom does not work night shifts. ``` -------------------------------- ### Initialize PyReason and Load Graph Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/tutorials/infer_edges.md Initializes PyReason settings, resets rules, and loads the NetworkX graph into PyReason for processing. Ensure PyReason is imported before use. ```python import pyreason as pr pr.reset() pr.reset_rules() # Modify pyreason settings to make verbose and to save the rule trace to a file pr.settings.verbose = True pr.settings.atom_trace = True pr.settings.memory_profile = False pr.settings.canonical = True pr.settings.inconsistency_check = False pr.settings.static_graph_facts = False pr.settings.output_to_file = False pr.settings.store_interpretation_changes = True pr.settings.save_graph_attributes_to_trace = True # Load all the files into pyreason pr.load_graph(G) ``` -------------------------------- ### Infer Edges with PyReason Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/user_guide/6_pyreason_output.md Loads a graph, adds a rule with infer_edges=True, and runs the PyReason interpretation for one timestep. This setup is used to demonstrate edge inference. ```python pr.load_graph(G) pr.add_rule(pr.Rule('isConnectedTo(A, Y) <-1 isConnectedTo(Y, B), Amsterdam_Airport_Schiphol(B), Vnukovo_International_Airport(A)', 'connected_rule_1', infer_edges=True)) # Run the program for two timesteps to see the diffusion take place interpretation = pr.reason(timesteps=1) ``` -------------------------------- ### Initialize PyReason and Load NetworkX Graph Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/tutorials/cybersecurity_inconsistency.md Initializes PyReason, resets rules, creates a NetworkX directed graph, and adds nodes and edges representing assets, software, and CVEs with their relationships. ```python import pyreason as pr import networkx as nx pr.reset() pr.reset_rules() g = nx.DiGraph() # Asset nodes g.add_nodes_from(['web_server', 'workstation_1', 'dev_server']) # Software nodes g.add_nodes_from(['sudo_1_9_5p1', 'linux_kernel_5_1', 'openssl_3_0_1']) # CVE nodes (constants start with lowercase per PyReason convention) g.add_nodes_from(['cve_2021_3156', 'cve_2022_0185', 'cve_2022_26923']) # Which asset runs which software g.add_edge('web_server', 'sudo_1_9_5p1', runs=1) g.add_edge('workstation_1', 'linux_kernel_5_1', runs=1) g.add_edge('dev_server', 'openssl_3_0_1', runs=1) # Which CVE affects which software g.add_edge('sudo_1_9_5p1', 'cve_2021_3156', has_cve=1) g.add_edge('linux_kernel_5_1', 'cve_2022_0185', has_cve=1) g.add_edge('openssl_3_0_1', 'cve_2022_26923', has_cve=1) ``` -------------------------------- ### Run All Test Suites Source: https://github.com/lab-v2/pyreason/blob/main/contributing.md Executes all configured test suites with unified coverage reporting. ```bash make test ``` -------------------------------- ### Get Rule Trace from PyReason Interpretation Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/user_guide/6_pyreason_output.md Retrieve the trace of applied rules for nodes and edges after a PyReason interpretation has been executed. This is useful for debugging and understanding the reasoning process. ```python interpretation = pr.reason(timesteps=5) nodes_trace, edges_trace = pr.get_rule_trace(interpretation) ``` -------------------------------- ### Create a Directed Graph with Networkx Source: https://github.com/lab-v2/pyreason/blob/main/docs/hello-world.md This snippet demonstrates how to initialize a directed graph using Networkx and add nodes and edges with attributes representing relationships like 'Friends' and 'owns'. ```python import networkx as nx # ================================ CREATE GRAPH==================================== # Create a Directed graph g = nx.DiGraph() # Add the nodes g.add_nodes_from(['John', 'Mary', 'Justin']) g.add_nodes_from(['Dog', 'Cat']) # Add the edges and their attributes. When an attribute = x which is <= 1, the annotation # associated with it will be [x,1]. NOTE: These attributes are immutable # Friend edges g.add_edge('Justin', 'Mary', Friends=1) g.add_edge('John', 'Mary', Friends=1) g.add_edge('John', 'Justin', Friends=1) # Pet edges g.add_edge('Mary', 'Cat', owns=1) g.add_edge('Justin', 'Cat', owns=1) g.add_edge('Justin', 'Dog', owns=1) g.add_edge('John', 'Dog', owns=1) ``` -------------------------------- ### Inconsistent Rules Example Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/key_concepts.md Demonstrates a logical inconsistency where two rules with the same premise lead to contradictory conclusions. PyReason resolves such inconsistencies by resetting affected interpretations to a state of complete uncertainty. ```text rule-1: grass_wet <- rained, rule-2: ~grass_wet <- rained, ``` -------------------------------- ### Define Customer, Pet, and Car Details Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/tutorials/advanced_tutorial.md Initializes lists containing details for customers, pets, and cars. These lists serve as the source data for creating graph nodes. ```python customer_details = [ ('John', 'M', 'New York', 'NY'), ('Mary', 'F', 'Los Angeles', 'CA'), ('Justin', 'M', 'Chicago', 'IL'), ('Alice', 'F', 'Houston', 'TX'), ('Bob', 'M', 'Phoenix', 'AZ'), ('Eva', 'F', 'San Diego', 'CA'), ('Mike', 'M', 'Dallas', 'TX') ] pet_details = [ ('Dog', 'Mammal'), ('Cat', 'Mammal'), ('Rabbit', 'Mammal'), ('Parrot', 'Bird'), ('Fish', 'Fish') ] car_details = [ ('Toyota Camry', 'Red'), ('Honda Civic', 'Blue'), ('Ford Focus', 'Red'), ('BMW 3 Series', 'Black'), ('Tesla Model S', 'Red'), ('Chevrolet Bolt EV', 'White'), ('Ford Mustang', 'Yellow'), ('Audi A4', 'Silver'), ('Mercedes-Benz C-Class', 'Grey'), ('Subaru Outback', 'Green'), ('Volkswagen Golf', 'Blue'), ('Porsche 911', 'Black') ] travels = [ ('John', 'Los Angeles', 'CA', 'New York', 'NY', 2), ('Alice', 'Houston', 'TX', 'Phoenix', 'AZ', 5), ('Eva', 'San Diego', 'CA', 'Dallas', 'TX', 1), ('Mike', 'Dallas', 'TX', 'Chicago', 'IL', 3) ] ``` -------------------------------- ### Run Classifier and Get Facts Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/user_guide/9_machine_learning_integration.md Execute the integrated classifier with dummy input data to obtain model predictions (logits, probabilities) and generated facts. These facts can then be added to the PyReason graph. ```python transaction_features = torch.rand(1, 5) # Get the prediction from the model logits, probabilities, classifier_facts = fraud_detector(transaction_features) ``` -------------------------------- ### Reset PyReason Settings to Default Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/user_guide/4_pyreason_settings.md Use this function to revert all PyReason settings to their original default values. This should be called before starting a new reasoning process if you want to ensure a clean slate. ```python import pyreason as pr pr.reset_settings() ``` -------------------------------- ### Initialize Pet Data Source: https://github.com/lab-v2/pyreason/blob/main/docs/advanced_graph.ipynb Creates a dictionary mapping pet index to their details (type, class). ```python # Pets pet_details = [ ('Dog', 'Mammal'), ('Cat', 'Mammal'), ('Rabbit', 'Mammal'), ('Parrot', 'Bird'), ('Fish', 'Fish') ] pet_dict = {i: pet for i, pet in enumerate(pet_details)} pet_dict ``` -------------------------------- ### Example User-Defined Annotation Function Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/user_guide/3_pyreason_rules.md Defines a numba-compiled annotation function to calculate the average lower and upper bounds of grounded atoms. It requires 'annotations' and 'weights' as input and returns two numbers. ```python import numba import numpy as np @numba.njit def avg_ann_fn(annotations, weights): # annotations contains the bounds of the atoms that were used to ground the rule. It is a nested list that contains a list for each clause # You can access for example the first grounded atom's bound by doing: annotations[0][0].lower or annotations[0][0].upper # We want the normalised sum of the bounds of the grounded atoms sum_upper_bounds = 0 sum_lower_bounds = 0 num_atoms = 0 for clause in annotations: for atom in clause: sum_lower_bounds += atom.lower sum_upper_bounds += atom.upper num_atoms += 1 a = sum_lower_bounds / num_atoms b = sum_upper_bounds / num_atoms return a, b ``` -------------------------------- ### Accessing and Modifying PyReason Settings Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/user_guide/4_pyreason_settings.md Demonstrates the basic syntax for accessing and modifying PyReason settings. Ensure PyReason is imported before use. ```python import pyreason as pr pr.settings.setting_name = value ``` -------------------------------- ### Import PyReason and NetworkX Source: https://github.com/lab-v2/pyreason/blob/main/docs/advanced_graph.ipynb Imports necessary libraries for PyReason and graph operations. Initializes PyReason caches for performance. ```python from pprint import pprint import networkx as nx import pyreason as pr ``` -------------------------------- ### Relational (Edge Rule) Domain Example Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/tutorials/natural_language_to_pyreason.md Extracts facts and rules from a relational-themed paragraph involving colleagues and project collaboration. This is a challenging case that requires encoding two-entity relationships as edge facts and rules. ```text Alice and Bob are colleagues. All colleagues who share projects tend to collaborate well. Alice and Bob share a project. Anyone who collaborates well is likely to get promoted. Carol and Dave are colleagues but do not share any projects. ``` -------------------------------- ### Run PyReason Reasoning Source: https://github.com/lab-v2/pyreason/blob/main/docs/hello-world.md This snippet shows the core command to initiate the PyReason reasoning process for a specified number of timesteps. The result is an interpretation of the graph's state over time. ```python interpretation = pr.reason(timesteps=2) ``` -------------------------------- ### Get PyReason Interpretation as Dictionary Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/user_guide/6_pyreason_output.md Use `.get_dict()` to retrieve the full interpretation as a nested dictionary. This is useful for detailed inspection of the reasoning results across all time steps and components. Requires importing `pyreason` and `pprint`. ```python import pyreason as pr from pprint import pprint interpretation = pr.reason(timesteps=2) interpretations_dict = interpretation.get_dict() pprint(interpretations_dict) ``` -------------------------------- ### Graph Creation and Rule Definition Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/examples_rst/infer_edges_example.md This snippet sets up a directed graph using NetworkX, adds nodes and edges with attributes, configures PyReason settings, and defines a rule to infer new 'isConnectedTo' edges. It then loads the graph into PyReason and initiates the reasoning process. ```python import pyreason as pr import networkx as nx import matplotlib.pyplot as plt # Create a directed graph G = nx.DiGraph() # Add nodes with attributes nodes = [ ("Amsterdam_Airport_Schiphol", {"Amsterdam_Airport_Schiphol": 1}), ("Riga_International_Airport", {"Riga_International_Airport": 1}), ("Chișinău_International_Airport", {"Chișinău_International_Airport": 1}), ("Yali", {"Yali": 1}), ("Düsseldorf_Airport", {"Düsseldorf_Airport": 1}), ("Pobedilovo_Airport", {"Pobedilovo_Airport": 1}), ("Dubrovnik_Airport", {"Dubrovnik_Airport": 1}), ("Hévíz-Balaton_Airport", {"Hévíz-Balaton_Airport": 1}), ("Athens_International_Airport", {"Athens_International_Airport": 1}), ("Vnukovo_International_Airport", {"Vnukovo_International_Airport": 1}) ] G.add_nodes_from(nodes) # Add edges with 'isConnectedTo' attribute edges = [ ("Pobedilovo_Airport", "Vnukovo_International_Airport", {"isConnectedTo": 1}), ("Vnukovo_International_Airport", "Hévíz-Balaton_Airport", {"isConnectedTo": 1}), ("Düsseldorf_Airport", "Dubrovnik_Airport", {"isConnectedTo": 1}), ("Dubrovnik_Airport", "Athens_International_Airport", {"isConnectedTo": 1}), ("Riga_International_Airport", "Amsterdam_Airport_Schiphol", {"isConnectedTo": 1}), ("Riga_International_Airport", "Düsseldorf_Airport", {"isConnectedTo": 1}), ("Chișinău_International_Airport", "Riga_International_Airport", {"isConnectedTo": 1}), ("Amsterdam_Airport_Schiphol", "Yali", {"isConnectedTo": 1}) ] G.add_edges_from(edges) # Print a drawing of the directed graph # nx.draw(G, with_labels=True, node_color='lightblue', font_weight='bold', node_size=3000) # plt.show() pr.reset() pr.reset_rules() # Modify pyreason settings to make verbose and to save the rule trace to a file pr.settings.verbose = True pr.settings.atom_trace = True pr.settings.memory_profile = False pr.settings.canonical = True pr.settings.inconsistency_check = False pr.settings.static_graph_facts = False pr.settings.output_to_file = False pr.settings.store_interpretation_changes = True pr.settings.save_graph_attributes_to_trace = True # Load all the files into pyreason pr.load_graph(G) pr.add_rule(pr.Rule('isConnectedTo(A, Y) <-1 isConnectedTo(Y, B), Amsterdam_Airport_Schiphol(B), Vnukovo_International_Airport(A)', 'connected_rule_1', infer_edges=True)) # Run the program for two timesteps to see the diffusion take place interpretation = pr.reason(timesteps=1) # pr.save_rule_trace(interpretation) # Display the changes in the interpretation for each timestep dataframes = pr.filter_and_sort_edges(interpretation, ['isConnectedTo']) for t, df in enumerate(dataframes): print(f'TIMESTEP - {t}') print(df) print() assert len(dataframes) == 2, 'Pyreason should run exactly 2 fixpoint operations' assert len(dataframes[1]) == 1, 'At t=1 there should be only 1 new isConnectedTo atom' assert ('Vnukovo_International_Airport', 'Riga_International_Airport') in dataframes[1]['component'].values.tolist() and dataframes[1]['isConnectedTo'].iloc[0] == [1, 1], '(Vnukovo_International_Airport, Riga_International_Airport) should have isConnectedTo bounds [1,1] for t=1 timesteps' nx.draw(G, with_labels=True, node_color='lightblue', font_weight='bold', node_size=3000) plt.show() ``` -------------------------------- ### Configure PyReason Settings and Load Graph Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/tutorials/cybersecurity_inconsistency.md Sets PyReason's verbose and atom tracing to true, enables inconsistency checking, and loads the previously constructed NetworkX graph into PyReason. ```python pr.settings.verbose = True pr.settings.atom_trace = True pr.settings.inconsistency_check = True pr.load_graph(g) ``` -------------------------------- ### Create Knowledge Graph Source: https://github.com/lab-v2/pyreason/blob/main/docs/source/tutorials/llm_generated_rules.md Builds a small academic knowledge graph with students, majors, and departments using NetworkX. Defines edges for 'major_in' and 'in_department' relationships. ```python import networkx as nx g = nx.DiGraph() g.add_edge('alice', 'math', major_in=1) g.add_edge('bob', 'math', major_in=1) g.add_edge('mary', 'cs', major_in=1) # Major -> Department g.add_edge('math', 'math_dept', in_department=1) g.add_edge('cs', 'cs_dept', in_department=1) ```