Documentation

VCVio.OracleComp.SimSemantics.Append

Append/Add Operation for Simulation Oracles #

def QueryImpl.add {ι₁ : Type u_4} {ι₂ : Type u_5} {spec₁ : OracleSpec ι₁} {spec₂ : OracleSpec ι₂} {m : Type u → Type u_1} (impl₁ : QueryImpl spec₁ m) (impl₂ : QueryImpl spec₂ m) :
QueryImpl (spec₁ + spec₂) m

Simplest version of adding queries when all implementations are in the same monad. The actual add notation for QueryImpl uses QueryImpl.addLift which adds monad lifting to this definition for greater flexibility.

Instances For
    @[implicit_reducible]
    instance QueryImpl.instHAddSumHAddOracleSpec {ι₁ : Type u_4} {ι₂ : Type u_5} {spec₁ : OracleSpec ι₁} {spec₂ : OracleSpec ι₂} {m : Type u → Type u_1} :
    HAdd (QueryImpl spec₁ m) (QueryImpl spec₂ m) (QueryImpl (spec₁ + spec₂) m)

    Add two QueryImpl to get an implementation on the sum of the two OracleSpec.

    theorem QueryImpl.add_apply {ι₁ : Type u_4} {ι₂ : Type u_5} {spec₁ : OracleSpec ι₁} {spec₂ : OracleSpec ι₂} {m : Type u → Type u_1} (impl₁ : QueryImpl spec₁ m) (impl₂ : QueryImpl spec₂ m) (t : (spec₁ + spec₂).Domain) :
    (impl₁ + impl₂) t = match t with | Sum.inl t => impl₁ t | Sum.inr t => impl₂ t
    @[simp]
    theorem QueryImpl.add_apply_inl {ι₁ : Type u_4} {ι₂ : Type u_5} {spec₁ : OracleSpec ι₁} {spec₂ : OracleSpec ι₂} {m : Type u → Type u_1} (impl₁ : QueryImpl spec₁ m) (impl₂ : QueryImpl spec₂ m) (t : spec₁.Domain) :
    (impl₁ + impl₂) (Sum.inl t) = impl₁ t
    @[simp]
    theorem QueryImpl.add_apply_inr {ι₁ : Type u_4} {ι₂ : Type u_5} {spec₁ : OracleSpec ι₁} {spec₂ : OracleSpec ι₂} {m : Type u → Type u_1} (impl₁ : QueryImpl spec₁ m) (impl₂ : QueryImpl spec₂ m) (t : spec₂.Domain) :
    (impl₁ + impl₂) (Sum.inr t) = impl₂ t
    def QueryImpl.addLift {ι₁ : Type u_7} {ι₂ : Type u_8} {spec₁ : OracleSpec ι₁} {spec₂ : OracleSpec ι₂} {m : Type u → Type u_4} {n : Type u → Type u_5} {r : Type u → Type u_6} [MonadLiftT m r] [MonadLiftT n r] (impl₁ : QueryImpl spec₁ m) (impl₂ : QueryImpl spec₂ n) :
    QueryImpl (spec₁ + spec₂) r

    Version of QueryImpl.add that also lifts the two implementations to a shared lift monad.

    Instances For
      @[simp]
      theorem QueryImpl.addLift_def {ι₁ : Type u_7} {ι₂ : Type u_8} {spec₁ : OracleSpec ι₁} {spec₂ : OracleSpec ι₂} {m : Type u → Type u_4} {n : Type u → Type u_5} {r : Type u → Type u_6} [MonadLiftT m r] [MonadLiftT n r] (impl₁ : QueryImpl spec₁ m) (impl₂ : QueryImpl spec₂ n) :
      impl₁.addLift impl₂ = liftTarget r impl₁ + liftTarget r impl₂
      @[simp]
      theorem QueryImpl.simulateQ_add_liftComp_left {ι₁' ι₂' : Type} {spec₁' : OracleSpec ι₁'} {spec₂' : OracleSpec ι₂'} {α : Type} {m' : TypeType v} [Monad m'] [LawfulMonad m'] (impl₁' : QueryImpl spec₁' m') (impl₂' : QueryImpl spec₂' m') (oa : OracleComp spec₁' α) :
      simulateQ (impl₁' + impl₂') (oa.liftComp (spec₁' + spec₂')) = simulateQ impl₁' oa
      @[simp]
      theorem QueryImpl.simulateQ_add_liftComp_right {ι₁' ι₂' : Type} {spec₁' : OracleSpec ι₁'} {spec₂' : OracleSpec ι₂'} {α : Type} {m' : TypeType v} [Monad m'] [LawfulMonad m'] (impl₁' : QueryImpl spec₁' m') (impl₂' : QueryImpl spec₂' m') (ob : OracleComp spec₂' α) :
      simulateQ (impl₁' + impl₂') (ob.liftComp (spec₁' + spec₂')) = simulateQ impl₂' ob
      theorem QueryImpl.simulateQ_add_liftM_left {ι₁' ι₂' : Type} {spec₁' : OracleSpec ι₁'} {spec₂' : OracleSpec ι₂'} {α : Type} {m' : TypeType v} [Monad m'] [LawfulMonad m'] (impl₁' : QueryImpl spec₁' m') (impl₂' : QueryImpl spec₂' m') (oa : OracleComp spec₁' α) :
      simulateQ (impl₁' + impl₂') (liftM oa) = simulateQ impl₁' oa

      liftM-normal-form companion of simulateQ_add_liftComp_left. Because liftComp_eq_liftM normalizes liftComp → liftM under simp, the liftComp-keyed lemma never fires inside simp; this liftM-keyed form is what simp actually needs.

      Deliberately not @[simp]: as a global rule it shifts the normal form of simulateQ over an added handler applied to a lifted-in computation, which pre-empts and breaks existing proofs that manage that reduction themselves. Pass it explicitly, e.g. simp [myHandler, simulateQ_add_liftM_left, simulateQ_toQueryImpl].

      theorem QueryImpl.simulateQ_add_liftM_right {ι₁' ι₂' : Type} {spec₁' : OracleSpec ι₁'} {spec₂' : OracleSpec ι₂'} {α : Type} {m' : TypeType v} [Monad m'] [LawfulMonad m'] (impl₁' : QueryImpl spec₁' m') (impl₂' : QueryImpl spec₂' m') (ob : OracleComp spec₂' α) :
      simulateQ (impl₁' + impl₂') (liftM ob) = simulateQ impl₂' ob

      liftM-normal-form companion of simulateQ_add_liftComp_right; opt-in, see simulateQ_add_liftM_left.

      theorem QueryImpl.simulateQ_liftComp_left_eq_of_apply {ι₁' ι₂' : Type} {spec₁' : OracleSpec ι₁'} {spec₂' : OracleSpec ι₂'} {α : Type} {m' : TypeType v} [Monad m'] [LawfulMonad m'] (impl : QueryImpl (spec₁' + spec₂') m') (impl₁ : QueryImpl spec₁' m') (h : ∀ (t : ι₁'), impl (Sum.inl t) = impl₁ t) (oa : OracleComp spec₁' α) :
      simulateQ impl (oa.liftComp (spec₁' + spec₂')) = simulateQ impl₁ oa
      theorem QueryImpl.simulateQ_liftComp_right_eq_of_apply {ι₁' ι₂' : Type} {spec₁' : OracleSpec ι₁'} {spec₂' : OracleSpec ι₂'} {α : Type} {m' : TypeType v} [Monad m'] [LawfulMonad m'] (impl : QueryImpl (spec₁' + spec₂') m') (impl₂ : QueryImpl spec₂' m') (h : ∀ (t : ι₂'), impl (Sum.inr t) = impl₂ t) (oa : OracleComp spec₂' α) :
      simulateQ impl (oa.liftComp (spec₁' + spec₂')) = simulateQ impl₂ oa
      theorem QueryImpl.simulateQ_toQueryImpl {ι : Type u_4} {spec : OracleSpec ι} {α : Type u} (mx : OracleComp spec α) :

      Simulating the trivial HasQuery.toQueryImpl handler back into OracleComp spec is the identity (the composite of HasQuery.toQueryImpl_eq_id' and simulateQ_id').

      Like toQueryImpl_eq_id', this is deliberately not @[simp]: globally it lets simulateQ of a unifFwdImpl-style toQueryImpl.liftTarget handler fully reduce, which can re-enable a backward induction-hypothesis rewrite and diverge. Pass it explicitly to simp (alongside the opaque handler definition) to discharge a lifted-in computation, e.g. simp [myHandler, simulateQ_toQueryImpl]; the simulateQ_add_liftM_left/_right and simulateQ_liftTarget rungs are @[simp] and fire on their own.

      theorem QueryImpl.simulateQ_liftM_eq_of_query {ι₁' ι₂' : Type} {spec₁' : OracleSpec ι₁'} {spec₂' : OracleSpec ι₂'} {α : Type} {m' : TypeType v} [Monad m'] [LawfulMonad m'] [MonadLiftT (OracleComp spec₁') (OracleComp spec₂')] [LawfulMonadLiftT (OracleComp spec₁') (OracleComp spec₂')] (impl : QueryImpl spec₂' m') (impl₁ : QueryImpl spec₁' m') (h : ∀ (t : ι₁'), simulateQ impl (liftM (liftM (OracleSpec.query t))) = impl₁ t) (oa : OracleComp spec₁' α) :
      simulateQ impl (liftM oa) = simulateQ impl₁ oa

      Query routing through a right-nested sum implementation #

      Routing lemmas for the spec + (spec₁ + spec₂) layout used by stateless protocol simulation oracles (e.g. a base spec plus a pair of message/statement oracle families, the simOracle2 layout): a single query lifted from one component — either at the query level (OracleQuery) or pre-embedded in its own computation monad (OracleComp, the shape produced by reusable query helpers) — resolves under simulateQ to the implementation at the routed index.

      Each left-hand side spells the canonical MonadLiftT chain that typeclass resolution synthesizes for that lift (through the intermediate spec + spec₂ etc.), which is what lets these fire by simp on goals produced by elaborated protocol definitions. All six are definitional modulo simulateQ_spec_query: the show … from rfl bridges re-express the chained lift as the canonical embedded query at the routed index.

      @[simp]
      theorem QueryImpl.simulateQ_add_add_liftM_query_base {ι' ι₁' ι₂' : Type} {spec : OracleSpec ι'} {spec₁ : OracleSpec ι₁'} {spec₂ : OracleSpec ι₂'} {m' : TypeType v} [Monad m'] [LawfulMonad m'] (implA : QueryImpl spec m') (implB : QueryImpl (spec₁ + spec₂) m') (t : spec.Domain) :
      simulateQ (implA + implB) (liftM (OracleSpec.query t)) = implA t
      @[simp]
      theorem QueryImpl.simulateQ_add_add_liftM_query_left {ι' ι₁' ι₂' : Type} {spec : OracleSpec ι'} {spec₁ : OracleSpec ι₁'} {spec₂ : OracleSpec ι₂'} {m' : TypeType v} [Monad m'] [LawfulMonad m'] (implA : QueryImpl spec m') (implB : QueryImpl (spec₁ + spec₂) m') (t : spec₁.Domain) :
      simulateQ (implA + implB) (liftM (OracleSpec.query t)) = implB (Sum.inl t)
      @[simp]
      theorem QueryImpl.simulateQ_add_add_liftM_query_right {ι' ι₁' ι₂' : Type} {spec : OracleSpec ι'} {spec₁ : OracleSpec ι₁'} {spec₂ : OracleSpec ι₂'} {m' : TypeType v} [Monad m'] [LawfulMonad m'] (implA : QueryImpl spec m') (implB : QueryImpl (spec₁ + spec₂) m') (t : spec₂.Domain) :
      simulateQ (implA + implB) (liftM (OracleSpec.query t)) = implB (Sum.inr t)
      @[simp]
      theorem QueryImpl.simulateQ_add_add_liftM_comp_base {ι' ι₁' ι₂' : Type} {spec : OracleSpec ι'} {spec₁ : OracleSpec ι₁'} {spec₂ : OracleSpec ι₂'} {m' : TypeType v} [Monad m'] [LawfulMonad m'] (implA : QueryImpl spec m') (implB : QueryImpl (spec₁ + spec₂) m') (t : spec.Domain) :
      simulateQ (implA + implB) (liftM (liftM (OracleSpec.query t))) = implA t
      @[simp]
      theorem QueryImpl.simulateQ_add_add_liftM_comp_left {ι' ι₁' ι₂' : Type} {spec : OracleSpec ι'} {spec₁ : OracleSpec ι₁'} {spec₂ : OracleSpec ι₂'} {m' : TypeType v} [Monad m'] [LawfulMonad m'] (implA : QueryImpl spec m') (implB : QueryImpl (spec₁ + spec₂) m') (t : spec₁.Domain) :
      simulateQ (implA + implB) (liftM (liftM (OracleSpec.query t))) = implB (Sum.inl t)
      @[simp]
      theorem QueryImpl.simulateQ_add_add_liftM_comp_right {ι' ι₁' ι₂' : Type} {spec : OracleSpec ι'} {spec₁ : OracleSpec ι₁'} {spec₂ : OracleSpec ι₂'} {m' : TypeType v} [Monad m'] [LawfulMonad m'] (implA : QueryImpl spec m') (implB : QueryImpl (spec₁ + spec₂) m') (t : spec₂.Domain) :
      simulateQ (implA + implB) (liftM (liftM (OracleSpec.query t))) = implB (Sum.inr t)

      Unit tests: a query lifted from a component of a sum spec routes through a sum implementation by simp alone, via the simulateQ_add_add_liftM_* routing lemmas. The shape spec + (spec₁ + spec₂) with an addLifted pair is the simOracle2 layout used by oracle-reduction verifiers downstream.

      theorem simulateQ_addLift_add_liftM_left {ι ι₁ ι₂ : Type} {spec : OracleSpec ι} {spec₁ : OracleSpec ι₁} {spec₂ : OracleSpec ι₂} {m : TypeType} [Monad m] [LawfulMonad m] {m₀ : TypeType} [MonadLiftT m₀ m] {n : TypeType} [Monad n] [LawfulMonad n] [MonadLiftT n m] [LawfulMonadLiftT n m] (impl : QueryImpl spec m₀) (impl₁ : QueryImpl spec₁ n) (impl₂ : QueryImpl spec₂ n) {α : Type} (x : OracleComp spec₁ α) :
      simulateQ (impl.addLift (impl₁.add impl₂)) (liftM (liftM x)) = liftM (simulateQ impl₁ x)

      Resolve a simulateQ over a three-way addLift impl (impl₁ + impl₂) applied to a computation x : OracleComp spec₁ α that has been double-liftM'd — first into the inner sum spec₁ + spec₂, then into the outer sum spec + (spec₁ + spec₂). The query routes to the left inner implementation impl₁, leaving liftM (simulateQ impl₁ x).

      This is the computation-level sibling of QueryImpl.simulateQ_add_add_liftM_comp_left: it peels the outer addLift (simulateQ_add_liftComp_right), commutes the inner simulateQ past the target lift (simulateQ_liftTarget), then peels the inner sum (simulateQ_add_liftComp_left). Stated for the inner pair living in a possibly-different monad n lifted into the target m.

      theorem simulateQ_addLift_add_liftM_right {ι ι₁ ι₂ : Type} {spec : OracleSpec ι} {spec₁ : OracleSpec ι₁} {spec₂ : OracleSpec ι₂} {m : TypeType} [Monad m] [LawfulMonad m] {m₀ : TypeType} [MonadLiftT m₀ m] {n : TypeType} [Monad n] [LawfulMonad n] [MonadLiftT n m] [LawfulMonadLiftT n m] (impl : QueryImpl spec m₀) (impl₁ : QueryImpl spec₁ n) (impl₂ : QueryImpl spec₂ n) {α : Type} (x : OracleComp spec₂ α) :
      simulateQ (impl.addLift (impl₁.add impl₂)) (liftM (liftM x)) = liftM (simulateQ impl₂ x)

      Resolve a simulateQ over a three-way addLift impl (impl₁ + impl₂) applied to a computation x : OracleComp spec₂ α that has been double-liftM'd — first into the inner sum spec₁ + spec₂, then into the outer sum spec + (spec₁ + spec₂). The query routes to the right inner implementation impl₂, leaving liftM (simulateQ impl₂ x).

      The right companion of simulateQ_addLift_add_liftM_left.

      theorem simulateQ_optionT_liftM_run_eq_of_query {ι₁' ι₂' : Type} {spec₁' : OracleSpec ι₁'} {spec₂' : OracleSpec ι₂'} {α : Type} {m' : TypeType} [Monad m'] [LawfulMonad m'] [MonadLiftT (OracleComp spec₁') (OracleComp spec₂')] [LawfulMonadLiftT (OracleComp spec₁') (OracleComp spec₂')] (impl : QueryImpl spec₂' m') (impl₁ : QueryImpl spec₁' m') (h : ∀ (t : ι₁'), simulateQ impl (liftM (liftM (OracleSpec.query t))) = impl₁ t) (oa : OracleComp spec₁' α) :
      simulateQ impl (liftM oa) = some <$> simulateQ impl₁ oa

      OptionT companion to QueryImpl.simulateQ_liftM_eq_of_query: simulating an OracleComp-computation oa lifted into OptionT (OracleComp spec₂') (the shape produced by an OptionT-monadic verifier's let _ ← liftM (queryHelper) binds) agrees, at the run (Option) level, with some-mapping the simulation of oa through a per-query-bridged handler impl₁.

      The key step is that the OptionT.run of a lifted OracleComp is some <$> (the OracleComp lift) definitionally (hrun below is rfl), which collapses the OptionT lift chain to a plain OracleComp lift; the chain-agnostic QueryImpl.simulateQ_liftM_eq_of_query then resolves it.