Programming Logic in Python

From Symbolic Reasoning to Rule-Based Systems

A Comprehensive Guide to Logic Libraries in Python
Back to Lecture Overview

Table of Contents

1. Introduction & Motivation

Why Learn Logic in Python?

Logic forms the foundation of reasoning, inference, and artificial intelligence. Understanding how to implement logical systems in Python enables you to:

Learning Outcomes

After completing this guide, you will be able to:

  1. Understand how logical reasoning works in Python
  2. Use libraries like SymPy, kanren, PyDatalog, Pytholog, and jsonLogic
  3. Implement simple reasoning systems and knowledge bases
  4. Compare symbolic vs. declarative vs. data-driven logic paradigms
  5. Choose the right library for your specific use case

2. Foundations of Logic Programming

What is Logic Programming?

Logic programming is a declarative paradigm where you describe what is true, not how to compute it. Programs are written as sets of:

Example (Prolog-style)
Prolog Logic
parent(adam, bob).
parent(bob, charlie).
grandparent(X, Z) :- parent(X, Y), parent(Y, Z).

?- grandparent(adam, charlie).
% Yes

Logic Types in Python

Type Description Example Libraries Use Case
Symbolic Logic Boolean formulas & proofs SymPy SAT solving, theorem proving
Logic Programming Relations & facts Kanren, PyDatalog, Pytholog Knowledge bases, expert systems
Rule-Based Logic JSON-encoded rules jsonLogic Dynamic business rules, APIs

3. Symbolic Logic with SymPy

SymPy

SymPy is a Python library for symbolic mathematics that includes powerful logic capabilities. It allows you to work with propositional logic, Boolean algebra, and satisfiability checking.

Basic Concepts

Complete Example: Propositional Logic

sympy_logic.py
from sympy import symbols, And, Or, Not, Implies, Equivalent, simplify, satisfiable

# Define propositional symbols
P, Q, R = symbols('P Q R')

# Example 1: Modus Ponens
print("=" * 50)
print("Example 1: Modus Ponens")
print("=" * 50)
premise1 = Implies(P, Q)  # P → Q
premise2 = P               # P
conclusion = Q             # Therefore Q

# Check if premises entail conclusion
formula = Implies(And(premise1, premise2), conclusion)
print(f"Formula: {formula}")
print(f"Simplified: {simplify(formula)}")  # Should be True (tautology)
print(f"Is valid? {satisfiable(Not(formula)) == False}")

# Example 2: De Morgan's Laws
print("\n" + "=" * 50)
print("Example 2: De Morgan's Laws")
print("=" * 50)
law1 = Equivalent(Not(And(P, Q)), Or(Not(P), Not(Q)))
law2 = Equivalent(Not(Or(P, Q)), And(Not(P), Not(Q)))

print(f"Law 1: ¬(P ∧ Q) ≡ (¬P ∨ ¬Q)")
print(f"Simplified: {simplify(law1)}")  # True
print(f"Law 2: ¬(P ∨ Q) ≡ (¬P ∧ ¬Q)")
print(f"Simplified: {simplify(law2)}")  # True

# Example 3: SAT Solving
print("\n" + "=" * 50)
print("Example 3: Satisfiability Checking")
print("=" * 50)
formula1 = And(Or(P, Q), Or(Not(P), R), Or(Not(Q), Not(R)))
formula2 = And(P, Not(P))  # Contradiction

print(f"Formula 1: (P ∨ Q) ∧ (¬P ∨ R) ∧ (¬Q ∨ ¬R)")
result1 = satisfiable(formula1)
print(f"Satisfiable? {result1}")

print(f"\nFormula 2: P ∧ ¬P")
result2 = satisfiable(formula2)
print(f"Satisfiable? {result2}")  # False (contradiction)

