Source code for pypdevs.randomGenerator

# Copyright 2014 Modelling, Simulation and Design Lab (MSDL) at 
# McGill University and the University of Antwerp (http://msdl.cs.mcgill.ca/)
# 
# 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.

"""
Module to offer 'really deterministic' (pseudo-)random number generation in a Distributed Time Warp implementation.

For local simulation, using the random library from Python as usual is perfectly ok.
"""

import random

[docs]class RandomGenerator(object): """ Base class, which implements a random number interface for the 'uniform' and 'random' Python standard library functions. .. note:: The generated random numbers are **not** equal to those generated by direct calls to the library functions, as we also use a random number to initialize the seed in the next iteration. """
[docs] def __init__(self, seed): """ Constructor :param seed: the seed to start with, this will simply be passed to the *random* library at every function call """ #NOTE: This is implemented using only a seed (and actually, only a number), instead of using the 'getState()' en 'setState(state)' # functions provided by the library. This was done to allow far more simple comparison (for memoization), hashing (as we # have overwritten the comparison) and copying (for custom state saving). self.seed = seed
[docs] def __eq__(self, other): """ Compare two instances of random number generators. Needed for memoization. :param other: the instance to compare with :returns: bool -- do these random number generators return the same sequence? """ return type(self) == type(other) and self.seed == other.seed
[docs] def __hash__(self): """ Hash this random number generator. Needed as the comparison method was changed! :returns: hash """ return self.seed
[docs] def copy(self): """ A copy method to be used when defining custom state saving methods. It will return a complete copy of this random number generator, which will generate exactly the same sequence of numbers. """ return RandomGenerator(self.seed)
def __wrapFunction(self, func, args): """ Internal wrapper for most functions, allows easy addition of new functions should the need arise. It updates the internal state and guarantees determinism even when revertions happen. :param func: the function to call on the *random* module (a string) :param args: the arguments to pass (a list) :returns: random -- the generated value """ random.seed(self.seed) val = getattr(random, func)(*args) self.seed = random.random() return val
[docs] def uniform(self, a, b): """ Call the uniform function of the *random* library. :param a: lower bound of generated value :param b: upper bound of generated value :returns: float -- the generated value """ return self.__wrapFunction("uniform", [a, b])
[docs] def random(self): """ Call the random function of the *random* library. :returns: float -- a random value between 0 and 1 """ return self.__wrapFunction("random", [])