Documentation

Complexitylib.Circuits.NormalForm.Defs

Normal Forms — Core Definitions #

This module defines Conjunctive Normal Form (CNF) and Disjunctive Normal Form (DNF) Boolean formulas over N variables, together with their evaluation semantics, complexity measures, and De Morgan negation duality.

Main definitions #

Relation to Complexity.SAT #

Complexity.Literal, Complexity.CNF, and Complexity.DNF are deliberately distinct from Complexity.SAT.Lit and Complexity.SAT.CNF. The types here are Fin-indexed over a fixed variable count N and are used for circuit lower bounds, whereas the SAT versions are Nat-indexed and serve as the language encoding for SAT.

structure Complexity.Literal (N : ) :

A literal: a Boolean variable (by index) together with a polarity flag.

polarity = true represents the positive literal xᵢ; polarity = false represents the negative literal ¬xᵢ.

  • var : Fin N

    The index of the Boolean variable this literal refers to.

  • polarity : Bool

    true = positive literal (xᵢ); false = negative literal (¬xᵢ).

Instances For
    @[implicit_reducible]
    instance Complexity.instReprLiteral {N✝ : } :
    Repr (Literal N✝)
    Equations
    Equations
    • One or more equations did not get rendered due to their size.
    Instances For
      def Complexity.instDecidableEqLiteral.decEq {N✝ : } (x✝ x✝¹ : Literal N✝) :
      Decidable (x✝ = x✝¹)
      Equations
      Instances For
        def Complexity.Literal.eval {N : } (l : Literal N) (x : BitString N) :

        Evaluate a literal on a bit assignment.

        Equations
        Instances For

          Negate a literal by flipping its polarity.

          Equations
          Instances For
            @[simp]
            theorem Complexity.Literal.neg_neg {N : } (literal : Literal N) :
            literal.neg.neg = literal

            Literal negation is an involution.

            theorem Complexity.Literal.eval_neg {N : } (l : Literal N) (x : BitString N) :
            l.neg.eval x = !l.eval x

            Negating a literal negates its evaluation.

            def Complexity.Literal.vars {N : } (literals : List (Literal N)) :

            The set of variables occurring in a list of literals.

            Equations
            Instances For
              @[simp]
              theorem Complexity.Literal.vars_cons {N : } (literal : Literal N) (literals : List (Literal N)) :
              vars (literal :: literals) = insert literal.var (vars literals)
              theorem Complexity.Literal.mem_vars_iff {N : } (literals : List (Literal N)) (index : Fin N) :
              index vars literals literalliterals, literal.var = index

              CNF #

              structure Complexity.CNF (N : ) :

              A CNF (Conjunctive Normal Form) formula over N Boolean variables.

              A CNF is a conjunction of clauses, where each clause is a disjunction of literals.

              • clauses : List (List (Literal N))

                The clauses of the formula. Each clause is a list of literals.

              Instances For
                @[implicit_reducible]
                instance Complexity.instReprCNF {N✝ : } :
                Repr (CNF N✝)
                Equations
                def Complexity.instReprCNF.repr {N✝ : } :
                CNF N✝Std.Format
                Equations
                • One or more equations did not get rendered due to their size.
                Instances For
                  def Complexity.instDecidableEqCNF.decEq {N✝ : } (x✝ x✝¹ : CNF N✝) :
                  Decidable (x✝ = x✝¹)
                  Equations
                  Instances For
                    def Complexity.CNF.eval {N : } (φ : CNF N) (x : BitString N) :

                    A CNF formula evaluates to true iff every clause contains at least one satisfied literal.

                    Equations
                    Instances For
                      def Complexity.CNF.complexity {N : } (φ : CNF N) :

                      The complexity of a CNF formula is its number of clauses.

                      Equations
                      Instances For
                        def Complexity.CNF.width {N : } (φ : CNF N) :

                        The width of a CNF is the maximum number of literals in any clause.

                        Equations
                        Instances For
                          theorem Complexity.CNF.length_le_width {N : } (φ : CNF N) (clause : List (Literal N)) (hclause : clause φ.clauses) :
                          clause.length φ.width

                          Every clause length is bounded by the declared CNF width.

                          theorem Complexity.CNF.width_le_iff {N : } (φ : CNF N) (bound : ) :
                          φ.width bound clauseφ.clauses, clause.length bound

                          A natural number bounds CNF width exactly when it bounds every clause length.

                          def Complexity.CNF.vars {N : } (φ : CNF N) :

                          The set of variables occurring in a CNF.

                          Equations
                          Instances For
                            @[simp]
                            theorem Complexity.CNF.vars_nil {N : } :
                            { clauses := [] }.vars =
                            @[simp]
                            theorem Complexity.CNF.vars_cons {N : } (clause : List (Literal N)) (clauses : List (List (Literal N))) :
                            { clauses := clause :: clauses }.vars = Literal.vars clause { clauses := clauses }.vars
                            theorem Complexity.CNF.mem_vars_iff {N : } (φ : CNF N) (index : Fin N) :
                            index φ.vars clauseφ.clauses, literalclause, literal.var = index

                            DNF #

                            structure Complexity.DNF (N : ) :

                            A DNF (Disjunctive Normal Form) formula over N Boolean variables.

                            A DNF is a disjunction of terms, where each term is a conjunction of literals.

                            • terms : List (List (Literal N))

                              The terms of the formula. Each term is a list of literals.

                            Instances For
                              @[implicit_reducible]
                              instance Complexity.instReprDNF {N✝ : } :
                              Repr (DNF N✝)
                              Equations
                              def Complexity.instDecidableEqDNF.decEq {N✝ : } (x✝ x✝¹ : DNF N✝) :
                              Decidable (x✝ = x✝¹)
                              Equations
                              Instances For
                                def Complexity.DNF.eval {N : } (φ : DNF N) (x : BitString N) :

                                A DNF formula evaluates to true iff at least one term has all its literals satisfied.

                                Equations
                                Instances For
                                  def Complexity.DNF.complexity {N : } (φ : DNF N) :

                                  The complexity of a DNF formula is its number of terms.

                                  Equations
                                  Instances For
                                    def Complexity.DNF.width {N : } (φ : DNF N) :

                                    The width of a DNF is the maximum number of literals in any term.

                                    Equations
                                    Instances For
                                      theorem Complexity.DNF.length_le_width {N : } (φ : DNF N) (term : List (Literal N)) (hterm : term φ.terms) :
                                      term.length φ.width

                                      Every term length is bounded by the declared DNF width.

                                      theorem Complexity.DNF.width_le_iff {N : } (φ : DNF N) (bound : ) :
                                      φ.width bound termφ.terms, term.length bound

                                      A natural number bounds DNF width exactly when it bounds every term length.

                                      def Complexity.DNF.vars {N : } (φ : DNF N) :

                                      The set of variables occurring in a DNF.

                                      Equations
                                      Instances For
                                        @[simp]
                                        theorem Complexity.DNF.vars_nil {N : } :
                                        { terms := [] }.vars =
                                        @[simp]
                                        theorem Complexity.DNF.vars_cons {N : } (term : List (Literal N)) (terms : List (List (Literal N))) :
                                        { terms := term :: terms }.vars = Literal.vars term { terms := terms }.vars
                                        theorem Complexity.DNF.mem_vars_iff {N : } (φ : DNF N) (index : Fin N) :
                                        index φ.vars termφ.terms, literalterm, literal.var = index

                                        De Morgan Negation Duality #

                                        def Complexity.CNF.neg {N : } (φ : CNF N) :
                                        DNF N

                                        Negate a CNF formula by flipping all literal polarities, producing a DNF. By De Morgan's laws, ¬(∧ᵢ ∨ⱼ lᵢⱼ) = ∨ᵢ ∧ⱼ ¬lᵢⱼ.

                                        Equations
                                        Instances For
                                          def Complexity.DNF.neg {N : } (φ : DNF N) :
                                          CNF N

                                          Negate a DNF formula by flipping all literal polarities, producing a CNF. By De Morgan's laws, ¬(∨ᵢ ∧ⱼ lᵢⱼ) = ∧ᵢ ∨ⱼ ¬lᵢⱼ.

                                          Equations
                                          Instances For
                                            @[simp]
                                            theorem Complexity.CNF.neg_neg {N : } (φ : CNF N) :
                                            φ.neg.neg = φ

                                            De Morgan negation from CNF to DNF and back is an involution.

                                            @[simp]
                                            theorem Complexity.DNF.neg_neg {N : } (φ : DNF N) :
                                            φ.neg.neg = φ

                                            De Morgan negation from DNF to CNF and back is an involution.

                                            theorem Complexity.CNF.eval_neg {N : } (φ : CNF N) (x : BitString N) :
                                            φ.neg.eval x = !φ.eval x

                                            Negating a CNF formula negates its evaluation (De Morgan duality).

                                            theorem Complexity.DNF.eval_neg {N : } (φ : DNF N) (x : BitString N) :
                                            φ.neg.eval x = !φ.eval x

                                            Negating a DNF formula negates its evaluation (De Morgan duality).

                                            theorem Complexity.CNF.vars_neg {N : } (φ : CNF N) :
                                            φ.neg.vars = φ.vars

                                            Negating a CNF preserves its variable support.

                                            theorem Complexity.DNF.vars_neg {N : } (φ : DNF N) :
                                            φ.neg.vars = φ.vars

                                            Negating a DNF preserves its variable support.

                                            Negating a CNF preserves complexity.

                                            Negating a DNF preserves complexity.

                                            theorem Complexity.CNF.width_neg {N : } (φ : CNF N) :

                                            Negating a CNF preserves width.

                                            theorem Complexity.DNF.width_neg {N : } (φ : DNF N) :

                                            Negating a DNF preserves width.