# Example 4: Truth Table Generation
print("\n" + "=" * 50)
print("Example 4: Checking Tautology")
print("=" * 50)
tautology = Or(P, Not(P))  # Law of Excluded Middle
print(f"Formula: P ∨ ¬P")
print(f"Simplified: {simplify(tautology)}")
print(f"Is tautology? {satisfiable(Not(tautology)) == False}")
================================================== Example 1: Modus Ponens ================================================== Formula: Implies(And(Implies(P, Q), P), Q) Simplified: True Is valid? True ================================================== Example 2: De Morgan's Laws ================================================== Law 1: ¬(P ∧ Q) ≡ (¬P ∨ ¬Q) Simplified: True Law 2: ¬(P ∨ Q) ≡ (¬P ∧ ¬Q) Simplified: True ================================================== Example 3: Satisfiability Checking ================================================== Formula 1: (P ∨ Q) ∧ (¬P ∨ R) ∧ (¬Q ∨ ¬R) Satisfiable? {P: False, Q: True, R: False} Formula 2: P ∧ ¬P Satisfiable? False ================================================== Example 4: Checking Tautology ================================================== Formula: P ∨ ¬P Simplified: True Is tautology? True

Use Cases for SymPy

✓ Model checking ✓ Truth table generation ✓ Tautology detection
✓ Contradiction detection ✓ Formula simplification ✓ Teaching logic

4. Logic Programming with Kanren

Kanren (logpy)

Kanren (available as logpy in Python) implements relational logic programming, similar to Prolog. It allows you to define relations and query them declaratively.

Key Features

Complete Example: Family Relations

kanren_logic.py
from kanren import run, var, Relation, facts, conde, eq

# Define relations
parent = Relation()
male = Relation()
female = Relation()

# Add facts to the knowledge base
facts(parent, ("Adam", "Bob"),
              ("Adam", "Beth"),
              ("Bob", "Charlie"),
              ("Bob", "Claire"),
              ("Beth", "David"))

facts(male, "Adam", "Bob", "Charlie", "David")
facts(female, "Beth", "Claire")

# Example 1: Simple Query - Who are Adam's children?
print("=" * 50)
print("Example 1: Who are Adam's children?")
print("=" * 50)
x = var()
result = run(0, x, parent("Adam", x))  # 0 means all solutions
print(f"Adam's children: {result}")

# Example 2: Reverse Query - Who is Charlie's parent?
print("\n" + "=" * 50)
print("Example 2: Who is Charlie's parent?")
print("=" * 50)
y = var()
result = run(0, y, parent(y, "Charlie"))
print(f"Charlie's parent: {result}")

# Example 3: Define Grandparent Relation
print("\n" + "=" * 50)
print("Example 3: Grandparent Relation")
print("=" * 50)

def grandparent(x, z):
    y = var()
    return conde([parent(x, y), parent(y, z)])

a, b = var(), var()
result = run(0, (a, b), grandparent(a, b))
print(f"Grandparent relations: {result}")

# Example 4: Uncle Relation (parent's brother)
print("\n" + "=" * 50)
print("Example 4: Uncle Relation")
print("=" * 50)

def uncle(x, z):
    y = var()
    return conde([parent(y, z), parent("Adam", x), male(x), 
                  lambda s: s if x != y else None])

u = var()
result = run(0, u, uncle(u, "Charlie"))
print(f"Charlie's uncles: {result}")

# Example 5: Multiple Conditions
print("\n" + "=" * 50)
print("Example 5: All male children")
print("=" * 50)

def male_child(person):
    p = var()
    return conde([parent(p, person), male(person)])

m = var()
result = run(0, m, male_child(m))
print(f"Male children: {result}")
================================================== Example 1: Who are Adam's children? ================================================== Adam's children: ('Bob', 'Beth') ================================================== Example 2: Who is Charlie's parent? ================================================== Charlie's parent: ('Bob',) ================================================== Example 3: Grandparent Relation ================================================== Grandparent relations: (('Adam', 'Charlie'), ('Adam', 'Claire'), ('Adam', 'David')) ================================================== Example 4: Uncle Relation ================================================== Charlie's uncles: ('Beth',) ================================================== Example 5: All male children ================================================== Male children: ('Bob', 'Charlie', 'David')

Use Cases for Kanren

✓ Relational queries ✓ Pattern matching ✓ Constraint solving
✓ Knowledge bases ✓ AI reasoning ✓ Symbolic AI

5. Datalog with PyDatalog

PyDatalog

PyDatalog implements Datalog, a subset of Prolog designed for database queries and recursive reasoning. It provides a SQL-like syntax for logical queries with powerful recursion support.

Key Features

Complete Example: Knowledge Base with Recursion

