From Coq Require Import Morphisms List.
From Velus Require Import Common.CommonList.
From Velus.Lustre.Denot.Cpo Require Import Cpo_def Cpo_streams_type.
Import ListNotations.
Require Import Cpo_def_ext.
Extension of the Cpo library
The cpo of n-uplets.
Section Nprod.
Context {
D :
cpo }.
Fixpoint nprod (
n :
nat) :
cpo :=
match n with
|
O =>
D
| 1 =>
D
|
S n =>
Dprod D (
nprod n)
end.
extract the first element
Definition nprod_hd {
n} :
nprod (
S n) -
C->
D :=
match n with
|
O =>
ID _
| (
S n) =>
FST _ _
end.
same with default value if n = 0
Definition nprod_hd_def d {
n} :
nprod n -
C->
D :=
match n with
|
O =>
CTE _ _
d
| (
S n) =>
nprod_hd
end.
throw away the first element
Definition nprod_tl {
n} :
nprod (
S n) -
C->
nprod n :=
match n with
|
O =>
ID _
| (
S n) =>
SND _ _
end.
cons function
Definition nprod_cons {
n} :
D -
C->
nprod n -
C->
nprod (
S n) :=
match n with
|
O =>
CTE _ _
|
S _ =>
PAIR _ _
end.
Lemma nprod_cons_Oeq_compat :
forall (
d1 d2 :
D)
n (
np1 np2 :
nprod n),
d1 ==
d2 ->
np1 ==
np2 ->
nprod_cons d1 np1 ==
nprod_cons d2 np2.
Proof.
destruct n; auto.
Qed.
Lemma nprod_hd_tl :
forall {
n} (
np :
nprod (
S n)),
np =
nprod_cons (
nprod_hd np) (
nprod_tl np).
Proof.
destruct n; auto.
destruct np; auto.
Qed.
Lemma nprod_hd_cons :
forall x n (
np:
nprod n),
nprod_hd (
nprod_cons x np) =
x.
Proof.
destruct n; auto.
Qed.
Lemma nprod_tl_cons :
forall x n (
np :
nprod (
S n)),
nprod_tl (
nprod_cons x np) =
np.
Proof.
auto.
Qed.
Lemma nprod_hd_bot :
forall n,
nprod_hd (0 :
nprod (
S n)) = 0.
Proof.
destruct n; reflexivity.
Qed.
Lemma nprod_tl_bot :
forall n,
nprod_tl (0 :
nprod (
S n)) = 0.
Proof.
destruct n; reflexivity.
Qed.
Lemma nprod_cons_bot :
forall n,
nprod_cons 0 (0 :
nprod n) = 0.
Proof.
destruct n; reflexivity.
Qed.
nprod concatenation
Fixpoint nprod_app {
n p} :
nprod n -
C->
nprod p -
C->
nprod (
n +
p) :=
match n return nprod n -
C->
nprod p -
C->
nprod (
n+
p)
with
|
O =>
curry (
SND _ _)
|
S n =>
curry ((
nprod_cons @2_
nprod_hd @_
FST _ _)
((
nprod_app @2_
nprod_tl @_
FST _ _) (
SND _ _)))
end.
Lemma nprod_hd_app :
forall m n (
mp :
nprod (
S m)) (
np :
nprod n),
nprod_hd (
nprod_app mp np) =
nprod_hd mp.
Proof.
destruct m, n; auto.
Qed.
Lemma nprod_tl_app :
forall m n (
mp :
nprod (
S (
S m))) (
np :
nprod n),
nprod_tl (
nprod_app mp np) =
nprod_app (
nprod_tl mp)
np.
Proof.
destruct m, n; auto.
Qed.
extract the k-th element if k < n, d otherwise
Fixpoint get_nth (
k :
nat) (
d :
D) {
n} :
nprod n -
C->
D :=
match n with
|
O =>
CTE _ _
d
| _ =>
match k with
|
O =>
nprod_hd
|
S k =>
get_nth k d @_
nprod_tl
end
end.
Lemma get_nth_Oeq_compat :
forall n k d (
np np' :
nprod n),
np ==
np' ->
get_nth k d np ==
get_nth k d np'.
Proof.
induction n;
simpl;
intros *
Heq.
-
destruct k;
auto.
-
destruct n,
k;
auto.
+
unfold get_nth.
now rewrite Heq.
+
simpl.
autorewrite with cpodb.
auto.
+
simpl.
autorewrite with cpodb.
auto.
Qed.
Global Add Parametric Morphism n k d : (
get_nth k d)
with signature @
Oeq (
nprod n) ==> @
Oeq D as get_nth_compat_morph.
Proof.
Lemma get_nth_tl :
forall {
n} (
np :
nprod (
S n))
k d,
get_nth (
S k)
d np =
get_nth k d (
nprod_tl np).
Proof.
induction k; auto.
Qed.
independence wrt. the default value
Lemma get_nth_indep :
forall n (
np :
nprod n)
k d d',
k <
n ->
get_nth k d np =
get_nth k d' np.
Proof.
induction n;
intros *
Hk.
-
inversion Hk.
-
destruct k;
auto;
simpl.
rewrite fcont_comp_simpl,
IHn with (
d' :=
d');
auto with arith.
Qed.
condition d'égalité pour les nprod
Lemma nprod_eq :
forall n (
np1 np2 :
nprod (
S n)),
(
forall k d,
k < (
S n) ->
get_nth k d np1 ==
get_nth k d np2) ->
np1 ==
np2.
Proof.
induction n;
simpl;
intros *
Heq.
-
apply (
Heq O np1);
auto.
-
destruct np1 as [
d1 np1],
np2 as [
d2 np2].
apply Dprod_eq_pair.
+
apply (
Heq O d1);
lia.
+
apply IHn;
intros.
rewrite (
Heq (
S k)
d);
auto;
lia.
Qed.
Lemma nprod_app_nth1 :
forall m n (
mp :
nprod m) (
np :
nprod n)
k d,
k <
m ->
get_nth k d (
nprod_app mp np) =
get_nth k d mp.
Proof.
induction m;
intros *
Hk.
-
inversion Hk.
-
destruct k;
simpl.
+
now unshelve setoid_rewrite nprod_hd_app.
+
autorewrite with cpodb.
rewrite <- (
IHm n _
np);
auto with arith.
destruct m;
simpl;
auto;
lia.
Qed.
Lemma nprod_app_nth2 :
forall m n (
mp :
nprod m) (
np :
nprod n)
k d,
k >=
m ->
get_nth k d (
nprod_app mp np) =
get_nth (
k-
m)
d np.
Proof.
induction m;
intros *
Hk.
-
simpl in *.
autorewrite with cpodb;
repeat f_equal;
auto with arith.
-
destruct k;
simpl.
+
lia.
+
destruct m,
n;
auto with arith.
*
destruct k;
simpl;
now autorewrite with cpodb.
*
rewrite <- (
IHm _ (
nprod_tl mp));
auto with arith.
*
rewrite <- (
IHm _ (
nprod_tl mp));
auto with arith.
*
rewrite <- (
IHm _ (
nprod_tl mp));
auto with arith.
Qed.
Lemma nprod_app_Oeq_compat :
forall {
n p} (
p1 p2 :
nprod n) (
p3 p4 :
nprod p),
p1 ==
p2 ->
p3 ==
p4 ->
nprod_app p1 p3 ==
nprod_app p2 p4.
Proof.
induction n; auto.
Qed.
Fixpoint nprod_const n :
D -
C->
nprod n :=
match n with
|
O =>
ID _
|
S n => (
nprod_cons @2_
ID _) (
nprod_const n)
end.
Lemma get_nth_const :
forall c n k d,
k <
n ->
get_nth k d (
nprod_const n c) =
c.
Proof.
induction n;
intros *
Hk.
-
inversion Hk.
-
destruct k;
simpl.
+
now setoid_rewrite nprod_hd_cons.
+
destruct n; [|
apply IHn];
lia.
Qed.
Lemma get_nth_err :
forall k d n (
np :
nprod n),
(
n <=
k)%
nat ->
get_nth k d np =
d.
Proof.
induction k;
simpl;
intros *
Hn.
-
inversion Hn;
subst.
now simpl.
-
destruct n;
cbn;
auto.
setoid_rewrite <-
get_nth_tl.
apply IHk;
auto with arith.
Qed.
A Forall predicate for n-uplets
Section Forall_Nprod.
Variable P :
D ->
Prop.
Definition forall_nprod {
n} (
np :
nprod n) :
Prop.
induction n as [|[]];
simpl in *.
-
exact True.
-
exact (
P np).
-
exact (
P (
fst np) /\
IHn (
snd np)).
Defined.
Lemma forall_nprod_hd :
forall {
n} (
np :
nprod (
S n)),
forall_nprod np ->
P (
nprod_hd np).
Proof.
intros * Hf.
destruct n; auto.
now inversion Hf.
Qed.
Lemma forall_nprod_tl :
forall {
n} (
np :
nprod (
S n)),
forall_nprod np ->
forall_nprod (
nprod_tl np).
Proof.
intros * Hf.
destruct n.
- now simpl.
- now inversion Hf.
Qed.
Lemma forall_nprod_inv :
forall n (
np :
nprod (
S n)),
forall_nprod np ->
P (
nprod_hd np) /\
forall_nprod (
nprod_tl np).
Proof.
intros [|[]] ?; simpl; auto.
Qed.
Lemma hd_tl_forall :
forall {
n} (
np :
nprod (
S n)),
P (
nprod_hd np) ->
forall_nprod (
nprod_tl np) ->
forall_nprod np.
Proof.
destruct n as [|[]]; intros * Hh Ht; now simpl in *.
Qed.
Lemma forall_nprod_cons :
forall {
n}
d (
np :
nprod n),
P d ->
forall_nprod np ->
forall_nprod (
nprod_cons d np).
Proof.
destruct n; simpl; auto.
Qed.
Lemma forall_nprod_cons_iff :
forall {
n}
d (
np :
nprod n),
forall_nprod (
nprod_cons d np)
<->
P d /\
forall_nprod np.
Proof.
split; destruct n; cbn; tauto.
Qed.
Lemma forall_nprod_bot :
forall n,
P 0 ->
@
forall_nprod n 0.
Proof.
induction n as [|[]]; intros; try split; auto.
Qed.
Lemma k_forall_nprod :
forall {
n} (
np :
nprod n),
(
forall k d,
k <
n ->
P (
get_nth k d np)) ->
forall_nprod np.
Proof.
induction n;
intros *
Hk;
auto;
try now simpl.
apply hd_tl_forall.
-
unshelve eapply (
Hk O);
auto with arith.
destruct n; [|
destruct np];
auto.
-
apply IHn;
intros.
apply (
Hk (
S k));
auto with arith.
Qed.
Lemma k_forall_nprod_def :
forall {
n} (
np :
nprod n)
d,
(
forall k,
k <
n ->
P (
get_nth k d np)) ->
forall_nprod np.
Proof.
induction n;
intros *
Hk;
try now simpl.
apply hd_tl_forall.
-
apply (
Hk O);
auto with arith.
-
apply (
IHn _
d);
intros.
apply (
Hk (
S k));
auto with arith.
Qed.
Lemma forall_nprod_k :
forall {
n} (
np :
nprod n),
forall_nprod np ->
(
forall k d,
k <
n ->
P (
get_nth k d np)).
Proof.
induction n;
intros *
Hf *
Hk.
inversion Hk.
apply forall_nprod_hd in Hf as ?.
apply forall_nprod_tl in Hf as ?.
destruct k;
auto.
apply IHn;
auto with arith.
Qed.
Lemma forall_nprod_k_def :
forall {
n} (
np :
nprod n)
d,
P d ->
forall_nprod np ->
(
forall k,
P (
get_nth k d np)).
Proof.
Lemma forall_nprod_k_iff :
forall {
n} (
np :
nprod n),
forall_nprod np <-> (
forall k d,
k <
n ->
P (
get_nth k d np)).
Proof.
Lemma forall_nprod_app :
forall {
n m} (
np :
nprod n) (
mp :
nprod m),
forall_nprod np ->
forall_nprod mp ->
forall_nprod (
nprod_app np mp).
Proof.
Lemma app_forall_nprod :
forall {
n m} (
np :
nprod n) (
mp :
nprod m),
forall_nprod (
nprod_app np mp) ->
forall_nprod np
/\
forall_nprod mp.
Proof.
Lemma forall_app_nprod :
forall {
n m} (
np :
nprod n) (
mp :
nprod m),
forall_nprod (
nprod_app np mp) <->
forall_nprod np
/\
forall_nprod mp.
Proof.
Lemma forall_nprod_const :
forall {
n}
c,
P c ->
forall_nprod (
nprod_const n c).
Proof.
Global Add Parametric Morphism n
(
P_compat:
Morphisms.Proper (@
Oeq D ==>
iff)
P)
: (
forall_nprod)
with signature Oeq (
O :=
nprod n) ==>
iff
as forall_nprod_morph.
Proof.
End Forall_Nprod.
Lemma forall_nprod_impl :
forall (
P Q :
D ->
Prop),
(
forall x,
P x ->
Q x) ->
forall {
n} (
np :
nprod n),
forall_nprod P np ->
forall_nprod Q np.
Proof.
Lemma forall_nprod_and :
forall (
P Q :
D ->
Prop),
forall {
n} (
np :
nprod n),
forall_nprod P np ->
forall_nprod Q np ->
forall_nprod (
fun x =>
P x /\
Q x)
np.
Proof.
Lemma and_forall_nprod :
forall (
P Q :
D ->
Prop),
forall {
n} (
np :
nprod n),
forall_nprod (
fun x =>
P x /\
Q x)
np ->
forall_nprod P np /\
forall_nprod Q np.
Proof.
Lemma forall_nprod_and_iff :
forall (
P Q :
D ->
Prop),
forall {
n} (
np :
nprod n),
(
forall_nprod P np /\
forall_nprod Q np)
<->
forall_nprod (
fun x =>
P x /\
Q x)
np.
Proof.
Global Instance :
Proper (
pointwise_relation D iff ==>
forall_relation (
fun n :
nat =>
eq ==>
iff))
forall_nprod.
Proof.
intros P Q PQ ??? Heq; subst.
split; intro Hf.
{ induction a as [|[]]; auto.
- apply PQ; auto.
- inversion_clear Hf; split.
+ apply PQ; auto.
+ apply IHa; auto. }
{ induction a as [|[]]; auto.
- apply PQ; auto.
- inversion_clear Hf; split.
+ apply PQ; auto.
+ apply IHa; auto. }
Qed.
From n-uplets, build lists of length n
Section List_of_nprod.
Import ListNotations.
Fixpoint list_of_nprod {
n} :
nprod n ->
list D :=
match n return nprod n -> _
with
| 0 =>
fun _ => []
|
S n =>
fun np =>
nprod_hd np ::
list_of_nprod (
nprod_tl np)
end.
Lemma list_of_nprod_length :
forall {
n} (
np :
nprod n),
length (
list_of_nprod np) =
n.
Proof.
induction n; simpl; auto.
Qed.
Lemma list_of_nprod_cons :
forall {
n}
d (
np :
nprod n),
list_of_nprod (
nprod_cons d np) =
d ::
list_of_nprod np.
Proof.
destruct n; auto.
Qed.
Lemma list_of_nprod_app :
forall {
n m} (
np :
nprod n) (
mp :
nprod m),
list_of_nprod (
nprod_app np mp) =
list_of_nprod np ++
list_of_nprod mp.
Proof.
induction n as [|[]]; intros; auto.
- destruct m; auto.
- destruct np as (p,np).
specialize (IHn _ np mp).
simpl; f_equal; auto.
Qed.
Lemma list_of_nprod_nth :
forall {
n} (
np :
nprod n)
k d,
nth k (
list_of_nprod np)
d =
get_nth k d np.
Proof.
induction n; destruct k; simpl; intros; auto.
Qed.
Lemma list_of_nprod_nth_error :
forall n (
np :
nprod n)
k d x,
nth_error (
list_of_nprod np)
k =
Some x ->
get_nth k d np =
x.
Proof.
Lemma forall_nprod_Forall :
forall P {
n} (
np :
nprod n),
forall_nprod P np ->
Forall P (
list_of_nprod np).
Proof.
Lemma Forall_forall_nprod :
forall P {
n} (
np :
nprod n),
Forall P (
list_of_nprod np) ->
forall_nprod P np.
Proof.
induction n;
intros *
Hf;
try now simpl.
inversion_clear Hf.
apply hd_tl_forall;
auto.
Qed.
Lemma nprod_forall_Forall :
forall P {
n} (
np :
nprod n),
forall_nprod P np <->
Forall P (
list_of_nprod np).
Proof.
Lemma Forall2_list_of_nprod_inv :
forall T (
P :
T ->
D ->
Prop)
n (
np :
nprod (
S n))
x l,
Forall2 P (
x ::
l) (
list_of_nprod np) <->
P x (
nprod_hd np) /\
Forall2 P l (
list_of_nprod (
nprod_tl np)).
Proof.
destruct n; split; intros * Hf;
inversion_clear Hf; constructor; auto.
Qed.
End List_of_nprod.
End Nprod.
Notation "A [ n ]" := (@
nprod A n) (
at level 100,
only printing,
format "A [ n ]").
Lifting functions over n-uplets
Section Lifting.
Context {
D1 D2 D3 :
cpo}.
Fixpoint lift (
F :
D1 -
C->
D2) {
n} : @
nprod D1 n -
C-> @
nprod D2 n :=
match n with
|
O =>
F
|
S n => (
nprod_cons @2_
F @_
nprod_hd) (
lift F @_
nprod_tl)
end.
Lemma lift_hd :
forall f n (
np :
nprod (
S n)),
nprod_hd (
lift f np) =
f (
nprod_hd np).
Proof.
destruct n; auto.
Qed.
Lemma lift_tl :
forall f n (
np :
nprod (
S n)),
nprod_tl (
lift f np) =
lift f (
nprod_tl np).
Proof.
destruct n; auto.
Qed.
Lemma lift_cons :
forall f n x (
np :
nprod n),
lift f (
nprod_cons x np) =
nprod_cons (
f x) (
lift f np).
Proof.
destruct n; auto.
Qed.
Lemma lift_bot :
forall (
f :
D1 -
C->
D2),
f 0 == 0 ->
forall n,
lift f (0 :
nprod n) == 0.
Proof.
Lemma lift_app :
forall f n1 (
np1 :
nprod n1)
n2 (
np2 :
nprod n2),
lift f (
nprod_app np1 np2) =
nprod_app (
lift f np1) (
lift f np2).
Proof.
Lemma nth_lift :
forall F n (
np :
nprod n)
k d1 d2,
k <
n ->
get_nth k d2 (
lift F np) =
F (
get_nth k d1 np).
Proof.
induction n as [|[]];
intros *
Hk.
-
inversion Hk.
-
now destruct k;
try lia.
-
destruct k;
auto.
rewrite 2
get_nth_tl,
lift_tl.
erewrite IHn;
auto;
lia.
Qed.
Lemma lift_ext :
forall (
f g :
D1 -
C->
D2)
n (
np :
nprod n),
(
forall x,
f x ==
g x) ->
lift f np ==
lift g np.
Proof.
induction n; intros * Heq; simpl; auto.
autorewrite with cpodb.
now rewrite Heq, IHn.
Qed.
Lemma forall_nprod_lift :
forall (
F :
D1 -
C->
D2),
forall (
P :
D2 ->
Prop),
forall {
n} (
np :
nprod n),
forall_nprod (
fun x =>
P (
F x))
np <->
forall_nprod P (
lift F np).
Proof.
split.
- intros * Hf.
induction n as [|[]]; auto.
inversion Hf.
constructor; auto.
now apply IHn.
- intros * Hf.
induction n as [|[]]; auto.
inversion Hf.
constructor; auto.
Qed.
Lemma lift_nprod_const :
forall F c n,
lift F (
nprod_const n c) =
nprod_const n (
F c).
Proof.
induction n;
auto.
simpl (
nprod_const _ _).
autorewrite with cpodb.
now rewrite lift_cons,
IHn.
Qed.
Definition llift {
A} (
F :
D1 -
C->
A -
C->
D2) {
n} :
@
nprod D1 n -
C->
A -
C-> @
nprod D2 n.
induction n as [|[]].
-
apply F.
-
apply F.
-
apply curry.
apply (
fcont_comp2 (
PAIR _ _)).
exact ((
F @2_ (
FST _ _ @_
FST _ _)) (
SND _ _)).
exact ((
IHn @2_ (
SND _ _ @_
FST _ _)) (
SND _ _)).
Defined.
Opaque llift.
Lemma llift_simpl :
forall A F n d u U,
@
llift A F (
S (
S n)) (
u,
U)
d = (
F u d, @
llift A F (
S n)
U d).
Proof.
trivial.
Qed.
Lemma llift_hd :
forall A F n d U,
nprod_hd (@
llift A F (
S n)
U d) =
F (
nprod_hd U)
d.
Proof.
destruct n; auto.
Qed.
Lemma llift_tl :
forall A F n d U,
nprod_tl (@
llift A F (
S n)
U d) =
llift F (
nprod_tl U)
d.
Proof.
destruct n; auto.
Qed.
Lemma llift_nth :
forall A (
F :
D1 -
C->
A -
C->
D2)
a,
forall {
n} (
np :
nprod n)
k d1 d2,
k <
n ->
get_nth k d2 (
llift F np a) =
F (
get_nth k d1 np)
a.
Proof.
induction n;
intros *
Hk.
-
inversion Hk.
-
destruct k;
simpl.
+
now setoid_rewrite llift_hd.
+
autorewrite with cpodb.
setoid_rewrite llift_tl;
auto with arith.
Qed.
Definition llift_env {
A I} (
F :
A -
C->
Dprodi (
fun _ :
I =>
D1) -
C->
D2) {
n} :
A -
C->
Dprodi (
fun _ :
I => @
nprod D1 n) -
C-> @
nprod D2 n.
induction n as [|[]].
-
apply F.
-
apply F.
-
apply curry.
apply (
fcont_comp2 (
PAIR _ _)).
+
exact ((
F @2_
FST _ _) (
DMAPi (
fun _ =>
FST _ _) @_
SND _ _)).
+
exact ((
IHn @2_
FST _ _) (
DMAPi (
fun _ =>
SND _ _) @_
SND _ _)).
Defined.
Definition lift2
(
F :
D1 -
C->
D2 -
C->
D3) {
n} :
@
nprod D1 n -
C-> @
nprod D2 n -
C-> @
nprod D3 n.
induction n as [|[]].
-
exact F.
-
exact F.
-
apply curry.
apply (
fcont_comp2 (
PAIR _ _)).
exact ((
F @2_ (
FST _ _ @_
FST _ _ )) (
FST _ _ @_
SND _ _ )).
exact ((
IHn @2_ (
SND _ _ @_
FST _ _ )) (
SND _ _ @_
SND _ _ )).
Defined.
Lemma lift2_hd :
forall F n (
U V :
nprod (
S n)),
nprod_hd (
lift2 F U V) =
F (
nprod_hd U) (
nprod_hd V).
Proof.
destruct n; auto.
Qed.
Lemma lift2_tl :
forall F n (
U V :
nprod (
S n)),
nprod_tl (
lift2 F U V) =
lift2 F (
nprod_tl U) (
nprod_tl V).
Proof.
destruct n; auto.
Qed.
Lemma lift2_simpl :
forall F n u U v V,
@
lift2 F (
S (
S n)) (
u,
U) (
v,
V) = (
F u v, @
lift2 F (
S n)
U V).
Proof.
trivial.
Qed.
Lemma lift2_nth :
forall (
F :
D1 -
C->
D2 -
C->
D3) {
n} (
np np' :
nprod n)
k d1 d2 d3,
k <
n ->
get_nth k d3 (
lift2 F np np') =
F (
get_nth k d1 np) (
get_nth k d2 np').
Proof.
induction n as [|[]];
intros;
auto;
try lia.
-
destruct k;
simpl;
auto;
lia.
-
destruct np,
np'.
rewrite lift2_simpl.
destruct k;
auto.
erewrite 3
get_nth_tl, <-
IHn;
auto with arith.
Qed.
Lemma forall_nprod_lift2 :
forall (
F :
D1 -
C->
D2 -
C->
D3),
forall (
P1 :
D1 ->
Prop)
(
P2 :
D2 ->
Prop)
(
P3 :
D3 ->
Prop),
(
forall x y,
P1 x ->
P2 y ->
P3 (
F x y)) ->
forall {
n} (
np np' :
nprod n),
forall_nprod P1 np ->
forall_nprod P2 np' ->
forall_nprod P3 (
lift2 F np np').
Proof.
intros f P1 P2 P3 Hf.
induction n as [|[]];
intros *
H1 H2;
auto.
-
cbn in *;
auto with *.
-
destruct np,
np',
H1,
H2.
rewrite lift2_simpl.
constructor.
apply Hf;
auto.
apply IHn;
auto.
Qed.
Lemma forall_nprod_llift :
forall A (
F :
D1 -
C->
A -
C->
D2)
d,
forall (
P :
D2 ->
Prop)
(
Q :
D1 ->
Prop),
(
forall x,
Q x ->
P (
F x d)) ->
forall {
n} (
np :
nprod n),
forall_nprod Q np ->
forall_nprod P (
llift F np d).
Proof.
intros A F d ??
Hf.
induction n as [|[]];
intros *
H;
auto.
-
cbn in *;
auto with *.
-
destruct np,
H.
rewrite llift_simpl.
constructor.
+
simpl in *;
auto.
+
apply IHn;
auto.
Qed.
Ltac inv H :=
inversion H;
clear H;
subst.
Ltac simpl_Forall :=
repeat
(
match goal with
|
H:
Forall2 _ _ (_ :: _) |- _ =>
inv H
end;
subst).
Lemma Forall2_lift2 :
forall A (
F :
D1 -
C->
D2 -
C->
D3)
(
P :
A ->
D1 ->
Prop)
(
Q :
A ->
D2 ->
Prop)
(
R :
A ->
D3 ->
Prop),
(
forall a x y,
P a x ->
Q a y ->
R a (
F x y)) ->
forall {
n} (
l1 l2 :
nprod n)
l,
Forall2 P l (
list_of_nprod l1) ->
Forall2 Q l (
list_of_nprod l2) ->
Forall2 R l (
list_of_nprod (
lift2 F l1 l2)).
Proof.
intros *
PQR.
induction n;
intros *
H1 H2.
-
simpl;
inversion H1;
auto.
-
inv H1.
inv H2.
constructor.
+
rewrite lift2_hd;
auto.
+
rewrite lift2_tl;
auto.
Qed.
Lemma Forall2_llift :
forall A B b (
F :
D1 -
C->
B -
C->
D2)
(
P :
A ->
D1 ->
Prop)
(
Q :
A ->
D2 ->
Prop),
(
forall a x,
P a x ->
Q a (
F x b)) ->
forall {
n} (
l1 :
nprod n) (
l :
list A),
Forall2 P l (
list_of_nprod l1) ->
Forall2 Q l (
list_of_nprod (
llift F l1 b)).
Proof.
intros *
PQ.
induction n;
intros *
Hf.
-
simpl;
inversion Hf;
auto.
-
inv Hf;
constructor.
+
rewrite llift_hd;
auto.
+
rewrite llift_tl;
auto.
Qed.
Lemma Forall_llift :
forall A a (
F :
D1 -
C->
A -
C->
D2)
(
P :
D1 ->
Prop)
(
Q :
D2 ->
Prop),
(
forall x,
P x ->
Q (
F x a)) ->
forall {
n} (
np :
nprod n),
Forall P (
list_of_nprod np) ->
Forall Q (
list_of_nprod (
llift F np a)).
Proof.
intros *
PQ.
induction n;
intros *
Hp;
constructor;
inv Hp.
-
rewrite llift_hd;
auto.
-
rewrite llift_tl;
auto.
Qed.
Lemma lift_map :
forall F n (
np :
nprod n),
list_of_nprod (
lift F np) =
List.map F (
list_of_nprod np).
Proof.
induction n as [|[]]; intros; auto.
simpl.
now setoid_rewrite IHn.
Qed.
End Lifting.
Lemma lift_ID :
forall D n (
np :
nprod n),
lift (
ID D)
np =
np.
Proof.
induction n;
simpl;
intros;
auto.
autorewrite with cpodb.
rewrite IHn.
now setoid_rewrite <- (
nprod_hd_tl np).
Qed.
Lemma lift_lift :
forall D1 D2 D3 (
F :
D1 -
C->
D2) (
G :
D2 -
C->
D3)
n (
np :
nprod n),
lift G (
lift F np) =
lift (
G @_
F)
np.
Proof.
induction n as [|[]]; intros; simpl; auto.
autorewrite with cpodb.
now setoid_rewrite <- IHn.
Qed.
Section Nprod_Fold.
Context {
A B :
cpo}.
Fixpoint nprod_Fold {
n} : (
B -
C->
A -
C->
A) -
C->
A -
C-> @
nprod B n -
C->
A.
destruct n.
-
apply CTE,
CTE.
-
apply curry,
curry.
refine ((
ID _ @3_ _) _ _).
+
exact ((
FST _ _ @_
FST _ _)).
+
exact (
nprod_hd @_
SND _ _).
+
exact ((
nprod_Fold n @3_
FST _ _ @_
FST _ _) (
SND _ _ @_
FST _ _) (
nprod_tl @_
SND _ _)).
Defined.
Lemma Fold_eq :
forall F a n (
np :
nprod (
S n)),
nprod_Fold F a np =
F (
nprod_hd np) (
nprod_Fold F a (
nprod_tl np)).
Proof.
trivial.
Qed.
Lemma Fold_eq' :
forall F a n (
np : @
nprod B n),
nprod_Fold F a np =
match n return nprod n -> _
with
|
O =>
fun _ =>
a
|
S n =>
fun np =>
F (
nprod_hd np) (
nprod_Fold F a (
nprod_tl np))
end np.
Proof.
destruct n; reflexivity.
Qed.
End Nprod_Fold.
A kind of List.fold_right for nprod
Section Nprod_Foldi.
Context {
I :
Type}.
Context {
A B :
cpo}.
Definition nprod_Foldi :
forall (
l :
list I),
(
I -
O->
B -
C->
A -
C->
A) -
C->
A -
C-> @
nprod B (
length l) -
C->
A.
induction l as [|
i l].
-
apply CTE,
CTE.
-
apply curry,
curry.
refine ((
ID _ @3_ _) _ _).
+
exact (
fcont_ford_shift _ _ _ (
ID _)
i @_ (
FST _ _ @_
FST _ _)).
+
exact (
nprod_hd @_
SND _ _).
+
exact ((
IHl @3_
FST _ _ @_
FST _ _) (
SND _ _ @_
FST _ _) (
nprod_tl @_
SND _ _)).
Defined.
Lemma Foldi_nil :
forall F a np,
nprod_Foldi []
F a np =
a.
Proof.
trivial.
Qed.
Lemma Foldi_cons :
forall i l f a np,
nprod_Foldi (
i ::
l)
f a np
=
f i (
nprod_hd np) (
nprod_Foldi l f a (
nprod_tl np)).
Proof.
trivial.
Qed.
Lemma Foldi_fold_right :
forall l f a np,
nprod_Foldi l f a np =
fold_right (
fun '(
i,
x)
a =>
f i x a)
a (
combine l (
list_of_nprod np)).
Proof.
induction l;
intros;
auto.
rewrite Foldi_cons;
simpl.
do 2
f_equal;
eauto.
Qed.
Lemma forall_nprod_Foldi :
forall (
P :
A ->
Prop)
(
Q :
B ->
Prop)
(
l :
list I) (
d :
A) (
f :
I -
O->
B -
C->
A -
C->
A)
np,
(
forall i d1 d2,
P d1 ->
Q d2 ->
P (
f i d2 d1)) ->
P d ->
forall_nprod Q np ->
P (
nprod_Foldi l f d np).
Proof.
A weak induction principle for nprod_Foldi
Lemma Foldi_rec :
forall (
P :
A ->
Prop) (
F :
I -
O->
B -
C->
A -
C->
A)
d,
P d ->
(
forall i d dd,
P dd ->
P (
F i d dd)) ->
forall l np,
P (
nprod_Foldi l F d np).
Proof.
clear.
intros *
Hd HF.
induction l;
intro np;
auto.
rewrite Foldi_cons.
apply HF,
IHl.
Qed.
End Nprod_Foldi.
To characterize stream functions defined with nprod_Foldi, it may be
useful to speak independently about heads and tails of streams.
Tails can be easily accessed with lift (@REM _) np while heads needs
a is_cons predicate to be extracted. This is the purpose of nprod_hds.
Section Nprod_hds.
Context {
A :
Type}.
Fixpoint nprod_hds {
n} :
forall (
np : @
nprod (
DS A)
n),
forall_nprod (@
is_cons _)
np ->
list A :=
match n with
|
O =>
fun _ _ => []
|
S n =>
fun _
Inf =>
projT1 (
uncons (
forall_nprod_hd _ _
Inf))
::
nprod_hds _ (
forall_nprod_tl _ _
Inf)
end.
Lemma hds_length :
forall n (
np :
nprod n)
npc,
length (
nprod_hds np npc) =
n.
Proof.
induction n; simpl; auto.
Qed.
Lemma Forall_hds :
forall (
P :
A ->
Prop) (
Q :
DS A ->
Prop),
(
forall x u U,
x ==
cons u U ->
Q x ->
P u) ->
forall n (
np :
nprod n)
Icn,
Forall Q (
list_of_nprod np) ->
Forall P (
nprod_hds np Icn).
Proof.
intros *
QP.
induction n;
intros *
Hf;
inversion_clear Hf;
constructor;
auto.
destruct (
uncons _)
as (?&?&
Hd);
simpl.
apply decomp_eqCon in Hd.
eapply QP;
eauto.
Qed.
Lemma Forall2_hds :
forall I (
P :
I ->
A ->
Prop) (
Q :
I ->
DS A ->
Prop),
(
forall i x u U,
x ==
cons u U ->
Q i x ->
P i u) ->
forall (
l :
list I) (
np :
nprod (
length l))
Icn,
Forall2 Q l (
list_of_nprod np) ->
Forall2 P l (
nprod_hds np Icn).
Proof.
intros *
QP.
induction l;
intros *
Hf;
inversion_clear Hf;
constructor;
auto.
destruct (
uncons _)
as (?&?&
Hd);
simpl.
apply decomp_eqCon in Hd.
eapply QP;
eauto.
Qed.
End Nprod_hds.
Matrix operations
Section Lift_nprod.
Context {
D1 D2 :
cpo}.
lift_nprod F np applies F to each row of the matrix to
produce a vector of size m.
F( x11 x12 ... x1n ) → F1
F( x21 x22 ... x2n ) → F2
F( .
F( .
F( xm1 xm2 ... xmn ) → Fm
Definition lift_nprod {
n m} :
(@
nprod D1 n -
C->
D2) -
C-> @
nprod (@
nprod D1 m)
n -
C-> @
nprod D2 m.
induction m.
-
apply ID.
-
refine (
curry ((
nprod_cons @2_ _) _)).
+
exact ((
AP _ _ @2_
FST _ _) (
lift nprod_hd @_
SND _ _)).
+
exact ((
IHm @2_
FST _ _) (
lift nprod_tl @_
SND _ _)).
Defined.
Lemma lift_nprod_simpl :
forall n m F (
np : @
nprod (@
nprod D1 (
S m))
n),
lift_nprod F np =
nprod_cons
(
F (
lift nprod_hd np))
(
lift_nprod F (
lift nprod_tl np)).
Proof.
trivial.
Qed.
Lemma hd_lift_nprod :
forall n m F (
np : @
nprod (@
nprod D1 (
S m))
n),
nprod_hd (
lift_nprod F np) =
F (
lift nprod_hd np).
Proof.
intros.
destruct m; auto.
Qed.
Lemma tl_lift_nprod :
forall n m F (
np : @
nprod (@
nprod D1 (
S m))
n),
nprod_tl (
lift_nprod F np) =
lift_nprod F (
lift nprod_tl np).
Proof.
intros.
destruct m; auto.
Qed.
Lemma lift_nprod_nth :
forall d1 d2 n F m k (
np : @
nprod (@
nprod D1 m)
n),
k <
m ->
get_nth k d2 (
lift_nprod F np) =
F (
lift (
get_nth k d1)
np).
Proof.
induction m as [|[|
m]];
intros *
Hk;
try lia.
-
destruct k;
try lia;
now cbn.
-
rewrite lift_nprod_simpl.
destruct k.
+
now setoid_rewrite nprod_hd_cons.
+
setoid_rewrite IHm;
auto with arith.
now rewrite lift_lift.
Qed.
If ∀ i, (Q xi1 ∧ Q xi2 ∧ ... ∧ Q xin) implies P (F (xi1, ... xin))
and Q indeed holds for every element of the matrix, then P holds
for the result of lift_nprod
Lemma forall_lift_nprod :
forall n (
F : @
nprod D1 n -
C->
D2),
forall (
P :
D2 ->
Prop) (
Q :
D1 ->
Prop),
(
forall x,
forall_nprod Q x ->
P (
F x)) ->
forall m np,
forall_nprod (
forall_nprod Q)
np ->
@
forall_nprod _
P m (
lift_nprod F np).
Proof.
If every column of the matrix satisfy the property (Forall2 P l)
then for all entries of l, P holds with every element in the corresponding
row of the matrix. Typically, l is a list of type annotations.
Lemma Forall2_lift_nprod :
forall n (
F : @
nprod D1 n -
C->
D2),
forall A (
P :
A ->
D1 ->
Prop) (
Q :
A ->
D2 ->
Prop),
(
forall a x,
forall_nprod (
P a)
x ->
Q a (
F x)) ->
forall (
l :
list A)
m (
np : @
nprod (@
nprod D1 m)
n),
m =
length l ->
Forall (
fun ss =>
Forall2 P l (
list_of_nprod ss)) (
list_of_nprod np) ->
Forall2 Q l (
list_of_nprod (
lift_nprod F np)).
Proof.
If (Forall2 Q l) holds for every row of the matrix
and implies P (F row) then P holds for the resulting vector.
Lemma Forall_lift_nprod :
forall A (
l :
list A),
forall (
F : @
nprod D1 (
length l) -
C->
D2),
forall (
P :
D2 ->
Prop) (
Q :
A ->
D1 ->
Prop),
(
forall (
np :
nprod (
length l)),
Forall2 Q l (
list_of_nprod np) ->
P (
F np)) ->
forall m (
np : @
nprod (@
nprod D1 m) (
length l)),
Forall2 (
fun e ss =>
forall_nprod (
Q e)
ss)
l (
list_of_nprod np) ->
Forall P (
list_of_nprod (
lift_nprod F np)).
Proof.
End Lift_nprod.
Lemma lift_lift_nprod :
forall D1 D2 D3,
forall (
F :
D2 -
C->
D3)
n m G np,
lift F (@
lift_nprod D1 D2 n m G np)
=
lift_nprod (
F @_
G)
np.
Proof.