Environment.fairnessMeasures module

Define some function to measure fairness of a vector of cumulated rewards, of shape (nbPlayers, horizon).

Environment.fairnessMeasures.amplitude_fairness(X, axis=0)[source]

(Normalized) Amplitude fairness, homemade formula: \(1 - \min(X, axis) / \max(X, axis)\).

Examples:

>>> import numpy.random as rn; rn.seed(1)  # for reproductibility
>>> X = np.cumsum(rn.rand(10, 1000))
>>> amplitude_fairness(X)  
0.999...
>>> amplitude_fairness(X ** 2)  # More spreadout  
0.999...
>>> amplitude_fairness(np.log(1 + np.abs(X)))  # Less spreadout  
0.959...
>>> rn.seed(3)  # for reproductibility
>>> X = rn.randint(0, 10, (10, 1000)); Y = np.cumsum(X, axis=1)
>>> np.min(Y, axis=0)[0], np.max(Y, axis=0)[0]
(3, 9)
>>> np.min(Y, axis=0)[-1], np.max(Y, axis=0)[-1]
(4387, 4601)
>>> amplitude_fairness(Y, axis=0).shape
(1000,)
>>> list(amplitude_fairness(Y, axis=0))  
[0.666..., 0.764..., ..., 0.0465...]
>>> X[X >= 3] = 3; Y = np.cumsum(X, axis=1)
>>> np.min(Y, axis=0)[0], np.max(Y, axis=0)[0]
(3, 3)
>>> np.min(Y, axis=0)[-1], np.max(Y, axis=0)[-1]
(2353, 2433)
>>> amplitude_fairness(Y, axis=0).shape
(1000,)
>>> list(amplitude_fairness(Y, axis=0))  # Less spreadout 
[0.0, 0.5, ..., 0.0328...]
Environment.fairnessMeasures.std_fairness(X, axis=0)[source]

(Normalized) Standard-variation fairness, homemade formula: \(2 * \mathrm{std}(X, axis) / \max(X, axis)\).

Examples:

>>> import numpy.random as rn; rn.seed(1)  # for reproductibility
>>> X = np.cumsum(rn.rand(10, 1000))
>>> std_fairness(X)  
0.575...
>>> std_fairness(X ** 2)  # More spreadout  
0.594...
>>> std_fairness(np.sqrt(np.abs(X)))  # Less spreadout  
0.470...
>>> rn.seed(2)  # for reproductibility
>>> X = np.cumsum(rn.randint(0, 10, (10, 100)))
>>> std_fairness(X)  
0.570...
>>> std_fairness(X ** 2)  # More spreadout  
0.587...
>>> std_fairness(np.sqrt(np.abs(X)))  # Less spreadout  
0.463...
Environment.fairnessMeasures.rajjain_fairness(X, axis=0)[source]

Raj Jain’s fairness index: \((\sum_{i=1}^{n} x_i)^2 / (n \times \sum_{i=1}^{n} x_i^2)\), projected to \([0, 1]\) instead of \([\frac{1}{n}, 1]\) as introduced in the reference article.

Examples:

>>> import numpy.random as rn; rn.seed(1)  # for reproductibility
>>> X = np.cumsum(rn.rand(10, 1000))
>>> rajjain_fairness(X)  
0.248...
>>> rajjain_fairness(X ** 2)  # More spreadout  
0.441...
>>> rajjain_fairness(np.sqrt(np.abs(X)))  # Less spreadout  
0.110...
>>> rn.seed(2)  # for reproductibility
>>> X = np.cumsum(rn.randint(0, 10, (10, 100)))
>>> rajjain_fairness(X)  
0.246...
>>> rajjain_fairness(X ** 2)  # More spreadout  
0.917...
>>> rajjain_fairness(np.sqrt(np.abs(X)))  # Less spreadout  
0.107...
Environment.fairnessMeasures.mo_walrand_fairness(X, axis=0, alpha=2)[source]

Mo and Walrand’s family fairness index: \(U_{\alpha}(X)\), NOT projected to \([0, 1]\).