pydatalog_logic.py
from pyDatalog import pyDatalog

# Initialize pyDatalog
pyDatalog.clear()
pyDatalog.create_terms('X, Y, Z, parent, ancestor, sibling, cousin, manager, employee, reports_to')

# Example 1: Basic Facts and Queries
print("=" * 50)
print("Example 1: Family Relations")
print("=" * 50)

# Add parent facts
+parent('Adam', 'Bob')
+parent('Adam', 'Beth')
+parent('Bob', 'Charlie')
+parent('Bob', 'Claire')
+parent('Beth', 'David')
+parent('Beth', 'Diana')

# Direct query
print("Adam's children:")
print(parent('Adam', X))

# Example 2: Recursive Ancestor Relation
print("\n" + "=" * 50)
print("Example 2: Recursive Ancestor")
print("=" * 50)

# Define ancestor recursively
ancestor(X, Y) <= parent(X, Y)
ancestor(X, Y) <= parent(X, Z) & ancestor(Z, Y)

# Query all ancestors
print("All of Charlie's ancestors:")
print(ancestor(X, 'Charlie'))

print("\nAll of Adam's descendants:")
print(ancestor('Adam', Y))

# Example 3: Sibling Relation
print("\n" + "=" * 50)
print("Example 3: Siblings")
print("=" * 50)

# Siblings share a parent
sibling(X, Y) <= parent(Z, X) & parent(Z, Y) & (X != Y)

print("Bob's siblings:")
print(sibling('Bob', Y))

print("\nAll sibling pairs:")
result = sibling(X, Y) & (X < Y)  # Avoid duplicates
print(result)

# Example 4: Cousin Relation
print("\n" + "=" * 50)
print("Example 4: Cousins")
print("=" * 50)

# Cousins: parents are siblings
cousin(X, Y) <= parent(P1, X) & parent(P2, Y) & sibling(P1, P2)

print("Charlie's cousins:")
print(cousin('Charlie', Y))

# Example 5: Organizational Hierarchy
print("\n" + "=" * 50)
print("Example 5: Corporate Hierarchy")
print("=" * 50)

pyDatalog.create_terms('level')

+manager('CEO', 'VP1')
+manager('CEO', 'VP2')
+manager('VP1', 'Director1')
+manager('VP1', 'Director2')
+manager('Director1', 'Employee1')
+manager('Director1', 'Employee2')

# Reports to (direct or indirect)
reports_to(X, Y) <= manager(Y, X)
reports_to(X, Y) <= manager(Z, X) & reports_to(Z, Y)

print("Who reports to CEO (directly or indirectly)?")
print(reports_to(X, 'CEO'))

# Example 6: Counting with Aggregation
print("\n" + "=" * 50)
print("Example 6: Count Descendants")
print("=" * 50)

(employee[Y] == len_(X)) <= ancestor(Y, X)

print("Number of descendants for each person:")
print(employee[Y] == X)
================================================== Example 1: Family Relations ================================================== Adam's children: X --- Bob Beth ================================================== Example 2: Recursive Ancestor ================================================== All of Charlie's ancestors: X ----- Bob Adam All of Adam's descendants: Y ------ Bob Beth Charlie Claire David Diana ================================================== Example 3: Siblings ================================================== Bob's siblings: Y ---- Beth All sibling pairs: X | Y ---------- Bob | Beth ================================================== Example 4: Cousins ================================================== Charlie's cousins: Y ----- David Diana ================================================== Example 5: Corporate Hierarchy ================================================== Who reports to CEO (directly or indirectly)? X ---------- VP1 VP2 Director1 Director2 Employee1 Employee2 ================================================== Example 6: Count Descendants ================================================== Number of descendants for each person: Y | X ---------- Adam | 6 Beth | 2 Bob | 2

Use Cases for PyDatalog

✓ Recursive queries ✓ Graph traversal ✓ Organizational charts
✓ Knowledge graphs ✓ Rule-based systems ✓ Data analysis

6. Prolog-Inspired Pytholog

Pytholog

Pytholog is a lightweight Prolog interpreter written in Python. It provides a simple, intuitive interface for building knowledge bases and performing logical queries.

Key Features

Complete Example: Expert System

pytholog_logic.py
import pytholog as pl

