Source code for Arms.UniformArm
# -*- coding: utf-8 -*-
""" Uniformly distributed arm in [0, 1], or [lower, lower + amplitude].
Example of creating an arm:
>>> import random; import numpy as np
>>> random.seed(0); np.random.seed(0)
>>> Unif01 = UniformArm(0, 1)
>>> Unif01
U(0, 1)
>>> Unif01.mean
0.5
Examples of sampling from an arm:
>>> Unif01.draw() # doctest: +ELLIPSIS
0.8444...
>>> Unif01.draw_nparray(20) # doctest: +ELLIPSIS,+NORMALIZE_WHITESPACE
array([0.54... , 0.71..., 0.60..., 0.54..., 0.42... ,
0.64..., 0.43..., 0.89... , 0.96..., 0.38...,
0.79..., 0.52..., 0.56..., 0.92..., 0.07...,
0.08... , 0.02... , 0.83..., 0.77..., 0.87...])
"""
from __future__ import division, print_function # Python 2 compatibility
__author__ = "Lilian Besson"
__version__ = "0.6"
from random import random
from numpy.random import random as nprandom
# Local imports
try:
from .Arm import Arm
from .kullback import klBern
except ImportError:
from Arm import Arm
from kullback import klBern
[docs]class UniformArm(Arm):
""" Uniformly distributed arm, default in [0, 1],
- default to (mini, maxi),
- or [lower, lower + amplitude], if (lower=lower, amplitude=amplitude) is given.
>>> arm_0_1 = UniformArm()
>>> arm_0_10 = UniformArm(0, 10) # maxi = 10
>>> arm_2_4 = UniformArm(2, 4)
>>> arm_m10_10 = UniformArm(-10, 10) # also UniformArm(lower=-10, amplitude=20)
"""
[docs] def __init__(self, mini=0., maxi=1., mean=None, lower=0., amplitude=1.):
"""New arm."""
mini = max(mini, lower)
maxi = min(maxi, lower + amplitude)
if mean is not None:
assert mini <= mean <= maxi, "Error: 'mean' = {} argument for UniformArm has to be between 'mini' = {} and 'maxi' = {}...".format(mean, mini, maxi) # DEBUG
gap = min(mean - mini, maxi - mean)
assert mini <= mean - gap <= mean + gap <= maxi, "Error: computing 'gap' = {} was wrong...".format(gap) # DEBUG
mini = mean - gap
maxi = mean + gap
assert mini >= lower, "Error: 'mini' = {} argument for UniformArm has to be >= 'lower' = {}...".format(mini, lower) # DEBUG
self.lower = mini #: Lower value of rewards
assert maxi <= lower + amplitude, "Error: 'maxi' = {} argument for UniformArm has to be >= 'lower + amplitude' = {}...".format(maxi, lower + amplitude)
self.amplitude = maxi - mini #: Amplitude of rewards
# self.mean = (mini + maxi) / 2.0
self.mean = self.lower + (self.amplitude / 2.0) #: Mean for this UniformArm arm
# --- Random samples
[docs] def draw(self, t=None):
""" Draw one random sample. The parameter t is ignored in this Arm."""
return self.lower + (random() * self.amplitude)
[docs] def draw_nparray(self, shape=(1,)):
""" Draw a numpy array of random samples, of a certain shape."""
return self.lower + (nprandom(shape) * self.amplitude)
# --- Printing
[docs] def __repr__(self):
return "U({:.3g}, {:.3g})".format(self.lower, self.lower + self.amplitude)
# --- Lower bound
[docs] @staticmethod
def oneLR(mumax, mu):
""" One term of the Lai & Robbins lower bound for UniformArm arms: (mumax - mu) / KL(mu, mumax). """
return (mumax - mu) / klBern(mu, mumax)
__all__ = ["UniformArm"]
# --- Debugging
if __name__ == "__main__":
# Code for debugging purposes.
from doctest import testmod
print("\nTesting automatically all the docstring written in each functions of this module :")
testmod(verbose=True)