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.