# Example 1: Family Knowledge Base
print("=" * 50)
print("Example 1: Family Relations")
print("=" * 50)

kb = pl.KnowledgeBase("family")
kb([
    "parent(adam, bob)",
    "parent(adam, beth)",
    "parent(bob, charlie)",
    "parent(bob, claire)",
    "parent(beth, david)",
    
    "male(adam)",
    "male(bob)",
    "male(charlie)",
    "male(david)",
    
    "female(beth)",
    "female(claire)",
    
    # Rules
    "grandparent(X, Z) :- parent(X, Y), parent(Y, Z)",
    "father(X, Y) :- parent(X, Y), male(X)",
    "mother(X, Y) :- parent(X, Y), female(X)",
    "sibling(X, Y) :- parent(Z, X), parent(Z, Y), X \\= Y",
    "brother(X, Y) :- sibling(X, Y), male(X)",
    "sister(X, Y) :- sibling(X, Y), female(X)"
])

# Query grandparents
print("Query: grandparent(adam, X)")
result = kb.query(pl.Expr("grandparent(adam, X)"))
print(f"Result: {result}")

# Query fathers
print("\nQuery: father(X, charlie)")
result = kb.query(pl.Expr("father(X, charlie)"))
print(f"Result: {result}")

# Example 2: Animal Classification Expert System
print("\n" + "=" * 50)
print("Example 2: Animal Classification")
print("=" * 50)

animal_kb = pl.KnowledgeBase("animals")
animal_kb([
    # Facts about animals
    "has_fur(dog)",
    "has_fur(cat)",
    "has_fur(lion)",
    
    "has_feathers(eagle)",
    "has_feathers(penguin)",
    "has_feathers(parrot)",
    
    "can_fly(eagle)",
    "can_fly(parrot)",
    
    "lives_in_water(penguin)",
    "lives_in_water(shark)",
    "lives_in_water(salmon)",
    
    "has_gills(shark)",
    "has_gills(salmon)",
    
    # Classification rules
    "mammal(X) :- has_fur(X)",
    "bird(X) :- has_feathers(X)",
    "fish(X) :- has_gills(X), lives_in_water(X)",
    "flying_bird(X) :- bird(X), can_fly(X)",
    "flightless_bird(X) :- bird(X), \\+ can_fly(X)"
])

# Classify animals
print("Query: What is a mammal?")
result = animal_kb.query(pl.Expr("mammal(X)"))
print(f"Mammals: {result}")

print("\nQuery: What is a flying bird?")
result = animal_kb.query(pl.Expr("flying_bird(X)"))
print(f"Flying birds: {result}")

print("\nQuery: What is a fish?")
result = animal_kb.query(pl.Expr("fish(X)"))
print(f"Fish: {result}")

# Example 3: Medical Diagnosis System
print("\n" + "=" * 50)
print("Example 3: Simple Medical Diagnosis")
print("=" * 50)

medical_kb = pl.KnowledgeBase("medical")
medical_kb([
    # Patient symptoms
    "symptom(john, fever)",
    "symptom(john, cough)",
    "symptom(john, fatigue)",
    
    "symptom(mary, headache)",
    "symptom(mary, nausea)",
    
    "symptom(alice, fever)",
    "symptom(alice, rash)",
    "symptom(alice, sore_throat)",
    
    # Diagnosis rules
    "diagnosis(Patient, flu) :- symptom(Patient, fever), symptom(Patient, cough), symptom(Patient, fatigue)",
    "diagnosis(Patient, migraine) :- symptom(Patient, headache), symptom(Patient, nausea)",
    "diagnosis(Patient, strep_throat) :- symptom(Patient, fever), symptom(Patient, sore_throat)"
])

# Diagnose patients
print("Query: diagnosis(john, Disease)")
result = medical_kb.query(pl.Expr("diagnosis(john, Disease)"))
print(f"John's diagnosis: {result}")

print("\nQuery: diagnosis(alice, Disease)")
result = medical_kb.query(pl.Expr("diagnosis(alice, Disease)"))
print(f"Alice's diagnosis: {result}")

print("\nQuery: Who has the flu?")
result = medical_kb.query(pl.Expr("diagnosis(Patient, flu)"))
print(f"Patients with flu: {result}")

