In-place randomized quicksort on the word RAM #
Iterative in-place 3-way randomized quicksort over Cslib.WordRAM.Basis.standard, sorting an
n-word input array in Block.mk 1 n using an explicit 2 * n-word range stack allocated at
[n + 1, 3 * n + 1).
Using Dutch National Flag 3-way partitioning (< piv, = piv, > piv) around a uniformly
sampled pivot off ← rand (hi - lo - 1) ensures that:
- Pathwise correctness: every execution path halts cleanly with
Block.mk 1 nholdinginput.mergeSort(a sorted permutation ofinput), modifying memory only withinFinset.Ico 1 (3 * n + 1); - Strict worst-case bounds: only subranges of length
≥ 2are pushed, and every partition strictly eliminates at least the sampled pivot, so stack potential∑ (hi - lo - 1)drops on every iteration — bounding every path to at mostn - 1randcalls and20 * n ^ 2 + 8 * n + 32instructions; - Unconditional
O(n log n)expected running time (including duplicates): equal elements fall into the middle= pivregion and are never recursed on, so the left and right recursive sizes on sorted rankrare at mostrandm - 1 - rregardless of duplicate keys. Bounding Mathlib'sharmonicnumbers viaharmonic_le_log_add_one(harmonic n ≤ Nat.log 2 n + 1) yieldsexpectedTime w program (.init input) ≤ 120 * n * (Nat.log 2 n + 1) + 32without transcendental analysis.
Main definitions #
Cslib.Algorithms.WordRAM.Quicksort.code,Cslib.Algorithms.WordRAM.Quicksort.program: structured and compiled 16-register randomized quicksort program.Cslib.Algorithms.WordRAM.Quicksort.worstCaseTime: quadratic worst-case step bound20 * n ^ 2 + 8 * n + 32.Cslib.Algorithms.WordRAM.Quicksort.expectedTimeBound:O(n log n)expected step bound120 * n * (Nat.log 2 n + 1) + 32.
Main results #
Cslib.Algorithms.WordRAM.Quicksort.quicksort_correct_and_bounds: joint certificate ofRandHaltsWithin,RandCallsBounded(≤ n - 1), pathwise sorted-array realization +Modifiesframe, andO(n log n)expectedTimeat word sizew ≥ logWidth 3 input.length.
Classical background on randomized quicksort, equal-key partitioning and the expected-cost recurrence appears in [CLRS09], Section 7.3, Section 7.4.2 and Problems 7-2–7-3; [MU17], Section 2.5, gives additional expected-cost background. The word-RAM implementation and step constants, constant-56 explicit-stack potential, ranked-loop drift formulation and duplicate-key rank-domination proof are original to this formalization.
References #
- T. H. Cormen, C. E. Leiserson, R. L. Rivest and C. Stein, Introduction to Algorithms, Section 7.3, Section 7.4.2 and Problems 7-2–7-3.
- M. Mitzenmacher and E. Upfal, Probability and Computing, Section 2.5.
Expected-partition potential recurrence #
Potential contribution of a subarray of length m in the expected-time drift argument.
Instances For
Memory slices, permutations, and 3-way partition rank bounds #
Swapping two addresses inside [a, b) preserves List.Perm on memSlice a b.
At 3-way partition exit (cur = gt), < piv has exact count lt - lo, > piv has exact
count hi - gt, and piv ∈ memSlice lo hi mem₀ implies lt < gt.
On a sorted list zs (Pairwise (· ≤ ·)), at index r < zs.length, at most r elements are
strictly less than zs[r] and at most zs.length - 1 - r elements are strictly greater than
zs[r].
Expected child subCost summed over all m = u.length uniform pivot choices is bounded by
∑ r < m, (subCost r + subCost (m - 1 - r)), even in the presence of duplicate keys.
Word-size arithmetic (logWidth 3 n ≤ w) and work-stack invariants #
logWidth 3 n ≤ w suffices to fit every address and temporary up to 3 * n + 3 for all
n : ℕ (including n = 0).
Twice S.length is at most n when ValidStack n S holds.
Structured WordRAM quicksort program (r = 16) #
Constant 0.
Instances For
Constant 1.
Instances For
Constant 2.
Instances For
Input array length n.
Instances For
Current stack pointer (S.length).
Instances For
Swap memory cells *a and *b using scratch registers v1, v2 (4 instructions).
Instances For
One Dutch National Flag 3-way partition step at cursor cur (≤ 9 instructions).
Instances For
Push [regs a, regs b) onto (stackLo, stackHi) if regs a + 2 ≤ regs b.
Instances For
One iteration of the outer work-stack loop.
Instances For
Structured in-place 3-way randomized quicksort over 16 registers.
Instances For
Compiled flat randomized quicksort program halting with 0 (in zero).
Instances For
Quadratic worst-case instruction budget 20 * n ^ 2 + 8 * n + 32.
Instances For
O(n log n) expected instruction budget 120 * n * (⌊log₂ n⌋ + 1) + 32.
Instances For
Subroutine executions and partition invariants #
swapCells a b v1 v2 executes in 4 instructions, swapping mem (regs a) and mem (regs b)
and writing only scratch registers v1, v2.
Dutch National Flag 3-way partition loop invariant on [lo, hi).
Register
oneholds1.Register
loholdsvlo.Register
hiholdsvhi.Register
pivholdsvpiv.- fits_hi : WordRAM.Fits w vhi
vhifits inwbits. vlo ≤ lt.gt ≤ vhi.mem[vlo .. vhi)is a permutation ofmem₀[vlo .. vhi).- modifies : WordRAM.Modifies (Finset.Ico vlo vhi) mem₀ x.mem
Only
Finset.Ico vlo vhihas been modified sincemem₀. [vlo, lt)holds elements< vpiv.[lt, cur)holds elements= vpiv.[gt, vhi)holds elements> vpiv.
Instances For
Full 3-way partition loop executes within 11 * (vhi - vlo) + 2 instructions and exits with
cur = gt.
Work-stack representation and pushIfNonTrivial #
Read the active work-stack directly from (x.regs sp, x.mem) at base addresses n + 1 and
2 * n + 1.
Instances For
pushIfNonTrivial a b runs within 8 instructions, appending (va, vb) to readStack n iff
va + 2 ≤ vb, and modifying memory only inside Finset.Ico (n + 1) (3 * n + 1).
Global outer-loop invariant and preservation across 3-way partition #
Full outer-loop machine invariant for in-place randomized quicksort.
Word size meets
logWidth 3 input.length ≤ w.Register
zeroholds0.Register
oneholds1.Register
twoholds2.Register
lenholdsinput.length.Register
stackLoholdsinput.length + 1.Register
stackHiholds2 * input.length + 1.- valid_stack : ValidStack input.length (readStack input.length x)
Active work-stack intervals are valid and pairwise disjoint.
- no_ext_inv : NoExternalInversions input.length x.mem (readStack input.length x)
All inversions lie strictly inside active work-stack intervals.
mem[1 .. n + 1)is a permutation ofinput.- modifies : WordRAM.Modifies (Finset.Ico 1 (3 * input.length + 1)) (WordRAM.Data.init input).mem x.mem
Only
Finset.Ico 1 (3 * n + 1)has been modified sinceData.init input.
Instances For
Deterministic execution of partitionAndPush after popAndSample has popped (vlo, vhi)
leaving stack S₀ and sampled offset k < vhi - vlo into tmp.
Randomized popAndSample, outerBody, setup, and headline bounds #
One iteration outerBody from an active state (0 < sp) pops (vlo, vhi), samples a uniform
pivot k ← unifFin (vhi - vlo - 1) (1 rand call), and runs partitionAndPush in at most
11 * (vhi - vlo) + 31 total instructions.
Quadratic worst-case step potential ∑_{(a,b) ∈ S} 20 * (b - a) ^ 2.
Instances For
rand-call potential ∑_{(a,b) ∈ S} (b - a - 1).
Instances For
Expected-time potential ENNReal.ofReal (∑_{(a,b) ∈ S} subCost (b - a)).
Instances For
setup executes deterministically from Data.init input within 8 * input.length + 29
instructions, establishing OuterInv with initial stack [(1, n + 1)] (if 2 ≤ n) or [].
In-place randomized quicksort: correctness, worst-case bounds, rand-call bound, and
O(n log n) expected running time.
For any input : List ℕ of length n and word size w ≥ logWidth 3 n with InputFits w input:
programhalts without faulting withinworstCaseTime n = 20 * n ^ 2 + 8 * n + 32instructions on every execution path (RandHaltsWithin);- Every execution path makes at most
n - 1randcalls (RandCallsBounded); - On every supported halting configuration
.halted 0 y,y.Bounded wholds,memSlice 1 (n + 1) y.memis a sorted permutation ofinput,Block.mk 1 nrealizesinput.mergeSort, and memory outsideFinset.Ico 1 (3 * n + 1)is untouched (Modifies); - The expected instruction count satisfies
expectedTime w program (.init input) ≤ expectedTimeBound n = 120 * n * (⌊log₂ n⌋ + 1) + 32unconditionally (even wheninputcontains duplicate elements).