-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-- This needs Lean v4.24.0 and https://github.com/verse-lab/velvet/ added as a dependency in the lakefile.toml
-- https://github.com/verse-lab/velvet/blob/master/Velvet/Examples/Examples.lean
import Velvet.Std
set_option loom.semantics.termination "total"
set_option loom.semantics.choice "demonic"
attribute [grind] Array.multiset_swap
method insertionSort_total (mut A : Array ℤ) return (u : Unit)
require 1 ≤ A.size
ensures ∀ i j, 0 ≤ i ∧ i ≤ j ∧ j < A.size → A[i]! ≤ A[j]!
ensures AOld.toMultiset = A.toMultiset
do
let A' := A
let N := A.size
let mut i := 1
while i ≠ A.size
invariant A.size = N
invariant 1 ≤ i ∧ i ≤ A.size
invariant ∀ i' j', 0 ≤ i' ∧ i' < j' ∧ j' ≤ i - 1 → A[i']! ≤ A[j']!
invariant A.toMultiset = A'.toMultiset
decreasing A.size - i
do
let mut j := i
while j ≠ 0
invariant A.size = N
invariant j ≤ i
invariant ∀ i' j', 0 ≤ i' ∧ i' < j' ∧ j' ≤ i ∧ j' ≠ j → A[i']! ≤ A[j']!
invariant A.toMultiset = A'.toMultiset
decreasing j
do
if A[j]! < A[j - 1]! then
swap! A[j - 1]! A[j]!
j := j - 1
i := i + 1
return
set_option maxHeartbeats 1000000 in
prove_correct insertionSort_total by
loom_solve