Tutorial 2: Your First Query¶
This tutorial introduces Mistaber's query system through a practical example: determining the halachic status of a meat and milk mixture.
Learning Objectives¶
- Understand the basic query interface
- Run queries using both the CLI and Python API
- Interpret query results
- Use the analyze command for scenario-based reasoning
Prerequisites¶
- Tutorial 1: Installation completed
- Mistaber environment set up
Estimated Time¶
15 minutes
Steps¶
Step 1: Understanding the Problem¶
Consider this scenario: You have a mixture containing beef and cow's milk. What is its halachic status according to the Shulchan Aruch?
This question involves:
- Food classification: Beef is beheima (domesticated animal)
- Mixture detection: The system must identify this as a basar bechalav (meat and milk) mixture
- Ruling derivation: The system must derive the appropriate prohibition level
Step 2: Create a Scenario File¶
Create a file called beef_milk_scenario.lp with the following content:
% beef_milk_scenario.lp
% A simple basar bechalav scenario
% Declare the foods
food(beef_portion).
food(cow_milk).
% Classify the foods
food_type(beef_portion, beheima). % Beef is from a domesticated animal
food_type(cow_milk, chalav). % Cow's milk is dairy
% Create a mixture
mixture(beef_milk_mix).
contains(beef_milk_mix, beef_portion).
contains(beef_milk_mix, cow_milk).
This scenario declares two foods, classifies them, and creates a mixture containing both.
Step 3: Run the Analyze Command (CLI)¶
Use the CLI to analyze this scenario:
python -m core.cli.main --ontology ./mistaber/ontology analyze beef_milk_scenario.lp --world mechaber
You should see output showing the derived conclusions:
Analysis Results
================
[1]
world: mechaber
scenario: food(beef_portion). food(cow_milk)...
atoms:
- holds(issur(achiila,beef_milk_mix,d_oraita),mechaber)
- holds(issur(bishul,beef_milk_mix,d_oraita),mechaber)
- holds(issur(hanaah,beef_milk_mix,d_oraita),mechaber)
- is_beheima_chalav_mixture(beef_milk_mix)
...
Step 4: Interpret the Results¶
The key derived atoms tell us:
| Atom | Meaning |
|---|---|
holds(issur(achiila,beef_milk_mix,d_oraita),mechaber) |
Eating is forbidden at the Torah level |
holds(issur(bishul,beef_milk_mix,d_oraita),mechaber) |
Cooking is forbidden at the Torah level |
holds(issur(hanaah,beef_milk_mix,d_oraita),mechaber) |
Deriving benefit is forbidden at the Torah level |
is_beheima_chalav_mixture(beef_milk_mix) |
System classified this as beheima + chalav |
The d_oraita level indicates this is a Torah-level prohibition, reflecting Yoreh Deah 87:1.
Step 5: Query Using Python API¶
Now let's do the same thing using the Python API:
from pathlib import Path
from mistaber.engine import HsrsEngine
# Initialize engine
engine = HsrsEngine(Path("mistaber/ontology"))
# Define the scenario
scenario = """
food(beef_portion).
food(cow_milk).
food_type(beef_portion, beheima).
food_type(cow_milk, chalav).
mixture(beef_milk_mix).
contains(beef_milk_mix, beef_portion).
contains(beef_milk_mix, cow_milk).
"""
# Analyze the scenario
result = engine.analyze(scenario, world="mechaber")
# Print derived atoms
print("Derived conclusions:")
for atom in result["atoms"]:
if "issur" in atom or "heter" in atom:
print(f" - {atom}")
Output:
Derived conclusions:
- holds(issur(achiila,beef_milk_mix,d_oraita),mechaber)
- holds(issur(bishul,beef_milk_mix,d_oraita),mechaber)
- holds(issur(hanaah,beef_milk_mix,d_oraita),mechaber)
Step 6: Query for Specific Information¶
Use pattern queries to extract specific information:
from pathlib import Path
from mistaber.engine import HsrsEngine
engine = HsrsEngine(Path("mistaber/ontology"))
# Query: What types of issur exist for our mixture?
scenario = """
food(beef).
food(milk).
food_type(beef, beheima).
food_type(milk, chalav).
mixture(test_mix).
contains(test_mix, beef).
contains(test_mix, milk).
"""
result = engine.analyze(scenario, world="mechaber")
# Filter for issur atoms
issurim = [a for a in result["atoms"] if "issur(" in a]
print("Prohibitions found:")
for issur in issurim:
print(f" {issur}")
Step 7: Compare Across Worlds¶
See how different authorities rule on the same scenario:
from pathlib import Path
from mistaber.engine import HsrsEngine
engine = HsrsEngine(Path("mistaber/ontology"))
# Compare issur holdings across mechaber and rema
comparison = engine.compare(
"holds(issur(achiila, M, D), W)",
worlds=["mechaber", "rema"]
)
print("Comparison of issur(achiila) across worlds:")
for world, results in comparison.items():
print(f"\n{world}:")
for r in results[:5]: # First 5 results
print(f" Mixture: {r.get('M', 'N/A')}, Level: {r.get('D', 'N/A')}")
Step 8: Ask Boolean Questions¶
Use ask() for simple yes/no questions:
from pathlib import Path
from mistaber.engine import HsrsEngine
engine = HsrsEngine(Path("mistaber/ontology"))
# Does the mechaber world exist?
print(f"Mechaber world exists: {engine.ask('world(mechaber)')}")
# Is mechaber accessible from base?
print(f"Mechaber inherits from base: {engine.ask('accessible(mechaber, base)')}")
Output:
Understanding Query Patterns¶
Variables vs Constants¶
In query patterns:
- Uppercase letters are variables: X, World, Mixture
- Lowercase words are constants: mechaber, base, achiila
# Variables (will match anything)
engine.query("world(X)") # All worlds
engine.query("holds(P, W)") # All properties in all worlds
# Constants (exact match)
engine.query("accessible(X, base)") # Worlds accessible from 'base'
Common Query Patterns¶
# All worlds
engine.query("world(X)")
# Inheritance relationships
engine.query("accessible(Child, Parent)")
# All issur holdings
engine.query("holds(issur(Act, Item, Level), World)")
# Specific issur type
engine.query("holds(issur(achiila, Item, Level), World)")
# All makor (source) citations
engine.query("makor(Rule, Source)")
Exercises¶
Exercise 1: Poultry and Milk¶
Create a scenario with chicken and milk. What issur level do you expect?
Solution
scenario = """
food(chicken_breast).
food(goat_milk).
food_type(chicken_breast, of). # Poultry
food_type(goat_milk, chalav).
mixture(chicken_milk_mix).
contains(chicken_milk_mix, chicken_breast).
contains(chicken_milk_mix, goat_milk).
"""
result = engine.analyze(scenario, world="mechaber")
# Expected: issur(achiila, chicken_milk_mix, d_rabanan)
# Note: Only eating is forbidden, and only at the rabbinic level
Exercise 2: Compare Mechaber and Rema¶
Create a fish and dairy scenario. How do the two authorities differ?
Solution
scenario = """
food(salmon).
food(cream).
food_type(salmon, dag).
food_type(cream, chalav).
mixture(fish_cream).
contains(fish_cream, salmon).
contains(fish_cream, cream).
"""
# Analyze in Mechaber's world
mechaber_result = engine.analyze(scenario, world="mechaber")
# Expected: sakana (health danger)
# Analyze in Rema's world
rema_result = engine.analyze(scenario, world="rema")
# Expected: heter (permitted)
What You've Learned¶
- How to create scenario files in ASP format
- How to use the
analyzecommand to derive conclusions - How to query using the Python API
- How to interpret issur and heter atoms
- How to compare results across worlds
Next Steps¶
Continue to Tutorial 3: Understanding Worlds to learn about Mistaber's multi-world Kripke semantics.
Quick Reference¶
from pathlib import Path
from mistaber.engine import HsrsEngine
engine = HsrsEngine(Path("mistaber/ontology"))
# Boolean query
engine.ask("world(base)") # True/False
# Pattern query
engine.query("world(X)") # List of bindings
# Analyze scenario
engine.analyze("food(x). ...", world="mechaber")
# Compare worlds
engine.compare("pattern", worlds=["mechaber", "rema"])