Skip to content

Commit

Permalink
proof of ResultsIndependent and brittleness of fisher-yates
Browse files Browse the repository at this point in the history
  • Loading branch information
stefan-aws committed Mar 5, 2024
1 parent bf5ddee commit 59913bf
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 20 deletions.
4 changes: 4 additions & 0 deletions src/Distributions/Uniform/Model.dfy
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,8 @@ module Uniform.Model {
SampleBound(b-a, s);
}

lemma {:axiom} IntervalSampleIsMeasurePreserving(a: int, b: int)
requires a < b
ensures Measures.IsMeasurePreserving(Rand.eventSpace, Rand.prob, Rand.eventSpace, Rand.prob, s => IntervalSample(a, b)(s).rest)

}
12 changes: 11 additions & 1 deletion src/ProbabilisticProgramming/Independence.dfy
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ module Independence {
)
requires hIndep: IsIndepFunction(h)
requires bMeasurable: bSeeds in Rand.eventSpace
requires hIsMeasurePreserving: Measures.IsMeasurePreserving(Rand.eventSpace, Rand.prob, Rand.eventSpace, Rand.prob, s => h(s).rest)
ensures Rand.prob(Monad.BitstreamsWithValueIn(h, aSet) * Monad.BitstreamsWithRestIn(h, bSeeds)) == Rand.prob(Monad.BitstreamsWithValueIn(h, aSet)) * Rand.prob(bSeeds)
{
var aSeeds := Monad.BitstreamsWithValueIn(h, aSet);
Expand All @@ -52,7 +53,16 @@ module Independence {
assert Measures.AreIndepEvents(Rand.eventSpace, Rand.prob, aSeeds, restBSeeds);
}
assert Rand.prob(restBSeeds) == Rand.prob(bSeeds) by {
assume {:axiom} false; // TODO
calc {
Rand.prob(restBSeeds);
Rand.prob(Monad.BitstreamsWithRestIn(h, bSeeds));
{ assert Monad.BitstreamsWithRestIn(h, bSeeds) == iset s | h(s).rest in bSeeds; }
Rand.prob(iset s | h(s).rest in bSeeds);
{ assert (iset s | h(s).rest in bSeeds) == Measures.PreImage(s => h(s).rest, bSeeds); }
Rand.prob(Measures.PreImage(s => h(s).rest, bSeeds));
{ reveal bMeasurable; reveal hIsMeasurePreserving; }
Rand.prob(bSeeds);
}
}
}

