Documentation

Complexitylib.SAT.Semantics

SAT: Semantic Layer #

This file contains the mathematical definition of Boolean satisfiability. No Turing machines are used here. Everything is pure recursion on inductive types; a reader can audit these definitions in a few minutes and check that they really capture "α satisfies φ".

All later claims about the SAT verifier are stated against the predicates defined here. If this file is wrong, nothing downstream rescues us.

Definitions #

Out-of-range convention #

A variable index i ≥ α.length is treated as assigned to false. This is standard in SAT textbooks ("unassigned variables default to 0") and makes the language closed under padding: a short satisfying assignment always exists, equal to a prefix of any longer one. This is essential for polynomial balance in the NP reduction.

A literal: sign = true means the positive literal x_var; sign = false means ¬x_var.

  • sign : Bool

    Polarity of the literal: true for x_var, false for ¬x_var.

  • var :

    Index of the variable this literal mentions.

Instances For
    def Complexity.SAT.instDecidableEqLit.decEq (x✝ x✝¹ : Lit) :
    Decidable (x✝ = x✝¹)
    Equations
    Instances For
      @[reducible, inline]

      A clause is a disjunction of literals. The empty clause is unsatisfiable (an empty disjunction is false).

      Equations
      Instances For
        @[reducible, inline]

        A CNF formula is a conjunction of clauses. The empty CNF is satisfiable (an empty conjunction is true).

        Equations
        Instances For
          @[reducible, inline]

          An assignment is a bit-string. Position i holds the value of variable i. Indices past the end read as false.

          Equations
          Instances For
            @[inline]

            Value of variable i under assignment α, with out-of-range = false.

            Equations
            Instances For
              @[inline]

              ℓ = (s, v) is satisfied by α iff α.get v = s.

              Equations
              Instances For
                @[inline]

                A clause is satisfied iff at least one literal is.

                Equations
                Instances For
                  @[inline]

                  A CNF is satisfied iff every clause is.

                  Equations
                  Instances For

                    φ is satisfiable if some assignment makes CNF.eval true.

                    Equations
                    Instances For
                      @[simp]

                      The empty CNF evaluates to true (empty conjunction).

                      @[simp]
                      theorem Complexity.SAT.CNF.eval_cons (α : Assignment) (c : Clause) (φ : CNF) :
                      eval α (c :: φ) = (Clause.eval α c && eval α φ)

                      Evaluating c :: φ is the conjunction of evaluating c and evaluating φ.

                      The empty formula is trivially satisfiable.

                      The formula [[]] (one empty clause) is unsatisfiable.

                      @[inline]

                      Largest variable index appearing in a literal (just ℓ.var).

                      Equations
                      Instances For

                        Largest variable index in a clause (0 if empty).

                        Equations
                        Instances For
                          @[simp]

                          The empty clause has maxVar = 0.

                          @[simp]
                          theorem Complexity.SAT.Clause.maxVar_cons ( : Lit) (ℓs : Clause) :
                          maxVar ( :: ℓs) = max .var ℓs.maxVar

                          maxVar of ℓ :: ℓs is the max of ℓ.var and maxVar ℓs.

                          theorem Complexity.SAT.Clause.var_le_maxVar { : Lit} {c : Clause} (hℓ : c) :
                          .var c.maxVar

                          Every literal's var in a clause is at most c.maxVar.

                          Largest variable index in a CNF (0 if empty).

                          Equations
                          Instances For
                            @[simp]

                            The empty CNF has maxVar = 0.

                            @[simp]
                            theorem Complexity.SAT.CNF.maxVar_cons (c : Clause) (cs : CNF) :
                            maxVar (c :: cs) = max c.maxVar cs.maxVar

                            maxVar of c :: cs is the max of c.maxVar and maxVar cs.

                            Every clause's maxVar is at most φ.maxVar.

                            theorem Complexity.SAT.Assignment.get_append_left (α β : Assignment) (i : ) (h : i < List.length α) :
                            (α ++ β).get i = α.get i

                            Assignment.get on α ++ β agrees with α at in-range indices.

                            theorem Complexity.SAT.Lit.eval_append_of_lt (α β : Assignment) ( : Lit) (h : .var < List.length α) :
                            eval (α ++ β) = eval α

                            Appending to an assignment doesn't change Lit.eval for in-range literals.

                            theorem Complexity.SAT.Assignment.get_take (α : Assignment) (i k : ) (hi : i < k) :
                            get (List.take k α) i = α.get i

                            α.get i is preserved by truncating to any length k > i.

                            theorem Complexity.SAT.Lit.eval_take (α : Assignment) ( : Lit) (k : ) (hk : .var < k) :
                            eval (List.take k α) = eval α

                            Lit.eval is invariant under truncation when the literal's var is in range.

                            theorem Complexity.SAT.Clause.eval_take (α : Assignment) (c : Clause) (k : ) (hk : c.maxVar < k) :
                            eval (List.take k α) c = eval α c

                            Clause.eval is preserved by truncation of α to length above c.maxVar.

                            theorem Complexity.SAT.CNF.eval_take (α : Assignment) (φ : CNF) (k : ) (hk : φ.maxVar < k) :
                            eval (List.take k α) φ = eval α φ

                            CNF.eval is preserved by truncation of α to length above φ.maxVar.

                            PolyBalanced witness lemma. A satisfiable formula has a satisfying assignment of length at most φ.maxVar + 1.

                            theorem Complexity.SAT.Lit.eval_eq_of_agree (α β : Assignment) ( : Lit) (h : α.get .var = β.get .var) :
                            eval α = eval β

                            If two assignments give the same value at every index (via Assignment.get), they produce the same literal evaluation.

                            theorem Complexity.SAT.Clause.eval_eq_of_agree (α β : Assignment) (c : Clause) (h : ∀ (i : ), α.get i = β.get i) :
                            eval α c = eval β c

                            Pointwise agreement of Assignment.get implies equal Clause.eval.

                            theorem Complexity.SAT.CNF.eval_eq_of_agree (α β : Assignment) (φ : CNF) (h : ∀ (i : ), α.get i = β.get i) :
                            eval α φ = eval β φ

                            Pointwise agreement of Assignment.get implies equal CNF.eval.

                            Appending falses doesn't change Assignment.get: out-of-range positions default to false anyway.

                            Padding an assignment with falses doesn't change CNF.eval.

                            @[implicit_reducible]

                            Brute-force decidability. Satisfiability is decidable by enumerating all 2^(φ.maxVar + 1) assignments of length φ.maxVar + 1. Not poly-time, but establishes that the semantic layer is concretely computable and enables decide on small instances.

                            Equations
                            @[simp]
                            theorem Complexity.SAT.Clause.eval_append (α : Assignment) (c d : Clause) :
                            eval α (c ++ d) = (eval α c || eval α d)

                            Evaluating a concatenation of clauses is the disjunction of the evaluations.

                            @[simp]
                            theorem Complexity.SAT.CNF.eval_append (α : Assignment) (φ ψ : CNF) :
                            eval α (φ ++ ψ) = (eval α φ && eval α ψ)

                            Evaluating a concatenation of CNFs is the conjunction of the evaluations.