Deciding acceptance under a time bound #
The first half of obligation O2 (blueprint rem:compression-abstract, item 3): the
acceptance table of the tabulated game. Filling it in needs Decider.Accepts — a Σ₁
statement, ∃ t, prog.Runs … — to be decided, and that is exactly what n-boundedness
buys: the bound supplies a budget within which the decider must halt, so one budgeted run
settles the question (Machine.runForD).
Decider.acceptBudget: the budgetT · (|d| + 1) ^ kthe bound gives at indexnon the tuple(x, y, a, b), read off the shape ofDecider.TimeBoundAt.Decider.accepts_iff_runForD: for a decider obeying that bound, acceptance is one budgeted run returningencode true.Decider.decidableAcceptsandVerifier.decidableAccepts: the resulting decision procedures, andVerifier.accepts_iff_runForDfor the verifier a string denotes, where the bound comes fromVerifier.IsBounded.
The other half of the tabulation is the question distribution, and the rest of this file is
what a GameData needs for it. CL.Sampler.queryUnder runs one sampler query under the same
kind of budget; Verifier.bitsToIdx turns the bit string a query returns into the number a
GameData names its questions by, and agrees with Verifier.questionEquiv; and
Verifier.weightList is the weight list itself — one entry of weight 1 for each point of
𝔽₂^{s(n)}, at the index pair its two marginals land on. Its questionWeight is then the
number of points landing on a given pair and its totalWeight is 2 ^ s(n), which is exactly
the quotient CL.clDist is: length_filter_bitStrsOfLen is the bridge, the bit strings of
length s being the vectors of 𝔽₂^s.
Verifier.answerEquiv_symm_val is the same service on the answer side: an answer's index is
its position among the bit strings of length at most T, the enumeration answerList being
bitStrsLE mapped by a truncation that is the identity on them.
Verifier.accListW is then the acceptance table: the index tuples of the answer tuples a
predicate accepts, enumerated over the two alphabets, with mem_accListW_iff saying exactly
what is in it. It takes the two question indexings fA, fB as parameters, because the
tabulation tags Alice's question differently from Bob's; Verifier.accList is the case
fA = fB = bitsToIdx and is the same list definitionally, so nothing
downstream of the old name changed. bitsToIdx_injOn is what lets a tuple be read back — the
index of a question determines it, among the strings of a fixed length — and tagEquiv is the
tagged alphabet it supports: a tag bit and a point of 𝔽₂^s packed into one index by
prepending the tag, so that bitsToIdx_lt and bitsToIdx_injOn apply verbatim at s + 1.
MIPRE.Halting.tabOf at the end assembles all of it: the GameData two encoded programs and
five numbers describe, with primrec_tabOf its computability. Plain data and not a verifier,
because a Verifier is a structure carrying proofs and so is not the sort of thing a Primrec
statement can mention; the bridge back to the verifier those parameters came from is in
Halting/Instantiation.lean.
Nothing here is efficient and nothing needs to be: the tabulation is a computable map, not a
polynomial-time one. The budget is not one number: the two sampler runs take theirs as the
parameters B, k, so that a caller can pass the sampler's own time bound, while accOf
alone runs at the n ^ n that the verifier's n-boundedness supplies.
The budget the time bound TimeBoundAt n T k gives on the tuple (x, y, a, b): the
decider's input is cons (encode n) (encode (x, y, a, b)), and the bound is T times the
k-th power of one more than the size of the second component.
Equations
Instances For
Acceptance under a time bound is one budgeted run.
Hence acceptance is decidable, for a decider that obeys a time bound at the index.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Acceptance by an n-bounded verifier is one budgeted run, at the budget its own
λ-boundedness supplies. This is what fills in the acceptance table of the tabulation.
Hence acceptance by an n-bounded verifier is decidable.
Equations
- V.decidableAccepts hb hn x y a b = V.decider.decidableAccepts ⋯ x y a b
Instances For
Sampler queries under the budget #
One query to the sampler, run under the budget its time bound supplies. The sampler is
required to halt on every input of the form (n, …), so this is total wherever the bound
holds.
Equations
- S.queryUnder T k n q = MIPRE.Cost.Machine.runForD (MIPRE.Cost.encode S.prog) (MIPRE.Cost.encode (n, q)) (T * ((MIPRE.Cost.encode q).size + 1) ^ k)
Instances For
Under the bound, a budgeted query returns exactly what the sampler's correctness clauses say it returns.
The dimension query.
The marginal at the top level is the CL function itself (CLFun.truncate_self), so one
budgeted marginal query at level ℓ computes L^w(z) — which is what the question weights
of the tabulated game are counted from.
A marginal query with the player and the level fixed is a primitive recursive function of
the point queried: a query is its tuple, encoded, and marginal w j z is (1, w, j, z, []),
so with w and j literal only encode z varies.
Questions as numbers #
The index of a bit string: the number whose binary digits it is, least significant first.
This is the ℕ-level form of Verifier.questionEquiv, and it is what the tabulation can
actually compute with — the question alphabet of a GameData is Fin (nX + 1), so every
question reached by a sampler query has to be turned into a number.
Equations
- MIPRE.Verifier.bitsToIdx [] = 0
- MIPRE.Verifier.bitsToIdx (b :: l) = (if b = true then 1 else 0) + 2 * MIPRE.Verifier.bitsToIdx l
Instances For
The Fin 2 form, where finFunctionFinEquiv is literally applicable: CL.𝔽₂ is ZMod 2,
which reduces to Fin 2 but does not unify with it at the transparency rw uses.
The index of a question is the number its bit string denotes. This is what lets the
tabulation name questions by numbers while the value agreement is read along
questionEquiv.
The question weights #
The index of a bit string is below 2 ^ its length.
The weight list of a tabulation: one entry of weight 1 for each point of 𝔽₂^s, at
the index pair its two marginals land on.
Equations
- MIPRE.Verifier.weightList s fA fB = List.map (fun (z : MIPRE.Cost.BitStr) => (fA z, fB z, 1)) (MIPRE.Cost.Data.bitStrsOfLen s)
Instances For
Every point of 𝔽₂^s is counted once, so the total weight is 2 ^ s.
The total weight of the list is 2 ^ s: every point of 𝔽₂^s contributes 1, and the
index pairs it can land on are all in range. That denominator is exactly the one CL.clDist
divides by.
Counting over 𝔽₂^s by enumerating bit strings. The bit strings of length s are the
vectors of 𝔽₂^s, so a count over one is a count over the other — which is what turns the
tabulation's weight list into the numerator of CL.clDist.
Answers as numbers #
The answers of length at most T are indexed by their position among the bit strings of
length at most T: the enumeration answerList is bitStrsLE mapped by truncation, which is
the identity on those strings.
The acceptance table #
bitsToIdx is injective on the bit strings of a fixed length: it is the binary expansion,
read through questionEquiv.
The doubled question alphabet, indexed #
A question of the doubled game is a tag bit and a point of 𝔽₂^s. It is packed into one
number by prepending the tag bit to the point's bit string: the index of (b, v) is
bitsToIdx (b :: CL.toBits v). Three things this packing buys, and they are the reason for
it:
- the packed index is
bitsToIdxof a bit string of lengths + 1, sobitsToIdx_ltbounds it by2 ^ (s + 1)andbitsToIdx_injOn— injectivity on strings of a fixed length — reads it back, both verbatim ats + 1; - Alice's indices are even and Bob's odd, so the two copies are automatically disjoint;
- nothing else in the tabulation changes: the weight list still enumerates
𝔽₂^s.
CL.toBits is injective: it is the binary expansion read by questionEquiv.
The packing is injective, componentwise. This is bitsToIdx_injOn at length s + 1,
which is why the tag is prepended rather than appended or added as an offset.
The packed index of a tagged question.
Equations
- MIPRE.Verifier.tagIdx p = ⟨MIPRE.Verifier.bitsToIdx (p.1 :: MIPRE.CL.toBits p.2), ⋯⟩
Instances For
The doubled question alphabet.
Equations
Instances For
The acceptance table: the index tuples of the answer tuples a predicate accepts, enumerated over the two alphabets.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The acceptance table is primitive recursive #
Written as four nested Primrec.list_flatMap the proof diverges at whnf: each body carries
the accumulated parameter tuple and unification grows with it. Flattening the product first
makes every flatMap body a bare tuple constructor, and the table is then one filterMap over
the flat list (accList_eq_filterMap) — with Verifier.accList itself unchanged.
The four-fold product of the two enumerations, as one flat list.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Prepending a fixed tag bit is primitive recursive.
The tabulation on parameters alone #
tabOf sd pd s T B k n is the GameData seven parameters describe: sd the encoded sampler
program, pd the encoded decider program, s the sampler's dimension at level n, T the
answer-length cut, B and k the coefficient and the degree of the budget the two sampler
runs get, and n the level itself. Nothing here mentions a Verifier, and that is
the point — a Verifier is a structure carrying proofs, so a function of one is not data,
while Primrec needs its input to be. The bridge back, that these parameters compute the
verifier's own sampler and decider, is MIPRE.Halting.dimOf_eq, margOf_eq and accOf_iff
in Halting/Instantiation.lean — the first two at every string and every level, the third on
an n-bounded verifier.
The three components each run one program under a budget, and the budgets differ: dimOf and
margOf one sampler query each (CL.Sampler.queryUnder at the B * (|q| + 1) ^ k passed in,
which the caller takes from the sampler's own time bound), accOf one decider run
(Decider.acceptBudget at T = n ^ n, k = n, the budget n-boundedness supplies — see
accOf, which cannot be re-budgeted and says why). Each defaults — to 0, [], false — when
the budget is missed or the answer does not decode, which is what makes them total; where the
budget is the right one the default is never taken.
The questions are doubled: Alice's index is her marginal's bit string with a false tag
prepended, Bob's with a true tag, so nX + 1 = 2 ^ (s + 1) and the acceptance table is
Verifier.accListW at those two indexings rather than accList. The packing is the section
"The doubled question alphabet, indexed" above; why the doubling is needed at all is in
Foundations/GameDouble.lean.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Player w's marginal question at the point z, under the budget B * (|q| + 1) ^ k.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Acceptance, from the encoded decider program alone. Unlike the two sampler runs this one
cannot be re-budgeted off GapCompression.sampler_time: the decider of the verifier a string
denotes is the string's own, wrapped, and nothing bounds it unconditionally. So accOf keeps
the budget n-boundedness supplies, and MIPRE.Halting.accOf_iff keeps its hypothesis.
decide (… = some …) rather than … == some …: the BEq a == elaborates to here is not the
one Primrec.eq is stated at, and reconciling them is a long detour for no gain.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The tabulation, doubled and re-budgeted. Alice's question index is her marginal's bit
string with a false tag prepended, Bob's with a true tag: the two blocks are disjoint and
the diagonal carries no weight. The weight list still enumerates 𝔽₂^s once, so the total
weight is still 2 ^ s.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The weight list of the doubled, re-budgeted tabulation. Verifier.weightList itself is
untouched: only the two index maps it is applied to have changed.
primrec_accOf, generic in the ambient parameter type. accOf reads only the decider
data and the level, so the shape of the tuple carrying them is irrelevant. Stating it this way
is what makes the re-budget cheap: a change to tabOf's parameter list never re-runs this
proof, which measures 210049 heartbeats at one fixed tuple, and composing it with a projection
to reach a wider one times out at the default budget.
O2, computability, on numbers alone: the doubled, re-budgeted tabulation is primitive recursive in every one of its parameters.