\[\begin{split}U_{\alpha}(X) = \begin{cases} \frac{1}{1 - \alpha} \sum_{i=1}^n x_i^{1 - \alpha} & \;\text{if}\; \alpha\in[0,+\infty)\setminus\{1\}, \\ \sum_{i=1}^{n} \ln(x_i) & \;\text{otherwise}. \end{cases}\end{split}\]

Examples:

>>> import numpy.random as rn; rn.seed(1)  # for reproductibility
>>> X = np.cumsum(rn.rand(10, 1000))
>>> alpha = 0
>>> mo_walrand_fairness(X, alpha=alpha)  
24972857.013...
>>> mo_walrand_fairness(X ** 2, alpha=alpha)  # More spreadout  
82933940429.039...
>>> mo_walrand_fairness(np.sqrt(np.abs(X)), alpha=alpha)  # Less spreadout  
471371.219...
>>> alpha = 0.99999
>>> mo_walrand_fairness(X, alpha=alpha)  
1000075176.390...
>>> mo_walrand_fairness(X ** 2, alpha=alpha)  # More spreadout  
1000150358.528...
>>> mo_walrand_fairness(np.sqrt(np.abs(X)), alpha=alpha)  # Less spreadout  
1000037587.478...
>>> alpha = 1
>>> mo_walrand_fairness(X, alpha=alpha)  
75173.509...
>>> mo_walrand_fairness(X ** 2, alpha=alpha)  # More spreadout  
150347.019...
>>> mo_walrand_fairness(np.sqrt(np.abs(X)), alpha=alpha)  # Less spreadout  
37586.754...
>>> alpha = 1.00001
>>> mo_walrand_fairness(X, alpha=alpha)  
-999924829.359...
>>> mo_walrand_fairness(X ** 2, alpha=alpha)  # More spreadout  
-999849664.476...
>>> mo_walrand_fairness(np.sqrt(np.abs(X)), alpha=alpha)  # Less spreadout  
-999962413.957...
>>> alpha = 2
>>> mo_walrand_fairness(X, alpha=alpha)  
-22.346...
>>> mo_walrand_fairness(X ** 2, alpha=alpha)  # More spreadout  
-9.874...
>>> mo_walrand_fairness(np.sqrt(np.abs(X)), alpha=alpha)  # Less spreadout  
-283.255...
>>> alpha = 5
>>> mo_walrand_fairness(X, alpha=alpha)  
-8.737...
>>> mo_walrand_fairness(X ** 2, alpha=alpha)  # More spreadout  
-273.522...
>>> mo_walrand_fairness(np.sqrt(np.abs(X)), alpha=alpha)  # Less spreadout  
-2.468...
Environment.fairnessMeasures.mean_fairness(X, axis=0, methods=(<function amplitude_fairness>, <function std_fairness>, <function rajjain_fairness>))[source]

Fairness index, based on mean of the 3 fairness measures: Amplitude, STD and Raj Jain fairness.

Examples:

>>> import numpy.random as rn; rn.seed(1)  # for reproductibility
>>> X = np.cumsum(rn.rand(10, 1000))
>>> mean_fairness(X)  
0.607...
>>> mean_fairness(X ** 2)  # More spreadout  
0.678...
>>> mean_fairness(np.sqrt(np.abs(X)))  # Less spreadout  
0.523...
>>> rn.seed(2)  # for reproductibility
>>> X = np.cumsum(rn.randint(0, 10, (10, 100)))
>>> mean_fairness(X)  
0.605...
>>> mean_fairness(X ** 2)  # More spreadout  
0.834...
>>> mean_fairness(np.sqrt(np.abs(X)))  # Less spreadout  
0.509...
Environment.fairnessMeasures.fairnessMeasure(X, axis=0, methods=(<function amplitude_fairness>, <function std_fairness>, <function rajjain_fairness>))

Default fairness measure

Environment.fairnessMeasures.fairness_mapping = {'Amplitude': <function amplitude_fairness>, 'Default': <function mean_fairness>, 'Mean': <function mean_fairness>, 'MoWalrand': <function mo_walrand_fairness>, 'RajJain': <function rajjain_fairness>, 'STD': <function std_fairness>}

Mapping of names of measure to their function