open import Level
open import Data.Bool hiding (_≤_ ; _<_ ; _≤?_)
open import Data.Bool.Properties using (¬-not ; not-¬)
open import Data.Nat
open import Data.Sum
open import Data.Unit
open import Data.Empty
open import Relation.Binary
open import Relation.Binary.Definitions
open import Relation.Binary.PropositionalEquality
open import Data.Product
open import Relation.Binary.Structures
open import Data.Fin hiding (_≤_ ; _≤?_)
open import Data.Vec hiding (restrict)
open import Data.Nat.Properties using (≤-refl ; ≤-trans ; ≤-<-trans ; n≤0⇒n≡0
; n≤1+n ; m≤n⇒m<n∨m≡n ; _≤?_ ; ≰⇒≥)
open import Data.Fin.Properties using (toℕ<n)
open import Relation.Nullary
open import Function hiding (_↔_)
open import Data.List hiding (lookup ; last)
open import Eser.Logic using (elimCaseLeft ; elimCaseRight)
open import Eser.Aux
open import Eser.EqRel.Definitions
module Eser.EqRel.Conversions where
FunToRel : NFFun → DecEquiv
FunToRel (f , nleq , nfix) =
(R , isequiv)
where
R : ℕ → ℕ → Bool
R n m = f n ≡ᵇ f m
R' : ℕ → ℕ → Set
R' = R ⊢_~_
isequiv : IsEquivalence R'
isequiv =
let
reflR : Reflexive R'
reflR {n} = numIsItself (f n)
in
let symR : Symmetric R'
symR {n} {m} R'nm = numEqualSym (f n) (f m) R'nm
in
let transR : Transitive R'
transR {i} {j} {k} R'ij R'jk =
numEqualTrans (f i) (f j) (f k) R'ij R'jk
in
record { refl = reflR ; sym = symR ; trans = transR }
NoSmaller : (n : ℕ) → (P : ℕ → Bool) → Set
NoSmaller n P = (x : ℕ) → (x ≤ n) → (P x ≡ true) → x ≡ n
IsMin : (n : ℕ) → (P : ℕ → Bool) → Set
IsMin n P = (P n ≡ true ) × NoSmaller n P
findMin : (n : ℕ) → (P : ℕ → Bool) →
((Σ[ ℓ ∈ ℕ ](ℓ ≤ n × IsMin ℓ P))
⊎
((ℓ : ℕ) → (ℓ ≤ n) → (P ℓ ≡ false))
)
findMin 0 P with ((P 0) Data.Bool.≟ true)
... | yes P0 =
let f : NoSmaller 0 P
f x x≤0 _ = n≤0⇒n≡0 x≤0
in
inj₁ (0 , ≤-refl , P0 , f)
... | no ¬P0 =
inj₂ (λ x x≤0 → subst (λ ℓ → P ℓ ≡ false) (sym (n≤0⇒n≡0 x≤0)) (¬-not ¬P0))
findMin (suc n) P with (findMin n P)
... | (inj₁ (m , m≤n , isminPm )) =
let m≤Sn : m ≤ ℕ.suc n
m≤Sn = ≤-trans m≤n (n≤1+n n)
in inj₁ (m , m≤Sn , isminPm)
... | (inj₂ f ) with (P (ℕ.suc n)) Data.Bool.≟ true
... | yes PSn =
let nosmallerPSn : NoSmaller (ℕ.suc n) P
nosmallerPSn x x≤Sn Px =
let H : x Data.Nat.< (ℕ.suc n) ⊎ (x ≡ ℕ.suc n)
H = m≤n⇒m<n∨m≡n x≤Sn
in
let ¬[x<Sn] : ¬ (x Data.Nat.< ℕ.suc n)
¬[x<Sn] Sx≤Sn =
let x≤n : x ≤ n
x≤n = s≤s⁻¹ Sx≤Sn
in
not-¬ (f x x≤n) Px
in
elimCaseLeft H ¬[x<Sn]
in inj₁ (ℕ.suc n , ≤-refl , PSn , nosmallerPSn)
... | no ¬PSn =
let f : (ℓ : ℕ) → ℓ ≤ ℕ.suc n → P ℓ ≡ false
f ℓ ℓ≤Sn =
let ℓ<Sn⊎l≡Sn = m≤n⇒m<n∨m≡n ℓ≤Sn
in
let H : ℓ Data.Nat.< ℕ.suc n → P ℓ ≡ false
H Sℓ≤Sn =
let ℓ≤n = s≤s⁻¹ Sℓ≤Sn
in
f ℓ ℓ≤n
in
let K : ℓ ≡ ℕ.suc n → P ℓ ≡ false
K ℓ≡Sn = subst (λ m → P m ≡ false) (sym ℓ≡Sn) (¬-not ¬PSn)
in
([_,_] H K) ℓ<Sn⊎l≡Sn
in
inj₂ f
findMinAlwaysPoss
: (n : ℕ)
→ (P : ℕ → Bool)
→ (P n ≡ true)
→ Σ[ ℓ ∈ ℕ ](ℓ ≤ n × IsMin ℓ P)
findMinAlwaysPoss n P Pn =
let foundMin = findMin n P
in
let notRightCase : ¬ ((ℓ : ℕ) → ℓ ≤ n → P ℓ ≡ false)
notRightCase p = not-¬ (p n ≤-refl) Pn
in
elimCaseRight foundMin notRightCase
minUnique
: (n m : ℕ)
→ (P : ℕ → Bool)
→ (IsMin n P)
→ (IsMin m P)
→ n ≡ m
minUnique n m P (Pn , noSmallerN) (Pm , noSmallerM) with (n ≤? m)
... | yes n≤m = noSmallerM n n≤m Pn
... | no n≰m =
let m≤n : m ≤ n
m≤n = ≰⇒≥ n≰m
in
sym (noSmallerN m m≤n Pm)
boolRelToSetRel
: {A : Set}
→ {a b : A}
→ {R : A → A → Bool}
→ (R a b ≡ true)
→ (R ⊢ a ~ b)
boolRelToSetRel {A} {a} {b} {R} Rab = Rab
setRelToBoolRel
: {A : Set}
→ {a b : A}
→ {R : A → A → Bool}
→ (R ⊢ a ~ b)
→ (R a b ≡ true)
setRelToBoolRel {A} {a} {b} {R} R⊢a~b with R a b Data.Bool.≟ true
... | yes Rab = Rab
... | no ¬Rab = ⊥-elim (¬Rab R⊢a~b)
boolRelTrans
: {A : Set}
→ {a b c : A}
→ {R : A → A → Bool}
→ (Transitive (R ⊢_~_))
→ (R a b ≡ true)
→ (R b c ≡ true)
→ (R a c ≡ true)
boolRelTrans {A} {a} {b} {c} {R} transR Rab Rbc = transR Rab Rbc
RelToFun : DecEquiv → NFFun
RelToFun (R , record { refl = reflR ; sym = symR ; trans = transR }) =
let f : ℕ → ℕ
f n = proj₁ (findMinAlwaysPoss n (R n) (reflR {n}))
in
let nleq : NFLeq f
nleq n = proj₁ (proj₂ (findMinAlwaysPoss n (R n) (reflR {n})))
in
let nfix : NFFix f
nfix n =
let fn = proj₁ (findMinAlwaysPoss n (R n) (reflR {n}))
in
let ffn = proj₁ (findMinAlwaysPoss fn (R fn) reflR)
in
let nRfn : R n (fn) ≡ true
nRfn = proj₁ (proj₂ (proj₂
(findMinAlwaysPoss n (R n) (reflR {n}))))
in
let fnRffn : R (fn) (ffn) ≡ true
fnRffn = proj₁ (proj₂ (proj₂
(findMinAlwaysPoss fn (R fn) (reflR {fn}))))
in
let nRffn : R n (ffn) ≡ true
nRffn = transR nRfn fnRffn
in
let ffn≤fn : ffn ≤ fn
ffn≤fn = proj₁ (proj₂
(findMinAlwaysPoss fn (R fn) (reflR {fn})))
in
let fnIsMin = proj₂ (proj₂ (proj₂
(findMinAlwaysPoss n (R n) (reflR {n}))))
in
fnIsMin ffn ffn≤fn nRffn
in
(f , nleq , nfix)