(* $Id: finite.v,v 1.20 2000/11/10 11:27:35 freek Exp $ *)

(* Obsolete but maintained *)

Require Export CPolynomials.

(* finite sets *)

Transparent sym_eq.
Transparent f_equal.

Implicit Arguments On.

Inductive fin : nat->Set :=
  FO : (n:nat)(fin (S n))		(* the (n+1)th element *)
| FS : (n:nat)(fin n)->(fin (S n)).	(* the first n elements *)

(* So, we fix as intended meaning that, going from [0,1,__,n] to *)
(* [0,1,__,n+1], we add a new element at the _end_ (the n+1) *)

(* Every finite set can be injected in the next finite set *)
(* This can be done in two ways (just like one can add an elt to a *)
(* list as the first or the last list-entry) *)
(* fin_inj maps [0,1,__,n] to [0,1,__,n] and adds n+1 *)
(* fin_inj_shift maps [0,1,__,n] to [1,__,n,n+1] and adds 0 *)

Definition fin_inj [n:nat; i:(fin n)] : (fin (S n)) := (FS i).

Fixpoint fin_inj_shift [n:nat; i:(fin n)] : (fin (S n)) :=
  <[m:nat](fin (S m))>Cases i
  of (FO m) => (FO (S m))
   | (FS m j) => (FS (fin_inj_shift j))
  end.

Fixpoint lt_dec [n,m:nat] :Prop :=
     Cases n m of
	O O => False
	| O (S y) => True
	| (S x) O => False
	| (S x)(S y) => (lt_dec x y)
     end.


(* nats and fins can be converted *)
Fixpoint nat_fin [n:nat] : (fin (S n)) :=
  <[m:nat](fin (S m))>Cases n
  of O     => (FO O)
   | (S m) => (FS (nat_fin m))
  end.
Fixpoint fin_nat [n:nat; i:(fin n)] : nat :=
  Cases i
  of (FO _)   => O
   | (FS _ j) => (S (fin_nat j))
  end.
(* more generally *)
Fixpoint Nat_Fin [n:nat] : (m:nat)(fin (S (plus n m))) :=
  [m:nat]<[n:nat](fin (S (plus n m)))>Cases n
  of O     => (FO m)
   | (S l) => (FS (Nat_Fin l m))
  end.

Definition lt_fin_dec := [n,m:nat; i: (fin n); j:(fin m)]
	(lt_dec (fin_nat i)(fin_nat j)).

