{-# OPTIONS --allow-unsolved-metas #-}
module session09 where

{-
  Options for today:

  0. Exercises [0]

  1. The infinite hat problem [3]
  
  2. Seemingly impossible programs [2]

  3. Sets as trees, giving (opinionated) answers to questions such as: [3]

     - What is the relation between sets and types?
     - What is a set?
     - Why should we not form the set of all subsets of a set?
       (In predicative mathematics, we don't accept the powerset construction.)
     - Why is the axiom of choice in general false, but why is countable choice true?
     - Why can we not always form the set { x ∈ X | ... }?

  4. The curious world of infinite-time Turing machines [no Agda code] [4]

     - An injection ℝ ↪ ℕ
     - What is problematic about (¬ ¬ (Σ[ n ∈ ℕ ] P n)) → Σ[ n ∈ ℕ ] P n?

  5. Forcing [0]

     - How can we prove that a function f : (ℕ → Bool) → X only inspects finitely
       many values of its argument φ : ℕ → Bool?
     - How can we throw exceptions in pure mathematics?
     - How can we turn any set X into a countable set, i.e. a set with a surjection ℕ ↠ X?
     - How can we construct an intermediate infinity between ℕ and (ℕ → Bool)?

  6. Metamathematics [3]

     - How can Agda talk about provability?
     - Metaproving that the double negation translation is effective
-}

open import Padova2025.Explorations.Uncountability.Applications
open import Padova2025.Explorations.Uncountability.Impossible.Toy
open import Padova2025.ProgrammingBasics.Booleans
open import Padova2025.ProgrammingBasics.Lists
open import Padova2025.ProgrammingBasics.Naturals.Base
open import Padova2025.ProvingBasics.Termination.Gas hiding (𝟙)

-- Given f, g : (ℕ → Bool) → Bool, is it decidable whether f and g produce the same outputs?
-- Is it possible to write an algorithm which determines whether f x ≡ g x for all x?
--
-- The type (ℕ → Bool) contains infinitely many values, in fact uncountably many,
-- so it should be impossible to write such a decision algorithm.

f : (  Bool)  Bool
f φ = false

open import Padova2025.ProgrammingBasics.Operators

g : (  Bool)  Bool
g φ = not (φ three) || not (φ one)

wtf : Bool
wtf = f ≡? g

-- Is it possible to determine whether a function f : (ℕ → Bool) → Bool has a root?
-- (A root is a function φ : ℕ → Bool such that f φ ≡ false.)

wtf' : Maybe (List Bool)
wtf' = root g


-- A Σ₁-set is a set of the form { n ∈ ℕ | ∃a ∈ ℕ. ∃b ∈ ℕ. ... ∃z ∈ ℕ. % },
-- with no further quantifiers in % (only =, ∧, ∨, ⇒, ⊥, ⊤)



module InfiniteHatProblem
  (Player : Set)
  (Color  : Set)
  where

  open import Padova2025.ProgrammingBasics.Lists
  open import Padova2025.ProvingBasics.Equality.Base
  open import Padova2025.ProvingBasics.Equality.General
  open import Padova2025.ProvingBasics.Negation
  open import Padova2025.ProvingBasics.Connectives.Disjunction
  open import Padova2025.ProvingBasics.Connectives.Existential
  open import Padova2025.ProvingBasics.Connectives.More

  Configuration : Set
  Configuration = (Player  Color)

  -- The evil monster will pick a configuration.

  BlindedConfiguration : Player  Set
  BlindedConfiguration p = (q : Player)  q  p  Color

  blind : Configuration  (p : Player)  BlindedConfiguration p
  blind c p = λ q _  c q

  IndividualStrategy : Player  Set
  IndividualStrategy p = BlindedConfiguration p  Color

  TeamStrategy : Set
  TeamStrategy = (p : Player)  IndividualStrategy p

  _≈_ : Configuration  Configuration  Set
  c  c' = Σ[ ps  List Player ] ((p : Player)  (c p  c' p)  (p  ps))

  -- `run s c` is a function which maps a player `p` to the guess made by player `p`
  -- when following strategy `s` in the situation `c`
  run : TeamStrategy  Configuration  (Player  Color)
  run s c p = s p (blind c p)

  isSuccessful : TeamStrategy  Set
  isSuccessful s = (c : Configuration)  c  run s c


module SetsAsTrees where

  {- Set theory has two fundamental ideas:

     1. Everything is a set. (For instance, the natural number zero
        can be encoded as the empty set ∅. The natural number one can
        be encoded as the set { 0 } = { ∅ } = {{}}. The natural number two
        can be encoded as the set { 0, 1 } = { {}, {{}} }. ...
        The ordinal number ω can be encoded as the set { 0, 1, 2, ... }.
        The ordinal number ω + 1 can be encoded as the set { ω, 0, 1, 2, ... }.)

     2. Up to some limitations, given a collection of sets,
        we can form the set of those sets.

     But formal set theory in the guise of ZFC (Zermelo–Fraenkel with the axiom
     of choice) leaves open the question what a set actually is. ZFC just has
     axioms like the following:

     A. There is a set which is empty.
     B. Given sets X and Y, there is a set which contains both X and Y.
     C. Given a set X, there is a set (typically written ⋃ X) which contains
        all the elements of the elements of X.
     ...

     As a consequence, as predicted by Gödel's incompleteness theorem,
     many assertions about sets are neither provable in ZFC nor refutable in ZFC.
     (For instance the continuum hypothesis is neither provable nor refutable.)
  -}

  -- Let's define, in Agda, the type V of all sets (sets as in set theory).
  -- The type V is not small (so does not belong to Agda's type Set of all small types).
  -- The type V is large (so belongs to Set₁).
  -- This type V will turn out to be a model of CZF (Constructive Zermelo–Fraenkel).
  -- If we activate Agda's classical mode, then V will turn out to be a model of ZF.
  data V : Set₁ where
    sup : {I : Set}  (I  V)  V
    -- We picture a function f : I → V as a family of sets,
    -- namely as the family consisting of the (f i)'s,
    -- where i ranges over the values of I.
    -- We then picture `sup f` as the set which contains
    -- exactly the members of the family `f` as elements.

   : V
   = sup {} λ ()
    where
    data  : Set where

  -- The set { ∅ } = 1.
  uno : V
  uno = sup {𝟙} λ i  
    where
    data 𝟙 : Set where
      * : 𝟙

  -- The set { 0, 1 } = 2.
  due : V
  due = sup {Bool} λ { false   ; true  uno }
  --       *
  --      / \
  --     *   *
  --         |
  --         *