Occurrences of a formula with a first clause to Moving a walked name from \(D\) to \(E\)

TheoremOccurrences of a formula with a first clause#✓fully proved

Let \(C\) be a clause and \(\varphi\) a CNF formula, and write a literal occurrence as a pair \((i, \ell)\) of a clause index \(i\) and a literal \(\ell\). The list of literal occurrences of the formula whose first clause is \(C\) and whose remaining clauses are those of \(\varphi\) is the list of \((0, \ell)\) for the literals \(\ell\) of \(C\) in order, followed by the list of \((i + 1, \ell)\) for the occurrences \((i, \ell)\) of \(\varphi\) in order.

theorem occs_cons (C : CNFClause) (φ : CNF) :
    occs (C :: φ) = C.map (fun l => (0, l)) ++ (occs φ).map fun o => (o.1 + 1, o.2)
Uses 3 · Used by 3

DefinitionPolarity-first tokens of a literal#✓fully proved

For a literal \((x, p)\) with variable index \(x \in \mathbb{N}\) and polarity \(p\), the token list is the polarity marker symbol for \(p\) followed by one name-bit symbol for each bit of the canonical binary representation of \(x\) (least significant bit first, empty for \(x = 0\)), in order.

This is how the CLIQUE emitter writes a walked literal occurrence on its stack \(D\), top first.

def dTok (l : ℕ × Bool) : List Sym := .lit l.2 :: (encodeNat l.1).map .bit
Uses 1 · Used by 3

DefinitionTokens of an item on the walked stack#✓fully proved

An item of the stack \(D\) is either \(\mathrm{none}\), standing for a clause marker, or an occurrence \((x, p)\) of the variable \(x\) with polarity \(p\). The tokens of \(\mathrm{none}\) are the single clause-marker symbol; the tokens of \((x, p)\) are the polarity marker of \(p\) followed by the binary encoding of \(x\) as name-bit symbols.

def itemTok : Option (ℕ × Bool) → List Sym
  | none => [.cl]
  | some l => dTok l
Uses 2 · Used by 6

DefinitionBits pushed by a walk of the CLIQUE emitter#✓fully proved

Let \(l = (x, p)\) be a literal occurrence with name \(x \in \mathbb{N}\) and polarity \(p\), let \(f\) be a Boolean, and let \(ds\) be a list whose items are literal occurrences or clause markers. The bit list \(\mathrm{walkBits}(l, f, ds)\) is defined by recursion on \(ds\): it is empty if \(ds\) is empty; if \(ds\) is a clause marker followed by \(ds'\), it is \(\mathrm{walkBits}(l, \mathrm{true}, ds')\); and if \(ds\) is an occurrence \(l'\) followed by \(ds'\), it is the bit \(f \wedge \mathrm{adj}(l, l')\) followed by \(\mathrm{walkBits}(l, f, ds')\). Here \(\mathrm{adj}(l, l')\) is the Karp adjacency of literals: it is false exactly when \(l\) and \(l'\) have the same name and opposite polarities.

The flag \(f\) records whether a clause marker has been passed; while it is false, each occurrence contributes a false bit.

def walkBits (l : ℕ × Bool) : Bool → List (Option (ℕ × Bool)) → List Bool
  | _, [] => []
  | _, none :: ds => walkBits l true ds
  | f, some l' :: ds => (f && adjL l l') :: walkBits l f ds
Uses 1 · Used by 5

DefinitionWalked items of a formula#✓fully proved

For a CNF formula \(\varphi\) with clauses \(C_1, \dots, C_m\) in order, the items of \(\varphi\) are the list made of, for each \(i = 1, \dots, m\) in turn, the literals of \(C_i\) in order, each as an occurrence item, followed by one clause-marker item \(\mathrm{none}\). These are the items on the stack \(D\) once the clauses of \(\varphi\) are walked.

def items (φ : CNF) : List (Option (ℕ × Bool)) := φ.flatMap fun C => C.map some ++ [none]
Uses 2 · Used by 6

DefinitionRows pushed for a clause's literals#✓fully proved

For a list \(I\) of items and literals \(l_1, \dots, l_k\), the rows are the concatenation, for \(i = 1, \dots, k\) in turn, of the reverse of the walk bits of \(l_i\) with flag false over the items \(l_{i+1}, \dots, l_k\) (as occurrence items) followed by \(I\). These are the bits pushed when the literals of a clause are walked above the items \(I\).

