Simulation Semantics for Oracles in a Computation #
This file defines a type SimOracle spec specₜ σ
to represent a way to simulate
oracles in spec
using the oracles in specₜ
, maintaining some state of type σ
.
We then define a function simulate so oa s
to simulate the computation oa
using so
to answer oracle queries, with initial state s
.
We mark lemmas regarding simulating specific computations as @[simp low]
,
so that lemmas specific to certain simulation oracles get applied firts.
For example idOracle
has no effect upon simulation, and we should apply that fact first.
Specifies a way to simulate a set of oracles using another set of oracles.
e.g. using uniform selection oracles with a query cache to simulate a random oracle.
simulateQ
gives a method for applying a simulation oracle to a specific computation.
Instances For
Equations
- QueryImpl.Inhabited = { default := { impl := fun {α : Type ?u.44} (q : spec.OracleQuery α) => pure q.defaultOutput } }
Canonical lifting of a function OracleQuery spec α → m α
to a new function OracleComp spec α
by preserving bind
, pure
, and failure
.
NOTE: could change the output type to OracleComp spec →ᵐ m
, makes some stuff below free
Equations
- OracleComp.simulateQ so oa = do let __do_lift ← (OptionT.run oa).mapM fun {α : Type ?u.11} => so.impl __do_lift.getM
Instances For
Simulate a computation using the original oracles by "replacing" queries with queries.
This operates as an actual identity for simulate'
, in that we get an exact equality
between the new and original computation.
This can be useful especially with SimOracle.append
, in order to simulate a single oracle
in a larger set of oracles, leaving the behavior of other oracles unchanged.
The relevant spec can usually be inferred automatically, so we leave it implicit.
Equations
- idOracle = { impl := fun {α : Type ?u.20} (q : spec.OracleQuery α) => OracleComp.lift q }
Instances For
Simulate a computation by having each oracle return the default value of the query output type for all queries. This gives a way to run arbitrary computations to get some output. Mostly useful in some existence proofs, not usually used in an actual implementation.
Equations
- defaultOracle = { impl := fun {α : Type ?u.30} (x : spec.OracleQuery α) => let q := x; pure q.defaultOutput }