
After studying this material, you should be able to:
A rule engine is a system that:
Input Variables (complete) → Rule Engine → Output Category
Real-world examples:
| Domain | Input Variables | Output Categories |
|---|---|---|
| Tax liability | income, deductions, filing status | tax bracket, amount owed |
| Travel reimbursement | distance, purpose, employee grade | approved/denied/partial |
| Benefit eligibility | age, income, residency | eligible/ineligible/conditional |
| Building code | floor area, occupancy type, materials | compliant/non-compliant |
Rule engines were designed assuming complete inputs
This works perfectly when a computer fills out every field. But humans don't think this way.
Instead of:
"I am 67 years old, earn $34,000/year, have lived in France for 12 years, and have 2 dependents — am I eligible?"
Humans ask:
"Are retired people eligible for this benefit?" "What happens if someone earns under $40,000?"
A region is a subset of the input space where some variables are specified and others are left open (under-specified).
Full Input Space = all possible combinations of all variables
Region = {
age: "retired" (specified),
income: ??? (unspecified),
residency: ??? (unspecified),
dependents: ??? (unspecified)
}
Visually:
┌─────────────────────────────────────┐
│ Full Input Space │
│ │
│ ┌─────────────────┐ │
│ │ Region │ │
│ │ (age=retired, │ │
│ │ others open) │ │
│ └─────────────────┘ │
│ │
└─────────────────────────────────────┘
Key insight: The question defines a region, not a single point.
An LLM reads the rules and tries to answer in natural language.
What it does well:
Critical failure:
❌ No completeness guarantee
The LLM might say:
"Retired people are generally eligible if they meet income requirements."
But it may miss edge cases, misread rule interactions, or hallucinate conditions.
As the decision space grows (more variables, more rules), the gap between what the LLM says and what is actually true widens.
Reliability
│
100%│ ──── Symbolic (always complete)
│
│ LLM
50%│ ─────────────────────────────
│ ↘ (degrades)
│
0%└────────────────────────────────→
Decision Space Complexity
A symbolic system explores every possible execution path through the rule engine.
What it does well:
Critical failure:
❌ Partition explosion — too large to summarize faithfully
Imagine a rule with 10 binary variables:
Presenting all paths to a user is useless — it's overwhelming and incomprehensible.
User asks: "Are retired people eligible?"
Symbolic system returns:
Path 1: age≥65 ∧ income<20000 ∧ residency>10 ∧ dependents=0 → ELIGIBLE
Path 2: age≥65 ∧ income<20000 ∧ residency>10 ∧ dependents=1 → ELIGIBLE
Path 3: age≥65 ∧ income<20000 ∧ residency>10 ∧ dependents=2 → ELIGIBLE
... (1,000+ more paths)
This is complete but not useful.
Combine the completeness of symbolic enumeration with the communicability of language models, using a budget-controlled follow-up question strategy.
The method has three key components:
┌──────────────────────────────────────────────────────┐
│ NEUROSYMBOLIC SYSTEM │
│ │
│ [LLM Agent] ←→ [Symbolic Enumerator] ←→ [SMT] │
│ │
│ • Lifts question • Enumerates paths • Verifies │
│ to a region • Partitions space completeness│
│ • Verbalizes • Finds best │
│ answer follow-up │
└──────────────────────────────────────────────────────┘
The LLM translates a natural language question into a formal region.
Natural Language: Formal Region:
"Are retired people?" → { age: ≥65, income: *, residency: *, ... }
The * means "unspecified" — this is what makes it a region rather than a point.
The system runs the rule engine symbolically over the entire region, finding all execution paths.
Concolic execution = concrete + symbolic execution
Region: { age: ≥65, others: * }
Partition:
Sub-region A: age≥65 ∧ income<30000 → ELIGIBLE
Sub-region B: age≥65 ∧ income≥30000 ∧ residency>5 → ELIGIBLE
Sub-region C: age≥65 ∧ income≥30000 ∧ residency≤5 → INELIGIBLE
SMT = Satisfiability Modulo Theories — a formal logic solver.
The system reconstructs the rule engine's path constraints in the SMT solver to verify:
✅ The partition is complete — every point in the region falls into exactly one sub-region
This is a checked theorem, not a claim. The difference matters:
| Type | Meaning |
|---|---|
| Claim | "We believe the enumeration is complete" |
| Checked theorem | "The SMT solver has formally verified completeness" |
When the partition is too large to present usefully, the system asks the single best follow-up question.
How to find the best question:
The goal is to find the variable that removes the most cases (maximizes information gain):
Partition has 500 sub-regions
Question: "What is the person's income level?"
→ If income < $30,000: reduces to 50 sub-regions
→ If income ≥ $30,000: reduces to 450 sub-regions
→ Average reduction: significant ✓
Question: "Does the person have a middle name?"
→ Irrelevant to rules
→ No reduction ✗
The system picks the question with the maximum reduction in partition size.
This creates a natural conversation:
User: "Are retired people eligible?"
System: "Are they earning under $30,000/year?"
User: "Yes."
System: "They are eligible if they have lived here for more than 5 years,
otherwise they must apply for an exception. [Cite: Article 12, §3]"
USER QUESTION
│
▼
┌─────────────────────┐
│ LLM Agent │
│ "Question Lifting" │
│ Natural language │
│ → Formal region │
└─────────┬───────────┘
│ Region specification
▼
┌─────────────────────┐
│ CUTECat Engine │
│ (Concolic executor │
│ for Catala) │
│ Enumerates all │
│ paths in region │
└─────────┬───────────┘
│ Raw partition
▼
┌─────────────────────┐
│ SMT Solver │
│ Verifies partition │
│ is complete │
│ (checked theorem) │
└─────────┬───────────┘
│ Verified partition
▼
┌─────────────────────┐
│ Budget Controller │
│ Is partition small │
│ enough to present? │
└──────┬──────────────┘
│
┌──────────┴──────────┐
│ YES │ NO
▼ ▼
┌─────────────┐ ┌──────────────────────┐
│ LLM Agent │ │ Find best follow-up │
│ Verbalizes │ │ question (max cases │
│ answer with │ │ removed) │
│ citations │ └──────────┬───────────┘
└─────────────┘ │
▼
Ask user → loop back
Catala is a domain-specific programming language designed specifically for encoding legal rules as executable code.
Why Catala?
Example (conceptual):
# Article 12 - Benefit Eligibility
scope BenefitEligibility:
rule eligible under condition
applicant.age >= 65
and applicant.income < income_threshold
consequence fulfilled
CUTECat is Catala's concolic execution engine:
The system was tested on:
Results:
| Metric | One-shot LLM | This System |
|---|---|---|
| Complete partitions | ❌ No guarantee | ✅ Proven complete |
| Citations to source | Sometimes | Always |
| Uses unmodified engine | No | Yes |
| Handles regional questions | Partially | Fully |
| Concept | Definition | Why It Matters |
|---|---|---|
| Rule Engine | Maps complete inputs to output categories | The system being retrofitted |
| Region | Subset of input space with some variables unspecified | How humans actually ask questions |
| Partition | Complete division of a region into sub-regions with definite answers | The complete answer to a regional question |
| Concolic Execution | Concrete + symbolic execution to find all paths | How completeness is achieved |
| SMT Solver | Formal logic solver that verifies constraints | How completeness is proven |
| Budget | Maximum partition size before asking follow-up | Keeps answers usable |
| Question Lifting | Translating natural language to a formal region | LLM's key role |
| Neurosymbolic | Combining neural (LLM) and symbolic (logic) methods | The hybrid approach |
Traditional Rule Engine:
Complete input required → Single answer
Chatbot with LLM only:
Partial input accepted → Possibly wrong/incomplete answer
This System:
Partial input accepted → Provably complete answer
(with follow-up questions if needed)
The fundamental insight:
A question is not a point — it is a region. Treating it as a region allows us to give answers that are both complete (symbolic guarantee) and comprehensible (LLM verbalization).