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
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
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
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
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