Require Import List EquivDec FunctionalExtensionality.
Require Import Isomorphism Eqdep_dec.
Require Import LibUtils.
Require Import Lia.
Require Import ListAdd Vector.
Class Finite (
A:
Type) :=
{
elms :
list A ;
finite :
forall x:
A,
In x elms
}.
Lemma Finite_equivlist {
A:
Type} (
fin1:
Finite A) (
fin2:
Finite A) :
equivlist (@
elms _ fin1) (@
elms _ fin2).
Proof.
destruct fin1 as [??]
; destruct fin2 as [??].
split; intuition.
Qed.
Program Instance Finite_iso {
A B} {
iso:
Isomorphism A B} {
fin:
Finite A} :
Finite B
:= {
elms:= (
List.map iso_f elms)
}.
Next Obligation.
Lemma in_dec_nd_pf_irrel {
A:
Type} {
dec:
EqDec A eq} {
a:
A} {
l:
list A} (
nd:
NoDup l) (
pf1 pf2:
In a l) :
pf1 =
pf2.
Proof.
induction l.
-
inversion pf1.
-
simpl in pf1,
pf2.
invcs nd.
destruct pf1;
destruct pf2.
+
f_equal.
apply UIP_dec.
apply dec.
+
congruence.
+
congruence.
+
f_equal.
auto.
Qed.
Fixpoint Inb {
A} {
dec:
EqDec A eq} (
a:
A)
l
:=
match l with
|
nil =>
false
|
b::
m =>
if b ==
a then
true
else Inb a m
end.
Definition In_strong {
A} {
dec:
EqDec A eq} (
a:
A)
l :=
Inb a l =
true.
Lemma In_strong_In {
A} {
dec:
EqDec A eq} (
a:
A)
l :
In_strong a l ->
In a l.
Proof.
unfold In_strong.
induction l;
simpl;
intuition.
destruct (
equiv_dec a0 a);
intuition.
Qed.
Lemma In_In_strong {
A} {
dec:
EqDec A eq} (
a:
A)
l :
In a l ->
In_strong a l.
Proof.
unfold In_strong.
induction l;
simpl;
trivial.
-
intuition.
-
destruct (
equiv_dec a0 a);
simpl;
intuition.
Qed.
Lemma in_strong_dec_pf_irrel_helper
{
SBP:
Prop} (
v:{
SBP} + {~
SBP}) (
P:
Prop)
(
pf1 pf2 :
if v then True else P)
(
IH :
forall pf1 pf2 :
P,
pf1 =
pf2) :
pf1 =
pf2.
Proof.
destruct v.
- destruct pf1; destruct pf2; trivial.
- apply IH.
Qed.
Lemma in_strong_dec_pf_irrel {
A:
Type} {
dec:
EqDec A eq} {
a:
A} {
l:
list A} (
pf1 pf2:
In_strong a l) :
pf1 =
pf2.
Proof.
Program Fixpoint Finite_fun_dep_elems_aux {
A:
Type} {
dec:
EqDec A eq} {
B:
A->
Type} (
la:
list A)
{
struct la} : (
forall x,
In_strong x la ->
list (
B x)) ->
list (
forall a,
In_strong a la ->
B a)
:=
match la as la'
return (
forall x,
In_strong x la' ->
list (
B x)) ->
list (
forall a,
In_strong a la' ->
B a)
with
|
nil =>
fun _ =>
_ ::
nil
|
a::
xs =>
fun lb =>
let rest :=
Finite_fun_dep_elems_aux xs (
fun x inx =>
lb x _)
in
let lbx :=
lb a _ in
List.concat (
List.map (
fun b =>
List.map (
fun x =>
_)
rest)
lbx)
end.
Next Obligation.
unfold In_strong in *.
simpl.
rewrite inx.
now destruct (
a ==
x).
Defined.
Next Obligation.
unfold In_strong in *.
simpl.
now destruct (
a ==
a); [|
congruence].
Defined.
Next Obligation.
destruct (
a ==
a0).
-
now destruct e.
-
apply x.
unfold In_strong in *.
simpl in H.
destruct (
a ==
a0);
trivial.
congruence.
Defined.
Definition Finite_fun_dep_elems
{
A:
Type} {
dec:
EqDec A eq} {
B:
A->
Type} (
finA:
Finite A) (
finB:
forall a,
Finite (
B a))
:
list (
forall a,
B a)
:=
List.map (
fun X a =>
X a (
In_In_strong _ _ (
finite a))) (
Finite_fun_dep_elems_aux (
B:=
B)
elms (
fun a ina =>
elms)).
Lemma Finite_fun_dep_elems_aux_all
{
A:
Type} {
dec:
EqDec A eq} {
B:
A->
Type} (
la:
list A)
(
lb:
forall a,
In_strong a la ->
list (
B a))
(
lbf:
forall a pf x,
In x (
lb a pf))
:
forall x:(
forall a:
A,
In_strong a la ->
B a),
In x (
Finite_fun_dep_elems_aux la lb).
Proof.
Lemma Finite_fun_dep_elems_all
{
A:
Type} {
dec:
EqDec A eq} {
B:
A->
Type} (
finA:
Finite A) (
finB:
forall a,
Finite (
B a))
:
forall x:(
forall a:
A,
B a),
In x (
Finite_fun_dep_elems finA finB).
Proof.
Instance Finite_fun_dep {
A:
Type} {
dec:
EqDec A eq} {
B:
A->
Type} (
finA:
Finite A) (
finB:
forall a,
Finite (
B a)):
Finite (
forall a :
A,
B a) :=
{|
elms :=
Finite_fun_dep_elems finA finB
;
finite :=
Finite_fun_dep_elems_all finA finB
|}.
Instance Finite_fun {
A:
Type} {
dec:
EqDec A eq} {
B} (
finA:
Finite A) (
finB:
Finite B):
Finite (
A ->
B) :=
@
Finite_fun_dep A dec (
fun _ =>
B)
finA (
fun _ =>
finB).
Lemma concat_length {
A:
Type} (
l:
list (
list A)) :
length (
concat l) =
fold_right plus 0 (
map (@
length _)
l).
Proof.
induction l;
simpl;
trivial.
now rewrite app_length,
IHl.
Qed.
Lemma fold_right_add_const {
A:
Type}
c (
l:
list A) :
fold_right Nat.add 0
(
map (
fun _ =>
c)
l) =
c *
length l.
Proof.
Lemma fold_right_mult_const {
A:
Type}
c (
l:
list A) :
fold_right Nat.mul 1
(
map (
fun _ =>
c)
l) =
NPeano.Nat.pow c (
length l).
Proof.
induction l; simpl; trivial.
now rewrite IHl; simpl.
Qed.
Lemma Finite_fun_dep_size {
A:
Type} {
dec:
EqDec A eq} {
B:
A->
Type} (
finA:
Finite A) (
finB:
forall a,
Finite (
B a))
:
length (@
elms _ (
Finite_fun_dep finA finB)) =
fold_right Nat.mul 1 (
List.map (
fun a =>
length (@
elms _ (
finB a))) (@
elms _ finA)).
Proof.
Lemma Finite_fun_size {
A:
Type} {
dec:
EqDec A eq} {
B:
Type} (
finA:
Finite A) (
finB:
Finite B)
:
length (@
elms _ (
Finite_fun finA finB)) =
NPeano.pow (
length (@
elms _ finB)) (
length (@
elms _ finA)).
Proof.
Global Program Instance finite_prod {
A B} (
finA:
Finite A) (
finB:
Finite B) :
Finite (
A*
B)
:= {
elms :=
list_prod elms elms }.
Next Obligation.
Definition bounded_nat_finite_list n :
list {
x :
nat | (
x <
n)%
nat}.
Proof.
induction n.
-
exact nil.
-
apply cons.
+
exists n;
lia.
+
eapply List.map; [|
exact IHn].
intros [
x ?].
exists x;
lia.
Defined.
Lemma bounded_nat_finite_list_proj n :
List.map (@
proj1_sig _ _) (
bounded_nat_finite_list n) =
rev (
seq 0
n).
Proof.
Global Program Instance bounded_nat_finite n :
Finite {
x :
nat | (
x <
n)%
nat}
:= {|
elms :=
rev (
bounded_nat_finite_list n)
|}.
Next Obligation.