Expand Down
77 changes: 58 additions & 19 deletions src/Util/FisherYates/Correctness.dfy
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ module FisherYates.Correctness {
var e := iset s | Model.Shuffle(xs, i)(s).value[i..] == p[i..];
assert |xs| > i + 1;
var h := Uniform.Model.IntervalSample(i, |xs|);
assert hIsMeasurePreserving: Measures.IsMeasurePreserving(Rand.eventSpace, Rand.prob, Rand.eventSpace, Rand.prob, s => h(s).rest) by {
Uniform.Model.IntervalSampleIsMeasurePreserving(i, |xs|);
}
assert HIsIndependent: Independence.IsIndepFunction(h) by {
Uniform.Correctness.IntervalSampleIsIndep(i, |xs|);
Independence.IsIndepImpliesIsIndepFunction(h);
Expand Down Expand Up @@ -238,33 +241,68 @@ module FisherYates.Correctness {
assert DecomposeE: e == Monad.BitstreamsWithValueIn(h, A) * Monad.BitstreamsWithRestIn(h, e') by {
DecomposeE(xs, ys, p, i, j, h, A, e, e');
}

assert CorrectnessPredicate(xs, p, i) by {
reveal DecomposeE;
reveal HIsIndependent;
reveal BitStreamsInA;
assert e' in Rand.eventSpace && Rand.prob(e') == 1.0 / (NatArith.FactorialTraditional(|xs|-(i+1)) as real) by {
assert e' in Rand.eventSpace by {
assert CorrectnessPredicate(ys, p, i+1) by { reveal InductionHypothesis; }
assert e' == CorrectnessConstructEvent(ys, p, i+1);
}
calc {
Rand.prob(e');
{ assert CorrectnessPredicate(ys, p, i+1) by { reveal InductionHypothesis; }
assert e' == CorrectnessConstructEvent(ys, p, i+1); }
1.0 / (NatArith.FactorialTraditional(|ys|-(i+1)) as real);
{ assert |xs| == |ys|;
assert |ys|-(i+1) == |xs|-(i+1);
assert NatArith.FactorialTraditional(|ys|-(i+1)) == NatArith.FactorialTraditional(|xs|-(i+1));
assert (NatArith.FactorialTraditional(|ys|-(i+1)) as real) == (NatArith.FactorialTraditional(|xs|-(i+1)) as real); }
1.0 / (NatArith.FactorialTraditional(|xs|-(i+1)) as real);
}
reveal InductionHypothesis;
reveal hIsMeasurePreserving;
CorrectnessFisherYatesUniqueElementsGeneralGreater1Helper(xs, ys, p, i, j, h, A, e, e');
}

}

lemma CorrectnessFisherYatesUniqueElementsGeneralGreater1Helper<T(!new)>(xs: seq<T>, ys: seq<T>, p: seq<T>, i: nat, j: nat, h: Monad.Hurd<int>, A: iset<int>, e: iset<Rand.Bitstream>, e': iset<Rand.Bitstream>)
decreases |xs| - i
requires i <= |xs|
requires i <= |p|
requires forall a, b | i <= a < b < |xs| :: xs[a] != xs[b]
requires |xs| == |p|
requires multiset(p[i..]) == multiset(xs[i..])
requires |xs[i..]| > 1
requires i <= j < |xs| && xs[j] == p[i]
requires |xs| == |ys|
requires ys == Model.Swap(xs, i, j)
requires e == CorrectnessConstructEvent(xs, p, i)
requires e' == CorrectnessConstructEvent(ys, p, i+1)
requires DecomposeE: e == Monad.BitstreamsWithValueIn(h, A) * Monad.BitstreamsWithRestIn(h, e')
requires HIsIndependent: Independence.IsIndepFunction(h)
requires BitStreamsInA: Monad.BitstreamsWithValueIn(h, A) == (iset s | Uniform.Model.IntervalSample(i, |xs|)(s).Equals(j))
requires InductionHypothesis: CorrectnessPredicate(ys, p, i+1)
requires hIsMeasurePreserving: Measures.IsMeasurePreserving(Rand.eventSpace, Rand.prob, Rand.eventSpace, Rand.prob, s => h(s).rest)
ensures CorrectnessPredicate(xs, p, i)
{
reveal DecomposeE;
reveal HIsIndependent;
reveal BitStreamsInA;
assert e' in Rand.eventSpace && Rand.prob(e') == 1.0 / (NatArith.FactorialTraditional(|xs|-(i+1)) as real) by {
assert e' in Rand.eventSpace by {
assert CorrectnessPredicate(ys, p, i+1) by { reveal InductionHypothesis; }
assert e' == CorrectnessConstructEvent(ys, p, i+1);
}
ProbabilityOfE(xs, ys, p, i, j, h, A, e, e');
calc {
Rand.prob(e');
{ assert CorrectnessPredicate(ys, p, i+1) by { reveal InductionHypothesis; }
assert e' == CorrectnessConstructEvent(ys, p, i+1); }
1.0 / (NatArith.FactorialTraditional(|ys|-(i+1)) as real);
{ assert |xs| == |ys|;
assert |ys|-(i+1) == |xs|-(i+1);
assert NatArith.FactorialTraditional(|ys|-(i+1)) == NatArith.FactorialTraditional(|xs|-(i+1));
assert (NatArith.FactorialTraditional(|ys|-(i+1)) as real) == (NatArith.FactorialTraditional(|xs|-(i+1)) as real); }
1.0 / (NatArith.FactorialTraditional(|xs|-(i+1)) as real);
}
}
reveal hIsMeasurePreserving;
assert e in Rand.eventSpace by {
EInEventSpace(xs, p, h, A, e, e');
}

assert Rand.prob(e) == 1.0 / (NatArith.FactorialTraditional(|xs|-i) as real) by {
ProbabilityOfE(xs, ys, p, i, j, h, A, e, e');
}
}


lemma BitStreamsInA<T(!new)>(xs: seq<T>, p: seq<T>, i: nat, j: nat, h: Monad.Hurd<int>, A: iset<int>)
requires i <= |xs|
requires i <= |p|
Expand Down Expand Up @@ -489,6 +527,7 @@ module FisherYates.Correctness {
requires |xs| == |ys|
requires DecomposeE: e == Monad.BitstreamsWithValueIn(h, A) * Monad.BitstreamsWithRestIn(h, e')
requires HIsIndependent: Independence.IsIndepFunction(h)
requires hIsMeasurePreserving: Measures.IsMeasurePreserving(Rand.eventSpace, Rand.prob, Rand.eventSpace, Rand.prob, s => h(s).rest)
requires InductionHypothesis: Rand.prob(e') == 1.0 / (NatArith.FactorialTraditional(|xs|-(i+1)) as real)
requires BitStreamsInA: Monad.BitstreamsWithValueIn(h, A) == (iset s | Uniform.Model.IntervalSample(i, |xs|)(s).Equals(j))
ensures
Expand All @@ -498,7 +537,7 @@ module FisherYates.Correctness {
Rand.prob(e);
{ reveal DecomposeE; }
Rand.prob(Monad.BitstreamsWithValueIn(h, A) * Monad.BitstreamsWithRestIn(h, e'));
{ reveal HIsIndependent; reveal InductionHypothesis; Independence.ResultsIndependent(h, A, e'); }
{ reveal HIsIndependent; reveal InductionHypothesis; reveal hIsMeasurePreserving; Independence.ResultsIndependent(h, A, e'); }
Rand.prob(Monad.BitstreamsWithValueIn(h, A)) * Rand.prob(e');
{ assert Rand.prob(Monad.BitstreamsWithValueIn(h, A)) == Rand.prob(iset s | Uniform.Model.IntervalSample(i, |xs|)(s).Equals(j)) by { reveal BitStreamsInA; } }
Rand.prob(iset s | Uniform.Model.IntervalSample(i, |xs|)(s).Equals(j)) * Rand.prob(e');
Expand Down

0 comments on commit 59913bf

Please sign in to comment.