(* $Id: Basics.v,v 1.27 2000/11/03 13:09:27 freek Exp $ *)

Require Export Omega.

(* Tex_Prose
\section{Basics}
This is random stuff that should be in the Coq basic library.
*)

(* Tex_Prose
This is the axiom of choice.  It currently is the one `real'
axiom.  We need it because we write our logic in Prop.
*)
(* Begin_Tex_Verb *)
Axiom ex_informative : (A:Set;P:A->Prop)(Ex [x:A](P x))->{x:A|(P x)}.
(* End_Tex_Verb *)

(* Tex_Prose
The next is needed to define the Max function. We have to be able
to go from a `non-informative' disjunction to an `informative' one
*)
(* Begin_Tex_Verb *)
Lemma or_informative : (A,B:Prop)A\/B->{A}+{B}.
(* End_Tex_Verb *)
Exact [A,B:?; H':?]
 (proj1_sig ?? (ex_informative ? [_:?]? (or_ind ???
   [H:?](ex_intro ? [_:?]? (left ?? H) I)
   [H:?](ex_intro ? [_:?]? (right ?? H) I) H'))).
Qed.

(* Begin_Tex_Verb *)
Lemma lt_z_two: (lt O (2)).
(* End_Tex_Verb *)
Auto.
Qed.

(* Begin_Tex_Verb *)
Lemma le_pred : (n,m:nat)(le n m)->(le (pred n)(pred m)).
(* End_Tex_Verb *)
Proof.
Induction n. Simpl. Intros. Apply le_O_n.
Intros n0 Hn0. Induction m. Simpl. Intro. Cut ~(le (S n0) (0)).
Intro.Elim H0.Exact H. Exact (le_Sn_O n0).
Intros. Simpl. Apply le_S_n. Exact H0.
Qed.

(* Begin_Tex_Verb *)
Lemma lt_mult_right :
  (x,y,z:nat) (lt x y) -> (lt (0) z) -> (lt (mult x z) (mult y z)).
(* End_Tex_Verb *)
Intros.
Induction z.
Elim (lt_n_n ? H0).
Rewrite mult_sym. Replace (mult y (S z)) with (mult (S z) y).
Apply lt_mult_left. Auto.
Auto with arith.
Qed.

(* Begin_Tex_Verb *)
Lemma le_mult_left :
  (x,y,z:nat) (le x y) -> (le (mult z x) (mult z y)).
(* End_Tex_Verb *)
Intros.
Induction z; Intros.
Auto.
Elim (le_lt_or_eq ?? H); Intros.
Apply lt_le_weak.
Apply lt_mult_left. Auto.
Rewrite H0.
Auto.
Qed.

(* Tex_Prose
Faculty function. Does not exist in Arith. (?)
Needed for special operations on polynomials.
*)
(* Begin_Tex_Verb *)

Fixpoint fac [n:nat] :nat :=
	Cases n of
	   O 		=> (S O)
	   | (S m)	=> (mult (S m)(fac m))
	end.
(* End_Tex_Verb *)

(* Begin_Tex_Verb *)
Lemma nat_fac_gtzero:(n:nat)(lt O (fac n)).
(* End_Tex_Verb *)
Proof.
Induction n. Simpl. Auto.Intros. Simpl.Apply lt_plus_trans. Trivial.
Qed.


(* needed for computational behavior of "Inversion" tactic *)
Transparent sym_eq.
Transparent f_equal.

Syntactic Definition Pair := (pair ??).
Syntactic Definition Proj1 := (proj1 ??).
Syntactic Definition Proj2 := (proj2 ??).

(*
Begin_Tex_Verb
Lemma nat_double_ind: (P:nat->nat->Prop)
    (P O O)->
    ((n:nat)(P O n)->(P O (S n)))->
    ((m:nat)((n:nat)(P m n))->(P (S m) O))->
    ((m:nat)((n:nat)(P m n))->(n:nat)(P (S m) n)->(P (S m) (S n)))->
    (m,n:nat)(P m n).
End_Tex_Verb
Intros P bb_step bs_step sb_step ss_step.
Induction m.
Intros n; Apply (nat_ind (P O)); Assumption.
Intros n h i; Apply (nat_ind (P (S n))).
  Apply (sb_step n h). Exact (ss_step n h).
Qed.
*)

Implicit Arguments On.

(* Following only needed in finite, but tha's now obsolete *)

(* Begin_Tex_Verb *)
Lemma not_eq_sym: (A:Set; a,b:A) ~a=b -> ~b=a.
(* End_Tex_Verb *)
Unfold not; Auto.
Qed.

(* Begin_Tex_Verb *)
Lemma contrapos: (A,B:Prop)(A->B)->(X:Prop)(B->X)->A->X.
(* End_Tex_Verb *)
Tauto.
Qed.

(* Begin_Tex_Verb *)
Lemma deMorgan_or_and: (A,B,X:Prop)((A\/B)->X) -> (A->X)/\(B->X).
(* End_Tex_Verb *)
Tauto.
Qed.

(* Begin_Tex_Verb *)
Lemma deMorgan_and_or: (A,B,X:Prop)(A->X)/\(B->X) -> (A\/B->X).
(* End_Tex_Verb *)
Tauto.
Qed.

(* Begin_Tex_Verb *)
Lemma deMorgan_ex_all:
  (A:Set)(P:A->Prop)(X:Prop)((Ex P)->X) -> (a:A)(P a)->X.
(* End_Tex_Verb *)
Intros. Apply H; Exists a; Assumption.
Qed.

(* Begin_Tex_Verb *)
Lemma deMorgan_all_ex:
  (A:Set)(P:A->Prop)(X:Prop)((a:A)(P a)->X) -> (Ex P)->X.
(* End_Tex_Verb *)
Intros. Elim H0; Assumption.
Qed.

(* Begin_Tex_Verb *)
Inductive Ex2 [A,B:Set; P:A->B->Prop] : Prop :=
   Ex2_intro: (a:A;b:B)(P a b) -> (Ex2 P).
(* End_Tex_Verb *)

Implicit Arguments Off.

(* Tex_Prose
Three lemmas for proving properties about definitions made with case
distinction to a sumbool, i.e. \verb!{A} + {B}!.
*)
(* Begin_Tex_Verb *)
Lemma sumbool_rec_or : (A,B:Prop)(S:Set)(l,r:S)(s:{A}+{B})
                  (sumbool_rec A B [_:{A}+{B}]S [x:A]l [x:B]r s) = l \/
                  (sumbool_rec A B [_:{A}+{B}]S [x:A]l [x:B]r s) = r.
(* End_Tex_Verb *)
Intros.Elim s.
Intros.Left.Reflexivity.
Intros.Right.Reflexivity.
Qed.

(* Begin_Tex_Verb *)
Lemma not_r_sumbool_rec : (A,B:Prop)(S:Set)(l,r:S)~B->(H:{A}+{B})
                  (sumbool_rec A B [_:{A}+{B}]S [x:A]l [x:B]r H) = l.
(* End_Tex_Verb *)
Intros. Elim H0.
Intros.Reflexivity.
Intro.Elim H.Assumption.
Qed.

(* Begin_Tex_Verb *)
Lemma not_l_sumbool_rec : (A,B:Prop)(S:Set)(l,r:S)~A->(H:{A}+{B})
                          (sumbool_rec A B [_:{A}+{B}]S [x:A]l [x:B]r H) = r.
(* End_Tex_Verb *)
Intros. Elim H0.
Intro.Elim H.Assumption.
Intros.Reflexivity.
Qed.

(* Begin_Tex_Verb *)
Definition max : nat->nat->nat.
(* End_Tex_Verb *)
Intros m n.
Elim (le_lt_dec m n); Intro.
Exact n.
Exact m.
Defined.

(* Begin_Tex_Verb *)
Lemma le_max1 : (m,n:nat)(le m (max m n)).
(* End_Tex_Verb *)
Intros.
Unfold max.
Elim (le_lt_dec m n); Intro.
Simpl.
Assumption.
Simpl.
Apply le_n.
Qed.

(* Begin_Tex_Verb *)
Lemma le_max2 : (m,n:nat)(le n (max m n)).
(* End_Tex_Verb *)
Intros.
Unfold max.
Elim (le_lt_dec m n); Intro.
Simpl.
Apply le_n.
Simpl.
Apply lt_le_weak.
Assumption.
Qed.

(* Tex_Prose
\subsection{Some results about Z}
*)

(* Tex_Prose
We consider the injection \verb!inject_nat! from \verb!nat! to !Z! as a
coercion.
*)
Coercion inject_nat: nat>->Z.

(* Begin_Tex_Verb *)
Lemma POS_anti_convert :
              (n:nat)`(S n) = (POS (anti_convert n))`.
Induction n.
Simpl.
Reflexivity.
Intros.
Simpl.
Reflexivity.
Qed.
(* End_Tex_Verb *)

(* Begin_Tex_Verb *)
Lemma NEG_anti_convert :
              (n:nat)`-(S n) = (NEG (anti_convert n))`.
(* End_Tex_Verb *)
Induction n.
Simpl.
Reflexivity.
Intros.
Simpl.
Reflexivity.
Qed.

(* Begin_Tex_Verb *)
Lemma lt_O_positive_to_nat :
                     (p:positive)(m:nat)(lt O m)->(lt O (positive_to_nat p m)).
(* End_Tex_Verb *)
Intro.
Elim p.
Intros.
Simpl.
Auto with arith.
Intros.
Simpl.
Apply H.
Auto with arith.
Intros.
Simpl.
Assumption.
Qed.

(* Begin_Tex_Verb *)
Lemma anti_convert_pred_convert :
                          (p:positive)(p = (anti_convert (pred (convert p)))).
(* End_Tex_Verb *)
Intro.
Pattern 1 p.
Rewrite <- bij3.
Cut (EX n:nat | (convert p) = (S n)).
Intro.
Elim H; Intros.
Rewrite H0.
Elim x.
Simpl.
Reflexivity.
Intros.
Simpl.
Rewrite sub_add_one.
Reflexivity.
Exists (pred (convert p)).
Apply S_pred with O.
Unfold convert.
Apply lt_O_positive_to_nat.
Auto with arith.
Qed.

(* Begin_Tex_Verb *)
Lemma p_is_some_anti_convert : (p:positive)(EX n:nat | p = (anti_convert n)).
(* End_Tex_Verb *)
Intro.
Exists (pred (convert p)).
Apply anti_convert_pred_convert.
Qed.

(* Begin_Tex_Verb *)
Lemma convert_is_POS :
              (p:positive)`(convert p) = (POS p)`.
(* End_Tex_Verb *)
Intro.
Elim (p_is_some_anti_convert p).
Intros.
Rewrite H.
Rewrite bij1.
Apply POS_anti_convert.
Qed.

(* Begin_Tex_Verb *)
Lemma min_convert_is_NEG :
              (p:positive)`-(convert p) = (NEG p)`.
(* End_Tex_Verb *)
Intro.
Elim (p_is_some_anti_convert p).
Intros.
Rewrite H.
Rewrite bij1.
Apply NEG_anti_convert.
Qed.

(* Begin_Tex_Verb *)
Lemma Z_exh : (z:Z)(EX n:nat | z=n) \/ (EX n:nat | z=`-n`).
(* End_Tex_Verb *)
Intro.
Elim z.
Left.
Exists O.
Auto.
Intro.
Left.
Exists (convert p).
Rewrite convert_is_POS.
Reflexivity.
Intro.
Right.
Exists (convert p).
Rewrite min_convert_is_NEG.
Reflexivity.
Qed.

(* Begin_Tex_Verb *)
Lemma nats_Z_ind :
                 (P:Z->Prop)((n:nat)(P n)) -> ((n:nat)(P `-n`)) -> (z:Z)(P z).
(* End_Tex_Verb *)
Intros.
Elim (Z_exh z); Intros.
Elim H1; Intros.
Rewrite H2.
Apply H.
Elim H1; Intros.
Rewrite H2.
Apply H0.
Qed.

(* Begin_Tex_Verb *)
Lemma pred_succ_Z_ind : (P:Z->Prop)(P `0`) ->
                                   ((n:Z)(P n)->(P `n+1`)) ->
                                   ((n:Z)(P n)->(P `n-1`)) ->
                                   (z:Z)(P z).
(* End_Tex_Verb *)
Intros.
Apply nats_Z_ind.
Intro.
Elim n.
Exact H.
Intros.
Replace ((S n0)::Z) with `n0+1`.
Apply H0.
Assumption.
Rewrite inj_S.
Reflexivity.
Intros.
Elim n.
Exact H.
Intros.
Replace `-(S n0)` with `-n0-1`.
Apply H1.
Assumption.
Rewrite inj_S.
Unfold Zs.
Rewrite Zopp_Zplus.
Reflexivity.
Qed.

(* Begin_Tex_Verb *)
Lemma Zmult_minus_distr_r : (n,m,p:Z)`p*(n-m) = p*n-p*m`.
(* End_Tex_Verb *)
Intros.
Rewrite Zmult_sym.
Rewrite Zmult_minus_distr.
Rewrite Zmult_sym.
Pattern `m*p`.
Rewrite Zmult_sym.
Reflexivity.
Qed.

(* Begin_Tex_Verb *)
Lemma Zodd_Zeven_min1 : (x:Z)(Zodd x) -> (Zeven `x-1`).
(* End_Tex_Verb *)
Intro x.
Elim x.
Simpl.
Auto.
Induction p.
Simpl.
Auto.
Intros.
Simpl in H0.
Tauto.
Simpl; Auto.
Induction p.
Simpl; Auto.
Simpl; Auto.
Auto.
Qed.

Implicit Arguments On.
(* Begin_Tex_Verb *)
Definition caseZ_diff := [A:Set][z:Z][f:nat->nat->A]
  Cases z of
    ZERO => (f O O)
  | (POS m) => (f (convert m) O)
  | (NEG m) => (f O (convert m))
  end.
(* End_Tex_Verb *)
Implicit Arguments Off.

(* Begin_Tex_Verb *)
Lemma caseZ_diff_O : (A:Set)(f:nat->nat->A)(caseZ_diff `0` f) = (f O O).
(* End_Tex_Verb *)
Intros.
Reflexivity.
Qed.

(* Begin_Tex_Verb *)
Lemma caseZ_diff_Pos : (A:Set)(f:nat->nat->A)(n:nat)
                       (caseZ_diff `n` f) = (f n O).
(* End_Tex_Verb *)
Intros.
Elim n.
Reflexivity.
Intros.
Simpl.
Rewrite bij1.
Reflexivity.
Qed.

(* Begin_Tex_Verb *)
Lemma caseZ_diff_Neg : (A:Set)(f:nat->nat->A)(n:nat)
                       (caseZ_diff `-n` f) = (f O n).
(* End_Tex_Verb *)
Intros.
Elim n.
Reflexivity.
Intros.
Simpl.
Rewrite bij1.
Reflexivity.
Qed.

(* Begin_Tex_Verb *)
Lemma proper_caseZ_diff : (A:Set)(f:nat->nat->A)
              ((m,n,p,q:nat)(plus m q) = (plus n p) -> (f m n) = (f p q)) ->
              (m,n:nat)(caseZ_diff `m-n` f) = (f m n).
(* End_Tex_Verb *)
Intros.
Pattern m n.
Apply nat_double_ind.
Intro.
Replace `O-n0` with `-n0`.
Rewrite caseZ_diff_Neg.
Reflexivity.
Simpl.
Reflexivity.
Intros.
Replace `(S n0)-O` with `(S n0)`::Z.
Rewrite caseZ_diff_Pos.
Reflexivity.
Simpl.
Reflexivity.
Intros.
Rewrite H with (S n0) (S m0) n0 m0.
Rewrite <- H0.
Replace `(S n0)-(S m0)` with `n0-m0`.
Reflexivity.
Repeat Rewrite inj_S.
Omega.
Omega.
Qed.

(* Begin_Tex_Verb *)
Lemma diff_Z_ind : (P:Z->Prop)((m,n:nat)(P `m-n`)) -> ((z:Z)(P z)).
(* End_Tex_Verb *)
Intros.
Apply nats_Z_ind.
Intro.
Replace `n`::Z with `n-O`.
Apply H.
Simpl.
Omega.
Intro.
Replace `-n` with `O-n`.
Apply H.
Simpl.
Reflexivity.
Qed.