# Example 4: Course Prerequisites
print("\n" + "=" * 50)
print("Example 4: Course Prerequisites")
print("=" * 50)

course_kb = pl.KnowledgeBase("courses")
course_kb([
    # Direct prerequisites
    "prerequisite(se444, se363)",
    "prerequisite(se363, coe202)",
    "prerequisite(se444, math201)",
    "prerequisite(se465, se363)",
    "prerequisite(se465, se444)",
    
    # Student completed courses
    "completed(ahmad, coe202)",
    "completed(ahmad, math201)",
    "completed(ahmad, se363)",
    
    "completed(sara, coe202)",
    "completed(sara, math201)",
    
    # Rules
    "can_take(Student, Course) :- prerequisite(Course, Prereq), completed(Student, Prereq)",
    "all_prereqs_met(Student, Course) :- \\+ (prerequisite(Course, Prereq), \\+ completed(Student, Prereq))"
])

print("Query: What can Ahmad take?")
result = course_kb.query(pl.Expr("can_take(ahmad, Course)"))
print(f"Ahmad can take: {result}")

print("\nQuery: Can Ahmad take SE444?")
result = course_kb.query(pl.Expr("can_take(ahmad, se444)"))
print(f"Result: {result}")
================================================== Example 1: Family Relations ================================================== Query: grandparent(adam, X) Result: [{'X': 'charlie'}, {'X': 'claire'}, {'X': 'david'}] Query: father(X, charlie) Result: [{'X': 'bob'}] ================================================== Example 2: Animal Classification ================================================== Query: What is a mammal? Mammals: [{'X': 'dog'}, {'X': 'cat'}, {'X': 'lion'}] Query: What is a flying bird? Flying birds: [{'X': 'eagle'}, {'X': 'parrot'}] Query: What is a fish? Fish: [{'X': 'shark'}, {'X': 'salmon'}] ================================================== Example 3: Simple Medical Diagnosis ================================================== Query: diagnosis(john, Disease) John's diagnosis: [{'Disease': 'flu'}] Query: diagnosis(alice, Disease) Alice's diagnosis: [{'Disease': 'strep_throat'}] Query: Who has the flu? Patients with flu: [{'Patient': 'john'}] ================================================== Example 4: Course Prerequisites ================================================== Query: What can Ahmad take? Ahmad can take: [{'Course': 'se444'}, {'Course': 'se465'}] Query: Can Ahmad take SE444? Result: [{'ahmad': 'ahmad', 'se444': 'se444'}]

Use Cases for Pytholog

✓ Expert systems ✓ Rule-based AI ✓ Decision support
✓ Classification ✓ Diagnosis ✓ Educational tools

7. Rule-Based Logic with jsonLogic

jsonLogic

jsonLogic is a way to write portable logic rules in JSON format. This makes rules shareable between different programming languages, databases, and APIs.

Key Features

Complete Example: Business Rules Engine

jsonlogic_rules.py
from json_logic import jsonLogic
import json

# Example 1: Simple Eligibility Check
print("=" * 50)
print("Example 1: Loan Eligibility")
print("=" * 50)

# Rule: Age > 18 AND Income > 30000
loan_rule = {
    "and": [
        {">": [{"var": "age"}, 18]},
        {">": [{"var": "income"}, 30000]}
    ]
}

# Test cases
applicant1 = {"age": 25, "income": 45000}
applicant2 = {"age": 17, "income": 50000}
applicant3 = {"age": 30, "income": 25000}

print(f"Rule: {json.dumps(loan_rule, indent=2)}")
print(f"\nApplicant 1 (age=25, income=45000): {jsonLogic(loan_rule, applicant1)}")
print(f"Applicant 2 (age=17, income=50000): {jsonLogic(loan_rule, applicant2)}")
print(f"Applicant 3 (age=30, income=25000): {jsonLogic(loan_rule, applicant3)}")

# Example 2: Complex Discount Calculator
print("\n" + "=" * 50)
print("Example 2: Dynamic Discount Rules")
print("=" * 50)

# Tiered discount system
discount_rule = {
    "if": [
        {">": [{"var": "total"}, 1000]},
        20,  # 20% discount for orders > 1000
        {">": [{"var": "total"}, 500]},
        15,  # 15% discount for orders > 500
        {">": [{"var": "total"}, 100]},
        10,  # 10% discount for orders > 100
        0    # No discount otherwise
    ]
}

