Couplings #
This file defines couplings of sub-distributions and the lifting operation that is fundamental to probabilistic relational Hoare logic.
Main definitions #
Coupling d₁ d₂- A coupling of two sub-distributionsCoupling.satisfies- A coupling satisfies a relationliftR R d₁ d₂- Relation R lifts to distributions (there exists a coupling satisfying R)
Main results #
liftR_refl- Equality lifts to any distribution (diagonal coupling)liftR_mono- Lifting is monotone in the relationliftR_bind- Lifting composes through bind (key for bind rule)
References #
- Probabilistic couplings in verification
- SSProve: theories/Crypt/rhl_semantics/only_prob/Couplings.v
Coupling definition #
A coupling of two sub-distributions. The joint distribution has the correct marginals.
The joint distribution
Left marginal condition: projecting gives d₁
- right_marginal (b : β) : (self.joint.bind fun (p : α × β) => SDistr.pure p.2) (some b) = d₂ (some b)
Right marginal condition: projecting gives d₂
Instances For
If (a, b) has nonzero joint mass, then a has nonzero left marginal mass.
Proof: By the left marginal condition,
d₁ (some a) = ∑' b', joint (some (a, b')) (modulo encoding).
Since joint (some (a, b)) ≠ 0, the sum is nonzero.
Lifting relation to distributions #
Lifting: relation R lifts from values to distributions if there exists a coupling where all coupled pairs satisfy R.
Equations
- (d₁ ⟨R⟩# d₂) = ∃ (c : CatCrypt.Prob.Coupling d₁ d₂), c.satisfies R
Instances For
Notation for lifting
Equations
- One or more equations did not get rendered due to their size.
Instances For
Standard coupling constructions #
Diagonal/identity coupling: couple each element with itself
Equations
- CatCrypt.Prob.Coupling.diagonal d = { joint := d.bind fun (a : α) => CatCrypt.Prob.SDistr.pure (a, a), left_marginal := ⋯, right_marginal := ⋯ }
Instances For
Bijection coupling: couple a with f(a)
Equations
- CatCrypt.Prob.Coupling.fromBij d f = { joint := d.bind fun (a : α) => CatCrypt.Prob.SDistr.pure (a, f a), left_marginal := ⋯, right_marginal := ⋯ }
Instances For
Key lifting lemmas #
Marginal sum lemmas #
Product coupling: independent sampling. Requires both distributions to have mass 1 (i.e., no failure probability). For sub-distributions with mass < 1, the product joint has marginals that are scaled by the other distribution's mass.
Note: This coupling is not used in the main pRHL development, which uses
liftR_bind for composition instead.
Equations
- CatCrypt.Prob.Coupling.prod d₁ d₂ h₁ h₂ = { joint := d₁.bind fun (a : α) => d₂.bind fun (b : β) => CatCrypt.Prob.SDistr.pure (a, b), left_marginal := ⋯, right_marginal := ⋯ }
Instances For
If d₁ and d₂ are coupled by equality (diagonal coupling only), then they are equal as distributions. Key insight: equality coupling forces all mass to be on the diagonal, and marginal sums on the diagonal give the same values for both.
Helper: given a joint distribution, continuation coupling kd, and a marginal condition,
prove that projecting the composed joint gives the expected bound distribution.
This abstracts the shared proof structure used for both left and right marginals
in liftR_bind.
Composition through bind (THE KEY LEMMA for pRHL) This is the fundamental lemma that makes probabilistic relational Hoare logic work. The construction composes couplings:
- Sample (a, b) from the coupling of d₁ and d₂
- For each sampled pair, use the coupling from hf to get the continuation coupling
- The result is a coupling of the bound computations
The key challenge in the formal proof is that hf requires R a b, but we only
know R a b when c.joint (some (a, b)) ≠ 0. We use Classical.choice to pick
couplings for pairs outside the support (any choice works since they have zero measure).
Specialized lifting lemmas #
Lifting for pure/return
Lifting for fail: fail lifts with fail on any relation. This is the correct formulation for sub-distributions: the coupling joint = fail satisfies both marginal conditions.
Lifting for fail on left when d₂ = fail. For sub-distributions with joint = fail, the right marginal is 0, so d₂ must also have 0 probability on all some values.
Lifting for fail on right when d₁ = fail. For sub-distributions with joint = fail, the left marginal is 0, so d₁ must also have 0 probability on all some values.
Same uniform distribution lifts with equality