feat(adr-0249): P3 structural formula→CNF converter (deduction leg) #68
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/adr-0249-p3-cnf-converter"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Third phase of the reader→Hamiltonian compiler arc. P1 (quantity kernel) and P2 (relation compiler) closed the arithmetic leg; this closes the deduction leg — both readers can now reach the corridor.
What it does
evals/logic_cnf_compiler.py— turns propositional formula strings (as emitted bygenerate.meaning_graph.to_deductive_logic, or anylogic_canonical-parseable syntax) into the corridor's CNFPropositionalProblem+ a queryClause, consumable by the ratifiedpropositional_entails.compile_entailment(premises, query)is the entry point;formula_to_clauses/query_to_clause/clauses_to_formulaare the pieces.Structural, not truth-table (spike §4.1)
The survey confirmed there is no
to_cnfanywhere in the tree, and thatlogic_canonical's recursive-descent parser is the one production grammar. So the converter reuses that parser for the AST (never re-implements it), then applies the standard sound rewrite itself: eliminateiff/implies→ push negations to literals (NNF) → distribute OR over AND, with constant folding, tautological-clause elimination, and a clause budget. It never enumerates assignments and never decides entailment — that stays the corridor's job.Soundness is proved, not asserted
For a 14-formula panel, the compiled CNF is rendered back to a formula and checked to have the same ROBDD identity as the source via the ratified
canonicalizeoracle (canonicalize(formula).canonical_key == canonicalize(clauses_to_formula(cnf)).canonical_key). Iff, De Morgan, nested implications, tautologies (P or not P→true) all preserved.End-to-end agreement, wrong=0
Compiling
premises ⊨ queryand running it throughpropositional_entailsmatches the ROBDD gold (evaluate_entailment) on consistent premises. One honest subtlety, handled explicitly: on inconsistent premises the ROBDD path returnsREFUSED, while the corridor returnsentailed=Truewithsatisfiable_premises=False(classical ex-falso). Those are different framings of the same fact, so ex-falso is pinned against the corridor's own contract, not cross-checked against the ROBDD path.Fail-closed + governance
Typed
CnfCompileErroron conjunctive/constant queries, formulas reducing tofalse, and CNF-budget overflow;>5atoms surfaces the corridor'sHamiltonianCompileError(atom_count_out_of_range)— the honest ≤5-atom boundary; out-of-regime (quantifiers/predicates) propagatesLogicRegimeError. Off-serving (A-04): imports the serving-side parser for its grammar only, lives in the eval quarantine, import-guard pinned. Lives inevals/because it bridges the generate-side parser to the corridor types (P1/P2 sat incore/physics/since they needed neither).Tests
tests/test_adr_0249_logic_cnf_compiler.py— 32/32 green. Soundness panel (14 formulas), entailment agreement (7 consistent cases), modus ponens, ex-falso disclosure, clause shape + determinism, five refusal classes, serve-wiring guard.[Verification]:
uv run python -m pytest tests/test_adr_0249_logic_cnf_compiler.py -q→ 32 passed;uv run core test --suite smoke -q→ 176 passed.