Expand description
Finite-domain grounding.
A logic grid — and any finite, domain-closed problem — becomes DECIDABLE by expanding bounded quantifiers over the finite set of individuals named in the premises:
∀x. φ(x) over {a, b, c, d} → φ(a) ∧ φ(b) ∧ φ(c) ∧ φ(d)
∃x. φ(x) over {a, b, c, d} → φ(a) ∨ φ(b) ∨ φ(c) ∨ φ(d)The result is QUANTIFIER-FREE, so our kernel proves it (certified, explainable) and Z3 decides it in milliseconds — no e-matching, no search blowup, guaranteed to terminate. This is general and reusable: it knows nothing about any specific puzzle, only about quantifiers and the finite domain the premises declare.
Functions§
- at_
most_ one_ lemmas - “Exactly one φ” entails “at most one φ” — for every premise of the form
∃x(φ(x) ∧ ∀y(φ(y) → y = x))(whatCardinal(1)produces), emit the PAIRWISE uniqueness∀x∀y((φ(x) ∧ φ(y)) → x = y). - column_
closure_ lemmas - HIDDEN SINGLE — the COLUMN closure, dual of the row closure. Each
Exactly one φpremise (∃x(φ(x) ∧ ∀y(φ(y) → y = x)), e.g. “exactly one trip is in Florida”) entails that AT LEAST ONE row holds the value:⋁_{r∈dom} value(r). The row closure says a row takes SOME value; this says a value is taken by SOME row. Together with functionality (a row takes at most one value), it is the deduction a human calls a “hidden single” — once every other row is excluded from a value, the remaining row MUST hold it, and the EXISTING literal unit-propagation forces it. - definite_
property_ implications - “The unique D-trip has property P.” Each single-
∃definite-description clue∃x(D(x) ∧ … ∧ P(x))whose anchorDis a SINGLETON grid value (it carries anExactly one …premise, so the description denotes a unique row) entails the propagatable rule∀t(D(t) → P(t)); whenPis ALSO a singleton value the biconditional∀t(P(t) → D(t))too — e.g. “the Florida trip is the hunting trip” ⇒In(t,Florida) ↔ Hunt(t). Sound: a singleton value names a unique row, so any row holding it IS that row and therefore carries the clue’s property. This replaces the existential (whose sort-aware grounding still explodes to a row-disjunction) with row-indexed implications the incremental solver propagates. - discharge_
unary_ facts - Discharge known ground UNARY facts (
Trip(Alpha), …) throughout the premises: each is true, so replace it withTrueand simplifyTrue ∧ X ↦ X,True → X ↦ X. Unit propagation on the sort facts — it strips the sort guards out of every grounded clause ((Trip(x) ∧ In(x,FL)) ∧ … ↦ In(x,FL) ∧ …, and a closureTrip(t) → D ↦ Dbecomes a bare disjunction fact), leaving the pure value-literal clauses propagation runs on in ONE step. Sound: a true conjunct/antecedent carries no information. - domain_
constants - The DOMAIN of a problem: every constant named across
exprs. For a domain-closed finite problem this is the universe of individuals to ground over. - functionality_
lemmas - FUNCTIONALITY — the missing half of a grid’s bijection. Each closure
∀x(guard(x) → L1 ∨ L2 ∨ … ∨ Ln)says a row takes AT LEAST one value; this emits the AT MOST ONE companion∀x(Li → ¬Lj)for every ordered pair of distinct disjuncts. A trip is in exactly one state (one year, …), so a value assigned to a row EXCLUDES the row’s other values — the propagation that, together with value-uniqueness, determines the whole grid. Sound: for a square grid functionality is entailed by closure + value-uniqueness + counting, and it is in any case the inherent single-valuedness of the attribute. EachLimust be an atom mentioning the bound variable (a genuine closure), so unrelated∀→∨premises are skipped. - ground
- Ground every quantifier in
eoverdomain(Herbrand expansion): a universal becomes the conjunction of its instances, an existential the disjunction. The returned expression is quantifier-free whendomaincovers the universe. - ground_
problem - Ground a whole problem — premises AND goal — over the domain of constants they name. The returned premises and goal are quantifier-free (so the kernel proves them, certified, and Z3 decides them instantly).
- ground_
problem_ sorted ground_problembut sort-aware (each quantifier grounds over its guard sort). The default entry point for finite-domain solving.- ground_
sorted - SORT-AWARE grounding: a guarded quantifier expands only over its sort’s domain
(
∀x(Trip(x)→…)over the trips), falling back tofallback(the full universe) for an unsorted quantifier. Sound for a domain-closed problem and dramatically smaller than universe-grounding — the optimization the larger puzzles need. - simplify_
trivial_ identities - Fold away trivial (reflexive) identities and the boolean constants they create: a
grounded
∃x∃yof-pair has a DIAGONAL instance (x = y = c) carrying¬(c = c), which isFalse, so that disjunct must drop. Without it the solver would face an unsatisfiable disjunct it cannot refute (the kernel has no reflexivity rule to provec = c).Identity(c,c) ↦ True,¬True ↦ False, then∧/∨/→constant-fold. - sort_
domains - Per-sort domains: for each UNARY predicate used as a sort guard (
Trip,Year, …), the constants asserted to have it. Built from the ground facts the declarations produce (Trip(Alpha),Trip(Beta), …). This is what lets grounding expand∀x(Trip(x)→…)over the 4 trips, not the whole universe.