Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
5909d1b
feat(DataStructure/Memory): word-addressed memory oracle and named fi…
SamuelSchlesinger Nov 1, 2026
412f614
doc(bib): add Guéneau, Charguéraud and Pottier (ESOP 2018)
SamuelSchlesinger Nov 1, 2026
16a647f
feat(DataStructure/StateTransition): refinements by abstraction funct…
SamuelSchlesinger Nov 1, 2026
2f12c49
feat(DataStructure/StateTransition): weaken and rescale amortized ref…
SamuelSchlesinger Nov 1, 2026
fba5208
Merge the memory-oracle branch (#2211) into the queue slice
SamuelSchlesinger Nov 1, 2026
98e3290
fix(DataStructure/StateTransition): place productCharge beside produc…
SamuelSchlesinger Nov 1, 2026
02ba9f7
Merge the refinement branch (#2212) into the queue slice
SamuelSchlesinger Nov 1, 2026
56232f9
refactor(DataStructure/StateTransition): make Refinement.Amortized a …
SamuelSchlesinger Nov 1, 2026
1b4e2ea
Merge the refinement branch (#2212) into the queue slice
SamuelSchlesinger Nov 1, 2026
fe7d60d
wip: array stack over memory and queue method lemmas
SamuelSchlesinger Nov 1, 2026
aad5f3e
feat(Foundations): affine cost bounds are O(size)
SamuelSchlesinger Nov 1, 2026
78cf872
Merge the refinement branch (#2212) into the queue slice
SamuelSchlesinger Nov 1, 2026
6698e86
wip: queue over memory
SamuelSchlesinger Nov 1, 2026
7dda248
refactor(DataStructure/StateTransition): product answer types via Sum…
SamuelSchlesinger Nov 1, 2026
93adf90
Merge the refinement branch (#2212) into the queue slice
SamuelSchlesinger Nov 1, 2026
412ad37
feat(DataStructure): queue over two array stacks over the memory oracle
SamuelSchlesinger Nov 1, 2026
4283b8f
feat(WordRAM): certify compositional register-word glue
SamuelSchlesinger Nov 1, 2026
cb0adff
Merge commit '4283b8fb714450e78ba170865bcb54ce8563bce3' into codex/ra…
SamuelSchlesinger Nov 1, 2026
45dd184
feat(WordRAM): realize memory queries with uniform bind and glue
SamuelSchlesinger Nov 1, 2026
d8f6bea
fix(WordRAM): normalize the memory return simp rule
SamuelSchlesinger Nov 1, 2026
4977e9b
feat(WordRAM): realize bounded loops and initialized client programs
SamuelSchlesinger Nov 1, 2026
04a06b5
feat(WordRAM): derive global and framed implementation certificates
SamuelSchlesinger Nov 2, 2026
e768e0a
chore(WordRAM): combine published realization and queue prerequisites
SamuelSchlesinger Nov 2, 2026
5917ae4
feat(WordRAM): realize runtime-layout memory-stack methods
SamuelSchlesinger Nov 2, 2026
a929a76
refactor(WordRAM): centralize realization history and word encodings
SamuelSchlesinger Nov 2, 2026
5b9f10e
Merge commit 'a929a76f23194a8e94428973bca2a317f9f23755' into codex/ra…
SamuelSchlesinger Nov 2, 2026
383a520
refactor(WordRAM): expose shared glue rules and infer stack push
SamuelSchlesinger Nov 2, 2026
a91fb0a
feat(WordRAM): realize tactic for memory-client realizations
SamuelSchlesinger Nov 2, 2026
141d112
feat(WordRAM): loops whose body issues a query in realize
SamuelSchlesinger Nov 2, 2026
de22695
test(WordRAM): a whole stack client to a flat program via realize
SamuelSchlesinger Nov 2, 2026
b32e835
feat(WordRAM): extract the static input reindex leaf
SamuelSchlesinger Nov 2, 2026
15eed51
feat(WordRAM): realize measure-bounded early-exit while loops
SamuelSchlesinger Nov 2, 2026
5fd685c
Merge remote-tracking branch 'pr/2246' into feat/ram-realization-adapter
SamuelSchlesinger Nov 2, 2026
0a8975c
fix(WordRAM): destructure the loop argument in Realizes.iterate₀
SamuelSchlesinger Nov 2, 2026
4d7e97c
feat(WordRAM): native backends for memory refinements, one realized b…
SamuelSchlesinger Nov 2, 2026
f51bcd8
style(tests): wrap long lines in the backend test
SamuelSchlesinger Nov 2, 2026
7d6ef37
feat(WordRAM): Backend.data, rep_data and fits_appendWords
SamuelSchlesinger Nov 2, 2026
fb0bf09
test(WordRAM): backend test uses fits_appendWords and Backend.data
SamuelSchlesinger Nov 2, 2026
212e582
perf(WordRAM): state realize certificates per form in the client's terms
SamuelSchlesinger Nov 2, 2026
53b120b
feat(WordRAM): export initialized flat programs with a standard layout
SamuelSchlesinger Nov 2, 2026
fc11f56
Merge remote-tracking branch 'origin/work/c5-while-1651-20261102' int…
SamuelSchlesinger Nov 2, 2026
929ced0
chore: regenerate the aggregate import after merging #2270
SamuelSchlesinger Nov 2, 2026
309306a
Merge origin/main into feat/ram-realization-adapter
SamuelSchlesinger Nov 2, 2026
cac0b0e
chore: drop imports the merge duplicated in Complexity.lean
SamuelSchlesinger Nov 2, 2026
3193d5b
fix(WordRAM): state iterate₀ in iterateRuntime's named-component form
SamuelSchlesinger Nov 2, 2026
f256f87
feat(WordRAM): framed backends - frames, products over one memory, al…
SamuelSchlesinger Nov 2, 2026
ed43a2c
test(WordRAM): allocate a pair of stacks in one body
SamuelSchlesinger Nov 2, 2026
381a01d
feat(WordRAM): guarded loops in realize
SamuelSchlesinger Nov 2, 2026
df7a183
style(WordRAM): wrap a long line in the realize loop tests
SamuelSchlesinger Nov 2, 2026
ddbc31f
refactor(WordRAM): use appendWords for the stack client's environments
SamuelSchlesinger Nov 2, 2026
78098fd
fix(WordRAM): keep iterate₀'s statement, as in #2277's proof-only repair
SamuelSchlesinger Nov 2, 2026
bd1b010
test(WordRAM): a heartbeat budget for the realize transfer loop
SamuelSchlesinger Nov 2, 2026
0d221c2
test(WordRAM): place the transfer loop's heartbeat budget before its …
SamuelSchlesinger Nov 2, 2026
83a32ba
test(WordRAM): a realize loop whose guard and step capture the enviro…
SamuelSchlesinger Nov 2, 2026
c684eb8
Merge origin/feat/framed-backend (#2283) into feat/dijkstra-native
SamuelSchlesinger Nov 2, 2026
73704c9
Merge #2281 (standard initialized flat programs) into feat/dijkstra-n…
SamuelSchlesinger Nov 2, 2026
1e77082
feat(WordRAM): export fixed programs over independent raw memory
SamuelSchlesinger Nov 2, 2026
a0a0968
Merge commit '1e77082f2fab7cc80a00a0e7a2b40690c9d66811' into codex/di…
SamuelSchlesinger Nov 2, 2026
b71a9b4
Merge published static reindex prerequisite for Dijkstra call sites
SamuelSchlesinger Nov 2, 2026
55ddebc
wip(WordRAM): freeze option-pair implementation during gated repair
SamuelSchlesinger Nov 2, 2026
2eb7dc0
fix(WordRAM): preserve scalar encoding normal form in generic option …
SamuelSchlesinger Nov 2, 2026
7675ce4
feat(WordRAM): reuse static method certificates and linked runs
SamuelSchlesinger Nov 2, 2026
ffa55c4
Merge published optional-pair supplier for Dijkstra calls
SamuelSchlesinger Nov 2, 2026
24784a9
fix(WordRAM): match packaged curried method calls
SamuelSchlesinger Nov 2, 2026
7ebe7a9
Merge commit '2eb7dc04d449e9a61799849c779e749ded56ad2b' into codex/di…
SamuelSchlesinger Nov 2, 2026
287e9be
chore(WordRAM): canonicalize supplier import order
SamuelSchlesinger Nov 2, 2026
2011dc2
Merge commit '287e9beef1c398ea840d42e0b9e78b4b70e86d10' into codex/di…
SamuelSchlesinger Nov 2, 2026
754a55b
fix(realize): match dependent method arguments after charged staging
SamuelSchlesinger Nov 2, 2026
27e8ada
fix(realize): scope tactic syntax to WordRAM
SamuelSchlesinger Nov 2, 2026
9b990eb
fix(realize): retain captured loop environment words
SamuelSchlesinger Nov 2, 2026
1907885
chore(realize): refresh captured-loop fix on actual core
SamuelSchlesinger Nov 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 69 additions & 6 deletions Complexity/Tactic/Realize.lean
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ the client syntax, unfolding definitions, with one rule per form:
* `match` on an optional word or word pair: the client equals the branch on its presence tag
(`Realizes.congr`, proved by cases).
* `iterate step D n a` whose step begins with a query: `Realizes.iterate₀`, after
`iterate_comap` moves `D` into the step.
adapting `D` and any captured live words to the whole environment. The source and reached-state
domain are transported back to the client's original loop.
* `boundedWhile G step D n a` whose step begins with a query: `Realizes.while₀`. The guard
`G D r` may be `a = b`, `a < b`, `a > b` or `a ≠ 0` (tested as `0 < a`), with any decidability
instance, over the live words and the state's words; an operand independent of the state, such
Expand Down Expand Up @@ -953,13 +954,14 @@ private partial def realizeIterate (ctx : Ctx) (env : Env) (d : Expr) (atoms : A
| none => encodingOf σ
let l ← encodingWidth out
let envB ← extend env σ out l
let captured := step.containsFVar d.fvarId!
-- the body over the whole environment
let body ← if D == d then pure step else
let body ← if D == d && !captured then pure step else
withLocalDeclD `x envB.ty fun x => do
let x1 ← mkAppM ``Prod.fst #[x]
let x2 ← mkAppM ``Prod.snd #[x]
let Dx := (← mkLambdaFVars #[d] D).beta #[x1]
mkLambdaFVars #[x] (mkApp step (← mkAppM ``Prod.mk #[Dx, x2]))
mkLambdaFVars #[x] (mkApp (step.replaceFVar d x1) (← mkAppM ``Prod.mk #[Dx, x2]))
let hB ← realizeProg ctx envB body (some out)
let hq ← proveQuery body envB.ty
let hLoop ← mkAppM ``Realizes.iterate₀ #[env.input, out, hB.proof, hq]
Expand Down Expand Up @@ -989,10 +991,71 @@ private partial def realizeIterate (ctx : Ctx) (env : Env) (d : Expr) (atoms : A
mkLambdaFVars #[w, d, s] (mkAnd (hA.safe.beta #[w, d, s]) (mkAnd sn sl))
let progR ← mkLambdaFVars #[d] (← mkAppM ``iterate #[body, d, n, a])
let proof ← certify ctx env proof progR out safe
if D == d then return { proof, output := out, safe }
if D == d && !captured then return { proof, output := out, safe }
let g ← mkLambdaFVars #[d] D
let eq ← mkLambdaFVars #[d] (← mkEqSymm (← mkAppM ``iterate_comap #[g, step, d, n, a]))
return { proof := ← mkAppM ``Realizes.congr #[proof, eq], output := out, safe }
let eq ← if captured then do
-- The adapted step agrees at this fixed environment, not at every possible environment.
let ty ← withLocalDeclD `n (mkConst ``Nat) fun n => withLocalDeclD `a σ fun a => do
mkForallFVars #[n, a] (← mkEq (← mkAppM ``iterate #[body, d, n, a])
(← mkAppM ``iterate #[step, D, n, a]))
let h ← Term.withSynthesize <| Term.elabTermEnsuringType (← `(by
intro n a
induction n generalizing a with
| zero => rfl
| succ n ih =>
simp only [iterate]
congr 1
funext b
exact ih b)) (some ty)
mkLambdaFVars #[d] (mkApp2 (← instantiateMVars h) n a)
else
mkLambdaFVars #[d] (← mkEqSymm (← mkAppM ``iterate_comap #[g, step, d, n, a]))
let proof ← mkAppM ``Realizes.congr #[proof, eq]
if !captured then return { proof, output := out, safe }
-- State the reached-state domain in the original loop's terms, as in `realizeWhile`.
let nat := mkConst ``Nat
let state := mkConst ``Memory.State
let pairTy ← mkAppM ``Prod #[← inferType D, σ]
let clientSafe ← withLocalDeclD `w nat fun w =>
withLocalDeclD `x pairTy fun x =>
withLocalDeclD `s state fun s => do
let pair ← mkAppM ``Prod.mk #[d, ← mkAppM ``Prod.snd #[x]]
mkLambdaFVars #[w, x, s] (← reducePairs (hB.safe.beta #[w, pair, s]))
let safe' ← withLocalDeclD `w nat fun w => withLocalDeclD `s state fun s => do
let pair ← mkAppM ``Prod.mk #[d, a]
let sn ← reducePairs (hN.safe.beta #[w, pair, s])
let sl ← mkAppM ``iterationSafe #[step, clientSafe, w, D, n, a, s]
mkLambdaFVars #[w, d, s] (mkAnd (hA.safe.beta #[w, d, s]) (mkAnd sn sl))
let pointwise ← withLocalDeclD `w nat fun w => withLocalDeclD `s state fun s => do
let ty ← withLocalDeclD `n nat fun n => withLocalDeclD `a σ fun a =>
withLocalDeclD `s state fun s => do
mkForallFVars #[n, a, s] (← mkEq
(← mkAppM ``iterationSafe #[body, hB.safe, w, d, n, a, s])
(← mkAppM ``iterationSafe #[step, clientSafe, w, D, n, a, s]))
let h ← Term.withSynthesize <| Term.elabTermEnsuringType (← `(by
intro n a s
induction n generalizing a s with
| zero => rfl
| succ n ih =>
simp only [iterationSafe]
congr 1
exact ih _ _)) (some ty)
let pair ← mkAppM ``Prod.mk #[d, a]
let sn ← reducePairs (hN.safe.beta #[w, pair, s])
let wrap ← withLocalDeclD `p (mkSort Level.zero) fun p =>
mkLambdaFVars #[p] (mkAnd (hA.safe.beta #[w, d, s]) (mkAnd sn p))
mkLambdaFVars #[w, d, s] (← mkAppM ``congrArg
#[wrap, mkApp3 (← instantiateMVars h) n a s])
let safeEq ← withLocalDeclD `w nat fun w => do
let hd ← withLocalDeclD `e env.ty fun e => do
mkLambdaFVars #[e] (← mkAppM ``funext #[mkApp2 pointwise w e])
mkLambdaFVars #[w] (← mkAppM ``funext #[hd])
let safeEq ← mkAppM ``funext #[safeEq]
let proofTy ← inferType proof
let wrap ← withLocalDeclD `safe (← inferType safe) fun s =>
mkLambdaFVars #[s] (mkAppN proofTy.getAppFn (proofTy.getAppArgs.set! 8 s))
let proof ← mkAppM ``Eq.mp #[← mkAppM ``congrArg #[wrap, safeEq], proof]
return { proof, output := out, safe := safe' }

/-- Certify `boundedWhile G step D n a` for the environment variable `d`.

Expand Down
134 changes: 134 additions & 0 deletions ComplexityTests/WordRAMRealizeIterateCapture.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/-
Copyright (c) 2026 Samuel Schlesinger. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Samuel Schlesinger
-/

module
-- upstream: local-only (captured iterate environment regression tests)

public import Complexity.Tactic.Realize

/-!
# Iteration steps retain runtime captures

The explicit loop environment can be `Unit` while the step closes over other live runtime words.
The same source, input encoding, per-step memory query and zero local-work grading are retained.
-/

public section

namespace Cslib.WordRAM.Realization.Tests.IterateCapture

open Cslib.DataStructure

/-- The read address is captured; neither the initial state nor the count selects native code. -/
theorem captured_read : Realizes .exact
(fun d : Fin 3 → ℕ => iterate (fun _ : Unit × ℕ => Memory.read (d 0)) () (d 1) (d 2))
(.refl _) (WordEncoding.encode (α := ℕ)) (fun _ _ _ => True) (fun _ _ => 0) := by
realize

/-- Captures are also adapted when the explicit loop argument is the whole environment. -/
theorem captured_read_whole : Realizes .exact
(fun d : Fin 3 → ℕ =>
iterate (fun _ : (Fin 3 → ℕ) × ℕ => Memory.read (d 0)) d (d 1) (d 2))
(.refl _) (WordEncoding.encode (α := ℕ)) (fun _ _ _ => True) (fun _ _ => 0) := by
realize

/-- A separately certified call keeps its domain at every reached memory, in the original
captured source's terms rather than an auxiliary environment chosen by the frontend. -/
theorem captured_call (m : ℕ × ℕ → Memory.Prog ℕ)
(P : ℕ → ℕ × ℕ → Memory.State → Prop)
(hm : Realizes .exact m (WordEncoding.encode (α := ℕ × ℕ))
(WordEncoding.encode (α := ℕ)) P (fun _ _ => 0)) :
Realizes .exact
(fun d : Fin 3 → ℕ => iterate (fun _ : Unit × ℕ => do
let v ← Memory.read (d 0)
m (d 0, v)) () (d 1) (d 2))
(.refl _) (WordEncoding.encode (α := ℕ))
(fun w d s => iterationSafe
(fun _ : Unit × ℕ => do let v ← Memory.read (d 0); m (d 0, v))
(fun w _ s => P w (d 0, s.mem (d 0)) s) w () (d 1) (d 2) s)
(fun _ _ => 0) := by
realize
exact h

/-- The same emitted body handles distinct captured addresses and zero/two iterations.
Both executions retain every initial memory cell; the query count remains charged. -/
theorem same_body_distinct_environments : ∃ r C, ∃ code : Code .exact r,
∃ result : Fin r, ∃ x₀ y₀ x₁ y₁ : Data r,
¬code.ReadsWidth ∧ x₀.Bounded 3 ∧ x₁.Bounded 3 ∧
ExecWithin 3 code x₀ y₀ C ∧ y₀.regs result = 5 ∧ y₀.mem = x₀.mem ∧
ExecWithin 3 code x₁ y₁ (3 * C) ∧ y₁.regs result = 7 ∧ y₁.mem = x₁.mem := by
obtain ⟨n, C, emit, he⟩ := captured_read
let r := 4 + (1 + n + 1)
let frontier : Fin r := ⟨0, by omega⟩
let src : Fin 3 → Fin r := fun i => ⟨1 + i.val, by omega⟩
let tmp : Fin (1 + n + 1) → Fin r := fun i => ⟨4 + i.val, by omega⟩
let result := tmp 0
have hi : Function.Injective tmp := by
intro i j h
apply Fin.ext
have := congrArg Fin.val h
dsimp only [tmp] at this
omega
have hd (i : Fin 3) (j : Fin (1 + n + 1)) : src i ≠ tmp j := by
intro h
have := congrArg Fin.val h
dsimp only [src, tmp] at this
have := i.isLt
omega
have hf (j : Fin (1 + n + 1)) : tmp j ≠ frontier := by
intro h
have := congrArg Fin.val h
dsimp only [tmp, frontier] at this
omega
have hs (i : Fin 3) : src i ≠ frontier := by
intro h
have := congrArg Fin.val h
dsimp only [src, frontier] at this
omega
let d₀ : Fin 3 → ℕ := ![1, 0, 5]
let d₁ : Fin 3 → ℕ := ![2, 2, 0]
let x₀ : Data r := ⟨fun i => if i.val = 0 then 3 else
if i.val = 1 then 1 else if i.val = 3 then 5 else 0, fun _ => 7⟩
let x₁ : Data r := ⟨fun i => if i.val = 0 then 3 else
if i.val = 1 ∨ i.val = 2 then 2 else 0, fun _ => 7⟩
have hx₀ : x₀.Bounded 3 := by
constructor
· intro i
change Fits 3 (if i.val = 0 then 3 else
if i.val = 1 then 1 else if i.val = 3 then 5 else 0)
split_ifs <;> decide
· intro a
change Fits 3 7
decide
have hx₁ : x₁.Bounded 3 := by
constructor
· intro i
change Fits 3 (if i.val = 0 then 3 else if i.val = 1 ∨ i.val = 2 then 2 else 0)
split_ifs <;> decide
· intro a
change Fits 3 7
decide
have hin₀ : x₀.regs ∘ src = d₀ := by funext i; fin_cases i <;> rfl
have hin₁ : x₁.regs ∘ src = d₁ := by funext i; fin_cases i <;> rfl
obtain ⟨hnw, hrun⟩ := he frontier src tmp hi hd hf hs
obtain ⟨y₀, hy₀, hm₀, ho₀, _⟩ := hrun 3 d₀ x₀ hx₀ hin₀ trivial (by trivial)
obtain ⟨y₁, hy₁, hm₁, ho₁, _⟩ := hrun 3 d₁ x₁ hx₁ hin₁ trivial (by
change 2 < 3 ∧ 2 < 3 ∧ True
decide)
have hc₀ : memoryCost (iterate (fun _ : Unit × ℕ => Memory.read (d₀ 0)) () (d₀ 1)
(d₀ 2)) (memoryState frontier x₀) = 0 := rfl
have hc₁ : memoryCost (iterate (fun _ : Unit × ℕ => Memory.read (d₁ 0)) () (d₁ 1)
(d₁ 2)) (memoryState frontier x₁) = 2 := rfl
have hy₀' : ExecWithin 3 (emit frontier src tmp) x₀ y₀ C := by
simpa only [hc₀, Nat.zero_add, Nat.add_zero, Nat.mul_one]
using hy₀
have hy₁' : ExecWithin 3 (emit frontier src tmp) x₁ y₁ (3 * C) := by
simpa only [hc₁, Nat.add_zero, Nat.reduceAdd, Nat.mul_comm]
using hy₁
exact ⟨r, C, emit frontier src tmp, result, x₀, y₀, x₁, y₁, hnw, hx₀, hx₁, hy₀',
ho₀ 0, congrArg Memory.State.mem hm₀, hy₁', ho₁ 0, congrArg Memory.State.mem hm₁⟩

end Cslib.WordRAM.Realization.Tests.IterateCapture
Loading