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.
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