Util Module

poisson_approval.utils.Util.array_to_d_candidate_value(values)[source]

Convert an array to a dictionary of candidates and values

Parameters

values (numpy.ndarray) – An array of size 3.

Returns

The corresponding dictionary.

Return type

DictPrintingInOrderIgnoringZeros

Examples

>>> values = [42, 51, 69]
>>> array_to_d_candidate_value(values)
{'a': 42, 'b': 51, 'c': 69}
poisson_approval.utils.Util.candidates_to_d_candidate_probability(candidates)[source]

Convert a set of candidates to a dictionary of probabilities (random tie-break).

Parameters

candidates (set) – A subset of {'a', 'b', 'c'}. Typically: a set of winners.

Returns

Key: 'a', 'b' or 'c'. Value: the probability of this candidate winning with a uniformly random tie-break.

Return type

DictPrintingInOrderIgnoringZeros

Examples

>>> winners = {'a', 'b'}
>>> candidates_to_d_candidate_probability(winners)
{'a': Fraction(1, 2), 'b': Fraction(1, 2)}
poisson_approval.utils.Util.candidates_to_probabilities(candidates)[source]

Convert a set of candidates to an array of probabilities (random tie-break).

Parameters

candidates (set) – A subset of {'a', 'b', 'c'}. Typically: a set of winners.

Returns

Array of size 3. For example, the first coefficient is the probability that candidate a wins by a random tie-break.

Return type

numpy.ndarray

Examples

>>> winners = {'a', 'b'}
>>> candidates_to_probabilities(winners)
array([Fraction(1, 2), Fraction(1, 2), 0], dtype=object)
poisson_approval.utils.Util.d_candidate_value_to_array(d_candidate_value)[source]

Convert a dictionary of candidates and values to an array

Parameters

d_candidate_value (dict) – Key: 'a', 'b' or 'c'.

Returns

The corresponding array.

Return type

numpy.ndarray

Examples

>>> d_candidate_value = {'a': 42, 'b': 51, 'c': 69}
>>> d_candidate_value_to_array(d_candidate_value)
array([42, 51, 69])
poisson_approval.utils.Util.give_figure(n, singular, plural=None)[source]

Combine a number with a unit, whose word can be singular or plural.

Parameters
  • n (int) – The number.

  • singular (str) – The singular word.

  • plural (str) – The plural word. Default: the singular with a final “s”.

Returns

The number and the word.

Return type

str

Examples

>>> give_figure(1, 'apple')
'1 apple'
>>> give_figure(2, 'apple')
'2 apples'
>>> give_figure(1, 'equilibrium', 'equilibria')
'1 equilibrium'
>>> give_figure(2, 'equilibrium', 'equilibria')
'2 equilibria'
poisson_approval.utils.Util.image_distribution(factory, n_samples, f, conditional_on=None)[source]

Distribution of f(something) for a random something.

Parameters
  • factory (callable or tuple) –

    This can be:

    • Either a callable that takes no input and that outputs a (random) something,

    • Or a tuple of such factories (cf. examples below).

  • n_samples (int) – Number of samples.

  • f (callable) – A function that take as input(s) the output(s) of the factory(ies).

  • conditional_on (callable) – A function that take as input(s) the output(s) of the factory(ies) and that returns a Boolean. Default: always True.

Returns

Keys: the obtained outputs for f. Values: the probability that f(something) has this output when something is generated by factory, conditional on the fact that it meets conditional_on, based on a Monte-Carlo estimation of n_samples trials.

Return type

DictPrintingInOrder

Examples

In this basic example with one factory, we compute the distribution of n modulo 10, when n is drawn uniformly at random between 0 included and 100 excluded, conditionally on the fact that n is even:

>>> initialize_random_seeds()
>>> def rand_integer():
...     return np.random.randint(0, 100)
>>> def modulo_10(n):
...     return n % 10
>>> def is_even(n):
...     return n % 2 == 0
>>> image_distribution(factory=rand_integer, n_samples=100, f=modulo_10, conditional_on=is_even)
{0: 0.21, 2: 0.21, 4: 0.2, 6: 0.18, 8: 0.2}

In this example with a tuple of factories, we compute the distribution of a mod b, when a is drawn uniformly at random between 0 included and 100 excluded, and b is drawn uniformly at random between 1 included and 11 excluded:

>>> initialize_random_seeds()
>>> def rand_integer():
...     return np.random.randint(0, 100)
>>> def rand_divider():
...     return np.random.randint(1, 11)
>>> def modulo(a, b):
...     return a % b
>>> image_distribution(factory=(rand_integer, rand_divider),
...                    n_samples=100, f=modulo)
{0: 0.31, 1: 0.16, 2: 0.18, 3: 0.12, 4: 0.07, 5: 0.04, 6: 0.02, 7: 0.08, 9: 0.02}
poisson_approval.utils.Util.initialize_random_seeds(n=0)[source]

