Running Pyreason with an advanced graph

In this tutorial, we will look at how to run PyReason with a more complex graph.

Graph

We use a larger graph for this example. In this example , we have customers , cars , pets and their relationships. We first have customer details followed by car details , pet details , travel details .

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)
]

We now have the relationships between the customers , cars , pets and travel details.

friendships = [('customer_2', 'customer_1'), ('customer_0', 'customer_1'), ('customer_3', 'customer_2'),
               ('customer_3', 'customer_4'), ('customer_4', 'customer_0'), ('customer_5', 'customer_3'),
               ('customer_6', 'customer_0'), ('customer_5', 'customer_6'), ('customer_4', 'customer_6'),
               ('customer_3', 'customer_1')]
car_ownerships = [('customer_1', 'Car_0'), ('customer_2', 'Car_1'), ('customer_0', 'Car_2'), ('customer_3', 'Car_3'),
                  ('customer_4', 'Car_4'), ('customer_3', 'Car_0'), ('customer_2', 'Car_3'), ('customer_5', 'Car_5'),
                  ('customer_6', 'Car_6'), ('customer_0', 'Car_7'), ('customer_1', 'Car_8'), ('customer_4', 'Car_9'),
                  ('customer_3', 'Car_10'), ('customer_2', 'Car_11'), ('customer_5', 'Car_2'), ('customer_6', 'Car_4')]

pet_ownerships = [('customer_1', 'Pet_1'), ('customer_2', 'Pet_1'), ('customer_2', 'Pet_0'), ('customer_0', 'Pet_0'),
                  ('customer_3', 'Pet_2'), ('customer_4', 'Pet_2'), ('customer_5', 'Pet_3'), ('customer_6', 'Pet_4'),
                  ('customer_0', 'Pet_4')]

Based on the relationships we now connect the nodes, edges and the form the graph.

for customer_id, details in customer_dict.items():
    attributes = {
        f'c_id-{customer_id}': 1,
        'name': details[0],
        'gender': details[1],
        'city': details[2],
        'state': details[3],
    }
    name = "customer_" + str(customer_id)
    g.add_node(name, **attributes)

for pet_id, details in pet_dict.items():
    dynamic_attribute = f"Pet_{pet_id}"
    attributes = {
        f'pet_id-{pet_id}': 1,
        'species': details[0],
        'class': details[1],
        dynamic_attribute: 1
    }
    name = "Pet_" + str(pet_id)
    g.add_node(name, **attributes)

for car_id, details in car_dict.items():
    dynamic_attribute = f"Car_{car_id}"
    attributes = {
        f'car_id-{car_id}': 1,
        'model': details[0],
        'color': details[1],
        dynamic_attribute: 1
    }
    name = "Car_" + str(car_id)
    g.add_node(name, **attributes)

# Add relationships(edges) between customers, pets, and cars

for f1, f2 in friendships:
    g.add_edge(f1, f2, Friends=1)
for owner, car in car_ownerships:
    g.add_edge(owner, car, owns_car=1, car_color_id=int(car.split('_')[1]))
for owner, pet in pet_ownerships:
    g.add_edge(owner, pet, owns_pet=1)

We now have the graph ready. We can now add the rules for our use case. Take a look at it at

image

advanced graph image

Rules

The below are the rules we want to add:

  1. A customer is popular if he is friends with a popular customer.

  2. A customer has a cool car if he owns a car and the car is of type Car_4.

  3. A customer has a cool pet if he owns a pet and the pet is of type Pet_2.

  4. A customer is trendy if he has a cool car and a cool pet.

pr.add_rule(pr.Rule('popular(x) <-1 popular(y), Friends(x,y)', 'popular_pet_rule'))
pr.add_rule(pr.Rule('cool_car(x) <-1 owns_car(x,y),Car_4(y)', 'cool_car_rule'))
pr.add_rule(pr.Rule('cool_pet(x)<-1 owns_pet(x,y),Pet_2(y)', 'cool_pet_rule'))
pr.add_rule(pr.Rule('trendy(x) <- cool_car(x) , cool_pet(x)', 'trendy_rule'))

The above rules are based on nodes. Now let us add some more rules based on the edges.

  1. Two customers are car_friends if they own the same car.

  2. Two customers are friends if they own the same color car.

pr.add_rule(pr.Rule("car_friend(x,y) <- owns_car(x,z), owns_car(y,z) , c_id(x) != c_id(y) ", "car_friend_rule"))
pr.add_rule(pr.Rule("same_color_car(x, y) <- owns_car(x, c1) , owns_car(y, c2),  car_color_id(x,c1) == car_color_id(y,c2) , c_id(x) != c_id(y)","same_car_color_rule"))

Facts

We now add the facts to the graph. There is only one fact we are going to use. 1. customer_0 is popular from time 0 to 5.

pr.add_fact(pr.Fact(name='popular-fact', component='customer_0', attribute='popular', bound=[1, 1], start_time=0, end_time=5))

Running Pyreason

We now run the PyReason with the graph and the rules.

interpretation = pr.reason(timesteps=6)
# pr.save_rule_trace(interpretation)

interpretations_dict = interpretation.get_interpretation_dict()

df1 = pr.filter_and_sort_nodes(interpretation, ['trendy', 'cool_car', 'cool_pet', 'popular'])
df2 = pr.filter_and_sort_edges(interpretation, ['car_friend', 'same_color_car'])

Note

The complete code for this example is on github at advanced_graph.py