(* Other injections of (fin n) into (fin (S n)) are also possible *)
(* `disregarding' one element of [1,__,n,n+1], like mapping *)
(* of [0,1,__,n] to [0,1,__,j-1,j+1,__,n+1] *)

Definition fin_inj_drop [n:nat; i:(fin n)] : (fin (S n)) :=
  <[m:nat](fin (S m))>Cases i
  of (FO m) => (FO (S m))
   | (FS m j) => (FS (fin_inj_shift j))
  end.

(* !! *)


Section some_fin.
Variable n : nat.

Definition F1: (fin (S (S n))) := (FS (FO n)).
Definition F2: (fin (S (S (S n)))) := (FS F1).
Definition F3: (fin (S (S (S (S n))))) := (FS F2).

End some_fin.

Section Special_fin_rec.
Variable C : (n:nat)(fin (S n))->Set.
Variable base : (n:nat)(C (FO n)).
Variable ih: (n:nat; i:(fin n))(C (FS i)).

Local tmp: (n:nat; i:(fin n))Set.
Induction n; Intros.
Exact unit.
Exact (C i).
Defined.

Definition fin_rec_S: (n:nat)(i:(fin (S n)))(C i).
Intros.
Cut (n:nat; i:(fin n))(tmp i)->(tmp (FS i)).
Intros h. Exact (!fin_rec tmp ([n:nat](base n)) h ? i).
Simpl. Intros. Apply ih.
Defined.
End Special_fin_rec.

Section Special_fin_ind.
Variable C : (n:nat)(fin (S n))->Prop.
Variable base : (n:nat)(C (FO n)).
Variable ih: (n:nat; i:(fin n))(C (FS i)).

Local tmp: (n:nat; i:(fin n))Prop.
Induction n; Intros.
Exact True.
Exact (C i).
Defined.

Lemma fin_ind_S: (n:nat)(i:(fin (S n)))(C i).
Intros.
Cut (n:nat; i:(fin n))(tmp i)->(tmp (FS i)).
Intros h. Exact (!fin_ind tmp ([n:nat](base n)) h ? i).
Simpl. Intros. Apply ih.
Qed.
End Special_fin_ind.


Lemma finO_inv: (i:(fin O))False.
Intro.
Inversion i.
Qed.

Lemma fin_inv: (n:nat; i:(fin n))(Ex[m:nat] n=(S m)).
Induction n; Intros.
Elim (finO_inv i).
Exists n0; Trivial.
Qed.

Lemma finS_inv:
   (n:nat; i:(fin (S n))) i=(FO n) \/ (Ex[j:(fin n)] i=(FS j)).
Intros n i. Elim i using fin_ind_S; Intros.
Left; Trivial.
Right; Exists i0; Trivial.
Qed.

Lemma eq_FS: (n:nat; x,y:(fin n)) x=y -> (FS x)=(FS y).
Proof [n:nat](f_equal (fin n) (fin (S n)) (FS 1!n)).

Definition IsFS [n:nat; i:(fin n)] : Prop :=
 Cases i of (FO _) => False | (FS _ _) => True end.

Lemma FO_FS: (n:nat; i:(fin n))~(FO n)=(FS i).
Red; Intros n i h.
Change (IsFS (FO n)).
Elim (sym_eq ? (FO n) (FS i));[Exact I | Assumption].
Qed.

Definition Fpred : (n:nat; i:(fin (S (S n))))(fin (S n)).
Induction n; Intros.
Inversion i; Exact (FO O).
Inversion i. Exact (FO (S n0)). Exact H1.
Defined.

Lemma Fpred_specS: (n:nat; i:(fin (S n)))(Fpred (FS i))=i.
Intros n i; Elim i using fin_ind_S; Induction n0.
Trivial.
Trivial.
Intros j; Elim (finO_inv j).
Trivial.
Qed.

Lemma FS_eq: (n:nat; x,y:(fin n)) (FS x)=(FS y) -> x=y.
Induction n; Intros.
Elim (finO_inv x).
Rewrite <- (Fpred_specS x); Rewrite <- (Fpred_specS y).
  Apply (f_equal ?? (!Fpred n0)); Assumption.
Qed.

Lemma fin_decidable: (n:nat; i,j:(fin n)) i=j \/ ~i=j.
Induction i; Intros.
Elim j using fin_ind_S; Intros.
  Left; Trivial.
  Right; Apply FO_FS.
Elim (finS_inv j); Intro h.
  Right; Rewrite h. Apply not_eq_sym; Apply FO_FS.
  Elim h; Intros x k; Rewrite k. Elim (H x); Unfold not; Intros.
     Left; Apply eq_FS; Assumption.
     Right; Exact (contrapos (!FS_eq ? f x) H0).
Qed.


Section finVectors.
Variable A : Set.
Variable n : nat.

Definition vec : Set := (fin n)->A.
Definition constVec [a:A]: vec := [i:(fin n)]a.

End finVectors.

Section VecBasics.

Variable R:CRing.
Definition n_distinct := [n:nat; v:(vec R n)]
	((i,j :(fin n)) (~(i=j)-> (v i)[#](v j))).

Definition RX := (cpoly_cring R).

(*
Ax_iom crit_cpoly_eq : (f,g:RX;n:nat)
	(Degree_le n f) -> (Degree_le n g) ->
		(v: (vec R (S n))) (n_distinct v) ->
			((i:(fin (S n)))(f!(v i)[=]g!(v i))) -> f[=]g.
*)

(* Syntactic Definition N_distinct := (n_distinct ?). *)

Definition vec_begin: (n:nat)(v:(vec R (S n)))(vec R n)
	:= [n:nat; v:((fin (S n))->(R)); H:(fin n)] (v (fin_inj H)).

Definition vec_end: (n:nat)(v:(vec R (S n)))(vec R n)
	:= [n:nat; v:((fin (S n))->(R)); H:(fin n)] (v (fin_inj_shift H)).

Definition vec_last: (n:nat)(vec R(S n))->R
	:= [n:nat;v: (vec R (S n))] (v (FO n)).

Fixpoint vec_first [n:nat]: (vec R(S n))->R
	:=<[m:nat](vec R(S m))->R> Cases n of
		O 	=> [v:(vec R(S O))](v (FO O))
		| (S x) => [v:(vec R(S (S x)))](vec_first (vec_begin v))
		end.
End VecBasics.


Section finMappingFolding.
Variables A,B,C : Set.
Variable f : A->B.
Variable g : A->B->C.
Variable n : nat.

Definition mapf [v:(vec A n)]: (vec B n) :=
    [i:(fin n)](f (v i)).
Definition map2f [v:(vec A n); u:(vec B n)]: (vec C n) :=
    [i:(fin n)](g (v i) (u i)).

(***********
Variable h : B -> C -> C.
Variable c : C.

STOP.   Gave up in short term: using listn to define foldrf!
Definition Le [n,m:nat]: Set := {p:nat|(plus n p)=m}.

Definition foldrf: (v:(vec B n))(m:nat; lemn:(Le m n))C.
Induction m; Intros.
Exact c.
Apply h.
Elim lemn.
 Induction x; Intros. Rewrite <- (plus_n_O (S n0)) in y.
  Exact (v (FO n0)).

Apply (h (v (fin_inj (nat_fin n0)))).

Intros until lemn; Elim lemn.
Exact c.
Exact (h (v (fin_inj (nat_fin n0))) H).

******************)

End finMappingFolding.

Implicit Arguments Off.


