Statistics Library Blog - #43
Conversation
This reverts commit 96d1888.
robin-aws
left a comment
There was a problem hiding this comment.
Very nice work on this, very readable and does a great job motivating the contribution and describing the journey to the final product.
|
|
||
| ## Order statistics: median and range | ||
|
|
||
| Beyond mean and variance, a statistics library should also provide basic order statistics such as median and range. Since Dafny’s standard collections already provide a merge sort ([MergeSortBy](https://github.com/dafny-lang/dafny/blob/68fb5ed04006b9be9601695d3d74687bbe3800b4/Source/DafnyStandardLibraries/src/Std/Collections/Seq.dfy#L1041)), we reuse it rather than re–implement ordering ourselves . This is exactly the kind of situation where strong libraries make a difference: instead of proving sorting correctness again, we can build directly on a verified component and focus on the statistical logic itself. |
| } | ||
| {% endhighlight %} | ||
|
|
||
| You remember our first line, What looks simple in code often becomes interesting the moment you try to prove it. This is one of the cases where we faced such an issue. Our FrequencyTable function seemed simple: take a sequence and build a map counting occurrences. |
There was a problem hiding this comment.
| You remember our first line, What looks simple in code often becomes interesting the moment you try to prove it. This is one of the cases where we faced such an issue. Our FrequencyTable function seemed simple: take a sequence and build a map counting occurrences. | |
| You remember our first line: "What looks simple in code often becomes interesting the moment you try to prove it." This is one of the cases where we faced such an issue. Our FrequencyTable function seemed simple: take a sequence and build a map counting occurrences. |
| {% endhighlight %} | ||
|
|
||
| You remember our first line, What looks simple in code often becomes interesting the moment you try to prove it. This is one of the cases where we faced such an issue. Our FrequencyTable function seemed simple: take a sequence and build a map counting occurrences. | ||
| Now , Formally, we wanted Dafny to verify: |
There was a problem hiding this comment.
'Formally' was a bit ambiguous there. I have rephrased the sentence to: 'To ensure correctness, we formally had to verify that:' to make the intent clearer.
| {% endhighlight %} | ||
|
|
||
| This design has a few advantages: | ||
| - It runs in *O(n)* time: one pass to build the frequency map and one pass to find the best. |
There was a problem hiding this comment.
This is a bit too strong a claim, for two different reasons:
- Building the frequency table actually takes quadratic time because each map update such as
m[key := m[key] + 1]have to make a new copy of the map (since Dafny maps are immutable). This could be optimized in the Dafny runtimes but hasn't been yet. - Each map lookup is not necessarily constant time in practice, because the runtimes generally use something like a HashMap, which is only going to be constant time on average, but can be linear in the worst case.
The first point could hypothetically be addressed by using a MutableMap from the Concurrent standard library, but the second point is a pretty fundamental data structures limit.
You definitely don't need to address this in the library itself, but you may want to add a bit of this detail, and definitely soften this runtime claim. It's still definitely true that the original version was quite a bit worse than quadratic :)
There was a problem hiding this comment.
I agree with the points. Writing Linear time is sort of a tall claim and hence, I have made the required change here by telling how our approach is better.
| They also show how simple it is to work with the module: you can call Mean, Median, VariancePopulation, Mode, and the rest just like any normal function without worrying about the underlying proofs. In that sense, the tests double as a quick “how to use this library” guide while demonstrating its correctness on real data. | ||
|
|
||
|
|
||
| ## Acknowledgments |
There was a problem hiding this comment.
Consider swapping the last two sections, I think it flows a bit better to end with acknowledgements
| layout: post | ||
| title: "A Verified Statistics Library for Dafny" | ||
| author: Bhavesh Bhatia and Tanay Mathur | ||
| date: 2025-12-01 09:00:00 +0000 |
There was a problem hiding this comment.
Just FYI since it came up earlier, this date is only used to allow blog posts to be merged that should not be actually published until a future date. When this is merged, as long as this date is in the past the new post will appear with the correct actual publication date. In other words this value is just fine. :)
| Because our helper `SumSquaredDifferences` is proven non-negative, Dafny automatically verifies that `VariancePopulation` and `VarianceSample` are also non-negative. Note that `VarianceSample` requires `|s| > 1`, because dividing by N - 1 where N is 1 would cause a division by zero! | ||
|
|
||
| ### 5. Standard Deviation | ||
| Finally, we arrive at Standard Deviation, which is the square root of the Variance. Since Dafny doesn't have a built-in square root, we define an `extern` function in a separate module. |
There was a problem hiding this comment.
Dafny doesn't have a built-in square root
Actually it does now! A new floating point type was added that supports square root: https://dafny.org/dafny/DafnyRef/DafnyRef#5236-mathematical-functions
You can just rephrase this to say it didn't have this at the time, and perhaps mention in the future work section that we could refactor the code to use this new type, and hence make it no longer target-specific.
There was a problem hiding this comment.
Ah! Thank you for letting us know. I have added the point as you asked me to!
Co-authored-by: Robin Salkeld <salkeldr@amazon.com>
Co-authored-by: Robin Salkeld <salkeldr@amazon.com>
Reworded sections for clarity and improved flow. Added acknowledgments section back to the document.
Corrected phrasing for clarity regarding Dafny's capabilities.
This serves as the PR for the blog post for official Statistics Library. @robin-aws Please let us know if there are any changes needed on the content or the CI side