FuzzyInfer Interactive Tutorial¶
Welcome to FuzzyInfer! This interactive notebook will guide you through:
- Basic fuzzy inference concepts
- Creating facts and rules
- Running inference
- Using the fluent API
- Real-world applications
Prerequisites: pip install fuzzy-infer
In [ ]:
Copied!
# Install fuzzy-infer if needed
# !pip install fuzzy-infer
from fuzzy_infer import FuzzyInfer, Fact, Rule
from fuzzy_infer.fluent import FluentKB, FuzzySession, fuzzy
import json
print("FuzzyInfer imported successfully!")
# Install fuzzy-infer if needed
# !pip install fuzzy-infer
from fuzzy_infer import FuzzyInfer, Fact, Rule
from fuzzy_infer.fluent import FluentKB, FuzzySession, fuzzy
import json
print("FuzzyInfer imported successfully!")
In [ ]:
Copied!
# Create a fact: "Tweety is a bird with 90% certainty"
fact = Fact("is-bird", ["tweety"], 0.9)
print(f"Predicate: {fact.predicate}")
print(f"Arguments: {fact.args}")
print(f"Degree: {fact.degree}")
print(f"\nConfidence: {fact.degree * 100:.0f}%")
# Create a fact: "Tweety is a bird with 90% certainty"
fact = Fact("is-bird", ["tweety"], 0.9)
print(f"Predicate: {fact.predicate}")
print(f"Arguments: {fact.args}")
print(f"Degree: {fact.degree}")
print(f"\nConfidence: {fact.degree * 100:.0f}%")
Creating the Inference Engine¶
In [ ]:
Copied!
# Create the inference engine
inf = FuzzyInfer(max_iterations=100)
# Add some facts
inf.add_fact(Fact("is-bird", ["tweety"], 0.9))
inf.add_fact(Fact("is-bird", ["robin"], 0.95))
inf.add_fact(Fact("has-wings", ["tweety"], 1.0))
inf.add_fact(Fact("has-wings", ["robin"], 1.0))
# Query what we know
birds = inf.query("is-bird")
print(f"Found {len(birds)} birds:")
for fact in birds:
print(f" - {fact.args[0]}: {fact.degree * 100:.0f}% confidence")
# Create the inference engine
inf = FuzzyInfer(max_iterations=100)
# Add some facts
inf.add_fact(Fact("is-bird", ["tweety"], 0.9))
inf.add_fact(Fact("is-bird", ["robin"], 0.95))
inf.add_fact(Fact("has-wings", ["tweety"], 1.0))
inf.add_fact(Fact("has-wings", ["robin"], 1.0))
# Query what we know
birds = inf.query("is-bird")
print(f"Found {len(birds)} birds:")
for fact in birds:
print(f" - {fact.args[0]}: {fact.degree * 100:.0f}% confidence")
Part 2: Rules and Inference¶
Rules define how to derive new knowledge from existing facts.
Example: "If X is a bird, then X can fly (with 90% confidence)"
In [ ]:
Copied!
# Create a rule: birds can fly
birds_fly_rule = Rule(
name="birds-can-fly",
conditions=[
{"pred": "is-bird", "args": ["?x"], "deg": "?d"}
],
actions=[
{"action": "add", "fact": {
"pred": "can-fly",
"args": ["?x"],
"deg": ["*", "?d", 0.9] # Multiply bird confidence by 0.9
}}
]
)
# Add rule to engine
inf.add_rule(birds_fly_rule)
print("Rule added successfully!")
# Create a rule: birds can fly
birds_fly_rule = Rule(
name="birds-can-fly",
conditions=[
{"pred": "is-bird", "args": ["?x"], "deg": "?d"}
],
actions=[
{"action": "add", "fact": {
"pred": "can-fly",
"args": ["?x"],
"deg": ["*", "?d", 0.9] # Multiply bird confidence by 0.9
}}
]
)
# Add rule to engine
inf.add_rule(birds_fly_rule)
print("Rule added successfully!")
In [ ]:
Copied!
# Run inference
print("Running inference...\n")
result = inf.run()
print(f"Inference completed in {result.iteration} iteration(s)")
print(f"New facts generated: {len(result.new_facts)}\n")
# Query who can fly
can_fly = inf.query("can-fly")
print("Flying creatures:")
for fact in can_fly:
print(f" - {fact.args[0]}: {fact.degree * 100:.1f}% confidence")
# Run inference
print("Running inference...\n")
result = inf.run()
print(f"Inference completed in {result.iteration} iteration(s)")
print(f"New facts generated: {len(result.new_facts)}\n")
# Query who can fly
can_fly = inf.query("can-fly")
print("Flying creatures:")
for fact in can_fly:
print(f" - {fact.args[0]}: {fact.degree * 100:.1f}% confidence")
How Degrees Are Calculated¶
Notice how the degrees are calculated:
- Tweety is bird (0.9) × can fly (0.9) = 0.81 (81%)
- Robin is bird (0.95) × can fly (0.9) = 0.855 (85.5%)
This is fuzzy reasoning - uncertainty propagates through the inference!
Part 3: Complex Rules with Multiple Conditions¶
Rules can have multiple conditions (AND logic).
In [ ]:
Copied!
# Start fresh
inf2 = FuzzyInfer()
# Add facts about animals
inf2.add_fact(Fact("has-fur", ["dog"], 1.0))
inf2.add_fact(Fact("has-four-legs", ["dog"], 1.0))
inf2.add_fact(Fact("barks", ["dog"], 0.95))
inf2.add_fact(Fact("has-fur", ["cat"], 1.0))
inf2.add_fact(Fact("has-four-legs", ["cat"], 1.0))
inf2.add_fact(Fact("meows", ["cat"], 0.9))
# Rule 1: Animals with fur and four legs are mammals
mammal_rule = Rule(
name="mammal-classification",
priority=100,
conditions=[
{"pred": "has-fur", "args": ["?x"], "deg": "?d1"},
{"pred": "has-four-legs", "args": ["?x"], "deg": "?d2"}
],
actions=[
{"action": "add", "fact": {
"pred": "is-mammal",
"args": ["?x"],
"deg": ["*", ["min", "?d1", "?d2"], 0.95] # Use minimum of both degrees
}}
]
)
# Rule 2: Mammals that bark are likely dogs
dog_rule = Rule(
name="dog-classification",
priority=50,
conditions=[
{"pred": "is-mammal", "args": ["?x"], "deg": "?d1"},
{"pred": "barks", "args": ["?x"], "deg": "?d2"},
{"deg-pred": [">", "?d2", 0.7]} # Only if barks > 70%
],
actions=[
{"action": "add", "fact": {
"pred": "is-dog",
"args": ["?x"],
"deg": ["*", ["min", "?d1", "?d2"], 0.9]
}}
]
)
# Rule 3: Mammals that meow are likely cats
cat_rule = Rule(
name="cat-classification",
priority=50,
conditions=[
{"pred": "is-mammal", "args": ["?x"], "deg": "?d1"},
{"pred": "meows", "args": ["?x"], "deg": "?d2"},
{"deg-pred": [">", "?d2", 0.7]}
],
actions=[
{"action": "add", "fact": {
"pred": "is-cat",
"args": ["?x"],
"deg": ["*", ["min", "?d1", "?d2"], 0.9]
}}
]
)
inf2.add_rules([mammal_rule, dog_rule, cat_rule])
print("Rules added successfully!")
# Start fresh
inf2 = FuzzyInfer()
# Add facts about animals
inf2.add_fact(Fact("has-fur", ["dog"], 1.0))
inf2.add_fact(Fact("has-four-legs", ["dog"], 1.0))
inf2.add_fact(Fact("barks", ["dog"], 0.95))
inf2.add_fact(Fact("has-fur", ["cat"], 1.0))
inf2.add_fact(Fact("has-four-legs", ["cat"], 1.0))
inf2.add_fact(Fact("meows", ["cat"], 0.9))
# Rule 1: Animals with fur and four legs are mammals
mammal_rule = Rule(
name="mammal-classification",
priority=100,
conditions=[
{"pred": "has-fur", "args": ["?x"], "deg": "?d1"},
{"pred": "has-four-legs", "args": ["?x"], "deg": "?d2"}
],
actions=[
{"action": "add", "fact": {
"pred": "is-mammal",
"args": ["?x"],
"deg": ["*", ["min", "?d1", "?d2"], 0.95] # Use minimum of both degrees
}}
]
)
# Rule 2: Mammals that bark are likely dogs
dog_rule = Rule(
name="dog-classification",
priority=50,
conditions=[
{"pred": "is-mammal", "args": ["?x"], "deg": "?d1"},
{"pred": "barks", "args": ["?x"], "deg": "?d2"},
{"deg-pred": [">", "?d2", 0.7]} # Only if barks > 70%
],
actions=[
{"action": "add", "fact": {
"pred": "is-dog",
"args": ["?x"],
"deg": ["*", ["min", "?d1", "?d2"], 0.9]
}}
]
)
# Rule 3: Mammals that meow are likely cats
cat_rule = Rule(
name="cat-classification",
priority=50,
conditions=[
{"pred": "is-mammal", "args": ["?x"], "deg": "?d1"},
{"pred": "meows", "args": ["?x"], "deg": "?d2"},
{"deg-pred": [">", "?d2", 0.7]}
],
actions=[
{"action": "add", "fact": {
"pred": "is-cat",
"args": ["?x"],
"deg": ["*", ["min", "?d1", "?d2"], 0.9]
}}
]
)
inf2.add_rules([mammal_rule, dog_rule, cat_rule])
print("Rules added successfully!")
In [ ]:
Copied!
# Run inference
result = inf2.run()
print(f"Inference completed in {result.iteration} iterations\n")
# Check classifications
for animal in ["dog", "cat"]:
print(f"\n{animal.upper()}:")
is_mammal = inf2.query("is-mammal", [animal])
if is_mammal:
print(f" is-mammal: {is_mammal[0].degree * 100:.1f}%")
is_dog = inf2.query("is-dog", [animal])
if is_dog:
print(f" is-dog: {is_dog[0].degree * 100:.1f}%")
is_cat = inf2.query("is-cat", [animal])
if is_cat:
print(f" is-cat: {is_cat[0].degree * 100:.1f}%")
# Run inference
result = inf2.run()
print(f"Inference completed in {result.iteration} iterations\n")
# Check classifications
for animal in ["dog", "cat"]:
print(f"\n{animal.upper()}:")
is_mammal = inf2.query("is-mammal", [animal])
if is_mammal:
print(f" is-mammal: {is_mammal[0].degree * 100:.1f}%")
is_dog = inf2.query("is-dog", [animal])
if is_dog:
print(f" is-dog: {is_dog[0].degree * 100:.1f}%")
is_cat = inf2.query("is-cat", [animal])
if is_cat:
print(f" is-cat: {is_cat[0].degree * 100:.1f}%")
Part 4: Fluent API - Beautiful Python¶
The fluent API provides a modern, chainable interface.
In [ ]:
Copied!
# Beautiful method chaining
results = (
FluentKB()
.fact("is-bird", ["robin"], 0.9)
.fact("is-bird", ["eagle"], 1.0)
.fact("is-bird", ["penguin"], 0.95)
.fact("is-flightless", ["penguin"], 1.0)
.rule(
when=("is-bird", "?x"),
then=("can-fly", "?x", 0.9),
name="birds-fly",
priority=50
)
.rule(
when=("is-flightless", "?x"),
then=("can-fly", "?x", 0.1),
name="flightless-override",
priority=100 # Higher priority
)
.infer()
.where("can-fly")
)
print("Flying creatures:")
for fact in results:
print(f" - {fact.args[0]}: {fact.degree * 100:.1f}%")
# Beautiful method chaining
results = (
FluentKB()
.fact("is-bird", ["robin"], 0.9)
.fact("is-bird", ["eagle"], 1.0)
.fact("is-bird", ["penguin"], 0.95)
.fact("is-flightless", ["penguin"], 1.0)
.rule(
when=("is-bird", "?x"),
then=("can-fly", "?x", 0.9),
name="birds-fly",
priority=50
)
.rule(
when=("is-flightless", "?x"),
then=("can-fly", "?x", 0.1),
name="flightless-override",
priority=100 # Higher priority
)
.infer()
.where("can-fly")
)
print("Flying creatures:")
for fact in results:
print(f" - {fact.args[0]}: {fact.degree * 100:.1f}%")
Query Chaining¶
In [ ]:
Copied!
# Create knowledge base with multiple facts
kb = fuzzy(
("temperature", ["room-1"], 0.85),
("temperature", ["room-2"], 0.45),
("temperature", ["room-3"], 0.92),
("humidity", ["room-1"], 0.70),
("humidity", ["room-2"], 0.30),
("humidity", ["room-3"], 0.75)
)
# Add rules for climate control
kb.rule(
when=kb["temperature"]["?room"] >= 0.7,
then=("ac-on", "?room", 0.95)
).rule(
when=kb["humidity"]["?room"] >= 0.65,
then=("dehumidifier-on", "?room", 0.9)
)
kb.infer()
# Query with chaining
hot_rooms = (
kb.where("temperature")
.having_degree('>', 0.8)
.map(lambda f: f.args[0])
)
print(f"Hot rooms: {hot_rooms}")
# Query what actions to take
ac_rooms = kb.where("ac-on").map(lambda f: f.args[0])
dehumid_rooms = kb.where("dehumidifier-on").map(lambda f: f.args[0])
print(f"Turn on AC in: {ac_rooms}")
print(f"Turn on dehumidifier in: {dehumid_rooms}")
# Create knowledge base with multiple facts
kb = fuzzy(
("temperature", ["room-1"], 0.85),
("temperature", ["room-2"], 0.45),
("temperature", ["room-3"], 0.92),
("humidity", ["room-1"], 0.70),
("humidity", ["room-2"], 0.30),
("humidity", ["room-3"], 0.75)
)
# Add rules for climate control
kb.rule(
when=kb["temperature"]["?room"] >= 0.7,
then=("ac-on", "?room", 0.95)
).rule(
when=kb["humidity"]["?room"] >= 0.65,
then=("dehumidifier-on", "?room", 0.9)
)
kb.infer()
# Query with chaining
hot_rooms = (
kb.where("temperature")
.having_degree('>', 0.8)
.map(lambda f: f.args[0])
)
print(f"Hot rooms: {hot_rooms}")
# Query what actions to take
ac_rooms = kb.where("ac-on").map(lambda f: f.args[0])
dehumid_rooms = kb.where("dehumidifier-on").map(lambda f: f.args[0])
print(f"Turn on AC in: {ac_rooms}")
print(f"Turn on dehumidifier in: {dehumid_rooms}")
Context Manager (FuzzySession)¶
In [ ]:
Copied!
# Automatic inference on context exit
with FuzzySession() as session:
session.facts(
("is-mammal", ["dog"], 1.0),
("is-mammal", ["cat"], 1.0),
("is-mammal", ["whale"], 0.95)
)
session.rule(
when=("is-mammal", "?x"),
then=("warm-blooded", "?x", 0.99)
)
# Inference happens automatically
warm = session.query("warm-blooded")
print("Warm-blooded creatures:")
for fact in warm:
print(f" - {fact.args[0]}: {fact.degree * 100:.1f}%")
# Automatic inference on context exit
with FuzzySession() as session:
session.facts(
("is-mammal", ["dog"], 1.0),
("is-mammal", ["cat"], 1.0),
("is-mammal", ["whale"], 0.95)
)
session.rule(
when=("is-mammal", "?x"),
then=("warm-blooded", "?x", 0.99)
)
# Inference happens automatically
warm = session.query("warm-blooded")
print("Warm-blooded creatures:")
for fact in warm:
print(f" - {fact.args[0]}: {fact.degree * 100:.1f}%")
Part 5: Real-World Application - Medical Diagnosis¶
Let's build a simple medical diagnosis system.
In [ ]:
Copied!
# Create medical diagnosis system
medical = FluentKB()
# Patient symptoms (with confidence levels)
medical.facts(
("symptom", ["patient1", "fever"], 0.9),
("symptom", ["patient1", "cough"], 0.7),
("symptom", ["patient1", "fatigue"], 0.8),
("symptom", ["patient2", "fever"], 0.95),
("symptom", ["patient2", "sore-throat"], 0.85),
("symptom", ["patient2", "headache"], 0.6)
)
# Diagnostic rules
medical.rule(
when=[
("symptom", "?patient", "fever"),
("symptom", "?patient", "cough")
],
then=("possible-condition", "?patient", "respiratory-infection", 0.75),
name="respiratory-diagnosis"
).rule(
when=[
("symptom", "?patient", "fever"),
("symptom", "?patient", "sore-throat")
],
then=("possible-condition", "?patient", "throat-infection", 0.7),
name="throat-diagnosis"
).rule(
when=[
("symptom", "?patient", "fatigue"),
("symptom", "?patient", "cough")
],
then=("possible-condition", "?patient", "chronic-condition", 0.5),
name="chronic-diagnosis"
)
# Run diagnosis
medical.infer()
# Show diagnoses
for patient in ["patient1", "patient2"]:
print(f"\n{patient.upper()} - Diagnosis:")
# Get symptoms
symptoms = medical.where("symptom").where(lambda f: f.args[0] == patient)
print(" Symptoms:")
for s in symptoms:
print(f" - {s.args[1]}: {s.degree * 100:.0f}%")
# Get possible conditions
conditions = medical.where("possible-condition").where(lambda f: f.args[0] == patient)
print(" Possible conditions:")
for c in sorted(conditions, key=lambda f: f.degree, reverse=True):
print(f" - {c.args[1]}: {c.degree * 100:.1f}% confidence")
# Create medical diagnosis system
medical = FluentKB()
# Patient symptoms (with confidence levels)
medical.facts(
("symptom", ["patient1", "fever"], 0.9),
("symptom", ["patient1", "cough"], 0.7),
("symptom", ["patient1", "fatigue"], 0.8),
("symptom", ["patient2", "fever"], 0.95),
("symptom", ["patient2", "sore-throat"], 0.85),
("symptom", ["patient2", "headache"], 0.6)
)
# Diagnostic rules
medical.rule(
when=[
("symptom", "?patient", "fever"),
("symptom", "?patient", "cough")
],
then=("possible-condition", "?patient", "respiratory-infection", 0.75),
name="respiratory-diagnosis"
).rule(
when=[
("symptom", "?patient", "fever"),
("symptom", "?patient", "sore-throat")
],
then=("possible-condition", "?patient", "throat-infection", 0.7),
name="throat-diagnosis"
).rule(
when=[
("symptom", "?patient", "fatigue"),
("symptom", "?patient", "cough")
],
then=("possible-condition", "?patient", "chronic-condition", 0.5),
name="chronic-diagnosis"
)
# Run diagnosis
medical.infer()
# Show diagnoses
for patient in ["patient1", "patient2"]:
print(f"\n{patient.upper()} - Diagnosis:")
# Get symptoms
symptoms = medical.where("symptom").where(lambda f: f.args[0] == patient)
print(" Symptoms:")
for s in symptoms:
print(f" - {s.args[1]}: {s.degree * 100:.0f}%")
# Get possible conditions
conditions = medical.where("possible-condition").where(lambda f: f.args[0] == patient)
print(" Possible conditions:")
for c in sorted(conditions, key=lambda f: f.degree, reverse=True):
print(f" - {c.args[1]}: {c.degree * 100:.1f}% confidence")
Part 6: Temperature Control System¶
A practical IoT example.
In [ ]:
Copied!
import random
# Simulate sensor readings
def generate_sensor_data(num_rooms=5):
"""Generate random sensor data for rooms."""
sensors = []
for i in range(1, num_rooms + 1):
room = f"room-{i}"
temp = random.uniform(0.0, 1.0)
humidity = random.uniform(0.0, 1.0)
sensors.append(("temperature", [room], temp))
sensors.append(("humidity", [room], humidity))
return sensors
# Create smart home system
sensors = generate_sensor_data(5)
smart_home = fuzzy(*sensors)
# Control rules
smart_home.rule(
when=smart_home["temperature"]["?room"] > 0.75,
then=("action", "?room", "cooling", 0.95),
name="hot-room-cooling"
).rule(
when=smart_home["temperature"]["?room"] < 0.25,
then=("action", "?room", "heating", 0.95),
name="cold-room-heating"
).rule(
when=smart_home["humidity"]["?room"] > 0.70,
then=("action", "?room", "dehumidify", 0.9),
name="humid-room-dehumidify"
).rule(
when=smart_home["humidity"]["?room"] < 0.30,
then=("action", "?room", "humidify", 0.9),
name="dry-room-humidify"
)
# Run control system
smart_home.infer()
# Display results
print("SMART HOME STATUS\n" + "="*50)
for i in range(1, 6):
room = f"room-{i}"
print(f"\n{room.upper()}:")
# Get sensor readings
temp = smart_home.query("temperature", [room]).first
humid = smart_home.query("humidity", [room]).first
if temp:
print(f" Temperature: {temp.degree * 100:.1f}% (0=cold, 100=hot)")
if humid:
print(f" Humidity: {humid.degree * 100:.1f}% (0=dry, 100=humid)")
# Get actions
actions = smart_home.where("action").where(lambda f: f.args[0] == room)
if actions:
print(" Actions:")
for action in actions:
print(f" → {action.args[1].upper()}: {action.degree * 100:.0f}% priority")
import random
# Simulate sensor readings
def generate_sensor_data(num_rooms=5):
"""Generate random sensor data for rooms."""
sensors = []
for i in range(1, num_rooms + 1):
room = f"room-{i}"
temp = random.uniform(0.0, 1.0)
humidity = random.uniform(0.0, 1.0)
sensors.append(("temperature", [room], temp))
sensors.append(("humidity", [room], humidity))
return sensors
# Create smart home system
sensors = generate_sensor_data(5)
smart_home = fuzzy(*sensors)
# Control rules
smart_home.rule(
when=smart_home["temperature"]["?room"] > 0.75,
then=("action", "?room", "cooling", 0.95),
name="hot-room-cooling"
).rule(
when=smart_home["temperature"]["?room"] < 0.25,
then=("action", "?room", "heating", 0.95),
name="cold-room-heating"
).rule(
when=smart_home["humidity"]["?room"] > 0.70,
then=("action", "?room", "dehumidify", 0.9),
name="humid-room-dehumidify"
).rule(
when=smart_home["humidity"]["?room"] < 0.30,
then=("action", "?room", "humidify", 0.9),
name="dry-room-humidify"
)
# Run control system
smart_home.infer()
# Display results
print("SMART HOME STATUS\n" + "="*50)
for i in range(1, 6):
room = f"room-{i}"
print(f"\n{room.upper()}:")
# Get sensor readings
temp = smart_home.query("temperature", [room]).first
humid = smart_home.query("humidity", [room]).first
if temp:
print(f" Temperature: {temp.degree * 100:.1f}% (0=cold, 100=hot)")
if humid:
print(f" Humidity: {humid.degree * 100:.1f}% (0=dry, 100=humid)")
# Get actions
actions = smart_home.where("action").where(lambda f: f.args[0] == room)
if actions:
print(" Actions:")
for action in actions:
print(f" → {action.args[1].upper()}: {action.degree * 100:.0f}% priority")
Part 7: Advanced - Chained Reasoning¶
Multiple rules can chain together to derive complex conclusions.
In [ ]:
Copied!
# Create a genealogy system
family = FluentKB()
# Define family relationships
family.facts(
("parent", ["alice", "bob"], 1.0),
("parent", ["bob", "charlie"], 1.0),
("parent", ["bob", "diana"], 1.0),
("parent", ["charlie", "eve"], 1.0),
("parent", ["diana", "frank"], 1.0)
)
# Rule 1: Grandparent relationship
family.rule(
when=[
("parent", "?x", "?y"),
("parent", "?y", "?z")
],
then=("grandparent", "?x", "?z", 0.95),
name="grandparent-rule"
)
# Rule 2: Great-grandparent relationship
family.rule(
when=[
("parent", "?x", "?y"),
("grandparent", "?y", "?z")
],
then=("great-grandparent", "?x", "?z", 0.9),
name="great-grandparent-rule"
)
# Rule 3: Siblings (share same parent)
family.rule(
when=[
("parent", "?p", "?x"),
("parent", "?p", "?y")
],
then=("sibling", "?x", "?y", 0.98),
name="sibling-rule"
)
# Run inference
family.infer()
# Display family tree insights
print("FAMILY RELATIONSHIPS\n" + "="*50)
print("\nGrandparents:")
for fact in family.where("grandparent"):
print(f" {fact.args[0]} is grandparent of {fact.args[1]} ({fact.degree * 100:.0f}%)")
print("\nGreat-grandparents:")
for fact in family.where("great-grandparent"):
print(f" {fact.args[0]} is great-grandparent of {fact.args[1]} ({fact.degree * 100:.0f}%)")
print("\nSiblings:")
siblings = family.where("sibling")
seen = set()
for fact in siblings:
pair = tuple(sorted([fact.args[0], fact.args[1]]))
if pair not in seen and fact.args[0] != fact.args[1]:
print(f" {fact.args[0]} and {fact.args[1]} are siblings ({fact.degree * 100:.0f}%)")
seen.add(pair)
# Create a genealogy system
family = FluentKB()
# Define family relationships
family.facts(
("parent", ["alice", "bob"], 1.0),
("parent", ["bob", "charlie"], 1.0),
("parent", ["bob", "diana"], 1.0),
("parent", ["charlie", "eve"], 1.0),
("parent", ["diana", "frank"], 1.0)
)
# Rule 1: Grandparent relationship
family.rule(
when=[
("parent", "?x", "?y"),
("parent", "?y", "?z")
],
then=("grandparent", "?x", "?z", 0.95),
name="grandparent-rule"
)
# Rule 2: Great-grandparent relationship
family.rule(
when=[
("parent", "?x", "?y"),
("grandparent", "?y", "?z")
],
then=("great-grandparent", "?x", "?z", 0.9),
name="great-grandparent-rule"
)
# Rule 3: Siblings (share same parent)
family.rule(
when=[
("parent", "?p", "?x"),
("parent", "?p", "?y")
],
then=("sibling", "?x", "?y", 0.98),
name="sibling-rule"
)
# Run inference
family.infer()
# Display family tree insights
print("FAMILY RELATIONSHIPS\n" + "="*50)
print("\nGrandparents:")
for fact in family.where("grandparent"):
print(f" {fact.args[0]} is grandparent of {fact.args[1]} ({fact.degree * 100:.0f}%)")
print("\nGreat-grandparents:")
for fact in family.where("great-grandparent"):
print(f" {fact.args[0]} is great-grandparent of {fact.args[1]} ({fact.degree * 100:.0f}%)")
print("\nSiblings:")
siblings = family.where("sibling")
seen = set()
for fact in siblings:
pair = tuple(sorted([fact.args[0], fact.args[1]]))
if pair not in seen and fact.args[0] != fact.args[1]:
print(f" {fact.args[0]} and {fact.args[1]} are siblings ({fact.degree * 100:.0f}%)")
seen.add(pair)
Summary¶
You've learned:
- Fuzzy Logic Basics: Degrees of truth (0.0 to 1.0)
- Facts: Representing knowledge with uncertainty
- Rules: Deriving new knowledge from existing facts
- Inference: Automatic forward-chaining reasoning
- Fluent API: Beautiful, chainable Python interface
- Real Applications: Medical diagnosis, smart homes, family trees
Next Steps¶
- Explore the API documentation
- Read the User Guide
- Try the CLI for Unix-style workflows
- Build your own fuzzy inference system!
Further Reading¶
- Core Concepts - Deep dive into theory
- Inference Engine - How it works
- Unix Pipes - Composable workflows
- Examples - More code examples
Happy inferring! 🚀