1 (** {1 VerifyThis @ ETAPS 2019 competition Challenge 2: Cartesian Trees }
3 Author: Quentin Garchery (LRI, Université Paris Sud)
12 (** {2 PART A : All nearest smaller value} *)
14 clone list.Sorted as Decr with type t = int, predicate le = (>=)
16 (** Implement the stack with a list *)
18 let function destruct l
19 requires { not is_nil l }
22 | Cons h t -> h, t end
25 requires { not is_nil l }
26 ensures { mem result l }
28 let h, _ = destruct l in
32 requires { not is_nil l }
34 let _, t = destruct l in
37 lemma destruct_peek_tail :
38 forall l : list 'a. not is_nil l -> l = Cons (peek l) (tail l)
40 (** Compute the sequence of left neighbors *)
42 let smaller_left (s : array int) : array int
43 (* Task 1 : left neighbor has smaller index *)
44 ensures { forall y. 0 <= y < s.length -> result[y] < y }
45 (* Task 2 : left neighbor has smaller value *)
46 ensures { forall y. 0 <= y < s.length -> 0 <= result[y] ->
48 (* Task 3 : no smaller value between an element and its left neighbor *)
49 ensures { forall x z. 0 <= x < s.length ->
50 result[x] < z < x -> s[z] >= s[x] }
51 ensures { result.length = s.length }
54 let left = make n (-1) in
55 let ref my_stack = Nil in
56 for x = 0 to s.length - 1 do
57 (* To show that the access are correct *)
58 invariant { forall z. mem z my_stack -> 0 <= z < x }
59 (* Good formation of the stack *)
60 invariant { is_nil my_stack -> x = 0 }
61 invariant { not is_nil my_stack -> peek my_stack = x-1 }
62 invariant { Decr.sorted my_stack }
64 invariant { forall y. 0 <= y < x -> left[y] < y }
66 invariant { forall y. 0 <= y < x -> 0 <= left[y] ->
68 (* Show that we only need to look in the stack to find the nearest smaller value *)
69 invariant { forall z. 0 <= z < x ->
70 exists y. z <= y < x /\ mem y my_stack /\ s[y] <= s[z] }
72 invariant { forall y z. 0 <= y < x -> left[y] < z < y ->
75 while not is_nil my_stack && s[peek my_stack] >= s[x] do
76 (* Good formation of the stack *)
77 invariant { forall z. mem z my_stack -> 0 <= z < x }
78 invariant { Decr.sorted my_stack }
79 (* Remember that what was removed from the stack was too big *)
80 invariant { forall z. mem z (my_stack at BeforeLoop) ->
81 s[z] >= s[x] \/ mem z my_stack }
82 (* Make sure that stack elements at the right of the current top of the stack
83 were previously removed *)
84 invariant { forall z. not is_nil my_stack ->
85 mem z my_stack -> z <= peek my_stack }
87 invariant { forall z. not is_nil my_stack ->
88 peek my_stack < z < x -> s[z] >= s[x] }
89 invariant { forall z. is_nil my_stack -> 0 <= z < x ->
91 variant { Length.length my_stack }
92 my_stack <- tail my_stack
94 assert { not is_nil my_stack -> s[peek my_stack] < s[x] };
97 else left[x] <- peek my_stack;
98 assert { 0 <= left[x] -> s[left[x]] < s[x] };
99 my_stack <- Cons x my_stack
103 (** Same thing but for closest smaller right value :
104 when there is no such value, return an integer greater than the length *)
106 val smaller_right (s : array int) : array int
107 (* Task 1 : right neighbor has greater index *)
108 ensures { forall y. 0 <= y < s.length -> result[y] > y }
109 (* Task 2 : right neighbor has smaller value *)
110 ensures { forall y. 0 <= y < s.length -> result[y] < s.length ->
111 s[result[y]] < s[y] }
112 (* Task 3 : no smaller value between an element and its right neighbor *)
113 ensures { forall x z. 0 <= x < s.length ->
114 x < z < result[x] -> s[z] >= s[x] }
115 ensures { result.length = s.length }
118 (** {2 PART B : Construction of a Cartesian Tree} *)
123 type dir = { left : option int;
126 type dirs = array dir
128 predicate parent (t : dirs) (p s : int) =
129 t[p].left = Some s \/ t[p].right = Some s
131 inductive descendant dirs int int =
132 | Self : forall t p s. p = s -> descendant t p s
133 | Son_left : forall t p s1 s2. descendant t p s1 -> t[s1].left = Some s2 ->
135 | Son_right : forall t p s1 s2. descendant t p s1 -> t[s1].right = Some s2 ->
138 predicate is_smallest (a : array int) (i : int) =
140 forall j. 0 <= j < a.length -> a[i] <= a[j]
142 (** Construct an array storing the eventual sons of a node *)
144 let construct_dirs (a : array int) : dirs
145 requires { forall i j. 0 <= i < j < a.length -> a[i] <> a[j] }
146 ensures { result.length = a.length }
147 (* Task 2 ++, heap property :
148 left and right sons have greater value than the parent
149 left son is on the left in the array, right son is on the right
150 between indices of parent and son there is no smaller value *)
151 ensures { forall j v. 0 <= j < a.length ->
152 (result[j].left = Some v ->
153 a[v] > a[j] /\ 0 <= v < j /\ forall x. v < x < j -> a[x] > a[j]) /\
154 (result[j].right = Some v ->
155 a[v] > a[j] /\ j < v < a.length /\ forall x. j < x < v -> a[x] > a[j]) }
156 ensures { forall p s. 0 <= p < a.length -> descendant result p s ->
157 0 <= s < a.length /\ a[s] >= a[p] }
158 (* Task3, in-order traversal :
159 every "left-descendant" is located on the left in the array
160 every "right-descendant" is located on the right in the array *)
161 ensures { forall p1 p2 s. 0 <= p1 < a.length -> descendant result p2 s ->
162 (result[p1].left = Some p2 -> s < p1) /\
163 (result[p1].right = Some p2 -> s > p1) }
164 (* Task 1, well-formedness *)
165 (* Every non-minimal element has a parent *)
166 ensures { forall i k. 0 <= i < a.length -> 0 <= k < a.length -> a[k] < a[i] ->
167 exists sm. 0 <= sm < a.length /\ parent result sm i }
168 ensures { forall i. 0 <= i < a.length ->
170 (exists sm. 0 <= sm < a.length /\ parent result sm i)) }
171 (* Every element has at most one parent *)
172 ensures { forall p1 p2 s. 0 <= p1 < a.length -> 0 <= p2 < a.length -> 0 <= s < a.length ->
173 parent result p1 s -> parent result p2 s -> p1 = p2 }
175 ensures { forall p1 p2 s. 0 <= p1 < a.length -> 0 <= p2 < a.length -> 0 <= s < a.length ->
176 parent result p1 p2 -> descendant result p2 s -> p1 <> s }
179 let s_left = smaller_left a in
180 let s_right = smaller_right a in
181 let dirs = Array.make n {left = None; right = None} in
184 invariant { forall j v. 0 <= j < a.length ->
185 (dirs[j].left = Some v ->
186 a[v] > a[j] /\ 0 <= v < j /\ forall x. v < x < j -> a[x] >= a[j]) /\
187 (dirs[j].right = Some v ->
188 a[v] > a[j] /\ j < v < a.length /\ forall x. j < x < v -> a[x] >= a[j]) }
189 (* Show that once a parent is set-up in <dirs>, it does not change *)
190 invariant { forall j. 0 <= j < i ->
191 if s_left[j] >= 0 && s_right[j] >= n
192 then dirs[s_left[j]].right = Some j
193 else if s_left[j] < 0 && s_right[j] < n
194 then dirs[s_right[j]].left = Some j
195 else if s_left[j] >= 0 && s_right[j] < n
196 then if a[s_left[j]] > a[s_right[j]]
197 then dirs[s_left[j]].right = Some j
198 else dirs[s_right[j]].left = Some j
201 invariant { forall j p. 0 <= j < a.length -> 0 <= p < a.length ->
202 (dirs[p].right = Some j -> p = s_left[j] /\
203 (s_right[j] < n -> a[s_left[j]] > a[s_right[j]]) ) /\
204 (dirs[p].left = Some j -> p = s_right[j] /\
205 (s_left[j] >= 0 -> a[s_left[j]] <= a[s_right[j]])) }
206 let li = s_left[i] in
207 let ri = s_right[i] in
210 then if a[li] > a[ri]
211 then dirs[li] <- { dirs[li] with right = Some i }
212 else dirs[ri] <- { dirs[ri] with left = Some i }
213 else dirs[li] <- { dirs[li] with right = Some i }
215 then dirs[ri] <- { dirs[ri] with left = Some i }
220 (** The function <par> finds the parent of a node and is used to define <all_descendant_root>.
221 This last lemma function is useful to show that every node is reachable from the root *)
223 let par (a : array int) (dirs : array dir) (j : int)
224 requires { exists sm. 0 <= sm < a.length /\ parent dirs sm j }
225 requires { a.length = dirs.length }
226 requires { forall j v. 0 <= j < a.length ->
227 (dirs[j].left = Some v ->
228 a[v] > a[j] /\ 0 <= v < j /\ forall x. v < x < j -> a[x] > a[j]) /\
229 (dirs[j].right = Some v ->
230 a[v] > a[j] /\ j < v < a.length /\ forall x. j < x < v -> a[x] > a[j]) }
231 ensures { 0 <= result < a.length }
232 ensures { parent dirs result j }
234 assert { not a.length = 0 };
236 for i = 0 to a.length - 1 do
237 invariant { 0 <= res < a.length }
238 invariant { parent dirs res j \/ exists sm. i <= sm < a.length /\ parent dirs sm j }
239 match dirs[i].left with
240 | Some jl -> if jl = j then res <- i
243 match dirs[i].right with
244 | Some jr -> if jr = j then res <- i
251 let rec lemma all_descendant_root a dirs root j
252 variant { a[j] - a[root] }
253 requires { a.length = dirs.length }
254 requires { forall j v. 0 <= j < a.length ->
255 (dirs[j].left = Some v ->
256 a[v] > a[j] /\ 0 <= v < j /\ forall x. v < x < j -> a[x] > a[j]) /\
257 (dirs[j].right = Some v ->
258 a[v] > a[j] /\ j < v < a.length /\ forall x. j < x < v -> a[x] > a[j]) }
259 requires { forall i j. 0 <= i < j < a.length -> a[i] <> a[j] }
260 requires { 0 <= j < a.length /\ 0 <= root < a.length }
261 requires { is_smallest a root }
262 requires { forall i. 0 <= i < a.length ->
264 (exists sm. 0 <= sm < a.length /\ parent dirs sm i)) }
265 ensures { descendant dirs root j }
268 then all_descendant_root a dirs root (par a dirs j)
270 (** Finds the root of the direction tree : it's the smallest element in the array *)
273 ensures { match result with
274 | Some mv -> is_smallest a mv
275 | None -> a.length = 0
278 for i = 0 to a.length - 1 do
279 invariant { match m with
280 | Some mv -> 0 <= mv < a.length /\ forall j. 0 <= j < i -> a[mv] <= a[j]
284 | Some mv -> if a[mv] > a[i] then m <- Some i
290 (** The other way to define descendant. Useful here because it follows the definition of
293 lemma other_descendant :
294 forall t p1 p2 s. parent t p1 p2 -> descendant t p2 s ->
297 lemma inv_other_descendant :
298 forall t p1 s. descendant t p1 s ->
300 exists p2. parent t p1 p2 /\ descendant t p2 s
302 clone list.Sorted as StrictIncr with type t = int, predicate le = (<)
304 (** In-order traversal, we store the indices we traversed *)
306 let rec traversal (a : array int) dirs top (ghost s : int) (ghost e)
308 requires { dirs.length = a.length }
309 requires { 0 <= s <= e <= a.length }
310 requires { forall p1 p2 s. 0 <= p1 < a.length -> descendant dirs p2 s ->
311 (dirs[p1].left = Some p2 -> s < p1) /\
312 (dirs[p1].right = Some p2 -> s > p1) }
313 requires { forall i j. 0 <= i < j < a.length -> a[i] <> a[j] }
314 requires { match top with
315 | Some top -> forall son. descendant dirs top son <-> s <= son < e
316 | None -> s = e end }
317 ensures { forall x. mem x result <-> s <= x < e }
318 ensures { StrictIncr.sorted result }
323 assert { s <= top < e by descendant dirs top top };
324 let dir = dirs[top] in
325 traversal a dirs dir.left s top ++
327 traversal a dirs dir.right (top+1) e)
330 (** We traverse the tree <construct_dirs a> in-order from the root <find_smaller a>,
331 and we collect the indices. Last 2 arguments of <traversal> are ghost.
333 We show that the result is the list [0..(a.length-1)], the in-order traversal of
334 the tree traverses elements from 0 to (a.length-1)
338 requires { forall i j. 0 <= i < j < a.length -> a[i] <> a[j] }
339 ensures { forall x. mem x result <-> 0 <= x < a.length }
340 ensures { StrictIncr.sorted result }
342 traversal a (construct_dirs a) (find_smaller a) 0 a.length