def lrows (ds : List (Option (ℕ × Bool))) : List (ℕ × Bool) → List Bool
  | [] => []
  | l :: Ls => (walkBits l false (Ls.map some ++ ds)).reverse ++ lrows ds Ls
Uses 1 · Used by 6

DefinitionRow bits of a formula for the CLIQUE emitter#✓fully proved

A literal is a pair \((x, s)\) of a variable \(x \in \mathbb{N}\) and a polarity \(s\), and an item is a literal or a clause marker. For a literal \(\ell = (x, s)\), a Boolean \(f\) and a list of items, the walk bits are defined by recursion on the list: there are none for the empty list; for a list starting with a clause marker they are the walk bits of the rest with \(f\) replaced by true; for a list starting with a literal \((x', s')\) they are the bit "\(f\) and not (\(x = x'\) and \(s \ne s'\))" followed by the walk bits of the rest with the same \(f\). For a list \(\delta\) of items, the rows of a list of literals are none for the empty list, and for a list \(\ell_1, \dots, \ell_k\) with \(k \ge 1\) they are the reverse of the walk bits of \(\ell_1\) with \(f\) false over the list \(\ell_2, \dots, \ell_k\) followed by \(\delta\), then the rows of \(\ell_2, \dots, \ell_k\). The items of a CNF formula \(\psi\) are, for each clause of \(\psi\) in order, its literals followed by a clause marker. The row bits of a CNF formula are defined by recursion on its clauses: the empty formula has none, and for the formula with first clause \(C\) and remaining clauses \(\varphi\) they are the rows of the literals of \(C\) for \(\delta\) the clause marker followed by the items of \(\varphi\), followed by the row bits of \(\varphi\).

def rowsF : CNF → List Bool
  | [] => []
  | C :: φ => lrows (none :: items φ) C ++ rowsF φ
Uses 4 · Used by 3

TheoremPair bits of a leading clause#✓fully proved

Let \(C\) be a clause and \(\varphi\) a CNF formula. Let \(O_\varphi\) be the list of literal occurrences of \(\varphi\) (clause index, variable, polarity), with every clause index increased by \(1\). Then the row-by-row pair bits of the list made of the literals of \(C\), each with clause index \(0\), followed by \(O_\varphi\), are the rows pushed for the literals of \(C\) walked above a clause marker and the items of \(\varphi\), followed by the row-by-row pair bits of \(O_\varphi\).

theorem bitsRec_clause (C : CNFClause) (φ : CNF) :
    bitsRec (C.map (fun l => (0, l)) ++ (occs φ).map fun o => (o.1 + 1, o.2)) =
      lrows (none :: items φ) C ++ bitsRec ((occs φ).map fun o => (o.1 + 1, o.2))
Uses 10 · Used by 1

TheoremThe CLIQUE emitter's row bits are Karp's pair bits#✓fully proved

For every CNF formula \(\varphi\), the row bits of \(\varphi\) equal the pair bits of Karp's CLIQUE graph of \(\varphi\): with \(o_0, \dots, o_{m-1}\) the literal occurrences of \(\varphi\), these are, for the pairs \((i, j)\) with \(i < j < m\) in encoding order (rows \(i\) ascending, and \(j\) descending within a row), the bits telling whether \(o_i\) and \(o_j\) lie in different clauses and are not complementary.

theorem rowsF_eq (φ : CNF) : rowsF φ = cliqueBits φ
Uses 13 · Used by 1

InductiveStacks of the SAT-to-CLIQUE emitter#✓fully proved

