{-# OPTIONS --safe #-}
open import Multiset.Prelude
open import Multiset.Functor
open import Multiset.Limit.Chain
open import Multiset.Limit.TerminalChain
open import Multiset.ListQuotient.Base
open import Multiset.Omniscience using (LLPO)
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Function using (_∘_ ; _$_)
open import Cubical.Data.Bool hiding (_≤_)
open import Cubical.Data.Empty as Empty
open import Cubical.Data.List as List hiding ([_])
open import Cubical.Data.Nat.Base as ℕ hiding (_^_)
open import Cubical.Data.Nat.Order
open import Cubical.Data.Sigma as Sigma
open import Cubical.Data.Sum as Sum using (_⊎_ ; inl ; inr)
open import Cubical.Data.Unit as Unit using (Unit ; tt)
open import Cubical.Relation.Nullary using (Dec ; Discrete ; yes ; no ; ¬_)
open import Cubical.HITs.PropositionalTruncation as PT using (∥_∥₁ ; ∣_∣₁)
open import Cubical.HITs.PropositionalTruncation.Monad using (_>>=_ ; _>>_ ; return)
module Multiset.Axioms.Completeness {ℓ}
(C : Chain ℓ)
(discrete-chain : ∀ n → Discrete (C .Chain.Ob n))
(is-set-chain : ∀ n → isSet (C .Chain.Ob n))
where
open module C = Chain C
private
≤-suc-cases : ∀ k n → k ≤ suc n
→ (k ≤ n) ⊎ (k ≡ suc n)
≤-suc-cases zero n le = inl zero-≤
≤-suc-cases (suc k) zero le = inr (cong suc (≤0→≡0 (pred-≤-pred le)))
≤-suc-cases (suc k) (suc n) le with ≤-suc-cases k n (pred-≤-pred le)
... | inl p = inl (suc-≤-suc p)
... | inr p = inr (cong suc p)
dec-∈-chain : (n : ℕ) (x : Ob n) (ys : List (Ob n)) → Dec (x ∈ ys)
dec-∈-chain n x ys with dec∈ (discrete-chain n) x ys
... | yes (y , m , p) = yes (subst (λ z → z ∈ ys) (sym p) m)
... | no ¬p = no (λ m → ¬p (x , m , refl))
rep-π : ∀ n k → k ≤ n → Ob n → Ob k
rep-π zero k k≤n x = J (λ k _ → Ob k) x (sym (≤0→≡0 k≤n))
rep-π (suc n) k k≤n x with ≤-suc-cases k n k≤n
... | inl p = rep-π n k p (π n x)
... | inr p = J (λ k _ → Ob k) x (sym p)
_∣_ : Limit C → (n : ℕ) → Ob n
x ∣ n = x .Limit.elements n
infix 20 _∣_
private
limitPath : ∀ {x y : Limit C} → (∀ n → x ∣ n ≡ y ∣ n) → x ≡ y
limitPath = isSet→LimitPathExt C is-set-chain
rep-π-≤ : ∀ (x : Limit C) → (n k : ℕ) → (k≤n : k ≤ n) → rep-π n k k≤n (x ∣ n) ≡ x ∣ k
rep-π-≤ x zero k k≤n =
J (λ k eq → J (λ k _ → Ob k) (x ∣ 0) eq ≡ x ∣ k) (JRefl {x = 0} (λ k _ → Ob k) _) (sym (≤0→≡0 k≤n))
rep-π-≤ x (suc n) k k≤n with ≤-suc-cases k n k≤n
... | inl p = cong (rep-π n k p) (x .Limit.is-lim n) ∙ rep-π-≤ x n k p
... | inr p = J (λ k eq → J (λ k _ → Ob k) (x ∣ (suc n)) eq ≡ x ∣ k) (JRefl {x = suc n} (λ k _ → Ob k) _) (sym p)
cut-≤ : ∀ (x y : Limit C) {k n} → k ≤ n → (x ∣ n ≡ y ∣ n) → (x ∣ k ≡ y ∣ k)
cut-≤ x y k≤n p = sym (rep-π-≤ x _ _ k≤n) ∙ cong (rep-π _ _ k≤n) p ∙ rep-π-≤ y _ _ k≤n
_≈⟨_⟩_ : (x : Limit C) (n : ℕ) → (y : Limit C) → Type _
x ≈⟨ n ⟩ y = (x ∣ n) ≡ (y ∣ n)
_≈_ : (x y : Limit C) → Type _
x ≈ y = ∀ n → x ≈⟨ n ⟩ y
Complete : Type _
Complete = (x y₁ y₂ : Limit C) → (∀ n → (x ≈⟨ n ⟩ y₁) ⊎ (x ≈⟨ n ⟩ y₂)) → ∥ (x ≡ y₁) ⊎ (x ≡ y₂) ∥₁
_≺⟨_⟩_ : (x : Limit C) → (n : ℕ) → (ys : List (Limit C)) → Type _
x ≺⟨ n ⟩ ys = ∥ (x ∣ n) ∈ map (_∣ n) ys ∥₁
_≺_ : (x : Limit C) → (ys : List (Limit C)) → Type _
x ≺ ys = ∀ n → x ≺⟨ n ⟩ ys
Complete* : Type _
Complete* = (x : Limit C) → (ys : List (Limit C)) → x ≺ ys → ∥ x ∈ ys ∥₁
_∈?⟨_⟩_ : (x : Limit C) (n : ℕ) (ys : List (Limit C)) → Dec ((x ∣ n) ∈ (map (_∣ n) ys))
x ∈?⟨ n ⟩ ys = dec-∈-chain n (x ∣ n) (map (_∣ n) ys)
Complete*⇒Complete : Complete* → Complete
Complete*⇒Complete complete* x y₁ y₂ approx-≡ = goal where
lemma : x ≺ (y₁ ∷ y₂ ∷ [])
lemma n = do
return (Sum.rec here (there ∘ here) (approx-≡ n))
goal : ∥ (x ≡ y₁) ⊎ (x ≡ y₂) ∥₁
goal = do
here x≡y₂ ← complete* x (y₁ ∷ y₂ ∷ []) lemma
where there (here x≡y₂) → return $ inr x≡y₂
return $ inl x≡y₂
private
parity : (a : ℕ → Bool) → Bool → ℕ → Bool
parity a b zero = (a 0 and b) or (not (a 0) and (not b))
parity a b (suc n) =
if (a 0 and b) or (not (a 0) and (not b))
then false
else parity (a ∘ suc) (not b) n
parity-prop' : ∀ a b (n1 n2 : ℕ)
→ parity a b n1 ≡ true → parity a b n2 ≡ true
→ n1 ≡ n2
parity-prop' a b zero zero p q = refl
parity-prop' a b zero (suc n2) p q with a 0
parity-prop' a false zero (suc n2) p q | false = Empty.rec (false≢true q)
parity-prop' a true zero (suc n2) p q | false = Empty.rec (false≢true p)
parity-prop' a false zero (suc n2) p q | true = Empty.rec (false≢true p)
parity-prop' a true zero (suc n2) p q | true = Empty.rec (false≢true q)
parity-prop' a b (suc n1) zero p q with a 0
parity-prop' a false (suc n1) zero p q | false = Empty.rec (false≢true p)
parity-prop' a true (suc n1) zero p q | false = Empty.rec (false≢true q)
parity-prop' a false (suc n1) zero p q | true = Empty.rec (false≢true q)
parity-prop' a true (suc n1) zero p q | true = Empty.rec (false≢true p)
parity-prop' a b (suc n1) (suc n2) p q with a 0
parity-prop' a false (suc n1) (suc n2) p q | false = Empty.rec (false≢true p)
parity-prop' a true (suc n1) (suc n2) p q | false =
cong suc (parity-prop' (a ∘ suc) false n1 n2 p q)
parity-prop' a false (suc n1) (suc n2) p q | true =
cong suc (parity-prop' (a ∘ suc) true n1 n2 p q)
parity-prop' a true (suc n1) (suc n2) p q | true = Empty.rec (false≢true p)
parity-prop : ∀ a b → isProp (Σ[ n ∈ ℕ ] parity a b n ≡ true)
parity-prop a b (n1 , eq1) (n2 , eq2) =
Σ≡Prop (λ _ → isSetBool _ _) (parity-prop' a b n1 n2 eq1 eq2)
even-not-odd : ∀ n → isEvenT n → isOddT n → ⊥
even-not-odd (suc n) p q = even-not-odd n q p
isEven? : Bool → ℕ → Type
isEven? false n = isOddT n
isEven? true n = isEvenT n
decEven : ∀ n → isEvenT n ⊎ isOddT n
decEven zero = inl _
decEven (suc n) = Sum.rec inr inl (decEven n)
parity-even : (a : ℕ → Bool)
→ ∀ n → isEvenT n
→ parity a true n ≡ false → a n ≡ true
→ Σ[ k ∈ ℕ ] Σ[ b ∈ Bool ] isEven? b k × (k < n) × (a k ≡ b) × (parity a true k ≡ true)
parity-even' : (a : ℕ → Bool)
→ ∀ n → isOddT n
→ parity a false n ≡ false → a n ≡ true
→ Σ[ k ∈ ℕ ] Σ[ b ∈ Bool ] isEven? b k × (k < n) × (a k ≡ not b) × (parity a false k ≡ true)
parity-even a zero ev eqf eqt =
Empty.rec (true≢false (sym (cong (λ b → b and true or not b and false) eqt) ∙ eqf))
parity-even a (suc n) ev eqf eqt with dichotomyBool (a 0)
... | inl q = 0 , true , _ , suc-≤-suc zero-≤ , q , cong (λ b → b and true or not b and false) q
... | inr q with parity-even' (a ∘ suc) n ev (sym (cong (λ b → if b and true or not b and false then false else parity (a ∘ suc) false n) q) ∙ eqf) eqt
... | k , false , p , le , eq' , r = _ , _ , p , suc-≤-suc le , eq' , cong (λ b → if b and true or not b and false then false else parity (a ∘ suc) false k) q ∙ r
... | k , true , p , le , eq' , r = _ , _ , p , suc-≤-suc le , eq' , cong (λ b → if b and true or not b and false then false else parity (a ∘ suc) false k) q ∙ r
parity-even' a (suc n) ev eqf eqt with dichotomyBool (a 0)
... | inr q = 0 , true , _ , suc-≤-suc zero-≤ , q , cong (λ b → b and false or not b and true) q
... | inl q with parity-even (a ∘ suc) n ev (sym (cong (λ b → if b and false or not b and true then false else parity (a ∘ suc) true n) q) ∙ eqf) eqt
... | k , false , p , le , eq' , r = _ , _ , p , suc-≤-suc le , eq' , cong (λ b → if b and false or not b and true then false else parity (a ∘ suc) true k) q ∙ r
... | k , true , p , le , eq' , r = _ , _ , p , suc-≤-suc le , eq' , cong (λ b → if b and false or not b and true then false else parity (a ∘ suc) true k) q ∙ r
parity-odd : (a : ℕ → Bool)
→ ∀ n → isOddT n
→ parity a true n ≡ false → a n ≡ false
→ Σ[ k ∈ ℕ ] Σ[ b ∈ Bool ] isEven? b k × (k < n) × (a k ≡ b) × (parity a true k ≡ true)
parity-odd' : (a : ℕ → Bool)
→ ∀ n → isEvenT n
→ parity a false n ≡ false → a n ≡ false
→ Σ[ k ∈ ℕ ] Σ[ b ∈ Bool ] isEven? b k × (k < n) × (a k ≡ not b) × (parity a false k ≡ true)
parity-odd a (suc n) odd eqt eqf with dichotomyBool (a 0)
... | inl q = 0 , true , _ , suc-≤-suc zero-≤ , q , cong (λ b → b and true or not b and false) q
... | inr q with parity-odd' (a ∘ suc) n odd ((sym (cong (λ b → if b and true or not b and false then false else parity (a ∘ suc) false n) q) ∙ eqt)) eqf
... | k , false , p , le , eq' , r = _ , _ , p , suc-≤-suc le , eq' , cong (λ b → if b and true or not b and false then false else parity (a ∘ suc) false k) q ∙ r
... | k , true , p , le , eq' , r = _ , _ , p , suc-≤-suc le , eq' , cong (λ b → if b and true or not b and false then false else parity (a ∘ suc) false k) q ∙ r
parity-odd' a zero _ eqt eqf =
Empty.rec (true≢false (sym (cong (λ b → b and false or not b and true) eqf) ∙ eqt))
parity-odd' a (suc n) odd eqt eqf with dichotomyBool (a 0)
... | inr q = 0 , true , _ , suc-≤-suc zero-≤ , q , cong (λ b → b and false or not b and true) q
... | inl q with parity-odd (a ∘ suc) n odd ((sym (cong (λ b → if b and false or not b and true then false else parity (a ∘ suc) true n) q) ∙ eqt)) eqf
... | k , false , p , le , eq' , r = _ , _ , p , suc-≤-suc le , eq' , cong (λ b → if b and false or not b and true then false else parity (a ∘ suc) true k) q ∙ r
... | k , true , p , le , eq' , r = _ , _ , p , suc-≤-suc le , eq' , cong (λ b → if b and false or not b and true then false else parity (a ∘ suc) true k) q ∙ r
_≟⟨_⟩_ : (x : Limit C) → (n : ℕ) → (y : Limit C) → Dec (x ∣ n ≡ y ∣ n)
_≟⟨_⟩_ x n y = discrete-chain n (x ∣ n) (y ∣ n)
∈-≤-weaken : ∀ x ys k n → k ≤ n
→ (x ∣ n) ∈ (map (_∣ n) ys)
→ (x ∣ k) ∈ (map (_∣ k) ys)
∈-≤-weaken x ys k n k≤n xₙ∈ysₙ using (x* , (x*∈ys , x*≈x)) ← pre∈mapList xₙ∈ysₙ = abs x* x*∈ys x*≈x where
abs : (x* : Limit C) → x* ∈ ys → (x* ∣ n ≡ x ∣ n) → (x ∣ k) ∈ (map (_∣ k) ys)
abs x* x*∈ys x*≈x = subst (_∈ (map (_∣ k) ys)) (cut-≤ x* x k≤n x*≈x) (∈mapList x*∈ys)
∈-<-weaken : ∀ x ys k n → k < n
→ (x ∣ n) ∈ (map (_∣ n) ys)
→ (x ∣ k) ∈ (map (_∣ k) ys)
∈-<-weaken x ys k n k<n = ∈-≤-weaken x ys k n (<-weaken k<n)
llpo⇒complete* : LLPO → Complete*
llpo⇒complete* llpo x = goal where
goal : ∀ ys → x ≺ ys → ∥ x ∈ ys ∥₁
goal [] x≺[] = do
x₀∈[] ← x≺[] 0
Empty.rec (∉[] x₀∈[])
goal (y ∷ ys) x≺y∷ys = ∥x∈y∷ys∥₁ where
a : ℕ → Bool
a n with decEven n
... | inl _ = not $ Dec→Bool $ x ≟⟨ n ⟩ y
... | inr _ = Dec→Bool $ x ∈?⟨ n ⟩ ys
a-even : ∀ n → isEvenT n → ¬ (x ∣ n ≡ y ∣ n) → a n ≡ true
a-even n ev mn with decEven n
... | inr odd = Empty.rec (even-not-odd n ev odd)
... | inl ev' with discrete-chain n (x ∣ n) (y ∣ n)
... | yes q = Empty.rec (mn q)
... | no ¬q = refl
a-odd : ∀ n → isOddT n → ¬ ((x ∣ n) ∈ List.map (_∣ n) ys) → a n ≡ false
a-odd n odd mn with decEven n
... | inl ev = Empty.rec (even-not-odd n ev odd)
... | inr _ with dec-∈-chain n (x ∣ n) (List.map (_∣ n) ys)
... | yes p = Empty.rec (mn p)
... | no ¬p = refl
par : ℕ → Bool
par = parity a true
magic : ∥ ((n : ℕ) → isEvenT n → par n ≡ false) ⊎
((n : ℕ) → isOddT n → par n ≡ false) ∥₁
magic = llpo par (parity-prop _ true)
case-even : ((n : ℕ) → isEvenT n → par n ≡ false) → x ≡ y
case-even par-even = limitPath x≈y
where
module is-even {n} (even : isEvenT n) where
¬¬x≈y : ¬ ¬ x ≈⟨ n ⟩ y
¬¬x≈y ¬xₙ≡yₙ with (parity-even a n even (par-even n even) (a-even n even ¬xₙ≡yₙ))
... | (k , true , k-even , _ , _ , par≡true) = false≢true false≡true where
false≡true =
false ≡⟨ sym $ par-even k k-even ⟩
par k ≡⟨ par≡true ⟩
true ∎
... | (k , false , k-odd , k<n , c , _) with decEven k
... | inl k-even = Empty.rec (even-not-odd k k-even k-odd)
... | inr _ with x ∈?⟨ k ⟩ ys
... | yes xₖ∈ysₖ = true≢false c
... | no ¬xₖ∈ysₖ = PT.rec isProp⊥ (λ ()) bot where
bot : ∥ ⊥ ∥₁
bot = x≺y∷ys n >>= λ where
(here xₙ≡yₙ) → return $ ¬xₙ≡yₙ xₙ≡yₙ
(there xₙ∈ysₙ) → do
return $ ¬xₖ∈ysₖ (∈-<-weaken x ys k n k<n xₙ∈ysₙ)
x≈y : x ≈⟨ n ⟩ y
x≈y with (discrete-chain n (x ∣ n) (y ∣ n))
... | yes xₙ≡yₙ = xₙ≡yₙ
... | no ¬xₙ≡yₙ = Empty.rec (¬¬x≈y ¬xₙ≡yₙ)
x≈y : x ≈ y
x≈y n with decEven n
... | inl even = is-even.x≈y even
... | inr odd =
(x ∣ n) ≡⟨ sym $ x .Limit.is-lim n ⟩
π n (x ∣ suc n) ≡⟨ cong (π n) (is-even.x≈y {n = suc n} odd) ⟩
π n (y ∣ suc n) ≡⟨ y .Limit.is-lim n ⟩
y ∣ n ∎
case-odd : ((n : ℕ) → isOddT n → par n ≡ false) → ∥ x ∈ ys ∥₁
case-odd par-odd = goal ys x≺ys
where module _ where
¬¬xₙ∈ysₙ-odd : ∀ n → isOddT n → ¬ ¬ (x ∣ n) ∈ map (_∣ n) ys
¬¬xₙ∈ysₙ-odd n odd ¬xₙ∈ysₙ with parity-odd a n odd (par-odd n odd) (a-odd n odd ¬xₙ∈ysₙ)
... | (k , false , k-odd , k<n , c , par≡true) = false≢true $
false ≡⟨ sym $ par-odd k k-odd ⟩
par k ≡⟨ par≡true ⟩
true ∎
... | (k , true , k-even , k<n , c , _) with decEven k
... | inr k-odd = Empty.rec (even-not-odd k k-even k-odd)
... | inl _ with x ≟⟨ k ⟩ y
... | yes xₖ≡yₖ = false≢true c
... | no ¬xₖ≡yₖ = PT.rec isProp⊥ (λ ()) bot where
bot : ∥ ⊥ ∥₁
bot = x≺y∷ys n >>= λ where
(here xₙ≡yₙ) → return $ ¬xₖ≡yₖ $
x ∣ k ≡⟨ cut-≤ x y (<-weaken k<n) xₙ≡yₙ ⟩
y ∣ k ∎
(there xₙ∈ysₙ) → return $ Empty.rec $ ¬xₙ∈ysₙ $ xₙ∈ysₙ
x≺ys-odd : ∀ n → isOddT n → ∥ (x ∣ n) ∈ map (_∣ n) ys ∥₁
x≺ys-odd n odd with x ∈?⟨ n ⟩ ys
... | yes xₙ∈ysₙ = return xₙ∈ysₙ
... | no ¬xₙ∈ysₙ = Empty.rec (¬¬xₙ∈ysₙ-odd n odd ¬xₙ∈ysₙ)
x≺ys-even : ∀ n → isEvenT n → ∥ (x ∣ n) ∈ map (_∣ n) ys ∥₁
x≺ys-even n even = do
xₙ₊₁∈ysₙ₊₁ ← x≺ys-odd (suc n) even
return $ ∈-≤-weaken x ys n (suc n) (≤-sucℕ {n}) xₙ₊₁∈ysₙ₊₁
x≺ys : ∀ n → ∥ (x ∣ n) ∈ map (_∣ n) ys ∥₁
x≺ys n = Sum.rec (x≺ys-even n) (x≺ys-odd n) (decEven n)
∥x∈y∷ys∥₁ : ∥ x ∈ (y ∷ ys) ∥₁
∥x∈y∷ys∥₁ = magic >>= λ where
(inl even) → return $ here $ case-even even
(inr odd) → do
x∈ys ← case-odd odd
return $ there x∈ys