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

org.cloudbus.cloudsim.distributions.PoissonDistr Maven / Gradle / Ivy

Go to download

CloudSim Plus: A modern, highly extensible and easier-to-use Java 8 Framework for Modeling and Simulation of Cloud Computing Infrastructures and Services

There is a newer version: 8.0.0
Show newest version
/*
 * CloudSim Plus: A modern, highly-extensible and easier-to-use Framework for
 * Modeling and Simulation of Cloud Computing Infrastructures and Services.
 * http://cloudsimplus.org
 *
 *     Copyright (C) 2015-2018 Universidade da Beira Interior (UBI, Portugal) and
 *     the Instituto Federal de Educação Ciência e Tecnologia do Tocantins (IFTO, Brazil).
 *
 *     This file is part of CloudSim Plus.
 *
 *     CloudSim Plus is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     CloudSim Plus is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with CloudSim Plus. If not, see .
 */
package org.cloudbus.cloudsim.distributions;

import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.IntStream;
import org.apache.commons.math3.util.CombinatoricsUtils;

/**
 * A pseudo random number generator which returns numbers
 * following a Poisson Distribution, modeling the probability of an event
 * to happen a number of times in a given time interval.
 *
 * @see Poisson Distribution
 * @see Poisson Point Process
 *
 * @author Manoel Campos da Silva Filho
 * @since CloudSim Plus 1.2.0
 */
public class PoissonDistr implements ContinuousDistribution {
    /**
     * A Uniform Pseudo Random Number Generator used
     * internally to generate Poisson numbers.
     */
    private final UniformDistr rand;

    /**
     * @see #getLambda()
     */
    private double lambda;

    /**
     * @see #getK()
     */
    private int k;

    /**
     * Creates a new Poisson random number generator to check
     * the probability of 1 event ({@link #getK() k}) to happen at each time
     * interval.
     *
     * @param lambda the average number of events that happen at each 1 time unit.
     *               If one considers the unit as minute, this value means the average number of arrivals
     *               at each minute.
     * @param seed the seed to initialize the uniform random number generator
     * @see #setK(int)
     * @see #setLambda(double)
     */
    public PoissonDistr(double lambda, long seed){
        this.rand = new UniformDistr(seed);
        this.k = 1;
        this.setLambda(lambda);
    }

    /**
     * Creates a new Poisson process that considers you want to check
     * the probability of 1 event ({@link #getK() k}) to happen at each time.
     *
     * @param lambda average number of events by interval.
     * For instance, if it was defined 1 event to be expected at
     * each 2.5 minutes, it means that 0.4 event is expected
     * at each minute (1/2.5).
     *
     * @see #setK(int)
     */
    public PoissonDistr(double lambda){
        this(lambda, -1);
    }

