From Coq Require Import Lia List Setoid Morphisms RelationPairs.
Import ListNotations.
From Velus Require Import Common CommonList.
Lemma and_impl :
forall (
A B C :
Prop),
(
A ->
B /\
C) <-> ((
A ->
B) /\ (
A ->
C)).
Proof.
firstorder.
Qed.
Lemma map_eq_nnil :
forall A B (
f :
A ->
B)
l,
l <> [] ->
List.map f l <> [].
Proof.
intros.
intro Hf; destruct l; [contradiction|].
discriminate Hf.
Qed.
Lemma map_ignore :
forall A B (
b :
B) (
l :
list A),
map (
fun _ =>
b)
l =
repeat b (
length l).
Proof.
induction l; simpl; auto.
Qed.
Lemma tl_length :
forall A (
l :
list A),
length (
tl l) =
Nat.pred (
length l).
Proof.
now destruct l.
Qed.
Lemma nth_nil :
forall A n (
d :
A),
nth n []
d =
d.
Proof.
destruct n; auto.
Qed.
Lemma hd_nth :
forall A (
l :
list A) (
d :
A),
nth O l d =
hd d l.
Proof.
destruct l; auto.
Qed.
Lemma tl_nth :
forall A (
l :
list A) (
d :
A)
n,
nth (
S n)
l d =
nth n (
tl l)
d.
Proof.
destruct l, n; auto.
Qed.
Lemma map_hd_nth :
forall A (
l :
list (
list A))
d,
map (
hd d)
l =
map (
fun l0 =>
nth 0
l0 d)
l.
Proof.
induction l;
simpl;
f_equal;
auto using hd_nth.
Qed.
Lemma map_tl_nth :
forall A (
l :
list (
list A))
n d,
map (
fun l0 =>
nth (
S n)
l0 d)
l =
map (
fun l0 =>
nth n (
tl l0)
d)
l.
Proof.
induction l;
simpl;
f_equal;
auto using tl_nth.
Qed.
Lemma list_eq_ext :
forall A (
l1 l2 :
list A)
d,
length l1 =
length l2 ->
(
forall n,
n <
length l1 ->
nth n l1 d =
nth n l2 d) ->
l1 =
l2.
Proof.
induction l1;
simpl;
intros *
Hl Hn.
-
destruct l2;
simpl in *;
congruence.
-
destruct l2;
try (
simpl in *;
congruence).
f_equal.
+
apply (
Hn O);
auto with arith.
+
eapply IHl1 with d;
intros;
auto.
rewrite (
Hn (
S n));
auto with arith.
Qed.
Lemma list_eq_ext2 :
forall A (
l1 l2 :
list A),
(
forall n,
nth_error l1 n =
nth_error l2 n) ->
l1 =
l2.
Proof.
induction l1;
intros *
Hn.
-
destruct l2;
simpl in *;
auto.
specialize (
Hn O);
inv Hn.
-
destruct l2.
specialize (
Hn O);
inv Hn.
f_equal.
+
now injection (
Hn O).
+
eapply IHl1;
intros;
auto.
apply (
Hn (
S n)).
Qed.
Lemma Forall3_same_1_2:
forall A B P (
xs:
list A) (
ys :
list B),
Forall3 P xs xs ys <->
Forall2 (
fun x y =>
P x x y)
xs ys.
Proof.
induction xs as [|x xs IH]; split; intros * H; inv H; constructor; auto.
rewrite <- IH; auto.
rewrite IH; auto.
Qed.
Lemma Forall3_same_2_3:
forall A B P (
xs:
list A) (
ys :
list B),
Forall3 P xs ys ys <->
Forall2 (
fun x y =>
P x y y)
xs ys.
Proof.
induction xs as [|x xs IH]; split; intros * H; inv H; constructor; auto.
rewrite <- IH; auto.
rewrite IH; auto.
Qed.
Lemma combine_map_2 :
forall A B C D (
f :
A ->
C ->
D) (
g :
B ->
C)
xs ys,
map (
fun '(
x,
y) =>
f x (
g y)) (
combine xs ys)
=
map (
fun '(
x,
z) =>
f x z) (
combine xs (
map g ys)).
Proof.
induction xs, ys; simpl; auto.
Qed.
Lemma length_combine' :
forall A B,
forall (
l :
list A) (
l' :
list B),
length l =
length l' ->
length (
combine l l') =
length l.
Proof.
Lemma In_list_pair_l :
forall {
A B} (
l :
list (
A*
B))
x y,
In (
x,
y)
l ->
In x (
map fst l).
Proof.
induction l; simpl; firstorder; subst; auto.
Qed.
Lemma Forall_In :
forall {
A} (
P :
A ->
Prop)
l x,
Forall P l ->
In x l ->
P x.
Proof.
Lemma Forall_impl_inside :
forall {
A} (
P Q :
A ->
Prop)
xs,
(
Forall (
fun x =>
P x ->
Q x)
xs) ->
Forall P xs ->
Forall Q xs.
Proof.
induction xs; auto.
intros FPQ FP. inv FPQ. inv FP.
constructor; auto.
Qed.
Lemma Forall_iff :
forall A (
P Q :
A ->
Prop)
l,
Forall (
fun x =>
P x <->
Q x)
l ->
Forall P l ->
Forall Q l.
Proof.
induction l; intros * Pq Hp; auto.
inversion Hp; inversion Pq; subst.
constructor; eauto; firstorder.
Qed.
Lemma in_app_weak' :
forall A (
x :
A)
l l',
In x l' ->
In x (
l ++
l').
Proof.
intros.
apply in_app;
auto.
Qed.
Lemma Forall2_Forall_eq :
forall {
A B} (
P :
A ->
B ->
Prop)
a l1 l2,
Forall (
eq a)
l1 ->
Forall2 P l1 l2 ->
Forall (
P a)
l2.
Proof.
induction 2; auto.
inversion H; subst.
constructor; auto.
Qed.
Lemma Forall2_Forall3 :
forall {
A B C} (
P :
A ->
B ->
Prop) (
Q :
B ->
C ->
Prop)
xs ys zs,
Forall2 P xs ys ->
Forall2 Q ys zs ->
Forall3 (
fun x y z =>
P x y /\
Q y z)
xs ys zs.
Proof.
intros * Hp Hq.
generalize dependent zs.
induction Hp; intros; simpl_Forall.
constructor.
inversion_clear Hq. constructor; auto.
Qed.
Lemma Forall2_nth :
forall {
A B} (
P :
A ->
B ->
Prop)
xs ys a b n,
Forall2 P xs ys ->
n <
length xs ->
P (
nth n xs a) (
nth n ys b).
Proof.
Lemma Forall3_nth :
forall {
A B C} (
P :
A ->
B ->
C ->
Prop)
xs ys zs a b c n,
Forall3 P xs ys zs ->
n <
length xs ->
P (
nth n xs a) (
nth n ys b) (
nth n zs c).
Proof.
Lemma Forall2_ignore1'':
forall {
A B} (
P :
B ->
Prop) (
xs :
list A)
ys,
Forall2 (
fun _
y =>
P y)
xs ys ->
Forall P ys.
Proof.
intros ?? P xs ys; revert xs.
induction ys; intros * Hf; inversion Hf; subst; eauto.
Qed.
Lemma concat_length_sum :
forall {
A} (
l :
list (
list A)),
length (
concat l) =
list_sum (
List.map (@
length A)
l).
Proof.
Lemma length_app_decomp :
forall {
A} (
l :
list A)
n m,
length l = (
n +
m)%
nat ->
exists l1 l2,
l =
l1 ++
l2
/\
length l1 =
n
/\
length l2 =
m.
Proof.
induction n;
simpl;
intros *
Hl.
-
exists [],
l.
auto.
-
destruct (
IHn (
S m))
as (
l1 & [|
x l2] &?&?&?);
simpl in *;
try lia.
exists (
l1 ++ [
x]),
l2.
rewrite <-
app_assoc,
List.length_app;
simpl.
repeat split;
auto;
lia.
Qed.
Lemma flat_map_repeat :
forall {
A B} (
f :
B ->
nat) (
a :
A) (
l :
list B),
flat_map (
fun e =>
repeat a (
f e))
l =
repeat a (
list_sum (
List.map f l)).
Proof.
Lemma map_repeat :
forall {
A B} (
f :
A ->
B) (
a :
A)
n,
List.map f (
repeat a n) =
repeat (
f a)
n.
Proof.
induction n; simpl; auto.
Qed.
Lemma repeat_map :
forall {
A} (
a :
A)
n,
repeat a n =
map (
fun _ =>
a) (
repeat a n).
Proof.
induction n; simpl; auto.
Qed.
Lemma nth_repeat_in :
forall {
A} (
a d :
A) (
m n :
nat),
(
n <
m)%
nat ->
nth n (
repeat a m)
d =
a.
Proof.
induction m; simpl; intros; cases; try lia.
auto with arith.
Qed.
Lemma Forall3_repeat :
forall {
A B C} (
R :
A ->
B ->
C ->
Prop)
a b c n,
R a b c ->
Forall3 R (
repeat a n) (
repeat b n) (
repeat c n).
Proof.
induction n; constructor; auto.
Qed.
Lemma Forall2_repeat :
forall {
A B} (
R :
A ->
B ->
Prop)
a b n,
R a b ->
Forall2 R (
repeat a n) (
repeat b n).
Proof.
induction n; constructor; auto.
Qed.
mem_nth l x returns the index of the first occurrence of x in l
Section Mem_nth.
Variable (
T :
Type).
Hypothesis T_eq_dec :
forall x y :
T, {
x =
y } + {
x <>
y }.
Fixpoint mem_nth (
l :
list T) (
x :
T) :
option nat :=
match l with
| [] =>
None
|
y ::
l =>
if T_eq_dec x y then Some O
else option_map S (
mem_nth l x)
end.
Lemma mem_nth_nth :
forall l k d,
NoDup l ->
k <
length l ->
mem_nth l (
nth k l d) =
Some k.
Proof.
induction l;
simpl;
intros *
Hdup Hk.
lia.
destruct k.
-
destruct T_eq_dec;
congruence.
-
inversion_clear Hdup.
destruct T_eq_dec;
subst.
+
exfalso.
auto using nth_In with arith.
+
rewrite IHl;
auto with arith.
Qed.
Lemma mem_nth_In :
forall l x n,
mem_nth l x =
Some n ->
In x l.
Proof.
induction l as [|
y l];
simpl;
intros *
Hm;
try congruence.
destruct (
T_eq_dec x y);
subst;
auto.
unfold option_map in Hm.
destruct mem_nth eqn:?;
inversion_clear Hm;
eauto.
Qed.
Lemma mem_nth_Some :
forall x l k d,
mem_nth l x =
Some k ->
k <
length l /\
nth k l d =
x.
Proof.
induction l;
simpl;
intros *
Hk;
try congruence.
destruct T_eq_dec;
subst.
-
inversion Hk;
auto with arith.
-
unfold option_map in Hk.
destruct mem_nth eqn:?;
inversion_clear Hk.
edestruct IHl;
eauto with arith.
Qed.
Lemma mem_nth_nin :
forall x xs,
mem_nth xs x =
None ->
In x xs ->
False.
Proof.
intros *
Hf Hin.
induction xs;
simpl in *;
auto.
destruct T_eq_dec;
subst;
inversion Hf.
destruct Hin;
auto.
unfold option_map in *;
destruct mem_nth eqn:?;
auto;
congruence.
Qed.
Lemma nth_mem_nth :
forall l x k,
NoDup l ->
nth_error l k =
Some x ->
mem_nth l x =
Some k.
Proof.
intros *
ND.
revert k x.
induction ND;
simpl;
intros *
Hn.
-
destruct k;
simpl in *;
congruence.
-
destruct T_eq_dec;
subst.
+
destruct k;
simpl in *;
auto.
now apply nth_error_In in Hn.
+
destruct k;
simpl in *.
congruence.
erewrite IHND;
now auto.
Qed.
Lemma mem_nth_error :
forall l x k,
mem_nth l x =
Some k ->
nth_error l k =
Some x.
Proof.
induction l;
simpl;
intros *
Hm.
congruence.
destruct T_eq_dec;
subst;
inversion Hm;
subst;
auto.
unfold option_map in *.
destruct mem_nth eqn:?;
inversion Hm;
subst;
simpl;
auto.
Qed.
End Mem_nth.
Lemma mem_ident_nth :
forall l x,
mem_ident x l =
true ->
exists k,
mem_nth _
ident_eq_dec l x =
Some k.
Proof.
intros *
Hm.
induction l;
simpl in *;
try congruence.
cases;
subst.
exists O;
auto with arith.
apply Bool.orb_prop in Hm as [
Hm|
Hm].
apply ident_eqb_eq in Hm;
congruence.
destruct IHl as [? ->];
simpl;
eauto with arith.
Qed.
Lifting of a relation over a list of elements
Section Forall2_relation.
Variables (
A B :
Type).
Variables (
RA :
relation A) (
RB :
relation B).
Global Add Parametric Morphism (
a :
A) `(
Reflexive _
RA) : (
hd a)
with signature Forall2 RA ==>
RA
as hd_morph.
Proof.
induction 1; simpl; auto.
Qed.
Global Add Parametric Morphism : (@
tl A)
with signature Forall2 RA ==>
Forall2 RA
as tl_morph.
Proof.
induction 1; simpl; auto.
Qed.
Global Instance F2_refl :
Reflexive RA ->
Reflexive (
Forall2 RA).
Proof.
intros Hr l; induction l; auto.
Qed.
Global Instance F2_sym :
Symmetric RA ->
Symmetric (
Forall2 RA).
Proof.
intros Hs xs ys.
induction 1; auto.
Qed.
Global Instance F2_trans :
Transitive RA ->
Transitive (
Forall2 RA).
Proof.
intros Ht xs ys zs Hf.
revert zs.
induction Hf; intros * Hf'; inv Hf'; constructor; eauto.
Qed.
Global Instance F2_equiv :
Equivalence RA ->
Equivalence (
Forall2 RA).
Proof.
Global Add Parametric Morphism (
f :
A ->
B) (
Hf :
Proper (
RA ==>
RB)
f) : (
map f)
with signature Forall2 RA ==>
Forall2 RB
as map_morph2.
Proof.
induction 1; simpl; auto.
Qed.
Global Add Parametric Morphism : (@
Forall A)
with signature (
RA ==>
Basics.impl) ==>
Forall2 RA ==>
Basics.impl
as F_morph3.
Proof.
intros P Q PQ xs ys.
induction 1; intro Hf; inv Hf; constructor; auto.
eapply PQ; eauto.
Qed.
Global Add Parametric Morphism : (@
Forall2 A B)
with signature (
RA ==>
RB ==>
Basics.impl) ==>
Forall2 RA ==>
Forall2 RB ==>
Basics.impl
as F2_morph2.
Proof.
intros P Q PQ xs1 xs2 Ha ys1 ys2 Hb Hf.
generalize dependent xs2.
generalize dependent ys2.
induction Hf; intros; inv Ha; inv Hb; constructor; eauto.
eapply PQ; eauto.
Qed.
Global Add Parametric Morphism : (@
Forall2 A B)
with signature (
RA ==>
RB ==>
iff) ==>
Forall2 RA ==>
Forall2 RB ==>
iff
as F2_morph2_iff.
Proof.
intros P Q PQ xs1 xs2 Ha ys1 ys2 Hb.
split;
intro Hf.
-
refine (
F2_morph2 _ _ _ _ _ _ _ _ _ _);
eauto.
intros ???????;
edestruct PQ;
eauto.
-
generalize dependent xs1.
generalize dependent ys1.
induction Hf;
intros;
inv Ha;
inv Hb;
constructor;
eauto.
eapply PQ;
eauto.
Qed.
Global Add Parametric Morphism : (@
combine A B)
with signature Forall2 RA ==>
Forall2 RB ==>
Forall2 (
RA *
RB)
as combine_morph.
Proof.
intros la1 la2 Eqa.
induction Eqa; simpl; auto.
intros lb1 lb2 Eqb.
induction Eqb; constructor; eauto.
Qed.
End Forall2_relation.
Global Instance :
forall A,
subrelation (
Forall2 (@
eq A)) (@
eq (
list A)).
Proof.
intros A xs ys.
induction 1; auto.
Qed.
Global Add Parametric Morphism A B : (@
Forall2 A B)
with signature (@
eq A ==> @
eq B ==>
iff) ==> @
eq (
list A) ==> @
eq (
list B) ==>
iff
as F2_morph_eq.
Proof.
intros P Q PQ xs ys.
split;
induction 1;
constructor;
auto.
all:
destruct (
PQ x x eq_refl y y eq_refl);
auto.
Qed.
Application d'un prédicat sur les lignes d'une matrice
Section Forall2t.
Context {
A B :
Type}.
Variable (
d :
A).
Variable (
P :
list A ->
B ->
Prop).
On considère une matrice de A avec une colonne supplémentaire de B.
Le prédicat P doit être vrai sur chaque ligne.
Inductive Forall2t :
list (
list A) ->
list B ->
Prop :=
|
f2tnil :
forall l,
Forall (
eq [])
l ->
Forall2t l []
|
f2tcons :
forall (
l :
list (
list A)) (
h :
B) (
t :
list B),
P (
List.map (
hd d)
l)
h ->
Forall2t (
List.map (@
tl A)
l)
t ->
Forall2t l (
h ::
t).
Lemma Forall2t_forall2 :
forall ll l (
b :
B),
Forall (
fun xl =>
length xl =
length l)
ll ->
Forall2t ll l
<->
forall n,
n <
length l ->
P (
map (
fun l =>
nth n l d)
ll) (
nth n l b).
Proof.
intros *
Hl;
split.
-
intros Ht.
induction Ht;
intros *
Le.
{
now inv Le. }
destruct n;
simpl.
+
rewrite <-
map_hd_nth;
auto.
+
setoid_rewrite map_map in IHHt.
rewrite map_tl_nth.
apply IHHt;
auto with arith.
eapply Forall_map,
Forall_impl;
eauto.
intros [] **;
simpl in *;
lia.
-
intro Nth.
generalize dependent ll.
induction l as [|
x l];
intros.
{
constructor;
simpl_Forall;
now apply symmetry,
length_zero_iff_nil. }
constructor.
+
rewrite map_hd_nth.
apply (
Nth O);
simpl;
auto with arith.
+
eapply IHl.
{
eapply Forall_map,
Forall_impl;
eauto.
intros [] **;
simpl in *;
lia. }
intros.
rewrite map_map, <-
map_tl_nth.
apply (
Nth (
S n));
simpl;
auto with arith.
Qed.
Calcul de la transposée d'une matrice. On donne sa spécification
dans son type car raisonner sur la fonction direcement est rendu
très pénible par la preuve de terminaison.
Program Fixpoint transp (
l :
list (
list A)) (
k : {
k |
Forall (
fun l =>
length l =
k)
l })
{
measure (
length (
concat l))}
: {
l' :
list (
list A)
| (
l <> [] ->
length l' =
k /\
Forall (
fun ll =>
length ll =
length l)
l')
/\
forall n m,
nth n (
nth m l' [])
d =
nth m (
nth n l [])
d } :=
match l with
| [] => []
| [] :: _ => []
|
rows =>
List.map (
hd d)
rows ::
transp (
List.map (@
tl _)
rows) (
exist _ (
Nat.pred k) _)
end.
Next Obligation.
simpl; split; intros; cases; congruence.
Qed.
Next Obligation.
Next Obligation.
Next Obligation.
Next Obligation.
Next Obligation.
split; intros; congruence.
Qed.
Forall2t est bien l'analogue de Forall2 sur la matrice tansposée.
Lemma Forall2t_Forall2 :
forall ll l (
Hl :
Forall (
fun l' =>
length l' =
length l)
ll),
ll <> [] ->
Forall2t ll l ->
Forall2 P (
proj1_sig (
transp ll (
exist _ _
Hl)))
l.
Proof.
intros *
Nnil Hft.
apply Forall2_forall2.
destruct transp as [
ll' [
Hlt Ht]];
simpl in *.
destruct Hlt as [
Hlt Hf];
auto.
split;
auto.
intros *
Hn ??;
subst.
rewrite (
nth_indep _ _ []
Hn).
rewrite (
Forall2t_forall2 _ _
b)
in Hft;
auto.
assert ((
nth n ll' []) = (
map (
fun l =>
nth n l d)
ll))
as ->.
2:
apply Hft;
congruence.
eapply list_eq_ext with d.
-
eapply Forall_nth in Hf as ->;
auto using length_map.
-
intros m Hm.
erewrite Ht,
map_nth';
auto.
eapply Forall_nth in Hf;
eauto.
now rewrite Hf in Hm.
Qed.
Global Add Parametric Morphism
(
eqA :
relation A) (
eqB :
relation B)
(
EqA :
Equivalence eqA)
(
reB :
Reflexive eqB)
(
P_compat :
Proper (
Forall2 eqA ==>
eqB ==>
Basics.impl)
P)
:
Forall2t
with signature (
Forall2 (
Forall2 eqA)) ==>
Forall2 eqB ==>
Basics.impl
as F2t_morph.
Proof.
intros xss xss' Hxy ys ys' Heq Hf.
revert Hxy Hf. revert xss xss'.
induction Heq; intros * Hxy Hf; inv Hf.
- constructor.
induction Hxy; auto.
inv H; constructor; auto; now simpl_Forall.
- constructor.
+ rewrite <- Hxy, <- H; auto.
+ eapply IHHeq; eauto.
now rewrite <- Hxy.
Qed.
Global Add Parametric Morphism
(
eqA :
relation A) (
eqB :
relation B)
(
EqA :
Equivalence eqA)
(
reB :
Reflexive eqB)
(
P_compat :
Proper (
Forall2 eqA ==>
eqB ==>
iff)
P)
:
Forall2t
with signature (
Forall2 (
Forall2 eqA)) ==>
Forall2 eqB ==>
iff
as F2t_morph_iff.
Proof.
intros xss xss' Hxy ys ys' Heq.
revert Hxy. revert xss xss'.
induction Heq; split; intro Hf; inv Hf.
- constructor.
clear - Hxy H.
induction Hxy; auto; inv H; inv H0; auto.
- constructor.
clear - Hxy H.
induction Hxy; auto; inv H; inv H0; auto.
- constructor.
+ now rewrite <- Hxy, <- H.
+ eapply IHHeq; eauto.
now rewrite <- Hxy.
- constructor.
+ now rewrite H, Hxy.
+ eapply IHHeq; eauto.
now rewrite Hxy.
Qed.
End Forall2t.
Lorsque l'on combine chaque ligne de la matrice ll avec une même
liste la, typiquement une liste d'enumtag.
Lemma Forall2t_combine :
forall A B C d1 d2 (
P :
list (
A *
B) ->
C ->
Prop) (
ll :
list (
list B))
la lc,
Forall (
fun xl =>
length xl =
length lc)
ll ->
Forall2t d1 (
fun l c =>
P (
combine la l)
c)
ll lc ->
Forall2t d2 P (
map (
fun '(
a,
l) =>
map (
pair a)
l) (
combine la ll))
lc.
Proof.
On peut simuler un Forall3t en ajoutant une colonne supplémentaire
grâce à un appel à combine sur le dernier argument.
Ou encore en ajoutant la colonne en tête de la matrice, et dans
ce cas il faut ajuster les arguments de P.
Lemma Forall2t_more_col :
forall A B (
P :
list A ->
A ->
B ->
Prop)
d lb ma la,
length la =
length lb ->
Forall2t d (
fun l b =>
P (
tl l) (
hd d l)
b) (
la ::
ma)
lb ->
Forall2t d (
fun l ab =>
P l (
fst ab) (
snd ab))
ma (
combine la lb).
Proof.
clear.
induction lb; intros * Hl Hft; inv Hft.
- destruct la; simpl in *; try congruence.
constructor; inv H; auto.
- destruct la; simpl in *; try congruence.
constructor; auto.
Qed.