-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathTreeOt.v
440 lines (388 loc) · 20.8 KB
/
TreeOt.v
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
Require Import Arith Commons ListTools Tree OtDef.
Section TreeOTDefinition.
Context {X : eqType} (cmd : Type) {ot : OTBase X cmd} {ip : OTInv _ _ ot}.
Inductive list_command : Type :=
| TreeInsert of nat & seq (tree X)
| TreeRemove of nat & seq (tree X)
| EditLabel of cmd.
Inductive tree_command : Type :=
| Atomic of list_command
| OpenRoot of nat & tree_command.
Fixpoint list_inv (c : list_command) :=
match c with
| TreeInsert n l => TreeRemove n l
| TreeRemove n l => if l is [::] then TreeInsert 0 [::] else TreeInsert n l
| EditLabel c => EditLabel (@inv X cmd ot ip c)
end.
Fixpoint tree_inv (c : tree_command) :=
match c with
| Atomic c => Atomic (list_inv c)
| OpenRoot n c => OpenRoot n (tree_inv c)
end.
Definition list_interp (op1 : list_command) (tr : tree_eqType X) : option (tree X) :=
match tr with Node x ls =>
match op1 with
| TreeInsert n l => NodeW x (ins n l ls)
| TreeRemove n l => NodeW x (rm n l ls)
| EditLabel c => match @interp X cmd ot c x with Some x' => Some (Node x' ls) | _ => None end
end
end.
Fixpoint tree_interp (op1 : tree_command) (tr : tree_eqType X) : option (tree X) :=
match tr with Node x ls =>
match op1 with
| OpenRoot n c => NodeW x (rplc n (bind (tree_interp c) (nth n ls)) ls)
| Atomic c => list_interp c tr
end
end.
Definition tr_ins (len : nat) (n1 n2 : nat) :=
if (n1 < n2) then n1 else n1 + len.
Definition tr_rem (len : nat) (n1 n2 : nat) :=
if (n1 < n2) then Some n1 else if (n1 >= n2 + len) then Some (n1 - len) else None.
Definition list_it (op1 op2 : list_command) (flag : bool) : seq list_command :=
match op1, op2 with
| EditLabel c1, EditLabel c2 => map EditLabel (it c1 c2 flag)
| EditLabel _, _ | _, EditLabel _ => [:: op1]
| TreeInsert n1 l1, TreeInsert n2 l2 =>
if (n1 == n2) then (if flag then [:: op1] else [:: TreeInsert (n1 + size l2) l1])
else [:: TreeInsert (tr_ins (size l2) n1 n2) l1]
| TreeInsert n1 l1, TreeRemove n2 l2 =>
let len := size l2 in
if (n1 <= n2) then [:: op1] else (if (n1 >= n2 + len) then [:: TreeInsert (n1 - len) l1] else nil)
| TreeRemove n1 l1, TreeRemove n2 l2 =>
let (len1, len2) := (size l1, size l2) in
if n2 + len2 <= n1 then [:: TreeRemove (n1 - len2) l1]
else if n1 + len1 <= n2 then [:: TreeRemove n1 l1]
else if n2 <= n1 then [:: TreeRemove n2 (cut l1 0 (len2 + n2 - n1))]
else [:: TreeRemove n1 (cut l1 (n2 - n1) len2)]
| TreeRemove n1 l1, TreeInsert n2 l2 =>
let (len1, len2) := (size l1, size l2) in
if (n1 + len1 <= n2) then [:: op1]
else if (n2 <= n1) then [:: TreeRemove (n1 + len2) l1]
else match ins (n2 - n1) l2 l1 with
| Some l1' => [:: TreeRemove n1 l1']
| None => [:: op1] (* <- this branch is unused *)
end
end.
Fixpoint tree_it (op1 op2 : tree_command) (flag : bool) : seq tree_command :=
match op1, op2 with
| Atomic c1, Atomic c2 => map Atomic (list_it c1 c2 flag)
| OpenRoot n1 tc1, OpenRoot n2 tc2 =>
if n1 == n2 then map (OpenRoot n1) (tree_it tc1 tc2 flag) else [:: op1]
| Atomic (TreeRemove n1 l1), OpenRoot n2 tc2 =>
match tr_rem (size l1) n2 n1 with
None => let i := n2 - n1 in
match rplc i ((bind (tree_interp tc2)) (nth i l1)) l1 with
| Some l1' => [:: Atomic (TreeRemove n1 l1')]
| _ => [:: op1]
end
| _ => [:: op1]
end
| OpenRoot n1 tc1, Atomic (TreeInsert n2 l2) => [:: OpenRoot (tr_ins (size l2) n1 n2) tc1]
| OpenRoot n1 tc1, Atomic (TreeRemove n2 l2) =>
match tr_rem (size l2) n1 n2 with
| Some n1' => [:: OpenRoot n1' tc1]
| None => nil
end
| _, _ => [:: op1]
end.
Ltac inspect_nodew := repeat let x := fresh "HN" in let y := fresh "HN" in
match goal with
| |- (NodeW _ _ = Some (Node _ _) -> _) => rewrite nodew_some => [] [] x y; rewrite x - y
| |- (Some (Node _ _) = NodeW _ _ -> _) => rewrite nodew_someS => [] [] x y; rewrite - x y
end.
Lemma Atomic_map_if f o1 o2: map Atomic (if f then o1 else o2) = if f then map Atomic o1 else map Atomic o2.
by destruct f. Qed.
Ltac interp_simpl :=
rewrite ?Atomic_map_if //= /foldl /flip /= /tr_ins ?orm_id ?rm_id ?orplc_some ?oins_some ?orm_some.
Ltac interp_simpl_nw := interp_simpl; inspect_nodew.
(* Auxilary arithmetic lemmas *)
Lemma arithm1 {x y z} : x + z <= y -> y <= x = false -> y = y - z + z /\ x <= y - z.
Proof. move=> H1 H2.
by move: (H1) => /(leq_sub2r z); rewrite -addnBA // subnn addn0;
move: H1 => /(leq_trans (leq_addl _ z)) /subnK.
Qed.
Lemma arithm1' {x y z} : x + z <= y -> y < x = false -> y = y - z + z /\ x <= y - z.
Proof. move=> H1 H2.
by move: (H1) => /(leq_sub2r z); rewrite -addnBA // subnn addn0;
move: H1 => /(leq_trans (leq_addl _ z)) /subnK.
Qed.
Lemma arithm2 {x y z} : y + z <= x -> x = z + (x - z) /\ y <= (x - z).
Proof. move=> H1.
move: (H1) => /(leq_trans (leq_addl _ z)) /subnK.
by move: H1 => /(leq_sub2r z); rewrite -addnBA ?subnn ?addn0 1?addnC; [|exact: leqnn].
Qed.
Lemma foldl_openroot (x : X) xs cs n: n < size xs ->
(exec_all tree_interp) (Some (Node x xs)) [seq OpenRoot n i | i <- cs]
= NodeW x (rplc n ((exec_all tree_interp) (nth n xs) cs) xs).
Proof. elim: cs xs => [|c cs IHcs] xs /=.
+ case Hnth: nth => [y|]; rewrite -Hnth; move: Hnth.
* by move=> /rplc_nth_id' ->.
* by move /nth_noneP; rewrite ltnNge; case: leq.
+ move=> Hsz. rewrite ?/flip => /=.
move A0: (bind (tree_interp c) (nth n xs)) => [t|] /=.
+ case A1: rplc => [t'|] /=.
rewrite IHcs.
* move: (A1) => /rplc_nth_eq ->.
case: exec_all => /= [a|]; last by rewrite ?rplc_none_none /=.
move: A1. rewrite ?orplc_some => <-. by rewrite rplc_rplcC_eq.
* by move: A1 A0 => /rplc_some_len <-; rewrite ltnNge; case: nth (nth_noneP n xs) => ? [].
+ by move: A1 A0 => /rplc_none_case [] // /nth_noneP ->.
+ by rewrite rplc_none_none ?exec_all_none rplc_none_none. Qed.
Lemma foldl_editroot (x : X) xs cs:
(exec_all tree_interp) (Some (Node x xs)) [seq Atomic (EditLabel i) | i <- cs] =
match ((exec_all interp) (Some x) cs) with
| Some x' => Some (Node x' xs)
| None => None
end.
Proof. elim: cs x xs => [|c cs IHcs] x xs //=. rewrite /flip /=.
case Hint: interp => [x'|] //. by rewrite ?exec_all_none. Qed.
Lemma insert_remove_commutation:
forall n1 l1 x ls (m1 m2 : tree X) (f g: bool) (n : nat) l,
NodeW x (ins n1 l1 ls) = Some m1 ->
NodeW x (rm n l ls) = Some m2 ->
(exec_all tree_interp) (Some m2)
(tree_it (Atomic (TreeInsert n1 l1)) (Atomic (TreeRemove n l)) f) =
(exec_all tree_interp) (Some m1)
(tree_it (Atomic (TreeRemove n l)) (Atomic (TreeInsert n1 l1)) g)
/\ exists os, (exec_all tree_interp) (Some m2)
(tree_it (Atomic (TreeInsert n1 l1)) (Atomic (TreeRemove n l)) f) = Some os.
Proof. move => n1 l1 x ls [x1 ls1] [x2 ls2] _ _ n2 l2 //=;
case H1: (n2 + size l2 <= n1); case H2: (n1 <= n2).
- case: l2 H1 => [|y2 ys2] //= H1; interp_simpl_nw => /=;
first (move: HN0 => /= ->; split => //; by exists (Node x2 ls1)).
move: H1; rewrite addnS => /(ltn_addr (size ys2)); rewrite ltnNge;
move: H2; by rewrite -(leq_add2r (size ys2)) => ->.
- interp_simpl_nw; move: (arithm1 H1 H2) HN0 HN2 => [] {2 4}-> /rm_insC_bef A.
rewrite addnC => /A B /B [] <- [os] => ->. split => //. by exists (Node x2 os).
- interp_simpl. move: H2 => /rm_insC_aft A /nodew_some [] -> Heq'.
move:(Heq') =>/A B /nodew_some [] -> Heq''. move:(Heq'') => /B [].
rewrite addnC -Heq'' -Heq' /= =>-> [os] ->. split => //. by exists (Node x2 os).
- move: H2; rewrite leqNgt => /negbFE => H2;
move: H1; rewrite leqNgt => /negbFE => H1;
case Hins: (ins (n1 - n2)) => [rm_ins|]; interp_simpl_nw.
+ simpl; case Hins': ins => [rm_ins'|].
rewrite (rm_insC_in n2 n1 _ l1 _ rm_ins rm_ins') 1?ltnW //= => ->. split => //.
by exists (Node x2 ls2).
simpl in HN0; by rewrite HN0 in Hins'.
+ move: Hins H1 => /ins_noneP; rewrite ltn_subRL. maxapply ltn_trans. by rewrite ltnn. Qed.
Lemma remove_openroot_commutation :
forall n1 l1 x ls (m1 m2 : tree_eqType X) (f g: bool) (t : tree_command) (n : nat),
NodeW x (rm n1 l1 ls) = Some m1 ->
NodeW x (rplc n ((bind (tree_interp t)) (nth n ls)) ls) = Some m2 ->
(exec_all tree_interp) (Some m2)
(tree_it (Atomic (TreeRemove n1 l1)) (OpenRoot n t) f) =
(exec_all tree_interp) (Some m1)
(tree_it (OpenRoot n t) (Atomic (TreeRemove n1 l1)) g)
/\ exists os,
(exec_all tree_interp) (Some m2) (tree_it (Atomic (TreeRemove n1 l1)) (OpenRoot n t) f) = Some os.
Proof. move=> n1 l1 x ls [x1 ls1] [x2 ls2] _ _ t n2 //=; case Htr_rem: tr_rem => [n|].
+ interp_simpl_nw. move: Htr_rem; rewrite /tr_rem; case H1: (n2 < n1).
- move=> [] <-; rewrite (rm_some_nth_aft _ ls _ l1 n1) //.
move: HN2. case: (bind (tree_interp t)) => //= [a|]; last by rewrite rplc_none_none.
move => /rplc_some []. move => _1 _2; move: _2 _1 => _. move: HN0 => /=. move: H1.
maxapply (@rplc_rmC_bef (tree_eqType X)) => /(_ a) [] -> [os] -> /=. by eauto.
- case H2: (n1 + size l1 <= n2) => //. move=> [] <-;
move: (arithm1' H2 H1) HN2 => [] {2 3 4 5 8 9}-> Hleq.
simpl in HN0. rewrite (rm_some_nth_bef n1 ls _ l1 (n2 - size l1)) //.
case: (bind (tree_interp t)) => [a /=|]; last by rewrite orplc_none //=.
move=> /rplc_some []. move => _1 _2; move: _2 _1 => _. rewrite addnC. move: Hleq HN0.
maxapply (@rplc_rmC_aft (tree_eqType X)) => /(_ a) [] -> [os] -> /=. by eauto.
+ move: Htr_rem; rewrite /tr_rem; case H1: (n2 < n1) => //;
case H2: (n1 + size l1 <= n2) => // ?. move:H1 => /negbT. rewrite -leqNgt => H1;
move: H2 => /negbT. rewrite -ltnNge => H2. case Hrplc: (rplc (n2 - n1)) => [l1'|] //=;
interp_simpl_nw => /nodew_some [] <- Hrm_some;
move: (H1) (H2) => /subnKC {1 2 3}<-;
rewrite ltn_add2l => H2'; rewrite addnC (rm_some_nth_in ls1 l1) => //.
- inspect_nodew.
rewrite nodew_some; simpl in Hrm_some. rewrite (rplc_rmC_in ls1 _ l1) /=; try by eauto.
- by move: Hrplc; rewrite rplc_none_case; move: H2'; rewrite ltnNge => /negbTE -> /=;
case: (bind (tree_interp t)) => [? [] //|] //; rewrite rplc_none_none. Qed.
Lemma insert_openroot_commutation:
forall n1 l1 x ls (m1 m2 : tree X) (n : nat) (t : tree_command),
NodeW x (rplc n (bind (tree_interp t) (nth n ls)) ls) = Some m2 ->
NodeW x (ins n1 l1 ls) = Some m1 ->
flip tree_interp m2 (Atomic (TreeInsert n1 l1)) =
flip tree_interp m1
(OpenRoot (tr_ins (size l1) n n1) t)
/\ exists node, flip tree_interp m2 (Atomic (TreeInsert n1 l1)) = Some node.
Proof.
move=> n1 l1 x ls // [x1 ls1] [x2 ls2] n t /=. rewrite /flip /= /tr_ins.
case Hltn: (n < n1); [|move: Hltn; rewrite leqNgt ltnS => /negbFE Hltn];
rewrite ?nodew_some => [] [] <- Hrplc; move: (Hrplc);
rewrite (oins_some _ _ ls2) => <- [] <- => H2;
[rewrite (ins_some_nth_aft ls l1 n1) |
move: Hrplc; rewrite (ins_some_nth_bef ls1 l1 n1) // => Hrplc];
interp_simpl => //; rewrite -H2.
* move: H2 => /ins_some [] _. move: Hltn. move=> /rplc_insC_bef A /A B.
case: (bind (tree_interp t)) Hrplc => [ti_r|]. move: (B ti_r l1) => [] <- [os] ->.
split=> //. by exists (Node x os).
by rewrite orplc_some orplc_none.
* rewrite addnC addnC.
case: (bind (tree_interp t)) Hrplc => [ti_r|]; last by rewrite orplc_some orplc_none.
move: Hltn => /rplc_insC_aft A => /rplc_some [] /A B _.
move: (B ti_r l1) => [] -> [os] ->. split=> //. by exists (Node x os). Qed.
Theorem tree_c1 : forall (op1 op2 : tree_command) (f : bool) m (m1 m2 : tree X),
tree_interp op1 m = Some m1 -> tree_interp op2 m = Some m2 ->
(exec_all tree_interp) (Some m2) (tree_it op1 op2 f)
= (exec_all tree_interp) (Some m1) (tree_it op2 op1 (~~f)) /\
exists node, (exec_all tree_interp) (Some m2) (tree_it op1 op2 f) = Some node.
Proof.
Ltac solve_openroot := interp_simpl; let X1 := fresh "X1" in let X2 := fresh "X2" in
case X1: interp => [?|] // [] <- <-; rewrite nodew_some => [] [] <- ->;
case X2: interp => [?|] //; move: X1 X2 => -> // [] ->; eauto.
elim => [[n1 l1 | n1 l1 | c1 ]| n1 c1 IHl1] [[n2 l2 | n2 l2 | c2] | n2 c2]
=> f [x ls] [x1 ls1] [x2 ls2] //=.
(* Case op1 = insert *)
* case Heq: (n1 == n2); rewrite eq_sym Heq.
- case: f => /=; interp_simpl; move: Heq;
rewrite eqn_leq => /andP [] => H1 H2; inspect_nodew; rewrite addnC ?oins_some;
[move: H1| move: H2] => /ins_insC A; [move: HN2| move: HN0] => /= /ins_some [] _ /A A';
[move: (A' l1 l2)| move: (A' l2 l1)] => [] [] -> [os]; split => //; exists (Node x2 os);
by rewrite p.
- rewrite /tr_ins (ltnNge n2 n1) (leq_eqVlt n1 n2) Heq.
case Hn12: (n1 < n2) => /=; interp_simpl; inspect_nodew; rewrite addnC; move: Hn12;
[move=> /ltnW | rewrite ltnNge => /negbFE] => /ins_insC A;
[move: HN2| move: HN0] => /= /ins_some [] _ /A A'; [move: (A' l1 l2)| move: (A' l2 l1)];
move=> [] -> [os]; split => //; exists (Node x2 os); by rewrite p.
* move=> /insert_remove_commutation A /A B. move: (B f (~~ f)) => /= [] -> [os] ->.
split => //. by exists os.
* interp_simpl. case Hx: interp => [intx|] // Hins [] <- <-.
move: Hins => /nodew_some [] <- ->. split; by [rewrite Hx| exists (Node intx ls1)].
* move=> H1 /= /insert_openroot_commutation A. by move: H1 => /A.
(* Case op1 = remove *)
* move=> /insert_remove_commutation A /A B. move: (B (~~f) f) => [] -> [os] ->.
split => //. by exists os.
* case H1: (n2 + size l2 <= n1); case H2: (n1 + size l1 <= n2);
interp_simpl; inspect_nodew.
+ case: l1 HN0 H2 => [|y1 ys1] Hsome1 //=.
- case: l2 HN2 H1 => [|y2 ys2] Hsome2 //.
* rewrite ?addn0 => H' H''. move/andP: (conj H' H'').
rewrite -eqn_leq rm_id orm_id => /eqP -> /=. rewrite rm_id orm_id. split => //.
by exists (Node x2 ls).
* rewrite addn0 addnS => H'. move: (leq_trans H' (leq_addr (size ys2) _)).
by rewrite ltn_add2r ltnNge => /negP.
rewrite addnS => H'. move: (leq_trans H' (leq_addr (size ys1) _)). rewrite ltn_add2r.
move: (leq_trans H1 (leq_addr (size l2) _)). by rewrite leq_add2r leqNgt => /negP.
+ move: (arithm2 H1) HN0 HN2 => [] {2}-> /rm_rmC A/A B/B [].
move: H1 => /leq_addWl /(addnBA (size l2)) ->. rewrite addnC.
rewrite -addnBA; last exact: (leqnn _). rewrite subnn addn0 /= => -> [os] -> /=. by eauto.
+ move: (arithm2 H2) HN0 HN2 => [] {2}-> /rm_rmC A/A B/B [].
move: H2 => /leq_addWl /(addnBA (size l1)) ->. rewrite addnC.
rewrite -addnBA; last exact: (leqnn _). rewrite subnn addn0 /= => -> [os] -> /=. by eauto.
+ case H3: (n2 <= n1); case H4: (n1 <= n2) => /=; rewrite /bind /flip /tree_interp;
rewrite ?orm_some; interp_simpl; inspect_nodew; move: HN0 HN2.
- move/andP: (conj H3 H4). rewrite -eqn_leq => /eqP ->.
move=> /rm_cut A /A B. move: (B (leqnn _) (leq_addr _ _)).
rewrite addnC subnn => [] [] /= -> [os]. rewrite -subnBA; last exact: (leqnn _).
rewrite subnn subn0 => -> /=. by eauto.
- move => _1 _2; move: _2 _1. move=> /rm_cut A /A B. move: H1 => /negbT. rewrite -ltnNge => /ltnW => /B C.
move: (C H3) => []. rewrite addnC => -> [os] -> /=. by eauto.
- move=> /rm_cut A /A B. move: H2 => /negbT. rewrite -ltnNge => /ltnW => /B C.
move: (C H4) => []. rewrite addnC => -> [os] -> /=. by eauto.
- move: (leq_total n1 n2). by rewrite H3 H4.
* rewrite nodew_some => [] [] <- Hrm. case Hint: interp => [c'|//]. interp_simpl_nw.
case Hint': interp => [c'' //|//] [] <- <-; rewrite -orm_some Hrm;
move: Hint Hint' -> => [] [] // -> //=. by eauto.
* maxapply remove_openroot_commutation => /(_ f (~~f)) /= [] -> [os] ->. by eauto.
(* Case op1 = editLabel *)
* by solve_openroot.
* by solve_openroot.
* case Hint1: interp => [x'|] // [] <- <-; case Hint2: interp => [x''|] // [] <- <-;
rewrite -?map_comp ?foldl_editroot /=. move: Hint1 Hint2. maxapply (@it_c1 X cmd) => /(_ f) /= [] -> [os] ->.
by eauto.
* by solve_openroot.
(* Case op1 = open root *)
* maxapply insert_openroot_commutation. rewrite /flip /= => [[] <-]. by eauto.
* maxapply remove_openroot_commutation => /(_ (~~f) f) => [] [] -> [os] ->. by eauto.
* interp_simpl. rewrite nodew_some => [] [] <-.
case: interp => [x'|] // Hrplc [] <- <-. rewrite Hrplc /=. by eauto.
* case Heq: (n1 == n2); rewrite ?1eq_sym Heq.
+ move/eqP: Heq ->.
let sol := fun m ls =>
let H := fresh
with Hleq := fresh "Hleq"
with Heq := fresh "Heq" in
(rewrite nodew_some => [] [] <- A;
move: (A) => /rplc_some_len Heq; move: (A) => /rplc_some []; move: (Heq) => -> Hleq [m] H;
rewrite (foldl_openroot x) //; move: (A);
rewrite (orplc_some _ _ ls) H => /rplc_nth_eq ->; move: A => <-;
rewrite H (orplc_some _ (Some m)) rplc_rplcC_eq) in (sol m ls1; sol m' ls2).
case B1: (nth n2 ls) H H0 => //=; maxapply IHl1 => /(_ f) [] -> [node] ->. split => //=.
case Hrplc: rplc => [a|]; first by exists (Node x a).
by move: Hrplc Hleq => /rplc_noneP1; rewrite ltnNge Heq; case leq.
interp_simpl_nw. rewrite eq_sym in Heq. rewrite rplc_rplcC_neq //. move: (HN0) (HN2).
move=> /negbT in Heq. simpl in HN0, HN2.
rewrite ?(rplc_nth_neq n2 n1 _ ls1 ((bind (tree_interp c1)) (nth n1 ls))) //.
rewrite eq_sym in Heq.
rewrite ?(rplc_nth_neq n1 n2 _ ls2 ((bind (tree_interp c2)) (nth n2 ls))) //.
split => //. move: HN3 => /= /rplc_some [] Hlt' [e'] ->.
case Hrplc: rplc => [a|]. move: Hrplc => /rplc_some_len Heqsz.
case: (bind (tree_interp c2)) HN4 => [b _|] //=; last by rewrite rplc_none_none.
case Hrplc': rplc => [a'|].
- by exists (Node x2 a').
- move: Hrplc' => /rplc_noneP1; move: HN2 => /rplc_some []. move => _1 _2; move: _2 _1 => _.
rewrite Heqsz. by maxapply Nleq_ltnC.
- move: Hrplc => /rplc_noneP1. move: HN0 => /rplc_some []. move => _1 _2; move: _2 _1 => _.
by maxapply Nleq_ltnC.
Qed.
Theorem tree_ip1: forall (op : tree_command) m mr,
tree_interp op m = Some mr ->
tree_interp (tree_inv op) mr = (Some m).
Proof.
elim => [[n l | n l | c]| n c IHc] [x ls] [xr lrs] //=.
+ by move=> /nodew_some [] <- /rm_ins_id ->.
+ case: l => [|x1 l1]; first by rewrite rm_id /= => ->.
have: (0 < size (x1 :: l1)); first by exact (ltn0Sn _).
move => _1 _2; move: _2 _1 => /nodew_some [] <-. maxapply (@ins_rm_id (tree_eqType X)). by move=> /= ->.
+ case Hint: interp => [a|] // [] <- <-. apply ip1 in Hint. by rewrite Hint.
+ move=> /nodew_some [] <-. case Hti: (bind (tree_interp c)) => [ti_r|]; last by rewrite rplc_none_none.
move: Hti. case Hnth: nth => [nth_r|]; last by simpl.
move=> /IHc. move => _1 _2; move: _2 _1. move => Hrplc. move: (Hrplc) => /rplc_nth_eq => ->. rewrite /bind => ->.
rewrite orplc_some -Hrplc -Hnth orplc_some rplc_rplcC_eq.
case Horplc: orplc => [a|].
- move: (Horplc) (Horplc). move /rplc_nth_id -> => //.
- move: Horplc => /= /rplc_none_case []; first by rewrite Hnth.
move: Hrplc => /rplc_some []. move => _1 _2; move: _2 _1 => _. by maxapply Nleq_ltnC.
Qed.
Instance treeOT: (OTBase (tree X) tree_command) := {interp := tree_interp; it := tree_it; it_c1 := tree_c1}.
Instance treeInv: (OTInv (tree X) tree_command treeOT) := {inv := tree_inv; ip1 := tree_ip1}.
End TreeOTDefinition.
Section Sandbox.
Require Import Comp.
Arguments TreeInsert [X] [cmd].
Arguments TreeRemove [X] [cmd].
Arguments OpenRoot [X] [cmd].
Arguments Atomic [X] [cmd].
Theorem c1: forall (op1 op2 : unit) (f : bool) (m m1 m2 : nat_eqType),
(fun=> [eta Some]) op1 m = Some m1 ->
(fun=> [eta Some]) op2 m = Some m2 ->
let m21 := exec_all (fun=> [eta Some]) (Some m2) ((fun=> (fun=> (fun=> [:: tt]))) op1 op2 f) in
let m12 := exec_all (fun=> [eta Some]) (Some m1) ((fun=> (fun=> (fun=> [:: tt]))) op2 op1 (~~ f)) in m21 = m12 /\ (exists node : nat_eqType, m21 = Some node).
move => _ _ _ m m1 m2 [] <- [] <- /=. split. done. exists m. by rewrite /flip. Qed.
Instance unitOT : OTBase nat_eqType unit := {interp := (fun c m => Some m); it := (fun _ _ _ => [:: tt]); it_c1:=c1}.
Definition it1 := transform (@tree_it nat_eqType unit unitOT).
Definition abclist := [:: Node 10 [::]; Node 11 [::]; Node 12 [::]].
Definition abc := Node 1 abclist.
Definition efg := Node 2 [:: Node 14 [::]; Node 15 [::]; Node 16 [::]].
Eval compute in it1 [:: Atomic (TreeRemove 1 [::efg]); OpenRoot 0 (Atomic (TreeInsert 3 abclist))]
[::OpenRoot 0 (Atomic (TreeInsert 3 [:: Node 13 [::] ])); OpenRoot 1 (Atomic (TreeInsert 3 [:: Node 17 [::]]))] 100.
End Sandbox.
Section SplitMerge.
Context {X : eqType} (cmd : Type) {ot : OTBase X cmd} {ip : OTInv _ _ ot}.
Inductive tree_command_ext : Type :=
| Atomic1 of @list_command X cmd
| OpenRoot1 of nat & tree_command_ext
| Split of nat & nat & X
| Merge of nat & nat & X.
Fixpoint tree_inv_ext (c : tree_command_ext) :=
match c with
| Atomic1 c1 => Atomic1 (@list_inv X cmd ot ip c1)
| Split n k c => Merge n k c
| Merge n k c => Split n k c
| OpenRoot1 n c => OpenRoot1 n (tree_inv_ext c)
end.
Fixpoint tree_it_ext (op1 op2 : tree_command_ext) (flag : bool) : seq tree_command_ext :=
match op1, op2 with
_, _ => [:: op1]
end.
End SplitMerge.