(*                (c) Copyright, Bill Richter 2013                           *)
(*          Distributed under the same license as HOL Light                  *)
(*                                                                           *)
(* Definitions of FunctionSpace and FunctionComposition.   A proof that the  *)
(* Cartesian product satisfies the universal property that given functions   *)
(* α â M â A and β â M â B, there is a unique γ â M â A â B whose            *)
(* projections to A and B are f and g.                                       *)
needs "RichterHilbertAxiomGeometry/readable.ml";;
ParseAsInfix("â",(11, "right"));;
ParseAsInfix("â",(20, "right"));;
ParseAsInfix("â",(20, "right"));;
ParseAsInfix("â",(13,"right"));;
(*
â |- âa l. a â l â ¬(a â l)
CartesianProduct
  |- âX Y. X â Y = {x,y | x â X â§ y â Y}
FUNCTION |- âα. FUNCTION α â
             (âf s t.  α = t,f,s â§
                  (âx. x â s â f x â t) â§ (âx. x â s â f x = (@y. T)))
SOURCE |- âα. SOURCE α = SND (SND α)
FUN |- âα. FUN α = FST (SND α)
TARGET |- âα. TARGET α = FST α
FunctionSpace
  |- âs t.  s â t = {α | FUNCTION α â§ s = SOURCE α â§ t = TARGET α}
makeFunction
  |- ât f s. makeFunction t f s = t,(λx. if x â s then f x else @y. T),s
Projection1Function
  |- âX Y. Pi1 X Y = makeFunction X FST (X â Y)
Projection2Function
  |- âX Y. Pi2 X Y = makeFunction Y SND (X â Y)
FunctionComposition
  |- âα β.  α â β = makeFunction (TARGET α) (FUN α o FUN β) (SOURCE β)
IN_CartesianProduct
  |- âX Y x y. x,y â X â Y â x â X â§ y â Y
CartesianFstSnd
  |- âpair. pair â X â Y â FST pair â X â§ SND pair â Y
FUNCTION_EQ
  |- âα β.  FUNCTION α â§ FUNCTION β â§ SOURCE α = SOURCE β â§ FUN α = FUN β â§
        TARGET α = TARGET β  â  Î± = β
IN_FunctionSpace
  |- âs t α.  α â s â t â
         FUNCTION α ⧠s = SOURCE α ⧠t = TARGET α
makeFunction_EQ
  |- âf g s t.  (âx. x â s â f x = g x)
         â makeFunction t f s = makeFunction t g s
makeFunctionyieldsFUN
  |- âα g t f s.  α = makeFunction t f s â§ g = FUN α
         â âx. x â s â f x = g x
makeFunctionEq
  |- âα β f g s t.
         α = makeFunction t f s ⧠β = makeFunction t g s â§
         (âx. x â s â f x = g x)  â  Î± = β
FunctionSpaceOnSource
  |- âα f s t.  α â s â t â§ f = FUN α  â  (âx. x â s â f x â t)
FunctionSpaceOnOffSource
  |- âα f s t.  α â s â t â§ f = FUN α
         â (âx. x â s â f x â t) â§ (âx. x â s â f x = (@y. T))
ImpliesTruncatedFunctionSpace
  |- âα s t f.
         α = makeFunction t f s â§ (âx. x â s â f x â t)
         â α â s â t
FunFunctionSpaceImplyFunction
  |- âα s t f.  α â s â t â§ f = FUN α  â  Î± = makeFunction t f s
UseFunctionComposition
  |- âα β u f t g s.
         α = makeFunction u f t ⧠β = makeFunction t g s ⧠β â s â t
         â α â β = makeFunction u (f o g) s
PairProjectionFunctions
  |- âX Y. Pi1 X Y â X â Y â X â§ Pi2 X Y â X â Y â Y
UniversalPropertyProduct
  |- âM A B α β.  α â M â A ⧠β â M â B
                    â (â!γ. γ â M â A â B â§
                       Pi1 A B â γ = α â§ Pi2 A B â γ = β)
*)
let NOTIN = NewDefinition `;
  âa l. a â l â ¬(a â l)`;;
let CartesianProduct = NewDefinition `;
  âX Y. X â Y = {x,y | x â X â§ y â Y}`;;