Initialize the random seeds.

Parameters

n (int) – The desired random seed. Default: 0.

poisson_approval.utils.Util.isnan(x)[source]

Is nan.

Parameters

x (Number) –

Returns

True if x is nan.

Return type

bool

Notes

This extends the usual numpy function isnan to fractions and sympy expressions.

Examples

>>> values = [sp.sqrt(3) - sp.sqrt(2), sp.nan,
...           sp.oo, - sp.oo,
...           sp.Rational(3, 5), Fraction(3, 5),
...           1, 0.42, np.inf, -np.inf, np.nan]
>>> print([x for x in values if isnan(x)])
[nan, nan]
poisson_approval.utils.Util.isneginf(x)[source]

Is negative infinity.

Parameters

x (Number) –

Returns

True if x is negative infinity.

Return type

bool

Notes

This extends the usual numpy function isneginf to fractions and sympy expressions.

Examples

>>> values = [sp.sqrt(3) - sp.sqrt(2), sp.nan,
...           sp.oo, - sp.oo,
...           sp.Rational(3, 5), Fraction(3, 5),
...           1, 0.42, np.inf, -np.inf, np.nan]
>>> print([x for x in values if isneginf(x)])
[-oo, -inf]
poisson_approval.utils.Util.isposinf(x)[source]

Is positive infinity.

Parameters

x (Number) –

Returns

True if x is positive infinity.

Return type

bool

Notes

This extends the usual numpy function isposinf to fractions and sympy expressions.

Examples

>>> values = [sp.sqrt(3) - sp.sqrt(2), sp.nan,
...           sp.oo, - sp.oo,
...           sp.Rational(3, 5), Fraction(3, 5),
...           1, 0.42, np.inf, -np.inf, np.nan]
>>> print([x for x in values if isposinf(x)])
[oo, inf]
poisson_approval.utils.Util.iterate_simplex_grid(d, denominator)[source]

Iterate over the points in the simplex, with rational coordinates of a given denominator

Parameters
  • d (int) – Number of coordinates. In other words, we consider the simplex of dimension d - 1.

  • denominator (int or iterable) – The coordinates will be fractions with this denominator. If an iterable is given, we consider each denominator given by the iterable.

Returns

Each tuple of length d, whose coordinates are fractions of the given denominator, and whose sum is 1.

Return type

tuple

Examples

>>> for t in iterate_simplex_grid(d=3, denominator=range(1, 3)):
...     print(t)
(1, 0, 0)
(0, 1, 0)
(0, 0, 1)
(1, 0, 0)
(Fraction(1, 2), Fraction(1, 2), 0)
(Fraction(1, 2), 0, Fraction(1, 2))
(0, 1, 0)
(0, Fraction(1, 2), Fraction(1, 2))
(0, 0, 1)
poisson_approval.utils.Util.iterator_integers_fixed_sum(d, fixed_sum)[source]

Iterate over vectors of integers with a fixed sum.

Parameters
  • d (int) – The desired number of integers. In other words, we consider a simplex of dimension d - 1.

  • fixed_sum (int) – The fixed sum.

Yields

tuple – Each tuple of d integers, whose sum is fixed_sum.

Examples

>>> for t in iterator_integers_fixed_sum(d=3, fixed_sum=2):
...     print(t)
(2, 0, 0)
(1, 1, 0)
(1, 0, 1)
(0, 2, 0)
(0, 1, 1)
(0, 0, 2)
poisson_approval.utils.Util.my_division(x, y)[source]

Division of two numbers, trying to be exact if it is reasonable.

Parameters
  • x (Number) –

  • y (Number) –

Returns

The division of x by y.

Return type

Number

Examples

Typical usages:

>>> my_division(6, 2)
3
>>> my_division(5, 2)
Fraction(5, 2)

If x or y is a float, then the result is a float:

>>> my_division(Fraction(5, 2), 0.1)
25.0
>>> my_division(0.1, Fraction(5, 2))
0.04

If x and y are integers, decimals, fractions or sympy expressions, then the result is symbolic:

>>> my_division(2, Fraction(5, 2))
Fraction(4, 5)
>>> my_division(Decimal('0.1'), Fraction(5, 2))
Fraction(1, 25)
>>> my_division(sp.sqrt(3), 2)
sqrt(3)/2

Possible errors:

