Created
December 4, 2017 22:14
-
-
Save fetburner/3e48c8a947206ad843a724f5039302f6 to your computer and use it in GitHub Desktop.
TPPmark 2017
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Require Import List Omega Program. | |
Section ListPairDP. | |
Variable A : Set. | |
Variable X : Set. | |
Variable f_nil_nil : A. | |
Variable f_nil_l2s : list (A * X). | |
Variable f_l1_nils : list (A * X). | |
Variable f_cons_cons : X -> X -> A -> A -> A -> A. | |
Variable R : list X -> list X -> A -> Prop. | |
Hypotheses f_nil_nil_spec : R nil nil f_nil_nil. | |
Hypotheses f_nil_l2s_spec : forall i f_nil_l2' y, | |
nth_error f_nil_l2s i = Some (f_nil_l2', y) -> | |
R nil (skipn i (map snd f_nil_l2s)) f_nil_l2'. | |
Hypotheses f_l1_nils_spec : forall i f_l1'_nil x, | |
nth_error f_l1_nils i = Some (f_l1'_nil, x) -> | |
R (skipn i (map snd f_l1_nils)) nil f_l1'_nil. | |
Hypotheses f_cons_cons_spec : forall x l1' y l2' f_l1'_l2' f_l1_l2' f_l1'_l2, | |
R l1' l2' f_l1'_l2' -> | |
R (x :: l1') l2' f_l1_l2' -> | |
R l1' (y :: l2') f_l1'_l2 -> | |
R (x :: l1') (y :: l2') (f_cons_cons x y f_l1'_l2' f_l1_l2' f_l1'_l2). | |
Definition ListPairDP_body {B} x f_l1_nil f_l1'_nil := fix ListPairDP_body k f_l1'_l2s : B := | |
match f_l1'_l2s with | |
| nil => k f_l1'_nil f_l1_nil nil | |
| (f_l1'_l2, y) :: f_l1'_l2's => ListPairDP_body (fun f_l1'_l2' f_l1_l2' memo_l1_l2' => | |
let f_l1_l2 := f_cons_cons x y f_l1'_l2' f_l1_l2' f_l1'_l2 in | |
k f_l1'_l2 f_l1_l2 ((f_l1_l2, y) :: memo_l1_l2')) f_l1'_l2's | |
end. | |
Fixpoint ListPairDP_aux {B} k f_l1_nils : B := | |
match f_l1_nils with | |
| nil => k f_nil_nil (hd f_nil_nil (map fst f_nil_l2s)) f_nil_l2s | |
| (f_l1_nil, x) :: f_l1'_nils => ListPairDP_aux (fun f_l1'_nil _ => | |
ListPairDP_body x f_l1_nil f_l1'_nil (const (k f_l1_nil))) f_l1'_nils | |
end. | |
Definition ListPairDP := ListPairDP_aux (fun _ f_l1_l2 _ => f_l1_l2) f_l1_nils. | |
Lemma ListPairDP_body_spec B (P : B -> Prop) x l1' f_l1_nil f_l1'_nil f_l1'_l2s : | |
R l1' nil f_l1'_nil -> | |
R (x :: l1') nil f_l1_nil -> | |
(forall i f_l1'_l2' y, | |
nth_error f_l1'_l2s i = Some (f_l1'_l2', y) -> | |
R l1' (skipn i (map snd f_l1'_l2s)) f_l1'_l2') -> | |
forall k, | |
(forall f_l1'_l2 f_l1_l2 f_l1_l2s, | |
R l1' (map snd f_l1'_l2s) f_l1'_l2 -> | |
R (x :: l1') (map snd f_l1'_l2s) f_l1_l2 -> | |
map snd f_l1'_l2s = map snd f_l1_l2s -> | |
(forall i f_l1_l2' y, | |
nth_error f_l1_l2s i = Some (f_l1_l2', y) -> | |
R (x :: l1') (skipn i (map snd f_l1'_l2s)) f_l1_l2') -> | |
P (k f_l1'_l2 f_l1_l2 f_l1_l2s)) -> | |
P (ListPairDP_body x f_l1_nil f_l1'_nil k f_l1'_l2s). | |
Proof. | |
intros ? ? Hf_l1'_l2s. | |
induction f_l1'_l2s as [ | [ ] ? IHf_l1'_l2's ]; simpl; intros k Hk. | |
- apply Hk; eauto. | |
intros [ ]; inversion 1. | |
- apply IHf_l1'_l2's. | |
+ intros i. apply Hf_l1'_l2s with (i := S i). | |
+ intros ? ? ? ? ? ? ?. | |
specialize (Hf_l1'_l2s 0 _ _ eq_refl); simpl in *. | |
apply Hk; eauto. | |
* simpl. congruence. | |
* intros [ ]; inversion 1; subst; simpl; eauto. | |
Qed. | |
Lemma ListPairDP_aux_spec B (P : B -> Prop) f_l1'_nils : | |
(forall i f_l1'_nil x, | |
nth_error f_l1'_nils i = Some (f_l1'_nil, x) -> | |
R (skipn i (map snd f_l1'_nils)) nil f_l1'_nil) -> | |
forall k, | |
(forall f_l1_nil f_l1_l2 f_l1_l2s, | |
R (map snd f_l1'_nils) nil f_l1_nil -> | |
R (map snd f_l1'_nils) (map snd f_nil_l2s) f_l1_l2 -> | |
map snd f_nil_l2s = map snd f_l1_l2s -> | |
(forall i f_l1_l2' y, | |
nth_error f_l1_l2s i = Some (f_l1_l2', y) -> | |
R (map snd f_l1'_nils) (skipn i (map snd f_nil_l2s)) f_l1_l2') -> | |
P (k f_l1_nil f_l1_l2 f_l1_l2s)) -> | |
P (ListPairDP_aux k f_l1'_nils). | |
Proof. | |
intros Hf_l1'_nil. | |
induction f_l1'_nils as [ | [ ? ? ] f_l1'_nils IHf_l1'_nils ]; simpl; intros k Hk. | |
- apply Hk; eauto. | |
destruct f_nil_l2s as [ | [ ? ? ]]; simpl in *; eauto. | |
apply (f_nil_l2s_spec 0 _ _ eq_refl). | |
- apply IHf_l1'_nils. | |
+ intros i. apply Hf_l1'_nil with (i := S i). | |
+ specialize (Hf_l1'_nil 0 _ _ eq_refl). simpl in *. | |
intros ? ? ? ? ? Heq ?. | |
rewrite Heq in *. | |
apply ListPairDP_body_spec with (l1' := map snd f_l1'_nils); eauto. | |
Qed. | |
Corollary ListPairDP_spec l1 l2 : | |
l1 = map snd f_l1_nils -> | |
l2 = map snd f_nil_l2s -> | |
R l1 l2 ListPairDP. | |
Proof. | |
intros. | |
subst. | |
apply ListPairDP_aux_spec with (P := R (map snd f_l1_nils) (map snd f_nil_l2s)); eauto. | |
Qed. | |
End ListPairDP. | |
Section LCS. | |
Variable X : Set. | |
Hypotheses X_eq_dec : forall x y : X, { x = y } + { x <> y }. | |
Inductive subseq : list X -> list X -> Prop := | |
| subsq_nil : subseq nil nil | |
| subseq_skip x l1 l2 : | |
subseq l1 l2 -> | |
subseq l1 (x :: l2) | |
| subseq_common x l1 l2 : | |
subseq l1 l2 -> | |
subseq (x :: l1) (x :: l2). | |
Hint Constructors subseq. | |
Lemma subseq_nil l : subseq nil l. | |
Proof. induction l; eauto. Qed. | |
Lemma subseq_tl l l2 : | |
subseq l l2 -> | |
forall x l1, l = x :: l1 -> | |
subseq l1 l2. | |
Proof. induction 1; inversion 1; subst; eauto. Qed. | |
Hint Resolve subseq_nil subseq_tl. | |
Definition LCS_aux l1 l2 := | |
ListPairDP _ _ (0, nil) | |
(map (pair (0, nil)) l2) | |
(map (pair (0, nil)) l1) | |
(fun x y (f_l1'_l2' f_l1_l2' f_l1'_l2 : _ * _) => | |
if X_eq_dec x y then | |
let (n, s) := f_l1'_l2' in (S n, x :: s) | |
else | |
let (n1, s1) := f_l1'_l2 in | |
let (n2, s2) := f_l1_l2' in | |
if le_ge_dec n1 n2 then (n2, s2) else (n1, s1)). | |
Definition LCS l1 l2 := snd (LCS_aux l1 l2). | |
Lemma LCS_aux_subseq l1 l2 : | |
subseq (snd (LCS_aux l1 l2)) l1 /\ subseq (snd (LCS_aux l1 l2)) l2. | |
Proof. | |
refine (ListPairDP_spec _ _ _ _ _ _ (fun l1 l2 p => subseq (snd p) l1 /\ subseq (snd p) l2) _ _ _ _ _ _ _ _); | |
repeat rewrite map_map, map_id; | |
simpl; | |
eauto. | |
- intros ? ? ? HIn. | |
apply nth_error_In in HIn. | |
apply in_map_iff in HIn. | |
destruct HIn as [ ? [ Heq ]]. | |
inversion Heq. subst. eauto. | |
- intros ? ? ? HIn. | |
apply nth_error_In in HIn. | |
apply in_map_iff in HIn. | |
destruct HIn as [ ? [ Heq ]]. | |
inversion Heq. subst. eauto. | |
- intros x ? y ? [ ? s ] [ n1 s1 ] [ n2 s2 ] [ ? ? ] [ ? ? ] [ ? ? ]. | |
destruct (X_eq_dec x y); subst; simpl; eauto. | |
destruct (le_ge_dec n2 n1); eauto. | |
Qed. | |
Corollary LCS_subseq l1 l2 : subseq (LCS l1 l2) l1 /\ subseq (LCS l1 l2) l2. | |
Proof. apply LCS_aux_subseq. Qed. | |
Lemma LCS_aux_longest l1 l2 : | |
let (n, s) := LCS_aux l1 l2 in | |
n = length s /\ (forall l, subseq l l1 -> subseq l l2 -> length l <= length s). | |
Proof. | |
Local Hint Resolve le_n_S. | |
refine (ListPairDP_spec _ _ _ _ _ _ (fun l1 l2 (p : _ * _) => | |
let (n, s) := p in | |
n = length s /\ (forall l, subseq l l1 -> subseq l l2 -> length l <= length s)) _ _ _ _ _ _ _ _); | |
repeat rewrite map_map, map_id; | |
simpl; | |
eauto. | |
- split; eauto. inversion 1; simpl; eauto. | |
- intros ? ? ? HIn. | |
apply nth_error_In in HIn. | |
apply in_map_iff in HIn. | |
destruct HIn as [ ? [ Heq ] ]. | |
inversion Heq. subst. simpl. | |
split; eauto. | |
inversion 1. simpl. eauto. | |
- intros ? ? ? HIn. | |
apply nth_error_In in HIn. | |
apply in_map_iff in HIn. | |
destruct HIn as [ ? [ Heq ] ]. | |
inversion Heq. subst. simpl. | |
split; eauto. | |
inversion 2. simpl. eauto. | |
- intros x ? y ? [ ? ? ] [ n1 ? ] [ n2 ? ] [ ? ? ] [ ? IH2 ] [ ? IH3 ]. | |
destruct (X_eq_dec x y); | |
[ subst | destruct (le_ge_dec n2 n1) ]; simpl; | |
split; eauto; | |
intros ? Hsubseq1 Hsubseq2; | |
inversion Hsubseq1 as [ | ? ? ? Hsubseq1' | ]; subst; | |
inversion Hsubseq2 as [ | ? ? ? Hsubseq2' | ]; subst; | |
try specialize (IH2 _ Hsubseq1 Hsubseq2'); | |
try specialize (IH3 _ Hsubseq1' Hsubseq2); | |
simpl in *; | |
(congruence || omega || eauto). | |
Qed. | |
Corollary LCS_longest l1 l2 l : | |
subseq l l1 -> | |
subseq l l2 -> | |
length l <= length (LCS l1 l2). | |
Proof. | |
unfold LCS. | |
specialize (LCS_aux_longest l1 l2). | |
destruct (LCS_aux l1 l2). | |
intros [ ? ? ]. | |
eauto. | |
Qed. | |
End LCS. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Require Import List Omega. | |
Section LCS. | |
Variable X : Set. | |
Hypotheses X_eq_dec : forall x y : X, { x = y } + { x <> y }. | |
Inductive subseq : list X -> list X -> Prop := | |
| subsq_nil : subseq nil nil | |
| subseq_skip x l1 l2 : | |
subseq l1 l2 -> | |
subseq l1 (x :: l2) | |
| subseq_common x l1 l2 : | |
subseq l1 l2 -> | |
subseq (x :: l1) (x :: l2). | |
Hint Constructors subseq. | |
Lemma subseq_nil l : subseq nil l. | |
Proof. induction l; eauto. Qed. | |
Lemma subseq_tl l l2 : | |
subseq l l2 -> | |
forall x l1, l = x :: l1 -> | |
subseq l1 l2. | |
Proof. induction 1; inversion 1; subst; eauto. Qed. | |
Hint Resolve subseq_nil subseq_tl. | |
Fixpoint LCS_body LCS x l2 := | |
match l2 with | |
| nil => nil | |
| y :: l2' => | |
if X_eq_dec x y then x :: LCS l2' | |
else | |
let s1 := LCS (y :: l2') in | |
let s2 := LCS_body LCS x l2' in | |
if le_ge_dec (length s1) (length s2) then s2 else s1 | |
end. | |
Fixpoint LCS l1 l2 := | |
match l1 with | |
| nil => nil | |
| x :: l1' => LCS_body (LCS l1') x l2 | |
end. | |
Lemma LCS_rect (P : list X -> list X -> Type) (Q : X -> list X -> list X -> Type) : | |
(forall l2, P nil l2) -> | |
(forall x l1 l2, Q x l1 l2 -> P (x :: l1) l2) -> | |
(forall x l1, Q x l1 nil) -> | |
(forall x l1 y l2, P l1 l2 -> P l1 (y :: l2) -> Q x l1 l2 -> Q x l1 (y :: l2)) -> | |
forall l1 l2, P l1 l2. | |
Proof. | |
intros ? IH2 ? ? l1. | |
induction l1; intros l2; eauto. | |
- apply IH2. | |
induction l2; eauto. | |
Qed. | |
Theorem LCS_subseq : forall l1 l2, subseq (LCS l1 l2) l1 /\ subseq (LCS l1 l2) l2. | |
Proof. | |
refine (LCS_rect _ | |
(fun x l1 l2 => | |
subseq (LCS_body (LCS l1) x l2) (x :: l1) /\ subseq (LCS_body (LCS l1) x l2) l2) _ _ _ _); simpl; eauto. | |
intros x l1 y l2 [? ?] [? ?] [? ?]. | |
destruct (X_eq_dec x y); subst; eauto. | |
destruct (le_ge_dec (length (LCS l1 (y :: l2))) (length (LCS_body (LCS l1) x l2))); eauto. | |
Qed. | |
Theorem LCS_longest : forall l1 l2 l, | |
subseq l l1 -> | |
subseq l l2 -> | |
length l <= length (LCS l1 l2). | |
Proof. | |
Local Hint Resolve le_n_S. | |
refine (LCS_rect _ | |
(fun x l1 l2 => forall l, | |
subseq l (x :: l1) -> | |
subseq l l2 -> | |
length l <= length (LCS_body (LCS l1) x l2)) _ _ _ _); simpl; eauto. | |
- inversion 1; simpl; eauto. | |
- inversion 2; simpl; eauto. | |
- intros x l1' y l2' ? IH2 IH3. | |
destruct (X_eq_dec x y); | |
[ subst | destruct (le_ge_dec (length (LCS l1' (y :: l2'))) (length (LCS_body (LCS l1') x l2'))) ]; | |
intros ? Hsubseq1 Hsubseq2; | |
inversion Hsubseq1 as [ | ? ? ? Hsubseq1' | ]; subst; | |
inversion Hsubseq2 as [ | ? ? ? Hsubseq2' | ]; subst; | |
try specialize (IH2 _ Hsubseq1' Hsubseq2); | |
try specialize (IH3 _ Hsubseq1 Hsubseq2'); | |
simpl in *; | |
(congruence || omega || eauto). | |
Qed. | |
End LCS. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment