Pre-computing Results of Oracle Queries #
This file defines a function QueryImpl.withPregen that modifies a query implementation
to take in a list of pre-chosen outputs to use when answering queries.
Uses StateT so that consumed seed values are threaded to subsequent queries.
Note that ordering is subtle, for example so.withCaching.withPregen will first check for seeds
and not cache the result if one is found, while so.withPregen.withCaching checks the cache first,
and include seed values into the cache after returning them.
Modify a QueryImpl to check for pregenerated responses for oracle queries first.
If a seed value is available for the query, it is used and the seed is consumed (the tail
replaces the head). When no seed remains, falls back to the underlying implementation.
Instances For
Use pregenerated oracle responses for queries, falling back to the real oracle
when the seed is exhausted. Seed consumption is tracked via StateT.
Instances For
The probability that a lifted uniform sample equals a fixed value is (card α)⁻¹.
Adding a uniform value at index i to a seed does not change the distribution of
running a computation with the seeded oracle. This is because the extra value replaces
what would otherwise be a fresh uniform oracle response.
Truncating the seed at oracle i₀ to only the first k entries does not change
the distribution when averaging over seeds from generateSeed.
Weighted takeAtIndex faithfulness: a prefix-dependent weight h preserves the
faithfulness equality between full-seed and truncated-seed simulation.
This generalizes the basic takeAtIndex faithfulness by allowing multiplication
by an arbitrary function of the seed prefix σ.takeAtIndex i₀ k.
If a pre-generated seed already supplies all but residual t of the answers allowed by the
structural per-index query bound qb, then running oa against seededOracle can make at most
those residual live queries.
This theorem is the core replay-cost statement for seeded simulations: a large enough seed turns most oracle interactions into deterministic table lookups, leaving only the uncovered suffix of the computation as genuine oracle queries.
A seed that covers the full structural query bound eliminates all live oracle queries.
If the seed stores only the first k answers for oracle i, then the replay can make live
queries only to i, and at most qb i - k of them remain.
This is the structural query-bound form of the usual forking-lemma intuition: after rewinding to
the k-th query to oracle i, every earlier answer is fixed by the prefix seed, so only the
suffix after the fork point can still hit the live oracle.
After rewinding to query index s and appending one fresh answer at oracle i, the replayed
run can still make live queries only to i, with at most qb i - (s + 1) such queries left.