Counting sparsification -- branching rules and depth-first tree search #
A counting branching rule (CountingBranchingRule) is the counting-sparsification analogue of
BranchingRule (Complexity/Logics/Propositional/ClauseSet/Sparsification/Tree.lean): a
deterministic step next : σ → Bool → σ on states σ representing clause sets via toClauseSet,
which at every state that is not sparse takes the heart (false) or petal-plus-negated-heart-units
(true) child (ClauseSet.Sparsification.countingChild) for some valid choice Choice θ.
When all thresholds for j ≥ 1 are at least 2 (in particular for countingThreshold M with
M ≥ 2), every non-sparse step strictly decreases the clause-set potential
potential ψ = ∑ C ∈ ψ, 2 ^ C.card (potential_countingChild_lt from CountingTree.lean,
CountingBranchingRule.potential_next_lt): removing a flower of |F| ≥ 2 clauses of width c
decreases the potential by |F| · 2 ^ c, while adding the |F| petals of width c - |H| ≤ c - 1
and |H| ≤ c - 1 unit clauses adds at most |F| · 2 ^ (c - 1) + 2 (c - 1) < |F| · 2 ^ c.
Furthermore, because reduce eliminates every clause of the flower F on both branches, each
step increases the total clause count by at most K (card_countingChild_le,
CountingBranchingRule.IsNodeWord.card_walk_le).
A depth-first search of the counting branching tree (CountingBranchingRule.searchStep) keeps a
stack of states and a cap-bounded ℕ accumulator. Started from (s :: rest, acc), after N
steps (with N + 1 ≤ 2 * W.card for the finset W of leaf words of s) the stack is back to
rest and the accumulator records min cap (acc + ∑ w ∈ W, f (R.walk s w))
(CountingBranchingRule.exists_iterate_searchStep). When f is additive across non-sparse
branches (in particular when f computes modelCountOn declared at the leaves), the leaf sum
equals the root value (CountingBranchingRule.sum_leafWords_eq,
CountingBranchingRule.sum_leafWords_modelCountOn).
At the list level, Cslib.Logic.PL.CNF.Sparsification.countingRule instantiates
CountingBranchingRule on {ψ : CNF V // CountingNormalized k ψ} using countingNext θ k.
Main definitions #
Cslib.Logic.PL.ClauseSet.Sparsification.CountingBranchingRule: a deterministic counting-sparsification branching rule.Cslib.Logic.PL.ClauseSet.Sparsification.CountingBranchingRule.walk,.IsNodeWord,.IsLeafWord: nodes and leaves of the counting branching tree.Cslib.Logic.PL.ClauseSet.Sparsification.CountingBranchingRule.searchStep: one step of the depth-first counting search with a cappedℕaccumulator.Cslib.Logic.PL.CNF.Sparsification.countingRule: the list-level counting branching rule on{ψ : CNF V // CountingNormalized k ψ}.
Main results #
Cslib.Logic.PL.ClauseSet.Sparsification.CountingBranchingRule.potential_next_lt: strict potential decrease on both counting branches when∀ j, 1 ≤ j → 2 ≤ θ j.Cslib.Logic.PL.ClauseSet.Sparsification.card_countingChild_le,Cslib.Logic.PL.ClauseSet.Sparsification.CountingBranchingRule.IsNodeWord.card_walk_le: each counting step increases the number of clauses by at most the widthK.Cslib.Logic.PL.ClauseSet.Sparsification.CountingBranchingRule.exists_iterate_searchStep: depth-first counting search visits every leaf within2 * W.cardsteps with stack height at mosth + 1and accumulator bounded bymax acc cap.Cslib.Logic.PL.ClauseSet.Sparsification.CountingBranchingRule.sum_leafWords_modelCountOn: the sum ofmodelCountOn declaredover all leaf words equals the rootmodelCountOn declared.
References #
- OpenAI, The Exponential Time Hypothesis is False, Section 6.4, Proposition 6.4 (pp. 43–44) and Appendix A (pp. 44–47).
Clause-set properties of countingChild #
The flower flower ψ c H is disjoint from both counting children countingChild ψ c H b:
on false every flower clause strictly contains H, and on true every flower clause C
strictly contains its petal C \ H.
Counting children keep the clause width ≤ k when 1 ≤ k.
Each counting child increases the number of clauses by at most k: the flower F is removed
from ψ while at most |F| + |H| ≤ |F| + k clauses are added.
Counting branching rules #
A counting branching rule for the thresholds θ: a deterministic step next on states σ,
each representing the clause set toClauseSet s, which at every state that is not sparse takes the
heart (false) or petal + negated-heart-units (true) child countingChild for one valid choice.
- toClauseSet : σ → ClauseSet V
The clause set a state represents.
- next : σ → Bool → σ
The heart (
false) or petal + negated-heart-units (true) child of a state. - exists_choice_next (s : σ) : ¬Sparse θ (self.toClauseSet s) → ∃ (c : ℕ) (H : Finset (Literal V)), Choice θ (self.toClauseSet s) c H ∧ ∀ (b : Bool), self.toClauseSet (self.next s b) = countingChild (self.toClauseSet s) c H b
At a state that is not sparse, both children are taken for one valid choice.
Instances For
The state reached along a word of branches.
Instances For
A node word: its proper prefixes reach states that are not sparse.
Instances For
A leaf word: its proper prefixes reach states that are not sparse and it reaches a sparse state.
Instances For
One step of the depth-first counting search of the branching tree, on a stack of states and a
cap-bounded ℕ accumulator: a sparse state on top is popped and f s is added to the
accumulator (capped at cap); any other state on top is replaced by its false and true
counting children.
Instances For
Termination. When ∀ j, 1 ≤ j → 2 ≤ θ j, each counting branching step strictly decreases
the potential.
Additive model-count conservation. At any non-sparse state, the declared-variable model count equals the sum of the model counts of its two children.
Every leaf word is a node word.
Walking along a leaf word reaches a sparse clause set.
Every state has a leaf word when ∀ j, 1 ≤ j → 2 ≤ θ j.
Node words preserve clause width ≤ k when 1 ≤ k.
Along a node word w from a state of width ≤ k (1 ≤ k), the number of clauses increases by
at most k * w.length.
Node words preserve declared-variable support containment.
Depth-first counting search. Started from a state s above rest with accumulator
acc ≤ cap, the search takes N steps (N + 1 ≤ 2 * W.card for the finset W of all leaf words
of s) to return to rest, with accumulator min cap (acc + ∑ w ∈ W, f (R.walk s w)). If all
leaf words of s have length at most h, the stack above rest has height at most h + 1 at
every intermediate step i ≤ N and the accumulator remains at most cap.
If M : σ → ℕ is additive across non-sparse steps
(M t = M (R.next t false) + M (R.next t true)) and f agrees with M on the leaves of s, then
the sum of f (R.walk s w) over any finset W containing exactly the leaf words of s equals
M s.
Leaf model-count partition. If f computes (R.toClauseSet ·).toCNF.modelCountOn declared
on every leaf of s, then the sum of f (R.walk s w) over the leaf words of s equals
(R.toClauseSet s).toCNF.modelCountOn declared.
For 2 ≤ M and 1 ≤ j, 2 ≤ countingThreshold M j.
The list-level counting branching rule, on formulas in nontautological normal form
(CountingNormalized k): uses countingNext θ k.
Instances For
Walking along countingRule preserves variable support containment for any word w.
List-level leaf model-count partition. If f computes CNF.modelCountOn · declared on
every leaf of s under countingRule, then the sum of f over the leaf words of s equals
s.1.modelCountOn declared.