Documentation

VCVio.ProgramLogic.Unary.Loom.Quantitative

Quantitative WP carrier for OracleComp (Loom2 default) #

This file is the home of the quantitative algebra structure on OracleComp spec valued in ℝ≥0∞, plus its registration as the default Std.Do'.WP (OracleComp spec) ℝ≥0∞ EPost.nil instance.

It provides three layers:

  1. Expectation algebraμ : OracleComp spec ℝ≥0∞ → ℝ≥0∞ and the legacy MAlgOrdered (OracleComp spec) ℝ≥0∞ instance. These remain the structural root for OracleComp.ProgramLogic.wp / .Triple and the relational eRHL stack until the irreversible Commit 8 prunes MAlgOrdered.
  2. Lean.Order adapters for ℝ≥0∞ — bridges Mathlib's and sSup to Lean core's Lean.Order.{PartialOrder, CompleteLattice}, which Loom2 builds on. Prop ships with its own adapters in Loom/LatticeExt.lean.
  3. Std.Do'.WP instance — the canonical entry point for new program-logic developments. Its wpTrans wraps the existing MAlgOrdered.wp, so the keystone alignment lemma wp_eq_mAlgOrdered_wp holds by rfl.

Layout #

This is one of three WP carriers we register on OracleComp. Because Std.Do'.WP's Pred and EPred are outParams, only one carrier can be visible to instance synthesis at a time. We register them asymmetrically:

There is no umbrella Unary/Loom.lean re-export. Consumers import the specific carrier they need. This makes the carrier choice explicit at every import site.

Loom2 vs. Mathlib lattice plumbing #

Loom2 builds on Lean.Order.{PartialOrder, CompleteLattice, CCPO} from Init.Internal.Order, a class hierarchy distinct from Mathlib's Order.{PartialOrder, CompleteLattice}. We provide the narrow ℝ≥0∞ adapters here.

When Volo's PR #12965 lands upstream and the Std.Do.{WP,…} API stabilizes, this bridge collapses to a re-export and the lattice adapters can move to a shared ToMathlib/Order/LeanOrderAdapter.lean.

Expectation algebra and the MAlgOrdered instance #

noncomputable def OracleComp.ProgramLogic.μ {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] (oa : OracleComp spec ENNReal) :

Expectation-style algebra for oracle computations returning ℝ≥0∞.

