Imports
Building integer branching trees
A specification contains the termination proof for every rounded child. The recurrence equation is stated independently, then strong induction identifies its solution with the cost of the generated finite tree.
namespace CLRSnamespace Chapter04open Finsetopen scoped BigOperatorsData needed to expand a natural-size recurrence into a finite tree.
structure IntegerBranchingSpec (Branch : Type) where
cutoff : Nat
childSize : Branch → Nat → Nat
localCost : Nat → Real
baseCost : Nat → Real
decreases : ∀ branch n, cutoff < n → childSize branch n < nnamespace IntegerBranchingSpecvariable {Branch : Type}The recurrence semantics, stated without referring to the generated tree.
structure Satisfies [Fintype Branch] (spec : IntegerBranchingSpec Branch)
(T : Nat → Real) : Prop where
base : ∀ n, n ≤ spec.cutoff → T n = spec.baseCost n
step : ∀ n, spec.cutoff < n →
T n = spec.localCost n + ∑ branch, T (spec.childSize branch n)Executably expand all children until their independently certified cutoff.
def build (spec : IntegerBranchingSpec Branch) (n : Nat) :
IntegerBranchingTree Branch :=
if _h : n ≤ spec.cutoff then
.leaf n (spec.baseCost n)
else
.node n (spec.localCost n) (fun branch => spec.build (spec.childSize branch n))
termination_by n
decreasing_by
exact spec.decreases _ _ (Nat.lt_of_not_ge _h)
@[simp] theorem build_of_le (spec : IntegerBranchingSpec Branch) (n : Nat)
(h : n ≤ spec.cutoff) :
spec.build n = .leaf n (spec.baseCost n) := by
rw [build]
simp [h]
@[simp] theorem build_of_lt (spec : IntegerBranchingSpec Branch) (n : Nat)
(h : spec.cutoff < n) :
spec.build n = .node n (spec.localCost n)
(fun branch => spec.build (spec.childSize branch n)) := by
rw [build]
simp [Nat.not_le_of_gt h]Building preserves the requested root subproblem size.
@[simp] theorem rootSize_build (spec : IntegerBranchingSpec Branch) (n : Nat) :
IntegerBranchingTree.rootSize (spec.build n) = n := by
by_cases h : n ≤ spec.cutoff
· simp [build_of_le spec n h]
· simp [build_of_lt spec n (Nat.lt_of_not_ge h)]Predicate saying that every leaf size satisfies a given property.
def EveryLeafSize (P : Nat → Prop) : IntegerBranchingTree Branch → Prop
| .leaf size _ => P size
| .node _ _ children => ∀ branch, EveryLeafSize P (children branch)Predicate saying that every internal-node size satisfies a property.
def EveryInternalSize (P : Nat → Prop) : IntegerBranchingTree Branch → Prop
| .leaf _ _ => True
| .node size _ children => P size ∧ ∀ branch, EveryInternalSize P (children branch)Every generated leaf is genuinely in the base-case range.
theorem build_everyLeaf_le (spec : IntegerBranchingSpec Branch) (n : Nat) :
EveryLeafSize (fun size => size ≤ spec.cutoff) (spec.build n) := by
induction n using Nat.strong_induction_on with
| h n ih =>
by_cases hbase : n ≤ spec.cutoff
· simp [EveryLeafSize, hbase]
· have hrec : spec.cutoff < n := Nat.lt_of_not_ge hbase
rw [build_of_lt spec n hrec]
simp only [EveryLeafSize]
intro branch
exact ih (spec.childSize branch n) (spec.decreases branch n hrec)Every generated internal node is genuinely above the cutoff.
theorem build_everyInternal_gt (spec : IntegerBranchingSpec Branch) (n : Nat) :
EveryInternalSize (fun size => spec.cutoff < size) (spec.build n) := by
induction n using Nat.strong_induction_on with
| h n ih =>
by_cases hbase : n ≤ spec.cutoff
· simp [build_of_le spec n hbase, EveryInternalSize]
· have hrec : spec.cutoff < n := Nat.lt_of_not_ge hbase
rw [build_of_lt spec n hrec]
simp only [EveryInternalSize]
refine ⟨hrec, fun branch => ?_⟩
exact ih (spec.childSize branch n) (spec.decreases branch n hrec)
Exact recurrence-tree semantics. This is not true by definition: T is
specified only by its base and recursive equations, independently of build.
theorem build_totalCost_eq [Fintype Branch] (spec : IntegerBranchingSpec Branch)
(T : Nat → Real) (hT : spec.Satisfies T) (n : Nat) :
IntegerBranchingTree.totalCost (spec.build n) = T n := by
induction n using Nat.strong_induction_on with
| h n ih =>
by_cases hbase : n ≤ spec.cutoff
· rw [build_of_le spec n hbase]
simp [hT.base n hbase]
· have hrec : spec.cutoff < n := Nat.lt_of_not_ge hbase
rw [build_of_lt spec n hrec]
simp only [IntegerBranchingTree.totalCost_node]
have hchildren : ∀ branch,
IntegerBranchingTree.totalCost
(spec.build (spec.childSize branch n)) =
T (spec.childSize branch n) := fun branch =>
ih (spec.childSize branch n) (spec.decreases branch n hrec)
simp_rw [hchildren]
exact (hT.step n hrec).symmend IntegerBranchingSpecend Chapter04end CLRS