>>> my_division(1, 0)
Traceback (most recent call last):
ZeroDivisionError: division by zero
>>> my_division(1, 'foo')
Traceback (most recent call last):
TypeError: unsupported operand type(s) for /: 'Fraction' and 'str'
poisson_approval.utils.Util.my_range(start, end, step)[source]

Iterable range adapted for fractions.

Parameters
  • start (Number) – Start value (included).

  • end (Number) – End value (excluded).

  • step (Number) – Increment of the counter.

Examples

>>> for x in my_range(0, 1, Fraction(1, 3)):
...     print(x)
0
1/3
2/3
>>> for x in my_range(1, 0, - Fraction(1, 3)):
...     print(x)
1
2/3
1/3
poisson_approval.utils.Util.my_sign(x)[source]

Sign.

Parameters

x (Number) –

Returns

Sign of x.

Return type

int

Examples

>>> my_sign(1.5)
1
>>> my_sign(0)
0
>>> my_sign(-4.2)
-1
poisson_approval.utils.Util.normalize_dict_to_0_1(d)[source]

Normalize the values of a dictionary to the interval [0, 1].

Parameters

d (dict) – Values must be numbers.

Returns

The same dictionary, but an affine transformation is applied so that the minimum value is 0 and the maximum value is 1.

Return type

DictPrintingInOrder

Examples

Typical usage:

>>> d_candidate_welfare = {'a': 0.1, 'b': 0.2, 'c': 0.5}
>>> d_candidate_relative_welfare = normalize_dict_to_0_1(d_candidate_welfare)
>>> d_candidate_relative_welfare
{'a': 0.0, 'b': 0.25, 'c': 1.0}

If all the values are equal, then conventionally all values are converted to 1:

>>> d_candidate_welfare = {'a': 0.1, 'b': 0.1, 'c': 0.1}
>>> d_candidate_relative_welfare = normalize_dict_to_0_1(d_candidate_welfare)
>>> d_candidate_relative_welfare
{'a': 1, 'b': 1, 'c': 1}
poisson_approval.utils.Util.one_over_log_log_t_plus_fourteen(t)[source]

Function 1 / log(log(t + 14)).

This function is provided as an example of update ratio for fictitious_play(). The constant 14 in the denominator is the smallest integer such that f(t = 2) < 1.

Parameters

t (Number) –

Returns

1 / log(log(t + 14)).

Return type

Number

Examples

>>> one_over_log_log_t_plus_fourteen(2)
0.9806022744169713
poisson_approval.utils.Util.one_over_log_t_plus_one(t)[source]

Function 1 / log(t + 1).

This function is provided as an example of update ratio for fictitious_play(). The constant 1 in the denominator is the smallest integer such that f(t = 2) < 1.

Parameters

t (Number) –

Returns

1 / log(t + 1).

Return type

Number

Examples

>>> one_over_log_t_plus_one(2)
0.9102392266268373
poisson_approval.utils.Util.one_over_sqrt_t(t)[source]

Function 1 / sqrt(t).

This function is provided as an example of update ratio for fictitious_play().

Parameters

t (Number) –

Returns

1 / sqrt(t).

Return type

Number

Examples

>>> one_over_sqrt_t(2)
0.7071067811865475
poisson_approval.utils.Util.one_over_t(t)[source]

Function 1 / t.

When used as an update ratio (cf. fictitious_play()), this amounts to computing the arithmetic mean.

Parameters

t (Number) –

Returns

1 / t.

Return type

Number

Examples

>>> one_over_t(2)
Fraction(1, 2)
poisson_approval.utils.Util.probability(factory, n_samples, test, conditional_on=None)[source]

Probability that a random something meets some given test.

Parameters
  • factory (callable or tuple of callable) –

    This can be:

    • Either a callable that takes no input and that outputs a (random) something,

    • Or a tuple of such factories (cf. examples below).

  • n_samples (int) – Number of samples.

  • test (callable or tuple of callable) –

    This can be:

    • Either a function that take as input(s) the output(s) of the factory(ies) and that returns a Boolean.

    • Or a tuple of such functions (cf. examples below).

  • conditional_on (callable) – A function that take as input(s) the output(s) of the factory(ies) and that returns a Boolean. Default: always True.

Returns

This can be:

  • Either the probability that the output(s) generated by factory meet(s) test, conditional on the fact that it meets conditional_on, based on a Monte-Carlo estimation of n_samples trials.

  • Or a tuple giving this probability for each member of test, when test is a tuple itself.

Return type

float or tuple of float

Examples

In this basic example with one factory, we estimate the probability that a random float between 0 and 1 is greater than .5, conditionally on being greater than .25:

