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 __str__(self): return "UniformArm"
[docs] def __repr__(self): return "U({:.3g}, {:.3g})".format(self.lower, self.lower + self.amplitude)
# --- Lower bound
[docs] @staticmethod def kl(x, y): """ The kl(x, y) to use for this arm.""" return klBern(x, y)
[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)