    /**
     * Gets the average number of events that are expected to happen at each 1 time unit.
     * It is the expected number of events to happen each time,
     * also called the event rate or rate parameter.
     *
     * 

If the unit is minute, this value means the average number of arrivals * at each minute. It's the inverse of the {@link #getInterarrivalMeanTime()}.

* @return */ public double getLambda(){ return lambda; } /** * Sets the average number of events that are expected to happen at each 1 time unit. * It is the expected number of events to happen each time, * also called the event rate or rate parameter. * *

If one considers the unit as minute, this value means the average number of arrivals * at each minute. It's the inverse of the {@link #getInterarrivalMeanTime()}.

* @param lambda the value to set */ private void setLambda(double lambda) { this.lambda = lambda; } /** * Gets the probability to arrive {@link #getK() K} events in the current time, * considering the expected average arrival time {@link #getLambda() lambda}. * It computes the Probability Mass Function (PMF) of the Poisson distribution. * @return * @see Poisson distribution */ public double eventsArrivalProbability(){ return (Math.pow(getLambda(), k) * Math.exp(-getLambda())) / CombinatoricsUtils.factorial(k); } /** * Checks if at the current time, {@link #getK() K} events have happened, * considering the {@link #eventsArrivalProbability() probability of these K events} * to happen in a time interval. * * @return true if the K events have happened at current time, false otherwise */ public boolean eventsHappened(){ final double r = rand.sample(); return r <= eventsArrivalProbability(); } /** * Gets a random number that represents the next time for an event to happen, * considering the {@link #getLambda() events arrival rate (lambda)}. * @return */ @Override public double sample() { return Math.exp(1.0 - rand.sample()) / getLambda(); } @Override public long getSeed() { return rand.getSeed(); } /** * Gets the number of events to check the probability for them to happen * in a time interval (default 1). * @return */ public int getK() { return k; } /** * Sets the number of events to check the probability to happen * in a time time. * @param k the value to set */ public void setK(int k) { this.k = k; } /** * Gets the mean time between arrival of two events, * which is the inverse of lambda. * The time unit (if seconds, minutes, hours, etc) is the same * considered when setting a value to the {@link #getLambda() lambda} * parameter. * @return */ public double getInterarrivalMeanTime(){ return 1.0/lambda; } /** * Tests the simulations of customers arrivals in a Poisson process. * All the code inside this method is just to try the class. * That is way it declares internal methods as Functional * objects, instead of declaring such methods * at the class level and just calling them. * * @param args */ public static void main(String args[]){ /* * Average number of customers that arrives per minute. * The value of 0.4 customers per minute means that 1 customer will arrive * at every 2.5 minutes. * It means that 1 minute / 0.4 customer per minute = 1 customer at every 2.5 minutes. * This is the interarrival time (in average). */ final double MEAN_CUSTOMERS_ARRIVAL_PER_MINUTE=0.4; /* * Time length of each simulation in minutes. */ final int SIMULATION_TIME_LENGHT = 25; //If the arrival of each customers must be shown. final boolean showCustomerArrivals = true; /* * Number of simulations to run. */ final int NUMBER_OF_SIMULATIONS = 100; final BiConsumer printArrivals = (poisson, minute) -> { if(showCustomerArrivals) { System.out.printf("%d customers arrived at minute %d\n", poisson.getK(), minute); } }; /* * A {@link Function} to simulate the arrival of customers for a given time period. * This is just a method to test the implementation. * * @param poisson the PoissonDistr object that will compute the customer arrivals probabilities * @return the number of arrived customers */ final Function runSimulation = poisson -> { /*We want to check the probability of 1 customer to arrive at each single minute. The default k value is 1, so we dont need to set it.*/ final int totalArrivedCustomers = IntStream.range(0, SIMULATION_TIME_LENGHT) .filter(i -> poisson.eventsHappened()) .peek(i -> printArrivals.accept(poisson, i)) .map(i -> poisson.getK()) .sum(); System.out.printf( "\t%d customers arrived in %d minutes\n", totalArrivedCustomers, SIMULATION_TIME_LENGHT); System.out.printf("\tArrival rate: %.2f customers per minute. Customers interarrival time: %.2f minutes in average\n", poisson.getLambda(), poisson.getInterarrivalMeanTime()); return totalArrivedCustomers; }; double customersArrivedInAllSimulations = 0; PoissonDistr poisson = null; final long seed=System.currentTimeMillis(); for(int i = 0; i < NUMBER_OF_SIMULATIONS; i++){ poisson = new PoissonDistr(MEAN_CUSTOMERS_ARRIVAL_PER_MINUTE, seed+i); System.out.printf("Simulation number %d\n", i); customersArrivedInAllSimulations += runSimulation.apply(poisson); } final double mean = customersArrivedInAllSimulations/NUMBER_OF_SIMULATIONS; System.out.printf("\nArrived customers average after %d simulations: %.2f\n", NUMBER_OF_SIMULATIONS, mean); System.out.printf( "%.2f customers expected by each %d minutes of simulation with interarrival time of %.2f minutes\n", poisson.getLambda()*SIMULATION_TIME_LENGHT, SIMULATION_TIME_LENGHT, poisson.getInterarrivalMeanTime()); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy