Indexed minimum priority queue
StructureIndexed minimum queue#✓fully proved
Let \(W\) be a linearly ordered type, let \(W \cup \{\top\}\) be \(W\) with a new greatest element \(\top\) adjoined, and let \(n\) be a natural number. An indexed minimum queue over the identities \(0, \dots, n-1\) consists of a binary min-heap whose entries are pairs \((k, v)\) of a key \(k \in W \cup \{\top\}\) and an identity \(v < n\), ordered lexicographically (first by key, then by identity), together with a position vector assigning to each identity \(v < n\) either nothing or an index \(i < n\). It is required that the heap has at most \(n\) entries and that, for all identities \(v < n\) and indices \(i < n\), the position of \(v\) is \(i\) exactly when \(i\) is a slot of the heap whose entry has identity \(v\).
structure IndexedMinQueue (W : Type u) [LinearOrder W] (n : Nat) where
heap : Cslib.Algorithms.Lean.MinHeap (WithTop W ×ₗ Fin n)
position : Vector (Option (Fin n)) n
capacity : heap.data.size ≤ n
inverse : ∀ (v i : Fin n), position[v] = some i ↔
∃ hi : i.val < heap.data.size, (ofLex (heap.data[i.val]'hi)).2 = v
structure MinHeap (α : Type u) [LinearOrder α] where
/-- The level-order storage array. -/
data : Array α
ordered : HeapOrdered data
CSLibExt/Algorithms/Lean/DataStructures/BinaryHeap.lean:538
heap : Cslib.Algorithms.Lean.MinHeap (WithTop W ×ₗ Fin n)
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:43
position : Vector (Option (Fin n)) n
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:44
Uses 1 · Used by 29
DefinitionEmpty indexed minimum queue#✓fully proved
For every linearly ordered type \(W\) and every natural number \(n\), the empty indexed minimum queue over the identities \(0, \dots, n-1\), with keys in \(W\) with a new greatest element adjoined, has the empty min-heap and a position vector that assigns nothing to each of the \(n\) identities, so no identity is present.
def empty {W : Type u} [LinearOrder W] (n : Nat) : IndexedMinQueue W n where
heap := MinHeap.empty
position := Vector.replicate n none
capacity := by simp [MinHeap.empty]
inverse := by simp [MinHeap.empty]
structure IndexedMinQueue (W : Type u) [LinearOrder W] (n : Nat) where
heap : Cslib.Algorithms.Lean.MinHeap (WithTop W ×ₗ Fin n)
position : Vector (Option (Fin n)) n
capacity : heap.data.size ≤ n
inverse : ∀ (v i : Fin n), position[v] = some i ↔
∃ hi : i.val < heap.data.size, (ofLex (heap.data[i.val]'hi)).2 = v
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:42
def MinHeap.empty {α : Type u} [LinearOrder α] : MinHeap α where
data := #[]
ordered := by simp [HeapOrdered]
CSLibExt/Algorithms/Lean/DataStructures/BinaryHeap.lean:548
Uses 3 · Used by 11
DefinitionMembership test in an indexed minimum queue#✓fully proved
Costs are counted as five event counts: comparisons, swaps, reads of the position vector, writes to the position vector, and entry appends, pops or replacements. For an indexed minimum queue \(q\) over the identities \(0, \dots, n-1\) and an identity \(v < n\), the membership test returns true exactly when the position vector of \(q\) assigns an index to \(v\), and its cost is one position read and no other event.
@[no_expose] def member {W : Type u} [LinearOrder W] {n : Nat}
(q : IndexedMinQueue W n) (v : Fin n) : TimeM (Fin 5 → Nat) Bool :=
⟨q.position[v].isSome, event 2⟩
structure IndexedMinQueue (W : Type u) [LinearOrder W] (n : Nat) where
heap : Cslib.Algorithms.Lean.MinHeap (WithTop W ×ₗ Fin n)
position : Vector (Option (Fin n)) n
capacity : heap.data.size ≤ n
inverse : ∀ (v i : Fin n), position[v] = some i ↔
∃ hi : i.val < heap.data.size, (ofLex (heap.data[i.val]'hi)).2 = v
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:42
private def event (i : Fin 5) : Fin 5 → Nat :=
fun j => if j = i then 1 else 0
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:49
Uses 1 · Used by 11
DefinitionInsertion into an indexed minimum queue#✓fully proved
Let \(W\) be a linearly ordered type and let \(W \cup \{\top\}\) be \(W\) with a new greatest element \(\top\) adjoined. Costs are counted as five event counts: comparisons, swaps, reads of the position vector, writes to the position vector, and entry appends, pops or replacements. Given an indexed minimum queue \(q\) over the identities \(0, \dots, n-1\) with keys in \(W \cup \{\top\}\), whose heap entries (pairs of a key and an identity) are ordered lexicographically, first by key and then by identity, an identity \(v < n\) and a key \(k \in W \cup \{\top\}\), insertion fails (returns nothing) when the position vector of \(q\) assigns an index to \(v\), at the cost of one position read. Otherwise it appends the entry \((k, v)\) at the end of the heap, sets the position of \(v\) to that slot, and sifts the entry up: while it is not at the root and is smaller than its parent, it is swapped with its parent and the positions of both swapped identities are updated. It returns the resulting queue, at the cost of one position read, one position write and one entry append, plus one comparison for each comparison with a parent and one swap and two position writes for each swap.
Cslib.Algorithms.Lean.IndexedMinQueue.insert · 28 lines
@[no_expose] def insert {W : Type u} [LinearOrder W] {n : Nat}
(q : IndexedMinQueue W n) (v : Fin n) (key : WithTop W) :
TimeM (Fin 5 → Nat) (Option (IndexedMinQueue W n)) :=
if hpresent : q.position[v].isSome = true then
⟨none, event 2⟩
else
have habsent : q.position[v] = none := by
simpa [Option.isSome_iff_ne_none] using hpresent
have hspare : q.heap.data.size < n := absent_spare q v habsent
let entry := toLex (key, v)
let a := q.heap.data.push entry
let position := q.position.set v (some ⟨q.heap.data.size, hspare⟩)
let hcap : a.size ≤ n := by simp [a]; omega
let r := siftUpTracked a position hcap q.heap.data.size
have hrdata : r.data = (q.heap.push entry).data := by
exact siftUpTracked_data a position hcap q.heap.data.size
have hrinv : Inverse r.data r.position := by
apply siftUpTracked_inverse a position hcap
exact inverse_push q.heap.data q.position hspare q.inverse v key habsent
let heap' : MinHeap (WithTop W ×ₗ Fin n) :=
⟨r.data, by rw [hrdata]; exact (q.heap.push entry).ordered⟩
have hcap' : heap'.data.size ≤ n := by
rw [show heap'.data = r.data from rfl, hrdata]
change (siftUp a q.heap.data.size).size ≤ n
rw [(siftUp_perm a q.heap.data.size).size_eq]
exact hcap
⟨some ⟨heap', r.position, hcap', hrinv⟩,
event 2 + event 3 + event 4 + r.time⟩
structure IndexedMinQueue (W : Type u) [LinearOrder W] (n : Nat) where
heap : Cslib.Algorithms.Lean.MinHeap (WithTop W ×ₗ Fin n)
position : Vector (Option (Fin n)) n
capacity : heap.data.size ≤ n
inverse : ∀ (v i : Fin n), position[v] = some i ↔
∃ hi : i.val < heap.data.size, (ofLex (heap.data[i.val]'hi)).2 = v
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:42
private def event (i : Fin 5) : Fin 5 → Nat :=
fun j => if j = i then 1 else 0
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:49
Uses 8 · Used by 13
DefinitionDecrease-key in an indexed minimum queue#✓fully proved
Let \(W\) be a linearly ordered type and let \(W \cup \{\top\}\) be \(W\) with a new greatest element \(\top\) adjoined. Costs are counted as five event counts: comparisons, swaps, reads of the position vector, writes to the position vector, and entry appends, pops or replacements. Given an indexed minimum queue \(q\) over the identities \(0, \dots, n-1\) with keys in \(W \cup \{\top\}\), whose heap entries (pairs of a key and an identity) are ordered lexicographically, first by key and then by identity, an identity \(v < n\) and a finite key \(k \in W\), decrease-key fails (returns nothing) when the position vector of \(q\) assigns no index to \(v\), at the cost of one position read, and when \(k\) is not strictly smaller than the current key of \(v\), at the cost of one position read and one comparison. Otherwise it replaces the entry of \(v\) by \((k, v)\) in the same slot and sifts it up: while it is not at the root and is smaller than its parent, it is swapped with its parent and the positions of both swapped identities are updated. It returns the resulting queue, at the cost of one position read, one comparison and one entry replacement, plus one comparison for each comparison with a parent and one swap and two position writes for each swap.
Cslib.Algorithms.Lean.IndexedMinQueue.decreaseKey · 27 lines
@[no_expose] def decreaseKey {W : Type u} [LinearOrder W] {n : Nat}
(q : IndexedMinQueue W n) (v : Fin n) (key : W) :
TimeM (Fin 5 → Nat) (Option (IndexedMinQueue W n)) :=
match hp : q.position[v] with
| none => ⟨none, event 2⟩
| some i =>
have hi : i.val < q.heap.data.size := (q.inverse v i).1 hp |>.choose
let old := q.heap.data[i.val]'hi
if hlt : (↑key : WithTop W) < (ofLex old).1 then
have hid : (ofLex old).2 = v := (q.inverse v i).1 hp |>.choose_spec
let a := q.heap.data.set i.val (toLex ((↑key : WithTop W), v)) hi
have hinv : Inverse a q.position :=
inverse_set_key q.heap.data q.position q.inverse i.val hi v hid key
let r := siftUpTracked a q.position (by simpa [a] using q.capacity) i.val
have hrinv := siftUpTracked_inverse a q.position (by simpa [a] using q.capacity) hinv i.val
let heap' : MinHeap (WithTop W ×ₗ Fin n) :=
⟨r.data, by
rw [siftUpTracked_data]
exact siftUp_ordered a i.val (set_decrease_ready q v key i hi hid hlt)⟩
let q' : IndexedMinQueue W n :=
⟨heap', r.position, by
rw [show heap'.data = r.data from rfl, siftUpTracked_data]
rw [(siftUp_perm a i.val).size_eq]
simpa [a] using q.capacity, hrinv⟩
⟨some q', event 2 + event 0 + event 4 + r.time⟩
else
⟨none, event 2 + event 0⟩
structure IndexedMinQueue (W : Type u) [LinearOrder W] (n : Nat) where
heap : Cslib.Algorithms.Lean.MinHeap (WithTop W ×ₗ Fin n)
position : Vector (Option (Fin n)) n
capacity : heap.data.size ≤ n
inverse : ∀ (v i : Fin n), position[v] = some i ↔
∃ hi : i.val < heap.data.size, (ofLex (heap.data[i.val]'hi)).2 = v
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:42
private def event (i : Fin 5) : Fin 5 → Nat :=
fun j => if j = i then 1 else 0
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:49
private def Inverse {W : Type u} [LinearOrder W] {n : Nat}
(a : Array (WithTop W ×ₗ Fin n))
(position : Vector (Option (Fin n)) n) : Prop :=
∀ (v i : Fin n), position[v] = some i ↔
∃ hi : i.val < a.size, (ofLex (a[i.val]'hi)).2 = v
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:57
private lemma inverse_set_key {W : Type u} [LinearOrder W] {n : Nat}
(a : Array (WithTop W ×ₗ Fin n))
(position : Vector (Option (Fin n)) n) (hinv : Inverse a position)
(i : Nat) (hi : i < a.size) (v : Fin n)
(hid : (ofLex (a[i]'hi)).2 = v) (key : WithTop W) :
Inverse (a.set i (toLex (key, v)) hi) position
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:149
private def siftUpTracked {W : Type u} [LinearOrder W] {n : Nat}
(a : Array (WithTop W ×ₗ Fin n))
(position : Vector (Option (Fin n)) n) (hcap : a.size ≤ n)
(i : Nat) : Tracked (W := W) n :=
if hi : i < a.size then
if hpos : 0 < i then
let p := heapParent i
let hp := heapParent_lt_size a i hi hpos
if a[i] < a[p] then
let a' := a.swap i p hi hp
let position' := swapPosition a position hcap i p hi hp
let r := siftUpTracked a' position' (by simpa [a'] using hcap) p
⋯
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:292
Uses 9 · Used by 12
DefinitionExtract-min in an indexed minimum queue#✓fully proved
Costs are counted as five event counts: comparisons, swaps, reads of the position vector, writes to the position vector, and entry appends, pops or replacements. Given an indexed minimum queue \(q\), extract-min fails (returns nothing) exactly when the heap of \(q\) is empty, at zero cost. Otherwise let \((k, v)\) be the root entry of the heap. If the heap has one entry, extract-min returns \((k, v)\) together with the queue whose heap is empty and in which \(v\) has no position, at the cost of one position write and one entry pop. If the heap has at least two entries, the root is swapped with the last entry and the positions of both are updated, the last slot is removed, the position of \(v\) is cleared, and the new root is sifted down: while it has a child, let \(c\) be its smaller child (the left one on ties); if \(c\) is smaller than it, the two are swapped and the positions of both are updated, otherwise the sift stops. It returns \((k, v)\) together with the resulting queue, at the cost of one swap, three position writes and one entry pop, plus, at each sift-down step, one comparison between the two children when both exist, one comparison with \(c\), and one swap and two position writes when a swap is made.
Cslib.Algorithms.Lean.IndexedMinQueue.extractMin · 60 lines
@[no_expose] def extractMin {W : Type u} [LinearOrder W] {n : Nat}
(q : IndexedMinQueue W n) :
TimeM (Fin 5 → Nat)
(Option ((WithTop W ×ₗ Fin n) × IndexedMinQueue W n)) :=
if hempty : q.heap.data.size = 0 then
⟨none, 0⟩
else
have hne : 0 < q.heap.data.size := Nat.pos_of_ne_zero hempty
let entry := q.heap.data[0]'hne
let v := (ofLex entry).2
if hone : q.heap.data.size = 1 then
let position := q.position.set v none
have hinv : Inverse (#[] : Array (WithTop W ×ₗ Fin n)) position := by
have hlast : (ofLex (q.heap.data[q.heap.data.size - 1]'(by omega))).2 = v := by
simp [v, entry, hone]
have hpop : q.heap.data.pop = #[] :=
Array.eq_empty_of_size_eq_zero (by simp [hone])
simpa only [hpop] using
inverse_pop_clear q.heap.data q.position q.capacity q.inverse hne v hlast
let q' : IndexedMinQueue W n :=
⟨MinHeap.empty, position, by simp [MinHeap.empty], hinv⟩
⟨some (entry, q'), event 3 + event 4⟩
else
have htwo : 1 < q.heap.data.size := by omega
let last := q.heap.data.size - 1
let aSwap := q.heap.data.swap 0 last hne (by dsimp [last]; omega)
let positionSwap := swapPosition q.heap.data q.position q.capacity 0 last hne
(by dsimp [last]; omega)
have hinvSwap : Inverse aSwap positionSwap := by
apply inverse_swap q.heap.data q.position q.capacity q.inverse 0 last hne
(by dsimp [last]; omega)
omega
let a := aSwap.pop
let position := positionSwap.set v none
have hlast : (ofLex (aSwap[aSwap.size - 1]'(by
dsimp only [aSwap]
rw [Array.size_swap]
omega))).2 = v := by
simp [aSwap, last, v, entry]
have hinv : Inverse a position := by
exact inverse_pop_clear aSwap positionSwap (by simpa [aSwap] using q.capacity)
hinvSwap (by simp [aSwap]; omega) v hlast
have hcap : a.size ≤ n := by
have hc := q.capacity
simp only [a, aSwap, Array.size_pop, Array.size_swap]
omega
let r := siftDownTracked a position hcap 0
have hrdata : r.data = (q.heap.extractTail hne).data := by
rw [MinHeap.extractTail, dite_eq_right hone]
exact siftDownTracked_data a position hcap 0
have hrinv := siftDownTracked_inverse a position hcap hinv 0
let heap' : MinHeap (WithTop W ×ₗ Fin n) :=
⟨r.data, by rw [hrdata]; exact (q.heap.extractTail hne).ordered⟩
let q' : IndexedMinQueue W n :=
⟨heap', r.position, by
change r.data.size ≤ n
rw [siftDownTracked_data, (siftDown_perm a 0).size_eq]
exact hcap, hrinv⟩
⟨some (entry, q'),
event 1 + event 3 + event 3 + event 3 + event 4 + r.time⟩
structure IndexedMinQueue (W : Type u) [LinearOrder W] (n : Nat) where
heap : Cslib.Algorithms.Lean.MinHeap (WithTop W ×ₗ Fin n)
position : Vector (Option (Fin n)) n
capacity : heap.data.size ≤ n
inverse : ∀ (v i : Fin n), position[v] = some i ↔
∃ hi : i.val < heap.data.size, (ofLex (heap.data[i.val]'hi)).2 = v
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:42
private def Inverse {W : Type u} [LinearOrder W] {n : Nat}
(a : Array (WithTop W ×ₗ Fin n))
(position : Vector (Option (Fin n)) n) : Prop :=
∀ (v i : Fin n), position[v] = some i ↔
∃ hi : i.val < a.size, (ofLex (a[i.val]'hi)).2 = v
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:57
Uses 14 · Used by 12
TheoremRecorded positions lie inside the heap#✓fully proved
Let \(W\) be a linearly ordered type and let \(q\) be an indexed min-queue over \(W\) with identities in \(\{0, \dots, n-1\}\). If the position table of \(q\) records slot \(i\) for an identity \(v\), then \(i\) is less than the number of entries currently stored in the heap array of \(q\).
theorem position_valid {W : Type u} [LinearOrder W] {n : Nat}
(q : IndexedMinQueue W n) (v i : Fin n)
(h : q.position[v] = some i) : i.val < q.heap.data.size
structure IndexedMinQueue (W : Type u) [LinearOrder W] (n : Nat) where
heap : Cslib.Algorithms.Lean.MinHeap (WithTop W ×ₗ Fin n)
position : Vector (Option (Fin n)) n
capacity : heap.data.size ≤ n
inverse : ∀ (v i : Fin n), position[v] = some i ↔
∃ hi : i.val < heap.data.size, (ofLex (heap.data[i.val]'hi)).2 = v
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:42
Uses 2 · Used by 12
TheoremAbsent identities carry no heap entry#✓fully proved
Let \(q\) be an indexed min queue over a linear order \(W\) with identities in \(\{0, \dots, n-1\}\) and let \(v\) be an identity. The position vector of \(q\) records no slot for \(v\) if and only if no entry of the heap array of \(q\) has identity \(v\).
theorem position_eq_none_iff {W : Type u} [LinearOrder W] {n : Nat}
(q : IndexedMinQueue W n) (v : Fin n) :
q.position[v] = none ↔
¬ ∃ entry ∈ q.heap.data.toList, (ofLex entry).2 = v
structure IndexedMinQueue (W : Type u) [LinearOrder W] (n : Nat) where
heap : Cslib.Algorithms.Lean.MinHeap (WithTop W ×ₗ Fin n)
position : Vector (Option (Fin n)) n
capacity : heap.data.size ≤ n
inverse : ∀ (v i : Fin n), position[v] = some i ↔
∃ hi : i.val < heap.data.size, (ofLex (heap.data[i.val]'hi)).2 = v
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:42
Uses 2 · Used by 8
TheoremThe empty indexed min queue has no present identity#✓fully proved
For every linear order \(W\), every \(n\) and every identity \(v \in \{0, \dots, n-1\}\), the position vector of the empty indexed min queue over \(W\) with identities in \(\{0, \dots, n-1\}\) records no slot for \(v\).
theorem empty_position {W : Type u} [LinearOrder W] {n : Nat}
(v : Fin n) : (empty (W := W) n).position[v] = none
def empty {W : Type u} [LinearOrder W] (n : Nat) : IndexedMinQueue W n where
heap := MinHeap.empty
position := Vector.replicate n none
capacity := by simp [MinHeap.empty]
inverse := by simp [MinHeap.empty]
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:441
Uses 2 · Used by 7
TheoremInsertion fails exactly on present identities#✓fully proved
Let \(q\) be an indexed min queue over a linear order \(W\) with identities in \(\{0, \dots, n-1\}\), let \(v\) be an identity and let \(k \in W \cup \{\top\}\). Inserting \(v\) with key \(k\) into \(q\) returns no queue if and only if the position vector of \(q\) records a slot for \(v\).
theorem insert_eq_none_iff {W : Type u} [LinearOrder W] {n : Nat}
(q : IndexedMinQueue W n) (v : Fin n) (key : WithTop W) :
(insert q v key).ret = none ↔ q.position[v].isSome = true
structure IndexedMinQueue (W : Type u) [LinearOrder W] (n : Nat) where
heap : Cslib.Algorithms.Lean.MinHeap (WithTop W ×ₗ Fin n)
position : Vector (Option (Fin n)) n
capacity : heap.data.size ≤ n
inverse : ∀ (v i : Fin n), position[v] = some i ↔
∃ hi : i.val < heap.data.size, (ofLex (heap.data[i.val]'hi)).2 = v
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:42
@[no_expose] def insert {W : Type u} [LinearOrder W] {n : Nat}
(q : IndexedMinQueue W n) (v : Fin n) (key : WithTop W) :
TimeM (Fin 5 → Nat) (Option (IndexedMinQueue W n)) :=
if hpresent : q.position[v].isSome = true then
⟨none, event 2⟩
else
have habsent : q.position[v] = none := by
simpa [Option.isSome_iff_ne_none] using hpresent
have hspare : q.heap.data.size < n := absent_spare q v habsent
let entry := toLex (key, v)
let a := q.heap.data.push entry
let position := q.position.set v (some ⟨q.heap.data.size, hspare⟩)
⋯
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:453
Uses 9 · Used by 7
TheoremExtraction from an indexed min queue fails exactly when it is empty#✓fully proved
Let \(q\) be an indexed min queue over a linear order \(W\) with identities in \(\{0, \dots, n-1\}\). Extracting the minimum of \(q\) returns no result if and only if the heap array of \(q\) has size \(0\).
theorem extractMin_eq_none_iff {W : Type u} [LinearOrder W] {n : Nat}
(q : IndexedMinQueue W n) :
(extractMin q).ret = none ↔ q.heap.data.size = 0
structure IndexedMinQueue (W : Type u) [LinearOrder W] (n : Nat) where
heap : Cslib.Algorithms.Lean.MinHeap (WithTop W ×ₗ Fin n)
position : Vector (Option (Fin n)) n
capacity : heap.data.size ≤ n
inverse : ∀ (v i : Fin n), position[v] = some i ↔
∃ hi : i.val < heap.data.size, (ofLex (heap.data[i.val]'hi)).2 = v
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:42
@[no_expose] def extractMin {W : Type u} [LinearOrder W] {n : Nat}
(q : IndexedMinQueue W n) :
TimeM (Fin 5 → Nat)
(Option ((WithTop W ×ₗ Fin n) × IndexedMinQueue W n)) :=
if hempty : q.heap.data.size = 0 then
⟨none, 0⟩
else
have hne : 0 < q.heap.data.size := Nat.pos_of_ne_zero hempty
let entry := q.heap.data[0]'hne
let v := (ofLex entry).2
if hone : q.heap.data.size = 1 then
let position := q.position.set v none
⋯
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:552
Uses 15 · Used by 7
TheoremMembership reads the position vector#✓fully proved
Let \(q\) be an indexed min queue over a linear order \(W\) with identities in \(\{0, \dots, n-1\}\) and let \(v\) be an identity. The membership test for \(v\) in \(q\) returns true if and only if the position vector of \(q\) records a slot for \(v\).
theorem member_ret {W : Type u} [LinearOrder W] {n : Nat}
(q : IndexedMinQueue W n) (v : Fin n) :
(member q v).ret = q.position[v].isSome
structure IndexedMinQueue (W : Type u) [LinearOrder W] (n : Nat) where
heap : Cslib.Algorithms.Lean.MinHeap (WithTop W ×ₗ Fin n)
position : Vector (Option (Fin n)) n
capacity : heap.data.size ≤ n
inverse : ∀ (v i : Fin n), position[v] = some i ↔
∃ hi : i.val < heap.data.size, (ofLex (heap.data[i.val]'hi)).2 = v
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:42
@[no_expose] def member {W : Type u} [LinearOrder W] {n : Nat}
(q : IndexedMinQueue W n) (v : Fin n) : TimeM (Fin 5 → Nat) Bool :=
⟨q.position[v].isSome, event 2⟩
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:448
Uses 2 · Used by 8
TheoremMembership costs one position read#✓fully proved
Let \(q\) be an indexed min queue over a linear order \(W\) with identities in \(\{0, \dots, n-1\}\) and let \(v\) be an identity. The cost of the membership test for \(v\) in \(q\), counted in five event classes (comparisons, swaps, position-vector reads, position-vector writes, and entry appends, pops or replacements), is exactly one position-vector read and no event of any other class.
theorem member_time {W : Type u} [LinearOrder W] {n : Nat}
(q : IndexedMinQueue W n) (v : Fin n) :
(member q v).time = fun c : Fin 5 => if c = 2 then 1 else 0
structure IndexedMinQueue (W : Type u) [LinearOrder W] (n : Nat) where
heap : Cslib.Algorithms.Lean.MinHeap (WithTop W ×ₗ Fin n)
position : Vector (Option (Fin n)) n
capacity : heap.data.size ≤ n
inverse : ∀ (v i : Fin n), position[v] = some i ↔
∃ hi : i.val < heap.data.size, (ofLex (heap.data[i.val]'hi)).2 = v
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:42
@[no_expose] def member {W : Type u} [LinearOrder W] {n : Nat}
(q : IndexedMinQueue W n) (v : Fin n) : TimeM (Fin 5 → Nat) Bool :=
⟨q.position[v].isSome, event 2⟩
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:448
Uses 2 · Used by 1
TheoremSuccessful insertion into an indexed min queue#✓fully proved
Let \(q\) be an indexed min queue over a linear order \(W\) with identities in \(\{0, \dots, n-1\}\), let \(v\) be an identity and let \(k \in W \cup \{\top\}\), and suppose that inserting \(v\) with key \(k\) into \(q\) returns the queue \(q'\). Then the heap of \(q'\) is the binary min-heap push of the entry \((k, v)\) onto the heap of \(q\); the position vector of \(q'\) records a slot \(i\) for \(v\), with \(i\) less than the size of the heap array of \(q'\), and that array holds \((k, v)\) at index \(i\); and every identity \(w \neq v\) has a recorded slot in \(q'\) if and only if it has one in \(q\).
theorem insert_ret {W : Type u} [LinearOrder W] {n : Nat}
(q q' : IndexedMinQueue W n) (v : Fin n) (key : WithTop W)
(h : (insert q v key).ret = some q') :
q'.heap = q.heap.push (toLex (key, v)) ∧
(∃ (i : Fin n) (hi : i.val < q'.heap.data.size),
q'.position[v] = some i ∧ q'.heap.data[i.val]'hi = toLex (key, v)) ∧
∀ w : Fin n, w ≠ v → q'.position[w].isSome = q.position[w].isSome
structure IndexedMinQueue (W : Type u) [LinearOrder W] (n : Nat) where
heap : Cslib.Algorithms.Lean.MinHeap (WithTop W ×ₗ Fin n)
position : Vector (Option (Fin n)) n
capacity : heap.data.size ≤ n
inverse : ∀ (v i : Fin n), position[v] = some i ↔
∃ hi : i.val < heap.data.size, (ofLex (heap.data[i.val]'hi)).2 = v
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:42
@[no_expose] def insert {W : Type u} [LinearOrder W] {n : Nat}
(q : IndexedMinQueue W n) (v : Fin n) (key : WithTop W) :
TimeM (Fin 5 → Nat) (Option (IndexedMinQueue W n)) :=
if hpresent : q.position[v].isSome = true then
⟨none, event 2⟩
else
have habsent : q.position[v] = none := by
simpa [Option.isSome_iff_ne_none] using hpresent
have hspare : q.heap.data.size < n := absent_spare q v habsent
let entry := toLex (key, v)
let a := q.heap.data.push entry
let position := q.position.set v (some ⟨q.heap.data.size, hspare⟩)
⋯
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:453
Uses 12 · Used by 8
TheoremDecrease-key fails exactly on absent identities and non-decreases#✓fully proved
Let \(q\) be an indexed min queue over a linear order \(W\) with identities in \(\{0, \dots, n-1\}\), let \(v\) be an identity and let \(k \in W\). Decreasing the key of \(v\) to \(k\) in \(q\) returns no queue if and only if either the position vector of \(q\) records no slot for \(v\), or it records a slot \(i\) for \(v\) with \(i\) less than the size of the heap array of \(q\) and \(k\) is not strictly less, in \(W \cup \{\top\}\), than the key of the heap entry at index \(i\).
theorem decreaseKey_eq_none_iff {W : Type u} [LinearOrder W] {n : Nat}
(q : IndexedMinQueue W n) (v : Fin n) (key : W) :
(decreaseKey q v key).ret = none ↔
q.position[v] = none ∨
∃ (i : Fin n) (hi : i.val < q.heap.data.size),
q.position[v] = some i ∧
¬ (↑key : WithTop W) < (ofLex (q.heap.data[i.val]'hi)).1
structure IndexedMinQueue (W : Type u) [LinearOrder W] (n : Nat) where
heap : Cslib.Algorithms.Lean.MinHeap (WithTop W ×ₗ Fin n)
position : Vector (Option (Fin n)) n
capacity : heap.data.size ≤ n
inverse : ∀ (v i : Fin n), position[v] = some i ↔
∃ hi : i.val < heap.data.size, (ofLex (heap.data[i.val]'hi)).2 = v
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:42
@[no_expose] def decreaseKey {W : Type u} [LinearOrder W] {n : Nat}
(q : IndexedMinQueue W n) (v : Fin n) (key : W) :
TimeM (Fin 5 → Nat) (Option (IndexedMinQueue W n)) :=
match hp : q.position[v] with
| none => ⟨none, event 2⟩
| some i =>
have hi : i.val < q.heap.data.size := (q.inverse v i).1 hp |>.choose
let old := q.heap.data[i.val]'hi
if hlt : (↑key : WithTop W) < (ofLex old).1 then
have hid : (ofLex old).2 = v := (q.inverse v i).1 hp |>.choose_spec
let a := q.heap.data.set i.val (toLex ((↑key : WithTop W), v)) hi
have hinv : Inverse a q.position :=
⋯
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:523
Uses 11 · Used by 8
TheoremSuccessful decrease-key#✓fully proved
Let \(q\) be an indexed min queue over a linear order \(W\) with identities in \(\{0, \dots, n-1\}\), let \(v\) be an identity and let \(k \in W\), and suppose that decreasing the key of \(v\) to \(k\) in \(q\) returns the queue \(q'\). Let \(a\) be the heap array of \(q\). Then the position vector of \(q\) records a slot \(i\) for \(v\) with \(i\) less than the size of \(a\), \(k\) is strictly less, in \(W \cup \{\top\}\), than the key of the entry \(a_i\), and the heap array of \(q'\) is obtained by sifting up from index \(i\) the array that agrees with \(a\) except that \(a_i\) is replaced by \((k, v)\). Moreover, every identity has a recorded slot in \(q'\) if and only if it has one in \(q\).
theorem decreaseKey_ret {W : Type u} [LinearOrder W] {n : Nat}
(q q' : IndexedMinQueue W n) (v : Fin n) (key : W)
(h : (decreaseKey q v key).ret = some q') :
(∃ (i : Fin n) (hi : i.val < q.heap.data.size),
q.position[v] = some i ∧
(↑key : WithTop W) < (ofLex (q.heap.data[i.val]'hi)).1 ∧
q'.heap.data = siftUp
(q.heap.data.set i.val (toLex ((↑key : WithTop W), v)) hi) i.val) ∧
∀ w : Fin n, q'.position[w].isSome = q.position[w].isSome
structure IndexedMinQueue (W : Type u) [LinearOrder W] (n : Nat) where
heap : Cslib.Algorithms.Lean.MinHeap (WithTop W ×ₗ Fin n)
position : Vector (Option (Fin n)) n
capacity : heap.data.size ≤ n
inverse : ∀ (v i : Fin n), position[v] = some i ↔
∃ hi : i.val < heap.data.size, (ofLex (heap.data[i.val]'hi)).2 = v
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:42
@[no_expose] def decreaseKey {W : Type u} [LinearOrder W] {n : Nat}
(q : IndexedMinQueue W n) (v : Fin n) (key : W) :
TimeM (Fin 5 → Nat) (Option (IndexedMinQueue W n)) :=
match hp : q.position[v] with
| none => ⟨none, event 2⟩
| some i =>
have hi : i.val < q.heap.data.size := (q.inverse v i).1 hp |>.choose
let old := q.heap.data[i.val]'hi
if hlt : (↑key : WithTop W) < (ofLex old).1 then
have hid : (ofLex old).2 = v := (q.inverse v i).1 hp |>.choose_spec
let a := q.heap.data.set i.val (toLex ((↑key : WithTop W), v)) hi
have hinv : Inverse a q.position :=
⋯
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:523
def siftUp {α : Type u} [LinearOrder α] (a : Array α) (i : Nat) : Array α :=
if hi : i < a.size then
if hpos : 0 < i then
let p := heapParent i
if hlt : a[i] < a[p]'(heapParent_lt_size a i hi hpos) then
siftUp (a.swap i p hi (heapParent_lt_size a i hi hpos)) p
else
a
else
a
else
a
⋯
CSLibExt/Algorithms/Lean/DataStructures/BinaryHeap.lean:193
Uses 11 · Used by 7
TheoremSuccessful extraction from an indexed min queue#✓fully proved
Let \(q\) be an indexed min queue over a linear order \(W\) with identities in \(\{0, \dots, n-1\}\), and suppose that extracting the minimum of \(q\) returns the heap entry \(e = (k, u)\), with key \(k \in W \cup \{\top\}\) and identity \(u\), together with the queue \(q'\). Then binary min-heap extraction on the heap of \(q\) returns \(e\) together with the heap of \(q'\); the position vector of \(q'\) records no slot for \(u\); and every identity \(w \neq u\) has a recorded slot in \(q'\) if and only if it has one in \(q\).
theorem extractMin_ret {W : Type u} [LinearOrder W] {n : Nat}
(q q' : IndexedMinQueue W n) (entry : WithTop W ×ₗ Fin n)
(h : (extractMin q).ret = some (entry, q')) :
q.heap.extractMin = some (entry, q'.heap) ∧
q'.position[(ofLex entry).2] = none ∧
∀ w : Fin n, w ≠ (ofLex entry).2 →
q'.position[w].isSome = q.position[w].isSome
structure IndexedMinQueue (W : Type u) [LinearOrder W] (n : Nat) where
heap : Cslib.Algorithms.Lean.MinHeap (WithTop W ×ₗ Fin n)
position : Vector (Option (Fin n)) n
capacity : heap.data.size ≤ n
inverse : ∀ (v i : Fin n), position[v] = some i ↔
∃ hi : i.val < heap.data.size, (ofLex (heap.data[i.val]'hi)).2 = v
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:42
@[no_expose] def extractMin {W : Type u} [LinearOrder W] {n : Nat}
(q : IndexedMinQueue W n) :
TimeM (Fin 5 → Nat)
(Option ((WithTop W ×ₗ Fin n) × IndexedMinQueue W n)) :=
if hempty : q.heap.data.size = 0 then
⟨none, 0⟩
else
have hne : 0 < q.heap.data.size := Nat.pos_of_ne_zero hempty
let entry := q.heap.data[0]'hne
let v := (ofLex entry).2
if hone : q.heap.data.size = 1 then
let position := q.position.set v none
⋯
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:552
Uses 19 · Used by 7
TheoremLogarithmic event bound for indexed-queue insertion#✓fully proved
Let \(W\) be a linearly ordered type and let \(W \cup \{\top\}\) be \(W\) with a new greatest element \(\top\) adjoined. Let \(q\) be an indexed minimum queue over the identities \(0, \dots, n-1\) with keys in \(W \cup \{\top\}\) whose heap has \(s\) entries, let \(v < n\) be an identity and let \(k \in W \cup \{\top\}\) be a key. For each of the five counted events (comparisons, swaps, position reads, position writes, and entry appends, pops or replacements), the number of times that event occurs when inserting \(v\) with key \(k\) into \(q\) is at most \(20 (\lfloor \log_2 (s + 1) \rfloor + 1)\).
theorem insert_time {W : Type u} [LinearOrder W] {n : Nat}
(q : IndexedMinQueue W n) (v : Fin n) (key : WithTop W) (c : Fin 5) :
(insert q v key).time c ≤ 20 * (Nat.log2 (q.heap.data.size + 1) + 1)
structure IndexedMinQueue (W : Type u) [LinearOrder W] (n : Nat) where
heap : Cslib.Algorithms.Lean.MinHeap (WithTop W ×ₗ Fin n)
position : Vector (Option (Fin n)) n
capacity : heap.data.size ≤ n
inverse : ∀ (v i : Fin n), position[v] = some i ↔
∃ hi : i.val < heap.data.size, (ofLex (heap.data[i.val]'hi)).2 = v
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:42
@[no_expose] def insert {W : Type u} [LinearOrder W] {n : Nat}
(q : IndexedMinQueue W n) (v : Fin n) (key : WithTop W) :
TimeM (Fin 5 → Nat) (Option (IndexedMinQueue W n)) :=
if hpresent : q.position[v].isSome = true then
⟨none, event 2⟩
else
have habsent : q.position[v] = none := by
simpa [Option.isSome_iff_ne_none] using hpresent
have hspare : q.heap.data.size < n := absent_spare q v habsent
let entry := toLex (key, v)
let a := q.heap.data.push entry
let position := q.position.set v (some ⟨q.heap.data.size, hspare⟩)
⋯
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:453
Uses 9 · Used by 2
TheoremLogarithmic event bound for indexed-queue decrease-key#✓fully proved
Let \(W\) be a linearly ordered type and let \(W \cup \{\top\}\) be \(W\) with a new greatest element \(\top\) adjoined. Let \(q\) be an indexed minimum queue over the identities \(0, \dots, n-1\) with keys in \(W \cup \{\top\}\) whose heap has \(s\) entries, let \(v < n\) be an identity and let \(k \in W\) be a key. For each of the five counted events (comparisons, swaps, position reads, position writes, and entry appends, pops or replacements), the number of times that event occurs when decreasing the key of \(v\) to \(k\) in \(q\) is at most \(20 (\lfloor \log_2 (s + 1) \rfloor + 1)\).
theorem decreaseKey_time {W : Type u} [LinearOrder W] {n : Nat}
(q : IndexedMinQueue W n) (v : Fin n) (key : W) (c : Fin 5) :
(decreaseKey q v key).time c ≤ 20 * (Nat.log2 (q.heap.data.size + 1) + 1)
structure IndexedMinQueue (W : Type u) [LinearOrder W] (n : Nat) where
heap : Cslib.Algorithms.Lean.MinHeap (WithTop W ×ₗ Fin n)
position : Vector (Option (Fin n)) n
capacity : heap.data.size ≤ n
inverse : ∀ (v i : Fin n), position[v] = some i ↔
∃ hi : i.val < heap.data.size, (ofLex (heap.data[i.val]'hi)).2 = v
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:42
@[no_expose] def decreaseKey {W : Type u} [LinearOrder W] {n : Nat}
(q : IndexedMinQueue W n) (v : Fin n) (key : W) :
TimeM (Fin 5 → Nat) (Option (IndexedMinQueue W n)) :=
match hp : q.position[v] with
| none => ⟨none, event 2⟩
| some i =>
have hi : i.val < q.heap.data.size := (q.inverse v i).1 hp |>.choose
let old := q.heap.data[i.val]'hi
if hlt : (↑key : WithTop W) < (ofLex old).1 then
have hid : (ofLex old).2 = v := (q.inverse v i).1 hp |>.choose_spec
let a := q.heap.data.set i.val (toLex ((↑key : WithTop W), v)) hi
have hinv : Inverse a q.position :=
⋯
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:523
Uses 11 · Used by 1
TheoremLogarithmic event bound for indexed-queue extract-min#✓fully proved
Let \(q\) be an indexed minimum queue whose heap has \(s\) entries. For each of the five counted events (comparisons, swaps, position reads, position writes, and entry appends, pops or replacements), the number of times that event occurs when extracting the minimum of \(q\) is at most \(20 (\lfloor \log_2 (s + 1) \rfloor + 1)\).
theorem extractMin_time {W : Type u} [LinearOrder W] {n : Nat}
(q : IndexedMinQueue W n) (c : Fin 5) :
(extractMin q).time c ≤ 20 * (Nat.log2 (q.heap.data.size + 1) + 1)
structure IndexedMinQueue (W : Type u) [LinearOrder W] (n : Nat) where
heap : Cslib.Algorithms.Lean.MinHeap (WithTop W ×ₗ Fin n)
position : Vector (Option (Fin n)) n
capacity : heap.data.size ≤ n
inverse : ∀ (v i : Fin n), position[v] = some i ↔
∃ hi : i.val < heap.data.size, (ofLex (heap.data[i.val]'hi)).2 = v
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:42
@[no_expose] def extractMin {W : Type u} [LinearOrder W] {n : Nat}
(q : IndexedMinQueue W n) :
TimeM (Fin 5 → Nat)
(Option ((WithTop W ×ₗ Fin n) × IndexedMinQueue W n)) :=
if hempty : q.heap.data.size = 0 then
⟨none, 0⟩
else
have hne : 0 < q.heap.data.size := Nat.pos_of_ne_zero hempty
let entry := q.heap.data[0]'hne
let v := (ofLex entry).2
if hone : q.heap.data.size = 1 then
let position := q.position.set v none
⋯
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:552
Uses 16 · Used by 1
TheoremEvent bound for building an indexed queue by repeated insertion#✓fully proved
Let \(W\) be a linearly ordered type and let \(W \cup \{\top\}\) be \(W\) with a new greatest element \(\top\) adjoined. Let \(q_0, \dots, q_n\) be indexed minimum queues over the identities \(0, \dots, n-1\) with keys in \(W \cup \{\top\}\), and let \(k_0, \dots, k_{n-1}\) be keys in \(W \cup \{\top\}\). Suppose \(q_0\) is the empty queue and, for each \(i < n\), inserting identity \(i\) with key \(k_i\) into \(q_i\) succeeds and returns \(q_{i+1}\). Then for each of the five counted events (comparisons, swaps, position reads, position writes, and entry appends, pops or replacements), the total number of times that event occurs over these \(n\) insertions is at most \(20 n (\lfloor \log_2 (n + 1) \rfloor + 1)\).
theorem repeated_insert_time {W : Type u} [LinearOrder W] {n : Nat}
(qs : Fin (n + 1) → IndexedMinQueue W n) (keys : Fin n → WithTop W)
(hstart : qs 0 = empty (W := W) n)
(hsteps : ∀ i : Fin n,
(insert (qs i.castSucc) i (keys i)).ret = some (qs i.succ))
(c : Fin 5) :
(∑ i : Fin n, (insert (qs i.castSucc) i (keys i)).time c) ≤
20 * n * (Nat.log2 (n + 1) + 1)
structure IndexedMinQueue (W : Type u) [LinearOrder W] (n : Nat) where
heap : Cslib.Algorithms.Lean.MinHeap (WithTop W ×ₗ Fin n)
position : Vector (Option (Fin n)) n
capacity : heap.data.size ≤ n
inverse : ∀ (v i : Fin n), position[v] = some i ↔
∃ hi : i.val < heap.data.size, (ofLex (heap.data[i.val]'hi)).2 = v
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:42
def empty {W : Type u} [LinearOrder W] (n : Nat) : IndexedMinQueue W n where
heap := MinHeap.empty
position := Vector.replicate n none
capacity := by simp [MinHeap.empty]
inverse := by simp [MinHeap.empty]
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:441
@[no_expose] def insert {W : Type u} [LinearOrder W] {n : Nat}
(q : IndexedMinQueue W n) (v : Fin n) (key : WithTop W) :
TimeM (Fin 5 → Nat) (Option (IndexedMinQueue W n)) :=
if hpresent : q.position[v].isSome = true then
⟨none, event 2⟩
else
have habsent : q.position[v] = none := by
simpa [Option.isSome_iff_ne_none] using hpresent
have hspare : q.heap.data.size < n := absent_spare q v habsent
let entry := toLex (key, v)
let a := q.heap.data.push entry
let position := q.position.set v (some ⟨q.heap.data.size, hspare⟩)
⋯
CSLibExt/Algorithms/Lean/DataStructures/IndexedMinQueue/Basic.lean:453
Uses 9
Loading dependency explorer…
The dependency explorer needs JavaScript and its graph data.