Co-operative Games With Finite Players - Game Theory

Skip to content
Back to top
View this page
Edit this page

# Co-operative Games With Finite Players

This module implements a class for a characteristic function cooperative game. Methods to calculate the Shapley value (a fair way of sharing common resources: see [CEW2011]) as well as test properties of the game (monotonicity, superadditivity) are also included.

AUTHORS:

- James Campbell and Vince Knight (06-2014): Original version

class sage.game_theory.cooperative_game.CooperativeGame(characteristic_function)

  Bases: `SageObject`

  An object representing a co-operative game. Primarily used to compute the Shapley value, but can also provide other information.

  INPUT:

  - `characteristic_function` – dictionary containing all possible sets of players:

    - key - each set must be entered as a tuple.

    - value - a real number representing each set of players contribution

  EXAMPLES:

  The type of game that is currently implemented is referred to as a Characteristic function game. This is a game on a set of players \(\Omega\) that is defined by a value function \(v : C \to \RR\) where \(C = 2^{\Omega}\) is the set of all coalitions of players. Let \(N := |\Omega|\). An example of such a game is shown below:

  \[\begin{split}v(c) = \begin{cases} 0 &\text{if } c = \emptyset, \\ 6 &\text{if } c = \{1\}, \\ 12 &\text{if } c = \{2\}, \\ 42 &\text{if } c = \{3\}, \\ 12 &\text{if } c = \{1,2\}, \\ 42 &\text{if } c = \{1,3\}, \\ 42 &\text{if } c = \{2,3\}, \\ 42 &\text{if } c = \{1,2,3\}. \\ \end{cases}\end{split}\]

  The function \(v\) can be thought of as a record of contribution of individuals and coalitions of individuals. Of interest, becomes how to fairly share the value of the grand coalition (\(\Omega\))? This class allows for such an answer to be formulated by calculating the Shapley value of the game.

  Basic examples of how to implement a co-operative game. These functions will be used repeatedly in other examples.

  Sage

      sage: integer_function = {(): 0,
      ....:                     (1,): 6,
      ....:                     (2,): 12,
      ....:                     (3,): 42,
      ....:                     (1, 2,): 12,
      ....:                     (1, 3,): 42,
      ....:                     (2, 3,): 42,
      ....:                     (1, 2, 3,): 42}
      sage: integer_game = CooperativeGame(integer_function)

  Python

      >>> from sage.all import *
      >>> integer_function = {(): Integer(0),
      ...                     (Integer(1),): Integer(6),
      ...                     (Integer(2),): Integer(12),
      ...                     (Integer(3),): Integer(42),
      ...                     (Integer(1), Integer(2),): Integer(12),
      ...                     (Integer(1), Integer(3),): Integer(42),
      ...                     (Integer(2), Integer(3),): Integer(42),
      ...                     (Integer(1), Integer(2), Integer(3),): Integer(42)}
      >>> integer_game = CooperativeGame(integer_function)

  We can also use strings instead of numbers.

  Sage

      sage: letter_function = {(): 0,
      ....:                    ('A',): 6,
      ....:                    ('B',): 12,
      ....:                    ('C',): 42,
      ....:                    ('A', 'B',): 12,
      ....:                    ('A', 'C',): 42,
      ....:                    ('B', 'C',): 42,
      ....:                    ('A', 'B', 'C',): 42}
      sage: letter_game = CooperativeGame(letter_function)

  [Python]

      >>> from sage.all import *
      >>> letter_function = {(): Integer(0),
      ...                    ('A',): Integer(6),
      ...                    ('B',): Integer(12),
      ...                    ('C',): Integer(42),
      ...                    ('A', 'B',): Integer(12),
      ...                    ('A', 'C',): Integer(42),
      ...                    ('B', 'C',): Integer(42),
      ...                    ('A', 'B', 'C',): Integer(42)}
      >>> letter_game = CooperativeGame(letter_function)

  Please note that keys should be tuples. `'1, 2, 3'` is not a valid key, neither is `123`. The correct input would be `(1, 2, 3)`. Similarly, for coalitions containing a single element the bracket notation (which tells Sage that it is a tuple) must be used. So `(1)`, `(1,)` are correct however simply inputting \(1\) is not.

  Characteristic function games can be of various types.

  A characteristic function game \(G = (N, v)\) is monotone if it satisfies \(v(C_2) \geq v(C_1)\) for all \(C_1 \subseteq C_2\). A characteristic function game \(G = (N, v)\) is superadditive if it satisfies \(v(C_1 \cup C_2) \geq v(C_1) + v(C_2)\) for all \(C_1, C_2 \subseteq 2^{\Omega}\) such that \(C_1 \cap C_2 = \emptyset\).

  We can test if a game is monotonic or superadditive.

  Sage

      sage: letter_game.is_monotone()
      True
      sage: letter_game.is_superadditive()
      False

  Python

      >>> from sage.all import *
      >>> letter_game.is_monotone()
      True
      >>> letter_game.is_superadditive()
      False

  Instances have a basic representation that will display basic information about the game:

  Sage

      sage: letter_game
      A 3 player co-operative game

  [Python]

      >>> from sage.all import *
      >>> letter_game
      A 3 player co-operative game

  It can be shown that the “fair” payoff vector, referred to as the Shapley value is given by the following formula:

  \[\phi_i(G) = \frac{1}{N!} \sum_{\pi\in\Pi_n} \Delta_{\pi}^G(i),\]

  where the summation is over the permutations of the players and the marginal contributions of a player for a given permutation is given as:

  \[\Delta_{\pi}^G(i) = v\bigl( S_{\pi}(i) \cup \{i\} \bigr) - v\bigl( S_{\pi}(i) \bigr)\]

  where \(S_{\pi}(i)\) is the set of predecessors of \(i\) in \(\pi\), i.e. \(S_{\pi}(i) = \{ j \mid \pi(i) > \pi(j) \}\) (or the number of inversions of the form \((i, j)\)).

  This payoff vector is “fair” in that it has a collection of properties referred to as: efficiency, symmetry, additivity and Null player. Some of these properties are considered in this documentation (and tests are implemented in the class) but for a good overview see [CEW2011].

  Note ([MSZ2013]) that an equivalent formula for the Shapley value is given by:

  \[\phi_i(G) = \sum_{S \subseteq \Omega} \sum_{p \in S} \frac{(|S|-1)!(N-|S|)!}{N!} \bigl( v(S) - v(S \setminus \{p\}) \bigr) = \sum_{S \subseteq \Omega} \sum_{p \in S} \frac{1}{|S|\binom{N}{|S|}} \bigl( v(S) - v(S \setminus \{p\}) \bigr).\]

  This later formulation is implemented in Sage and requires \(2^N-1\) calculations instead of \(N!\).

  To compute the Shapley value in Sage is simple:

  Sage

      sage: letter_game.shapley_value()
      {'A': 2, 'B': 5, 'C': 35}

  Python

      >>> from sage.all import *
      >>> letter_game.shapley_value()
      {'A': 2, 'B': 5, 'C': 35}

  The following example implements a (trivial) 10 player characteristic function game with \(v(c) = |c|\) for all \(c \in 2^{\Omega}\).

  Sage

      sage: def simple_characteristic_function(N):
      ....:     return {tuple(coalition) : len(coalition)
      ....:                   for coalition in subsets(range(N))}
      sage: g = CooperativeGame(simple_characteristic_function(10))
      sage: g.shapley_value()
      {0: 1, 1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1, 7: 1, 8: 1, 9: 1}

  [Python]

      >>> from sage.all import *
      >>> def simple_characteristic_function(N):
      ...     return {tuple(coalition) : len(coalition)
      ...                   for coalition in subsets(range(N))}
      >>> g = CooperativeGame(simple_characteristic_function(Integer(10)))
      >>> g.shapley_value()
      {0: 1, 1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1, 7: 1, 8: 1, 9: 1}

  For very large games it might be worth taking advantage of the particular problem structure to calculate the Shapley value and there are also various approximation approaches to obtaining the Shapley value of a game (see [SWJ2008] for one such example). Implementing these would be a worthwhile development For more information about the computational complexity of calculating the Shapley value see [XP1994].

  We can test 3 basic properties of any payoff vector \(\lambda\). The Shapley value (described above) is known to be the unique payoff vector that satisfies these and 1 other property not implemented here (additivity). They are:

  - Efficiency - \(\sum_{i=1}^N \lambda_i = v(\Omega)\) In other words, no value of the total coalition is lost.

  - The nullplayer property - If there exists an \(i\) such that \(v(C \cup i) = v(C)\) for all \(C \in 2^{\Omega}\) then, \(\lambda_i = 0\). In other words: if a player does not contribute to any coalition then that player should receive no payoff.

  - Symmetry property - If \(v(C \cup i) = v(C \cup j)\) for all \(C \in 2^{\Omega} \setminus \{i,j\}\), then \(x_i = x_j\). If players contribute symmetrically then they should get the same payoff:

    Sage

        sage: payoff_vector = letter_game.shapley_value()
        sage: letter_game.is_efficient(payoff_vector)
        True
        sage: letter_game.nullplayer(payoff_vector)
        True
        sage: letter_game.is_symmetric(payoff_vector)
        True

    Python

        >>> from sage.all import *
        >>> payoff_vector = letter_game.shapley_value()
        >>> letter_game.is_efficient(payoff_vector)
        True
        >>> letter_game.nullplayer(payoff_vector)
        True
        >>> letter_game.is_symmetric(payoff_vector)
        True

  Any payoff vector can be passed to the game and these properties can once again be tested:

  Sage

      sage: payoff_vector = {'A': 0, 'C': 35, 'B': 3}
      sage: letter_game.is_efficient(payoff_vector)
      False
      sage: letter_game.nullplayer(payoff_vector)
      True
      sage: letter_game.is_symmetric(payoff_vector)
      True

  Python

      >>> from sage.all import *
      >>> payoff_vector = {'A': Integer(0), 'C': Integer(35), 'B': Integer(3)}
      >>> letter_game.is_efficient(payoff_vector)
      False
      >>> letter_game.nullplayer(payoff_vector)
      True
      >>> letter_game.is_symmetric(payoff_vector)
      True

  is_efficient(payoff_vector)

    Return `True` if `payoff_vector` is efficient.

    A payoff vector \(v\) is efficient if \(\sum_{i=1}^N \lambda_i = v(\Omega)\); in other words, no value of the total coalition is lost.

    INPUT:

    - `payoff_vector` – dictionary where the key is the player and the value is their payoff

    EXAMPLES:

    An efficient payoff vector:

    Sage

        sage: letter_function = {(): 0,
        ....:                    ('A',): 6,
        ....:                    ('B',): 12,
        ....:                    ('C',): 42,
        ....:                    ('A', 'B',): 12,
        ....:                    ('A', 'C',): 42,
        ....:                    ('B', 'C',): 42,
        ....:                    ('A', 'B', 'C',): 42}
        sage: letter_game = CooperativeGame(letter_function)
        sage: letter_game.is_efficient({'A': 14, 'B': 14, 'C': 14})
        True

        sage: letter_function = {(): 0,
        ....:                    ('A',): 6,
        ....:                    ('B',): 12,
        ....:                    ('C',): 42,
        ....:                    ('A', 'B',): 12,
        ....:                    ('A', 'C',): 42,
        ....:                    ('B', 'C',): 42,
        ....:                    ('A', 'B', 'C',): 42}
        sage: letter_game = CooperativeGame(letter_function)
        sage: letter_game.is_efficient({'A': 10, 'B': 14, 'C': 14})
        False

    Python

        >>> from sage.all import *
        >>> letter_function = {(): Integer(0),
        ...                    ('A',): Integer(6),
        ...                    ('B',): Integer(12),
        ...                    ('C',): Integer(42),
        ...                    ('A', 'B',): Integer(12),
        ...                    ('A', 'C',): Integer(42),
        ...                    ('B', 'C',): Integer(42),
        ...                    ('A', 'B', 'C',): Integer(42)}
        >>> letter_game = CooperativeGame(letter_function)
        >>> letter_game.is_efficient({'A': Integer(14), 'B': Integer(14), 'C': Integer(14)})
        True

        >>> letter_function = {(): Integer(0),
        ...                    ('A',): Integer(6),
        ...                    ('B',): Integer(12),
        ...                    ('C',): Integer(42),
        ...                    ('A', 'B',): Integer(12),
        ...                    ('A', 'C',): Integer(42),
        ...                    ('B', 'C',): Integer(42),
        ...                    ('A', 'B', 'C',): Integer(42)}
        >>> letter_game = CooperativeGame(letter_function)
        >>> letter_game.is_efficient({'A': Integer(10), 'B': Integer(14), 'C': Integer(14)})
        False

    A longer example:

    Sage

        sage: long_function = {(): 0,
        ....:                  (1,): 0,
        ....:                  (2,): 0,
        ....:                  (3,): 0,
        ....:                  (4,): 0,
        ....:                  (1, 2): 0,
        ....:                  (1, 3): 0,
        ....:                  (1, 4): 0,
        ....:                  (2, 3): 0,
        ....:                  (2, 4): 0,
        ....:                  (3, 4): 0,
        ....:                  (1, 2, 3): 0,
        ....:                  (1, 2, 4): 45,
        ....:                  (1, 3, 4): 40,
        ....:                  (2, 3, 4): 0,
        ....:                  (1, 2, 3, 4): 65}
        sage: long_game = CooperativeGame(long_function)
        sage: long_game.is_efficient({1: 20, 2: 20, 3: 5, 4: 20})
        True

    [Python]

        >>> from sage.all import *
        >>> long_function = {(): Integer(0),
        ...                  (Integer(1),): Integer(0),
        ...                  (Integer(2),): Integer(0),
        ...                  (Integer(3),): Integer(0),
        ...                  (Integer(4),): Integer(0),
        ...                  (Integer(1), Integer(2)): Integer(0),
        ...                  (Integer(1), Integer(3)): Integer(0),
        ...                  (Integer(1), Integer(4)): Integer(0),
        ...                  (Integer(2), Integer(3)): Integer(0),
        ...                  (Integer(2), Integer(4)): Integer(0),
        ...                  (Integer(3), Integer(4)): Integer(0),
        ...                  (Integer(1), Integer(2), Integer(3)): Integer(0),
        ...                  (Integer(1), Integer(2), Integer(4)): Integer(45),
        ...                  (Integer(1), Integer(3), Integer(4)): Integer(40),
        ...                  (Integer(2), Integer(3), Integer(4)): Integer(0),
        ...                  (Integer(1), Integer(2), Integer(3), Integer(4)): Integer(65)}
        >>> long_game = CooperativeGame(long_function)
        >>> long_game.is_efficient({Integer(1): Integer(20), Integer(2): Integer(20), Integer(3): Integer(5), Integer(4): Integer(20)})
        True

  is_monotone()

    Return `True` if `self` is monotonic.

    A game \(G = (N, v)\) is monotonic if it satisfies \(v(C_2) \geq v(C_1)\) for all \(C_1 \subseteq C_2\).

    EXAMPLES:

    A simple game that is monotone:

    Sage

        sage: integer_function = {(): 0,
        ....:                  (1,): 6,
        ....:                  (2,): 12,
        ....:                  (3,): 42,
        ....:                  (1, 2,): 12,
        ....:                  (1, 3,): 42,
        ....:                  (2, 3,): 42,
        ....:                  (1, 2, 3,): 42}
        sage: integer_game = CooperativeGame(integer_function)
        sage: integer_game.is_monotone()
        True

    Python

        >>> from sage.all import *
        >>> integer_function = {(): Integer(0),
        ...                  (Integer(1),): Integer(6),
        ...                  (Integer(2),): Integer(12),
        ...                  (Integer(3),): Integer(42),
        ...                  (Integer(1), Integer(2),): Integer(12),
        ...                  (Integer(1), Integer(3),): Integer(42),
        ...                  (Integer(2), Integer(3),): Integer(42),
        ...                  (Integer(1), Integer(2), Integer(3),): Integer(42)}
        >>> integer_game = CooperativeGame(integer_function)
        >>> integer_game.is_monotone()
        True

    An example when the game is not monotone:

    Sage

        sage: integer_function = {(): 0,
        ....:                  (1,): 6,
        ....:                  (2,): 12,
        ....:                  (3,): 42,
        ....:                  (1, 2,): 10,
        ....:                  (1, 3,): 42,
        ....:                  (2, 3,): 42,
        ....:                  (1, 2, 3,): 42}
        sage: integer_game = CooperativeGame(integer_function)
        sage: integer_game.is_monotone()
        False

    [Python]

        >>> from sage.all import *
        >>> integer_function = {(): Integer(0),
        ...                  (Integer(1),): Integer(6),
        ...                  (Integer(2),): Integer(12),
        ...                  (Integer(3),): Integer(42),
        ...                  (Integer(1), Integer(2),): Integer(10),
        ...                  (Integer(1), Integer(3),): Integer(42),
        ...                  (Integer(2), Integer(3),): Integer(42),
        ...                  (Integer(1), Integer(2), Integer(3),): Integer(42)}
        >>> integer_game = CooperativeGame(integer_function)
        >>> integer_game.is_monotone()
        False

    An example on a longer game:

    Sage

        sage: long_function = {(): 0,
        ....:                  (1,): 0,
        ....:                  (2,): 0,
        ....:                  (3,): 0,
        ....:                  (4,): 0,
        ....:                  (1, 2): 0,
        ....:                  (1, 3): 0,
        ....:                  (1, 4): 0,
        ....:                  (2, 3): 0,
        ....:                  (2, 4): 0,
        ....:                  (3, 4): 0,
        ....:                  (1, 2, 3): 0,
        ....:                  (1, 2, 4): 45,
        ....:                  (1, 3, 4): 40,
        ....:                  (2, 3, 4): 0,
        ....:                  (1, 2, 3, 4): 65}
        sage: long_game = CooperativeGame(long_function)
        sage: long_game.is_monotone()
        True

    Python

        >>> from sage.all import *
        >>> long_function = {(): Integer(0),
        ...                  (Integer(1),): Integer(0),
        ...                  (Integer(2),): Integer(0),
        ...                  (Integer(3),): Integer(0),
        ...                  (Integer(4),): Integer(0),
        ...                  (Integer(1), Integer(2)): Integer(0),
        ...                  (Integer(1), Integer(3)): Integer(0),
        ...                  (Integer(1), Integer(4)): Integer(0),
        ...                  (Integer(2), Integer(3)): Integer(0),
        ...                  (Integer(2), Integer(4)): Integer(0),
        ...                  (Integer(3), Integer(4)): Integer(0),
        ...                  (Integer(1), Integer(2), Integer(3)): Integer(0),
        ...                  (Integer(1), Integer(2), Integer(4)): Integer(45),
        ...                  (Integer(1), Integer(3), Integer(4)): Integer(40),
        ...                  (Integer(2), Integer(3), Integer(4)): Integer(0),
        ...                  (Integer(1), Integer(2), Integer(3), Integer(4)): Integer(65)}
        >>> long_game = CooperativeGame(long_function)
        >>> long_game.is_monotone()
        True

  is_superadditive()

    Return `True` if `self` is superadditive.

    A characteristic function game \(G = (N, v)\) is superadditive if it satisfies \(v(C_1 \cup C_2) \geq v(C_1) + v(C_2)\) for all \(C_1, C_2 \subseteq 2^{\Omega}\) such that \(C_1 \cap C_2 = \emptyset\).

    EXAMPLES:

    An example that is not superadditive:

    Sage

        sage: integer_function = {(): 0,
        ....:                  (1,): 6,
        ....:                  (2,): 12,
        ....:                  (3,): 42,
        ....:                  (1, 2,): 12,
        ....:                  (1, 3,): 42,
        ....:                  (2, 3,): 42,
        ....:                  (1, 2, 3,): 42}
        sage: integer_game = CooperativeGame(integer_function)
        sage: integer_game.is_superadditive()
        False

    Python

        >>> from sage.all import *
        >>> integer_function = {(): Integer(0),
        ...                  (Integer(1),): Integer(6),
        ...                  (Integer(2),): Integer(12),
        ...                  (Integer(3),): Integer(42),
        ...                  (Integer(1), Integer(2),): Integer(12),
        ...                  (Integer(1), Integer(3),): Integer(42),
        ...                  (Integer(2), Integer(3),): Integer(42),
        ...                  (Integer(1), Integer(2), Integer(3),): Integer(42)}
        >>> integer_game = CooperativeGame(integer_function)
        >>> integer_game.is_superadditive()
        False

    An example that is superadditive:

    Sage

        sage: A_function = {(): 0,
        ....:               (1,): 6,
        ....:               (2,): 12,
        ....:               (3,): 42,
        ....:               (1, 2,): 18,
        ....:               (1, 3,): 48,
        ....:               (2, 3,): 55,
        ....:               (1, 2, 3,): 80}
        sage: A_game = CooperativeGame(A_function)
        sage: A_game.is_superadditive()
        True

    [Python]

        >>> from sage.all import *
        >>> A_function = {(): Integer(0),
        ...               (Integer(1),): Integer(6),
        ...               (Integer(2),): Integer(12),
        ...               (Integer(3),): Integer(42),
        ...               (Integer(1), Integer(2),): Integer(18),
        ...               (Integer(1), Integer(3),): Integer(48),
        ...               (Integer(2), Integer(3),): Integer(55),
        ...               (Integer(1), Integer(2), Integer(3),): Integer(80)}
        >>> A_game = CooperativeGame(A_function)
        >>> A_game.is_superadditive()
        True

    An example with a longer game that is superadditive:

    Sage

        sage: long_function = {(): 0,
        ....:                  (1,): 0,
        ....:                  (2,): 0,
        ....:                  (3,): 0,
        ....:                  (4,): 0,
        ....:                  (1, 2): 0,
        ....:                  (1, 3): 0,
        ....:                  (1, 4): 0,
        ....:                  (2, 3): 0,
        ....:                  (2, 4): 0,
        ....:                  (3, 4): 0,
        ....:                  (1, 2, 3): 0,
        ....:                  (1, 2, 4): 45,
        ....:                  (1, 3, 4): 40,
        ....:                  (2, 3, 4): 0,
        ....:                  (1, 2, 3, 4): 65}
        sage: long_game = CooperativeGame(long_function)
        sage: long_game.is_superadditive()
        True

    Python

        >>> from sage.all import *
        >>> long_function = {(): Integer(0),
        ...                  (Integer(1),): Integer(0),
        ...                  (Integer(2),): Integer(0),
        ...                  (Integer(3),): Integer(0),
        ...                  (Integer(4),): Integer(0),
        ...                  (Integer(1), Integer(2)): Integer(0),
        ...                  (Integer(1), Integer(3)): Integer(0),
        ...                  (Integer(1), Integer(4)): Integer(0),
        ...                  (Integer(2), Integer(3)): Integer(0),
        ...                  (Integer(2), Integer(4)): Integer(0),
        ...                  (Integer(3), Integer(4)): Integer(0),
        ...                  (Integer(1), Integer(2), Integer(3)): Integer(0),
        ...                  (Integer(1), Integer(2), Integer(4)): Integer(45),
        ...                  (Integer(1), Integer(3), Integer(4)): Integer(40),
        ...                  (Integer(2), Integer(3), Integer(4)): Integer(0),
        ...                  (Integer(1), Integer(2), Integer(3), Integer(4)): Integer(65)}
        >>> long_game = CooperativeGame(long_function)
        >>> long_game.is_superadditive()
        True

    An example with a longer game that is not:

    Sage

        sage: long_function = {(): 0,
        ....:                  (1,): 0,
        ....:                  (2,): 0,
        ....:                  (3,): 55,
        ....:                  (4,): 0,
        ....:                  (1, 2): 0,
        ....:                  (1, 3): 0,
        ....:                  (1, 4): 0,
        ....:                  (2, 3): 0,
        ....:                  (2, 4): 0,
        ....:                  (3, 4): 0,
        ....:                  (1, 2, 3): 0,
        ....:                  (1, 2, 4): 45,
        ....:                  (1, 3, 4): 40,
        ....:                  (2, 3, 4): 0,
        ....:                  (1, 2, 3, 4): 85}
        sage: long_game = CooperativeGame(long_function)
        sage: long_game.is_superadditive()
        False

    [Python]

        >>> from sage.all import *
        >>> long_function = {(): Integer(0),
        ...                  (Integer(1),): Integer(0),
        ...                  (Integer(2),): Integer(0),
        ...                  (Integer(3),): Integer(55),
        ...                  (Integer(4),): Integer(0),
        ...                  (Integer(1), Integer(2)): Integer(0),
        ...                  (Integer(1), Integer(3)): Integer(0),
        ...                  (Integer(1), Integer(4)): Integer(0),
        ...                  (Integer(2), Integer(3)): Integer(0),
        ...                  (Integer(2), Integer(4)): Integer(0),
        ...                  (Integer(3), Integer(4)): Integer(0),
        ...                  (Integer(1), Integer(2), Integer(3)): Integer(0),
        ...                  (Integer(1), Integer(2), Integer(4)): Integer(45),
        ...                  (Integer(1), Integer(3), Integer(4)): Integer(40),
        ...                  (Integer(2), Integer(3), Integer(4)): Integer(0),
        ...                  (Integer(1), Integer(2), Integer(3), Integer(4)): Integer(85)}
        >>> long_game = CooperativeGame(long_function)
        >>> long_game.is_superadditive()
        False

  is_symmetric(payoff_vector)

    Return `True` if `payoff_vector` possesses the symmetry property.

    A payoff vector possesses the symmetry property if \(v(C \cup i) = v(C \cup j)\) for all \(C \in 2^{\Omega} \setminus \{i,j\}\), then \(x_i = x_j\).

    INPUT:

    - `payoff_vector` – dictionary where the key is the player and the value is their payoff

    EXAMPLES:

    A payoff vector that has the symmetry property:

    Sage

        sage: letter_function = {(): 0,
        ....:                    ('A',): 6,
        ....:                    ('B',): 12,
        ....:                    ('C',): 42,
        ....:                    ('A', 'B',): 12,
        ....:                    ('A', 'C',): 42,
        ....:                    ('B', 'C',): 42,
        ....:                    ('A', 'B', 'C',): 42}
        sage: letter_game = CooperativeGame(letter_function)
        sage: letter_game.is_symmetric({'A': 5, 'B': 14, 'C': 20})
        True

    Python

        >>> from sage.all import *
        >>> letter_function = {(): Integer(0),
        ...                    ('A',): Integer(6),
        ...                    ('B',): Integer(12),
        ...                    ('C',): Integer(42),
        ...                    ('A', 'B',): Integer(12),
        ...                    ('A', 'C',): Integer(42),
        ...                    ('B', 'C',): Integer(42),
        ...                    ('A', 'B', 'C',): Integer(42)}
        >>> letter_game = CooperativeGame(letter_function)
        >>> letter_game.is_symmetric({'A': Integer(5), 'B': Integer(14), 'C': Integer(20)})
        True

    A payoff vector that returns `False`:

    Sage

        sage: integer_function = {(): 0,
        ....:                     (1,): 12,
        ....:                     (2,): 12,
        ....:                     (3,): 42,
        ....:                     (1, 2,): 12,
        ....:                     (1, 3,): 42,
        ....:                     (2, 3,): 42,
        ....:                     (1, 2, 3,): 42}
        sage: integer_game = CooperativeGame(integer_function)
        sage: integer_game.is_symmetric({1: 2, 2: 5, 3: 35})
        False

    [Python]

        >>> from sage.all import *
        >>> integer_function = {(): Integer(0),
        ...                     (Integer(1),): Integer(12),
        ...                     (Integer(2),): Integer(12),
        ...                     (Integer(3),): Integer(42),
        ...                     (Integer(1), Integer(2),): Integer(12),
        ...                     (Integer(1), Integer(3),): Integer(42),
        ...                     (Integer(2), Integer(3),): Integer(42),
        ...                     (Integer(1), Integer(2), Integer(3),): Integer(42)}
        >>> integer_game = CooperativeGame(integer_function)
        >>> integer_game.is_symmetric({Integer(1): Integer(2), Integer(2): Integer(5), Integer(3): Integer(35)})
        False

    A longer example for symmetry:

    Sage

        sage: long_function = {(): 0,
        ....:                  (1,): 0,
        ....:                  (2,): 0,
        ....:                  (3,): 0,
        ....:                  (4,): 0,
        ....:                  (1, 2): 0,
        ....:                  (1, 3): 0,
        ....:                  (1, 4): 0,
        ....:                  (2, 3): 0,
        ....:                  (2, 4): 0,
        ....:                  (3, 4): 0,
        ....:                  (1, 2, 3): 0,
        ....:                  (1, 2, 4): 45,
        ....:                  (1, 3, 4): 40,
        ....:                  (2, 3, 4): 0,
        ....:                  (1, 2, 3, 4): 65}
        sage: long_game = CooperativeGame(long_function)
        sage: long_game.is_symmetric({1: 20, 2: 20, 3: 5, 4: 20})
        True

    Python

        >>> from sage.all import *
        >>> long_function = {(): Integer(0),
        ...                  (Integer(1),): Integer(0),
        ...                  (Integer(2),): Integer(0),
        ...                  (Integer(3),): Integer(0),
        ...                  (Integer(4),): Integer(0),
        ...                  (Integer(1), Integer(2)): Integer(0),
        ...                  (Integer(1), Integer(3)): Integer(0),
        ...                  (Integer(1), Integer(4)): Integer(0),
        ...                  (Integer(2), Integer(3)): Integer(0),
        ...                  (Integer(2), Integer(4)): Integer(0),
        ...                  (Integer(3), Integer(4)): Integer(0),
        ...                  (Integer(1), Integer(2), Integer(3)): Integer(0),
        ...                  (Integer(1), Integer(2), Integer(4)): Integer(45),
        ...                  (Integer(1), Integer(3), Integer(4)): Integer(40),
        ...                  (Integer(2), Integer(3), Integer(4)): Integer(0),
        ...                  (Integer(1), Integer(2), Integer(3), Integer(4)): Integer(65)}
        >>> long_game = CooperativeGame(long_function)
        >>> long_game.is_symmetric({Integer(1): Integer(20), Integer(2): Integer(20), Integer(3): Integer(5), Integer(4): Integer(20)})
        True

  nullplayer(payoff_vector)

    Return `True` if `payoff_vector` possesses the nullplayer property.

    A payoff vector \(v\) has the nullplayer property if there exists an \(i\) such that \(v(C \cup i) = v(C)\) for all \(C \in 2^{\Omega}\) then, \(\lambda_i = 0\). In other words: if a player does not contribute to any coalition then that player should receive no payoff.

    INPUT:

    - `payoff_vector` – dictionary where the key is the player and the value is their payoff

    EXAMPLES:

    A payoff vector that returns `True`:

    Sage

        sage: letter_function = {(): 0,
        ....:                    ('A',): 0,
        ....:                    ('B',): 12,
        ....:                    ('C',): 42,
        ....:                    ('A', 'B',): 12,
        ....:                    ('A', 'C',): 42,
        ....:                    ('B', 'C',): 42,
        ....:                    ('A', 'B', 'C',): 42}
        sage: letter_game = CooperativeGame(letter_function)
        sage: letter_game.nullplayer({'A': 0, 'B': 14, 'C': 14})
        True

    Python

        >>> from sage.all import *
        >>> letter_function = {(): Integer(0),
        ...                    ('A',): Integer(0),
        ...                    ('B',): Integer(12),
        ...                    ('C',): Integer(42),
        ...                    ('A', 'B',): Integer(12),
        ...                    ('A', 'C',): Integer(42),
        ...                    ('B', 'C',): Integer(42),
        ...                    ('A', 'B', 'C',): Integer(42)}
        >>> letter_game = CooperativeGame(letter_function)
        >>> letter_game.nullplayer({'A': Integer(0), 'B': Integer(14), 'C': Integer(14)})
        True

    A payoff vector that returns `False`:

    Sage

        sage: A_function = {(): 0,
        ....:               (1,): 0,
        ....:               (2,): 12,
        ....:               (3,): 42,
        ....:               (1, 2,): 12,
        ....:               (1, 3,): 42,
        ....:               (2, 3,): 55,
        ....:               (1, 2, 3,): 55}
        sage: A_game = CooperativeGame(A_function)
        sage: A_game.nullplayer({1: 10, 2: 10, 3: 25})
        False

    [Python]

        >>> from sage.all import *
        >>> A_function = {(): Integer(0),
        ...               (Integer(1),): Integer(0),
        ...               (Integer(2),): Integer(12),
        ...               (Integer(3),): Integer(42),
        ...               (Integer(1), Integer(2),): Integer(12),
        ...               (Integer(1), Integer(3),): Integer(42),
        ...               (Integer(2), Integer(3),): Integer(55),
        ...               (Integer(1), Integer(2), Integer(3),): Integer(55)}
        >>> A_game = CooperativeGame(A_function)
        >>> A_game.nullplayer({Integer(1): Integer(10), Integer(2): Integer(10), Integer(3): Integer(25)})
        False

    A longer example for nullplayer:

    Sage

        sage: long_function = {(): 0,
        ....:                  (1,): 0,
        ....:                  (2,): 0,
        ....:                  (3,): 0,
        ....:                  (4,): 0,
        ....:                  (1, 2): 0,
        ....:                  (1, 3): 0,
        ....:                  (1, 4): 0,
        ....:                  (2, 3): 0,
        ....:                  (2, 4): 0,
        ....:                  (3, 4): 0,
        ....:                  (1, 2, 3): 0,
        ....:                  (1, 2, 4): 45,
        ....:                  (1, 3, 4): 40,
        ....:                  (2, 3, 4): 0,
        ....:                  (1, 2, 3, 4): 65}
        sage: long_game = CooperativeGame(long_function)
        sage: long_game.nullplayer({1: 20, 2: 20, 3: 5, 4: 20})
        True

    Python

        >>> from sage.all import *
        >>> long_function = {(): Integer(0),
        ...                  (Integer(1),): Integer(0),
        ...                  (Integer(2),): Integer(0),
        ...                  (Integer(3),): Integer(0),
        ...                  (Integer(4),): Integer(0),
        ...                  (Integer(1), Integer(2)): Integer(0),
        ...                  (Integer(1), Integer(3)): Integer(0),
        ...                  (Integer(1), Integer(4)): Integer(0),
        ...                  (Integer(2), Integer(3)): Integer(0),
        ...                  (Integer(2), Integer(4)): Integer(0),
        ...                  (Integer(3), Integer(4)): Integer(0),
        ...                  (Integer(1), Integer(2), Integer(3)): Integer(0),
        ...                  (Integer(1), Integer(2), Integer(4)): Integer(45),
        ...                  (Integer(1), Integer(3), Integer(4)): Integer(40),
        ...                  (Integer(2), Integer(3), Integer(4)): Integer(0),
        ...                  (Integer(1), Integer(2), Integer(3), Integer(4)): Integer(65)}
        >>> long_game = CooperativeGame(long_function)
        >>> long_game.nullplayer({Integer(1): Integer(20), Integer(2): Integer(20), Integer(3): Integer(5), Integer(4): Integer(20)})
        True

  shapley_value()

    Return the Shapley value for `self`.

    The Shapley value is the “fair” payoff vector and is computed by the following formula:

    \[\phi_i(G) = \sum_{S \subseteq \Omega} \sum_{p \in S} \frac{1}{|S|\binom{N}{|S|}} \bigl( v(S) - v(S \setminus \{p\}) \bigr).\]

    EXAMPLES:

    A typical example of computing the Shapley value:

    Sage

        sage: integer_function = {(): 0,
        ....:                  (1,): 6,
        ....:                  (2,): 12,
        ....:                  (3,): 42,
        ....:                  (1, 2,): 12,
        ....:                  (1, 3,): 42,
        ....:                  (2, 3,): 42,
        ....:                  (1, 2, 3,): 42}
        sage: integer_game = CooperativeGame(integer_function)
        sage: integer_game.player_list
        (1, 2, 3)
        sage: integer_game.shapley_value()
        {1: 2, 2: 5, 3: 35}

    Python

        >>> from sage.all import *
        >>> integer_function = {(): Integer(0),
        ...                  (Integer(1),): Integer(6),
        ...                  (Integer(2),): Integer(12),
        ...                  (Integer(3),): Integer(42),
        ...                  (Integer(1), Integer(2),): Integer(12),
        ...                  (Integer(1), Integer(3),): Integer(42),
        ...                  (Integer(2), Integer(3),): Integer(42),
        ...                  (Integer(1), Integer(2), Integer(3),): Integer(42)}
        >>> integer_game = CooperativeGame(integer_function)
        >>> integer_game.player_list
        (1, 2, 3)
        >>> integer_game.shapley_value()
        {1: 2, 2: 5, 3: 35}

    A longer example of the Shapley value:

    Sage

        sage: long_function = {(): 0,
        ....:                  (1,): 0,
        ....:                  (2,): 0,
        ....:                  (3,): 0,
        ....:                  (4,): 0,
        ....:                  (1, 2): 0,
        ....:                  (1, 3): 0,
        ....:                  (1, 4): 0,
        ....:                  (2, 3): 0,
        ....:                  (2, 4): 0,
        ....:                  (3, 4): 0,
        ....:                  (1, 2, 3): 0,
        ....:                  (1, 2, 4): 45,
        ....:                  (1, 3, 4): 40,
        ....:                  (2, 3, 4): 0,
        ....:                  (1, 2, 3, 4): 65}
        sage: long_game = CooperativeGame(long_function)
        sage: long_game.shapley_value()
        {1: 70/3, 2: 10, 3: 25/3, 4: 70/3}

    [Python]

        >>> from sage.all import *
        >>> long_function = {(): Integer(0),
        ...                  (Integer(1),): Integer(0),
        ...                  (Integer(2),): Integer(0),
        ...                  (Integer(3),): Integer(0),
        ...                  (Integer(4),): Integer(0),
        ...                  (Integer(1), Integer(2)): Integer(0),
        ...                  (Integer(1), Integer(3)): Integer(0),
        ...                  (Integer(1), Integer(4)): Integer(0),
        ...                  (Integer(2), Integer(3)): Integer(0),
        ...                  (Integer(2), Integer(4)): Integer(0),
        ...                  (Integer(3), Integer(4)): Integer(0),
        ...                  (Integer(1), Integer(2), Integer(3)): Integer(0),
        ...                  (Integer(1), Integer(2), Integer(4)): Integer(45),
        ...                  (Integer(1), Integer(3), Integer(4)): Integer(40),
        ...                  (Integer(2), Integer(3), Integer(4)): Integer(0),
        ...                  (Integer(1), Integer(2), Integer(3), Integer(4)): Integer(65)}
        >>> long_game = CooperativeGame(long_function)
        >>> long_game.shapley_value()
        {1: 70/3, 2: 10, 3: 25/3, 4: 70/3}