File: Mathlib/Order/Estimator.lean

full_name: EstimatorData.improve
code: /--
Given `[EstimatorData a ε]`
* a term `e : ε` can be interpreted via `bound a e : α` as a lower bound for `a`, and
* we can ask for an improved lower bound via `improve a e : Option ε`.

The value `a` in `α` that we are estimating is hidden inside a `Thunk` to avoid evaluation.
 -/
class EstimatorData (a : Thunk α) (ε : Type*) where
  /-- The value of the bound for `a` representation by a term of `ε`. -/
  bound : ε → α
  /-- Generate an improved lower bound. -/
  improve : ε → Option ε
goal: ε → Option ε

full_name: EstimatorData
code: /--
Given `[EstimatorData a ε]`
* a term `e : ε` can be interpreted via `bound a e : α` as a lower bound for `a`, and
* we can ask for an improved lower bound via `improve a e : Option ε`.

The value `a` in `α` that we are estimating is hidden inside a `Thunk` to avoid evaluation.
 -/
class EstimatorData (a : Thunk α) (ε : Type*) where
  /-- The value of the bound for `a` representation by a term of `ε`. -/
  bound : ε → α
  /-- Generate an improved lower bound. -/
  improve : ε → Option ε
goal: Type (max u_1 u_3)

full_name: EstimatorData.bound
code: /--
Given `[EstimatorData a ε]`
* a term `e : ε` can be interpreted via `bound a e : α` as a lower bound for `a`, and
* we can ask for an improved lower bound via `improve a e : Option ε`.

The value `a` in `α` that we are estimating is hidden inside a `Thunk` to avoid evaluation.
 -/
class EstimatorData (a : Thunk α) (ε : Type*) where
  /-- The value of the bound for `a` representation by a term of `ε`. -/
  bound : ε → α
  /-- Generate an improved lower bound. -/
  improve : ε → Option ε
goal: ε → α

full_name: Estimator.bound_le
code: /--
Given `[Estimator a ε]`
* we have `bound a e ≤ a.get`, and
* `improve a e` returns none iff `bound a e = a.get`,
  and otherwise it returns a strictly better bound.
-/
class Estimator [Preorder α] (a : Thunk α) (ε : Type*) extends EstimatorData a ε where
  /-- The calculated bounds are always lower bounds. -/
  bound_le e : bound e ≤ a.get
  /-- Calling `improve` either gives a strictly better bound,
  or a proof that the current bound is exact. -/
  improve_spec e : match improve e with
    | none => bound e = a.get
    | some e' => bound e < bound e'
goal: EstimatorData.bound a e ≤ a.get

full_name: Estimator.improve_spec
code: /--
Given `[Estimator a ε]`
* we have `bound a e ≤ a.get`, and
* `improve a e` returns none iff `bound a e = a.get`,
  and otherwise it returns a strictly better bound.
-/
class Estimator [Preorder α] (a : Thunk α) (ε : Type*) extends EstimatorData a ε where
  /-- The calculated bounds are always lower bounds. -/
  bound_le e : bound e ≤ a.get
  /-- Calling `improve` either gives a strictly better bound,
  or a proof that the current bound is exact. -/
  improve_spec e : match improve e with
    | none => bound e = a.get
    | some e' => bound e < bound e'
goal: match EstimatorData.improve a e with
| none => EstimatorData.bound a e = a.get
| some e' => EstimatorData.bound a e < EstimatorData.bound a e'

full_name: Estimator
code: /--
Given `[Estimator a ε]`
* we have `bound a e ≤ a.get`, and
* `improve a e` returns none iff `bound a e = a.get`,
  and otherwise it returns a strictly better bound.
-/
class Estimator [Preorder α] (a : Thunk α) (ε : Type*) extends EstimatorData a ε where
  /-- The calculated bounds are always lower bounds. -/
  bound_le e : bound e ≤ a.get
  /-- Calling `improve` either gives a strictly better bound,
  or a proof that the current bound is exact. -/
  improve_spec e : match improve e with
    | none => bound e = a.get
    | some e' => bound e < bound e'
goal: Type (max u_1 u_3)

full_name: Estimator.trivial
code: /-- A trivial estimator, containing the actual value. -/
abbrev Estimator.trivial.{u} {α : Type u} (a : α) : Type u 
goal: Type u

full_name: instBotTrivial
code: instance {a : α} : Bot (Estimator.trivial a) 
goal: Bot (Estimator.trivial a)

full_name: instWellFoundedGTUnit
code: instance : WellFoundedGT Unit 
goal: WellFoundedGT Unit

full_name: instWellFoundedGTTrivial
code: instance (a : α) : WellFoundedGT (Estimator.trivial a) 
goal: WellFoundedGT (Estimator.trivial a)

full_name: instEstimatorPureTrivial
code: instance {a : α} : Estimator (Thunk.pure a) (Estimator.trivial a) 
goal: Estimator (Thunk.pure a) (Estimator.trivial a)

full_name: Estimator.improveUntilAux
code: /-- Implementation of `Estimator.improveUntil`. -/
def Estimator.improveUntilAux
    (a : Thunk α) (p : α → Bool) [Estimator a ε]
    [WellFoundedGT (range (bound a : ε → α))]
    (e : ε) (r : Bool) : Except (Option ε) ε 
goal: Except (Option ε) ε

full_name: Estimator.improveUntil
code: /--
Improve an estimate until it satisfies a predicate,
or else return the best available estimate, if any improvement was made.
-/
def Estimator.improveUntil (a : Thunk α) (p : α → Bool)
    [Estimator a ε] [WellFoundedGT (range (bound a : ε → α))] (e : ε) :
    Except (Option ε) ε 
