Imports
Counted bottom-up rod cutting
The outer loop computes its preceding array once. The inner loop reads that stored array once per candidate, retaining its running maximum. Counters record candidate evaluations and appended table entries in that same execution. Array access, price lookup, and natural-number operations are primitive events; their implementation internals and persistent-array copying are not counted.
namespace CLRS.Chapter15.RodExecutionstructure Scan where
value : Nat
candidates : Nat
deriving Repr
Scan cuts 1..k using an already computed revenue array.
def scan (price : Nat → Nat) (previous : Array Nat) (n : Nat) : Nat → Scan
| 0 => ⟨0, 0⟩
| k + 1 =>
let rest := scan price previous n k
let candidate := price (k + 1) + arrGet previous (n - (k + 1))
⟨max rest.value candidate, rest.candidates + 1⟩theorem scan_candidates (price : Nat → Nat) (previous : Array Nat) (n k : Nat) :
(scan price previous n k).candidates = k := by
induction k with
| zero => rfl
| succ k ih => simp [scan, ih]
theorem scan_value (price : Nat → Nat) (previous : Array Nat) (n k : Nat) :
(scan price previous n k).value =
(Finset.Icc 1 k).sup (fun i => price i + arrGet previous (n - i)) := by
induction k with
| zero => simp [scan]
| succ k ih =>
have hs : Finset.Icc 1 (k + 1) = insert (k + 1) (Finset.Icc 1 k) := by
ext i
simp only [Finset.mem_Icc, Finset.mem_insert]
omega
simp only [scan, ih, hs, Finset.sup_insert]
exact max_comm _ _structure Run where
array : Array Nat
candidates : Nat
writes : Nat
deriving ReprAppend each new optimum once, using only the previously stored prefix.
def execute (price : Nat → Nat) : Nat → Run
| 0 => ⟨#[0], 0, 1⟩
| j + 1 =>
let previous := execute price j
let row := scan price previous.array (j + 1) (j + 1)
⟨previous.array.push row.value,
previous.candidates + row.candidates, previous.writes + 1⟩The actual stored array refines the previously proved revenue table.
theorem execute_array (price : Nat → Nat) (n : Nat) :
(execute price n).array = rodRevenueArrayAux price n := by
induction n with
| zero => rfl
| succ n ih => simp only [execute, ih, scan_value, rodRevenueArrayAux]
theorem execute_entry (price : Nat → Nat) (n k : Nat) (hk : k ≤ n) :
arrGet (execute price n).array k = bottomUpRodRevenue price k := by
rw [execute_array]
exact arrGet_rodRevenueArrayAux price n k hkExact candidate visits obtained by adding counters of the executed scans.
theorem execute_candidates (price : Nat → Nat) (n : Nat) :
(execute price n).candidates = (Finset.range (n + 1)).sum (fun j => j) := by
induction n with
| zero => simp [execute]
| succ n ih => simp only [execute, ih, scan_candidates, Finset.sum_range_succ]Includes the boundary entry at length zero.
theorem execute_writes (price : Nat → Nat) (n : Nat) :
(execute price n).writes = n + 1 := by
induction n with
| zero => rfl
| succ n ih => simp [execute, ih]
theorem execute_size (price : Nat → Nat) (n : Nat) :
(execute price n).array.size = n + 1 := by
rw [execute_array, rodRevenueArrayAux_size]end CLRS.Chapter15.RodExecution