Mercurial > hg > Members > kono > Proof > ZF-in-agda
view src/bijection.agda @ 1314:8cd195679686
...
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Sat, 10 Jun 2023 12:37:13 +0900 |
parents | b8489dcae236 |
children | 08cd04cc33fe |
line wrap: on
line source
{-# OPTIONS --allow-unsolved-metas #-} module bijection where open import Level renaming ( zero to Zero ; suc to Suc ) open import Data.Nat open import Data.Maybe open import Data.List hiding ([_] ; sum ) open import Data.Nat.Properties open import Relation.Nullary open import Data.Empty open import Data.Unit hiding ( _≤_ ) open import Relation.Binary.Core hiding (_⇔_) open import Relation.Binary.Definitions open import Relation.Binary.PropositionalEquality open import logic open import nat -- record Bijection {n m : Level} (R : Set n) (S : Set m) : Set (n Level.⊔ m) where -- field -- fun← : S → R -- fun→ : R → S -- fiso← : (x : R) → fun← ( fun→ x ) ≡ x -- fiso→ : (x : S ) → fun→ ( fun← x ) ≡ x -- -- injection : {n m : Level} (R : Set n) (S : Set m) (f : R → S ) → Set (n Level.⊔ m) -- injection R S f = (x y : R) → f x ≡ f y → x ≡ y open Bijection bi-trans : {n m l : Level} (R : Set n) (S : Set m) (T : Set l) → Bijection R S → Bijection S T → Bijection R T bi-trans R S T rs st = record { fun← = λ x → fun← rs ( fun← st x ) ; fun→ = λ x → fun→ st ( fun→ rs x ) ; fiso← = λ x → trans (cong (λ k → fun← rs k) (fiso← st (fun→ rs x))) ( fiso← rs x) ; fiso→ = λ x → trans (cong (λ k → fun→ st k) (fiso→ rs (fun← st x))) ( fiso→ st x) } bid : {n : Level} (R : Set n) → Bijection R R bid {n} R = record { fun← = λ x → x ; fun→ = λ x → x ; fiso← = λ _ → refl ; fiso→ = λ _ → refl } bi-sym : {n m : Level} (R : Set n) (S : Set m) → Bijection R S → Bijection S R bi-sym R S eq = record { fun← = fun→ eq ; fun→ = fun← eq ; fiso← = fiso→ eq ; fiso→ = fiso← eq } open import Relation.Binary.Structures bijIsEquivalence : {n : Level } → IsEquivalence (Bijection {n} {n}) bijIsEquivalence = record { refl = λ {R} → bid R ; sym = λ {R} {S} → bi-sym R S ; trans = λ {R} {S} {T} → bi-trans R S T } -- ¬ A = A → ⊥ -- -- famous diagnostic function -- diag : {S : Set } (b : Bijection ( S → Bool ) S) → S → Bool diag b n = not (fun← b n n) diagonal : { S : Set } → ¬ Bijection ( S → Bool ) S diagonal {S} b = diagn1 (fun→ b (λ n → diag b n) ) refl where diagn1 : (n : S ) → ¬ (fun→ b (λ n → diag b n) ≡ n ) diagn1 n dn = ¬t=f (diag b n ) ( begin not (diag b n) ≡⟨⟩ not (not (fun← b n n)) ≡⟨ cong (λ k → not (k n) ) (sym (fiso← b _)) ⟩ not (fun← b (fun→ b (diag b)) n) ≡⟨ cong (λ k → not (fun← b k n) ) dn ⟩ not (fun← b n n) ≡⟨⟩ diag b n ∎ ) where open ≡-Reasoning b1 : (b : Bijection ( ℕ → Bool ) ℕ) → ℕ b1 b = fun→ b (diag b) b-iso : (b : Bijection ( ℕ → Bool ) ℕ) → fun← b (b1 b) ≡ (diag b) b-iso b = fiso← b _ -- -- ℕ <=> ℕ + 1 -- to1 : {n : Level} {R : Set n} → Bijection ℕ R → Bijection ℕ (⊤ ∨ R ) to1 {n} {R} b = record { fun← = to11 ; fun→ = to12 ; fiso← = to13 ; fiso→ = to14 } where to11 : ⊤ ∨ R → ℕ to11 (case1 tt) = 0 to11 (case2 x) = suc ( fun← b x ) to12 : ℕ → ⊤ ∨ R to12 zero = case1 tt to12 (suc n) = case2 ( fun→ b n) to13 : (x : ℕ) → to11 (to12 x) ≡ x to13 zero = refl to13 (suc x) = cong suc (fiso← b x) to14 : (x : ⊤ ∨ R) → to12 (to11 x) ≡ x to14 (case1 x) = refl to14 (case2 x) = cong case2 (fiso→ b x) open _∧_ record NN ( i : ℕ) (nxn→n : ℕ → ℕ → ℕ) : Set where field j k : ℕ k1 : nxn→n j k ≡ i nn-unique : {j0 k0 : ℕ } → nxn→n j0 k0 ≡ i → ⟪ j , k ⟫ ≡ ⟪ j0 , k0 ⟫ i≤0→i≡0 : {i : ℕ } → i ≤ 0 → i ≡ 0 i≤0→i≡0 {0} z≤n = refl nxn : Bijection ℕ (ℕ ∧ ℕ) nxn = record { fun← = λ p → nxn→n (proj1 p) (proj2 p) ; fun→ = n→nxn ; fiso← = λ i → NN.k1 (nn i) ; fiso→ = λ x → nn-id (proj1 x) (proj2 x) } where nxn→n : ℕ → ℕ → ℕ nxn→n zero zero = zero nxn→n zero (suc j) = j + suc (nxn→n zero j) nxn→n (suc i) zero = suc i + suc (nxn→n i zero) nxn→n (suc i) (suc j) = suc i + suc j + suc (nxn→n i (suc j)) nn : ( i : ℕ) → NN i nxn→n n→nxn : ℕ → ℕ ∧ ℕ n→nxn n = ⟪ NN.j (nn n) , NN.k (nn n) ⟫ k0 : {i : ℕ } → n→nxn i ≡ ⟪ NN.j (nn i) , NN.k (nn i) ⟫ k0 {i} = refl nxn→n0 : { j k : ℕ } → nxn→n j k ≡ 0 → ( j ≡ 0 ) ∧ ( k ≡ 0 ) nxn→n0 {zero} {zero} eq = ⟪ refl , refl ⟫ nxn→n0 {zero} {(suc k)} eq = ⊥-elim ( nat-≡< (sym eq) (subst (λ k → 0 < k) (+-comm _ k) (s≤s z≤n))) nxn→n0 {(suc j)} {zero} eq = ⊥-elim ( nat-≡< (sym eq) (s≤s z≤n) ) nxn→n0 {(suc j)} {(suc k)} eq = ⊥-elim ( nat-≡< (sym eq) (s≤s z≤n) ) nid20 : (i : ℕ) → i + (nxn→n 0 i) ≡ nxn→n i 0 nid20 zero = refl -- suc (i + (i + suc (nxn→n 0 i))) ≡ suc (i + suc (nxn→n i 0)) nid20 (suc i) = begin suc (i + (i + suc (nxn→n 0 i))) ≡⟨ cong (λ k → suc (i + k)) (sym (+-assoc i 1 (nxn→n 0 i))) ⟩ suc (i + ((i + 1) + nxn→n 0 i)) ≡⟨ cong (λ k → suc (i + (k + nxn→n 0 i))) (+-comm i 1) ⟩ suc (i + suc (i + nxn→n 0 i)) ≡⟨ cong ( λ k → suc (i + suc k)) (nid20 i) ⟩ suc (i + suc (nxn→n i 0)) ∎ where open ≡-Reasoning nid4 : {i j : ℕ} → i + 1 + j ≡ i + suc j nid4 {zero} {j} = refl nid4 {suc i} {j} = cong suc (nid4 {i} {j} ) nid5 : {i j k : ℕ} → i + suc (suc j) + suc k ≡ i + suc j + suc (suc k ) nid5 {zero} {j} {k} = begin suc (suc j) + suc k ≡⟨ +-assoc 1 (suc j) _ ⟩ 1 + (suc j + suc k) ≡⟨ +-comm 1 _ ⟩ (suc j + suc k) + 1 ≡⟨ +-assoc (suc j) (suc k) _ ⟩ suc j + (suc k + 1) ≡⟨ cong (λ k → suc j + k ) (+-comm (suc k) 1) ⟩ suc j + suc (suc k) ∎ where open ≡-Reasoning nid5 {suc i} {j} {k} = cong suc (nid5 {i} {j} {k} ) -- increment in the same stage nid2 : (i j : ℕ) → suc (nxn→n i (suc j)) ≡ nxn→n (suc i) j nid2 zero zero = refl nid2 zero (suc j) = refl nid2 (suc i) zero = begin suc (nxn→n (suc i) 1) ≡⟨ refl ⟩ suc (suc (i + 1 + suc (nxn→n i 1))) ≡⟨ cong (λ k → suc (suc k)) nid4 ⟩ suc (suc (i + suc (suc (nxn→n i 1)))) ≡⟨ cong (λ k → suc (suc (i + suc (suc k)))) (nid3 i) ⟩ suc (suc (i + suc (suc (i + suc (nxn→n i 0))))) ≡⟨ refl ⟩ nxn→n (suc (suc i)) zero ∎ where open ≡-Reasoning nid3 : (i : ℕ) → nxn→n i 1 ≡ i + suc (nxn→n i 0) nid3 zero = refl nid3 (suc i) = begin suc (i + 1 + suc (nxn→n i 1)) ≡⟨ cong suc nid4 ⟩ suc (i + suc (suc (nxn→n i 1))) ≡⟨ cong (λ k → suc (i + suc (suc k))) (nid3 i) ⟩ suc (i + suc (suc (i + suc (nxn→n i 0)))) ∎ nid2 (suc i) (suc j) = begin suc (nxn→n (suc i) (suc (suc j))) ≡⟨ refl ⟩ suc (suc (i + suc (suc j) + suc (nxn→n i (suc (suc j))))) ≡⟨ cong (λ k → suc (suc (i + suc (suc j) + k))) (nid2 i (suc j)) ⟩ suc (suc (i + suc (suc j) + suc (i + suc j + suc (nxn→n i (suc j))))) ≡⟨ cong ( λ k → suc (suc k)) nid5 ⟩ suc (suc (i + suc j + suc (suc (i + suc j + suc (nxn→n i (suc j)))))) ≡⟨ refl ⟩ nxn→n (suc (suc i)) (suc j) ∎ where open ≡-Reasoning -- increment the stage nid00 : (i : ℕ) → suc (nxn→n i 0) ≡ nxn→n 0 (suc i) nid00 zero = refl nid00 (suc i) = begin suc (suc (i + suc (nxn→n i 0))) ≡⟨ cong (λ k → suc (suc (i + k ))) (nid00 i) ⟩ suc (suc (i + (nxn→n 0 (suc i)))) ≡⟨ refl ⟩ suc (suc (i + (i + suc (nxn→n 0 i)))) ≡⟨ cong suc (sym ( +-assoc 1 i (i + suc (nxn→n 0 i)))) ⟩ suc ((1 + i) + (i + suc (nxn→n 0 i))) ≡⟨ cong (λ k → suc (k + (i + suc (nxn→n 0 i)))) (+-comm 1 i) ⟩ suc ((i + 1) + (i + suc (nxn→n 0 i))) ≡⟨ cong suc (+-assoc i 1 (i + suc (nxn→n 0 i))) ⟩ suc (i + suc (i + suc (nxn→n 0 i))) ∎ where open ≡-Reasoning ----- -- -- create the invariant NN for all n -- nn zero = record { j = 0 ; k = 0 ; k1 = refl ; nn-unique = λ {j0} {k0} eq → cong₂ (λ x y → ⟪ x , y ⟫) (sym (proj1 (nxn→n0 eq))) (sym (proj2 (nxn→n0 {j0} {k0} eq))) } nn (suc i) with NN.k (nn i) | inspect NN.k (nn i) ... | zero | record { eq = eq } = record { k = suc (sum ) ; j = 0 ; k1 = nn02 ; nn-unique = nn04 } where --- --- increment the stage --- sum = NN.j (nn i) + NN.k (nn i) stage = minus i (NN.j (nn i)) j = NN.j (nn i) NNnn : NN.j (nn i) + NN.k (nn i) ≡ sum NNnn = sym refl nn02 : nxn→n 0 (suc sum) ≡ suc i nn02 = begin sum + suc (nxn→n 0 sum) ≡⟨ sym (+-assoc sum 1 (nxn→n 0 sum)) ⟩ (sum + 1) + nxn→n 0 sum ≡⟨ cong (λ k → k + nxn→n 0 sum ) (+-comm sum 1 )⟩ suc (sum + nxn→n 0 sum) ≡⟨ cong suc (nid20 sum ) ⟩ suc (nxn→n sum 0) ≡⟨ cong (λ k → suc (nxn→n k 0 )) (sym (NNnn )) ⟩ suc (nxn→n (NN.j (nn i) + (NN.k (nn i)) ) 0) ≡⟨ cong₂ (λ j k → suc (nxn→n (NN.j (nn i) + j) k )) eq (sym eq) ⟩ suc (nxn→n (NN.j (nn i) + 0 ) (NN.k (nn i))) ≡⟨ cong (λ k → suc ( nxn→n k (NN.k (nn i)))) (+-comm (NN.j (nn i)) 0) ⟩ suc (nxn→n (NN.j (nn i)) (NN.k (nn i))) ≡⟨ cong suc (NN.k1 (nn i) ) ⟩ suc i ∎ where open ≡-Reasoning nn04 : {j0 k0 : ℕ} → nxn→n j0 k0 ≡ suc i → ⟪ 0 , suc (sum ) ⟫ ≡ ⟪ j0 , k0 ⟫ nn04 {zero} {suc k0} eq1 = cong (λ k → ⟪ 0 , k ⟫ ) (cong suc (sym nn08)) where -- eq : nxn→n zero (suc k0) ≡ suc i -- nn07 : nxn→n k0 0 ≡ i nn07 = cong pred ( begin suc ( nxn→n k0 0 ) ≡⟨ nid00 k0 ⟩ nxn→n 0 (suc k0 ) ≡⟨ eq1 ⟩ suc i ∎ ) where open ≡-Reasoning nn08 : k0 ≡ sum nn08 = begin k0 ≡⟨ cong proj1 (sym (NN.nn-unique (nn i) nn07)) ⟩ NN.j (nn i) ≡⟨ +-comm 0 _ ⟩ NN.j (nn i) + 0 ≡⟨ cong (λ k → NN.j (nn i) + k) (sym eq) ⟩ NN.j (nn i) + NN.k (nn i) ≡⟨ NNnn ⟩ sum ∎ where open ≡-Reasoning nn04 {suc j0} {k0} eq1 = ⊥-elim ( nat-≡< (cong proj2 (nn06 nn05)) (subst (λ k → k < suc k0) (sym eq) (s≤s z≤n))) where nn05 : nxn→n j0 (suc k0) ≡ i nn05 = begin nxn→n j0 (suc k0) ≡⟨ cong pred ( begin suc (nxn→n j0 (suc k0)) ≡⟨ nid2 j0 k0 ⟩ nxn→n (suc j0) k0 ≡⟨ eq1 ⟩ suc i ∎ ) ⟩ i ∎ where open ≡-Reasoning nn06 : nxn→n j0 (suc k0) ≡ i → ⟪ NN.j (nn i) , NN.k (nn i) ⟫ ≡ ⟪ j0 , suc k0 ⟫ nn06 = NN.nn-unique (nn i) ... | suc k | record {eq = eq} = record { k = k ; j = suc (NN.j (nn i)) ; k1 = nn11 ; nn-unique = nn13 } where --- --- increment in a stage --- sum = NN.j (nn i) + NN.k (nn i) stage = minus i (NN.j (nn i)) j = NN.j (nn i) NNnn : NN.j (nn i) + NN.k (nn i) ≡ sum NNnn = sym refl nn10 : suc (NN.j (nn i)) + k ≡ sum nn10 = begin suc (NN.j (nn i)) + k ≡⟨ cong (λ x → x + k) (+-comm 1 _) ⟩ (NN.j (nn i) + 1) + k ≡⟨ +-assoc (NN.j (nn i)) 1 k ⟩ NN.j (nn i) + suc k ≡⟨ cong (λ k → NN.j (nn i) + k) (sym eq) ⟩ NN.j (nn i) + NN.k (nn i) ≡⟨ NNnn ⟩ sum ∎ where open ≡-Reasoning nn11 : nxn→n (suc (NN.j (nn i))) k ≡ suc i -- nxn→n ( NN.j (nn i)) (NN.k (nn i) ≡ i nn11 = begin nxn→n (suc (NN.j (nn i))) k ≡⟨ sym (nid2 (NN.j (nn i)) k) ⟩ suc (nxn→n (NN.j (nn i)) (suc k)) ≡⟨ cong (λ k → suc (nxn→n (NN.j (nn i)) k)) (sym eq) ⟩ suc (nxn→n ( NN.j (nn i)) (NN.k (nn i))) ≡⟨ cong suc (NN.k1 (nn i)) ⟩ suc i ∎ where open ≡-Reasoning nn18 : zero < NN.k (nn i) nn18 = subst (λ k → 0 < k ) ( begin suc k ≡⟨ sym eq ⟩ NN.k (nn i) ∎ ) (s≤s z≤n ) where open ≡-Reasoning nn13 : {j0 k0 : ℕ} → nxn→n j0 k0 ≡ suc i → ⟪ suc (NN.j (nn i)) , k ⟫ ≡ ⟪ j0 , k0 ⟫ nn13 {zero} {suc k0} eq1 = ⊥-elim ( nat-≡< (sym (cong proj2 nn17)) nn18 ) where -- (nxn→n zero (suc k0)) ≡ suc i nn16 : nxn→n k0 zero ≡ i nn16 = cong pred ( subst (λ k → k ≡ suc i) (sym ( nid00 k0 )) eq1 ) nn17 : ⟪ NN.j (nn i) , NN.k (nn i) ⟫ ≡ ⟪ k0 , zero ⟫ nn17 = NN.nn-unique (nn i) nn16 nn13 {suc j0} {k0} eq1 = begin ⟪ suc (NN.j (nn i)) , pred (suc k) ⟫ ≡⟨ cong (λ k → ⟪ suc (NN.j (nn i)) , pred k ⟫ ) (sym eq) ⟩ ⟪ suc (NN.j (nn i)) , pred (NN.k (nn i)) ⟫ ≡⟨ cong (λ k → ⟪ suc (proj1 k) , pred (proj2 k) ⟫) ( begin ⟪ NN.j (nn i) , NN.k (nn i) ⟫ ≡⟨ nn15 ⟩ ⟪ j0 , suc k0 ⟫ ∎ ) ⟩ ⟪ suc j0 , k0 ⟫ ∎ where -- nxn→n (suc j0) k0 ≡ suc i open ≡-Reasoning nn14 : nxn→n j0 (suc k0) ≡ i nn14 = cong pred ( subst (λ k → k ≡ suc i) (sym ( nid2 j0 k0 )) eq1 ) nn15 : ⟪ NN.j (nn i) , NN.k (nn i) ⟫ ≡ ⟪ j0 , suc k0 ⟫ nn15 = NN.nn-unique (nn i) nn14 nn-id : (j k : ℕ) → n→nxn (nxn→n j k) ≡ ⟪ j , k ⟫ nn-id j k = begin n→nxn (nxn→n j k) ≡⟨ refl ⟩ ⟪ NN.j (nn (nxn→n j k)) , NN.k (nn (nxn→n j k)) ⟫ ≡⟨ NN.nn-unique (nn (nxn→n j k)) refl ⟩ ⟪ j , k ⟫ ∎ where open ≡-Reasoning -- [] 0 -- 0 → 1 -- 1 → 2 -- 01 → 3 -- 11 → 4 -- ... -- -- binary invariant -- record LB (n : ℕ) (lton : List Bool → ℕ ) : Set where field nlist : List Bool isBin : lton nlist ≡ n isUnique : (x : List Bool) → lton x ≡ n → nlist ≡ x lb+1 : List Bool → List Bool lb+1 [] = false ∷ [] lb+1 (false ∷ t) = true ∷ t lb+1 (true ∷ t) = false ∷ lb+1 t lb-1 : List Bool → List Bool lb-1 [] = [] lb-1 (true ∷ t) = false ∷ t lb-1 (false ∷ t) with lb-1 t ... | [] = true ∷ [] ... | x ∷ t1 = true ∷ x ∷ t1 LBℕ : Bijection ℕ ( List Bool ) LBℕ = record { fun← = λ x → lton x ; fun→ = λ n → LB.nlist (lb n) ; fiso← = λ n → LB.isBin (lb n) ; fiso→ = λ x → LB.isUnique (lb (lton x)) x refl } where lton1 : List Bool → ℕ lton1 [] = 1 lton1 (true ∷ t) = suc (lton1 t + lton1 t) lton1 (false ∷ t) = lton1 t + lton1 t lton : List Bool → ℕ lton x = pred (lton1 x) lton1>0 : (x : List Bool ) → 0 < lton1 x lton1>0 [] = a<sa lton1>0 (true ∷ x₁) = 0<s lton1>0 (false ∷ t) = ≤-trans (lton1>0 t) x≤x+y 2lton1>0 : (t : List Bool ) → 0 < lton1 t + lton1 t 2lton1>0 t = ≤-trans (lton1>0 t) x≤x+y lb=3 : {x y : ℕ} → 0 < x → 0 < y → 1 ≤ pred (x + y) lb=3 {suc x} {suc y} (s≤s 0<x) (s≤s 0<y) = subst (λ k → 1 ≤ k ) (+-comm (suc y) _ ) (s≤s z≤n) lton-cons>0 : {x : Bool} {y : List Bool } → 0 < lton (x ∷ y) lton-cons>0 {true} {[]} = refl-≤s lton-cons>0 {true} {x ∷ y} = ≤-trans ( lb=3 (lton1>0 (x ∷ y)) (lton1>0 (x ∷ y))) px≤x lton-cons>0 {false} {[]} = refl-≤ lton-cons>0 {false} {x ∷ y} = lb=3 (lton1>0 (x ∷ y)) (lton1>0 (x ∷ y)) lb=0 : {x y : ℕ } → pred x < pred y → suc (x + x ∸ 1) < suc (y + y ∸ 1) lb=0 {0} {suc y} lt = s≤s (subst (λ k → 0 < k ) (+-comm (suc y) y ) 0<s) lb=0 {suc x} {suc y} lt = begin suc (suc ((suc x + suc x) ∸ 1)) ≡⟨ refl ⟩ suc (suc x) + suc x ≡⟨ refl ⟩ suc (suc x + suc x) ≤⟨ <-plus (s≤s lt) ⟩ suc y + suc x <⟨ <-plus-0 {suc x} {suc y} {suc y} (s≤s lt) ⟩ suc y + suc y ≡⟨ refl ⟩ suc ((suc y + suc y) ∸ 1) ∎ where open ≤-Reasoning lb=2 : {x y : ℕ } → pred x < pred y → suc (x + x ) < suc (y + y ) lb=2 {zero} {suc y} lt = s≤s 0<s lb=2 {suc x} {suc y} lt = s≤s (lb=0 {suc x} {suc y} lt) lb=1 : {x y : List Bool} {z : Bool} → lton (z ∷ x) ≡ lton (z ∷ y) → lton x ≡ lton y lb=1 {x} {y} {true} eq with <-cmp (lton x) (lton y) ... | tri< a ¬b ¬c = ⊥-elim (nat-≡< (cong suc eq) (lb=2 {lton1 x} {lton1 y} a)) ... | tri≈ ¬a b ¬c = b ... | tri> ¬a ¬b c = ⊥-elim (nat-≡< (cong suc (sym eq)) (lb=2 {lton1 y} {lton1 x} c)) lb=1 {x} {y} {false} eq with <-cmp (lton x) (lton y) ... | tri< a ¬b ¬c = ⊥-elim (nat-≡< (cong suc eq) (lb=0 {lton1 x} {lton1 y} a)) ... | tri≈ ¬a b ¬c = b ... | tri> ¬a ¬b c = ⊥-elim (nat-≡< (cong suc (sym eq)) (lb=0 {lton1 y} {lton1 x} c)) --- --- lton is unique in a head --- lb-tf : {x y : List Bool } → ¬ (lton (true ∷ x) ≡ lton (false ∷ y)) lb-tf {x} {y} eq with <-cmp (lton1 x) (lton1 y) ... | tri< a ¬b ¬c = ⊥-elim ( nat-≡< eq (lb=01 a)) where lb=01 : {x y : ℕ } → x < y → x + x < (y + y ∸ 1) lb=01 {x} {y} x<y = begin suc (x + x) ≡⟨ refl ⟩ suc x + x ≤⟨ ≤-plus x<y ⟩ y + x ≡⟨ refl ⟩ pred (suc y + x) ≡⟨ cong (λ k → pred ( k + x)) (+-comm 1 y) ⟩ pred ((y + 1) + x ) ≡⟨ cong pred (+-assoc y 1 x) ⟩ pred (y + suc x) ≤⟨ px≤py (≤-plus-0 {suc x} {y} {y} x<y) ⟩ (y + y) ∸ 1 ∎ where open ≤-Reasoning ... | tri> ¬a ¬b c = ⊥-elim ( nat-≡< (sym eq) (lb=02 c) ) where lb=02 : {x y : ℕ } → x < y → x + x ∸ 1 < y + y lb=02 {0} {y} lt = ≤-trans lt x≤x+y lb=02 {suc x} {y} lt = begin suc ( suc x + suc x ∸ 1 ) ≡⟨ refl ⟩ suc x + suc x ≤⟨ ≤-plus {suc x} (<to≤ lt) ⟩ y + suc x ≤⟨ ≤-plus-0 (<to≤ lt) ⟩ y + y ∎ where open ≤-Reasoning ... | tri≈ ¬a b ¬c = ⊥-elim ( nat-≡< (sym eq) ( begin suc (lton1 y + lton1 y ∸ 1) ≡⟨ sucprd ( 2lton1>0 y) ⟩ lton1 y + lton1 y ≡⟨ cong (λ k → k + k ) (sym b) ⟩ lton1 x + lton1 x ∎ )) where open ≤-Reasoning --- --- lton injection --- lb=b : (x y : List Bool) → lton x ≡ lton y → x ≡ y lb=b [] [] eq = refl lb=b [] (x ∷ y) eq = ⊥-elim ( nat-≡< eq (lton-cons>0 {x} {y} )) lb=b (x ∷ y) [] eq = ⊥-elim ( nat-≡< (sym eq) (lton-cons>0 {x} {y} )) lb=b (true ∷ x) (false ∷ y) eq = ⊥-elim ( lb-tf {x} {y} eq ) lb=b (false ∷ x) (true ∷ y) eq = ⊥-elim ( lb-tf {y} {x} (sym eq) ) lb=b (true ∷ x) (true ∷ y) eq = cong (λ k → true ∷ k ) (lb=b x y (lb=1 {x} {y} {true} eq)) lb=b (false ∷ x) (false ∷ y) eq = cong (λ k → false ∷ k ) (lb=b x y (lb=1 {x} {y} {false} eq)) lb : (n : ℕ) → LB n lton lb zero = record { nlist = [] ; isBin = refl ; isUnique = lb05 } where lb05 : (x : List Bool) → lton x ≡ zero → [] ≡ x lb05 x eq = lb=b [] x (sym eq) lb (suc n) with LB.nlist (lb n) | inspect LB.nlist (lb n) ... | [] | record { eq = eq } = record { nlist = false ∷ [] ; isUnique = lb06 ; isBin = lb10 } where open ≡-Reasoning lb10 : lton1 (false ∷ []) ∸ 1 ≡ suc n lb10 = begin lton (false ∷ []) ≡⟨ refl ⟩ suc 0 ≡⟨ refl ⟩ suc (lton []) ≡⟨ cong (λ k → suc (lton k)) (sym eq) ⟩ suc (lton (LB.nlist (lb n))) ≡⟨ cong suc (LB.isBin (lb n) ) ⟩ suc n ∎ lb06 : (x : List Bool) → pred (lton1 x ) ≡ suc n → false ∷ [] ≡ x lb06 x eq1 = lb=b (false ∷ []) x (trans lb10 (sym eq1)) -- lton (false ∷ []) ≡ lton x ... | false ∷ t | record { eq = eq } = record { nlist = true ∷ t ; isBin = lb01 ; isUnique = lb09 } where lb01 : lton (true ∷ t) ≡ suc n lb01 = begin lton (true ∷ t) ≡⟨ refl ⟩ lton1 t + lton1 t ≡⟨ sym ( sucprd (2lton1>0 t) ) ⟩ suc (pred (lton1 t + lton1 t )) ≡⟨ refl ⟩ suc (lton (false ∷ t)) ≡⟨ cong (λ k → suc (lton k )) (sym eq) ⟩ suc (lton (LB.nlist (lb n))) ≡⟨ cong suc (LB.isBin (lb n)) ⟩ suc n ∎ where open ≡-Reasoning lb09 : (x : List Bool) → lton1 x ∸ 1 ≡ suc n → true ∷ t ≡ x lb09 x eq1 = lb=b (true ∷ t) x (trans lb01 (sym eq1) ) -- lton (true ∷ t) ≡ lton x ... | true ∷ t | record { eq = eq } = record { nlist = lb+1 (true ∷ t) ; isBin = lb02 (true ∷ t) lb03 ; isUnique = lb07 } where lb03 : lton (true ∷ t) ≡ n lb03 = begin lton (true ∷ t) ≡⟨ cong (λ k → lton k ) (sym eq ) ⟩ lton (LB.nlist (lb n)) ≡⟨ LB.isBin (lb n) ⟩ n ∎ where open ≡-Reasoning add11 : (x1 : ℕ ) → suc x1 + suc x1 ≡ suc (suc (x1 + x1)) add11 zero = refl add11 (suc x) = cong (λ k → suc (suc k)) (trans (+-comm x _) (cong suc (+-comm _ x))) lb04 : (t : List Bool) → suc (lton1 t) ≡ lton1 (lb+1 t) lb04 [] = refl lb04 (false ∷ t) = refl lb04 (true ∷ []) = refl lb04 (true ∷ t0 @ (_ ∷ _)) = begin suc (suc (lton1 t0 + lton1 t0)) ≡⟨ sym (add11 (lton1 t0)) ⟩ suc (lton1 t0) + suc (lton1 t0) ≡⟨ cong (λ k → k + k ) (lb04 t0 ) ⟩ lton1 (lb+1 t0) + lton1 (lb+1 t0) ∎ where open ≡-Reasoning lb02 : (t : List Bool) → lton t ≡ n → lton (lb+1 t) ≡ suc n lb02 [] refl = refl lb02 (t @ (_ ∷ _)) eq1 = begin lton (lb+1 t) ≡⟨ refl ⟩ pred (lton1 (lb+1 t)) ≡⟨ cong pred (sym (lb04 t)) ⟩ pred (suc (lton1 t)) ≡⟨ sym (sucprd (lton1>0 t)) ⟩ suc (pred (lton1 t)) ≡⟨ refl ⟩ suc (lton t) ≡⟨ cong suc eq1 ⟩ suc n ∎ where open ≡-Reasoning lb07 : (x : List Bool) → pred (lton1 x ) ≡ suc n → lb+1 (true ∷ t) ≡ x lb07 x eq1 = lb=b (lb+1 (true ∷ t)) x (trans ( lb02 (true ∷ t) lb03 ) (sym eq1)) -- Bernstein is non constructive, so we cannot use this without some assumption -- but in case of ℕ, we can construct it directly. record InjectiveF (A B : Set) : Set where field f : A → B inject : {x y : A} → f x ≡ f y → x ≡ y record Is (A C : Set) (f : A → C) (c : C) : Set where field a : A fa=c : f a ≡ c Countable-Bernstein : (A B C : Set) → Bijection A ℕ → Bijection C ℕ → (fi : InjectiveF A B ) → (gi : InjectiveF B C ) → (is-A : (c : C ) → Dec (Is A C (λ x → (InjectiveF.f gi (InjectiveF.f fi x))) c )) → (is-B : (c : C ) → Dec (Is B C (InjectiveF.f gi) c) ) → Bijection B ℕ Countable-Bernstein A B C an cn fi gi is-A is-B = record { fun→ = λ x → bton x ; fun← = λ n → ntob n ; fiso→ = λ n → ? ; fiso← = λ x → ? } where -- -- an f g cn -- ℕ → A → B → C → ℕ -- open Bijection f = InjectiveF.f fi g = InjectiveF.f gi -- -- count number of valid A and B in C -- the count of B is the numner of B in Bijection B ℕ -- if we have a , number a of A is larger than the numner of B C, so we have the inverse -- count-B : ℕ → ℕ count-B zero with is-B (fun← cn zero) ... | yes isb = 1 ... | no nisb = 0 count-B (suc n) with is-B (fun← cn (suc n)) ... | yes isb = suc (count-B n) ... | no nisb = count-B n bton : B → ℕ bton b = count-B (fun→ cn (g b)) count-A : ℕ → ℕ count-A zero with is-A (fun← cn zero) ... | yes isb = 1 ... | no nisb = 0 count-A (suc n) with is-A (fun← cn (suc n)) ... | yes isb = suc (count-A n) ... | no nisb = count-A n count-A-≤cong : {i j : ℕ} → i ≤ j → count-A i ≤ count-A j count-A-≤cong {i} {j} i≤j with ≤-∨ i≤j ... | case1 refl = ≤-refl ... | case2 i<j = lem00 _ _ i<j where lem00 : (i j : ℕ) → i < j → count-A i ≤ count-A j lem00 i (suc j) (s≤s i<j) = ≤-trans (count-A-≤cong i<j) (lem01 j) where lem01 : (j : ℕ) → count-A j ≤ count-A (suc j) lem01 zero with is-A (fun← cn (suc zero)) ... | yes isb = refl-≤s ... | no nisb = ≤-refl lem01 (suc n) with is-A (fun← cn (suc (suc n))) ... | yes isb = refl-≤s ... | no nisb = ≤-refl count-A<i : (i : ℕ) → count-A i ≤ suc i count-A<i zero with is-A (fun← cn zero) | inspect ( count-A ) zero ... | yes isa | record { eq = eq1 } = ≤-refl ... | no nisa | record { eq = eq1 } = refl-≤s count-A<i (suc i) with is-A (fun← cn (suc i)) | inspect ( count-A ) (suc i) ... | yes isa | record { eq = eq1 } = s≤s ( count-A<i i ) ... | no nisa | record { eq = eq1 } = ≤-trans (count-A<i i ) refl-≤s full-a : (i : ℕ) → i < count-A i → Is A C (λ x → g (f x)) (fun← cn i) full-a zero i<ci with is-A (fun← cn zero) | inspect ( count-A ) zero ... | yes isa | record { eq = eq1 } = isa ... | no nisa | record { eq = eq1 } = ⊥-elim ( nat-≡< refl i<ci ) full-a (suc i) i<ci with is-A (fun← cn (suc i)) | inspect ( count-A ) (suc i) ... | yes isa | record { eq = eq1 } = isa ... | no nisa | record { eq = eq1 } = ⊥-elim ( nat-≤> (≤-trans lem36 lem39) a<sa ) where lem36 : suc (suc i) ≤ count-A i lem36 = i<ci lem39 : count-A i ≤ suc i lem39 = count-A<i i ¬isA∧isB : (y : C ) → Is A C (λ x → g ( f x)) y → ¬ Is B C g y → ⊥ ¬isA∧isB y isa nisb = ⊥-elim ( nisb record { a = f (Is.a isa) ; fa=c = lem } ) where lem : g (f (Is.a isa)) ≡ y lem = begin g (f (Is.a isa)) ≡⟨ Is.fa=c isa ⟩ y ∎ where open ≡-Reasoning ca≤cb0 : (n : ℕ) → count-A n ≤ count-B n ca≤cb0 zero with is-A (fun← cn zero) | is-B (fun← cn zero) ... | yes isA | yes isB = ≤-refl ... | yes isA | no nisB = ⊥-elim ( ¬isA∧isB _ isA nisB ) ... | no nisA | yes isB = px≤x ... | no nisA | no nisB = ≤-refl ca≤cb0 (suc n) with is-A (fun← cn (suc n)) | is-B (fun← cn (suc n)) ... | yes isA | yes isB = s≤s (ca≤cb0 n) ... | yes isA | no nisB = ⊥-elim ( ¬isA∧isB _ isA nisB ) ... | no nisA | yes isB = ≤-trans (ca≤cb0 n) px≤x ... | no nisA | no nisB = ca≤cb0 n record maxAC (n : ℕ) : Set where field ac : ℕ n<ca : n < count-A ac record maxACN (n : ℕ) : Set where field acn : ℕ cn<acn : (i : ℕ) → i ≤ n → fun→ cn (g (f (fun← an i))) ≤ acn lem02 : (n : ℕ) → maxAC n lem02 n = lem03 n where maxac : (i : ℕ) → maxACN i maxac zero = record { acn = fun→ cn (g (f (fun← an zero))) ; cn<acn = ? } maxac (suc i) with <-cmp (fun→ cn (g (f (fun← an (suc i))))) (maxACN.acn (maxac i)) ... | tri< a ¬b ¬c = record { acn = maxACN.acn (maxac i) ; cn<acn = ? } ... | tri≈ ¬a b ¬c = record { acn = maxACN.acn (maxac i) ; cn<acn = ? } ... | tri> ¬a ¬b c = record { acn = fun→ cn (g (f (fun← an (suc i)))) ; cn<acn = ? } lem03 : (i : ℕ) → maxAC i lem03 i = lem10 i where lem11 : (i : ℕ) → i ≤ n → fun→ cn (g (f (fun← an i))) ≤ maxACN.acn (maxac n) lem11 i i≤n = maxACN.cn<acn (maxac n) i i≤n lem10 : (j : ℕ) → maxAC j lem10 zero = lem12 _ refl where lem12 : (i : ℕ) → i ≡ fun→ cn (g (f (fun← an zero))) → maxAC zero lem12 zero i=z with is-A (fun← cn zero) | inspect ( count-A ) zero ... | yes isa | record { eq = eq1 } = record { ac = zero ; n<ca = subst (λ k → 0 < k) (sym eq1) (s≤s z≤n) } ... | no nisa | record { eq = eq1 } = ⊥-elim ( nisa record { a = fun← an 0 ; fa=c = trans (sym (fiso← cn _)) (sym (cong (fun← cn) i=z)) } ) lem12 (suc i) i=z with is-A (fun← cn (suc i)) | inspect ( count-A ) (suc i) ... | yes isa | record { eq = eq1 } = record { ac = suc i ; n<ca = subst (λ k → 0 < k) (sym eq1) 0<s } ... | no nisa | record { eq = eq1 } = ⊥-elim ( nisa record { a = fun← an zero ; fa=c = trans (sym (fiso← cn _)) (sym (cong (fun← cn) i=z)) } ) lem10 (suc j) with <-cmp (suc j) (count-A (maxAC.ac (lem10 j))) ... | tri< a ¬b ¬c = record { ac = maxAC.ac (lem10 j) ; n<ca = a } -- if suc j < count-A (maxAC.ac lem14) , we can reuse lem10 j ... | tri> ¬a ¬b (s≤s c) = ⊥-elim ( nat-≤> c (maxAC.n<ca (lem10 j))) ... | tri≈ ¬a sj=ca ¬c = record { ac = fun→ cn (g (f (fun← an (suc j)))) ; n<ca = lem31 } where -- -- then suc j ≡ count-A (maxAC.ac (lem10 j)) -- it means count-A is full -- the new one must be above -- lem31 : suc j < count-A (fun→ cn (g (f (fun← an (suc j))))) lem31 with <∨≤ (suc j) (fun→ cn (g (f (fun← an (suc j))))) ... | case1 lt = lem12 _ lt ≤-refl where lem13 : suc j < fun→ cn (g (f (fun← an (suc j)))) lem13 = lt -- suc j is current count of A -- it increase at fun→ cn (g (f (fun← an (suc j)))) -- otherwise ≤ lem12 : (i : ℕ) → suc j < i → i ≤ fun→ cn (g (f (fun← an (suc j)))) → suc j < count-A i lem12 (suc i) (s≤s sj<i) i≤fj with ≤-∨ sj<i ... | case1 eq = ? ... | case2 lt = ? where lem14 : suc j < count-A i lem14 = lem12 i lt (≤-trans refl-≤s i≤fj) ... | case2 le = ? where -- count-A<i : (i : ℕ) → count-A i ≤ suc i lem33 : (i : ℕ) → i ≡ fun→ cn (g (f (fun← an (suc j)))) → ¬ (i ≤ maxAC.ac (lem10 j)) lem33 zero i=f i≤m = ? lem33 (suc i) si=f= i≤m = ? lem34 : maxAC.ac (lem10 j) ≤ fun→ cn (g (f (fun← an (suc j)))) lem34 = ? lem32 : suc j ≤ count-A (fun→ cn (g (f (fun← an (suc j))))) lem32 with <∨≤ (count-A (fun→ cn (g (f (fun← an (suc j))))) ) (suc j) ... | case2 le = le ... | case1 lt = ? lem30 : maxAC.ac (lem10 j) < fun→ cn (g (f (fun← an (suc j)))) lem30 = ? lem20 : suc j ≡ count-A (maxAC.ac (lem10 j)) lem20 = sj=ca lem14 : maxAC j lem14 = lem10 j lem17 : j < count-A (maxAC.ac lem14) lem17 = maxAC.n<ca lem14 lem01 : (n i : ℕ) → n < count-B i → B lem01 zero zero lt with is-B (fun← cn zero) ... | yes isB = Is.a isB ... | no nisB = ⊥-elim (¬a≤a lt) lem01 zero (suc i) lt with is-B (fun← cn (suc i)) ... | yes isB = Is.a isB ... | no nisB = lem01 zero i lt lem01 (suc n) zero lt with is-B (fun← cn zero) ... | yes isB = Is.a isB ... | no nisB = ⊥-elim (nat-≤> lt 0<s ) lem01 (suc n) (suc i) lt with is-B (fun← cn (suc i)) ... | yes isB = Is.a isB ... | no nisB = lem01 (suc n) i lt ntob : (n : ℕ) → B ntob n = lem01 n (maxAC.ac (lem02 n)) (≤-trans (maxAC.n<ca (lem02 n)) (ca≤cb0 (maxAC.ac (lem02 n))) ) biso : (n : ℕ) → bton (ntob n) ≡ n biso n = ? -- lem03 _ (≤-trans (maxAC.n<ca (lem02 n )) ?) refl biso1 : (b : B) → ntob (bton b) ≡ b biso1 b = ? bi-∧ : {A B C D : Set} → Bijection A B → Bijection C D → Bijection (A ∧ C) (B ∧ D) bi-∧ {A} {B} {C} {D} ab cd = record { fun← = λ x → ⟪ fun← ab (proj1 x) , fun← cd (proj2 x) ⟫ ; fun→ = λ n → ⟪ fun→ ab (proj1 n) , fun→ cd (proj2 n) ⟫ ; fiso← = lem0 ; fiso→ = lem1 } where open Bijection lem0 : (x : A ∧ C) → ⟪ fun← ab (fun→ ab (proj1 x)) , fun← cd (fun→ cd (proj2 x)) ⟫ ≡ x lem0 ⟪ x , y ⟫ = cong₂ ⟪_,_⟫ (fiso← ab x) (fiso← cd y) lem1 : (x : B ∧ D) → ⟪ fun→ ab (fun← ab (proj1 x)) , fun→ cd (fun← cd (proj2 x)) ⟫ ≡ x lem1 ⟪ x , y ⟫ = cong₂ ⟪_,_⟫ (fiso→ ab x) (fiso→ cd y) LM1 : (A : Set ) → Bijection (List A ) ℕ → Bijection (List A ∧ List Bool) ℕ LM1 A Ln = bi-trans (List A ∧ List Bool) (ℕ ∧ ℕ) ℕ (bi-∧ Ln (bi-sym _ _ LBℕ) ) (bi-sym _ _ nxn) open import Data.List.Properties open import Data.Maybe.Properties LMℕ : (A : Set ) → Bijection (List A) ℕ → Bijection (List (Maybe A)) ℕ LMℕ A Ln = Countable-Bernstein (List A) (List (Maybe A)) (List A ∧ List Bool) Ln (LM1 A Ln) fi gi ? ? where f : List A → List (Maybe A) f [] = [] f (x ∷ t) = just x ∷ f t f-inject : {x y : List A} → f x ≡ f y → x ≡ y f-inject {[]} {[]} refl = refl f-inject {x ∷ xt} {y ∷ yt} eq = cong₂ (λ j k → j ∷ k ) (just-injective (∷-injectiveˡ eq)) (f-inject (∷-injectiveʳ eq) ) g : List (Maybe A) → List A ∧ List Bool g [] = ⟪ [] , [] ⟫ g (just h ∷ t) = ⟪ h ∷ proj1 (g t) , true ∷ proj2 (g t) ⟫ g (nothing ∷ t) = ⟪ proj1 (g t) , false ∷ proj2 (g t) ⟫ g⁻¹ : List A ∧ List Bool → List (Maybe A) g⁻¹ ⟪ [] , [] ⟫ = [] g⁻¹ ⟪ x ∷ xt , [] ⟫ = just x ∷ g⁻¹ ⟪ xt , [] ⟫ g⁻¹ ⟪ [] , true ∷ y ⟫ = [] g⁻¹ ⟪ x ∷ xt , true ∷ yt ⟫ = just x ∷ g⁻¹ ⟪ xt , yt ⟫ g⁻¹ ⟪ [] , false ∷ y ⟫ = nothing ∷ g⁻¹ ⟪ [] , y ⟫ g⁻¹ ⟪ x ∷ x₁ , false ∷ y ⟫ = nothing ∷ g⁻¹ ⟪ x ∷ x₁ , y ⟫ g-iso : {x : List (Maybe A)} → g⁻¹ (g x) ≡ x g-iso {[]} = refl g-iso {just x ∷ xt} = cong ( λ k → just x ∷ k) ( g-iso ) g-iso {nothing ∷ []} = refl g-iso {nothing ∷ just x ∷ xt} = cong (λ k → nothing ∷ k ) ( g-iso {_} ) g-iso {nothing ∷ nothing ∷ xt} with g-iso {nothing ∷ xt} ... | t = trans (lemma01 (proj1 (g xt)) (proj2 (g xt)) ) ( cong (λ k → nothing ∷ k ) t ) where lemma01 : (x : List A) (y : List Bool ) → g⁻¹ ⟪ x , false ∷ false ∷ y ⟫ ≡ nothing ∷ g⁻¹ ⟪ x , false ∷ y ⟫ lemma01 [] y = refl lemma01 (x ∷ x₁) y = refl g-inject : {x y : List (Maybe A)} → g x ≡ g y → x ≡ y g-inject {x} {y} eq = subst₂ (λ j k → j ≡ k ) g-iso g-iso (cong g⁻¹ eq ) fi : InjectiveF (List A) (List (Maybe A)) fi = record { f = f ; inject = f-inject } gi : InjectiveF (List (Maybe A)) (List A ∧ List Bool ) gi = record { f = g ; inject = g-inject } -- open import Data.Fin -- --- LBFin : {n : ℕ } → Bijection (List (Meybe (Fin n))) ( List (Fin (suc n))) -- --- LBFin : {n : ℕ } → Bijection ℕ ( List (Fin n)) --- LBFin = ? --