goal: Except (Option ε) ε

full_name: Estimator.improveUntilAux_spec
code: /--
If `Estimator.improveUntil a p e` returns `some e'`, then `bound a e'` satisfies `p`.
Otherwise, that value `a` must not satisfy `p`.
-/
theorem Estimator.improveUntilAux_spec (a : Thunk α) (p : α → Bool)
    [Estimator a ε] [WellFoundedGT (range (bound a : ε → α))] (e : ε) (r : Bool) :
    match Estimator.improveUntilAux a p e r with
    | .error _ => ¬ p a.get
    | .ok e' => p (bound a e') 
goal: match Estimator.improveUntilAux a p e r with
| Except.error a_1 => ¬p a.get = true
| Except.ok e' => p (EstimatorData.bound a e') = true

full_name: Estimator.improveUntil_spec
code: /--
If `Estimator.improveUntil a p e` returns `some e'`, then `bound a e'` satisfies `p`.
Otherwise, that value `a` must not satisfy `p`.
-/
theorem Estimator.improveUntil_spec
    (a : Thunk α) (p : α → Bool) [Estimator a ε] [WellFoundedGT (range (bound a : ε → α))] (e : ε) :
    match Estimator.improveUntil a p e with
    | .error _ => ¬ p a.get
    | .ok e' => p (bound a e') 
goal: match Estimator.improveUntil a p e with
| Except.error a_1 => ¬p a.get = true
| Except.ok e' => p (EstimatorData.bound a e') = true

full_name: instEstimatorDataHAddThunkProd
code: @[simps]
instance [Add α] {a b : Thunk α} (εa εb : Type*) [EstimatorData a εa] [EstimatorData b εb] :
    EstimatorData (a + b) (εa × εb) 
goal: EstimatorData (a + b) (εa × εb)

full_name: instEstimatorDataHAddThunkProd_improve
code: @[simps]
instance [Add α] {a b : Thunk α} (εa εb : Type*) [EstimatorData a εa] [EstimatorData b εb] :
    EstimatorData (a + b) (εa × εb) 
goal: EstimatorData.improve (a + b) e =
  match EstimatorData.improve a e.1 with
  | some e' => some (e', e.2)
  | none =>
    match EstimatorData.improve b e.2 with
    | some e' => some (e.1, e')
    | none => none

full_name: instEstimatorDataHAddThunkProd_bound
code: @[simps]
instance [Add α] {a b : Thunk α} (εa εb : Type*) [EstimatorData a εa] [EstimatorData b εb] :
    EstimatorData (a + b) (εa × εb) 
goal: EstimatorData.bound (a + b) e = EstimatorData.bound a e.1 + EstimatorData.bound b e.2

full_name: instEstimatorNatHAddThunkProd
code: instance (a b : Thunk ℕ) {εa εb : Type*} [Estimator a εa] [Estimator b εb] :
    Estimator (a + b) (εa × εb) 
goal: Estimator (a + b) (εa × εb)

full_name: Estimator.fst.inner
code: /--
An estimator for `(a, b)` can be turned into an estimator for `a`,
simply by repeatedly running `improve` until the first factor "improves".
The hypothesis that `>` is well-founded on `{ q // q ≤ (a, b) }` ensures this terminates.
-/
structure Estimator.fst
    (p : Thunk (α × β)) (ε : Type*) [Estimator p ε] where
  /-- The wrapped bound for a value in `α × β`,
  which we will use as a bound for the first component. -/
  inner : ε
goal: ε

full_name: Estimator.fst
code: /--
An estimator for `(a, b)` can be turned into an estimator for `a`,
simply by repeatedly running `improve` until the first factor "improves".
The hypothesis that `>` is well-founded on `{ q // q ≤ (a, b) }` ensures this terminates.
-/
structure Estimator.fst
    (p : Thunk (α × β)) (ε : Type*) [Estimator p ε] where
  /-- The wrapped bound for a value in `α × β`,
  which we will use as a bound for the first component. -/
  inner : ε
goal: Type u_4

full_name: instWellFoundedGTElemRangeBound
code: instance {a : Thunk α} [Estimator a ε] : WellFoundedGT (range (bound a : ε → α)) 
goal: WellFoundedGT ↑(Set.range (EstimatorData.bound a))

full_name: instEstimatorDataFstProdOfDecidableRelLtOfWellFoundedGTSubtypeProdLe
code: instance [DecidableRel ((· : α) < ·)] {a : Thunk α} {b : Thunk β}
    (ε : Type*) [Estimator (a.prod b) ε] [∀ (p : α × β), WellFoundedGT { q // q ≤ p }] :
    EstimatorData a (Estimator.fst (a.prod b) ε) 
goal: EstimatorData a (Estimator.fst (a.prod b) ε)

full_name: Estimator.fstInst
code: /-- Given an estimator for a pair, we can extract an estimator for the first factor. -/
-- This isn't an instance as at the sole use case we need to provide
-- the instance arguments by hand anyway.
def Estimator.fstInst [DecidableRel ((· : α) < ·)] [∀ (p : α × β), WellFoundedGT { q // q ≤ p }]
    (a : Thunk α) (b : Thunk β) (i : Estimator (a.prod b) ε) :
    Estimator a (Estimator.fst (a.prod b) ε) 
goal: Estimator a (Estimator.fst (a.prod b) ε)