{-# OPTIONS --allow-unsolved-metas #-}
-- AGDA IN PADOVA 2023
-- Exercise sheet 6

-- The usual naturals, the constructor names shortened to "zer" and "suc"
-- to not confuse them with the ordinal zero and ordinal successor
-- (Agda wouldn't mind, but we might).
data  : Set where
  zer : 
  suc :   


-----------------------------
----[ BASIC DEFINITIONS ]----
-----------------------------

-- "O" will be the type of (representations of) (countable) ordinal numbers.
data O : Set

-- "x ≤ y" will be the type of witnesses that "x" is smaller or equal to "y".
data _≤_ : O  O  Set

-- "x < y" will be the type of witnesses that "x" is strictly smaller than "y".
_<_ : O  O  Set

-- "Monotonic f" is the type of witnesses that "f" is a strictly increasing sequence
-- of ordinals.
Monotonic : (  O)  Set
Monotonic f = (a : )  f a < f (suc a)

-- The following definition expresses the three fundamental convictions regarding
-- (countable) ordinal numbers:
-- 1. zero should exist.
-- 2. Every number should have a successor.
-- 3. Every (strictly increasing) sequence should have a limit.
data O where
  zero : O
  succ : O  O
  lim  : (f :   O)  Monotonic f  O

data _≤_ where
  ≤-zero     : {x : O}      zero  x
  ≤-trans    : {x y z : O}  x  y  y  z  x  z
  ≤-succ-mon : {x y : O}    x  y  succ x  succ y
  ≤-cocone   : {f :   O} {fmon : Monotonic f} {x : O} {n : }
              x  f n  x  lim f fmon
  ≤-limiting : {f :   O} {fmon : Monotonic f} {x : O}
              ((n : )  f n  x)  lim f fmon  x

x < y = succ x  y


----------------------------
----[ BASIC PROPERTIES ]----
----------------------------

-- If the terms of "f" are all smaller than the corresponding term in "g",
-- then the limit of "f" is smaller than the limit of "g".
lim-mon
  : {f g :   O} {fmon : Monotonic f} {gmon : Monotonic g}
   ((n : )  f n  g n)
   lim f fmon  lim g gmon
lim-mon p = ≤-limiting  n  ≤-cocone (p n))

refl : {x : O}  x  x
refl {zero}       = ≤-zero
refl {succ x}     = ≤-succ-mon refl
refl {lim f fmon} = lim-mon  a  refl)

id≤succ : {x : O}  x  succ x
id≤succ {zero}    = ≤-zero
id≤succ {succ x}  = ≤-succ-mon id≤succ
id≤succ {lim f x} = ≤-limiting  n  ≤-trans id≤succ (≤-succ-mon (≤-cocone refl)))


--------------------------
----[ BASIC EXAMPLES ]----
--------------------------

fromℕ :   O
fromℕ zer     = zero
fromℕ (suc n) = succ (fromℕ n)

fromℕ-monotonic : Monotonic fromℕ
fromℕ-monotonic n = refl

ω : O
ω = lim fromℕ fromℕ-monotonic

ω' : O
ω' = lim  n  fromℕ (suc n))  n  refl)

example₀ : ω  ω'
example₀ = lim-mon  n  id≤succ)

example₁ : ω'  ω
example₁ = ≤-limiting  n  ≤-cocone {n = suc n} refl)


----------------------------
----[ ORDINAL ADDITION ]----
----------------------------

-- The following two functions are defined in a mutually recursive fashion.
_+_ : O  O  O
+-mon : {x a b : O}  a  b  (x + a)  (x + b)

a + zero       = a
a + succ b     = succ (a + b)
a + lim f fmon = lim  n  a + f n)  n  +-mon (fmon n))

+-mon {b = zero} ≤-zero       = refl
+-mon {b = succ b} ≤-zero     = ≤-trans id≤succ (≤-succ-mon (+-mon ≤-zero))
+-mon {b = lim f fmon} ≤-zero = ≤-cocone (+-mon (≤-zero {f zer}))
+-mon (≤-trans p q)           = ≤-trans (+-mon p) (+-mon q)
+-mon (≤-succ-mon p)          = ≤-succ-mon (+-mon p)
+-mon (≤-cocone p)            = ≤-cocone (+-mon p)
+-mon (≤-limiting p)          = ≤-limiting  b  +-mon (p b))

example₂ : ω < (ω + succ zero)
example₂ = refl

example₃ : (succ zero + ω)  ω
example₃ = ≤-limiting  n  ≤-cocone {n = suc n} (lemma n))
  where
  lemma : (n : )  (succ zero + fromℕ n)  succ (fromℕ n)
  lemma zer = refl
  lemma (suc n) = ≤-succ-mon (lemma n)

-- EXERCISE: Prove this.
+-zero : (a : O)  (zero + a)  a
+-zero = ?

-- EXERCISE: Prove this. For some clauses, you may need to case split
-- on the implicit variable a.
+-mon' : {x y a : O}  x  y  (x + a)  (y + a)
+-mon' {a = a} p = ?


-----------------------------------
----[ MORE ORDINAL ARITHMETIC ]----
-----------------------------------

-- EXERCISE: Define ordinal multiplication and exponentiation, by
-- implementing the rules listed on the Wikipedia page on ordinal arithmetic.

-- EXERCISE: Define the ordinal number ε₀.

-- EXERCISE: State and prove that ω ^ ε₀ is the same as ε₀.

-- EXERCISE: Define the numbers ε₁, ε₂, ...

-- NOTE: Do not expect these exercises to have short solutions.
-- The monotonicity requirement in the "lim" constructor entails
-- quite a few proof obligations. However, we cannot drop this
-- requirement as else exponentiation is no longer definable:
-- The definition requires a case distinction which is possible
-- only because of the monotonicity requirement.

-- For an extensive discussion, see https://arxiv.org/abs/2208.03844.


----------------------------------
----[ LEMMAS FOR COMPARISONS ]----
----------------------------------

data Σ (A : Set) (B : A  Set) : Set where
  _,_ : (x : A)  (y : B x)  Σ A B

proj₁ : {A : Set} {B : A  Set}  Σ A B  A
proj₁ (x , y) = x

proj₂ : {A : Set} {B : A  Set}  (p : Σ A B)  B (proj₁ p)
proj₂ (x , y) = y

-- "f simulates g" expresses that every term in the sequence "g"
-- is dominated by some term in the sequence "f".
-- For instance, the sequence 0,1,2,… simulates the sequence 0,1,2,4,8,16,…
-- (and vice versa).
_simulates_ : (  O)  (  O)  Set
f simulates g = (a : )  Σ   b  g a  f b)

-- EXERCISE: Prove this.
comparison-lemma
  : {f g :   O} {fmon : Monotonic f} {gmon : Monotonic g}
   f simulates g  lim g gmon  lim f fmon
comparison-lemma sim = ?

-- EXERCISE: Reprove "lim-mon" from above using "comparison-lemma".
lim-mon'
  : {f g :   O} {fmon : Monotonic f} {gmon : Monotonic g}
   ((n : )  f n  g n)
   lim f fmon  lim g gmon
lim-mon' p = comparison-lemma  n  n , p n)


--------------------------------------
----[ THE FAST-GROWING HIERARCHY ]----
--------------------------------------

-- EXERCISE: Implement the "fast-growing hierarchy" of functions,
-- by following the definition of the respective Wikipedia entry.