>>> initialize_random_seeds()
>>> def rand_number():
...     return random.random()
>>> probability(factory=rand_number, n_samples=1000,
...             test=lambda x: x > .5, conditional_on=lambda x: x > .25)
0.661

In this example with a tuple of factories, we estimate the probability that a random 2*2 matrix and a random vector of size 2, both with integer coefficients between -10 included and 11 excluded, have a dot product that is null, conditionally on not being null themselves:

>>> initialize_random_seeds()
>>> def rand_matrix():
...     return np.random.randint(-10, 11, (2, 2))
>>> def rand_vector():
...     return np.random.randint(-10, 11, 2)
>>> def test_dot_zero(matrix, vector):
...     return np.all(np.dot(matrix, vector) == 0)
>>> def test_non_trivial(matrix, vector):
...     return not np.all(matrix == 0) and not np.all(vector == 0)
>>> probability(factory=(rand_matrix, rand_vector), n_samples=10000,
...             test=test_dot_zero, conditional_on=test_non_trivial)
0.0003

In the following example, we estimate the probability that a random float between 0 and 1 is greater than .5, and the probability that it is greater than .75, conditionally on being greater than .25:

>>> initialize_random_seeds()
>>> def rand_number():
...     return random.random()
>>> probability(factory=rand_number, n_samples=1000,
...             test=(lambda x: x > .5, lambda x: x > .75), conditional_on=lambda x: x > .25)
(0.661, 0.332)

When using a tuple of tests, the same sample is used to estimate each probability.

poisson_approval.utils.Util.product_dict(d_key_possible_values)[source]

Iterable: product of dictionaries.

Source: https://stackoverflow.com/questions/5228158/cartesian-product-of-a-dictionary-of-lists.

Parameters

d_key_possible_values – To each key, associate a list of possible values (cf. example below).

Yields

dict – A dictionary that, to each key, associates one of its possible values. All elements of the Cartesian product are returned this way.

Examples

>>> d_key_possible_values = {'foo': [0, 1], 'bar': ['a', 'b', 'c']}
>>> for d_key_value in product_dict(d_key_possible_values):
...     print(d_key_value)
{'foo': 0, 'bar': 'a'}
{'foo': 0, 'bar': 'b'}
{'foo': 0, 'bar': 'c'}
{'foo': 1, 'bar': 'a'}
{'foo': 1, 'bar': 'b'}
{'foo': 1, 'bar': 'c'}
poisson_approval.utils.Util.rand_integers_fixed_sum(d, fixed_sum)[source]

Generate integers with a given sum (uniformly).

Parameters
  • d (int) – The desired number of integers. In other words, we consider a simplex of dimension d - 1.

  • fixed_sum (int) – The fixed sum.

Returns

A numpy array of d integers, whose sum is fixed_sum, and drawn uniformly.

Return type

numpy.ndarray

Examples

>>> initialize_random_seeds()
>>> rand_integers_fixed_sum(d=6, fixed_sum=100)
array([ 2, 23, 34,  0, 22, 19])
poisson_approval.utils.Util.rand_simplex(d=6)[source]

Draw a random point in the simplex.

Parameters

d (int) – Number of coordinates. In other words, we consider the simplex of dimension d - 1.

Returns

A numpy array of length d, whose sum is 1.

Return type

numpy.ndarray

Examples

>>> initialize_random_seeds()
>>> rand_simplex(d=6)  
array([0.4236548 , 0.12122838, 0.00393032, 0.05394987, 0.11242599, 0.28481063])
poisson_approval.utils.Util.rand_simplex_grid(d, denominator)[source]

Draw a random point in the simplex, with rational coordinates of a given denominator

Parameters
  • d (int) – Number of coordinates. In other words, we consider the simplex of dimension d - 1.

  • denominator (int) – The coordinates will be fractions with this denominator.

Returns

A numpy array of length d, whose coordinates are fractions of the given denominator, and whose sum is 1.

Return type

numpy.ndarray

Examples

>>> initialize_random_seeds()
>>> rand_simplex_grid(d=3, denominator=100)
array([Fraction(13, 50), Fraction(13, 20), Fraction(9, 100)], dtype=object)
poisson_approval.utils.Util.to_callable(o)[source]

Convert to a callable.

Parameters

o (object) –

Returns

The conversion of o to a callable.

Return type

callable

Examples

If o is callable, then return o:

>>> def square(x):
...     return x**2
>>> my_function = to_callable(square)
>>> my_function(4)
16

If o is not callable, then return a function *args, **kwargs -> o:

>>> x = 42
>>> my_function = to_callable(x)
>>> my_function('some_argument', keyword='some_value')
42