pRHL, version 2 — the literal explicit-coupling judgment #
This module develops the candidate pRHL definition from CLAUDE.md
subtask 3 in its most literal form and shows it delivers the same rule
set as the existing ProgramDenotation.prhl (PRHL/Prhl.lean).
The difference from ProgramDenotation.prhl #
ProgramDenotation.prhl packages the coupling existential inside the ProgramDenotation.Coupling
structure, whose marginals are stated in expected-value form
(∀ F, μ.expected (F ∘ fst) = c.wp F σ₁) and whose support uses the
range form (∀ f vanishing on B, ∫ f dμ = 0).
ProgramDenotation.prhl2 instead spells out the existential directly, exactly as in
the subtask-3 text:
prhl2 A c d B := ∀ σ₁ σ₂, A σ₁ σ₂ →
∃ μ, map fst μ = c σ₁ ∧ map snd μ = d σ₂ ∧ satisfy μ B
with the marginals as distribution equality (map fst μ = c σ₁,
written μ >>= fun x => pure x.1 = c σ₁) and the support as the pointwise
SubProbability.satisfies (∀ x, μ {x} ≠ 0 → B x).
What this buys #
The two formulations are interderivable, so prhl2 inherits every rule:
ProgramDenotation.prhl.to_prhl2(forward) recovers the distribution-equality marginals viaCoupling.map_fst/map_snd, andsatisfies_of_rangeturns the range support into the pointwise one.ProgramDenotation.prhl2.to_prhl(backward) reads the pointwisesatisfiesback as the range form because the integral is the sum of its atoms (range_of_satisfies).
Originally the backward direction (and every rule consuming a coupling) carried a [Countable]
hypothesis: the atom-sum identity was lintegral_countable'. Since subtask 4 this is gone — the
SubProbability discreteness invariant gives the atom-sum (lintegral_eq_tsum_smul), the marginals
(discreteMeasure_measure_iUnion), and the sampling swap (lintegral_lintegral_swap_discrete) with
no countability of the carriers. So prhl2 and all its rules are now countability-free.
The judgment #
Literal coupling-based pRHL: the subtask-3 existential, with
marginals as distribution equality and support as the pointwise
SubProbability.satisfies.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Pushforward of expected along a deterministic map: integrating F
against map g μ is integrating F ∘ g against μ. The workhorse for
manipulating the literal map-marginals.
Discrete disintegration toolkit (for trans) #
Over countable carriers (the ⊤ σ-algebra) a SubProbability is determined
by its atom weights, and the integral is a countable sum of atoms. These
helpers let us build the glued coupling for transitivity as an explicit
atomic measure and reason about its marginals by tsum algebra.
An atomic sub-probability built from a summable weight function.
Equations
- GaudisCrypt.SubProbability.ofWeights w h = ⟨MeasureTheory.Measure.sum fun (t : T) => w t • MeasureTheory.Measure.dirac t, ⋯⟩
Instances For
A left-marginal atom is the sum of the joint atoms over the fiber. Countability-free
(subtask 4): discreteMeasure_measure_iUnion instead of measure_iUnion.
A right-marginal atom is the sum of the joint atoms over the fiber. Countability-free
(subtask 4): discreteMeasure_measure_iUnion instead of measure_iUnion.
The atom weights of a sub-probability sum to at most one. Countability-free (subtask 4):
∑' t, ν{t} = ν univ directly from the discreteness invariant at univ.
Bind algebra and fixed-point helpers (for while_loop) #
A lifted sampling unfolded at a state.
A lifted sampling threads the state unchanged: (sample; K) σ = μ >>= K(·,σ).
Commutativity of independent sampling (Tonelli): two state-free samplings can be drawn in either order.
Swap two independent (state-free) samplings in a program.
A bind whose continuation reads only the first coordinate factors through the first marginal.
A bind whose continuation reads only the second coordinate factors through the second marginal.
Two binds with continuations agreeing on the support are equal.
The integral against a least fixed point is the supremum of the integrals against the Kleene iterates (monotone convergence).
If every Kleene iterate is supported in B, so is the least fixed point.
Support of a bind: if each fibre is supported in B, so is the bind.
Monotone convergence for the program while_loop (curried fixed point).
Unfold one step of the while_iteration functional at a state.
Bridges to ProgramDenotation.prhl #
Forward bridge (unconditional): the structure-packaged judgment
yields the literal one. Marginals come from Coupling.map_fst/map_snd;
the pointwise support comes from the range support via
satisfies_of_range.
Backward bridge (discrete): the literal judgment yields the
structure-packaged one. The marginal equalities become the
expected-value marginals by integrating both sides; the pointwise
support becomes the range support via range_of_satisfies (countability-free
since subtask 4, via the discreteness invariant).
For discrete (countable) joint type the two formulations coincide.
Soundness with respect to the wp-lifting #
Every literal coupling judgment yields the two-sided wp-lifting
judgment (discrete); all relE elimination forms transfer.
Structural rules #
The leaves and the purely structural rules are unconditional; the seq rule inherits the discreteness hypothesis (see the module header).
Consequence — same witness, the support and precondition only weaken.
Reflexivity.
The rnd rule: uniform samples coupled along a bijection.
Existential in the precondition.
Disjunction in the precondition.
The seq rule (discrete). The composite coupling is built by
ProgramDenotation.prhl.bind; the discreteness hypotheses are what let the
pointwise-satisfies prefixes and continuations be reassembled.
Symmetry: a coupling is inherently two-sided — swap the joint
distribution coordinate-wise. The pointwise satisfies is propagated through the swap map (via
the range form), countability-free since subtask 4.
Read coupling: two gets relate when the read values (and unchanged
states) satisfy the post. Unconditional leaf.
Write coupling: two sets relate when the updated states satisfy the
post. Unconditional leaf.
Bounded-loop congruence: if the bodies preserve the invariant Inv
relationally, so do their n-fold iterates. Proved by induction on n
using prhl2.bind; covers the loops the crypto clients actually use
(oracle_loop_n). The unbounded while fixed point stays open.
Left footprint: strengthen the post with a left-side fact C that
holds almost surely for c (i.e. fails with probability 0). This is how
inRange-style unary facts enter the coupling logic. Discrete (the
support is rebalanced).
Right footprint: the mirror of strengthen_left, obtained by
symmetry.
Tier 2: one-sided/frame rules and rnd generalizations #
Left frame: a left-only prefix p₀ matched against skip on the
right (carrying Pre to Mid), then the continuations from Mid,
gives (p₀; k) ~ q. Avoids inserting pure () >>= on the right by
hand. Derived from bind + the monad law.
Right frame: the mirror of prefix_left.
Left ghost write: a left-only set L v matched against skip. The
coupling analogue of EquivModuloLens.set_equiv_pure. Unconditional
(both sides are point masses).
Right ghost write: the mirror of set_skip_left.
Synchronized sampling (rnd with the identity coupling): both runs
draw the same uniform value. The common special case of uniform.
Tier 3: transitivity by discrete disintegration #
Transitivity: compose a coupling of (p, q) with a coupling of
(q, r) into a coupling of (p, r), gluing along the shared middle
marginal q σ₂. The glued weight is
ν{(x,z)} = ∑ₘ μ₁{(x,m)}·μ₂{(m,z)} / q{m} — the discrete disintegration
(independent given the middle), with the middle weights cancelling in
each marginal. Countability-free since subtask 4 (the discreteness invariant).
Synchronized while rule (the coupling least fixed point). Under the
invariant the guards are coupled to agree (PostC records the invariant
refined by the guard value), the bodies preserve the invariant from
PostC true, and the loops relate at PostC false. The witness coupling
is Φ.lfp, the least fixed point of the coupling transformer that runs
the guard coupling and, while it fires, the body coupling.
Synchronized conditional (if): if the guards are coupled to
produce equal booleans (carrying Mid), and the branches are related
from Mid, then the conditionals are related.
Case split on a state predicate P.
General rnd: couple two samplings μ, ν along a function e
that pushes μ to ν (map e μ = ν); the post must hold for every
drawn a paired with e a. Subsumes uniform/uniform_id (take μ,
ν uniform and e a bijection).
Kill a lossless left-only statement: a lossless p₀ whose output
almost-surely satisfies the post (against the unchanged right state) is
related to skip. Generalizes set_skip_left from deterministic to any
lossless program.
Swap two independent samplings on the left program.
Swap two independent samplings on the right program.
One-sided rules (EasyCrypt if⟨i⟩, kill) #
One-sided if on the left (if⟨1⟩): a left conditional on a
deterministic state guard e, related to an arbitrary right program by
relating each branch under the refined precondition.
One-sided if on the right (if⟨2⟩).
Kill a lossless right-only statement (mirror of kill_left).
The adversary / call rule (EasyCrypt call (_ : ={glob A})) #
An adversary is a program confined to a state window L (a lens); glob A
is exactly this window. Running it from two states that agree on the window
returns equal results and states that again agree on the window —
={glob A} ⟹ ={res, glob A}. The coupling is the diagonal one through L:
run the inner program once and write its result back into both states.
Adversary call, constructive form: L.lift P (an adversary acting
through window L) from L-agreeing states gives equal results and
L-agreeing states.
Adversary call, abstract form: any A confined to the window L
(A.inFootprint L.footprint) satisfies the same rule, via the factorization
A = L.lift (L.factor A). This is the modular adversary principle.
Smoke tests #
Completeness (relE → prhl): the forward half, and the open step #
The converse of prhl2.to_relE — that the wp-lifting judgment yields a
coupling — is discrete Strassen (the coupling-lifting theorem). Its
only proofs go through max-flow–min-cut / LP-duality, none of which is in
Mathlib (no transportation feasibility, no fractional Hall, no
Birkhoff–von Neumann), so it would be a from-scratch standalone
formalization. It remains the single open step between the two logics.
What the wp judgment does give directly is the forward half:
plugging in indicator post-conditions turns rel into Hall's
marginal-domination condition. By the classical (discrete) Strassen
theorem this condition is also sufficient for a coupling — so this lemma
isolates exactly the combinatorial fact that is missing.
Hall's condition from rel (the necessary half of discrete
Strassen): the mass c places on any set A is dominated by the mass
d places on the Post-image of A. The converse (Hall ⇒ coupling)
is the open Strassen step.
For a two-sided relE, Hall's condition holds in both directions:
d's mass on B is dominated by c's mass on the Post-preimage of
B.
Scaling a sub-probability (for the mass-normalization reduction) #
Scale a sub-probability by c (well-defined as a sub-probability when
c · (total mass) ≤ 1).
Equations
- GaudisCrypt.SubProbability.scale c ν h = ⟨c • ↑ν, ⋯⟩
Instances For
Discrete Strassen / coupling lifting (axiom), probability-measure
form. This is Strassen's 1965 theorem verbatim: over countable
carriers, two probability measures satisfying Hall's marginal-
domination condition p(A) ≤ q(R(A)) admit a coupling with those
marginals supported on the relation. It is not available in Mathlib
(no max-flow–min-cut / fractional Hall / transportation feasibility),
so we take it as an axiom; SubProbability.exists_coupling_of_hall
below derives the sub-probability form from it by normalization, and
ProgramDenotation.rel.hall shows the hypothesis is exactly what relE supplies.
References (this is a true, classical theorem):
- V. Strassen, "The existence of probability measures with given marginals", Ann. Math. Statist. 36(2):423–439, 1965 — the general theorem. A countable discrete space is Polish and every relation on it is closed, so the 1965 result applies here directly. https://projecteuclid.org/euclid.aoms/1177700153
- T. Koperberg, "Couplings and Matchings: combinatorial notes on Strassen's theorem", Statist. Probab. Lett. (2024), arXiv:2202.02092 — the finite case in exactly this Hall form, shown equivalent to Hall's marriage theorem.
- Combinatorial proof: max-flow–min-cut / weighted Hall; see Lovász & Plummer, "Matching Theory" (1986).
- Use in coupling-based program logics (the
relE ↔ prhl2correspondence here): Barthe, Espitau, Grégoire, Hsu, Strub, "Probabilistic Couplings for Probabilistic Reasoning", arXiv:1710.09951.
Coupling lifting, sub-probability form — derived from the
probability-measure axiom exists_coupling_of_hall_prob by mass
normalization (no new assumption). Two-sided Hall forces equal total
mass; the zero-mass case is the empty coupling, and otherwise we
normalize both sides to probability measures, invoke the axiom, and
scale the resulting coupling back.
Completeness relE → prhl2 (discrete, modulo the Strassen axiom):
the wp-lifting judgment yields a coupling. The reduction is real — it
extracts Hall's condition in both directions from relE via
rel.hall and feeds it to exists_coupling_of_hall; only the
combinatorial coupling-existence step is assumed. Together with
prhl2.to_relE this shows the two logics coincide over countable
carriers.
The two relational logics coincide over countable carriers (discrete, modulo the Strassen axiom).
Footprint-confined adversary self-coupling #
A program confined to a Footprint R self-couples under ={glob} — from states agreeing on the
touched content it returns equal results and states again agreeing on the touched content. The
EqvGen-closure of a single deterministic Rᶜ-step, glued by coupling transitivity.
Adversary rule — single Rᶜ-step (footprint glob). A program confined to R, run from
a state σ and its image f σ under one deterministic Rᶜ-update, self-couples: equal
results, output states again one Rᶜ-step apart. This is the base case of the ={glob A}
adversary rule for glob A = R.touched_getter. The full rule is its EqvGen closure over the
Rᶜ-orbit.
Adversary rule (full), footprint glob. A program confined to R self-couples under
={glob A} (with glob A = R.touched_getter): from states agreeing on glob A it returns
equal results and states that again agree on glob A. The EqvGen-closure of
adversary_couple_step — refl/symm/trans on prhl2 (the trans = coupling gluing,
ProgramDenotation.prhl2.trans, discrete disintegration).
Coupling through a lossless, projection-preserving tail, over a base
coupling. Given a self-coupling of p under P with equal results and
g-equal finals, extending the right leg by a lossless tail c that
preserves g on its support couples p against q' = p; c (result kept)
with the same pre/post. The equal-initial-states version
(prhl2_of_lossless_tail_proj) is the instance at the diagonal coupling.
Coupling through a lossless, projection-preserving tail (equal initial
states): the diagonal instance of prhl2_of_lossless_tail_proj_inv.
Converts distribution-level transfer equations
(Lib/RO/TransferConvert.lean) into prhl2.
Coupling through a lossless tail. If q equals p followed by a lossless state-only
post-processor c (which keeps p's result), then p and q couple from equal initial
states with equal results: route the diagonal coupling of p through c on the right leg.
The projection-free instance of prhl2_of_lossless_tail_proj.