kyonifer / koma

A scientific computing library for Kotlin. https://kyonifer.github.io/koma
Other
270 stars 23 forks source link

Unexpected RNG behavior w/seed #39

Closed RatsRatsRats closed 6 years ago

RatsRatsRats commented 6 years ago
val seed : Long = 1

// Seeding java produces matches
val r = Random()
r.setSeed(seed)
val firstJava = r.nextGaussian()
r.setSeed(seed)
assert(r.nextGaussian() == firstJava)

// So does EJML directly
r.setSeed(seed)
val firstEJML = SimpleMatrix.random(1, 1, 0.0, 1.0, r)
r.setSeed(seed)
val secEJML = SimpleMatrix.random(1, 1, 0.0, 1.0, r)
assert(secEJML.isIdentical(firstEJML, 1e-20))

// koma w/ EJML backend behaves differently
assertMatrixEquals(randn(1, 1, seed), randn(1, 1, seed))  // fails
kyonifer commented 6 years ago

Thanks for the report.

I agree the current behavior of ignoring a seed if its been set to that number before is non-obvious. Having randn(seed=something) always apply is also suboptimal, since it means someone setting the seed when they actually need a random number could lead to a bug where they are getting an identical number out every time. They would then have to pull seed setting randn calls outside of any loop, which is awkward because the seed set call will still generate a random number (since seed setting is done in randn). The right solution here I think is to refactor out to a separate seed function, so that you'd call seed(someNum); randn(5) following the more conventional APIs for rngs.

Doing so should probably be part of #36, which in turn is probably dependent on #38 getting done first, since the current "module" system was just a set of quick hacks using conditional compilation until kotlin supported something better.