mirror of
https://github.com/AdaCore/why3.git
synced 2026-02-12 12:34:55 -08:00
222 lines
5.2 KiB
Plaintext
222 lines
5.2 KiB
Plaintext
(*
|
|
|
|
"naive" version of insertion sort: makes too many assignments
|
|
|
|
see insertion_sort.mlw for a better version
|
|
|
|
*)
|
|
|
|
module InsertionSortNaive
|
|
|
|
use int.Int
|
|
use ref.Ref
|
|
use ref.Refint
|
|
use array.Array
|
|
use array.IntArraySorted
|
|
use array.ArrayPermut
|
|
|
|
let sort (a:array int)
|
|
ensures { sorted a }
|
|
ensures { permut_all (old a) a }
|
|
=
|
|
for i = 0 to a.length - 1 do
|
|
invariant { permut_all (old a) a }
|
|
invariant { sorted_sub a 0 i }
|
|
let j = ref i in
|
|
while !j > 0 && a[!j-1] > a[!j] do
|
|
invariant { 0 <= !j <= i }
|
|
invariant { permut_all (old a) a }
|
|
invariant { sorted_sub a 0 !j }
|
|
invariant { sorted_sub a !j (i+1) }
|
|
invariant { forall k1 k2:int. 0 <= k1 < !j /\ !j+1 <= k2 <= i ->
|
|
a[k1] <= a[k2] }
|
|
variant { !j }
|
|
label L in
|
|
let b = !j - 1 in
|
|
let t = a[!j] in
|
|
a[!j] <- a[b];
|
|
a[b] <- t;
|
|
assert { exchange (a at L) a (!j-1) !j };
|
|
decr j
|
|
done
|
|
done
|
|
|
|
|
|
end
|
|
|
|
|
|
module InsertionSortNaiveGen
|
|
|
|
use int.Int
|
|
use ref.Ref
|
|
use ref.Refint
|
|
use array.Array
|
|
use array.ArrayPermut
|
|
|
|
type elt
|
|
|
|
val predicate le elt elt
|
|
|
|
clone map.MapSorted as M with type elt = elt, predicate le = le
|
|
|
|
axiom le_refl: forall x:elt. le x x
|
|
|
|
axiom le_asym: forall x y:elt. not (le x y) -> le y x
|
|
|
|
axiom le_trans: forall x y z:elt. le x y /\ le y z -> le x z
|
|
|
|
predicate sorted_sub (a : array elt) (l u : int) =
|
|
M.sorted_sub a.elts l u
|
|
|
|
predicate sorted (a : array elt) =
|
|
M.sorted_sub a.elts 0 a.length
|
|
|
|
let sort (a:array elt)
|
|
ensures { sorted a }
|
|
ensures { permut_all (old a) a }
|
|
=
|
|
for i = 0 to a.length - 1 do
|
|
invariant { permut_all (old a) a }
|
|
invariant { sorted_sub a 0 i }
|
|
let j = ref i in
|
|
while !j > 0 && not (le a[!j-1] a[!j]) do
|
|
invariant { 0 <= !j <= i }
|
|
invariant { permut_all (old a) a }
|
|
invariant { sorted_sub a 0 !j }
|
|
invariant { sorted_sub a !j (i+1) }
|
|
invariant { forall k1 k2:int. 0 <= k1 < !j /\ !j+1 <= k2 <= i ->
|
|
le a[k1] a[k2] }
|
|
variant { !j }
|
|
label L in
|
|
let b = !j - 1 in
|
|
let t = a[!j] in
|
|
a[!j] <- a[b];
|
|
a[b] <- t;
|
|
assert { exchange (a at L) a (!j-1) !j };
|
|
decr j
|
|
done
|
|
done
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
module InsertionSortParam
|
|
|
|
use int.Int
|
|
use ref.Ref
|
|
use ref.Refint
|
|
use map.Map
|
|
use array.Array
|
|
use array.ArrayPermut
|
|
|
|
type param
|
|
|
|
type elt
|
|
|
|
val predicate le param elt elt
|
|
|
|
axiom le_refl: forall p:param, x:elt. le p x x
|
|
|
|
axiom le_asym: forall p:param, x y:elt. not (le p x y) -> le p y x
|
|
|
|
axiom le_trans: forall p:param, x y z:elt. le p x y /\ le p y z -> le p x z
|
|
|
|
(* a[l..u) is sorted for le *)
|
|
predicate sorted_sub (p:param) (a : Map.map int elt) (l u : int) =
|
|
forall i1 i2 : int. l <= i1 <= i2 < u -> le p (Map.get a i1) (Map.get a i2)
|
|
|
|
predicate sorted (p:param) (a : array elt) =
|
|
sorted_sub p a.elts 0 a.length
|
|
|
|
let sort (p:param) (a:array elt)
|
|
ensures { sorted p a }
|
|
ensures { permut_all (old a) a }
|
|
=
|
|
for i = 0 to a.length - 1 do
|
|
invariant { permut_all (old a) a }
|
|
invariant { sorted_sub p a.elts 0 i }
|
|
let j = ref i in
|
|
while !j > 0 && not (le p a[!j-1] a[!j]) do
|
|
invariant { 0 <= !j <= i }
|
|
invariant { permut_all (old a) a }
|
|
invariant { sorted_sub p a.elts 0 !j }
|
|
invariant { sorted_sub p a.elts !j (i+1) }
|
|
invariant { forall k1 k2:int. 0 <= k1 < !j /\ !j+1 <= k2 <= i ->
|
|
le p a[k1] a[k2] }
|
|
variant { !j }
|
|
label L in
|
|
let b = !j - 1 in
|
|
let t = a[!j] in
|
|
a[!j] <- a[b];
|
|
a[b] <- t;
|
|
assert { exchange (a at L) a (!j-1) !j };
|
|
assert { sorted_sub p a.elts (!j-1) (i+1) };
|
|
decr j
|
|
done
|
|
done
|
|
|
|
|
|
end
|
|
|
|
module InsertionSortParamBad
|
|
|
|
(* this version is hard to prove because predicate sorted_sub
|
|
applies to an array instead of a map *)
|
|
|
|
use int.Int
|
|
use ref.Ref
|
|
use ref.Refint
|
|
use map.Map
|
|
use array.Array
|
|
use array.ArrayPermut
|
|
|
|
type param
|
|
|
|
type elt
|
|
|
|
val predicate le param elt elt
|
|
|
|
axiom le_refl: forall p:param, x:elt. le p x x
|
|
|
|
axiom le_asym: forall p:param, x y:elt. not (le p x y) -> le p y x
|
|
|
|
axiom le_trans: forall p:param, x y z:elt. le p x y /\ le p y z -> le p x z
|
|
|
|
(* a[l..u) is sorted for le *)
|
|
predicate sorted_sub (p:param) (a : array elt) (l u : int) =
|
|
forall i1 i2 : int. l <= i1 <= i2 < u -> le p a[i1] a[i2]
|
|
|
|
predicate sorted (p:param) (a : array elt) =
|
|
sorted_sub p a 0 a.length
|
|
|
|
let sort (p:param) (a:array elt)
|
|
ensures { sorted p a }
|
|
ensures { permut_all (old a) a }
|
|
=
|
|
for i = 0 to a.length - 1 do
|
|
invariant { permut_all (old a) a }
|
|
invariant { sorted_sub p a 0 i }
|
|
let j = ref i in
|
|
while !j > 0 && not (le p a[!j-1] a[!j]) do
|
|
invariant { 0 <= !j <= i }
|
|
invariant { permut_all (old a) a }
|
|
invariant { sorted_sub p a 0 !j }
|
|
invariant { sorted_sub p a !j (i+1) }
|
|
invariant { forall k1 k2:int. 0 <= k1 < !j /\ !j+1 <= k2 <= i ->
|
|
le p a[k1] a[k2] }
|
|
variant { !j }
|
|
label L in
|
|
let b = !j - 1 in
|
|
let t = a[!j] in
|
|
a[!j] <- a[b];
|
|
a[b] <- t;
|
|
assert { exchange (a at L) a (!j-1) !j };
|
|
decr j
|
|
done
|
|
done
|
|
|
|
|
|
end
|