orders = [
    {"total": 1500},
    {"total": 750},
    {"total": 150},
    {"total": 50}
]

print(f"Discount Rule: {json.dumps(discount_rule, indent=2)}")
for order in orders:
    discount = jsonLogic(discount_rule, order)
    print(f"Order total ${order['total']}: {discount}% discount")

# Example 3: Healthcare Risk Assessment
print("\n" + "=" * 50)
print("Example 3: Healthcare Risk Score")
print("=" * 50)

# Risk score: multiple factors
risk_rule = {
    "+": [
        # Age factor (0-30 points)
        {"if": [{">": [{"var": "age"}, 60]}, 30, 
                {">": [{"var": "age"}, 40]}, 15, 0]},
        
        # BMI factor (0-20 points)
        {"if": [{">": [{"var": "bmi"}, 30]}, 20,
                {">": [{"var": "bmi"}, 25]}, 10, 0]},
        
        # Smoking (25 points)
        {"if": [{"var": "smoker"}, 25, 0]},
        
        # Diabetes (15 points)
        {"if": [{"var": "diabetes"}, 15, 0]}
    ]
}

patients = [
    {"age": 65, "bmi": 32, "smoker": True, "diabetes": True},
    {"age": 35, "bmi": 24, "smoker": False, "diabetes": False},
    {"age": 50, "bmi": 28, "smoker": True, "diabetes": False}
]

print("Risk Assessment Rule:")
for i, patient in enumerate(patients, 1):
    risk_score = jsonLogic(risk_rule, patient)
    risk_level = "HIGH" if risk_score > 50 else "MEDIUM" if risk_score > 25 else "LOW"
    print(f"Patient {i}: Score = {risk_score} ({risk_level})")
    print(f"  Age={patient['age']}, BMI={patient['bmi']}, "
          f"Smoker={patient['smoker']}, Diabetes={patient['diabetes']}")

# Example 4: Access Control Rules
print("\n" + "=" * 50)
print("Example 4: Access Control System")
print("=" * 50)

# Rule: Can edit if (owner OR admin) AND not_locked
access_rule = {
    "and": [
        {
            "or": [
                {"==": [{"var": "role"}, "admin"]},
                {"==": [{"var": "user_id"}, {"var": "owner_id"}]}
            ]
        },
        {"!": {"var": "locked"}}
    ]
}

# Test scenarios
scenarios = [
    {"user_id": 101, "owner_id": 101, "role": "user", "locked": False},
    {"user_id": 102, "owner_id": 101, "role": "admin", "locked": False},
    {"user_id": 101, "owner_id": 101, "role": "user", "locked": True},
    {"user_id": 103, "owner_id": 101, "role": "user", "locked": False}
]

print(f"Access Rule: {json.dumps(access_rule, indent=2)}")
for i, scenario in enumerate(scenarios, 1):
    can_edit = jsonLogic(access_rule, scenario)
    print(f"Scenario {i}: Can edit = {can_edit}")
    print(f"  {scenario}")

# Example 5: Product Recommendation
print("\n" + "=" * 50)
print("Example 5: Product Recommendation Logic")
print("=" * 50)

# Recommend premium if: (income > 80000 AND age > 25) OR lifetime_value > 50000
recommend_premium_rule = {
    "or": [
        {
            "and": [
                {">": [{"var": "income"}, 80000]},
                {">": [{"var": "age"}, 25]}
            ]
        },
        {">": [{"var": "lifetime_value"}, 50000]}
    ]
}

customers = [
    {"income": 90000, "age": 30, "lifetime_value": 10000},
    {"income": 60000, "age": 35, "lifetime_value": 60000},
    {"income": 50000, "age": 22, "lifetime_value": 5000}
]

print("Premium Recommendation Rule:")
for i, customer in enumerate(customers, 1):
    recommend = jsonLogic(recommend_premium_rule, customer)
    print(f"Customer {i}: Recommend Premium = {recommend}")
    print(f"  Income=${customer['income']}, Age={customer['age']}, "
          f"LTV=${customer['lifetime_value']}")

