All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.data2viz.random.RandomDistribution.kt Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2018-2019. data2viz sàrl.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

package io.data2viz.random

import kotlin.math.*
import kotlin.random.*

typealias RandomGenerator = () -> Double

/**
 * Generate random numbers from various distributions.
 */
class RandomDistribution internal constructor(private val random:Random = Random){

    companion object Default {

        private val randomDistribution= RandomDistribution()

        /**
         * Returns a function for generating random numbers with a uniform distribution.
         * The minimum allowed value of a returned number is min, and the maximum is max.
         * If min is not specified, it defaults to 0; if max is not specified, it defaults to 1.
         */
        fun uniform(min: Double = .0, max: Double = 1.0): RandomGenerator       = randomDistribution.uniform(min, max)

        /**
         * returns a function for generating random numbers with a Bates distribution with n independent variables.
         */
        fun bates(n: Double = 1.0): RandomGenerator                             = randomDistribution.bates(n)

        /**
         * returns a function for generating random numbers with a log-normal distribution.
         * The expected value of the random variable’s natural logarithm is mu, with the given
         * standard deviation sigma. If mu is not specified, it defaults to 0;
         * if sigma is not specified, it defaults to 1.
         */
        fun logNormal(mu: Double = .0, sigma: Double = 1.0): RandomGenerator    = randomDistribution.logNormal(mu, sigma)


        /**
         * Returns a function for generating random numbers with an exponential distribution with
         * the rate lambda; equivalent to time between events in a Poisson process with a mean of 1 / lambda.
         * For example, exponential(1/40) generates random times between events where, on average, one event
         * occurs every 40 units of time.
         */
        fun exponential(lambda: Double = 1.0): RandomGenerator                  = randomDistribution.exponential(lambda)

        /**
         * Returns a function for generating random numbers with an Irwin–Hall distribution with n independent variables.
         */
        fun irwinHall(n: Double): RandomGenerator                               = randomDistribution.irwinHall(n)

        /**
         * Returns a function for generating random numbers with a normal (Gaussian) distribution.
         * The expected value of the generated numbers is mu, with the given standard deviation sigma.
         * If mu is not specified, it defaults to 0.0; if sigma is not specified, it defaults to 1.0
         */
        fun normal(mu: Double = .0, sigma: Double = 1.0): RandomGenerator       = randomDistribution.normal(mu, sigma)
    }



    fun uniform(min: Double = .0, max: Double = 1.0): RandomGenerator = { random() * (max - min) + min }
    fun bates(n: Double = 1.0): RandomGenerator = { irwinHall(n)() / n }
    fun logNormal(mu: Double = .0, sigma: Double = 1.0): RandomGenerator = { exp(normal(mu, sigma)()) }
    fun exponential(lambda: Double = 1.0): RandomGenerator = { -ln(1 - random()) / lambda }
    fun irwinHall(n: Double): RandomGenerator = {
        var sum = 0.0
        (0 until n.toInt()).forEach {
            sum += random()
        }
        sum
    }


    fun normal(mu: Double = .0, sigma: Double = 1.0): RandomGenerator = {
        var x: Double? = null
        var r = 0.0
        var y = 0.0

        if (x != null) {
            y = x
        } else {
            while (r == 0.0 || r > 1) {
                x = random() * 2 - 1
                y = random() * 2 - 1
                r = x * x + y * y
            }
        }
        mu + sigma * y * sqrt(-2 * ln(r) / r)
    }

    fun random(): Double = random.nextDouble()


}






© 2015 - 2025 Weber Informatics LLC | Privacy Policy