Optimize Random.sample(_, _) for performance (#716)

* Optimize Random.sample(_, _) for performance
* Make tests treat random samples as unordered
* Test all sample sizes possible
* Tweak random sampling algorithm for performance
This commit is contained in:
kawa-yoiko
2020-06-14 12:31:23 +08:00
committed by GitHub
parent fea0dfafa0
commit f3493d0499
4 changed files with 64 additions and 129 deletions

View File

@ -1,19 +0,0 @@
import "random" for Random
var random = Random.new(12345)
// Should choose all elements with roughly equal probability.
var list = ["a", "b", "c"]
var histogram = {}
for (i in 1..5000) {
var sample = random.sample(list, 3)
var string = sample.toString
if (!histogram.containsKey(string)) histogram[string] = 0
histogram[string] = histogram[string] + 1
}
System.print(histogram.count) // expect: 6
for (key in histogram.keys) {
var error = (histogram[key] / (5000 / 6) - 1).abs
if (error > 0.1) System.print("!!! %(error)")
}

View File

@ -3,17 +3,25 @@ import "random" for Random
var random = Random.new(12345)
// Should choose all elements with roughly equal probability.
var list = ["a", "b", "c", "d"]
var histogram = {}
for (i in 1..5000) {
var sample = random.sample(list, 3)
var string = sample.toString
if (!histogram.containsKey(string)) histogram[string] = 0
histogram[string] = histogram[string] + 1
}
var list = (0...10).toList
var binom = [1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1]
System.print(histogram.count) // expect: 24
for (key in histogram.keys) {
var error = (histogram[key] / (5000 / 24) - 1).abs
if (error > 0.2) System.print("!!! %(error)")
for (k in 0..10) {
var count = binom[k]
var histogram = {}
for (i in 1..count * 100) {
var sample = random.sample(list, k)
// Create a bitmask to represent the unordered set.
var bitmask = 0
sample.each {|s| bitmask = bitmask | (1 << s) }
if (!histogram.containsKey(bitmask)) histogram[bitmask] = 0
histogram[bitmask] = histogram[bitmask] + 1
}
if (histogram.count != count) System.print("!!! %(count) %(histogram.count)")
for (key in histogram.keys) {
var error = (histogram[key] - 100).abs
if (error > 50) System.print("!!! %(error)")
}
}