# Example 6: Array Operations
print("\n" + "=" * 50)
print("Example 6: Working with Arrays")
print("=" * 50)

# Check if any order is high priority
priority_rule = {
    "some": [
        {"var": "orders"},
        {">": [{"var": "priority"}, 8]}
    ]
}

customer_data = {
    "orders": [
        {"id": 1, "priority": 5},
        {"id": 2, "priority": 9},
        {"id": 3, "priority": 3}
    ]
}

has_high_priority = jsonLogic(priority_rule, customer_data)
print(f"Has high priority order: {has_high_priority}")

# Filter high-value items
filter_rule = {
    "filter": [
        {"var": "items"},
        {">": [{"var": "price"}, 100]}
    ]
}

cart_data = {
    "items": [
        {"name": "Laptop", "price": 1200},
        {"name": "Mouse", "price": 25},
        {"name": "Monitor", "price": 350},
        {"name": "Keyboard", "price": 80}
    ]
}

expensive_items = jsonLogic(filter_rule, cart_data)
print(f"\nExpensive items (>$100): {expensive_items}")
================================================== Example 1: Loan Eligibility ================================================== Rule: { "and": [ {">": [{"var": "age"}, 18]}, {">": [{"var": "income"}, 30000]} ] } Applicant 1 (age=25, income=45000): True Applicant 2 (age=17, income=50000): False Applicant 3 (age=30, income=25000): False ================================================== Example 2: Dynamic Discount Rules ================================================== Order total $1500: 20% discount Order total $750: 15% discount Order total $150: 10% discount Order total $50: 0% discount ================================================== Example 3: Healthcare Risk Score ================================================== Risk Assessment Rule: Patient 1: Score = 90 (HIGH) Age=65, BMI=32, Smoker=True, Diabetes=True Patient 2: Score = 0 (LOW) Age=35, BMI=24, Smoker=False, Diabetes=False Patient 3: Score = 50 (MEDIUM) Age=50, BMI=28, Smoker=True, Diabetes=False ================================================== Example 4: Access Control System ================================================== Scenario 1: Can edit = True {'user_id': 101, 'owner_id': 101, 'role': 'user', 'locked': False} Scenario 2: Can edit = True {'user_id': 102, 'owner_id': 101, 'role': 'admin', 'locked': False} Scenario 3: Can edit = False {'user_id': 101, 'owner_id': 101, 'role': 'user', 'locked': True} Scenario 4: Can edit = False {'user_id': 103, 'owner_id': 101, 'role': 'user', 'locked': False} ================================================== Example 5: Product Recommendation Logic ================================================== Premium Recommendation Rule: Customer 1: Recommend Premium = True Income=$90000, Age=30, LTV=$10000 Customer 2: Recommend Premium = True Income=$60000, Age=35, LTV=$60000 Customer 3: Recommend Premium = False Income=$50000, Age=22, LTV=$5000 ================================================== Example 6: Working with Arrays ================================================== Has high priority order: True Expensive items (>$100): [{'name': 'Laptop', 'price': 1200}, {'name': 'Monitor', 'price': 350}]

Use Cases for jsonLogic

✓ Business rules engines ✓ Dynamic pricing ✓ Access control ✓ Eligibility checks
✓ Risk assessment ✓ Content filtering ✓ API logic ✓ Form validation

8. Comparison & Integration

Comprehensive Library Comparison

Library Type Syntax Strength Best For Learning Curve
SymPy Symbolic Logic Python Mathematical proofs SAT, tautologies, teaching Low
Kanren Logic Programming Declarative Relational reasoning AI reasoning, constraints Medium
PyDatalog Datalog SQL-like Recursive queries Knowledge bases, graphs Medium
Pytholog Prolog Declarative Rule-based AI Expert systems, diagnosis Medium-High
jsonLogic Rule Engine JSON Dynamic evaluation Business rules, APIs Low

When to Use Each Library

Choose SymPy when:
  • You need to verify logical formulas
  • Working with Boolean algebra
  • Teaching propositional logic
  • Building SAT solvers
Choose Kanren when:
  • You need bidirectional queries
  • Working with relations and unification
  • Building constraint solvers
  • Implementing symbolic AI
