Propositional logic¶
Boolean connectives, normal forms, exact two-level minimisation, reduced
ordered binary decision diagrams (ROBDDs) and equivalence checking. Atoms are
Boolean symbols; the transformations that hold under any interpretation of
their atoms (to_nnf(), to_cnf(), to_dnf(),
simplify_logic()) also accept arithmetic relations such as
pool.gt(x, 0) as opaque atoms. Refusals raise LogicError
(E-LOGIC-002 … E-LOGIC-006); an active alkahest.Budget is honoured
everywhere (BudgetExceededError).
Connectives¶
- alkahest.Or(*args) Expr¶
n-ary conjunction / disjunction. Nested arguments of the same kind are flattened, the identity (
True/False) is dropped, the absorbing constant or a complementary pairx, Not(x)collapses the result, duplicates are removed, and the arguments are put in a canonical order, soAnd(c, And(b, a)) == And(a, b, c). Python bools are accepted alongside expressions; at least oneExpris required (it names the pool).
Normal forms and minimisation¶
- alkahest.to_dnf(expr, simplify=False) Expr¶
Normal forms by distribution (contradictory/tautological, duplicate and absorbed terms dropped). Exponential in the worst case and refused past 100 000 terms (
E-LOGIC-003).simplify=Truereturns the minimum form ofsimplify_logic()instead.
- alkahest.simplify_logic(expr, form='auto', dontcare=None, exact=None) Expr¶
Two-level minimisation:
formis"dnf","cnf"or"auto"(the one with fewer literals).dontcareis a formula marking assignments whose value is free. Up to 12 variables (16 withexact=True) the result is a proven minimum — fewest terms, then fewest literals — from Quine–McCluskey prime implicants and a branch-and-bound Petrick cover. Beyond that, an espresso-style expand/irredundant pass on the BDD of the function returns an equivalent cover that is not guaranteed minimum (exact=Truerefuses withE-LOGIC-004instead). Every result is checked against the input before it is returned.Example:
p = ExprPool(); a, b = p.symbol("a"), p.symbol("b") simplify_logic(Or(And(a, b), And(a, Not(b)))) # a
- alkahest.minimize_logic(expr, form='dnf', dontcare=None, exact=None) MinimizedLogic¶
As
simplify_logic(), returning aMinimizedLogicwithexpr,form,exact(minimality proven),termsandliterals.
Decision diagrams¶
- alkahest.bdd(expr, order=None, max_nodes=None) BDD¶
The ROBDD of a formula over Boolean symbols.
order(symbols or names, root first) fixes the variable order; unlisted symbols are appended. The default order is depth-first first-visit over the canonical formula, which interleaves the operand bits of bit-sliced arithmetic. A BDD pastmax_nodes(default 2 000 000) is refused withE-LOGIC-003— the middle output bit of ann-bit multiplier is exponential under every order, so this is a real limit, not a formality.
- class alkahest.BDD¶
&,|,^,~;implies,iff,ite(g, h);restrict({x: True});exists([x])/forall([x]);sat_count(variables=None)(exactint; by default over every variable of the BDD’s manager);node_count();support();order;satisfy_one();equivalent(other);to_expr(). Operands from separatebdd()calls (or plainExprformulas) are merged by variable name.
Equivalence and truth tables¶
- alkahest.equivalent(f, g, method='auto', counterexample=False) bool¶
method:"truth_table"(≤ 22 variables),"bdd","sat"(DPLL on the miterf ⊕ g), or"auto"(truth table up to 16 variables, then a bounded BDD, then SAT).counterexample=Truereturns(verdict, assignment_or_None). With relations present aTrueverdict is still a proof, but a propositional difference is refused (E-LOGIC-002):x > 0andNot(x <= 0)are propositionally independent and equal over ℝ.
- alkahest.truth_table(expr, variables=None) list[tuple[tuple[bool, ...], bool]]¶
Rows from all-
Falseto all-True, the last variable varying fastest;variables=Nonesorts the symbols by name.
satisfiable() decides any purely propositional formula, including ones
wider than 64 symbols or with heavily shared sub-formulas (parity chains,
carry chains), on the formula’s DAG.