Module scurve.Reduction
Require Import ListExt.From Stdlib Require Import ZArith.
Require Import PrimitiveSegment.
Import ListNotations.
Open Scope Z_scope.
Require Import Eq.
Inductive Direction : Set :=
| Plus : Direction
| Minus : Direction
.
Definition Direction_dec: forall (x y: Direction), {x = y} + {x <> y}.
refine (fun x y => match x, y with
| Plus, Plus => left _
| Minus, Minus => left _
| _, _ => right _
end); now auto.
Canonical Direction_eqDec := @Pack _ Direction_dec.
Definition orn (x:PrimitiveSegment) : Direction :=
match x with
| (n, e, cx) | (s, e, cx) | (s, w, cc) | (n, w, cc) => Plus
| (s ,w, cx) | (s, e, cc) | (n, e, cc) | (n, w, cx) => Minus
end.
Definition rotation_difference (ds: list Direction) : Z :=
fold_right Z.add 0 (map (fun d =>
match d with
| Plus => 1
| Minus => -1
end
) ds).
Lemma rotation_difference_distribution:
forall (ds ds': list Direction),
rotation_difference (ds ++ ds') = rotation_difference ds + rotation_difference ds'.
Proof.
intros ds ds'.
unfold rotation_difference.
set (F := fun d =>
match d with
| Plus => 1
| Minus => -1
end).
induction ds as [| d ds IH]; [now simpl | simpl].
rewrite IH. now auto with zarith.
Qed.
unfold rotation_difference.
set (F := fun d =>
match d with
| Plus => 1
| Minus => -1
end).
induction ds as [| d ds IH]; [now simpl | simpl].
rewrite IH. now auto with zarith.
Qed.
Inductive Rule : list Direction -> list Direction -> Prop :=
| R1Plus : Rule [Plus; Minus; Plus] [Plus]
| R1Minus : Rule [Minus; Plus; Minus] [Minus]
| R2Plus : Rule [Plus; Plus; Minus; Minus] [Plus; Minus]
| R2Minus : Rule [Minus; Minus; Plus; Plus] [Minus; Plus]
.
Hint Constructors Rule : core.
Lemma Rule_same_src ds ds1 ds2: Rule ds ds1 -> Rule ds ds2 -> ds1 = ds2.
Proof.
intros rule1 rule2.
inversion rule1; inversion rule2; subst; now try discriminate.
Qed.
inversion rule1; inversion rule2; subst; now try discriminate.
Qed.
Lemma rotation_difference_preservation_rule:
forall (ds ds': list Direction), Rule ds ds' -> rotation_difference ds = rotation_difference ds'.
Proof.
intros ds ds' H. now destruct H.
Qed.
Qed.
Lemma Rule_preserve_both_ends: forall ds ds',
Rule ds ds' -> head ds = head ds' /\ last_opt ds = last_opt ds'.
Proof.
intros ds ds' H.
destruct H; auto.
Qed.
destruct H; auto.
Qed.
Inductive ReduceDirStep : list Direction -> list Direction -> Prop :=
| RDS : forall (l r ds ds': list Direction), Rule ds ds' ->
ReduceDirStep (l ++ ds ++ r) (l ++ ds' ++ r)
.
Lemma ReduceDirStep_length ds ds':
ReduceDirStep ds ds' -> length ds = (2 + length ds')%nat.
Proof.
intros H.
induction H.
destruct H; simpl; repeat rewrite length_app, length_cons; repeat rewrite plus_n_Sm; reflexivity.
Qed.
induction H.
destruct H; simpl; repeat rewrite length_app, length_cons; repeat rewrite plus_n_Sm; reflexivity.
Qed.
Lemma rotation_difference_preservation_step:
forall (ds ds': list Direction), ReduceDirStep ds ds' -> rotation_difference ds = rotation_difference ds'.
Proof.
intros ds ds' H.
destruct H.
apply rotation_difference_preservation_rule in H.
repeat rewrite rotation_difference_distribution.
apply Z.add_cancel_l. apply Z.add_cancel_r. now apply H.
Qed.
destruct H.
apply rotation_difference_preservation_rule in H.
repeat rewrite rotation_difference_distribution.
apply Z.add_cancel_l. apply Z.add_cancel_r. now apply H.
Qed.
Lemma ReduceDirStep_preserve_both_ends: forall ds ds',
ReduceDirStep ds ds' -> head ds = head ds' /\ last_opt ds = last_opt ds'.
Proof.
intros ds ds' H.
destruct H as [l r es es' rule].
destruct (Rule_preserve_both_ends _ _ rule) as [head last].
split.
- destruct l; [simpl | now reflexivity].
destruct es'; [now rewrite nil_head in head |].
destruct es; [now discriminate | simpl].
simpl in head. apply head.
- repeat rewrite last_head in last.
repeat rewrite last_head.
repeat rewrite rev_app_distr.
destruct (rev r); [simpl | now reflexivity].
destruct (rev es').
* rewrite nil_head in last.
rewrite last.
now reflexivity.
* destruct (rev es); [now discriminate | now simpl].
Qed.
destruct H as [l r es es' rule].
destruct (Rule_preserve_both_ends _ _ rule) as [head last].
split.
- destruct l; [simpl | now reflexivity].
destruct es'; [now rewrite nil_head in head |].
destruct es; [now discriminate | simpl].
simpl in head. apply head.
- repeat rewrite last_head in last.
repeat rewrite last_head.
repeat rewrite rev_app_distr.
destruct (rev r); [simpl | now reflexivity].
destruct (rev es').
* rewrite nil_head in last.
rewrite last.
now reflexivity.
* destruct (rev es); [now discriminate | now simpl].
Qed.
Inductive ReduceDir : list Direction -> list Direction -> Prop :=
| RDRefl : forall ds, ReduceDir ds ds
| RDTrans : forall ds ds' ds'', ReduceDirStep ds ds' -> ReduceDir ds' ds'' ->
ReduceDir ds ds''
.
Lemma ReduceDir_preserve_both_ends: forall ds ds',
ReduceDir ds ds' -> head ds = head ds' /\ last_opt ds = last_opt ds'.
Proof.
intros ds ds' H.
induction H; [split; reflexivity|].
destruct (ReduceDirStep_preserve_both_ends _ _ H) as [head_eq last_eq].
destruct IHReduceDir as [head_eq' last_eq'].
split; [now rewrite head_eq, head_eq' | now rewrite last_eq, last_eq'].
Qed.
induction H; [split; reflexivity|].
destruct (ReduceDirStep_preserve_both_ends _ _ H) as [head_eq last_eq].
destruct IHReduceDir as [head_eq' last_eq'].
split; [now rewrite head_eq, head_eq' | now rewrite last_eq, last_eq'].
Qed.
Definition Reduce (p p': list PrimitiveSegment): Prop :=
ReduceDir (map orn p) (map orn p').
Definition rule_dec ds: {exists ds', Rule ds ds'} + {~ exists ds', Rule ds ds'}.
refine (match ds with
| [Plus; Minus; Plus] => left (ex_intro _ [Plus] _)
| [Minus; Plus; Minus] => left (ex_intro _ [Minus] _)
| [Plus; Plus; Minus; Minus] => left (ex_intro _ [Plus; Minus] _)
| [Minus; Minus; Plus; Plus] => left (ex_intro _ [Minus; Plus] _)
| _ => right _
end);try now auto; intros H; destruct H.
Lemma ReduceDirStep_ex_sublist ds :
(exists ds', ReduceDirStep ds ds') <-> ex_sublists (fun ds0 => exists ds0', Rule ds0 ds0') ds.
Proof.
split.
- intros existsds'. destruct existsds' as [ds' HRDS]. apply all_sublists_ex. apply Exists_exists.
inversion HRDS as [l r l0 r0 HRule _eq1 _eq2]. exists l0. split.
+ apply all_sublists_iff. now apply (SL l l0 r).
+ now exists r0.
- intros Hex_sub. apply all_sublists_ex in Hex_sub. apply Exists_exists in Hex_sub. destruct Hex_sub as [l0 [HIn [r0 HR]]].
apply all_sublists_iff in HIn. inversion HIn as [l _l0 r _eq _eq2]. exists (l ++ r0 ++ r). now apply (RDS l r l0 r0).
Qed.
- intros existsds'. destruct existsds' as [ds' HRDS]. apply all_sublists_ex. apply Exists_exists.
inversion HRDS as [l r l0 r0 HRule _eq1 _eq2]. exists l0. split.
+ apply all_sublists_iff. now apply (SL l l0 r).
+ now exists r0.
- intros Hex_sub. apply all_sublists_ex in Hex_sub. apply Exists_exists in Hex_sub. destruct Hex_sub as [l0 [HIn [r0 HR]]].
apply all_sublists_iff in HIn. inversion HIn as [l _l0 r _eq _eq2]. exists (l ++ r0 ++ r). now apply (RDS l r l0 r0).
Qed.
Definition CanReduceDirStep ds := exists ds', ReduceDirStep ds ds'.
Lemma CanReduceDirStep_or ds: CanReduceDirStep ds \/ ~CanReduceDirStep ds.
Proof.
destruct (ex_sublists_dec (fun ds0 => exists ds0', Rule ds0 ds0') rule_dec ds).
- left. now apply ReduceDirStep_ex_sublist.
- right. intros HCRDS. apply n. apply ReduceDirStep_ex_sublist. exact HCRDS.
Qed.
- left. now apply ReduceDirStep_ex_sublist.
- right. intros HCRDS. apply n. apply ReduceDirStep_ex_sublist. exact HCRDS.
Qed.
Lemma termination : forall x, exists y, ReduceDir x y /\ ~ CanReduceDirStep y.
Proof.
apply (Nat.measure_induction _ (@List.length _)).
intros x IHx.
destruct (CanReduceDirStep_or x) as [canReduce|].
- destruct canReduce as [x' step]. destruct IHx with x' as [final [reduce cannnotStep]].
+ rewrite (ReduceDirStep_length x x'); auto with arith.
+ exists final. now split; [apply RDTrans with x' |].
- exists x. now split; [constructor|].
Qed.
intros x IHx.
destruct (CanReduceDirStep_or x) as [canReduce|].
- destruct canReduce as [x' step]. destruct IHx with x' as [final [reduce cannnotStep]].
+ rewrite (ReduceDirStep_length x x'); auto with arith.
+ exists final. now split; [apply RDTrans with x' |].
- exists x. now split; [constructor|].
Qed.
Lemma rotation_difference_preservation:
forall (ds ds': list Direction), ReduceDir ds ds' -> rotation_difference ds = rotation_difference ds'.
Proof.
intros ds ds' H.
induction H as [| ds ds']; [now reflexivity |].
apply rotation_difference_preservation_step in H.
rewrite H. now apply IHReduceDir.
Qed.
induction H as [| ds ds']; [now reflexivity |].
apply rotation_difference_preservation_step in H.
rewrite H. now apply IHReduceDir.
Qed.
Lemma tl_cannot_reduce h tl: ~ CanReduceDirStep (h :: tl) -> ~ CanReduceDirStep tl.
Proof.
intros notreduce reduce.
apply notreduce. inversion reduce as [tl' HRDS]. inversion HRDS as [l r ds ds' HRule eq1 eq2].
exists ((h :: l) ++ ds' ++ r). rewrite app_comm_cons.
now auto.
Qed.
apply notreduce. inversion reduce as [tl' HRDS]. inversion HRDS as [l r ds ds' HRule eq1 eq2].
exists ((h :: l) ++ ds' ++ r). rewrite app_comm_cons.
now auto.
Qed.
Lemma ReduceDir_reduced_form_PlusPlus l r:
~ CanReduceDirStep (l ++ [Plus;Plus] ++ r) -> r <> [] ->
exists lst (n: nat), r = (List.repeat Plus n) ++ [lst].
Proof.
revert l. induction r as [|d r IHr].
- contradiction.
- intros l NotReduce _Hnil. clear _Hnil. destruct d.
+ destruct r as [|d r'];[now exists Plus, 0%nat|].
assert (Heq: (l ++ [Plus; Plus] ++ Plus :: d::r') = ((l++[Plus]) ++ [Plus;Plus] ++ d :: r')).
{
simpl. rewrite <- app_assoc. reflexivity.
}
rewrite Heq in NotReduce.
apply IHr in NotReduce;[|discriminate].
destruct NotReduce as [lst [n _eqr]].
rewrite _eqr. exists lst, (1+n)%nat. reflexivity.
+ destruct r as [|d r'];[now exists Minus, 0%nat|].
destruct d.
* contradict NotReduce. simpl. exists ((l ++ [Plus]) ++ [Plus] ++ r').
assert(Heq: (l ++ Plus :: Plus :: Minus :: Plus :: r') = ((l ++ [Plus]) ++ [Plus ; Minus ; Plus] ++ r')).
{ rewrite <- app_assoc. reflexivity. }
rewrite Heq. now auto.
* contradict NotReduce. simpl. exists (l ++ [Plus; Minus] ++ r').
change (l ++ Plus :: Plus :: Minus :: Minus :: r') with (l ++ [Plus; Plus; Minus; Minus] ++ r').
now auto.
Qed.
- contradiction.
- intros l NotReduce _Hnil. clear _Hnil. destruct d.
+ destruct r as [|d r'];[now exists Plus, 0%nat|].
assert (Heq: (l ++ [Plus; Plus] ++ Plus :: d::r') = ((l++[Plus]) ++ [Plus;Plus] ++ d :: r')).
{
simpl. rewrite <- app_assoc. reflexivity.
}
rewrite Heq in NotReduce.
apply IHr in NotReduce;[|discriminate].
destruct NotReduce as [lst [n _eqr]].
rewrite _eqr. exists lst, (1+n)%nat. reflexivity.
+ destruct r as [|d r'];[now exists Minus, 0%nat|].
destruct d.
* contradict NotReduce. simpl. exists ((l ++ [Plus]) ++ [Plus] ++ r').
assert(Heq: (l ++ Plus :: Plus :: Minus :: Plus :: r') = ((l ++ [Plus]) ++ [Plus ; Minus ; Plus] ++ r')).
{ rewrite <- app_assoc. reflexivity. }
rewrite Heq. now auto.
* contradict NotReduce. simpl. exists (l ++ [Plus; Minus] ++ r').
change (l ++ Plus :: Plus :: Minus :: Minus :: r') with (l ++ [Plus; Plus; Minus; Minus] ++ r').
now auto.
Qed.
Lemma ReduceDir_reduced_form_MinusMinus l r:
~ CanReduceDirStep (l ++ [Minus;Minus] ++ r) -> r <> [] ->
exists lst (n: nat), r = (List.repeat Minus n) ++ [lst].
Proof.
revert l. induction r as [|d r IHr].
- contradiction.
- intros l NotReduce _Hnil. clear _Hnil. destruct d.
+ destruct r as [|d r'];[now exists Plus, 0%nat|].
destruct d.
* contradict NotReduce. simpl. exists (l ++ [Minus; Plus] ++ r').
change (l ++ Minus :: Minus :: Plus :: Plus :: r') with (l ++ [Minus; Minus; Plus; Plus] ++ r').
now auto.
* contradict NotReduce. simpl. exists ((l ++ [Minus]) ++ [Minus] ++ r').
assert(Heq: (l ++ Minus :: Minus :: Plus :: Minus :: r') = ((l ++ [Minus]) ++ [Minus ; Plus ; Minus] ++ r')).
{ rewrite <- app_assoc. reflexivity. }
rewrite Heq. now auto.
+ destruct r as [|d r'];[now exists Minus, 0%nat|].
assert (Heq: (l ++ [Minus; Minus] ++ Minus :: d::r') = ((l++[Minus]) ++ [Minus;Minus] ++ d :: r')).
{
simpl. rewrite <- app_assoc. reflexivity.
}
rewrite Heq in NotReduce.
apply IHr in NotReduce;[|discriminate].
destruct NotReduce as [lst [n _eqr]].
rewrite _eqr. exists lst, (1+n)%nat. reflexivity.
Qed.
- contradiction.
- intros l NotReduce _Hnil. clear _Hnil. destruct d.
+ destruct r as [|d r'];[now exists Plus, 0%nat|].
destruct d.
* contradict NotReduce. simpl. exists (l ++ [Minus; Plus] ++ r').
change (l ++ Minus :: Minus :: Plus :: Plus :: r') with (l ++ [Minus; Minus; Plus; Plus] ++ r').
now auto.
* contradict NotReduce. simpl. exists ((l ++ [Minus]) ++ [Minus] ++ r').
assert(Heq: (l ++ Minus :: Minus :: Plus :: Minus :: r') = ((l ++ [Minus]) ++ [Minus ; Plus ; Minus] ++ r')).
{ rewrite <- app_assoc. reflexivity. }
rewrite Heq. now auto.
+ destruct r as [|d r'];[now exists Minus, 0%nat|].
assert (Heq: (l ++ [Minus; Minus] ++ Minus :: d::r') = ((l++[Minus]) ++ [Minus;Minus] ++ d :: r')).
{
simpl. rewrite <- app_assoc. reflexivity.
}
rewrite Heq in NotReduce.
apply IHr in NotReduce;[|discriminate].
destruct NotReduce as [lst [n _eqr]].
rewrite _eqr. exists lst, (1+n)%nat. reflexivity.
Qed.
Lemma ReduceDir_reduced_form_MinusPlusRepeat: forall (n: nat) r,
~ CanReduceDirStep (Minus :: Plus :: (List.repeat Minus n) ++ r)
-> n = 0%nat.
Proof.
Lemma ReduceDir_reduced_form_PlusMinusRepeat: forall (n: nat) r,
~ CanReduceDirStep (Plus :: Minus :: (List.repeat Plus n) ++ r)
-> n = 0%nat.
Proof.
Lemma repeat_last_P n lst x: x = repeat Plus n ++ [lst] -> exists n' m', (m' <= 1)%nat /\ x = repeat Plus n' ++ repeat Minus m'.
Proof.
Lemma repeat_last_M n lst x: x = repeat Minus n ++ [lst] -> exists n' m', (m' <= 1)%nat /\ x = repeat Minus n' ++ repeat Plus m'.
Proof.
Open Scope nat_scope.
Lemma reduced_form : forall (x: list Direction), ~ CanReduceDirStep x
-> exists (l m n:nat), (l <= 1) /\ (n <= 1) /\
(x = (List.repeat Plus l) ++ (List.repeat Minus m) ++ (List.repeat Plus n) \/
x = (List.repeat Minus l) ++ (List.repeat Plus m) ++ (List.repeat Minus n)).
Proof.
intros x. induction x as [|h x IHx];[exists 0, 0, 0; split;try now auto|].
intros NotReduce. apply tl_cannot_reduce in NotReduce as NotReducex. apply IHx in NotReducex. clear IHx. destruct NotReducex as [l [m [n [l1 [n1 [PMP | MPM]]]]]].
- destruct h.
+ destruct l as [|l].
* exists 1, m, n. split; try split; try now auto. left. rewrite PMP. reflexivity.
* destruct l as [|l];[|apply le_S_n in l1; apply Nat.nle_succ_0 in l1; contradiction].
simpl in PMP. destruct m as [|m];[exists 0,(2+n),0; split;[now auto|split;[now auto|right; rewrite PMP;now rewrite app_nil_r]]|].
rewrite PMP in NotReduce. change (Plus :: Plus :: repeat Minus (S m) ++ repeat Plus n) with ([] ++ [Plus; Plus] ++ (Minus :: repeat Minus m ++ repeat Plus n)) in NotReduce. apply ReduceDir_reduced_form_PlusPlus in NotReduce;[|now auto].
destruct NotReduce as [lst [m' eq]]. simpl in PMP. rewrite eq in PMP. change (Plus :: repeat Plus m' ++ [lst]) with (repeat Plus (1+m') ++ [lst]) in PMP. apply repeat_last_P in PMP.
destruct PMP as [m'' [n' [Hle eq']]]. exists 0,(1+m''),n'.
split;[now auto | split;[now auto| right]]. rewrite eq'. reflexivity.
+ destruct l as [|l]; [exists 0, (1+m), n; split; [now auto|]; split; [now auto|]; left; now rewrite PMP |].
destruct l as [|l].
* simpl in PMP. rewrite PMP in NotReduce. apply ReduceDir_reduced_form_MinusPlusRepeat in NotReduce. subst. simpl.
exists 1, (1+n), 0. split;[now auto| split]; [now auto|right]. rewrite app_nil_r. reflexivity.
* apply le_S_n in l1. apply Nat.nle_succ_0 in l1; contradiction.
- destruct h.
+ destruct l as [|l]; [exists 0, (1+m), n; split; [now auto|]; split; [now auto|]; right; now rewrite MPM |].
destruct l as [|l].
* simpl in MPM. rewrite MPM in NotReduce. apply ReduceDir_reduced_form_PlusMinusRepeat in NotReduce. subst. simpl.
exists 1, (1+n), 0. split;[now auto| split]; [now auto|left]. rewrite app_nil_r. reflexivity.
* apply le_S_n in l1. apply Nat.nle_succ_0 in l1; contradiction.
+ destruct l as [|l].
* exists 1, m, n. split; try split; try now auto. right. rewrite MPM. reflexivity.
* destruct l as [|l];[|apply le_S_n in l1; apply Nat.nle_succ_0 in l1; contradiction].
simpl in MPM. destruct m as [|m];[exists 0,(2+n),0; split;[now auto|split;[now auto|left; rewrite MPM;now rewrite app_nil_r]]|].
rewrite MPM in NotReduce. change (Minus :: Minus :: repeat Plus (S m) ++ repeat Minus n) with ([] ++ [Minus;Minus] ++ (Plus :: repeat Plus m ++ repeat Minus n)) in NotReduce. apply ReduceDir_reduced_form_MinusMinus in NotReduce;[|now auto].
destruct NotReduce as [lst [m' eq]]. simpl in MPM. rewrite eq in MPM. change (Minus :: repeat Minus m' ++ [lst]) with (repeat Minus (1+m') ++ [lst]) in MPM. apply repeat_last_M in MPM.
destruct MPM as [m'' [n' [Hle eq']]]. exists 0,(1+m''),n'.
split;[now auto | split;[now auto| left]]. rewrite eq'. reflexivity.
Qed.
intros NotReduce. apply tl_cannot_reduce in NotReduce as NotReducex. apply IHx in NotReducex. clear IHx. destruct NotReducex as [l [m [n [l1 [n1 [PMP | MPM]]]]]].
- destruct h.
+ destruct l as [|l].
* exists 1, m, n. split; try split; try now auto. left. rewrite PMP. reflexivity.
* destruct l as [|l];[|apply le_S_n in l1; apply Nat.nle_succ_0 in l1; contradiction].
simpl in PMP. destruct m as [|m];[exists 0,(2+n),0; split;[now auto|split;[now auto|right; rewrite PMP;now rewrite app_nil_r]]|].
rewrite PMP in NotReduce. change (Plus :: Plus :: repeat Minus (S m) ++ repeat Plus n) with ([] ++ [Plus; Plus] ++ (Minus :: repeat Minus m ++ repeat Plus n)) in NotReduce. apply ReduceDir_reduced_form_PlusPlus in NotReduce;[|now auto].
destruct NotReduce as [lst [m' eq]]. simpl in PMP. rewrite eq in PMP. change (Plus :: repeat Plus m' ++ [lst]) with (repeat Plus (1+m') ++ [lst]) in PMP. apply repeat_last_P in PMP.
destruct PMP as [m'' [n' [Hle eq']]]. exists 0,(1+m''),n'.
split;[now auto | split;[now auto| right]]. rewrite eq'. reflexivity.
+ destruct l as [|l]; [exists 0, (1+m), n; split; [now auto|]; split; [now auto|]; left; now rewrite PMP |].
destruct l as [|l].
* simpl in PMP. rewrite PMP in NotReduce. apply ReduceDir_reduced_form_MinusPlusRepeat in NotReduce. subst. simpl.
exists 1, (1+n), 0. split;[now auto| split]; [now auto|right]. rewrite app_nil_r. reflexivity.
* apply le_S_n in l1. apply Nat.nle_succ_0 in l1; contradiction.
- destruct h.
+ destruct l as [|l]; [exists 0, (1+m), n; split; [now auto|]; split; [now auto|]; right; now rewrite MPM |].
destruct l as [|l].
* simpl in MPM. rewrite MPM in NotReduce. apply ReduceDir_reduced_form_PlusMinusRepeat in NotReduce. subst. simpl.
exists 1, (1+n), 0. split;[now auto| split]; [now auto|left]. rewrite app_nil_r. reflexivity.
* apply le_S_n in l1. apply Nat.nle_succ_0 in l1; contradiction.
+ destruct l as [|l].
* exists 1, m, n. split; try split; try now auto. right. rewrite MPM. reflexivity.
* destruct l as [|l];[|apply le_S_n in l1; apply Nat.nle_succ_0 in l1; contradiction].
simpl in MPM. destruct m as [|m];[exists 0,(2+n),0; split;[now auto|split;[now auto|left; rewrite MPM;now rewrite app_nil_r]]|].
rewrite MPM in NotReduce. change (Minus :: Minus :: repeat Plus (S m) ++ repeat Minus n) with ([] ++ [Minus;Minus] ++ (Plus :: repeat Plus m ++ repeat Minus n)) in NotReduce. apply ReduceDir_reduced_form_MinusMinus in NotReduce;[|now auto].
destruct NotReduce as [lst [m' eq]]. simpl in MPM. rewrite eq in MPM. change (Minus :: repeat Minus m' ++ [lst]) with (repeat Minus (1+m') ++ [lst]) in MPM. apply repeat_last_M in MPM.
destruct MPM as [m'' [n' [Hle eq']]]. exists 0,(1+m''),n'.
split;[now auto | split;[now auto| left]]. rewrite eq'. reflexivity.
Qed.
Notation have_common_reduce ds1 ds2 := (exists ds', ReduceDir ds1 ds' /\ ReduceDir ds2 ds').
Lemma non_overlap_reduction_confluence l c r ds1 ds2 ds1' ds2':
Rule ds1 ds1' -> Rule ds2 ds2' ->
have_common_reduce (l ++ ds1' ++ c ++ ds2 ++ r) (l ++ ds1 ++ c ++ ds2' ++ r).
Proof.
Lemma Rule_app_inv r1 r2 ds1l ds1r ds1 ds2 ds1' ds2':
ds1r <> [] -> ds1 = ds1l ++ ds1r ->
Rule ds1 ds1' ->
Rule ds2 ds2' ->
ds2 ++ r2 = ds1r ++ r1 ->
(ds1l = [] /\ ds1r = ds2)
\/ (ds1l = [Plus] /\ ds1r = [Minus; Plus] /\ ds2 = [Minus; Plus; Minus])
\/ (ds1l = [Minus] /\ ds1r = [Plus; Minus] /\ ds2 = [Plus; Minus; Plus])
\/ (ds1l = [Plus; Minus] /\ ds1r = [Plus] /\ ds2 = [Plus; Minus; Plus])
\/ (ds1l = [Minus; Plus] /\ ds1r = [Minus] /\ ds2 = [Minus; Plus; Minus])
\/ (ds1l = [Plus; Minus] /\ ds1r = [Plus] /\ ds2 = [Plus; Plus; Minus; Minus])
\/ (ds1l = [Minus; Plus] /\ ds1r = [Minus] /\ ds2 = [Minus; Minus; Plus; Plus])
\/ (ds1l = [Plus; Plus] /\ ds1r = [Minus; Minus] /\ ds2 = [Minus; Minus; Plus; Plus])
\/ (ds1l = [Minus; Minus] /\ ds1r = [Plus; Plus] /\ ds2 = [Plus; Plus; Minus; Minus])
\/ (ds1l = [Plus; Plus; Minus] /\ ds1r = [Minus] /\ ds2 = [Minus; Plus; Minus])
\/ (ds1l = [Plus; Plus; Minus] /\ ds1r = [Minus] /\ ds2 = [Minus; Minus; Plus; Plus])
\/ (ds1l = [Minus; Minus; Plus] /\ ds1r = [Plus] /\ ds2 = [Plus; Minus; Plus])
\/ (ds1l = [Minus; Minus; Plus] /\ ds1r = [Plus] /\ ds2 = [Plus; Plus; Minus; Minus])
.
Proof.
intros nonnil eds1 rule1 rule2 prefix_ds2.
destruct ds1r as [|d ds1r]; [now auto|].
assert (or4: ds1l = []
\/ (exists d0, ds1l = [d0])
\/ (exists d0 d1, ds1l = [d0; d1])
\/ (exists d0 d1 d2, ds1l = [d0; d1; d2])
).
+ destruct ds1l as [|d0]; [now left|].
destruct ds1l as [|d1]; [now right; left; exists d0|].
destruct ds1l as [|d2]; [now right; right; left; exists d0, d1|].
destruct ds1l as [|d3]; [now right; right; right; exists d0, d1, d2|].
simpl in eds1. rewrite eds1 in rule1.
now destruct ds1l; inversion rule1.
+ destruct or4 as [|[ [d0 e0] |[ [d0 [d1 e]] | [d0 [d1 [d2 e]]]]
]];
destruct rule1, rule2; subst; try inversion eds1; subst; try now auto; try tauto.
Qed.
destruct ds1r as [|d ds1r]; [now auto|].
assert (or4: ds1l = []
\/ (exists d0, ds1l = [d0])
\/ (exists d0 d1, ds1l = [d0; d1])
\/ (exists d0 d1 d2, ds1l = [d0; d1; d2])
).
+ destruct ds1l as [|d0]; [now left|].
destruct ds1l as [|d1]; [now right; left; exists d0|].
destruct ds1l as [|d2]; [now right; right; left; exists d0, d1|].
destruct ds1l as [|d3]; [now right; right; right; exists d0, d1, d2|].
simpl in eds1. rewrite eds1 in rule1.
now destruct ds1l; inversion rule1.
+ destruct or4 as [|[ [d0 e0] |[ [d0 [d1 e]] | [d0 [d1 [d2 e]]]]
]];
destruct rule1, rule2; subst; try inversion eds1; subst; try now auto; try tauto.
Qed.
Lemma eq_have_common_reduce ds1 ds2: ds1 = ds2 -> have_common_reduce ds1 ds2.
Proof.
Lemma ReduceDirStep_Reduce_dir ds ds': ReduceDirStep ds ds' -> ReduceDir ds ds'.
Lemma ReduceDir_local_confluence_aux l1 r1 ds1 ds1' l2 r2 ds2 ds2':
Rule ds1 ds1' ->
Rule ds2 ds2' ->
l2 ++ ds2 ++ r2 = l1 ++ ds1 ++ r1 ->
Prefix l1 l2 ->
have_common_reduce (l1 ++ ds1' ++ r1) (l2 ++ ds2' ++ r2).
Proof.
intros rule1 rule2 e prefix.
destruct (prefix) as [l1' prefix_]. subst l2.
rewrite <- app_assoc, app_inv_head_iff in e.
destruct (ds1 =? l1').
- (* ds1 = l1' の場合: rule1,2で重ならない *)
rewrite <- app_assoc. subst l1'.
rewrite app_inv_head_iff in e. subst r1.
now apply (non_overlap_reduction_confluence l1 []).
- destruct (@prefix_brothers_is_prefix _ ds1 l1' (ds1 ++ r1)) as[prefix'|prefix'].
+ now auto.
+ now rewrite <- e.
+ (* ds1 < l1' の場合: rule1,2で重ならない *)
destruct prefix' as [l1'']. subst l1'.
rewrite <- app_assoc, app_inv_head_iff in e. subst r1.
repeat rewrite <- app_assoc.
now apply non_overlap_reduction_confluence.
+ (* ds1 > l1' の場合: 重なるパターンを考える *)
repeat rewrite <- app_assoc.
destruct prefix' as [ds1_r ]. subst ds1.
rewrite <- app_assoc, app_inv_head_iff in e.
assert (nonnil: ds1_r <> []);
[now intros enil; rewrite enil, app_nil_r in n|].
destruct (Rule_app_inv r1 r2 l1' ds1_r (l1' ++ ds1_r) ds2 ds1' ds2' nonnil (refl_equal _) rule1 rule2 e) as
[es|[es|[es|[es|[es|[es|[es|[es|[es|[es|[es|[es|es]]]] ]]]]]]]].
* destruct es as [e1 e2]. subst. simpl in *.
rewrite (Rule_same_src _ _ _ rule1 rule2).
rewrite (app_inv_head _ _ _ e).
now apply eq_have_common_reduce.
* destruct es as [e1 [e2 e3]]; subst.
inversion rule1. subst. inversion rule2. subst.
apply eq_have_common_reduce.
do 2 f_equal. now inversion e.
* destruct es as [e1 [e2 e3]]; subst.
inversion rule1. inversion rule2. subst.
apply eq_have_common_reduce.
do 2 f_equal. now inversion e.
* destruct es as [e1 [e2 e3]]; subst.
inversion rule1. inversion rule2. subst.
apply eq_have_common_reduce. now rewrite <- e .
* destruct es as [e1 [e2 e3]]; subst.
inversion rule1. inversion rule2. subst.
apply eq_have_common_reduce. now rewrite <- e .
* destruct es as [e1 [e2 e3]]; subst.
inversion rule1. inversion rule2. subst.
exists (l1 ++ [Plus; Minus] ++r2). rewrite <- e.
split; apply ReduceDirStep_Reduce_dir; [now constructor|].
change ([Plus; Minus] ++ [Plus; Minus] ++ r2) with ([Plus; Minus; Plus] ++ [Minus] ++ r2).
now change ([Plus; Minus] ++ r2) with ([Plus] ++ [Minus] ++ r2).
* destruct es as [e1 [e2 e3]]; subst.
inversion rule1. inversion rule2. subst.
exists (l1 ++ [Minus; Plus] ++ r2). rewrite <- e.
split; apply ReduceDirStep_Reduce_dir; [now constructor|].
change ([Minus; Plus] ++ [Minus; Plus] ++ r2) with ([Minus; Plus; Minus] ++ [Plus] ++ r2).
now change ([Minus; Plus] ++ r2) with ([Minus] ++ [Plus]++r2).
* destruct es as [e1 [e2 e3]]; subst.
inversion rule1. inversion rule2. subst. inversion e.
exists (l1 ++ [Plus] ++ Plus::r2).
change ([Plus; Minus] ++ Plus :: Plus :: r2) with ([Plus; Minus; Plus] ++ Plus :: r2).
split; apply ReduceDirStep_Reduce_dir; [now repeat constructor|].
change ([Plus; Plus] ++ [Minus; Plus] ++ r2) with ([Plus] ++ [Plus; Minus; Plus] ++ r2).
change (Plus :: r2) with ([Plus] ++ r2).
now do 2 rewrite (app_assoc l1).
* destruct es as [e1 [e2 e3]]; subst.
inversion rule1. inversion rule2. subst. inversion e. subst.
exists (l1 ++ [Minus; Minus] ++ r2). split; apply ReduceDirStep_Reduce_dir.
-- replace (l1 ++ [Minus; Plus] ++ Minus :: Minus :: r2)
with ((l1 ++ [Minus;Plus;Minus] ++ ([Minus] ++ r2))); [|reflexivity].
now change (l1 ++ [Minus; Minus] ++ r2) with (l1 ++ [Minus] ++ ([Minus] ++ r2)).
-- replace (l1 ++ [Minus; Minus] ++ [Plus; Minus] ++ r2)
with ((l1 ++ [Minus]) ++ [Minus;Plus; Minus] ++ r2); [|now rewrite <- app_assoc].
now replace (l1 ++ [Minus; Minus] ++ r2) with ((l1 ++ [Minus]) ++ [Minus] ++ r2);
[|now rewrite <- app_assoc].
* destruct es as [e1 [e2 e3]]; subst.
inversion rule1. inversion rule2. subst. inversion e. subst r1.
exists (l1 ++ [Plus; Minus] ++ r2); split; apply ReduceDirStep_Reduce_dir.
-- change (l1 ++ [Plus;Minus] ++ Plus :: Minus :: r2) with
(l1 ++ [Plus;Minus;Plus]++([Minus] ++ r2)).
now change (l1 ++ [Plus;Minus] ++ r2) with (l1 ++ [Plus] ++ ([Minus] ++ r2)).
-- now change ([Plus;Plus;Minus] ++ [Minus] ++ r2) with
([Plus; Plus; Minus; Minus] ++ r2).
* destruct es as [e1 [e2 e3]]; subst.
inversion rule1. inversion rule2. subst. inversion e. subst r1.
exists ((l1 ++ [Plus]) ++ [Minus; Plus] ++ r2). split; apply ReduceDirStep_Reduce_dir.
-- now replace (l1 ++ [Plus;Minus] ++ Minus::Plus::Plus::r2)
with ((l1 ++ [Plus]) ++ [Minus;Minus;Plus;Plus] ++ r2);
[|now rewrite <- app_assoc].
-- change (l1 ++ [Plus;Plus;Minus]++[Minus; Plus] ++ r2)
with (l1 ++ [Plus;Plus;Minus;Minus]++ ([Plus] ++ r2)).
now replace ((l1 ++ [Plus]) ++ [Minus;Plus] ++ r2)
with (l1 ++ [Plus;Minus] ++ ([Plus] ++ r2)); [|now rewrite <- app_assoc].
* destruct es as [e1 [e2 e3]]; subst.
inversion rule1. inversion rule2. subst. inversion e; subst r1.
exists (l1 ++ [Minus; Plus] ++ r2). split; apply ReduceDirStep_Reduce_dir.
-- change (l1 ++ [Minus; Plus] ++ Minus:: Plus :: r2) with (l1 ++ [Minus; Plus; Minus] ++ ([Plus]++r2)).
now change (l1 ++ [Minus; Plus] ++ r2) with (l1 ++ [Minus] ++ ([Plus] ++ r2)).
-- now change ([Minus; Minus; Plus] ++ [Plus] ++ r2)
with ([Minus; Minus; Plus; Plus] ++ r2).
* destruct es as [e1 [e2 e3]]; subst.
inversion rule1. inversion rule2. subst. inversion e. subst r1.
exists (l1 ++ [Minus; Plus] ++ ([Minus] ++ r2)). split; apply ReduceDirStep_Reduce_dir.
-- replace (l1 ++ [Minus; Plus] ++ Plus :: Minus:: Minus ::r2)
with ((l1 ++ [Minus]) ++ [Plus; Plus; Minus; Minus] ++ r2);
[|now rewrite <- app_assoc].
now replace (l1 ++ [Minus;Plus] ++ [Minus] ++ r2)
with ((l1 ++ [Minus]) ++ [Plus;Minus] ++ r2); [|now rewrite <- app_assoc].
-- now change ([Minus; Minus; Plus] ++ [Plus; Minus] ++ r2)
with ([Minus;Minus;Plus;Plus] ++ [Minus]++r2).
Qed.
destruct (prefix) as [l1' prefix_]. subst l2.
rewrite <- app_assoc, app_inv_head_iff in e.
destruct (ds1 =? l1').
- (* ds1 = l1' の場合: rule1,2で重ならない *)
rewrite <- app_assoc. subst l1'.
rewrite app_inv_head_iff in e. subst r1.
now apply (non_overlap_reduction_confluence l1 []).
- destruct (@prefix_brothers_is_prefix _ ds1 l1' (ds1 ++ r1)) as[prefix'|prefix'].
+ now auto.
+ now rewrite <- e.
+ (* ds1 < l1' の場合: rule1,2で重ならない *)
destruct prefix' as [l1'']. subst l1'.
rewrite <- app_assoc, app_inv_head_iff in e. subst r1.
repeat rewrite <- app_assoc.
now apply non_overlap_reduction_confluence.
+ (* ds1 > l1' の場合: 重なるパターンを考える *)
repeat rewrite <- app_assoc.
destruct prefix' as [ds1_r ]. subst ds1.
rewrite <- app_assoc, app_inv_head_iff in e.
assert (nonnil: ds1_r <> []);
[now intros enil; rewrite enil, app_nil_r in n|].
destruct (Rule_app_inv r1 r2 l1' ds1_r (l1' ++ ds1_r) ds2 ds1' ds2' nonnil (refl_equal _) rule1 rule2 e) as
[es|[es|[es|[es|[es|[es|[es|[es|[es|[es|[es|[es|es]]]] ]]]]]]]].
* destruct es as [e1 e2]. subst. simpl in *.
rewrite (Rule_same_src _ _ _ rule1 rule2).
rewrite (app_inv_head _ _ _ e).
now apply eq_have_common_reduce.
* destruct es as [e1 [e2 e3]]; subst.
inversion rule1. subst. inversion rule2. subst.
apply eq_have_common_reduce.
do 2 f_equal. now inversion e.
* destruct es as [e1 [e2 e3]]; subst.
inversion rule1. inversion rule2. subst.
apply eq_have_common_reduce.
do 2 f_equal. now inversion e.
* destruct es as [e1 [e2 e3]]; subst.
inversion rule1. inversion rule2. subst.
apply eq_have_common_reduce. now rewrite <- e .
* destruct es as [e1 [e2 e3]]; subst.
inversion rule1. inversion rule2. subst.
apply eq_have_common_reduce. now rewrite <- e .
* destruct es as [e1 [e2 e3]]; subst.
inversion rule1. inversion rule2. subst.
exists (l1 ++ [Plus; Minus] ++r2). rewrite <- e.
split; apply ReduceDirStep_Reduce_dir; [now constructor|].
change ([Plus; Minus] ++ [Plus; Minus] ++ r2) with ([Plus; Minus; Plus] ++ [Minus] ++ r2).
now change ([Plus; Minus] ++ r2) with ([Plus] ++ [Minus] ++ r2).
* destruct es as [e1 [e2 e3]]; subst.
inversion rule1. inversion rule2. subst.
exists (l1 ++ [Minus; Plus] ++ r2). rewrite <- e.
split; apply ReduceDirStep_Reduce_dir; [now constructor|].
change ([Minus; Plus] ++ [Minus; Plus] ++ r2) with ([Minus; Plus; Minus] ++ [Plus] ++ r2).
now change ([Minus; Plus] ++ r2) with ([Minus] ++ [Plus]++r2).
* destruct es as [e1 [e2 e3]]; subst.
inversion rule1. inversion rule2. subst. inversion e.
exists (l1 ++ [Plus] ++ Plus::r2).
change ([Plus; Minus] ++ Plus :: Plus :: r2) with ([Plus; Minus; Plus] ++ Plus :: r2).
split; apply ReduceDirStep_Reduce_dir; [now repeat constructor|].
change ([Plus; Plus] ++ [Minus; Plus] ++ r2) with ([Plus] ++ [Plus; Minus; Plus] ++ r2).
change (Plus :: r2) with ([Plus] ++ r2).
now do 2 rewrite (app_assoc l1).
* destruct es as [e1 [e2 e3]]; subst.
inversion rule1. inversion rule2. subst. inversion e. subst.
exists (l1 ++ [Minus; Minus] ++ r2). split; apply ReduceDirStep_Reduce_dir.
-- replace (l1 ++ [Minus; Plus] ++ Minus :: Minus :: r2)
with ((l1 ++ [Minus;Plus;Minus] ++ ([Minus] ++ r2))); [|reflexivity].
now change (l1 ++ [Minus; Minus] ++ r2) with (l1 ++ [Minus] ++ ([Minus] ++ r2)).
-- replace (l1 ++ [Minus; Minus] ++ [Plus; Minus] ++ r2)
with ((l1 ++ [Minus]) ++ [Minus;Plus; Minus] ++ r2); [|now rewrite <- app_assoc].
now replace (l1 ++ [Minus; Minus] ++ r2) with ((l1 ++ [Minus]) ++ [Minus] ++ r2);
[|now rewrite <- app_assoc].
* destruct es as [e1 [e2 e3]]; subst.
inversion rule1. inversion rule2. subst. inversion e. subst r1.
exists (l1 ++ [Plus; Minus] ++ r2); split; apply ReduceDirStep_Reduce_dir.
-- change (l1 ++ [Plus;Minus] ++ Plus :: Minus :: r2) with
(l1 ++ [Plus;Minus;Plus]++([Minus] ++ r2)).
now change (l1 ++ [Plus;Minus] ++ r2) with (l1 ++ [Plus] ++ ([Minus] ++ r2)).
-- now change ([Plus;Plus;Minus] ++ [Minus] ++ r2) with
([Plus; Plus; Minus; Minus] ++ r2).
* destruct es as [e1 [e2 e3]]; subst.
inversion rule1. inversion rule2. subst. inversion e. subst r1.
exists ((l1 ++ [Plus]) ++ [Minus; Plus] ++ r2). split; apply ReduceDirStep_Reduce_dir.
-- now replace (l1 ++ [Plus;Minus] ++ Minus::Plus::Plus::r2)
with ((l1 ++ [Plus]) ++ [Minus;Minus;Plus;Plus] ++ r2);
[|now rewrite <- app_assoc].
-- change (l1 ++ [Plus;Plus;Minus]++[Minus; Plus] ++ r2)
with (l1 ++ [Plus;Plus;Minus;Minus]++ ([Plus] ++ r2)).
now replace ((l1 ++ [Plus]) ++ [Minus;Plus] ++ r2)
with (l1 ++ [Plus;Minus] ++ ([Plus] ++ r2)); [|now rewrite <- app_assoc].
* destruct es as [e1 [e2 e3]]; subst.
inversion rule1. inversion rule2. subst. inversion e; subst r1.
exists (l1 ++ [Minus; Plus] ++ r2). split; apply ReduceDirStep_Reduce_dir.
-- change (l1 ++ [Minus; Plus] ++ Minus:: Plus :: r2) with (l1 ++ [Minus; Plus; Minus] ++ ([Plus]++r2)).
now change (l1 ++ [Minus; Plus] ++ r2) with (l1 ++ [Minus] ++ ([Plus] ++ r2)).
-- now change ([Minus; Minus; Plus] ++ [Plus] ++ r2)
with ([Minus; Minus; Plus; Plus] ++ r2).
* destruct es as [e1 [e2 e3]]; subst.
inversion rule1. inversion rule2. subst. inversion e. subst r1.
exists (l1 ++ [Minus; Plus] ++ ([Minus] ++ r2)). split; apply ReduceDirStep_Reduce_dir.
-- replace (l1 ++ [Minus; Plus] ++ Plus :: Minus:: Minus ::r2)
with ((l1 ++ [Minus]) ++ [Plus; Plus; Minus; Minus] ++ r2);
[|now rewrite <- app_assoc].
now replace (l1 ++ [Minus;Plus] ++ [Minus] ++ r2)
with ((l1 ++ [Minus]) ++ [Plus;Minus] ++ r2); [|now rewrite <- app_assoc].
-- now change ([Minus; Minus; Plus] ++ [Plus; Minus] ++ r2)
with ([Minus;Minus;Plus;Plus] ++ [Minus]++r2).
Qed.
Lemma exists_iff {A:Type} (P Q : A -> Prop) :
(forall x, P x <-> Q x) -> (exists x, P x) <-> (exists x, Q x).
Proof.
intros pq. now split; intros [x p]; exists x; [rewrite <- pq| rewrite pq].
Qed.
Qed.
Lemma ReduceDir_local_confluence src dst1 dst2:
ReduceDirStep src dst1 ->
ReduceDirStep src dst2 ->
have_common_reduce dst1 dst2.
Proof.
intros step1 step2.
inversion step1 as [l1 r1 ds1 ds1' rule1 e1 e2].
inversion step2 as [l2 r2 ds2 ds2' rule2 e12 e22]. subst.
destruct (@prefix_brothers_is_prefix _ l1 l2 (l1 ++ (ds1 ++ r1))) as [prefix|prefix].
- now auto.
- now rewrite <- e12.
- now apply (ReduceDir_local_confluence_aux _ _ _ _ _ _ _ _ rule1 rule2).
- rewrite (exists_iff _ _ (fun ds => and_comm _ _)).
now eapply (ReduceDir_local_confluence_aux _ _ _ _ _ _ _ _ rule2 rule1).
Qed.
inversion step1 as [l1 r1 ds1 ds1' rule1 e1 e2].
inversion step2 as [l2 r2 ds2 ds2' rule2 e12 e22]. subst.
destruct (@prefix_brothers_is_prefix _ l1 l2 (l1 ++ (ds1 ++ r1))) as [prefix|prefix].
- now auto.
- now rewrite <- e12.
- now apply (ReduceDir_local_confluence_aux _ _ _ _ _ _ _ _ rule1 rule2).
- rewrite (exists_iff _ _ (fun ds => and_comm _ _)).
now eapply (ReduceDir_local_confluence_aux _ _ _ _ _ _ _ _ rule2 rule1).
Qed.