Losslessness for Stateful Probabilistic Computations #
This file defines the isLossless predicate for SPComp computations and proves
that basic operations (pure, get, set, sample) are lossless, while fail is not.
A computation is lossless if it has total mass 1 from any initial heap, meaning
it never fails (never produces the none outcome in the underlying sub-distribution).
Main definitions #
isLossless- Unconditional losslessness: mass 1 from every heapisLosslessIf- Conditional losslessness: mass 1 from heaps satisfying a precondition
Main results #
lossless_pure-pure ais losslesslossless_get-get lis losslesslossless_set-set l vis losslesslossless_sample-sample αis lossless (for finite nonempty types)not_lossless_fail-failis not losslesslossless_bind- bind preserves losslessness
References #
- EasyCrypt:
islosslesspredicate on distributions - SSProve (Rocq): lossless reasoning in pHL
Losslessness predicates #
A computation is lossless if it has total mass 1 from any initial heap. This means the computation never fails.
Equations
- CatCrypt.Unary.isLossless c = ∀ (h : CatCrypt.Core.Heap), (c h).mass = 1
Instances For
Lossless with precondition: only requires mass 1 from heaps satisfying P.
Equations
- CatCrypt.Unary.isLosslessIf P c = ∀ (h : CatCrypt.Core.Heap), P h → (c h).mass = 1
Instances For
Relationship between isLossless and isLosslessIf #
Unconditional losslessness implies conditional losslessness for any P.
Conditional losslessness with truePre is equivalent to unconditional.
Losslessness of basic operations #
pure a is lossless: returning a value never fails.
get l is lossless: reading from a location never fails.
set l v is lossless: writing to a location never fails.
fail is not lossless: it always fails (mass 0).
The mass of fail is 0, as an explicit lemma for use in proofs.
Helper lemmas for mass reasoning #
Losslessness of sample #
sample α is lossless: sampling from a finite nonempty type never fails.
Losslessness of bind #
Bind preserves losslessness: if c is lossless and f a is lossless for all a,
then c.bind f is lossless.
Proof idea: We need to show (c h).bind (fun (a, h') => f a h') none = 0.
Since c is lossless, (c h) none = 0, so the none-to-none path contributes 0.
For each (a, h') in the support of c h, f a h' is lossless, so
(f a h') none = 0, meaning the some-to-none path also contributes 0.
Variant of lossless_bind with conditional losslessness for the continuation.
The continuation only needs to be lossless for outcomes actually produced by c.
Derived losslessness lemmas #
Assert is lossless when the condition holds.
Assert is not lossless when the condition fails.
Sequential composition preserves losslessness.