-
Notifications
You must be signed in to change notification settings - Fork 0
/
counter_alt.mlw
99 lines (72 loc) · 2.58 KB
/
counter_alt.mlw
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
(* Abstract specification of a concurrent shared memory counter, assuming atomic updates
*)
module Counter
use export int.Int
use export map.Map
use export map.Const
type state = Start | Done
(* threads identified by numbers
*)
type thread = int
val constant n_threads : int
axiom n_threads_pos : n_threads > 0
(* System configurations
*)
type world = { pc : map thread state ; counter : int }
(* Inductive invariant
*)
(* Aux function - counts threads that terminated
*)
let rec function count (w:world) (n:int)
requires { 0 <= n <= n_threads }
ensures { 0 <= result <= n }
ensures { (forall t :thread. 0<=t<n -> w.pc[t]=Start) -> result = 0 }
ensures { (forall t :thread. 0<=t<n -> w.pc[t]=Done) -> result = n }
variant { n }
= if n=0 then 0
else let c = match w.pc[n-1] with | Start -> 0 | Done -> 1 end
in c + count w (n-1)
(* lemma about a pair of configurations
differing only in state of one thread.
Required for proving inductiveness of invariant
*)
let rec lemma count_lm (w1:world) (w2:world) (t:thread) (n:int)
requires { 0 <= n <= n_threads }
requires { 0 <= t < n_threads }
requires { forall t' :thread. 0<=t'<n_threads-> t'<>t -> w2.pc[t'] = w1.pc[t'] }
ensures { t<n /\ w1.pc[t] = Start /\ w2.pc[t] = Done -> count w2 n = count w1 n + 1 }
ensures { t<n /\ w2.pc[t] = Start /\ w1.pc[t] = Done -> count w1 n = count w2 n + 1 }
ensures { w1.pc[t] = w2.pc[t] \/ t>=n -> count w2 n = count w1 n }
variant { n }
= if n=0 then ()
else count_lm w1 w2 t (n-1)
predicate inv (w:world) =
w.counter = count w n_threads
(* System INIT
*)
predicate initWorld_p (w:world) = w.pc = const Start /\ w.counter=0
let ghost predicate initWorld (w:world) = initWorld_p w
(* System action
*)
predicate trans_enbld (w:world) (t:thread) =
0<=t<n_threads /\ w.pc[t] = Start
let ghost function trans (w:world) (t:thread) : world
requires { trans_enbld w t }
ensures { inv w -> inv result }
= { pc = set (w.pc) t Done ; counter = w.counter+1 }
(* Transition relation
*)
inductive stepind world world =
| trans : forall w :world, t :thread.
trans_enbld w t -> stepind w (trans w t )
let ghost predicate step (w1:world) (w2:world) = stepind w1 w2
(* Proof of inductiveness
*)
clone export inductiveness.Inductiveness with
type world,
predicate inv,
val step,
val initWorld
lemma correctness : forall w :world. reachable w ->
(forall t :thread. w.pc[t]=Done) -> w.counter=n_threads
end