The emitter has nine stacks: \(T\) (tokens), \(O\) (output), \(A\) (the current name), \(B\) (scratch), \(D\) (walked occurrences), \(E\) (the walk's other side), \(X\) (scratch), \(C\) (the clause count) and \(N\) (the occurrence count).

inductive K | T | O | A | B | D | E | X | C | N
  deriving DecidableEq
Used by 18

DefinitionStack alphabets of the CLIQUE emitter#✓fully proved

In the CLIQUE emitter, the output stack \(O\) has the Booleans as its alphabet, and every other stack has the token symbols as its alphabet.

The counter stacks \(C\) and \(N\) hold copies of the clause marker.

@[reducible] def Γ : K → Type
  | .O => Bool
  | _ => Sym
Uses 2 · Used by 17

InductiveLabels of the SAT-to-CLIQUE emitter#✓fully proved

For bits \(p, q, f, b\) the labels are \(\mathsf{start}\), \(\mathsf{lits}\), \(\mathsf{nm}(p)\), \(\mathsf{walk}(p, f)\), \(\mathsf{cmp}(p, q)\), \(\mathsf{res}(p, b)\), \(\mathsf{rsA}(p)\), \(\mathsf{rsD}(p)\), \(\mathsf{mvN}(p, f)\), \(\mathsf{back}(p)\), \(\mathsf{put}(p)\), \(\mathsf{put2}(p)\), \(\mathsf{put3}(p)\), \(\mathsf{fin}\), \(\mathsf{finN}\), \(\mathsf{fin2}\), \(\mathsf{finC}\) and \(\mathsf{done}\). Here \(p\) is the polarity of the current occurrence. \(\mathsf{start}\) begins a clause and \(\mathsf{lits}\) pops a literal marker; \(\mathsf{nm}\) moves its name to \(A\); \(\mathsf{walk}(p, f)\) walks \(D\), where \(f\) tells whether a clause marker was passed; \(\mathsf{cmp}(p, q)\), \(\mathsf{res}\), \(\mathsf{rsA}\) and \(\mathsf{rsD}\) compare with an occurrence of polarity \(q\), push the bit \(b\) and restore; \(\mathsf{mvN}\) moves that occurrence's name to \(E\); \(\mathsf{back}\) moves \(E\) back to \(D\); \(\mathsf{put}\), \(\mathsf{put2}\) and \(\mathsf{put3}\) put the current occurrence on \(D\); \(\mathsf{fin}\) to \(\mathsf{finC}\) push the instance prefix, and \(\mathsf{done}\) halts.

inductive Lab
  | start | lits | nm (p : Bool) | walk (p f : Bool) | cmp (p q : Bool) | res (p b : Bool)
  | rsA (p : Bool) | rsD (p : Bool) | mvN (p f : Bool) | back (p : Bool) | put (p : Bool)
  | put2 (p : Bool) | put3 (p : Bool) | fin | finN | fin2 | finC | done
  deriving DecidableEq
Used by 16

DefinitionThe CLIQUE emitter machine#✓fully proved

The CLIQUE emitter is the multi-stack machine with stacks \(T, O, A, B, D, E, X, C, N\), a Boolean flag and the labels named below. The stack \(O\) holds Booleans and the others hold symbols, among them the bit symbols \(\mathrm{bit}(b)\), the literal symbols \(\mathrm{lit}(p)\) and the clause marker \(\mathrm{cl}\). Each test sets the flag to its outcome, a pop that reads a polarity or a bit sets the flag to it, and other pops leave the flag unchanged. To move the bits of \(Y\) to \(Z\) and then go to \(\lambda\) means: while the top of \(Y\) is a bit symbol, pop it and push it onto \(Z\); once \(Y\) is empty or its top is another symbol, go to \(\lambda\) (the flag serves as scratch). The instruction at each label is as follows.

At \(\mathrm{start}\): test whether \(T\) is empty; if so go to \(\mathrm{fin}\), else pop \(T\), push \(\mathrm{cl}\) onto \(D\) and onto \(C\), and go to \(\mathrm{lits}\). At \(\mathrm{lits}\): test whether the top of \(T\) is a literal symbol; if so pop it, reading the polarity \(q\) (true exactly for \(\mathrm{lit}(\mathrm{true})\)), push \(\mathrm{cl}\) onto \(N\) and go to \(\mathrm{nm}(q)\); else go to \(\mathrm{start}\). At \(\mathrm{nm}(p)\): move the bits of \(T\) to \(A\), then go to \(\mathrm{walk}(p, \mathrm{false})\). At \(\mathrm{walk}(p, f)\): test whether \(D\) is empty; if so go to \(\mathrm{back}(p)\); else test whether the top of \(D\) is \(\mathrm{cl}\); if so pop it, push \(\mathrm{cl}\) onto \(E\) and go to \(\mathrm{walk}(p, \mathrm{true})\); else pop \(D\), reading \(q\) (true exactly for \(\mathrm{lit}(\mathrm{true})\)), push \(\mathrm{lit}(q)\) onto \(E\), and if \(f\) go to \(\mathrm{cmp}(p, q)\), else push false onto \(O\) and go to \(\mathrm{mvN}(p, \mathrm{false})\). At \(\mathrm{cmp}(p, q)\): compare the bits of \(A\) and \(D\), that is, while both tops are bit symbols of the same bit, pop both and push that bit symbol onto \(X\) and onto \(B\); when both bit blocks end together go to \(\mathrm{res}(p, b)\) with \(b\) true exactly when \(p = q\), and on a mismatch (different bits, or one block ending first) go to \(\mathrm{res}(p, \mathrm{true})\) without popping (the flag serves as scratch). At \(\mathrm{res}(p, b)\): push \(b\) onto \(O\) and go to \(\mathrm{rsA}(p)\). At \(\mathrm{rsA}(p)\): move the bits of \(X\) to \(A\), then go to \(\mathrm{rsD}(p)\). At \(\mathrm{rsD}(p)\): move the bits of \(B\) to \(D\), then go to \(\mathrm{mvN}(p, \mathrm{true})\). At \(\mathrm{mvN}(p, f)\): move the bits of \(D\) to \(E\), then go to \(\mathrm{walk}(p, f)\). At \(\mathrm{back}(p)\): test whether \(E\) is empty; if so go to \(\mathrm{put}(p)\); else test whether its top is \(\mathrm{cl}\); if so pop it and push \(\mathrm{cl}\) onto \(D\); else test whether its top is a literal symbol; if so pop it, reading \(q\) (true exactly for \(\mathrm{lit}(\mathrm{true})\)), and push \(\mathrm{lit}(q)\) onto \(D\); else pop it, reading \(b\) (true exactly for \(\mathrm{bit}(\mathrm{true})\)), and push \(\mathrm{bit}(b)\) onto \(D\); in these three cases stay at \(\mathrm{back}(p)\). At \(\mathrm{put}(p)\): move the bits of \(A\) to \(B\), then go to \(\mathrm{put2}(p)\). At \(\mathrm{put2}(p)\): move the bits of \(B\) to \(D\), then go to \(\mathrm{put3}(p)\). At \(\mathrm{put3}(p)\): push \(\mathrm{lit}(p)\) onto \(D\) and go to \(\mathrm{lits}\). At \(\mathrm{fin}\): push false onto \(O\) and go to \(\mathrm{finN}\). At \(\mathrm{finN}\): pop \(N\), testing whether a symbol was popped; if so push true onto \(O\) and stay, else go to \(\mathrm{fin2}\). At \(\mathrm{fin2}\): push false onto \(O\) and go to \(\mathrm{finC}\). At \(\mathrm{finC}\): pop \(C\), testing whether a symbol was popped; if so push true onto \(O\) and stay, else go to \(\mathrm{done}\). At \(\mathrm{done}\): halt.

Cslib.Complexity.Karp.EmitClique.prog · 37 lines
def prog : Lab → TM2.Stmt Γ Lab Bool
  | .start => .peek .T (fun _ o => o.isNone) <| .branch id (.goto fun _ => .fin) <|
      .pop .T (fun s _ => s) <| .push .D (fun _ => Sym.cl) <| .push .C (fun _ => Sym.cl) <|
        .goto fun _ => .lits
  | .lits => .peek .T (fun _ o => Emit3.isLit o) <| .branch id
      (.pop .T (fun _ o => o == some (.lit true)) <| .push .N (fun _ => Sym.cl) <|
        .goto fun s => .nm s)
      (.goto fun _ => .start)
  | .nm p => moveB .T .A Sym.bit? Sym.bit (.nm p) (.walk p false)
  | .walk p f => .peek .D (fun _ o => o.isNone) <| .branch id (.goto fun _ => .back p) <|
      .peek .D (fun _ o => o == some .cl) <| .branch id
        (.pop .D (fun s _ => s) <| .push .E (fun _ => Sym.cl) <| .goto fun _ => .walk p true)
        (.pop .D (fun _ o => o == some (.lit true)) <| .push .E (fun s => Sym.lit s) <|
          if f then .goto fun s => .cmp p s
          else .push .O (fun _ => false) <| .goto fun _ => .mvN p false)
  | .cmp p q => cmpB .A .D .X .B Sym.bit? Sym.bit? Sym.bit Sym.bit (.cmp p q) (.res p (p == q))
      (.res p true)
  | .res p b => .push .O (fun _ => b) <| .goto fun _ => .rsA p
  | .rsA p => moveB .X .A Sym.bit? Sym.bit (.rsA p) (.rsD p)
  | .rsD p => moveB .B .D Sym.bit? Sym.bit (.rsD p) (.mvN p true)
  | .mvN p f => moveB .D .E Sym.bit? Sym.bit (.mvN p f) (.walk p f)
  | .back p => .peek .E (fun _ o => o.isNone) <| .branch id (.goto fun _ => .put p) <|
      .peek .E (fun _ o => o == some .cl) <| .branch id
        (.pop .E (fun s _ => s) <| .push .D (fun _ => Sym.cl) <| .goto fun _ => .back p) <|
      .peek .E (fun _ o => Emit3.isLit o) <| .branch id
        (.pop .E (fun _ o => o == some (.lit true)) <| .push .D (fun s => Sym.lit s) <|
          .goto fun _ => .back p)
        (.pop .E (fun _ o => o == some (.bit true)) <| .push .D (fun s => Sym.bit s) <|
          .goto fun _ => .back p)
  | .put p => moveB .A .B Sym.bit? Sym.bit (.put p) (.put2 p)
  | .put2 p => moveB .B .D Sym.bit? Sym.bit (.put2 p) (.put3 p)
  | .put3 p => .push .D (fun _ => Sym.lit p) <| .goto fun _ => .lits
  | .fin => .push .O (fun _ => false) <| .goto fun _ => .finN
  | .finN => xferE .N .O [true] .finN .fin2
  | .fin2 => .push .O (fun _ => false) <| .goto fun _ => .finC
  | .finC => xferE .C .O [true] .finC .done
  | .done => .halt
Uses 10 · Used by 13

DefinitionStart label of the CLIQUE emitter#✓fully proved

The start label of the CLIQUE emitter machine is its label \(\mathsf{start}\).

def start : Lab := .start
Uses 1 · Used by 2

DefinitionConfiguration stacks of the CLIQUE emitter#✓fully proved

For a token stack \(t\), an output stack \(o\) of bits, stacks \(a\), \(d\), \(e\) of token symbols and natural numbers \(c\) and \(n\), this assigns to each stack of the CLIQUE emitter its contents: the token stack \(T\) holds \(t\), the output stack \(O\) holds \(o\), the name stack \(A\) holds \(a\), the walked-occurrence stack \(D\) holds \(d\), the walk's other stack \(E\) holds \(e\), the clause counter \(C\) holds \(c\) copies of the clause marker, the occurrence counter \(N\) holds \(n\) copies of the clause marker, and the scratch stacks \(B\) and \(X\) are empty.

def st (t : List Sym) (o : List Bool) (a d e : List Sym) (c n : ℕ) : ∀ k, List (Γ k)
  | .T => t
  | .O => o
  | .A => a
  | .B => []
  | .D => d
  | .E => e
  | .X => []
  | .C => cnt Sym.cl c
  | .N => cnt Sym.cl n
Uses 4 · Used by 13

TheoremCLIQUE emitter: recognizing a standard state#✓fully proved

Let \(S\) assign contents to the stacks of the CLIQUE emitter and let \(c, n \in \mathbb{N}\). If the scratch stacks \(B\) and \(X\) are empty and the counters \(C\) and \(N\) hold exactly \(c\) and \(n\) clause markers, then \(S\) is the standard state whose stacks \(T\), \(O\), \(A\), \(D\), \(E\) hold what they hold in \(S\), whose stacks \(B\) and \(X\) are empty and whose counters \(C\) and \(N\) hold \(c\) and \(n\) clause markers.

theorem st_eq {S : ∀ k, List (Γ k)} {c n : ℕ} (hB : S .B = []) (hX : S .X = [])
    (hC : S .C = cnt Sym.cl c) (hN : S .N = cnt Sym.cl n) :
    S = st (S .T) (S .O) (S .A) (S .D) (S .E) c n
Uses 5

DefinitionTokens moved by the walk#✓fully proved

A symbol is a token of the walk between the stacks \(D\) and \(E\) when it is a name bit, a literal marker or a clause marker; the value symbols and the dead symbol are not.

def isTok : Sym → Bool
  | .bit _ | .lit _ | .cl => true
  | _ => false
Uses 1 · Used by 2

AbbreviationName bits of a variable in the CLIQUE emitter#✓fully proved

For \(x \in \mathbb{N}\), the name of \(x\) is the list of symbols obtained from the binary encoding of \(x\) (least significant bit first, empty for \(x = 0\)) by writing each bit \(b\) as the bit symbol \(\mathrm{bit}(b)\). This is the form in which the stacks \(A\) and \(D\) of the CLIQUE emitter hold variable names.

abbrev name (x : ℕ) : List Sym := (encodeNat x).map Sym.bit
Uses 1 · Used by 3

TheoremCLIQUE emitter: reading a variable name#✓fully proved

Stacks are listed top first. Let \(p\) be a Boolean, \(x \in \mathbb{N}\) with name \(w\) (its binary encoding written as bit symbols) of length \(\ell\), and \(R\) a list of symbols that is empty or whose top symbol is not a bit symbol. Let \(v\) be a flag, \(o\) a list of Booleans, \(d\) and \(e\) lists of symbols, and \(c, n \in \mathbb{N}\). Started at label \(\mathrm{nm}(p)\) with flag \(v\), the token stack \(T\) holding \(w\) reversed on top of \(R\), empty stacks \(A\), \(B\), \(X\), stacks \(O\), \(D\), \(E\) holding \(o\), \(d\), \(e\), and \(c\) and \(n\) clause markers on the counters \(C\) and \(N\), the CLIQUE emitter reaches, in exactly \(\ell + 1\) steps and with some flag, the label \(\mathrm{walk}(p, \mathrm{false})\) with \(T\) holding \(R\), \(A\) holding \(w\), and all other stacks as before.

theorem nm_run (p : Bool) (x : ℕ) (R : List Sym) (hR : R.head?.bind Sym.bit? = none) :
    ∃ v', Run prog ((encodeNat x).length + 1)
      ⟨some (.nm p), v, st ((name x).reverse ++ R) o [] d e c n⟩
      ⟨some (.walk p false), v', st R o (name x) d e c n⟩
Uses 12 · Used by 1

TheoremMoving a walked name from \(D\) to \(E\)#✓fully proved

Write \(\langle \ell, v \mid t, o, a, d, e, c, n\rangle\) for the configuration of the SAT-to-CLIQUE emitter at label \(\ell\) with local bit \(v\), stacks \(T = t\), \(O = o\), \(A = a\), \(D = d\), \(E = e\), empty scratch stacks \(B\) and \(X\), and \(c\) and \(n\) marks on the counters \(C\) and \(N\); juxtaposition of lists is concatenation. Let \(p, f\) be bits, \(w\) a list of bits with \(\bar w\) the corresponding list of name-bit symbols, \(R\) a list of symbols that is empty or does not start with a name-bit symbol, and \(t, o, a, e, c, n, v\) arbitrary. Then for some bit \(v'\) the machine goes in exactly \(|w| + 1\) steps from \(\langle \mathsf{mvN}(p, f), v \mid t, o, a, \bar w R, e, c, n\rangle\) to \(\langle \mathsf{walk}(p, f), v' \mid t, o, a, R, \bar w^{\mathrm{rev}} e, c, n\rangle\), where \(\bar w^{\mathrm{rev}}\) is the reverse of \(\bar w\).

theorem mvN_run (p f : Bool) (w : List Bool) (R : List Sym) (hR : R.head?.bind Sym.bit? = none) :
    ∃ v', Run prog (w.length + 1) ⟨some (.mvN p f), v, st t o a (w.map Sym.bit ++ R) e c n⟩
      ⟨some (.walk p f), v', st t o a R ((w.map Sym.bit).reverse ++ e) c n⟩
Uses 11 · Used by 1
20 fully proved

The dependency explorer needs JavaScript and its graph data.

Download the complete graph data.