Comp.v (272 lines of code) (raw):
Require Import Ssromega OtDef Commons.
Lemma ltnSn n: n < S n. ssromega. Qed.
Lemma list_const: forall X X' (l : list X') (x : X), match l with nil => x | _ :: _ => x end = x.
Proof. intros. destruct l; reflexivity. Qed.
Lemma tstab {cmd} t: forall n k (op1 op2 op1' op2' : list cmd),
transform t op1 op2 n = Some (op2', op1') -> transform t op1 op2 (n + k) = Some (op2', op1').
Proof. elim => [|n IHn] k [|o1 op1] [|o2 op2] op1' op2' //=.
move A1: (transform t _ _ n) => [[x y]|] //; move A2: (transform t _ _ n) => [[x' y']|] // h.
by rewrite (IHn k _ _ _ _ A1) (IHn k _ _ _ _ A2) h. Qed.
(* =============================================== *)
Section OTCorrectness.
Context {X cmd : Type} (ot : OTBase X cmd) (comp : @OTComp X cmd ot).
Lemma sz_nil: sz nil = 0. by rewrite /sz. Qed.
Lemma si_nil: si nil = 0. by rewrite /si. Qed.
Lemma cats_sz (l1 l2 : list cmd): sz (l1 ++ l2) = sz l1 + sz l2.
elim: l1 l2 => [| l ls IHl] l2. by rewrite cat0s sz_nil add0n. rewrite /sz /= in IHl.
by rewrite cat_cons /sz /= ?add0n fadd (fadd (cmdsz l)) IHl addnA. Qed.
Lemma cats_si (l1 l2 : list cmd): si (l1 ++ l2) = si l1 + si l2.
elim: l1 l2 => [| l ls IHl] l2. by rewrite cat0s si_nil add0n. rewrite /si /= in IHl.
by rewrite cat_cons /si /= ?add0n fadd (fadd (cmdsi l)) IHl addnA. Qed.
Lemma execute_app: forall (op1 op2 : list cmd) (m : option X),
(exec_all interp) m (op1 ++ op2) = (exec_all interp) (exec_all interp m op1) op2.
elim => [| x xs IHx] op2 m //. rewrite cat_cons /= IHx //. Qed.
Lemma execute_none op: exec_all interp None op = None.
by elim: op => [|x xs IHx] //=. Qed.
Lemma transform_ind:
forall (op1 op2 : list cmd) n, transform it op1 op2 (S n) =
match op1, op2 with
| nil, _ | _, nil => Some (op2, op1)
| x :: xs, y :: ys =>
match transform it xs (it y x false) n with
Some (y'', xs') =>
match transform it ((it x y true) ++ xs') ys n with
Some (ys', x'') => Some (y'' ++ ys', x'')
| _ => None
end
| _ => None
end
end. done. Qed.
Theorem ot_computability': forall n m (op1 op2 : list cmd),
(sz op1 + sz op2 < n) -> (si op1 + si op2 < m) ->
(exists n, exists op1', exists op2', transform it op1 op2 n = Some (op2', op1') /\
(sz op1' + sz op2' <= sz op1 + sz op2) /\
(si op1' + si op2' <= si op1 + si op2) /\
(((sz op1' <= sz op1) /\ (sz op2' <= sz op2)) \/
(si op1' + si op2' < si op1 + si op2))).
elim => [|n IHn].
+ move => m op1 op2 h. by have: False by ssromega.
+ elim => [|m IHm] // op1 op2.
case: op1 => [*|x xs].
+ exists 1. exists (@nil cmd). exists op2.
rewrite ?sz_nil ?si_nil ?add0n /=. split. done.
split. ssromega. split. ssromega. left. split; ssromega.
+ case: op2 => [*|y ys].
+ exists 1. exists (x :: xs). exists (@nil cmd).
rewrite ?sz_nil ?si_nil ?add0n ?addn0 /=. split. done.
split. ssromega. split. ssromega. left. split; ssromega.
replace (x :: xs) with ([::x] ++ xs); [| by simpl].
replace (y :: ys) with ([::y] ++ ys); [| by simpl].
+ rewrite ?cats_sz ?cats_si.
move => h h'. assert (AA := comp_corr x y false). rewrite /computability /= in AA.
rewrite /cat. assert (E0 := sz_nondg x). assert (E1 := sz_nondg y).
assert (E0': sz [::x] > 0). by rewrite /sz.
assert (E1': sz [::y] > 0). by rewrite /sz. clear E0 E1.
move Heqy': (@it _ _ ot x y true) => x'.
move Heqx': (@it _ _ ot y x false) => y'.
rewrite Heqx' Heqy' in AA.
move: AA => /= [B1[B2[[B0 B0']|B0 {B2}]]];
[assert (A0: sz xs + sz y' < n) by ssromega;
move: (IHn (S (si xs + si y')) xs y' A0 (ltnSn _)) |
assert (A0: sz xs + sz y' < n.+1) by ssromega;
assert (A0': si xs + si y' < m) by ssromega;
move: (IHm xs y' A0 A0') ];
move => [n'1 [xs' [y'' [C1 [C2 [C3 C4]]]]]] {A0};
[move: C4 => [[C01 C02]|C0];
[ assert (A0: sz (x' ++ xs') + sz ys < n) by (rewrite cats_sz; ssromega);
move: (IHn (S (si (x' ++ xs') + si ys)) (x' ++ xs') ys A0 (ltnSn _)) => A1|
assert (A0: sz (x' ++ xs') + sz ys < S n) by (rewrite cats_sz; ssromega);
assert (A0': si (x' ++ xs') + si ys < m) by (rewrite cats_si; ssromega);
move: (IHm (x' ++ xs') ys A0 A0') => A1] |
assert (A0: sz (x' ++ xs') + sz ys < S n) by (rewrite cats_sz; ssromega);
clear A0'; assert (A0': si (x' ++ xs') + si ys < m) by (rewrite cats_si; ssromega);
move: (IHm (x' ++ xs') ys A0 A0') => A1];
rewrite cats_sz cats_si in A1;
move: A1 => [n'2 [op1' [ys' [D1 [D2 [D3 D4]]]]]];
apply (tstab _ _ n'2) in C1; apply (tstab _ _ n'1) in D1; rewrite addnC in D1;
exists (S (n'1 + n'2));
rewrite transform_ind Heqy' Heqx' C1 D1;
exists op1'; exists (y'' ++ ys'); rewrite ?cats_sz ?cats_si;
(split; [done|split;[ssromega|split;[ssromega|]]]).
+ move: D4 => [[D41 D42]| D4];[left; split |right]; ssromega.
+ right; ssromega.
+ right; ssromega. Qed.
Corollary ot_computability'' op1 op2:
(exists n, exists op1', exists op2', transform it op1 op2 n = Some (op2', op1') /\
(sz op1' + sz op2' <= sz op1 + sz op2) /\
(si op1' + si op2' <= si op1 + si op2) /\
(((sz op1' <= sz op1) /\ (sz op2' <= sz op2)) \/
(si op1' + si op2' < si op1 + si op2))).
by apply (ot_computability' (S (sz op1 + sz op2)) (S (si op1 + si op2)) op1 op2 (ltnSn _) (ltnSn _)). Qed.
Corollary ot_computable: forall (op1 op2 : list cmd), exists nSteps op1' op2', transform it op1 op2 nSteps = Some (op2', op1').
move => op1 op2. move: (ot_computability'' op1 op2). move => [n [op1' [op2' [A B]]]]. exists n. exists op1'. exists op2'. done. Qed.
Theorem ot_execution: forall nSteps op1 op2 op1' op2' m (m1 m2 : X), exec_all interp m op1 = Some m1 /\ exec_all interp m op2 = Some m2 ->
transform it op1 op2 nSteps = Some (op2', op1') ->
exec_all interp (Some m1) op2' = exec_all interp (Some m2) op1' /\ exists m3, exec_all interp (Some m1) op2' = Some m3.
elim => [|n IHn] op1 op2 op1' op2' m m1 m2 [h h'] H0 //. rewrite transform_ind in H0.
case: op1 H0 h => [[H0 H1] [h]| x xs H0 h].
+ rewrite -H0 -H1 -h /= h'. by eauto.
+ case: op2 H0 h' h => [[H0 H1] [h']| y ys].
* rewrite -H0 -H1 -h' /=. eauto.
* move A0: (it y x false) => y'. move A1: (transform it xs y' n) => [[y'' xs']|] //.
move A2: (it x y true) => x'. move A3: (transform it (x' ++ xs') ys n) => [[ys' x'']|] //= [H0 H1].
rewrite -H0 -H1 execute_app {H0 H1}.
case: m => [m|]; [|rewrite exec_all_none //]. rewrite /Basics.flip /=.
move M1: (interp x m) => [t1|]; [|rewrite execute_none]; rewrite //.
move M2: (interp y m) => [t2|]; [|rewrite execute_none]; move => // h h'.
move: (it_c1 _ _ true _ _ _ M1 M2). rewrite A0 A2. move => /= [B1 [s1 B2]]. rewrite B1 in B2.
move: (IHn _ _ _ _ _ _ _ (conj h' B2) A1) => /= [C1 [s2 C2]].
assert (D1: exec_all interp (Some t2) (x' ++ xs') = Some s2). by rewrite execute_app B1 B2 -C1 C2.
move: (IHn _ _ _ _ _ _ _ (conj D1 h) A3) => /= [E1 [s3 E2]]. rewrite -E1 C2 E2. by eauto. Qed.
Corollary ot_correctness: forall op1 op2 m (m1 m2 : X),
exec_all interp m op1 = Some m1 /\ exec_all interp m op2 = Some m2 ->
exists nSteps op1' op2', transform it op1 op2 nSteps = Some (op2', op1') /\
exec_all interp (Some m1) op2' = exec_all interp (Some m2) op1' /\ exists m3, exec_all interp (Some m1) op2' = Some m3.
move => op1 op2 m m1 m2 H. move: (ot_computable op1 op2) => [n [op1' [op2' A0]]].
exists n. exists op1'. exists op2'. split. done. by move: (ot_execution _ _ _ _ _ _ _ _ H A0). Qed.
End OTCorrectness.
(* =============================================== *)
Module TransformApp.
Corollary tstab1 {cmd} t: forall n (op1 op2 op1' op2' : list cmd),
transform t op1 op2 n = Some (op2', op1') -> transform t op1 op2 (n.+1) = Some (op2', op1').
intros. apply tstab with (k:=1) in H. by rewrite -addn1. Qed.
Lemma tr_through_nil {cmd} t (l : list cmd) n:
transform t l nil n.+1 = Some (nil, l). by rewrite /= list_const. Qed.
Lemma tr_nil {cmd} t (l : list cmd) n:
transform t nil l n.+1 = Some (l, nil). done. Qed.
Lemma part_lemma {cmd} t n: forall (y : cmd) x ys y' x',
transform t x (y :: ys) n = Some (y', x') ->
match transform t x [:: y] n with
Some (y', x') => match transform t x' ys n with
Some (ys', x'') => Some (y' ++ ys', x'')
| _ => None
end
| _ => None
end = Some (y', x').
intros. case: n x H => [|n] [|x xs] // H. simpl in H.
case A0: (transform t xs (t y x false) n) H => [[a b]|] // H.
case A1: (transform t (t x y true ++ b) ys n) H => [[c d]|] // [A2 A3].
remember (n.+1) as n1. rewrite {1}Heqn1 /= A0. destruct n. inversion A0.
rewrite tr_through_nil cats0. subst. apply tstab1 in A1. rewrite A1. done. Qed.
Lemma part_lemma2 {cmd} t x (y : cmd) ys y' x' y1' x'' n:
transform t x [:: y] n = Some (y', x') ->
transform t x' ys n = Some (y1', x'') ->
transform t x (y :: ys) n.+1 = Some (y' ++ y1', x'').
case A1: n => [|n1] // H H0.
simpl in H. case: x H => [|x xs] //. simpl.
+ move => [*]. subst. by case: n1 H0 => [|n1] [H0 H1]; rewrite -H0 -H1.
+ case A0: transform => [[y''0 xs']|]//. destruct n1; [inversion A0|].
rewrite tr_through_nil cats0. move => [A2 A3]. subst.
remember (n1.+2) as n2. apply tstab1 in A0. rewrite -Heqn2 in A0. simpl. by rewrite A0 H0. Qed.
Lemma vpart1inv {cmd} t: forall y1 (x : list cmd) y2 k,
transform t x y1 k = None -> transform t x (y1 ++ y2) k = None.
elim => [|y1 y1s IHy1]; intros. by case: k x H => [|k] [|a l].
case: k H => [|k] //. rewrite cat_cons. remember (k.+1) as k1. rewrite {1}Heqk1 /=.
destruct x. done. case A1: transform => [[y'' xs']|];[| by subst; rewrite /= A1].
case A2: transform => [[ys' x'']|] // A3 {A3}. subst. simpl. rewrite A1.
by rewrite (IHy1 _ y2 _ A2). Qed.
Theorem vpart1 {cmd} t: forall (y1 : list cmd) n x y2 y' x' y1' x'',
transform t x y1 n = Some (y', x') ->
transform t x' y2 n = Some (y1', x'') ->
exists k, transform t x (y1 ++ y2) k = Some (y' ++ y1', x'').
elim => [|y y1s IHy] [|n] //; intros.
+ rewrite tr_through_nil in H. inversion H. subst. by exists n.+1.
+ move: (part_lemma _ _ _ _ _ _ _ H).
case A0: transform => [[y'0 x'0]|]//.
case A1: transform => [[ys' x''0]|]// [A2 A3].
rewrite A3 {A3 x''0} in A1. rewrite -A2. rewrite -A2 {A2 y'} in H.
move: (IHy _ _ _ _ _ _ _ A1 H0) => [k' A2]. apply (tstab _ _ (n.+1)) in A2.
apply (tstab _ _ k') in A0. rewrite addSn in A0. rewrite addnS addnC in A2.
exists (n + k').+2. by rewrite cat_cons (part_lemma2 _ _ _ _ _ _ _ _ _ A0 A2) catA. Qed.
Theorem vpart2 {cmd} t: forall (y1 y2 x : list cmd) y' x' n,
transform t x (y1 ++ y2) n = Some (y', x') ->
match transform t x y1 n with
Some (y1', x') => match transform t x' y2 n with
Some (y2', x'') => Some (y1' ++ y2', x'')
| _ => None
end
| _ => None
end = Some (y', x').
elim => [|y y1s IHy1] y2 x Y' X' [|n] H //.
+ rewrite /= list_const. case: x y2 H => [|a b] [|c d] //= H. by rewrite H.
+ remember (n.+1) as n1. rewrite cat_cons in H. move: (part_lemma _ _ _ _ _ _ _ H).
case A0: transform => [[y' x']|] //. case A1: transform => [[ys' x'']|] // [B0 B1].
rewrite -B1 -B0. rewrite -B1 -B0 {B0 B1 X' Y'} in H.
move: (IHy1 _ _ _ _ _ A1).
case A2: transform => [[y1' x'0]|] //.
case A3: transform => [[y2' x''0]|] // [B2 B3].
rewrite B3 {B3 x''0 }in A3. rewrite -B2. rewrite -B2 {B2 ys'} in H A1.
destruct n1; [inversion A0|].
case A4: transform => [[y1'0 x'1]|];[|by rewrite -cat_cons (vpart1inv t (y::y1s) x y2 (n1.+1) A4) in H].
move: (part_lemma2 _ _ _ _ _ _ _ _ _ A0 A2) => H0. apply tstab1 in A4. rewrite A4 in H0. inversion H0. subst.
by rewrite A3 catA. Qed.
Theorem hpart2 {cmd} t n: forall (x1 x2 y y' x': list cmd),
transform t (x1 ++ x2) y n = Some (y', x') ->
exists k,
match transform t x1 y k with
Some (y', x1') =>
match transform t x2 y' k with
Some (y'', x2') => Some (y'', x1' ++ x2')
| _ => None
end
| _ => None
end = Some (y', x').
elim: n => [|n IHn]. done. remember (n.+1) as n1.
case => [|x1 x1s] x2 y Y' X'; intros.
+ rewrite /= in H. exists n1.+1. by rewrite tr_nil (tstab1 _ _ _ _ _ _ H).
+ case: y H => [|y ys] H.
+ rewrite Heqn1 tr_through_nil in H. move: H => [A0 A1].
exists n1. by rewrite Heqn1 2!tr_through_nil -A0 -A1 -cat_cons.
+ move: H. rewrite {1}Heqn1 /=.
case A0: transform => [[y'' xs']|] //.
case A1: transform => [[ys' X'2]|] // [A2 A3].
move: (IHn _ _ _ _ _ A0) => [k1].
case A4: transform => [[y' x1s']|] //.
case A5: transform => [[y''1 x2']|] // [A6 A7].
rewrite -A7 {A7 xs'} in A1 A0. rewrite A3 {A3 X'2} catA in A1.
rewrite A6 {A6 y''1} in A5. rewrite -A2 {A2 Y'}.
move: (IHn _ _ _ _ _ A1) => [k2].
case A6: transform => [[ys0' x1'']|] //.
case A7: transform => [[y''0 x2'']|] // [A8 A9].
rewrite -A9. rewrite -A9 {X' A9} in A1. rewrite A8 {A8 y''0} in A7.
apply (tstab _ _ k2) in A5. apply (tstab _ _ k1) in A7.
apply (tstab _ _ k2) in A4. apply (tstab _ _ k1) in A6.
rewrite addnC in A6 A7.
move: (vpart1 _ _ _ _ _ _ _ _ _ A5 A7) => [k'' B].
exists (k1+k2+k'').+1. remember (k1+k2+k'').+1 as k. rewrite {1}Heqk /=.
apply (tstab _ _ k'') in A4. apply (tstab _ _ k'') in A6.
apply (tstab _ _ (k1+k2)) in B. rewrite addnC in B.
by rewrite A4 A6 Heqk (tstab1 _ _ _ _ _ _ B). Qed.
End TransformApp.
(* =============================================== *)
Module Transform2.
Fixpoint transform2 {cmd} (t : cmd -> cmd -> bool -> list cmd) (op1 op2 : list cmd) (nSteps : nat) : option ((list cmd) * (list cmd)) :=
match nSteps with 0 => None | S nSteps' =>
match op1, op2 with
| nil, _ | _, nil => Some (op2, op1)
| x :: xs, y :: ys => let y' := t y x false in let x' := t x y true in
match transform2 t xs y' nSteps', transform2 t x' ys nSteps' with
Some (y'', xs'), Some (ys', x'') =>
match transform2 t xs' ys' nSteps' with
Some (ys'', xs'') => Some (y'' ++ ys'', x'' ++ xs'')
| _ => None
end
| _, _ => None
end
end
end.
Lemma tstab2 {cmd} t: forall n k (op1 op2 op1' op2' : list cmd),
transform2 t op1 op2 n = Some (op2', op1') ->
transform2 t op1 op2 (n + k) = Some (op2', op1').
elim => [|n IHn] k [|o1 op1] [|o2 op2] op1' op2' //=.
case A1: transform2 => [[y'' xs']|] //. case A2: transform2 => [[ys' x'']|] //.
case A3: transform2 => [[ys'' xs'']|] // [B0 B1]. subst.
by rewrite (IHn k _ _ _ _ A1) (IHn k _ _ _ _ A2) (IHn k _ _ _ _ A3). Qed.
Corollary tstab12 {cmd} t: forall n (op1 op2 op1' op2' : list cmd),
transform2 t op1 op2 n = Some (op2', op1') -> transform2 t op1 op2 (n.+1) = Some (op2', op1').
intros. apply tstab2 with (k:=1) in H. by rewrite -addn1. Qed.
Lemma tr2_through_nil {cmd} t (l : list cmd) n:
transform2 t l nil n.+1 = Some (nil, l). by rewrite /= list_const. Qed.
Lemma tr2_nil {cmd} t (l : list cmd) n:
transform2 t nil l n.+1 = Some (l, nil). done. Qed.
End Transform2.