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

com.waioeka.graph.Distribution.scala Maven / Gradle / Ivy

There is a newer version: 0.0.6
Show newest version
/*
 * Copyright (c) 2016
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.waioeka.graph

import scala.math.log
import scala.util.Random


/**
  * Distribution Monad.
  */
trait Distribution[A]  { self =>

  /** Return an element of the distribution. */
  def get: A

  /**
    * Map given a function of A => B return a distribution of B.
    *
    * @param f    the function f : A=> B.
    * @tparam B   the type of B.
    * @return     a distribution of B.
    */
  def map[B](f: A => B): Distribution[B] = new Distribution[B] {
    override def get = f(self.get)
  }

  /**
    * Given a function A => distribution of B, return a distribution of B.
    *
    * @param f    the function f : A => distribution of B.
    * @tparam B   the type of B.
    * @return     a distribution of B.
    */
  def flatMap[B](f: A => Distribution[B]): Distribution[B] = new Distribution[B] {
    override def get = f(self.get).get
  }

}


/**
  * Case class that allow creation of different probability distributions.
  *
  * @param seed the initial seed value.
  */
case class Distributions(private val seed: Long) {

  /**
    * Base random number generator, n.b. constructed from
    * a given seed value.
    */
  val random = new Random(seed)

  /**
    * Returns a uniform distribution.
    *
    * @return a uniform distribution of doubles.
    */
  def uniform = new Distribution[Double] { override def get = random.nextDouble() }

  /**
    * Returns a normal distribution.
    *
    * @return a normal distribution of doubles.
    */
  def normal = new Distribution[Double] { override def get = random.nextGaussian() }

  /**
    * Returns an exponential distribution.
    *
    * @param l  lambda.
    * @return   the exponential distribution.
    */
  def exponential(l: Double): Distribution[Double] = for (x <- uniform) yield -log(x)/l

  /**
    * Returns a list of size n (if n>0, otherwise an empty list) of elements
    * drawn from a distribution.
    *
    * @param n    the number of elements.
    * @param d    the distribution.
    * @tparam A   the type of elements.
    * @return     the list of n elements from the distribution.
    */
  def fill[A](n: Int)(implicit d: Distribution[A]): List[A] = List.fill(n)(d.get)

  /**
    * Draw elements from a distribution until a predicate over the list
    * is satisfied.
    *
    * @param p      the predicate.
    * @param d      the distribution.
    * @tparam A     the type of elements in the list.
    * @return       a list of elements.
    */
  def until[A](p: List[A] => Boolean)(implicit d: Distribution[A]): List[A] = {
    def filter(acc: List[A]): List[A] = if (p(acc)) acc else filter(d.get :: acc)
    filter(List.empty)
  }

}








© 2015 - 2024 Weber Informatics LLC | Privacy Policy