TreeOt.v (323 lines of code) (raw):
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.