2022-02-24 14:12:53 +03:00
|
|
|
||| This module is based on Todd Waugh Ambridge's blog post series
|
|
|
|
||| "Search over uniformly continuous decidable predicates on
|
|
|
|
||| infinite collections of types"
|
|
|
|
||| https://www.cs.bham.ac.uk/~txw467/tychonoff/
|
|
|
|
|
|
|
|
module Search.Tychonoff.PartI
|
|
|
|
|
|
|
|
import Data.DPair
|
|
|
|
import Data.Nat
|
|
|
|
import Data.Nat.Order
|
|
|
|
import Data.So
|
|
|
|
import Data.Vect
|
|
|
|
import Decidable.Equality
|
|
|
|
import Decidable.Decidable
|
|
|
|
|
|
|
|
%default total
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
-- Searchable types
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
Pred : Type -> Type
|
|
|
|
Pred a = a -> Type
|
|
|
|
|
|
|
|
0 Decidable : Pred a -> Type
|
|
|
|
Decidable p = (x : a) -> Dec (p x)
|
|
|
|
|
|
|
|
||| Hilbert's epsilon is a function that for a given predicate
|
|
|
|
||| returns a value that satisfies it if any value exists that
|
|
|
|
||| that would satisfy it.
|
|
|
|
-- NB: this is not in the original posts, it's me making potentially
|
|
|
|
-- erroneous connections
|
|
|
|
0 HilbertEpsilon : Pred x -> Type
|
|
|
|
HilbertEpsilon p = (v : x ** (v0 : x) -> p v0 -> p v)
|
|
|
|
|
|
|
|
||| A type is searchable if for any
|
|
|
|
||| @ p a decidable predicate over that type
|
|
|
|
||| @ x can be found such that if there exists a
|
|
|
|
||| @ x0 satisfying p then x also satisfies p
|
|
|
|
0 IsSearchable : Type -> Type
|
|
|
|
IsSearchable x = (0 p : Pred x) -> Decidable p -> HilbertEpsilon p
|
|
|
|
|
2024-04-03 17:41:57 +03:00
|
|
|
private infix 0 <->
|
2022-02-24 14:12:53 +03:00
|
|
|
record (<->) (a, b : Type) where
|
|
|
|
constructor MkIso
|
|
|
|
forwards : a -> b
|
|
|
|
backwards : b -> a
|
|
|
|
inverseL : (x : a) -> backwards (forwards x) === x
|
|
|
|
inverseR : (y : b) -> forwards (backwards y) === y
|
|
|
|
|
|
|
|
||| Searchable is closed under isomorphisms
|
|
|
|
map : (a <-> b) -> IsSearchable a -> IsSearchable b
|
|
|
|
map (MkIso f g _ inv) search p pdec =
|
|
|
|
let (xa ** prfa) = search (p . f) (\ x => pdec (f x)) in
|
|
|
|
(f xa ** \ xb, pxb => prfa (g xb) $ replace {p} (sym $ inv xb) pxb)
|
|
|
|
|
|
|
|
interface Searchable (0 a : Type) where
|
|
|
|
constructor MkSearchable
|
|
|
|
search : IsSearchable a
|
|
|
|
|
|
|
|
Inhabited : Type -> Type
|
|
|
|
Inhabited a = a
|
|
|
|
|
|
|
|
searchableIsInhabited : IsSearchable a -> Inhabited a
|
|
|
|
searchableIsInhabited search = fst (search (\ _ => ()) (\ _ => Yes ()))
|
|
|
|
|
|
|
|
-- Finite types are trivially searchable
|
|
|
|
|
|
|
|
||| Unit is searchable
|
|
|
|
Searchable () where
|
|
|
|
search p pdef = (() ** \ (), prf => prf)
|
|
|
|
|
|
|
|
||| Bool is searchable
|
|
|
|
Searchable Bool where
|
|
|
|
search p pdec = case pdec True of
|
|
|
|
-- if p True holds we're done
|
|
|
|
Yes prf => MkDPair True $ \ _, _ => prf
|
|
|
|
-- otherwise p False is our best bet
|
|
|
|
No contra => MkDPair False $ \case
|
|
|
|
False => id
|
|
|
|
True => absurd . contra
|
|
|
|
|
|
|
|
||| Searchable is closed under finite sum
|
|
|
|
-- Note that this would enable us to go back and prove Bool searchable
|
|
|
|
-- via the iso Bool <-> Either () ()
|
|
|
|
(Searchable a, Searchable b) => Searchable (Either a b) where
|
|
|
|
search p pdec =
|
|
|
|
let (xa ** prfa) = search (p . Left) (\ xa => pdec (Left xa)) in
|
|
|
|
let (xb ** prfb) = search (p . Right) (\ xb => pdec (Right xb)) in
|
|
|
|
case pdec (Left xa) of
|
|
|
|
Yes pxa => (Left xa ** \ _, _ => pxa)
|
|
|
|
No npxa => case pdec (Right xb) of
|
|
|
|
Yes pxb => (Right xb ** \ _, _ => pxb)
|
|
|
|
No npxb => MkDPair (Left xa) $ \case
|
|
|
|
Left xa' => \ pxa' => absurd (npxa (prfa xa' pxa'))
|
|
|
|
Right xb' => \ pxb' => absurd (npxb (prfb xb' pxb'))
|
|
|
|
|
|
|
|
||| Searchable is closed under finite product
|
|
|
|
(Searchable a, Searchable b) => Searchable (a, b) where
|
|
|
|
search p pdec =
|
|
|
|
-- How cool is that use of choice?
|
|
|
|
let (fb ** prfb) = Pair.choice $ \ a => search (p . (a,)) (\ b => pdec (a, b)) in
|
|
|
|
let (xa ** prfa) = search (\ a => p (a, fb a)) (\ xa => pdec (xa, fb xa)) in
|
|
|
|
MkDPair (xa, fb xa) $ \ (xa', xb'), pxab' => prfa xa' (prfb xa' xb' pxab')
|
|
|
|
|
|
|
|
||| Searchable for Vect
|
|
|
|
%hint
|
|
|
|
searchVect : Searchable a => (n : Nat) -> Searchable (Vect n a)
|
|
|
|
searchVect 0 = MkSearchable $ \ p, pdec => ([] ** \case [] => id)
|
|
|
|
searchVect (S n) = MkSearchable $ \ p, pdec =>
|
|
|
|
let %hint ih : Searchable (Vect n a)
|
|
|
|
ih = searchVect n
|
|
|
|
0 P : Pred (a, Vect n a)
|
|
|
|
P = p . Prelude.uncurry (::)
|
|
|
|
Pdec : Decidable P
|
|
|
|
Pdec = \ (x, xs) => pdec (x :: xs)
|
|
|
|
in bimap (uncurry (::)) (\ prf => \case (v0 :: vs0) => prf (v0, vs0))
|
|
|
|
$ search P Pdec
|
|
|
|
|
|
|
|
||| The usual LPO is for Nat only
|
|
|
|
0 LPO : Type -> Type
|
|
|
|
LPO a = (f : a -> Bool) ->
|
|
|
|
Either (x : a ** f x === True) ((x : a) -> f x === False)
|
|
|
|
|
|
|
|
0 LPO' : Type -> Type
|
|
|
|
LPO' a = (0 p : Pred a) -> Decidable p ->
|
|
|
|
Either (x : a ** p x) ((x : a) -> Not (p x))
|
|
|
|
|
|
|
|
SearchableIsLPO : IsSearchable a -> LPO' a
|
|
|
|
SearchableIsLPO search p pdec =
|
|
|
|
let (x ** prf) = search p pdec in
|
|
|
|
case pdec x of
|
|
|
|
Yes px => Left (x ** px)
|
|
|
|
No npx => Right (\ x', px' => absurd (npx (prf x' px')))
|
|
|
|
|
|
|
|
LPOIsSearchable : LPO' a -> Inhabited a -> IsSearchable a
|
|
|
|
LPOIsSearchable lpo inh p pdec = case lpo p pdec of
|
|
|
|
Left (x ** px) => (x ** \ _, _ => px)
|
|
|
|
Right contra => (inh ** \ x, px => absurd (contra x px))
|
|
|
|
|
|
|
|
EqUntil : (m : Nat) -> (a, b : Nat -> x) -> Type
|
|
|
|
EqUntil m a b = (k : Nat) -> k `LTE` m -> a k === b k
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
-- Closeness functions and extended naturals
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
||| A decreasing sequence of booleans
|
|
|
|
Decreasing : (Nat -> Bool) -> Type
|
|
|
|
Decreasing f = (n : Nat) -> So (f (S n)) -> So (f n)
|
|
|
|
|
|
|
|
||| Nat extended with a point at infinity
|
|
|
|
record NatInf where
|
|
|
|
constructor MkNatInf
|
|
|
|
sequence : Nat -> Bool
|
|
|
|
isDecreasing : Decreasing sequence
|
|
|
|
|
|
|
|
repeat : x -> (Nat -> x)
|
|
|
|
repeat v = const v
|
|
|
|
|
|
|
|
Zero : NatInf
|
|
|
|
Zero = MkNatInf (repeat False) (\ n, prf => prf)
|
|
|
|
|
|
|
|
Omega : NatInf
|
|
|
|
Omega = MkNatInf (repeat True) (\ n, prf => prf)
|
|
|
|
|
|
|
|
(::) : x -> (Nat -> x) -> (Nat -> x)
|
|
|
|
(v :: f) 0 = v
|
|
|
|
(v :: f) (S n) = f n
|
|
|
|
|
|
|
|
Succ : NatInf -> NatInf
|
|
|
|
Succ f = MkNatInf (True :: f .sequence) decr where
|
|
|
|
|
|
|
|
decr : Decreasing (True :: f .sequence)
|
|
|
|
decr 0 = const Oh
|
|
|
|
decr (S n) = f .isDecreasing n
|
|
|
|
|
|
|
|
fromNat : Nat -> NatInf
|
|
|
|
fromNat 0 = Zero
|
|
|
|
fromNat (S k) = Succ (fromNat k)
|
|
|
|
|
|
|
|
soFromNat : k `LT` n -> So ((fromNat n) .sequence k)
|
|
|
|
soFromNat p = case view p of
|
|
|
|
LTZero => Oh
|
|
|
|
LTSucc p => soFromNat p
|
|
|
|
|
|
|
|
fromNatSo : {k, n : Nat} -> So ((fromNat n) .sequence k) -> k `LT` n
|
|
|
|
fromNatSo {n = 0} hyp = absurd hyp
|
|
|
|
fromNatSo {k = 0} {n = S n} hyp = LTESucc LTEZero
|
|
|
|
fromNatSo {k = S k} {n = S n} hyp = LTESucc (fromNatSo hyp)
|
|
|
|
|
|
|
|
LTE : (f, g : NatInf) -> Type
|
|
|
|
f `LTE` g = (n : Nat) -> So (f .sequence n) -> So (g .sequence n)
|
|
|
|
|
|
|
|
minimalZ : (f : NatInf) -> fromNat 0 `LTE` f
|
|
|
|
minimalZ f n prf = absurd prf
|
|
|
|
|
|
|
|
maximalInf : (f : NatInf) -> f `LTE` Omega
|
|
|
|
maximalInf f n prf = Oh
|
|
|
|
|
|
|
|
min : (f, g : NatInf) -> NatInf
|
|
|
|
min (MkNatInf f prf) (MkNatInf g prg)
|
|
|
|
= MkNatInf (\ n => f n && g n) $ \ n, prfg =>
|
|
|
|
let (l, r) = soAnd prfg in
|
|
|
|
andSo (prf n l, prg n r)
|
|
|
|
|
|
|
|
minLTE : (f, g : NatInf) -> min f g `LTE` f
|
|
|
|
minLTE (MkNatInf f prf) (MkNatInf g prg) n pr = fst (soAnd pr)
|
|
|
|
|
|
|
|
max : (f, g : NatInf) -> NatInf
|
|
|
|
max (MkNatInf f prf) (MkNatInf g prg)
|
|
|
|
= MkNatInf (\ n => f n || g n) $ \ n, prfg =>
|
|
|
|
orSo $ case soOr prfg of
|
|
|
|
Left pr => Left (prf n pr)
|
|
|
|
Right pr => Right (prg n pr)
|
|
|
|
|
|
|
|
maxLTE : (f, g : NatInf) -> f `LTE` max f g
|
|
|
|
maxLTE (MkNatInf f prf) (MkNatInf g prg) n pr = orSo (Left pr)
|
|
|
|
|
|
|
|
record ClosenessFunction (0 x : Type) (c : (v, w : x) -> NatInf) where
|
|
|
|
constructor MkClosenessFunction
|
|
|
|
selfClose : (v : x) -> c v v === Omega
|
|
|
|
closeSelf : (v, w : x) -> c v w === Omega -> v === w
|
|
|
|
symmetric : (v, w : x) -> c v w === c w v
|
|
|
|
ultrametic : (u, v, w : x) -> min (c u v) (c v w) `LTE` c u w
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
-- Discrete closeness function
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
Discrete : Type -> Type
|
|
|
|
Discrete = DecEq
|
|
|
|
|
|
|
|
dc : Discrete x => (v, w : x) -> NatInf
|
|
|
|
dc v w = ifThenElse (isYes $ decEq v w) Omega Zero
|
|
|
|
|
|
|
|
dcIsClosenessFunction : Discrete x => ClosenessFunction x PartI.dc
|
|
|
|
dcIsClosenessFunction
|
|
|
|
= MkClosenessFunction selfClose closeSelf symmetric ultrametric
|
|
|
|
|
|
|
|
where
|
|
|
|
|
|
|
|
selfClose : (v : x) -> dc v v === Omega
|
|
|
|
selfClose v with (decEq v v)
|
|
|
|
_ | Yes pr = Refl
|
|
|
|
_ | No npr = absurd (npr Refl)
|
|
|
|
|
|
|
|
closeSelf : (v, w : x) -> dc v w === Omega -> v === w
|
|
|
|
closeSelf v w eq with (decEq v w)
|
|
|
|
_ | Yes pr = pr
|
|
|
|
_ | No npr = absurd (cong (($ 0) . sequence) eq)
|
|
|
|
|
|
|
|
symmetric : (v, w : x) -> dc v w === dc w v
|
|
|
|
symmetric v w with (decEq v w)
|
|
|
|
symmetric v v | Yes Refl = rewrite decEqSelfIsYes {x = v} in Refl
|
|
|
|
_ | No nprf with (decEq w v)
|
|
|
|
_ | Yes prf = absurd (nprf (sym prf))
|
|
|
|
_ | No _ = Refl
|
|
|
|
|
|
|
|
ultrametric : (u, v, w : x) -> min (dc u v) (dc v w) `LTE` dc u w
|
|
|
|
ultrametric u v w n with (decEq u w)
|
|
|
|
_ | Yes r = const Oh
|
|
|
|
_ | No nr with (decEq u v)
|
|
|
|
_ | Yes p with (decEq v w)
|
|
|
|
_ | Yes q = absurd (nr (trans p q))
|
|
|
|
_ | No nq = id
|
|
|
|
_ | No np with (decEq v w)
|
|
|
|
_ | Yes q = id
|
|
|
|
_ | No nq = id
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
-- Discrete-sequence closeness function
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
decEqUntil : Discrete x => (n : Nat) -> (f, g : Nat -> x) -> Dec (EqUntil n f g)
|
|
|
|
decEqUntil n f g = decideLTEBounded (\ n => decEq (f n) (g n)) n
|
|
|
|
|
|
|
|
fromYes : (d : Dec p) -> isYes d === True -> p
|
|
|
|
fromYes (Yes prf) _ = prf
|
|
|
|
|
|
|
|
decEqUntilPred :
|
|
|
|
Discrete x => (n : Nat) -> (f, g : Nat -> x) ->
|
|
|
|
isYes (decEqUntil (S n) f g) === True ->
|
|
|
|
isYes (decEqUntil n f g) === True
|
|
|
|
decEqUntilPred n f g eq with (decEqUntil n f g)
|
|
|
|
_ | Yes prf = Refl
|
|
|
|
_ | No nprf = let prf = fromYes (decEqUntil (S n) f g) eq in
|
|
|
|
absurd (nprf $ \ l, bnd => prf l (lteSuccRight bnd))
|
|
|
|
|
|
|
|
public export
|
|
|
|
dsc : Discrete x => (f, g : Nat -> x) -> NatInf
|
|
|
|
dsc f g = (MkNatInf Meas decr) where
|
|
|
|
|
|
|
|
Meas : Nat -> Bool
|
|
|
|
Meas = \ n => (ifThenElse (isYes $ decEqUntil n f g) Omega Zero) .sequence n
|
|
|
|
|
|
|
|
decr : Decreasing Meas
|
|
|
|
decr n with (decEqUntil (S n) f g) proof eq
|
|
|
|
_ | Yes eqSn = rewrite decEqUntilPred n f g (cong isYes eq) in id
|
|
|
|
_ | No neqSn = \case prf impossible
|
|
|
|
|
|
|
|
interface IsSubSingleton x where
|
|
|
|
isSubSingleton : (v, w : x) -> v === w
|
|
|
|
|
|
|
|
IsSubSingleton Void where
|
|
|
|
isSubSingleton p q = absurd p
|
|
|
|
|
|
|
|
IsSubSingleton () where
|
|
|
|
isSubSingleton () () = Refl
|
|
|
|
|
|
|
|
(IsSubSingleton a, IsSubSingleton b) => IsSubSingleton (a, b) where
|
|
|
|
isSubSingleton (p,q) (u,v) = cong2 (,) (isSubSingleton p u) (isSubSingleton q v)
|
|
|
|
|
|
|
|
IsSubSingleton (So b) where
|
|
|
|
isSubSingleton Oh Oh = Refl
|
|
|
|
|
|
|
|
-- K axiom
|
|
|
|
IsSubSingleton (v === w) where
|
|
|
|
isSubSingleton Refl Refl = Refl
|
|
|
|
|
|
|
|
0 (~~~) : {0 b : a -> Type} -> (f, g : (x : a) -> b x) -> Type
|
|
|
|
f ~~~ g = (x : a) -> f x === g x
|
|
|
|
|
|
|
|
0 ExtensionalEquality : Type
|
|
|
|
ExtensionalEquality
|
|
|
|
= {0 a : Type} -> {0 b : a -> Type} ->
|
|
|
|
{f, g : (x : a) -> b x} ->
|
|
|
|
f ~~~ g -> f === g
|
|
|
|
|
|
|
|
interface Extensionality where
|
|
|
|
functionalExt : ExtensionalEquality
|
|
|
|
|
|
|
|
{0 p : a -> Type} ->
|
|
|
|
Extensionality =>
|
|
|
|
((x : a) -> IsSubSingleton (p x)) =>
|
|
|
|
IsSubSingleton ((x : a) -> p x) where
|
|
|
|
isSubSingleton v w = functionalExt (\ x => isSubSingleton (v x) (w x))
|
|
|
|
|
|
|
|
-- Extensionality is needed for the No/No case
|
|
|
|
Extensionality => IsSubSingleton p => IsSubSingleton (Dec p) where
|
|
|
|
isSubSingleton (Yes p) (Yes q) = cong Yes (isSubSingleton p q)
|
|
|
|
isSubSingleton (Yes p) (No nq) = absurd (nq p)
|
|
|
|
isSubSingleton (No np) (Yes q) = absurd (np q)
|
|
|
|
isSubSingleton (No np) (No nq) = cong No (isSubSingleton np nq)
|
|
|
|
|
|
|
|
parameters {auto _ : Extensionality}
|
|
|
|
|
|
|
|
seqEquals : {f, g : Nat -> x} -> f ~~~ g -> f === g
|
|
|
|
seqEquals = functionalExt
|
|
|
|
|
|
|
|
decEqUntilSelfIsYes : Discrete x => (n : Nat) -> (f : Nat -> x) ->
|
|
|
|
decEqUntil n f f === Yes (\ k, bnd => Refl)
|
|
|
|
decEqUntilSelfIsYes n f = isSubSingleton ? ?
|
|
|
|
|
|
|
|
NatInfEquals : {f, g : Nat -> Bool} ->
|
|
|
|
{fdecr : Decreasing f} ->
|
|
|
|
{gdecr : Decreasing g} ->
|
|
|
|
f ~~~ g -> MkNatInf f fdecr === MkNatInf g gdecr
|
|
|
|
NatInfEquals {f} eq with (seqEquals eq)
|
|
|
|
_ | Refl = cong (MkNatInf f) (isSubSingleton ? ?)
|
|
|
|
|
|
|
|
dscIsClosenessFunction : Discrete x => ClosenessFunction (Nat -> x) PartI.dsc
|
|
|
|
dscIsClosenessFunction {x}
|
|
|
|
= MkClosenessFunction
|
|
|
|
selfClose
|
|
|
|
(\ v, w, eq => seqEquals (closeSelf v w eq))
|
|
|
|
(\ v, w => NatInfEquals (symmetric v w))
|
|
|
|
ultrametric
|
|
|
|
|
|
|
|
where
|
|
|
|
|
|
|
|
selfClose : (v : Nat -> x) -> dsc v v === Omega
|
|
|
|
selfClose v = NatInfEquals $ \ n => rewrite decEqUntilSelfIsYes n v in Refl
|
|
|
|
|
|
|
|
closeSelf : (v, w : Nat -> x) -> dsc v w === Omega -> v ~~~ w
|
|
|
|
closeSelf v w eq n with (cong (\ f => f .sequence n) eq)
|
|
|
|
_ | prf with (decEqUntil n v w)
|
|
|
|
_ | Yes eqn = eqn n reflexive
|
|
|
|
_ | No neqn = absurd prf
|
|
|
|
|
|
|
|
symmetric : (v, w : Nat -> x) -> (dsc v w) .sequence ~~~ (dsc w v) .sequence
|
|
|
|
symmetric v w n with (decEqUntil n v w)
|
|
|
|
_ | Yes p with (decEqUntil n w v)
|
|
|
|
_ | Yes q = Refl
|
|
|
|
_ | No nq = absurd (nq $ \ k, bnd => sym (p k bnd))
|
|
|
|
_ | No np with (decEqUntil n w v)
|
|
|
|
_ | Yes q = absurd (np $ \ k, bnd => sym (q k bnd))
|
|
|
|
_ | No nq = Refl
|
|
|
|
|
|
|
|
ultrametric : (u, v, w : Nat -> x) -> min (dsc u v) (dsc v w) `LTE` dsc u w
|
|
|
|
ultrametric u v w n with (decEqUntil n u w)
|
|
|
|
_ | Yes r = const Oh
|
|
|
|
_ | No nr with (decEqUntil n u v)
|
|
|
|
_ | Yes p with (decEqUntil n v w)
|
|
|
|
_ | Yes q = absurd (nr (\ k, bnd => trans (p k bnd) (q k bnd)))
|
|
|
|
_ | No nq = id
|
|
|
|
_ | No np with (decEqUntil n v w)
|
|
|
|
_ | Yes q = id
|
|
|
|
_ | No nq = id
|
|
|
|
|
|
|
|
closeImpliesEqUntil : Discrete x =>
|
|
|
|
(n : Nat) -> (f, g : Nat -> x) ->
|
|
|
|
fromNat (S n) `LTE` dsc f g ->
|
|
|
|
EqUntil n f g
|
|
|
|
closeImpliesEqUntil n f g prf with (prf n)
|
|
|
|
_ | prfn with (decEqUntil n f g)
|
|
|
|
_ | Yes eqn = eqn
|
|
|
|
_ | No neqn = absurd (prfn (soFromNat reflexive))
|
|
|
|
|
|
|
|
eqUntilImpliesClose : Discrete x =>
|
|
|
|
(n : Nat) -> (f, g : Nat -> x) ->
|
|
|
|
EqUntil n f g ->
|
|
|
|
fromNat (S n) `LTE` dsc f g
|
|
|
|
eqUntilImpliesClose n f g prf k hyp with (decEqUntil k f g)
|
|
|
|
_ | Yes p = Oh
|
|
|
|
_ | No np = let klten = fromLteSucc $ fromNatSo {k} {n = S n} hyp in
|
|
|
|
absurd (np $ \ k', bnd => prf k' (transitive bnd klten))
|
|
|
|
|
|
|
|
buildUp : Discrete x => (n : Nat) -> (f, g : Nat -> x) ->
|
|
|
|
fromNat n `LTE` dsc f g ->
|
|
|
|
(v : x) ->
|
|
|
|
fromNat (S n) `LTE` dsc (v :: f) (v :: g)
|
|
|
|
buildUp n f g hyp v
|
|
|
|
= eqUntilImpliesClose n (v :: f) (v :: g)
|
|
|
|
$ \ k, bnd => case bnd of
|
|
|
|
LTEZero => Refl
|
|
|
|
LTESucc bnd => closeImpliesEqUntil ? f g hyp ? bnd
|
|
|
|
|
|
|
|
head : (Nat -> x) -> x
|
|
|
|
head f = f Z
|
|
|
|
|
|
|
|
tail : (Nat -> x) -> (Nat -> x)
|
|
|
|
tail f = f . S
|
|
|
|
|
|
|
|
parameters {auto _ : Extensionality}
|
|
|
|
|
|
|
|
eta : (f : Nat -> x) -> f === head f :: tail f
|
|
|
|
eta f = functionalExt $ \case
|
|
|
|
Z => Refl
|
|
|
|
S n => Refl
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
-- Continuity and continuously searchable types
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
||| Uniform modulus of continuity
|
|
|
|
||| @ c the notion of closeness used
|
|
|
|
||| @ p the predicate of interest
|
|
|
|
||| @ mod the modulus being characterised
|
|
|
|
0 IsUModFor : (c : (v, w : x) -> NatInf) -> (p : Pred x) -> (mod : Nat) -> Type
|
|
|
|
IsUModFor c p mod = (v, w : x) -> fromNat mod `LTE` c v w -> p v -> p w
|
|
|
|
|
|
|
|
||| Uniformly continuous predicate wrt a closeness function
|
|
|
|
||| @ c the notion of closeness used
|
|
|
|
||| @ p the uniformly continuous predicate
|
|
|
|
record UContinuous {0 x : Type} (c : (v, w : x) -> NatInf) (p : Pred x) where
|
|
|
|
constructor MkUC
|
|
|
|
uModulus : Nat
|
|
|
|
isUModFor : IsUModFor c p uModulus
|
|
|
|
|
|
|
|
||| A type equipped with
|
|
|
|
||| @ c a notion of closeness
|
|
|
|
||| is continuously searchable if for any
|
|
|
|
||| @ p a decidable predicate over that type
|
|
|
|
||| @ x can be found such that if there exists a
|
|
|
|
||| @ x0 satisfying p then x also satisfies p
|
|
|
|
0 IsCSearchable : (x : Type) -> ((v, w : x) -> NatInf) -> Type
|
|
|
|
IsCSearchable x c
|
|
|
|
= (0 p : Pred x) -> UContinuous c p -> Decidable p ->
|
|
|
|
HilbertEpsilon p
|
|
|
|
|
|
|
|
interface CSearchable x (0 c : (v, w : x) -> NatInf) where
|
|
|
|
csearch : IsCSearchable x c
|
|
|
|
|
|
|
|
[DEMOTE] Searchable x => CSearchable x c where
|
|
|
|
csearch p uc pdec = search p pdec
|
|
|
|
|
|
|
|
CSearchable Bool (PartI.dc {x = Bool}) where
|
|
|
|
csearch = csearch @{DEMOTE}
|
|
|
|
|
|
|
|
discreteIsUContinuous :
|
|
|
|
{0 p : Pred x} -> Discrete x =>
|
|
|
|
Decidable p -> UContinuous PartI.dc p
|
|
|
|
discreteIsUContinuous pdec = MkUC 1 isUContinuous where
|
|
|
|
|
|
|
|
isUContinuous : IsUModFor PartI.dc p 1
|
|
|
|
isUContinuous v w hyp pv with (decEq v w)
|
|
|
|
_ | Yes eq = replace {p} eq pv
|
|
|
|
_ | No neq = absurd (hyp 0 Oh)
|
|
|
|
|
|
|
|
[PROMOTE] Discrete x => CSearchable x PartI.dc => Searchable x where
|
|
|
|
search p pdec = csearch p (discreteIsUContinuous pdec) pdec
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
-- Main result
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
-- Lemma 1
|
|
|
|
|
|
|
|
nullModHilbert :
|
|
|
|
Decidable p -> IsUModFor c p 0 ->
|
|
|
|
(v : x ** p v) -> (v : x) -> p v
|
|
|
|
nullModHilbert pdec pmod0 (v0 ** pv0) v = pmod0 v0 v (\ n => absurd) pv0
|
|
|
|
|
|
|
|
trivial : UContinuous c (const ())
|
|
|
|
trivial = MkUC 0 (\ _, _, _, _ => ())
|
|
|
|
|
|
|
|
-- Lemma 2
|
|
|
|
|
|
|
|
|
|
|
|
0 tailPredicate : Pred (Nat -> x) -> x -> Pred (Nat -> x)
|
|
|
|
tailPredicate p v = p . (v ::)
|
|
|
|
|
|
|
|
parameters
|
|
|
|
{0 p : Pred (Nat -> x)}
|
|
|
|
{auto _ : Discrete x}
|
|
|
|
(pdec : Decidable p)
|
|
|
|
|
|
|
|
decTail : (v : x) -> Decidable (tailPredicate p v)
|
|
|
|
decTail v vs = pdec (v :: vs)
|
|
|
|
|
|
|
|
predModTail :
|
|
|
|
(mod : Nat) -> IsUModFor PartI.dsc p (S mod) ->
|
|
|
|
(v : x) -> IsUModFor PartI.dsc (tailPredicate p v) mod
|
|
|
|
predModTail mod hyp v f g prf pvf
|
|
|
|
= hyp (v :: f) (v :: g) (buildUp mod f g prf v) pvf
|
|
|
|
|
|
|
|
[BYUCONTINUITY] Extensionality =>
|
|
|
|
Discrete x =>
|
|
|
|
CSearchable x PartI.dc =>
|
|
|
|
CSearchable (Nat -> x) (PartI.dsc {x}) where
|
|
|
|
csearch q quni qdec
|
|
|
|
= go (search @{PROMOTE})
|
|
|
|
qdec
|
|
|
|
(quni .uModulus)
|
|
|
|
(quni .isUModFor)
|
|
|
|
|
|
|
|
where
|
|
|
|
|
|
|
|
go : IsSearchable x ->
|
|
|
|
{0 p : Pred (Nat -> x)} -> Decidable p ->
|
|
|
|
(n : Nat) -> IsUModFor PartI.dsc p n ->
|
|
|
|
HilbertEpsilon p
|
|
|
|
go s pdec 0 hyp
|
|
|
|
= let f = const (searchableIsInhabited s) in
|
|
|
|
MkDPair f (\ v0, pv0 => nullModHilbert {c = dsc} pdec hyp (v0 ** pv0) f)
|
|
|
|
go s pdec (S mod) hyp
|
|
|
|
= let -- Stepping function generating a tail from the head
|
|
|
|
stepping : x -> (Nat -> x)
|
|
|
|
stepping i = fst (go s (decTail pdec i) mod (predModTail pdec mod hyp i))
|
|
|
|
-- Searching for the head
|
|
|
|
0 PH : Pred x
|
|
|
|
PH = \ v => p (v :: stepping v)
|
|
|
|
pHdec : Decidable PH
|
|
|
|
pHdec = \ v => pdec (v :: stepping v)
|
|
|
|
sH : HilbertEpsilon PH
|
|
|
|
sH = s PH pHdec
|
|
|
|
-- Searching for the tail given an arbitrary head
|
|
|
|
0 PT : x -> Pred (Nat -> x)
|
|
|
|
PT i = tailPredicate p i
|
|
|
|
pTdec : (v : x) -> Decidable (PT v)
|
|
|
|
pTdec i = decTail pdec i
|
|
|
|
sT : (v : x) -> HilbertEpsilon (PT v)
|
|
|
|
sT i = go s (pTdec i) mod (predModTail pdec mod hyp i)
|
|
|
|
-- build up the result
|
|
|
|
v : x; v = sH .fst
|
|
|
|
vs : Nat -> x; vs = (sT v) .fst
|
|
|
|
in MkDPair (v :: vs) $ \ vv0s, pvv0s =>
|
|
|
|
let v0 : x; v0 = head vv0s
|
|
|
|
v0s : Nat -> x; v0s = tail vv0s
|
|
|
|
in sH .snd v0
|
|
|
|
$ (sT v0) .snd v0s
|
|
|
|
$ replace {p} (eta vv0s) pvv0s
|
|
|
|
|
|
|
|
cantorIsCSearchable : Extensionality => IsCSearchable (Nat -> Bool) PartI.dsc
|
|
|
|
cantorIsCSearchable = csearch @{BYUCONTINUITY}
|