Case Study: Basar Bechalav Complete¶
A comprehensive walkthrough of Yoreh Deah Siman 87, demonstrating how Mistaber encodes the full spectrum of meat and milk prohibitions across all seven worlds.
Overview¶
Basar bechalav (meat and milk) is one of the foundational prohibitions in Jewish dietary law. The Torah states three times "lo tevashel gedi bachalev imo" (do not cook a kid in its mother's milk), teaching three distinct prohibitions:
- Bishul - Cooking meat and milk together
- Achiila - Eating meat and milk together
- Hanaah - Deriving benefit from meat and milk together
This case study demonstrates how Mistaber formally encodes these rules, handling the distinctions between different animal types and the disputes between authorities.
The Halachic Framework¶
Animal Categories¶
| Category | Hebrew | Examples | Level with Milk |
|---|---|---|---|
| Beheima | בהמה | Cow, sheep, goat | D'oraita |
| Chaya | ×—×™×” | Deer, gazelle | D'rabanan |
| Of | עוף | Chicken, turkey | D'rabanan |
| Dag | דג | Fish, salmon | Machloket (sakana vs mutar) |
The Three Prohibitions by Category¶
| Category | Achiila | Bishul | Hanaah |
|---|---|---|---|
| Beheima + Chalav | D'oraita | D'oraita | D'oraita |
| Chaya + Chalav | D'rabanan | Mutar | Mutar |
| Of + Chalav | D'rabanan | Mutar | Mutar |
| Dag + Chalav | Machloket | Machloket | Depends |
Core ASP Implementation¶
Mixture Detection (corpus/yd_87/base.lp)¶
The foundation is detecting what type of mixture we have:
% Basar types relevant to YD 87
basar_type(beheima).
basar_type(chaya).
basar_type(of).
basar_type(dag).
% A mixture contains basar if any component has a basar food type
mixture_has_basar(M, BType) :-
mixture(M),
contains(M, F),
food(F),
food_type(F, BType),
is_basar_type(BType).
% A mixture contains chalav if any component is dairy
mixture_has_chalav(M) :-
mixture(M),
contains(M, F),
food(F),
food_type(F, chalav).
% Specific mixture classifications
is_beheima_chalav_mixture(M) :-
mixture_has_basar(M, beheima),
mixture_has_chalav(M).
is_of_chalav_mixture(M) :-
mixture_has_basar(M, of),
mixture_has_chalav(M).
is_chaya_chalav_mixture(M) :-
mixture_has_basar(M, chaya),
mixture_has_chalav(M).
is_dag_chalav_mixture(M) :-
mixture_has_basar(M, dag),
mixture_has_chalav(M).
Mechaber's Rulings (worlds/mechaber.lp)¶
The Mechaber encodes the Shulchan Aruch's rulings:
% YD 87:1 - BEHEIMA + CHALAV: D'ORAITA
rule(r_bb_beheima_achiila).
makor(r_bb_beheima_achiila, sa("yd:87:1")).
madrega(r_bb_beheima_achiila, d_oraita).
scope(r_bb_beheima_achiila, mechaber).
asserts(mechaber, issur(achiila, M, d_oraita)) :-
is_beheima_chalav_mixture(M).
asserts(mechaber, issur(bishul, M, d_oraita)) :-
is_beheima_chalav_mixture(M).
asserts(mechaber, issur(hanaah, M, d_oraita)) :-
is_beheima_chalav_mixture(M).
% YD 87:3 - OF + CHALAV: D'RABANAN
rule(r_bb_of_achiila).
makor(r_bb_of_achiila, sa("yd:87:3")).
madrega(r_bb_of_achiila, d_rabanan).
scope(r_bb_of_achiila, mechaber).
asserts(mechaber, issur(achiila, M, d_rabanan)) :-
is_of_chalav_mixture(M).
% Bishul and hanaah are PERMITTED for of + chalav
asserts(mechaber, heter(bishul, M)) :-
is_of_chalav_mixture(M).
asserts(mechaber, heter(hanaah, M)) :-
is_of_chalav_mixture(M).
% YD 87:3 - DAG + CHALAV: SAKANA (Mechaber's unique position)
rule(r_bb_dag_sakana).
makor(r_bb_dag_sakana, sa("yd:87:3")).
makor(r_bb_dag_sakana, beit_yosef("yd:87")).
scope(r_bb_dag_sakana, mechaber).
asserts(mechaber, sakana(M)) :-
is_dag_chalav_mixture(M).
asserts(mechaber, issur(achiila, M, sakana)) :-
is_dag_chalav_mixture(M).
Rema's Rulings with Override (worlds/rema.lp)¶
The Rema agrees on most points but differs on fish + dairy:
% Rema agrees on beheima, chaya, and of
% (These rules mirror mechaber's)
% YD 87:3 - DAG + CHALAV: PERMITTED (KEY DISAGREEMENT)
rule(r_rema_dag_chalav_mutar).
makor(r_rema_dag_chalav_mutar, rema("yd:87:3")).
makor(r_rema_dag_chalav_mutar, taz("yd:87:3")).
scope(r_rema_dag_chalav_mutar, rema).
% Override the sakana ruling from Mechaber
override(rema, sakana(M), no_sakana) :-
is_dag_chalav_mixture(M).
override(rema, issur(achiila, M, sakana), permitted) :-
is_dag_chalav_mixture(M).
% Explicitly assert permission
asserts(rema, heter(achiila, M)) :-
is_dag_chalav_mixture(M).
asserts(rema, no_sakana(M)) :-
is_dag_chalav_mixture(M).
% Mark the machloket
machloket(dag_chalav, mechaber, rema, M) :-
is_dag_chalav_mixture(M).
Running the Complete Analysis¶
Test Scenario: Multiple Mixtures¶
from pathlib import Path
from mistaber.engine import HsrsEngine
engine = HsrsEngine(Path("mistaber/ontology"))
scenario = """
% === Define foods ===
food(beef). food_type(beef, beheima).
food(chicken). food_type(chicken, of).
food(venison). food_type(venison, chaya).
food(salmon). food_type(salmon, dag).
food(milk). food_type(milk, chalav).
% === Create mixtures ===
mixture(beef_milk).
contains(beef_milk, beef).
contains(beef_milk, milk).
mixture(chicken_milk).
contains(chicken_milk, chicken).
contains(chicken_milk, milk).
mixture(venison_milk).
contains(venison_milk, venison).
contains(venison_milk, milk).
mixture(salmon_milk).
contains(salmon_milk, salmon).
contains(salmon_milk, milk).
"""
# Analyze each mixture in both worlds
for world in ["mechaber", "rema"]:
result = engine.analyze(scenario, world=world)
print(f"\n=== {world.upper()} ===")
for mixture in ["beef_milk", "chicken_milk", "venison_milk", "salmon_milk"]:
issurim = [a for a in result["atoms"]
if mixture in a and ("issur" in a or "heter" in a or "sakana" in a)]
print(f"\n{mixture}:")
for i in issurim:
print(f" {i}")
Expected Output¶
=== MECHABER ===
beef_milk:
holds(issur(achiila,beef_milk,d_oraita),mechaber)
holds(issur(bishul,beef_milk,d_oraita),mechaber)
holds(issur(hanaah,beef_milk,d_oraita),mechaber)
chicken_milk:
holds(issur(achiila,chicken_milk,d_rabanan),mechaber)
holds(heter(bishul,chicken_milk),mechaber)
holds(heter(hanaah,chicken_milk),mechaber)
venison_milk:
holds(issur(achiila,venison_milk,d_rabanan),mechaber)
holds(heter(bishul,venison_milk),mechaber)
holds(heter(hanaah,venison_milk),mechaber)
salmon_milk:
holds(sakana(salmon_milk),mechaber)
holds(issur(achiila,salmon_milk,sakana),mechaber)
=== REMA ===
beef_milk:
holds(issur(achiila,beef_milk,d_oraita),rema)
holds(issur(bishul,beef_milk,d_oraita),rema)
holds(issur(hanaah,beef_milk,d_oraita),rema)
chicken_milk:
holds(issur(achiila,chicken_milk,d_rabanan),rema)
holds(heter(bishul,chicken_milk),rema)
holds(heter(hanaah,chicken_milk),rema)
venison_milk:
holds(issur(achiila,venison_milk,d_rabanan),rema)
holds(heter(bishul,venison_milk),rema)
holds(heter(hanaah,venison_milk),rema)
salmon_milk:
holds(heter(achiila,salmon_milk),rema)
holds(heter(bishul,salmon_milk),rema)
holds(no_sakana(salmon_milk),rema)
Tier 3 Worlds Inheritance¶
The Tier 3 worlds (ashk_mb, ashk_ah, sefardi_yo) inherit from their respective Tier 2 parents:
Sefardi Yalkut Yosef¶
% sefardi_yo inherits from mechaber
accessible(sefardi_yo, mechaber).
% Therefore:
% - Beheima+chalav: d'oraita (inherited)
% - Of+chalav: d'rabanan for achiila, mutar for bishul/hanaah (inherited)
% - Dag+chalav: SAKANA (inherited from mechaber)
Ashkenazi Mishnah Berurah¶
% ashk_mb inherits from rema
accessible(ashk_mb, rema).
% Therefore:
% - Beheima+chalav: d'oraita (inherited)
% - Of+chalav: d'rabanan for achiila, mutar for bishul/hanaah (inherited)
% - Dag+chalav: MUTAR (inherited via rema's override)
Ashkenazi Aruch Hashulchan¶
% ashk_ah inherits from BOTH rema AND gra
accessible(ashk_ah, rema).
accessible(ashk_ah, gra).
% Multiple inheritance - both parents agree on dag+chalav: mutar
% If they disagreed, would need explicit resolution
Comparing All Seven Worlds¶
from pathlib import Path
from mistaber.engine import HsrsEngine
engine = HsrsEngine(Path("mistaber/ontology"))
# Fish + dairy scenario
scenario = """
food(fish). food_type(fish, dag).
food(cream). food_type(cream, chalav).
mixture(fish_cream).
contains(fish_cream, fish).
contains(fish_cream, cream).
"""
all_worlds = ["base", "mechaber", "rema", "gra", "sefardi_yo", "ashk_mb", "ashk_ah"]
print("Fish + Dairy Status by World:")
print("=" * 50)
for world in all_worlds:
result = engine.analyze(scenario, world=world)
atoms = result["atoms"]
has_sakana = any("sakana(fish_cream)" in a for a in atoms)
has_issur = any("issur(achiila,fish_cream" in a for a in atoms)
has_heter = any("heter(achiila,fish_cream)" in a for a in atoms)
if has_sakana:
status = "FORBIDDEN (sakana)"
elif has_issur:
status = "FORBIDDEN (issur)"
elif has_heter:
status = "PERMITTED"
else:
status = "No ruling derived"
print(f"{world:15} -> {status}")
Expected Output¶
Fish + Dairy Status by World:
==================================================
base -> No ruling derived
mechaber -> FORBIDDEN (sakana)
rema -> PERMITTED
gra -> PERMITTED
sefardi_yo -> FORBIDDEN (sakana)
ashk_mb -> PERMITTED
ashk_ah -> PERMITTED
Source Citations (Makor)¶
Every rule has traceable sources:
engine = HsrsEngine(Path("mistaber/ontology"))
# Query all makor citations for YD 87 rules
makorot = engine.query("makor(Rule, Source)")
print("Source citations in basar bechalav rules:")
for m in makorot:
if "bb" in m.get("Rule", "").lower() or "87" in str(m.get("Source", "")):
print(f" {m['Rule']}: {m['Source']}")
Sample Output¶
Source citations in basar bechalav rules:
r_bb_beheima_achiila: sa("yd:87:1")
r_bb_beheima_bishul: sa("yd:87:1")
r_bb_of_achiila: sa("yd:87:3")
r_bb_dag_sakana: sa("yd:87:3")
r_bb_dag_sakana: beit_yosef("yd:87")
r_rema_dag_chalav_mutar: rema("yd:87:3")
r_rema_dag_chalav_mutar: taz("yd:87:3")
Practical Applications¶
Application 1: Restaurant Compliance¶
A restaurant wants to know if a dish is compliant for both Ashkenazi and Sefardi customers:
def check_compliance(mixture_scenario, target_worlds):
"""Check if a dish is compliant across multiple traditions."""
engine = HsrsEngine(Path("mistaber/ontology"))
compliance = {}
for world in target_worlds:
result = engine.analyze(mixture_scenario, world=world)
atoms = result["atoms"]
has_issur = any("issur(" in a for a in atoms)
has_sakana = any("sakana(" in a for a in atoms)
compliance[world] = not (has_issur or has_sakana)
return compliance
# Check lox and cream cheese
scenario = """
food(salmon). food_type(salmon, dag).
food(cream_cheese). food_type(cream_cheese, chalav).
mixture(lox_cream_cheese).
contains(lox_cream_cheese, salmon).
contains(lox_cream_cheese, cream_cheese).
"""
result = check_compliance(scenario, ["sefardi_yo", "ashk_mb"])
print(f"Lox & cream cheese compliance:")
print(f" Sefardi (Yalkut Yosef): {'OK' if result['sefardi_yo'] else 'NOT OK'}")
print(f" Ashkenazi (Mishnah Berurah): {'OK' if result['ashk_mb'] else 'NOT OK'}")
Application 2: Educational Tool¶
Generate a comparison table for teaching:
def generate_comparison_table():
"""Generate a teaching comparison table."""
engine = HsrsEngine(Path("mistaber/ontology"))
mixtures = {
"beef_milk": ("beheima", "chalav"),
"chicken_milk": ("of", "chalav"),
"fish_milk": ("dag", "chalav"),
}
for mix_name, (basar, dairy) in mixtures.items():
scenario = f"""
food({basar}_item). food_type({basar}_item, {basar}).
food({dairy}_item). food_type({dairy}_item, {dairy}).
mixture({mix_name}).
contains({mix_name}, {basar}_item).
contains({mix_name}, {dairy}_item).
"""
print(f"\n{mix_name.upper().replace('_', ' + ')}:")
for world in ["mechaber", "rema"]:
result = engine.analyze(scenario, world=world)
# Extract and display ruling...
Summary¶
This case study demonstrated:
- Mixture Detection: How ASP rules classify mixtures by component types
- World-Specific Rules: How different authorities encode their rulings
- Override Mechanism: How Rema's disagreement blocks inheritance
- Inheritance Chain: How Tier 3 worlds inherit from Tier 2
- Practical Queries: How to check compliance across traditions
- Source Traceability: Every rule maps back to its textual source
The basar bechalav encoding shows Mistaber's power: formally encoding complex, multi-layered halachic reasoning while preserving the authentic structure of rabbinic discourse.
Related Resources¶
- Fish and Dairy Machloket - Deep dive into the dispute
- Tutorial 3: Understanding Worlds
- Tutorial 5: Encoding Machloket