Instances For
    theorem OracleComp.ProgramLogic.μ_bind_eq_tsum {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {α : Type} (oa : OracleComp spec α) (ob : αOracleComp spec ENNReal) :
    μ (oa >>= ob) = ∑' (x : α), Pr[= x | oa] * μ (ob x)
    @[implicit_reducible]
    noncomputable instance OracleComp.ProgramLogic.instMAlgOrdered {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] :

    Lean.Order adapters for ℝ≥0∞ #

    Loom2's Std.Do'.WP m Pred EPred requires Assertion Pred (a class abbrev for Lean.Order.CompleteLattice). We bridge Mathlib's order structure on ℝ≥0∞ to Lean core's lattice hierarchy here.

    @[implicit_reducible]

    Bridge Mathlib's sSup on ℝ≥0∞ to Lean.Order.CompleteLattice.

    Lean.Order.CompleteLattice.has_sup c requires a least upper bound for the predicate-encoded set {x | c x}. We discharge it with Mathlib's sSup specialization.

    Lean.Order.CCPO instance for Std.Do'.EPost.nil #

    Loom2's Hoare-triple notation ⦃ pre ⦄ x ⦃ post ⦄ (defined in Loom.Triple.Basic) expands to Std.Do'.Triple pre x post ⊥ where is the Lean.Order.CCPO-bottom (Lean.Order.bot). For monads with no exception layer, the EPred is Std.Do'.EPost.nil, which Loom2 ships only with a Lean.Order.CompleteLattice instance, not a CCPO one. (CCPO and CompleteLattice are independent sibling classes in Lean core's Init.Internal.Order.)

    We provide the missing CCPO instance here. EPost.nil is a single-element type, so the chain-supremum is trivial: every chain has the unique element EPost.nil.mk as its least upper bound.

    Std.Do'.WP instance for OracleComp #

    @[implicit_reducible]
    noncomputable instance OracleComp.ProgramLogic.Loom.instWP {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] :

    Quantitative Std.Do'.WP interpretation of OracleComp spec valued in ℝ≥0∞.

    The wpTrans is the existing MAlgOrdered.wp (i.e. expectation of post under evalDist); the EPost.nil argument is ignored since OracleComp has no first-class exception slot. The three WP axioms reduce to the existing MAlgOrdered.{wp_pure, wp_bind, wp_mono} equalities.

    Definitional alignment with MAlgOrdered.wp #

    The keystone lemma confirms Std.Do'.wp agrees with MAlgOrdered.wp on the nose, so every existing quantitative wp_* theorem in HoareTriple.lean transports for free when the user rewrites Std.Do'.wp _ _ _ ↦ MAlgOrdered.wp _ _.

    The epost argument is to match Loom2's ⦃ _ ⦄ _ ⦃ _ ⦄ notation in Loom.Triple.Basic. The WP instance for OracleComp ignores the epost argument entirely, so any element of EPost.nil would yield the same value.

    theorem OracleComp.ProgramLogic.Loom.wp_eq_mAlgOrdered_wp {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {α : Type} (oa : OracleComp spec α) (post : αENNReal) :
    theorem OracleComp.ProgramLogic.Loom.wp_eq_mAlgOrdered_wp_epost {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {α : Type} (oa : OracleComp spec α) (post : αENNReal) (epost : EPost⟨) :
    Std.Do'.wp oa post epost = MAlgOrdered.wp oa post

    StateT (OracleComp spec) WP normalization #

    @[simp]
    theorem OracleComp.ProgramLogic.Loom.wp_StateT_bind {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {α β σ : Type} (x : StateT σ (OracleComp spec) α) (f : αStateT σ (OracleComp spec) β) (post : βσENNReal) :
    Std.Do'.wp (x.bind f) post Lean.Order.bot = fun (s : σ) => Std.Do'.wp x (fun (a : α) (s' : σ) => Std.Do'.wp (f a) post Lean.Order.bot s') Lean.Order.bot s
    @[simp]
    theorem OracleComp.ProgramLogic.Loom.wp_StateT_bind' {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {α β σ : Type} (x : StateT σ (OracleComp spec) α) (f : αStateT σ (OracleComp spec) β) (post : βσENNReal) :
    Std.Do'.wp (x >>= f) post Lean.Order.bot = fun (s : σ) => Std.Do'.wp x (fun (a : α) (s' : σ) => Std.Do'.wp (f a) post Lean.Order.bot s') Lean.Order.bot s
    @[simp]
    theorem OracleComp.ProgramLogic.Loom.wp_StateT_pure {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {α σ : Type} (x : α) (post : ασENNReal) :
    Std.Do'.wp (pure x) post Lean.Order.bot = fun (s : σ) => post x s
    @[simp]
    theorem OracleComp.ProgramLogic.Loom.wp_StateT_get {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {σ : Type} (post : σσENNReal) :
    Std.Do'.wp MonadStateOf.get post Lean.Order.bot = fun (s : σ) => post s s
    @[simp]
    theorem OracleComp.ProgramLogic.Loom.wp_StateT_set {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {σ : Type} (s' : σ) (post : PUnit.{1}σENNReal) :
    Std.Do'.wp (set s') post Lean.Order.bot = fun (x : σ) => post PUnit.unit s'
    @[simp]
    theorem OracleComp.ProgramLogic.Loom.wp_StateT_modifyGet {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {α σ : Type} (f : σα × σ) (post : ασENNReal) :
    Std.Do'.wp (MonadStateOf.modifyGet f) post Lean.Order.bot = fun (s : σ) => post (f s).1 (f s).2
    @[simp]
    theorem OracleComp.ProgramLogic.Loom.wp_StateT_monadLift {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {α σ : Type} (oa : OracleComp spec α) (post : ασENNReal) :
    Std.Do'.wp (MonadLift.monadLift oa) post Lean.Order.bot = fun (s : σ) => Std.Do'.wp oa (fun (a : α) => post a s) Lean.Order.bot

    OptionT (OracleComp spec) WP normalization #

    @[simp]
    theorem OracleComp.ProgramLogic.Loom.wp_OptionT_bind {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {α β : Type} (x : OptionT (OracleComp spec) α) (f : αOptionT (OracleComp spec) β) (post : βENNReal) (epost : EPost⟨ENNReal) :
    Std.Do'.wp (x >>= f) post epost = Std.Do'.wp x (fun (a : α) => Std.Do'.wp (f a) post epost) epost
    @[simp]
    theorem OracleComp.ProgramLogic.Loom.wp_OptionT_pure {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {α : Type} (x : α) (post : αENNReal) (epost : EPost⟨ENNReal) :
    Std.Do'.wp (pure x) post epost = post x
    @[simp]
    theorem OracleComp.ProgramLogic.Loom.wp_OptionT_failure {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {α : Type} (post : αENNReal) (epost : EPost⟨ENNReal) :
    Std.Do'.wp failure post epost = epost.head
    @[simp]
    theorem OracleComp.ProgramLogic.Loom.wp_OptionT_monadLift {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {α : Type} (oa : OracleComp spec α) (post : αENNReal) (epost : EPost⟨ENNReal) :
    @[simp]
    theorem OracleComp.ProgramLogic.Loom.wp_OptionT_lift {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {α : Type} (oa : OracleComp spec α) (post : αENNReal) (epost : EPost⟨ENNReal) :
    @[simp]
    theorem OracleComp.ProgramLogic.Loom.wp_OptionT_map {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {α β : Type} (f : αβ) (x : OptionT (OracleComp spec) α) (post : βENNReal) (epost : EPost⟨ENNReal) :
    Std.Do'.wp (f <$> x) post epost = Std.Do'.wp x (fun (a : α) => post (f a)) epost

    ExceptT (OracleComp spec) WP normalization #

    @[simp]
    theorem OracleComp.ProgramLogic.Loom.wp_ExceptT_bind {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {α β ε : Type} (x : ExceptT ε (OracleComp spec) α) (f : αExceptT ε (OracleComp spec) β) (post : βENNReal) (epost : EPost⟨εENNReal) :
    Std.Do'.wp (x >>= f) post epost = Std.Do'.wp x (fun (a : α) => Std.Do'.wp (f a) post epost) epost
    @[simp]
    theorem OracleComp.ProgramLogic.Loom.wp_ExceptT_pure {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {α ε : Type} (x : α) (post : αENNReal) (epost : EPost⟨εENNReal) :
    Std.Do'.wp (pure x) post epost = post x
    @[simp]
    theorem OracleComp.ProgramLogic.Loom.wp_ExceptT_throw {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {α ε : Type} (e : ε) (post : αENNReal) (epost : EPost⟨εENNReal) :
    Std.Do'.wp (throw e) post epost = epost.head e
    @[simp]
    theorem OracleComp.ProgramLogic.Loom.wp_ExceptT_monadLift {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {α ε : Type} (oa : OracleComp spec α) (post : αENNReal) (epost : EPost⟨εENNReal) :

    ReaderT (OracleComp spec) WP normalization #

    @[simp]
    theorem OracleComp.ProgramLogic.Loom.wp_ReaderT_bind {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {α β ρ : Type} (x : ReaderT ρ (OracleComp spec) α) (f : αReaderT ρ (OracleComp spec) β) (post : βρENNReal) :
    Std.Do'.wp (x >>= f) post Lean.Order.bot = fun (r : ρ) => Std.Do'.wp x (fun (a : α) (r' : ρ) => Std.Do'.wp (f a) post Lean.Order.bot r') Lean.Order.bot r
    @[simp]
    theorem OracleComp.ProgramLogic.Loom.wp_ReaderT_pure {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {α ρ : Type} (x : α) (post : αρENNReal) :
    Std.Do'.wp (pure x) post Lean.Order.bot = fun (r : ρ) => post x r
    @[simp]
    theorem OracleComp.ProgramLogic.Loom.wp_ReaderT_read {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {ρ : Type} (post : ρρENNReal) :
    Std.Do'.wp MonadReaderOf.read post Lean.Order.bot = fun (r : ρ) => post r r
    @[simp]
    theorem OracleComp.ProgramLogic.Loom.wp_ReaderT_monadLift {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {α ρ : Type} (oa : OracleComp spec α) (post : αρENNReal) :
    Std.Do'.wp (MonadLift.monadLift oa) post Lean.Order.bot = fun (r : ρ) => Std.Do'.wp oa (fun (a : α) => post a r) Lean.Order.bot

    Generic WriterT WP normalization #

    @[implicit_reducible, instance 100]
    instance Std.Do'.WriterT.instWP {m : TypeType v} {Pred EPred ω : Type} [Monad m] [Monoid ω] [Assertion Pred] [Assertion EPred] [WP m Pred EPred] :
    WP (WriterT ω m) (ωPred) EPred
    @[simp]
    theorem Std.Do'.WriterT.apply_wp {m : TypeType v} {Pred EPred ω α : Type} [Monad m] [Monoid ω] [Assertion Pred] [Assertion EPred] [WP m Pred EPred] (x : WriterT ω m α) (post : αωPred) (epost : EPred) (w : ω) :
    wp x post epost w = wp x.run (fun (p : α × ω) => post p.1 (w * p.2)) epost
    theorem Std.Do'.WriterT.wp_pure {m : TypeType v} {Pred EPred ω α : Type} [Monad m] [Monoid ω] [Assertion Pred] [Assertion EPred] [WP m Pred EPred] (x : α) (post : αωPred) (epost : EPred) :
    Lean.Order.PartialOrder.rel (fun (w : ω) => post x w) (wp (pure x) post epost)
    theorem Std.Do'.WriterT.wp_bind {m : TypeType v} {Pred EPred ω α β : Type} [Monad m] [Monoid ω] [Assertion Pred] [Assertion EPred] [WP m Pred EPred] (x : WriterT ω m α) (f : αWriterT ω m β) (post : βωPred) (epost : EPred) :
    Lean.Order.PartialOrder.rel (fun (w : ω) => wp x (fun (a : α) (w' : ω) => wp (f a) post epost w') epost w) (wp (x >>= f) post epost)
    theorem Std.Do'.WriterT.wp_tell {m : TypeType v} {Pred EPred ω : Type} [Monad m] [Monoid ω] [Assertion Pred] [Assertion EPred] [WP m Pred EPred] (out : ω) (post : PUnit.{1}ωPred) (epost : EPred) :
    Lean.Order.PartialOrder.rel (fun (w : ω) => post PUnit.unit (w * out)) (wp (tell out) post epost)
    theorem Std.Do'.WriterT.wp_monadLift {m : TypeType v} {Pred EPred ω α : Type} [Monad m] [Monoid ω] [Assertion Pred] [Assertion EPred] [WP m Pred EPred] (x : m α) (post : αωPred) (epost : EPred) :
    Lean.Order.PartialOrder.rel (fun (w : ω) => wp x (fun (a : α) => post a w) epost) (wp (MonadLift.monadLift x) post epost)
    theorem Std.Do'.WriterT.wp_map {m : TypeType v} {Pred EPred ω α β : Type} [Monad m] [Monoid ω] [Assertion Pred] [Assertion EPred] [WP m Pred EPred] (f : αβ) (x : WriterT ω m α) (post : βωPred) (epost : EPred) :
    Lean.Order.PartialOrder.rel (wp x (fun (a : α) (w : ω) => post (f a) w) epost) (wp (f <$> x) post epost)
    theorem Std.Do'.Spec.tell_WriterT {m : TypeType v} {Pred EPred ω : Type} [Monad m] [Monoid ω] [Assertion Pred] [Assertion EPred] [WP m Pred EPred] (out : ω) (post : PUnit.{1}ωPred) (epost : EPred) :
    Triple (fun (w : ω) => post PUnit.unit (w * out)) (tell out) post epost
    theorem Std.Do'.Spec.monadLift_WriterT {m : TypeType v} {Pred EPred ω α : Type} [Monad m] [Monoid ω] [Assertion Pred] [Assertion EPred] [WP m Pred EPred] (x : m α) (post : αωPred) (epost : EPred) :
    Triple (fun (w : ω) => wp x (fun (a : α) => post a w) epost) (MonadLift.monadLift x) post epost
    theorem Std.Do'.Spec.mk_WriterT {m : TypeType v} {Pred EPred ω α : Type} [Monad m] [Monoid ω] [Assertion Pred] [Assertion EPred] [WP m Pred EPred] (x : m (α × ω)) (post : αωPred) (epost : EPred) :
    Triple (fun (w : ω) => wp x (fun (p : α × ω) => post p.1 (w * p.2)) epost) (WriterT.mk x) post epost
    @[simp]
    theorem OracleComp.ProgramLogic.Loom.WriterT.wp_bind {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {α β ω : Type} [Monoid ω] (x : WriterT ω (OracleComp spec) α) (f : αWriterT ω (OracleComp spec) β) (post : βωENNReal) :
    Std.Do'.wp (x >>= f) post Lean.Order.bot = fun (w : ω) => Std.Do'.wp x (fun (a : α) (w' : ω) => Std.Do'.wp (f a) post Lean.Order.bot w') Lean.Order.bot w
    @[simp]
    theorem OracleComp.ProgramLogic.Loom.WriterT.wp_pure {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {α ω : Type} [Monoid ω] (x : α) (post : αωENNReal) :
    Std.Do'.wp (pure x) post Lean.Order.bot = fun (w : ω) => post x w
    @[simp]
    theorem OracleComp.ProgramLogic.Loom.WriterT.wp_tell {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {ω : Type} [Monoid ω] (out : ω) (post : PUnit.{1}ωENNReal) :
    Std.Do'.wp (tell out) post Lean.Order.bot = fun (w : ω) => post PUnit.unit (w * out)
    @[simp]
    theorem OracleComp.ProgramLogic.Loom.WriterT.wp_monadLift {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {α ω : Type} [Monoid ω] (oa : OracleComp spec α) (post : αωENNReal) :
    Std.Do'.wp (MonadLift.monadLift oa) post Lean.Order.bot = fun (w : ω) => Std.Do'.wp oa (fun (a : α) => post a w) Lean.Order.bot
    @[simp]
    theorem OracleComp.ProgramLogic.Loom.WriterT.wp_map {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {α β ω : Type} [Monoid ω] (f : αβ) (x : WriterT ω (OracleComp spec) α) (post : βωENNReal) :
    Std.Do'.wp (f <$> x) post Lean.Order.bot = Std.Do'.wp x (fun (a : α) (w : ω) => post (f a) w) Lean.Order.bot
    theorem OracleComp.ProgramLogic.Loom.triple_iff_mAlgOrdered_triple {ι : Type u} {spec : OracleSpec ι} [spec.Fintype] [spec.Inhabited] {α : Type} (pre : ENNReal) (oa : OracleComp spec α) (post : αENNReal) :

    Std.Do'.Triple agrees with MAlgOrdered.Triple propositionally.

    Use as a forward iff: triple_iff_mAlgOrdered_triple.mp extracts pre ≤ MAlgOrdered.wp from a Std.Do'.Triple, and .mpr packages it back. The two are not definitionally equal because Std.Do'.Triple is an inductive wrapper rather than a def over .