Predicate Selection¶
Predicates are the fundamental building blocks of Mistaber encodings. Choosing the correct predicate ensures type safety, semantic clarity, and compatibility with the reasoning engine. This document explains predicate naming conventions, the registry reference, arity guidelines, and when to create new predicates.
Predicate Naming Conventions¶
General Naming Rules¶
| Rule | Example | Rationale |
|---|---|---|
| All lowercase | food_type |
ASP convention |
| Underscores for separation | is_beheima_chalav_mixture |
Readability |
| Descriptive names | mixture_has_basar |
Self-documenting |
| No abbreviations (usually) | permitted not perm |
Clarity |
| Hebrew terms when appropriate | achiila, chalav |
Domain accuracy |
Rule ID Naming¶
Rule identifiers use the r_ prefix:
% CORRECT - descriptive, topic-based
r_bb_beheima_achiila % basar bechalav beheima eating
r_bb_of_bishul_mutar % basar bechalav of cooking permitted
r_bb_dag_sakana % fish danger in bb laws
r_rema_dag_chalav_mutar % Rema's fish+dairy permission
% WRONG - opaque, location-based
r_87_1 % What is this?
r_rule_001 % Meaningless
r_yd87s3 % Cryptic
Category Naming¶
| Category | Prefix/Pattern | Example |
|---|---|---|
| Sort membership | is_X |
is_food, is_mixture |
| Classification | X_type |
food_type, kli_status |
| Relationships | contains, has_X |
contains, has_issur |
| Actions | verb form | achiila, bishul |
| Status | issur, heter |
issur(achiila, X, madrega) |
Existing Predicate Registry Reference¶
Core Sort Predicates¶
| Predicate | Arity | Signature | CWA | Description |
|---|---|---|---|---|
food |
1 | [food] | Yes | Entity is food |
mixture |
1 | [mixture] | Yes | Entity is mixture |
vessel |
1 | [vessel] | Yes | Entity is vessel |
world |
1 | [world] | Yes | Valid world identifier |
rule |
1 | [rule_id] | Yes | Valid rule identifier |
Food Classification¶
| Predicate | Arity | Signature | CWA | Description |
|---|---|---|---|---|
food_type |
2 | [food, food_category] | Yes | Food's category |
basar_type |
1 | [category] | Yes | Subcategory of basar |
is_basar_type |
1 | [category] | No | Helper predicate |
Mixture Predicates¶
| Predicate | Arity | Signature | CWA | Description |
|---|---|---|---|---|
contains |
2 | [mixture, food] | Yes | Mixture contains food |
mixture_has_basar |
2 | [mixture, basar_type] | No | Derived: has meat type |
mixture_has_chalav |
1 | [mixture] | No | Derived: has dairy |
is_beheima_chalav_mixture |
1 | [mixture] | No | Derived: beheima+dairy |
is_of_chalav_mixture |
1 | [mixture] | No | Derived: poultry+dairy |
is_dag_chalav_mixture |
1 | [mixture] | No | Derived: fish+dairy |
Normative Predicates¶
| Predicate | Arity | Signature | CWA | Description |
|---|---|---|---|---|
issur |
3 | [action, food, madrega] | No | Prohibition with level |
heter |
2 | [action, food] | No | Permission |
sakana |
1 | [food] | No | Health danger |
no_sakana |
1 | [food] | No | No health danger |
forbidden |
4 | [world, action, food, context] | No | Full prohibition |
permitted |
4 | [world, action, food, context] | No | Full permission |
Attribution Predicates¶
| Predicate | Arity | Signature | CWA | Description |
|---|---|---|---|---|
makor |
2 | [rule_id, source_ref] | Yes | Source citation |
madrega |
2 | [rule_id, madrega_type] | Yes | Obligation level |
scope |
2 | [rule_id, world] | Yes | World scope |
World Structure¶
| Predicate | Arity | Signature | CWA | Description |
|---|---|---|---|---|
accessible |
2 | [world, world] | Yes | Parent relationship |
asserts |
2 | [world, proposition] | Yes | World asserts proposition |
holds |
2 | [proposition, world] | No | Proposition holds in world |
override |
3 | [world, prop, value] | Yes | World overrides proposition |
overridden |
2 | [proposition, world] | No | Proposition is overridden |
Enumerated Values¶
action_type: achiila, bishul, hanaah, melicha, kavush, netila
food_category: basar, chalav, parve, beheima, chaya, of, dag, mashkeh, tavlin
madrega_type: d_oraita, d_rabanan, minhag, chumra
context: ctx_normal, ctx_hefsed, ctx_shaat_hadchak, ctx_choleh, ctx_pikuach_nefesh
When to Create New Predicates¶
Decision Tree¶
graph TD
A[Need to express something] --> B{Existing predicate?}
B -->|Yes| C[Use existing predicate]
B -->|No| D{Related predicate exists?}
D -->|Yes| E{Can extend existing?}
D -->|No| F{Is it domain-specific?}
E -->|Yes| G[Create helper predicate]
E -->|No| H[Create new predicate]
F -->|Yes| H
F -->|No| I[Consider if needed]
H --> J[Document in PR]
G --> J
Valid Reasons to Create New Predicates¶
- New domain concept not covered by existing predicates
- Helper predicate for complex derived conditions
- Specific mixture type detection (pattern:
is_X_Y_mixture) - New action type (must be added to enum)
Invalid Reasons to Create New Predicates¶
- Synonym of existing - use existing predicate
- Slightly different arity - consider if existing works
- Convenience only - helpers should serve multiple rules
- Personal preference - follow established patterns
Predicate Arity Guidelines¶
Arity 1 (Unary)¶
Use for sort membership and simple properties:
% Sort membership
food(chicken).
mixture(m1).
vessel(pot1).
% Simple properties
sakana(M).
no_sakana(M).
Arity 2 (Binary)¶
Use for classifications, relationships, and simple assertions:
% Classifications
food_type(chicken, of).
kli_status(pot1, kli_rishon).
% Relationships
contains(m1, chicken).
accessible(ashk_mb, rema).
% Assertions
makor(r_example, sa("yd:87:1")).
madrega(r_example, d_oraita).
Arity 3 (Ternary)¶
Use for actions with context or propositions with conditions:
% Action with level
issur(achiila, M, d_oraita).
issur(bishul, M, d_rabanan).
% Override with value
override(rema, sakana(M), no_sakana).
Arity 4 (Quaternary)¶
Use for full normative determinations:
% Full prohibition structure
forbidden(world, action_type, food, context).
forbidden(mechaber, achiila, M, ctx_normal).
% Full permission structure
permitted(world, action_type, food, context).
permitted(rema, achiila, M, ctx_normal).
Arity Guidelines Summary¶
| Arity | Use Case | Example |
|---|---|---|
| 1 | Membership, simple property | food(X), sakana(M) |
| 2 | Classification, binary relation | food_type(X, Y), contains(M, F) |
| 3 | Action + qualifier, override | issur(A, F, M), override(W, P, V) |
| 4 | Full determination with context | forbidden(W, A, F, C) |
| 5+ | Rarely needed, consider decomposition | Avoid if possible |
Type Constraints¶
Sort Compatibility¶
Every predicate argument must match its declared sort:
% food_type/2 has signature [food, food_category]
% CORRECT - arguments match sorts
food_type(chicken, of). % chicken: food, of: food_category
food_type(milk, chalav). % milk: food, chalav: food_category
% WRONG - sort mismatch
food_type(pot1, basar). % pot1 is vessel, not food!
food_type(chicken, d_oraita). % d_oraita is madrega, not food_category!
Checking Sort Compatibility¶
Before using a predicate:
- Check the predicate registry for signature
- Verify each argument matches its declared sort
- Ensure enum values are from correct enumeration
% Registry shows: issur/3 = [action_type, food, madrega_type]
% Verify each argument:
% - achiila: action_type enum? YES
% - M: mixture/food? YES (mixture is subtype)
% - d_oraita: madrega_type enum? YES
issur(achiila, M, d_oraita). % Valid!
CWA vs OWA Predicates¶
CWA (Closed World Assumption): If not stated, it's false.
% CWA predicates - absence = false
food(chicken). % chicken is food
% beef is NOT food (not declared)
OWA (Open World Assumption): Absence doesn't imply falsity.
% OWA predicates - absence = unknown
permitted(W, A, F, C). % derived, not directly stated
forbidden(W, A, F, C). % derived, not directly stated
Negating OWA Predicates
Negating open-world predicates is unsafe and generates a warning:
Creating New Predicates¶
Step 1: Verify Necessity¶
- [ ] No existing predicate serves this purpose
- [ ] Cannot compose from existing predicates
- [ ] Will be used by multiple rules (not one-off)
- [ ] Has clear semantic meaning
Step 2: Design the Predicate¶
# Proposed predicate documentation
- name: is_X_Y_mixture
arity: 1
signature: [mixture]
hebrew: "תערובת X עם Y"
english: "Mixture containing X and Y"
cwa: false
derived: true
note: "Derived predicate for detecting X+Y combinations"
Step 3: Implement with Documentation¶
% ============================================================
% NEW PREDICATE: is_X_Y_mixture/1
% ============================================================
% Purpose: Detects mixtures containing both X and Y
% Signature: [mixture] -> boolean
% CWA: false (derived)
%
% Usage:
% is_X_Y_mixture(M) :- mixture(M), contains(M, X_item), contains(M, Y_item).
%
% Added: 2026-01-25
% Change: Record the PR/reference that introduced this predicate.
% ============================================================
is_X_Y_mixture(M) :-
mixture(M),
contains(M, F1),
food(F1),
food_type(F1, x_category),
contains(M, F2),
food(F2),
food_type(F2, y_category),
F1 != F2.
Step 4: Add Tests¶
def test_new_predicate_positive():
"""New predicate correctly detects X+Y mixture."""
result = query("""
mixture(m1).
food(x_item). food_type(x_item, x_category).
food(y_item). food_type(y_item, y_category).
contains(m1, x_item). contains(m1, y_item).
""")
assert result.holds("is_X_Y_mixture(m1)")
def test_new_predicate_negative():
"""New predicate does not fire for non-matching mixtures."""
result = query("""
mixture(m1).
food(x_item). food_type(x_item, x_category).
food(z_item). food_type(z_item, z_category). # Not Y!
contains(m1, x_item). contains(m1, z_item).
""")
assert not result.holds("is_X_Y_mixture(m1)")
Step 5: Document in PR¶
Include in PR description:
## New Predicate: is_X_Y_mixture/1
**Purpose**: Detects mixtures containing both X and Y categories.
**Signature**: `is_X_Y_mixture(mixture)`
**Justification**: Needed for YD XX:Y rules that apply specifically
to X+Y combinations. No existing predicate captures this.
**Usage Example**:
```prolog
asserts(mechaber, issur(achiila, M, d_rabanan)) :-
is_X_Y_mixture(M).
Tests Added: 2 positive, 2 negative cases
## Common Predicate Mistakes
### Mistake 1: Wrong Arity
```prolog
% WRONG - issur takes 3 arguments
issur(M). % Missing action and madrega
issur(achiila, M). % Missing madrega
% CORRECT
issur(achiila, M, d_rabanan).
Mistake 2: Wrong Sort¶
% WRONG - food_type second arg must be food_category
food_type(chicken, animal). % 'animal' not in food_category enum
% CORRECT - use valid food_category
food_type(chicken, of). % 'of' is valid food_category
Mistake 3: Using String Instead of Atom¶
% WRONG - quoted string where atom expected
food_type("chicken", of). % "chicken" is string
% CORRECT - unquoted atom
food_type(chicken, of). % chicken is atom
Mistake 4: Creating Duplicate Predicate¶
% WRONG - creating synonym of food_type
food_category(chicken, of). % This already exists as food_type!
% CORRECT - use existing predicate
food_type(chicken, of).
Mistake 5: Over-Engineering New Predicates¶
% WRONG - overly specific predicate for one rule
is_chicken_in_pot_with_milk_on_fire(M).
% CORRECT - composable predicates
is_of_chalav_mixture(M).
in_vessel(M, V).
on_heat_source(V).
Predicate Selection Checklist¶
Before using a predicate:
- [ ] Checked predicate registry for existence
- [ ] Verified arity matches usage
- [ ] Confirmed sort compatibility for each argument
- [ ] Used enum values from correct enumeration
- [ ] Avoided negating OWA predicates
- [ ] Used existing predicates before creating new ones
Before creating new predicate:
- [ ] Verified no existing predicate serves purpose
- [ ] Documented predicate specification
- [ ] Added comprehensive tests
- [ ] Included in PR documentation
Related Guidelines¶
- Predicate Registry - Complete predicate documentation
- HLL Language Reference - Full language specification
- Encoding Methodology - Complete encoding process
- Testing Requirements - Test coverage requirements