Data Flows¶
Overview¶
This document describes how data flows through Mistaber from user input to final reasoning results.
High-Level Flow¶
flowchart TB
subgraph INPUT["USER INPUT"]
hll["HLL Source Code<br/>@world, @rule, @makor, facts, rules"]
end
subgraph COMPILE["COMPILATION FLOW"]
comp["HLL → AST → Normalized → Validated → ASP"]
end
subgraph REASON["REASONING FLOW"]
reason["ASP + Ontology → Clingo → Answer Sets"]
end
subgraph OUTPUT["OUTPUT"]
out["Forbidden/Permitted • Source traceability • Explanations"]
end
INPUT --> COMPILE --> REASON --> OUTPUT
1. Compilation Flow¶
Input: HLL Source Code¶
@world(base)
@rule(r_basar_bechalav)
@makor([sa("YD:87:1"), rambam("Maachalot Asurot 9:1")])
@madrega(d_oraita)
basar(chicken).
chalav(milk).
mixture(m1).
contains(m1, chicken).
contains(m1, milk).
forbidden(W, achiila, M, ctx_normal) :-
mixture(M),
mixture_is_basar_bechalav(M).
Stage 1: Parsing¶
Input: HLL source string
Output: ParseResult dataclass
ParseResult(
facts=[
Fact(predicate="basar", args=["chicken"]),
Fact(predicate="chalav", args=["milk"]),
Fact(predicate="mixture", args=["m1"]),
Fact(predicate="contains", args=["m1", "chicken"]),
Fact(predicate="contains", args=["m1", "milk"]),
],
rules=[
Rule(
head=Atom(predicate="forbidden", args=["W", "achiila", "M", "ctx_normal"]),
body=[
Atom(predicate="mixture", args=["M"]),
Atom(predicate="mixture_is_basar_bechalav", args=["M"]),
]
)
],
world="base",
rule_id="r_basar_bechalav",
sources=[("sa", "YD:87:1"), ("rambam", "Maachalot Asurot 9:1")],
madrega="d_oraita"
)
Stage 2: Normalization¶
Input: ParseResult with surface syntax
Output: ParseResult with canonical predicates
Transformations:
| Surface | Canonical |
|---------|-----------|
| basar(chicken) | food_type(chicken, basar) |
| chalav(milk) | food_type(milk, chalav) |
ParseResult(
facts=[
Fact(predicate="food_type", args=["chicken", "basar"]), # Normalized
Fact(predicate="food_type", args=["milk", "chalav"]), # Normalized
Fact(predicate="mixture", args=["m1"]),
Fact(predicate="contains", args=["m1", "chicken"]),
Fact(predicate="contains", args=["m1", "milk"]),
],
# ... rules unchanged, directives preserved
)
Stage 3: Type Checking¶
Input: Normalized ParseResult
Output: List of TypeCheckError (errors and warnings)
Validations:
1. Predicate lookup: food_type exists in registry
2. Arity check: food_type has arity 2
3. Sort check: basar is valid for food_category sort
4. Makor check: normative rules have @makor directive
5. OWA negation: warn if negating open-world predicates
errors = [] # No errors in valid input
# If errors occurred:
errors = [
TypeCheckError(
message="Undeclared predicate: 'unknown_pred'",
severity="error"
),
TypeCheckError(
message="Using negation on OWA predicate 'permitted'",
severity="warning"
)
]
Stage 4: Emission¶
Input: Validated ParseResult
Output: ASP code string
% World: base
% Rule ID: r_basar_bechalav
rule(r_basar_bechalav).
scope(r_basar_bechalav, base).
makor(r_basar_bechalav, sa("YD:87:1")).
makor(r_basar_bechalav, rambam("Maachalot Asurot 9:1")).
madrega(r_basar_bechalav, d_oraita).
food_type(chicken, basar).
food_type(milk, chalav).
mixture(m1).
contains(m1, chicken).
contains(m1, milk).
%!trace_rule {"r_basar_bechalav: action on food is forbidden"}
forbidden(W, achiila, M, ctx_normal) :- mixture(M), mixture_is_basar_bechalav(M).
2. Reasoning Flow¶
Input Assembly¶
The solver receives multiple inputs combined:
flowchart LR
subgraph CLINGO["CLINGO INPUT"]
direction TB
schema["1. Schema Files<br/>sorts.lp | constraints.lp | disjointness.lp"]
base["2. Base Ontology<br/>substance.lp | madrega.lp | context.lp<br/>temporal.lp | status.lp | shiur.lp"]
ext["3. Extensions (optional)<br/>ontology/extensions/*.lp"]
user["4. User Program<br/>Compiled ASP from HLL"]
end
schema --> base --> ext --> user
Grounding Phase¶
Clingo grounds all rules with concrete values:
% User declared:
food_type(chicken, basar).
% Ontology rule (substance.lp):
food_type(F, Parent) :- food_type(F, Child), subcategory_of(Child, Parent).
% After grounding with subcategory(basar, maakhal):
food_type(chicken, maakhal). % Derived
% User declared:
contains(m1, chicken).
contains(m1, milk).
% Ontology rule (substance.lp):
mixture_contains_basar(M) :- mixture(M), contains(M, F), food_type(F, basar).
% After grounding:
mixture_contains_basar(m1). % Derived (chicken is basar)
mixture_contains_chalav(m1). % Derived (milk is chalav)
mixture_is_basar_bechalav(m1). % Derived
Solving Phase¶
Clingo computes stable models (answer sets):
Answer Set 1:
food_type(chicken, basar)
food_type(chicken, maakhal)
food_type(milk, chalav)
food_type(milk, maakhal)
mixture(m1)
contains(m1, chicken)
contains(m1, milk)
mixture_contains_basar(m1)
mixture_contains_chalav(m1)
mixture_is_basar_bechalav(m1)
forbidden(base, achiila, m1, ctx_normal) ← DERIVED
Output Extraction¶
with ctl.solve(yield_=True) as handle:
for model in handle:
atoms = model.symbols(shown=True)
# Extract forbidden atoms
forbidden = [a for a in atoms if a.name == "forbidden"]
# → [forbidden(base, achiila, m1, ctx_normal)]
# Extract permitted atoms
permitted = [a for a in atoms if a.name == "permitted"]
# → []
# Extract safek atoms
safek = [a for a in atoms if a.name == "safek"]
# → []
3. Data Transformation Summary¶
HLL to AST¶
HLL Text → Python Dataclasses
───────────────────── ───────────────────
"basar(chicken)." → Fact(predicate="basar", args=["chicken"])
"forbidden(W,A,M,C):-" → Rule(head=Atom(...), body=[...])
"@world(base)" → ParseResult.world = "base"
AST to Normalized AST¶
Surface Syntax → Canonical Predicates
────────────────────── ────────────────────
basar(chicken) → food_type(chicken, basar)
issur(achiila, X) → forbidden(W, achiila, X, ctx_normal)
chalav(Y) → food_type(Y, chalav)
Normalized AST to ASP¶
Python Dataclasses → ASP Text
────────────────────── ─────────
Fact(food_type, [a,b]) → "food_type(a, b)."
Rule(head, body) → "head :- body."
ParseResult.sources → "makor(rule_id, source)."
ASP + Ontology to Answer Sets¶
ASP Facts + Rules → Derived Atoms
───────────────────── ────────────────────
food_type(chicken, of) → food_type(chicken, basar)
contains(m1, chicken) → mixture_contains_basar(m1)
contains(m1, milk) → mixture_is_basar_bechalav(m1)
mixture_is_basar... → forbidden(base, achiila, m1, ctx_normal)
4. Complete Example¶
Input HLL¶
@world(base)
@rule(r_example)
@makor([sa("YD:87:1")])
@madrega(d_oraita)
food(beef).
food_type(beef, beheima).
food(milk).
food_type(milk, chalav).
mixture(stew).
contains(stew, beef).
contains(stew, milk).
forbidden(W, achiila, M, ctx_normal) :-
world(W),
mixture(M),
mixture_is_basar_bechalav(M).
Compilation¶
Reasoning¶
import clingo
ctl = clingo.Control(["--warn=none"])
# Load ontology
ctl.load("mistaber/ontology/schema/sorts.lp")
ctl.load("mistaber/ontology/schema/disjointness.lp")
ctl.load("mistaber/ontology/base/substance.lp")
# Add compiled user program
ctl.add("user", [], asp_code)
# Ground
ctl.ground([("base", []), ("user", [])])
# Solve
results = []
with ctl.solve(yield_=True) as handle:
for model in handle:
results = [str(a) for a in model.symbols(shown=True)]
Output¶
# Derived atoms include:
"food_type(beef, beheima)"
"food_type(beef, basar)" # Inherited
"food_type(beef, maakhal)" # Inherited
"mixture_contains_basar(stew)"
"mixture_contains_chalav(stew)"
"mixture_is_basar_bechalav(stew)"
"forbidden(base, achiila, stew, ctx_normal)" # Final ruling
5. Error Flows¶
Parse Error Flow¶
Type Error Flow¶
Valid syntax, invalid semantics → TypeChecker → TypeCheckError → CompileError
↓
"Undeclared predicate: 'unknwon_pred'"
Unsatisfiable Flow¶
Contradictory facts → Clingo → UNSATISFIABLE → No answer sets
↓
food_type(X, basar) AND food_type(X, chalav) # Violates disjointness
6. Data Structures Reference¶
ParseResult¶
@dataclass
class ParseResult:
facts: List[Fact]
rules: List[Rule]
world: Optional[str]
rule_id: Optional[str]
sources: Optional[List[Tuple[str, str]]]
madrega: Optional[str]
TypeCheckError¶
@dataclass
class TypeCheckError:
message: str
severity: Literal["error", "warning"]
predicate: str = ""
line: int = 0
Clingo Symbols¶
# Clingo returns Symbol objects
symbol.name # "forbidden"
symbol.arguments # [Symbol("base"), Symbol("achiila"), ...]
str(symbol) # "forbidden(base,achiila,m1,ctx_normal)"
7. Performance Considerations¶
Grounding Size¶
The number of ground atoms grows with: - Number of declared entities (foods, vessels, mixtures) - Number of rules with variables - Depth of inheritance hierarchies
Solving Complexity¶
Answer set computation is NP-complete. Factors affecting performance: - Number of choice rules - Depth of negation - Size of search space after constraints
Optimization Tips¶
- Minimize variables: Use concrete values where possible
- Add constraints early: Disjointness rules prune the search space
- Use
#showdirectives: Limit output to relevant predicates - Ground incrementally: For large programs, ground in stages