let FUNCTION = NewDefinition `;
  FUNCTION α  â  âf s t. α = (t, f, s)  â§
    (âx. x IN s â f x  IN t) â§ âx. x â s â f x  = @y. T`;;
let SOURCE = NewDefinition `;
  SOURCE α = SND (SND α)`;;
let FUN = NewDefinition `;
  FUN α = FST (SND α)`;;
let TARGET = NewDefinition `;
  TARGET α = FST α`;;
let FunctionSpace = NewDefinition `;
  âs t. s â t = {α | FUNCTION α  â§  s = SOURCE α  â§ t = TARGET α}`;;
let makeFunction = NewDefinition `;
  ât f s. makeFunction t f s = (t, (λx. if x â s then f x else @y. T), s)`;;
let Projection1Function = NewDefinition `;
  Pi1 X Y = makeFunction X FST (X â Y)`;;
let Projection2Function = NewDefinition `;
  Pi2 X Y = makeFunction Y SND (X â Y)`;;
let FunctionComposition = NewDefinition `;
  âα β.  α â β = makeFunction (TARGET α) (FUN α o FUN β) (SOURCE β)`;;
let IN_CartesianProduct = theorem `;
  âX Y x y. x,y â X â Y  â  x â X â§ y â Y
  proof
    rewrite IN_ELIM_THM CartesianProduct;     fol PAIR_EQ;     qed;
`;;
let IN_CartesianProduct = theorem `;
  âX Y x y. x,y â X â Y  â  x â X â§ y â Y
  proof
    rewrite IN_ELIM_THM CartesianProduct;     fol PAIR_EQ;     qed;
`;;
let CartesianFstSnd = theorem `;
  âpair. pair â X â Y  â  FST pair â X â§ SND pair â Y
  by rewrite FORALL_PAIR_THM PAIR_EQ IN_CartesianProduct`;;
let FUNCTION_EQ = theorem `;
  âα β. FUNCTION α  â§  FUNCTION β  â§  SOURCE α = SOURCE β  â§
    FUN α = FUN β  ⧠ TARGET α = TARGET β
    â α = β
  by simplify FORALL_PAIR_THM FUNCTION SOURCE TARGET FUN PAIR_EQ`;;
let IN_FunctionSpace = theorem `;
  âs t α. α â s â t
    â  FUNCTION α  â§  s = SOURCE α  â§  t = TARGET α
  by rewrite IN_ELIM_THM FunctionSpace`;;
let makeFunction_EQ = theorem `;
  âf g s t.  (âx. x â s â f x = g x)
    â  makeFunction t f s = makeFunction t g s
  by simplify makeFunction â FUN_EQ_THM`;;
let makeFunctionyieldsFUN = theorem `;
  âα g t f s.  α = makeFunction t f s â§ g = FUN α
    â âx. x â s â f x = g x
  by simplify makeFunction FORALL_PAIR_THM FUN PAIR_EQ`;;
let makeFunctionEq = theorem `;
  âα β f g s t.  α = makeFunction t f s  ⧠β = makeFunction t g s  â§
    (âx. x â s â f x = g x)  â  Î± = β
  by simplify FORALL_PAIR_THM makeFunction PAIR_EQ`;;
