(* This program is free software; you can redistribute it and/or      *)
(* modify it under the terms of the GNU Lesser General Public License *)
(* as published by the Free Software Foundation; either version 2.1   *)
(* of the License, or (at your option) any later version.             *)
(*                                                                    *)
(* This program is distributed in the hope that it will be useful,    *)
(* but WITHOUT ANY WARRANTY; without even the implied warranty of     *)
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the      *)
(* GNU General Public License for more details.                       *)
(*                                                                    *)
(* You should have received a copy of the GNU Lesser General Public   *)
(* License along with this program; if not, write to the Free         *)
(* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *)
(* 02110-1301 USA                                                     *)

(************************************************************************)
(* Copyright 2005 Milad Niqui                                           *)
(* This file is distributed under the terms of the                      *) 
(* GNU Lesser General Public License Version 2.1                        *)
(************************************************************************)

(** We start by some general notions for expressing the bijection *)

Definition identity (A:Type) := fun (a:A) => a.
Definition compose (A B C:Type) (g:B->C) (f:A->B) := fun (a:A) => g(f a).

Section Denumerability.

(** What it means to have the same cardinality *)
Definition same_cardinality (A:Type) (B:Type) :=
 {f:A->B & { g:B->A | 
  (forall b,(compose _ _ _ f g) b = (identity B) b) /\
   forall a,(compose _ _ _ g f) a = (identity A) a}}.

(** What it means to be a denumerable *)
Definition is_denumerable A := same_cardinality A nat.

Lemma same_cardinality_transitive :
 forall A B C, same_cardinality A B -> same_cardinality B C -> same_cardinality A C.
Proof.
Admitted.

Lemma is_denumerable_transitive :
 forall A B, is_denumerable A -> same_cardinality B A -> is_denumerable B.
Proof.
Admitted.

End Denumerability.

(** We first prove that [Z] is denumerable *)

From Coq Require Import ZArith.
From Coq Require Import Lia.

(** An injection from [Z] to [nat] *)
Definition Z_to_nat_i (z:Z) :nat :=
   match z with 
   | Z0 => O
   | Zpos p => Nat.double (nat_of_P p)
   | Zneg p => pred (Nat.double (nat_of_P p))
   end.

(** Some lemmas about parity. *)
Lemma odd_pred2n: forall n : nat, Nat.
Proof.
Admitted.

Lemma even_2n : forall n : nat, Nat.
Proof.
Admitted.

Lemma even_odd_exists_dec : forall n, {p : nat | n = Nat.
Proof.
Admitted.

(** An injection from [nat] to [Z] *)
Definition nat_to_Z_i (n:nat) := 
  match even_odd_exists_dec n with
  | inl s => let (k, _) := s in Z_of_nat k
  | inr s => let (k, _) := s in Z.opp (Z_of_nat k)
  end.

Lemma double_eq_half_eq:forall m n, Nat.
Proof.
Admitted.

Lemma parity_mismatch_not_eq:forall m n, Nat.
Proof.
Admitted.

Lemma even_double : forall n, Nat.
Proof.
Admitted.

Lemma double_S_neq_pred:forall m n, ~Nat.
Proof.
Admitted.

Lemma eq_add_pred : forall n m : nat, pred n = pred m -> {n = m} + {n < 2 /\ m < 2}.
Proof.
Admitted.

(** We prove that the maps [Z_to_nat_i] is the right inverse of [nat_to_Z_i].*)

Lemma nat_to_Z_to_nat_i : forall (z:Z), nat_to_Z_i (Z_to_nat_i z) = z.
Proof.
Admitted.

(** We prove that the maps [Z_to_nat_i] is the left inverse of [nat_to_Z_i].*)

Lemma Z_to_nat_to_Z_i : forall (n:nat), Z_to_nat_i (nat_to_Z_i n) = n.
Proof.
Admitted. 

(** And hence [Z] is denumerable: *)

Theorem Z_is_denumerable:is_denumerable Z.
Proof.
Admitted.

(** Next we prove that [Q] and [Z] have the same cardinality *)

From QArithSternBrocot Require Import Q_field.

(** Here there is not much to prove, as [Z] and [Q] are isomorphic data-types.*)

(** An injection from [positive] to [Qpositive]: *)
Fixpoint positive_to_Qpositive_i (p:positive) : Qpositive := 
   match p with 
   | xI p => nR (positive_to_Qpositive_i p)
   | xO p => dL (positive_to_Qpositive_i p)
   | xH => One
   end. 

(** An injection from [Z] to [Q] *)
Definition Z_to_Q_i (z:Z) :=
   match z with 
   | Z0 => Zero
   | Zpos p => Qpos (positive_to_Qpositive_i p)
   | Zneg p => Qneg (positive_to_Qpositive_i p)
   end. 

(** An injection from [Qpositive] to [positive] *) 
Fixpoint Qpositive_to_positive_i (qp:Qpositive) : positive := 
   match qp with 
   | nR qp => xI (Qpositive_to_positive_i qp)
   | dL qp => xO (Qpositive_to_positive_i qp)
   | One => xH
   end. 

(** An injection from [Q] to [Z] *)
Definition Q_to_Z_i (q:Q) :=
   match q with 
   | Zero => Z0
   | Qpos qp => Zpos (Qpositive_to_positive_i qp)
   | Qneg qp => Zneg (Qpositive_to_positive_i qp)
   end. 

(** Proof that [Qpositive_to_positive_i] is the left inverse of [positive_to_Qpositive_i]:*)
Lemma Qpositive_to_positive_to_Qpositive_i : forall (p:positive), Qpositive_to_positive_i (positive_to_Qpositive_i p) = p.
Proof.
Admitted.

(** Proof that [Qpositive_to_positive_i] is the right inverse of [positive_to_Qpositive_i]:*)
Lemma positive_to_Qpositive_to_positive_i : forall qp, positive_to_Qpositive_i (Qpositive_to_positive_i qp) = qp.
Proof.
Admitted.

(** Proof that [Q_to_Z_i] is the left inverse of [Z_to_Q_i]:*)
Lemma Q_to_Z_to_Q_i : forall (z:Z), Q_to_Z_i (Z_to_Q_i z) = z.
Proof.
Admitted.

(** Proof that [Q_to_Z_i] is the right inverse of [Z_to_Q_i]:*)
Lemma Z_to_Q_to_Z_i : forall (q:Q), Z_to_Q_i (Q_to_Z_i q) = q.
Proof.
Admitted.

(** And hence [Q] is denumerable: *)
Theorem Q_is_denumerable: is_denumerable Q.
Proof.
Admitted.