Choose PyDatalog when:
  • You need recursive queries
  • Working with hierarchical data
  • Traversing graphs
  • Aggregating logical data
Choose Pytholog when:
  • Building expert systems
  • Need Prolog-like syntax
  • Creating rule-based agents
  • Educational Prolog alternative
Choose jsonLogic when:
  • Rules need to be stored in databases
  • Logic must be language-agnostic
  • Building dynamic business rules
  • Creating configurable workflows
  • Rules need to be edited by non-programmers

Combining Logic Systems

Hybrid Reasoning Approach

You can combine multiple libraries for powerful hybrid systems:

  • SymPy + jsonLogic: Use SymPy to verify rule correctness, jsonLogic for runtime evaluation
  • PyDatalog + Pytholog: Use PyDatalog for data queries, Pytholog for expert system rules
  • Kanren + LLMs: Use Kanren for structured reasoning, LLMs for natural language understanding
  • All + Knowledge Graphs: Store facts in knowledge graphs, query with logic engines

Example: Hybrid System

hybrid_system.py
# Combining SymPy and jsonLogic for a complete system

from sympy import symbols, And, Or, Not, Implies, simplify
from json_logic import jsonLogic

# Step 1: Verify rule correctness with SymPy
print("Step 1: Verifying rule correctness with SymPy")
print("=" * 50)

P, Q, R = symbols('P Q R')
# Rule: If (P AND Q) then R
symbolic_rule = Implies(And(P, Q), R)
print(f"Symbolic rule: {symbolic_rule}")
print(f"Simplified: {simplify(symbolic_rule)}")

# Check if it's logically valid
test_formula = Or(Not(And(P, Q)), R)  # Equivalent form
print(f"Equivalent form: {test_formula}")
print(f"Are they equivalent? {simplify(Implies(symbolic_rule, test_formula)) == True}")

# Step 2: Convert to jsonLogic for runtime use
print("\n\nStep 2: Converting to jsonLogic for runtime")
print("=" * 50)

json_rule = {
    "if": [
        {"and": [{"var": "P"}, {"var": "Q"}]},
        {"var": "R"},
        True
    ]
}

# Test cases
test_cases = [
    {"P": True, "Q": True, "R": True},
    {"P": True, "Q": True, "R": False},
    {"P": False, "Q": True, "R": False},
]

for i, case in enumerate(test_cases, 1):
    result = jsonLogic(json_rule, case)
    print(f"Test case {i}: {case} => {result}")

print("\n✓ Rule verified symbolically and ready for production use!")

9. Advanced Topics

Beyond Basic Logic Programming

Once you're comfortable with the fundamentals, explore these advanced areas:

Constraint Programming

Google OR-Tools and python-constraint provide powerful constraint satisfaction problem (CSP) solving.

  • Scheduling and planning
  • Resource allocation
  • Optimization problems
Knowledge Graphs

RDFLib and Neo4j enable semantic reasoning over graph-structured knowledge.

  • Ontology reasoning
  • Semantic web applications
  • SPARQL queries
Probabilistic Logic

ProbLog and PyMC combine logic with probability for uncertain reasoning.

  • Uncertain knowledge
  • Bayesian reasoning
  • Statistical relational learning
Neuro-Symbolic AI

Combining deep learning with symbolic reasoning for explainable AI.

  • Logic Tensor Networks
  • Neural Theorem Provers
  • Differentiable reasoning

Installation Guide

Installation Commands
# Install all libraries covered in this guide
pip install sympy
pip install logpy  # Kanren
pip install pyDatalog
pip install pytholog
pip install json-logic

# Optional: Advanced libraries
pip install ortools  # Constraint programming
pip install python-constraint
pip install rdflib  # Knowledge graphs
pip install problog  # Probabilistic logic

10. References & Resources

Official Documentation

Books & Papers

Additional Learning Resources

Key Takeaways

  1. Logic enables structured reasoning - Essential for AI and intelligent systems
  2. Python supports multiple logic paradigms - Choose based on your use case
  3. Each library has strengths - SymPy for math, Kanren for relations, jsonLogic for portability
  4. Libraries can interoperate - Combine them for powerful hybrid systems
  5. Start simple, scale up - Begin with basic examples, then tackle complex problems
SE444: Artificial Intelligence | Programming Logic in Python Guide