let FunctionSpaceOnSource = theorem `;
  âα f s t.  α â s â t  â§  f = FUN α
    â  âx. x â s â f x â t
  proof
    rewrite FORALL_PAIR_THM IN_FunctionSpace FUNCTION SOURCE TARGET PAIR_EQ FUN;
    fol;     qed;
`;;
let FunctionSpaceOnOffSource = theorem `;
  âα f s t.  α â s â t  â§  f = FUN α
    â  (âx. x â s â f x â t) â§ âx. x â s â f x = @y. T
  proof
    rewrite FORALL_PAIR_THM IN_FunctionSpace FUNCTION SOURCE TARGET PAIR_EQ FUN;
    fol;     qed;
`;;
let ImpliesTruncatedFunctionSpace = theorem `;
  âα s t f.  α = makeFunction t f s  â§  (âx. x â s â f x â t)
    â α â s â t
  proof
    rewrite FORALL_PAIR_THM IN_FunctionSpace makeFunction FUNCTION SOURCE TARGET NOTIN PAIR_EQ;
    fol;
  qed;
`;;
let FunFunctionSpaceImplyFunction = theorem `;
  âα s t f.  α â s â t  â§  f = FUN α  â  Î± = makeFunction t f s
  proof
    rewrite FORALL_PAIR_THM IN_FunctionSpace makeFunction FUNCTION SOURCE TARGET FUN NOTIN PAIR_EQ;
    fol FUN_EQ_THM;
  qed;
`;;
let UseFunctionComposition = theorem `;
  âα β u f t g s. α = makeFunction u f t  â§
    β = makeFunction t g s  â§  β â s â t
    â α _o_ β = makeFunction u (f o g) s
  proof
    rewrite FORALL_PAIR_THM makeFunction FunctionComposition SOURCE TARGET FUN BETA_THM o_THM IN_FunctionSpace FUNCTION SOURCE TARGET NOTIN PAIR_EQ;
    X_genl_TAC u' f' t' t1 g1 s1 u f t g s;
    intro_TAC Hα Hβ Hβ_st Hs Ht;
    (âx. x â s â g x â t)     [g_st] by fol Hβ_st Hβ;
    simplify Hα GSYM Hs Hβ g_st;
  qed;
`;;
let PairProjectionFunctions = theorem `;
  âX Y. Pi1 X Y â X â Y â X  â§  Pi2 X Y â X â Y â Y
  proof
    intro_TAC âX Y;
    âpair. pair â X â Y  â  FST pair â X  â§ SND pair â Y     [] by fol CartesianFstSnd;
    fol Projection1Function Projection2Function - ImpliesTruncatedFunctionSpace;
  qed;
`;;
let UniversalPropertyProduct = theorem `;
  âM A B α β.  α â M â A  â§  β â M â B
      â  â!γ.  γ â M â A â B  â§  Pi1 A B â γ = α  â§  Pi2 A B â γ = β
  proof
    intro_TAC âM A B α β, H1;
    consider f g such that f = FUN α ⧠g = FUN β     [fgExist] by fol;
    consider h such that h = λx. (f x,g x)     [hExists] by fol;
    âx. x â M  â  h x â A â B     [hProd] by fol hExists IN_CartesianProduct H1 fgExist FunctionSpaceOnSource;
    consider γ such that γ = makeFunction (A â B) h  M     [γExists] by fol;
    γ â M â A â B     [γFunSpace] by fol - hProd ImpliesTruncatedFunctionSpace;
    âx. x â M  â  (FST o h) x = f x  â§  (SND o h) x = g x     [h_fg] by simplify hExists PAIR o_THM;
    Pi1 A B â γ = makeFunction A (FST o h) M  â§
    Pi2 A B â γ = makeFunction B (SND o h) M     [] by fol Projection1Function Projection2Function γExists  γFunSpace UseFunctionComposition;
    Pi1 A B â γ = α  â§  Pi2 A B â γ = β     [γWorks] by fol - h_fg makeFunction_EQ H1 fgExist FunFunctionSpaceImplyFunction;
   âθ.  θ â M â A â B  â§  Pi1 A B â θ = α  â§  Pi2 A B â θ = β  â θ = γ     []
     proof
      intro_TAC âθ, θWorks;
      consider k such that k = FUN θ     [kExists] by fol;
      θ = makeFunction (A â B) k M     [θFUNk] by fol θWorks - FunFunctionSpaceImplyFunction;
      α = makeFunction A (FST o k) M  ⧠ β = makeFunction B (SND o k) M     [] by fol Projection1Function Projection2Function θFUNk θWorks UseFunctionComposition;
      âx. x â M  â  f x = (FST o k) x â§ g x = (SND o k) x     [fg_k] by fol ISPECL [α; f; A; (FST o k); M] makeFunctionyieldsFUN ISPECL [β; g; B; (SND o k); M] makeFunctionyieldsFUN - fgExist;
      âx. x â M â k x = ((FST o k) x, (SND o k) x)     [] by fol PAIR o_THM;
      âx. x â M â k x = (f x, g x)     [] by fol - fg_k PAIR_EQ;
      fol hExists θFUNk γExists  - makeFunctionEq;
     qed;
     fol γFunSpace γWorks - EXISTS_UNIQUE_THM;
  qed;
`;;