Source code for shapley_numba.examples.games

"""Examples of jit-compiled games in shapley-numba."""

import numba
import numpy as np

from shapley_numba import numba_game
from shapley_numba.typing import CoalitionType

__all__ = [
    'GloveGame',
    'CoalitionGame',
    'WikipediaExample',
    'AirPortGame',
]

glove_spec = [('num_left_gloves', numba.int_)]


[docs] @numba_game(glove_spec) class GloveGame(object): """A game representing the value of glove market. The value of a coalition is the minimum of the number of left gloves and right gloves it possesses. Attributes ---------- num_left_gloves : int The number of left gloves available in the game. """ def __init__(self, num_left_gloves: int): """Initialize the GloveGame. Parameters ---------- num_left_gloves : int The number of left gloves. """ self.num_left_gloves = num_left_gloves def value(self, subset): """Compute the value of a given subset of players. Parameters ---------- subset : numpy.ndarray A binary array where 1 indicates the presence of a player in the subset and 0 indicates absence. The length of the array should be `2 * num_left_gloves`. Returns ------- int The value of the subset, which is `min(left_gloves, right_gloves)`. """ left_gloves = np.sum(subset[: self.num_left_gloves]) right_gloves = np.sum(subset[self.num_left_gloves :]) return min(left_gloves, right_gloves)
coalition_spec = [('seats', numba.float64[:]), ('quorum', numba.float64)]
[docs] @numba_game(coalition_spec) class CoalitionGame: """A game representing a political coalition. Game is "won" if a coalition achieves majority """ def __init__(self, seats): """Initialize the CoalitionGame. Parameters ---------- seats : numpy.ndarray An array of floats representing the number of seats each player holds. """ self.seats = seats self.quorum = np.sum(self.seats) / 2 def value(self, subset): """Compute the value of a given subset of players.""" return 1 if np.sum(subset * self.seats) > self.quorum else 0
wikipedia_example_spec = [('game', numba.types.DictType(numba.int32, numba.float64))]
[docs] @numba_game(wikipedia_example_spec) class WikipediaExample: """Game taken from shapley value wikipedia page. Players are represented by their index: 0 - "you" 1 - "Emma" 2 - Liam """ def __init__(self) -> None: """Initialize the WikipediaExample.""" game = { 0: 0.0, # empty 1: 30.0, # you 2: 20.0, # Emma 4: 10.0, # Liam 3: 90.0, # you + Emma 5: 100.0, # you + Liam 6: 30.0, # Emma + Liam 7: 280.0, # you + Emma + Liam } self.game = numba.typed.Dict.empty(numba.types.int32, numba.types.float64) for key, value in game.items(): self.game[np.int32(key)] = value def value(self, subset: CoalitionType) -> np.float64: """Compute the value of a given subset of players.""" return np.float64(self.game[np.sum(subset * (2 ** np.arange(3)))])
airport_game_spec = [('length_requirements', numba.float64[:])]
[docs] @numba_game(airport_game_spec) class AirPortGame: """Airport game. Classic game, where length requirements are translated to cost assignments, via Shapley values. See https://en.wikipedia.org/wiki/Airport_problem for more details. """ def __init__(self, length_requirements: np.ndarray): """Initialize the AirPortGame.""" if not np.all(length_requirements >= 0): raise ValueError('All length requirements must be non-negative.') self.length_requirements = length_requirements def value(self, subset: CoalitionType): """Compute the value of a given subset of players.""" return max(self.length_requirements * subset)