Skip to content

Commit

Permalink
fixed rectification or normal distribution
Browse files Browse the repository at this point in the history
  • Loading branch information
holgerbrandl committed Jan 20, 2024
1 parent 7213f25 commit 46e648f
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 7 deletions.
15 changes: 8 additions & 7 deletions src/main/kotlin/org/kalasim/Distributions.kt
Expand Up @@ -65,9 +65,9 @@ fun SimContext.exponential(mean: Duration) = ExponentialDistribution(env.rg, mea
* For additional details see https://www.kalasim.org/basics/#randomness-distributions.
*/
fun SimContext.normal(mean: Number = 0, sd: Number = 1, rectify: Boolean = false): NormalDistribution = if(rectify) {
NormalDistribution(env.rg, mean.toDouble(), sd.toDouble())
} else {
RectifiedNormalDistribution(env.rg, mean.toDouble(), sd.toDouble())
} else {
NormalDistribution(env.rg, mean.toDouble(), sd.toDouble())
}


Expand All @@ -82,17 +82,18 @@ operator fun ExponentialDistribution.invoke(): Double = sample()
* For additional details see https://www.kalasim.org/basics/#randomness-distributions.
*/
fun SimContext.normal(mean: Duration, sd: Duration, rectify: Boolean = false): DurationDistribution = if(rectify) {
NormalDistribution(env.rg, mean.inSeconds, sd.inSeconds)
} else {
RectifiedNormalDistribution(env.rg, mean.inSeconds, sd.inSeconds)
} else {
NormalDistribution(env.rg, mean.inSeconds, sd.inSeconds)
}.seconds


private class RectifiedNormalDistribution(rng: RandomGenerator, mean: Double, sd: Double) :
NormalDistribution(rng, mean, sd) {
override fun probability(x0: Double, x1: Double): Double {
return super.probability(x0, x1).let { if(it < 0) 0.0 else it }
}

override fun sample(sampleSize: Int): DoubleArray = Array(sampleSize) { sample() }.toDoubleArray()

override fun sample(): Double = super.sample().let { if(it < 0) 0.0 else it }
}


Expand Down
25 changes: 25 additions & 0 deletions src/test/kotlin/org/kalasim/test/DistributionTests.kt
@@ -0,0 +1,25 @@
package org.kalasim.test

import io.kotest.matchers.doubles.shouldBeGreaterThanOrEqual
import org.junit.Test
import org.kalasim.Environment
import org.kalasim.normal
import kotlin.time.Duration.Companion.days
import kotlin.time.DurationUnit

class DistributionTests {

@Test
fun `it should correctly rectify a normal distribution`() {

Environment().apply {
val tbf = normal(3.days, 2.days, rectify = true)
val tbf2 = normal(3, 2, rectify = true)

repeat(1000) {
tbf().toDouble(DurationUnit.HOURS) shouldBeGreaterThanOrEqual 0.0
tbf2.sample() shouldBeGreaterThanOrEqual 0.0
}
}
}
}

0 comments on commit 46e648f

Please sign in to comment.