示例#1
0
def test_hierarchical_dev_expansion():
    """Test that hierarchical dev expansion is correct"""
    game = rsgame.empty([9, 16], [4, 3])
    mask = [True, False, True, False, False, True, False]
    profs = hr.expand_deviation_profiles(game, mask, [3, 4])
    actual = utils.axis_to_elem(profs)
    expected = utils.axis_to_elem([
        [6, 3, 0, 0, 0, 16, 0],
        [3, 3, 3, 0, 0, 16, 0],
        [0, 3, 6, 0, 0, 16, 0],
        [6, 0, 0, 3, 0, 16, 0],
        [3, 0, 3, 3, 0, 16, 0],
        [0, 0, 6, 3, 0, 16, 0],
        [9, 0, 0, 0, 4, 12, 0],
        [6, 0, 3, 0, 4, 12, 0],
        [3, 0, 6, 0, 4, 12, 0],
        [0, 0, 9, 0, 4, 12, 0],
        [9, 0, 0, 0, 0, 12, 4],
        [6, 0, 3, 0, 0, 12, 4],
        [3, 0, 6, 0, 0, 12, 4],
        [0, 0, 9, 0, 0, 12, 4],
    ])
    assert np.setxor1d(actual, expected).size == 0

    profs = hr.expand_deviation_profiles(game, mask, [3, 4], 0)
    actual = utils.axis_to_elem(profs)
    expected = utils.axis_to_elem([
        [6, 3, 0, 0, 0, 16, 0],
        [3, 3, 3, 0, 0, 16, 0],
        [0, 3, 6, 0, 0, 16, 0],
        [6, 0, 0, 3, 0, 16, 0],
        [3, 0, 3, 3, 0, 16, 0],
        [0, 0, 6, 3, 0, 16, 0],
    ])
    assert np.setxor1d(actual, expected).size == 0
示例#2
0
def test_rand_dpr_allow_incomplete(add_prob, num_obs, game_desc):
    """Test that allow_incomplete works for random games"""
    # Generate games
    players, strategies, red_players = game_desc
    base = rsgame.BaseGame(players, strategies)
    game = gamegen.add_profiles(base, add_prob)
    sgame = gamegen.add_noise(game, 1, num_obs)
    red = reduction.DeviationPreserving(strategies, players, red_players)

    # Try to reduce game
    red_game = red.reduce_game(game, True)
    red_sgame = red.reduce_game(sgame, True)

    # Verify that when allow_incomplete, then reduce returns all profiles
    reduced_full_profiles = utils.axis_to_elem(
        red.reduce_profiles(game.profiles))
    reduced_profiles = utils.axis_to_elem(red_game.profiles)
    assert np.setxor1d(reduced_profiles, reduced_full_profiles).size == 0
    reduced_sample_profiles = utils.axis_to_elem(red_sgame.profiles)
    assert np.setxor1d(reduced_sample_profiles,
                       reduced_full_profiles).size == 0

    redord = np.argsort(reduced_profiles)
    redsord = np.argsort(reduced_sample_profiles)
    assert np.all(np.isnan(red_game.payoffs[redord]) ==
                  np.isnan(red_sgame.payoffs[redsord])), \
        "sample game and game didn't have same nan payoffs"
    assert all(np.all(np.isnan(p).any(-1) == np.isnan(p).all(-1)) for p
               in red_sgame.sample_payoffs), \
        "some sample payoffs had partial nans"
示例#3
0
def test_identity_dev_expansion():
    """Test that identity dev expansion is correct"""
    game = rsgame.empty([3, 4], [4, 3])
    mask = [True, False, True, False, False, True, False]
    profs = ir.expand_deviation_profiles(game, mask)
    actual = utils.axis_to_elem(profs)
    expected = utils.axis_to_elem([
        [2, 1, 0, 0, 0, 4, 0],
        [1, 1, 1, 0, 0, 4, 0],
        [0, 1, 2, 0, 0, 4, 0],
        [2, 0, 0, 1, 0, 4, 0],
        [1, 0, 1, 1, 0, 4, 0],
        [0, 0, 2, 1, 0, 4, 0],
        [3, 0, 0, 0, 1, 3, 0],
        [2, 0, 1, 0, 1, 3, 0],
        [1, 0, 2, 0, 1, 3, 0],
        [0, 0, 3, 0, 1, 3, 0],
        [3, 0, 0, 0, 0, 3, 1],
        [2, 0, 1, 0, 0, 3, 1],
        [1, 0, 2, 0, 0, 3, 1],
        [0, 0, 3, 0, 0, 3, 1],
    ])
    assert np.setxor1d(actual, expected).size == 0

    profs = ir.expand_deviation_profiles(game, mask, role_index=0)
    actual = utils.axis_to_elem(profs)
    expected = utils.axis_to_elem([
        [2, 1, 0, 0, 0, 4, 0],
        [1, 1, 1, 0, 0, 4, 0],
        [0, 1, 2, 0, 0, 4, 0],
        [2, 0, 0, 1, 0, 4, 0],
        [1, 0, 1, 1, 0, 4, 0],
        [0, 0, 2, 1, 0, 4, 0],
    ])
    assert np.setxor1d(actual, expected).size == 0
示例#4
0
def test_elem_axis():
    """Test identity of axis_to_elem o axis_from_elem"""
    arr = np.array([[5.4, 2.2], [5.7, 2.8], [9.6, 1.2]], float)
    assert np.all(arr == utils.axis_from_elem(utils.axis_to_elem(arr)))
    assert np.all(
        arr.astype(int) == utils.axis_from_elem(
            utils.axis_to_elem(arr.astype(int))))
示例#5
0
def test_twins_dev_expansion():
    """Test that dpr dev expansion is correct

    Note, this is the only one that has "new" code, so it's the most important
    to test."""
    game = rsgame.empty([9, 16], [4, 3])
    mask = [True, False, True, False, False, True, False]
    profs = tr.expand_deviation_profiles(game, mask)
    actual = utils.axis_to_elem(profs)
    expected = utils.axis_to_elem([
        [8, 1, 0, 0, 0, 16, 0],
        [0, 1, 8, 0, 0, 16, 0],
        [8, 0, 0, 1, 0, 16, 0],
        [0, 0, 8, 1, 0, 16, 0],
        [9, 0, 0, 0, 1, 15, 0],
        [5, 0, 4, 0, 1, 15, 0],
        [0, 0, 9, 0, 1, 15, 0],
        [9, 0, 0, 0, 0, 15, 1],
        [5, 0, 4, 0, 0, 15, 1],
        [0, 0, 9, 0, 0, 15, 1],
    ])
    assert np.setxor1d(actual, expected).size == 0

    profs = tr.expand_deviation_profiles(game, mask, role_index=0)
    actual = utils.axis_to_elem(profs)
    expected = utils.axis_to_elem([
        [8, 1, 0, 0, 0, 16, 0],
        [0, 1, 8, 0, 0, 16, 0],
        [8, 0, 0, 1, 0, 16, 0],
        [0, 0, 8, 1, 0, 16, 0],
    ])
    assert np.setxor1d(actual, expected).size == 0
示例#6
0
def test_empty_elem_axis():
    """Test axis_to_elem works for empty arrays"""
    arr = np.empty((0, 2), float)
    assert np.all(arr.shape == utils.axis_from_elem(
        utils.axis_to_elem(arr)).shape)
    assert np.all(
        arr.astype(int).shape ==
        utils.axis_from_elem(utils.axis_to_elem(arr.astype(int))).shape)
示例#7
0
def test_elem_axis():
    """Test identity of axis_to_elem o axis_from_elem"""
    arr = np.array([[5.4, 2.2],
                    [5.7, 2.8],
                    [9.6, 1.2]], float)
    assert np.all(arr == utils.axis_from_elem(utils.axis_to_elem(arr)))
    assert np.all(arr.astype(int) ==
                  utils.axis_from_elem(utils.axis_to_elem(arr.astype(int))))
示例#8
0
def test_empty_elem_axis():
    """Test axis_to_elem works for empty arrays"""
    arr = np.empty((0, 2), float)
    assert np.all(
        arr.shape == utils.axis_from_elem(utils.axis_to_elem(arr)).shape)
    assert np.all(
        arr.astype(int).shape == utils.axis_from_elem(
            utils.axis_to_elem(arr.astype(int))).shape)
示例#9
0
def test_elem_axis():
    x = np.array([[5.4, 2.2],
                  [5.7, 2.8],
                  [9.6, 1.2]], float)
    assert np.all(x == utils.elem_to_axis(utils.axis_to_elem(x), float))
    assert np.all(x.astype(int) ==
                  utils.elem_to_axis(utils.axis_to_elem(x.astype(int)), int))
    assert utils.unique_axis(x).shape == (3, 2)
    array, counts = utils.unique_axis(x.astype(int), return_counts=True)
    assert array.shape == (2, 2)
    assert not np.setxor1d(counts, [2, 1]).size
示例#10
0
def test_max_prob_prof(players, strategies):
    game = rsgame.basegame(players, strategies)
    profiles = game.all_profiles()
    log_prob = (np.sum(sps.gammaln(game.num_players + 1)) -
                np.sum(sps.gammaln(profiles + 1), 1))
    for mix in game.random_mixtures(100):
        probs = np.sum(np.log(mix + TINY) * profiles, 1) + log_prob
        mask = np.max(probs) - EPS < probs
        max_prob_profs = profiles[mask]
        actual = game.max_prob_prof(mix)
        assert np.all(np.in1d(utils.axis_to_elem(actual),
                              utils.axis_to_elem(max_prob_profs)))
示例#11
0
def test_approximate_dpr_expansion():
    """Test expansion on approximate dpr"""
    full_game = rsgame.empty([8, 11], [2, 2])
    red_prof = [[1, 2, 2, 2]]
    full_profs = dpr.expand_profiles(
        full_game, red_prof)
    profs = utils.axis_to_elem(full_profs)
    expected = utils.axis_to_elem([
        [4, 4, 6, 5],
        [1, 7, 6, 5],
        [3, 5, 4, 7],
        [3, 5, 7, 4]])
    assert np.setxor1d(profs, expected).size == 0, \
        'generated different profiles than expected'
示例#12
0
def test_maximal_subgames_partial_profiles():
    """Test that maximal subgames properly handles partial profiles"""
    profiles = [[2, 0],
                [1, 1],
                [0, 2]]
    payoffs = [[1, 0],
               [np.nan, 2],
               [0, 3]]
    game = rsgame.Game([2], [2], profiles, payoffs)
    subs = subgame.maximal_subgames(game)
    expected = utils.axis_to_elem(np.array([
        [True, False],
        [False, True]]))
    assert np.setxor1d(utils.axis_to_elem(subs), expected).size == 0, \
        "Didn't produce both pure subgames"
示例#13
0
def test_maximal_restrictions_partial_profiles():
    """Test that maximal restrictions properly handles partial profiles"""
    profiles = [[2, 0],
                [1, 1],
                [0, 2]]
    payoffs = [[1, 0],
               [np.nan, 2],
               [0, 3]]
    game = paygame.game([2], [2], profiles, payoffs)
    rests = restrict.maximal_restrictions(game)
    expected = utils.axis_to_elem(np.array([
        [True, False],
        [False, True]]))
    assert np.setxor1d(utils.axis_to_elem(rests), expected).size == 0, \
        "Didn't produce both pure restrictions"
示例#14
0
    def expand_profiles(self, profiles, return_contributions=False):
        """Expand a set of profiles

        If `return_contributions` then a boolean array of matching shape is
        returned indicating the payoffs that are needed for the initial
        profiles."""
        profiles = np.asarray(profiles, int)
        num_profs = profiles.shape[0]
        dev_profs = profiles[:, None] - np.eye(self.full_game.num_role_strats,
                                               dtype=int)
        dev_profs = np.reshape(dev_profs, (-1, self.full_game.num_role_strats))
        dev_full_players = self._devs(self.full_game.num_players, num_profs)
        dev_red_players = self._devs(self.red_game.num_players, num_profs)

        mask = ~np.any(dev_profs < 0, 1)
        devs = np.eye(self.full_game.num_role_strats, dtype=bool)[None]\
            .repeat(num_profs, 0)\
            .reshape((-1, self.full_game.num_role_strats))[mask]
        dev_full_profs = _expand_rsym_profiles(
            self.full_game, dev_profs[mask], dev_full_players[mask],
            dev_red_players[mask]) + devs
        ids = utils.axis_to_elem(dev_full_profs)
        if not return_contributions:
            return dev_full_profs[np.unique(ids, return_index=True)[1]]
        else:
            # This is more complicated because we need to line up devs for the
            # same profile se we can "reduceat" to merge them
            order = np.argsort(ids)
            sids = ids[order]
            mask = np.insert(sids[1:] != sids[:-1], 0, True)
            profs = dev_full_profs[order[mask]]
            ored_devs = np.bitwise_or.reduceat(devs[order],
                                               mask.nonzero()[0], 0)
            return profs, ored_devs
示例#15
0
    def restrict(self, restriction):
        restriction = np.asarray(restriction, bool)
        base = rsgame.empty_copy(self).restrict(restriction)

        size_mask = restriction.repeat(self._sizes)
        sizes = self._sizes[restriction]
        profiles = self._profiles[size_mask]
        lengths = self._lengths[restriction]
        zeros = (profiles[:, ~restriction] /
                 lengths[:, ~restriction].repeat(sizes, 0))
        removed = np.exp(-np.einsum('ij,ij->i', zeros, zeros) / 2)  # pylint: disable=invalid-unary-operand-type
        uprofs, inds = np.unique(recfunctions.merge_arrays([
            np.arange(restriction.sum()).repeat(sizes).view([('s', int)]),
            utils.axis_to_elem(profiles[:, restriction])
        ],
                                                           flatten=True),
                                 return_inverse=True)
        new_alpha = np.bincount(inds, removed * self._alpha[size_mask])
        new_sizes = np.diff(
            np.concatenate([[-1],
                            np.flatnonzero(np.diff(uprofs['s'])),
                            [new_alpha.size - 1]]))

        return _RbfGpGame(base.role_names, base.strat_names,
                          base.num_role_players, self._offset[restriction],
                          self._coefs[restriction], lengths[:, restriction],
                          new_sizes, uprofs['axis'], new_alpha)
示例#16
0
    def restrict(self, restriction):
        restriction = np.asarray(restriction, bool)
        base = rsgame.empty_copy(self).restrict(restriction)

        size_mask = restriction.repeat(self._sizes)
        sizes = self._sizes[restriction]
        profiles = self._profiles[size_mask]
        lengths = self._lengths[restriction]
        zeros = (profiles[:, ~restriction] /
                 lengths[:, ~restriction].repeat(sizes, 0))
        removed = np.exp(-np.einsum('ij,ij->i', zeros, zeros) / 2) # pylint: disable=invalid-unary-operand-type
        uprofs, inds = np.unique(
            recfunctions.merge_arrays([
                np.arange(restriction.sum()).repeat(sizes).view([('s', int)]),
                utils.axis_to_elem(profiles[:, restriction])], flatten=True),
            return_inverse=True)
        new_alpha = np.bincount(inds, removed * self._alpha[size_mask])
        new_sizes = np.diff(np.concatenate([
            [-1], np.flatnonzero(np.diff(uprofs['s'])),
            [new_alpha.size - 1]]))

        return _RbfGpGame(
            base.role_names, base.strat_names, base.num_role_players,
            self._offset[restriction], self._coefs[restriction],
            lengths[:, restriction], new_sizes, uprofs['axis'], new_alpha)
示例#17
0
 def __hash__(self):
     hprofs = np.sort(
         utils.axis_to_elem(
             np.concatenate([
                 np.arange(self.num_strats).repeat(self._sizes)[:, None],
                 self._profiles
             ], 1))).tobytes()
     return hash((super().__hash__(), hprofs))
示例#18
0
def rbfgame_train(game, num_restarts=3): # pylint: disable=too-many-locals
    """Train a regression game with an RBF Gaussian process

    This model is somewhat well tests and has a few added benefits over
    standard regression models due the nature of its functional form.

    Parameters
    ----------
    game : RsGame
        The game to learn. Must have at least one payoff per strategy.
    num_restarts : int, optional
        The number of random restarts to make with the optimizer. Higher
        numbers will give a better fit (in expectation), but will take
        longer.
    """
    dev_players = np.maximum(game.num_role_players - np.eye(
        game.num_roles, dtype=int), 1).repeat(
            game.num_role_strats, 0).repeat(game.num_role_strats, 1)
    bounds = np.insert(dev_players[..., None], 0, 1, 2)
    # TODO Add an alpha that is smaller for points near the edge of the
    # simplex, accounting for the importance of minimizing error at the
    # extrema.
    means = np.empty(game.num_strats)
    coefs = np.empty(game.num_strats)
    lengths = np.empty((game.num_strats, game.num_strats))
    profiles = []
    alpha = []
    sizes = []
    for (strat, profs, pays), bound in zip(_dev_profpay(game), bounds):
        pay_mean = pays.mean()
        pays -= pay_mean
        reg = gp.GaussianProcessRegressor(
            1.0 * gp.kernels.RBF(bound.mean(1), bound) +
            gp.kernels.WhiteKernel(1), n_restarts_optimizer=num_restarts,
            copy_X_train=False)
        reg.fit(profs, pays)

        means[strat] = pay_mean
        coefs[strat] = reg.kernel_.k1.k1.constant_value
        lengths[strat] = reg.kernel_.k1.k2.length_scale
        uprofs, inds = np.unique(
            utils.axis_to_elem(profs), return_inverse=True)
        profiles.append(utils.axis_from_elem(uprofs))
        alpha.append(np.bincount(inds, reg.alpha_))
        sizes.append(uprofs.size)

    if np.any(lengths[..., None] == bounds):
        warnings.warn(
            'some lengths were at their bounds, this may indicate a poor '
            'fit')

    return _RbfGpGame(
        game.role_names, game.strat_names, game.num_role_players, means, coefs,
        lengths, np.array(sizes), np.concatenate(profiles),
        np.concatenate(alpha))
示例#19
0
def rbfgame_train(game, num_restarts=3):  # pylint: disable=too-many-locals
    """Train a regression game with an RBF Gaussian process

    This model is somewhat well tests and has a few added benefits over
    standard regression models due the nature of its functional form.

    Parameters
    ----------
    game : RsGame
        The game to learn. Must have at least one payoff per strategy.
    num_restarts : int, optional
        The number of random restarts to make with the optimizer. Higher
        numbers will give a better fit (in expectation), but will take
        longer.
    """
    dev_players = np.maximum(
        game.num_role_players - np.eye(game.num_roles, dtype=int),
        1).repeat(game.num_role_strats, 0).repeat(game.num_role_strats, 1)
    bounds = np.insert(dev_players[..., None], 0, 1, 2)
    # TODO Add an alpha that is smaller for points near the edge of the
    # simplex, accounting for the importance of minimizing error at the
    # extrema.
    means = np.empty(game.num_strats)
    coefs = np.empty(game.num_strats)
    lengths = np.empty((game.num_strats, game.num_strats))
    profiles = []
    alpha = []
    sizes = []
    for (strat, profs, pays), bound in zip(_dev_profpay(game), bounds):
        pay_mean = pays.mean()
        pays -= pay_mean
        reg = gp.GaussianProcessRegressor(
            1.0 * gp.kernels.RBF(bound.mean(1), bound) +
            gp.kernels.WhiteKernel(1),
            n_restarts_optimizer=num_restarts,
            copy_X_train=False)
        reg.fit(profs, pays)

        means[strat] = pay_mean
        coefs[strat] = reg.kernel_.k1.k1.constant_value
        lengths[strat] = reg.kernel_.k1.k2.length_scale
        uprofs, inds = np.unique(utils.axis_to_elem(profs),
                                 return_inverse=True)
        profiles.append(utils.axis_from_elem(uprofs))
        alpha.append(np.bincount(inds, reg.alpha_))
        sizes.append(uprofs.size)

    if np.any(lengths[..., None] == bounds):
        warnings.warn(
            'some lengths were at their bounds, this may indicate a poor '
            'fit')

    return _RbfGpGame(game.role_names, game.strat_names, game.num_role_players,
                      means, coefs, lengths, np.array(sizes),
                      np.concatenate(profiles), np.concatenate(alpha))
示例#20
0
def test_approximate_dpr_expansion():
    """Test expansion on approximate dpr"""
    red = reduction.DeviationPreserving([2, 2], [8, 11], [3, 4])
    red_prof = [[1, 2, 2, 2]]
    full_profs, contributions = red.expand_profiles(red_prof, True)
    profs = utils.axis_to_elem(full_profs)
    expected = utils.axis_to_elem([
        [4, 4, 6, 5],
        [1, 7, 6, 5],
        [3, 5, 4, 7],
        [3, 5, 7, 4]])
    assert np.setxor1d(profs, expected).size == 0, \
        "generated different profiles than expected"
    expected_conts = np.array([
        [0, 1, 0, 0],
        [1, 0, 0, 0],
        [0, 0, 1, 0],
        [0, 0, 0, 1]], bool)
    eord = np.argsort(expected)
    pord = np.argsort(profs)
    assert np.all(expected_conts[eord] == contributions[pord])
示例#21
0
def test_dpr_dev_expansion():
    """Test that dpr dev expansion is correct

    Note, this is the only one that has "new" code, so it's the most important
    to test."""
    game = rsgame.BaseGame([3, 4], [4, 3])
    red = reduction.DeviationPreserving(
        game.num_strategies, game.num_players ** 2, game.num_players)
    mask = [True, False, True, False, False, True, False]
    profs = red.expand_deviation_profiles(mask)
    actual = utils.axis_to_elem(profs)
    expected = utils.axis_to_elem([
        [8, 1, 0, 0, 0, 16, 0],
        [4, 1, 4, 0, 0, 16, 0],
        [0, 1, 8, 0, 0, 16, 0],
        [8, 0, 0, 1, 0, 16, 0],
        [4, 0, 4, 1, 0, 16, 0],
        [0, 0, 8, 1, 0, 16, 0],
        [9, 0, 0, 0, 1, 15, 0],
        [6, 0, 3, 0, 1, 15, 0],
        [3, 0, 6, 0, 1, 15, 0],
        [0, 0, 9, 0, 1, 15, 0],
        [9, 0, 0, 0, 0, 15, 1],
        [6, 0, 3, 0, 0, 15, 1],
        [3, 0, 6, 0, 0, 15, 1],
        [0, 0, 9, 0, 0, 15, 1],
    ])
    assert np.setxor1d(actual, expected).size == 0

    profs = red.expand_deviation_profiles(mask, 0)
    actual = utils.axis_to_elem(profs)
    expected = utils.axis_to_elem([
        [8, 1, 0, 0, 0, 16, 0],
        [4, 1, 4, 0, 0, 16, 0],
        [0, 1, 8, 0, 0, 16, 0],
        [8, 0, 0, 1, 0, 16, 0],
        [4, 0, 4, 1, 0, 16, 0],
        [0, 0, 8, 1, 0, 16, 0],
    ])
    assert np.setxor1d(actual, expected).size == 0
示例#22
0
def test_random_dpr(keep_prob, game_desc, _):
    """Simple test that dpr functions are consistent"""
    players, strategies, red_players = game_desc
    # Create game
    game = gamegen.game(players, strategies, keep_prob)

    # Try to reduce game
    red_game = dpr.reduce_game(game, red_players)
    assert (rsgame.empty(red_players, strategies) ==
            dpr.reduce_game(rsgame.empty(players, strategies),
                            red_players))

    # Assert that reducing all profiles covers reduced game
    reduced_profiles = utils.axis_to_elem(red_game.profiles())
    reduced_full_profiles = utils.axis_to_elem(
        dpr.reduce_profiles(red_game, game.profiles()))
    assert np.setdiff1d(reduced_profiles, reduced_full_profiles).size == 0, \
        "reduced game contained profiles it shouldn't have"

    # Assert that all contributing profiles are in the expansion of the reduced
    # game, we need to first filter for complete profiles
    full_profiles = utils.axis_to_elem(game.profiles())
    complete_profs = ~np.isnan(red_game.payoffs()).any(1)
    full_reduced_profiles = utils.axis_to_elem(
        dpr.expand_profiles(game, red_game.profiles()[complete_profs]))
    assert np.setdiff1d(full_reduced_profiles, full_profiles).size == 0, \
        'full game did not have data for all profiles required of reduced'

    # Assert that dpr counts are accurate
    num_dpr_profiles = dpr.expand_profiles(
        game, red_game.all_profiles()).shape[0]
    assert num_dpr_profiles == red_game.num_all_dpr_profiles

    # Test the dpr deviation profile counts are accurate
    rest = red_game.random_restriction()
    dpr_devs = dpr.expand_profiles(
        game, restrict.deviation_profiles(red_game, rest)).shape[0]
    num = restrict.num_dpr_deviation_profiles(red_game, rest)
    assert dpr_devs == num, \
        "num_dpr_deviation_profiles didn't return correct number"
示例#23
0
def test_identity(keep_prob, game_desc):
    players, strategies = game_desc
    # Create game and reduction
    game = gamegen.role_symmetric_game(players, strategies)
    game = gamegen.drop_profiles(game, keep_prob)
    red = reduction.Identity(strategies, players)

    # Try to reduce game
    red_game = red.reduce_game(game)

    # Assert that reducing all profiles covers reduced game
    reduced_full_profiles = utils.axis_to_elem(
        red.reduce_profiles(game.profiles))
    reduced_profiles = utils.axis_to_elem(red_game.profiles)
    assert np.setxor1d(reduced_full_profiles, reduced_profiles).size == 0, \
        "reduced game didn't match full game"

    full_profiles = utils.axis_to_elem(game.profiles)
    full_reduced_profiles = utils.axis_to_elem(
        red.expand_profiles(red_game.profiles))
    assert np.setxor1d(full_profiles, full_reduced_profiles).size == 0, \
        "full game did not match reduced game"
示例#24
0
def test_acomb():
    actual = utils.acomb(5, 0)
    assert actual.shape == (1, 5)
    assert not actual.any()

    actual = utils.acomb(5, 5)
    assert actual.shape == (1, 5)
    assert actual.all()

    actual = utils.acomb(6, 4)
    expected = np.zeros_like(actual)
    for i, inds in enumerate(itertools.combinations(range(6), 4)):
        expected[i, inds] = True
    assert np.setxor1d(utils.axis_to_elem(actual),
                       utils.axis_to_elem(expected)).size == 0

    actual = utils.acomb(6, 4, True)
    expected = np.zeros_like(actual)
    for i, inds in enumerate(map(list, itertools.combinations_with_replacement(
            range(6), 4))):
        np.add.at(expected[i], inds, 1)
    assert np.setxor1d(utils.axis_to_elem(actual),
                       utils.axis_to_elem(expected)).size == 0
示例#25
0
def test_random_identity(keep_prob, game_desc, _):
    """Test random identity"""
    players, strategies = game_desc
    # Create game and reduction
    game = gamegen.game(players, strategies, keep_prob)
    assert (paygame.game_copy(rsgame.empty(players, strategies)) ==
            ir.reduce_game(rsgame.empty(players, strategies)))

    # Try to reduce game
    red_game = ir.reduce_game(game)

    # Assert that reducing all profiles covers reduced game
    reduced_full_profiles = utils.axis_to_elem(
        ir.reduce_profiles(red_game, game.profiles()))
    reduced_profiles = utils.axis_to_elem(red_game.profiles())
    assert np.setxor1d(reduced_full_profiles, reduced_profiles).size == 0, \
        "reduced game didn't match full game"

    full_profiles = utils.axis_to_elem(game.profiles())
    full_reduced_profiles = utils.axis_to_elem(
        ir.expand_profiles(game, red_game.profiles()))
    assert np.setxor1d(full_profiles, full_reduced_profiles).size == 0, \
        'full game did not match reduced game'
示例#26
0
def test_random_twins(players, strategies, keep_prob, _):
    """Test random twins reduction"""
    # Create game and reduction
    game = gamegen.game(players, strategies, keep_prob)

    # Try to reduce game
    red_game = tr.reduce_game(game)

    # Assert that reducing all profiles covers reduced game
    reduced_full_profiles = utils.axis_to_elem(
        tr.reduce_profiles(red_game, game.profiles()))
    reduced_profiles = utils.axis_to_elem(red_game.profiles())
    assert np.setdiff1d(reduced_profiles, reduced_full_profiles).size == 0, \
        "reduced game contained profiles it shouldn't have"

    # Assert that all contributing profiles are in the expansion of the reduced
    # game. We need to remove partial profiles first
    full_profiles = utils.axis_to_elem(game.profiles())
    complete_profs = ~np.isnan(red_game.payoffs()).any(1)
    full_reduced_profiles = utils.axis_to_elem(
        tr.expand_profiles(game, red_game.profiles()[complete_profs]))
    assert np.setdiff1d(full_reduced_profiles, full_profiles).size == 0, \
        'full game did not have data for all profiles required of reduced'
示例#27
0
def test_expansion_contributions():
    """Test expansion on approximate dpr"""
    red = reduction.DeviationPreserving([2, 2], [4, 9], [2, 3])
    red_profs = [
        [2, 0, 0, 3],
        [1, 1, 3, 0]]
    full_profs, contributions = red.expand_profiles(red_profs, True)
    profs = utils.axis_to_elem(full_profs)
    expected = utils.axis_to_elem([
        [4, 0, 0, 9],
        [1, 3, 9, 0],
        [3, 1, 9, 0],
        [2, 2, 9, 0]])
    assert np.setxor1d(profs, expected).size == 0, \
        "generated different profiles than expected"
    expected_conts = np.array([
        [1, 0, 0, 1],
        [1, 0, 0, 0],
        [0, 1, 0, 0],
        [0, 0, 1, 0]], bool)
    eord = np.argsort(expected)
    pord = np.argsort(profs)
    assert np.all(expected_conts[eord] == contributions[pord])
示例#28
0
def test_hierarchical_dev_expansion():
    """Test that hierarchical dev expansion is correct"""
    game = rsgame.BaseGame([3, 4], [4, 3])
    red = reduction.Hierarchical(game.num_strategies, game.num_players ** 2,
                                 game.num_players)
    mask = [True, False, True, False, False, True, False]
    profs = red.expand_deviation_profiles(mask)
    actual = utils.axis_to_elem(profs)
    expected = utils.axis_to_elem([
        [6, 3, 0, 0, 0, 16, 0],
        [3, 3, 3, 0, 0, 16, 0],
        [0, 3, 6, 0, 0, 16, 0],
        [6, 0, 0, 3, 0, 16, 0],
        [3, 0, 3, 3, 0, 16, 0],
        [0, 0, 6, 3, 0, 16, 0],
        [9, 0, 0, 0, 4, 12, 0],
        [6, 0, 3, 0, 4, 12, 0],
        [3, 0, 6, 0, 4, 12, 0],
        [0, 0, 9, 0, 4, 12, 0],
        [9, 0, 0, 0, 0, 12, 4],
        [6, 0, 3, 0, 0, 12, 4],
        [3, 0, 6, 0, 0, 12, 4],
        [0, 0, 9, 0, 0, 12, 4],
    ])
    assert np.setxor1d(actual, expected).size == 0

    profs = red.expand_deviation_profiles(mask, 0)
    actual = utils.axis_to_elem(profs)
    expected = utils.axis_to_elem([
        [6, 3, 0, 0, 0, 16, 0],
        [3, 3, 3, 0, 0, 16, 0],
        [0, 3, 6, 0, 0, 16, 0],
        [6, 0, 0, 3, 0, 16, 0],
        [3, 0, 3, 3, 0, 16, 0],
        [0, 0, 6, 3, 0, 16, 0],
    ])
    assert np.setxor1d(actual, expected).size == 0
示例#29
0
def test_identity_dev_expansion():
    """Test that identity dev expansion is correct"""
    game = rsgame.BaseGame([3, 4], [4, 3])
    red = reduction.Identity(game.num_strategies, game.num_players)
    mask = [True, False, True, False, False, True, False]
    profs = red.expand_deviation_profiles(mask)
    actual = utils.axis_to_elem(profs)
    expected = utils.axis_to_elem([
        [2, 1, 0, 0, 0, 4, 0],
        [1, 1, 1, 0, 0, 4, 0],
        [0, 1, 2, 0, 0, 4, 0],
        [2, 0, 0, 1, 0, 4, 0],
        [1, 0, 1, 1, 0, 4, 0],
        [0, 0, 2, 1, 0, 4, 0],
        [3, 0, 0, 0, 1, 3, 0],
        [2, 0, 1, 0, 1, 3, 0],
        [1, 0, 2, 0, 1, 3, 0],
        [0, 0, 3, 0, 1, 3, 0],
        [3, 0, 0, 0, 0, 3, 1],
        [2, 0, 1, 0, 0, 3, 1],
        [1, 0, 2, 0, 0, 3, 1],
        [0, 0, 3, 0, 0, 3, 1],
    ])
    assert np.setxor1d(actual, expected).size == 0

    profs = red.expand_deviation_profiles(mask, 0)
    actual = utils.axis_to_elem(profs)
    expected = utils.axis_to_elem([
        [2, 1, 0, 0, 0, 4, 0],
        [1, 1, 1, 0, 0, 4, 0],
        [0, 1, 2, 0, 0, 4, 0],
        [2, 0, 0, 1, 0, 4, 0],
        [1, 0, 1, 1, 0, 4, 0],
        [0, 0, 2, 1, 0, 4, 0],
    ])
    assert np.setxor1d(actual, expected).size == 0
示例#30
0
async def test_basic_profile():
    """Test that basic profiles are sampled twice"""
    sgame = gamegen.samplegame([4, 3], [3, 4])
    profs = utils.axis_from_elem(
        np.unique(utils.axis_to_elem(sgame.random_profiles(20))))

    save = savesched.savesched(gamesched.samplegamesched(sgame))
    sched = countsched.countsched(save, 10)
    assert str(sched) is not None
    paylist = await asyncio.gather(*[sched.sample_payoffs(p) for p in profs])
    pays = np.stack(paylist)
    assert np.allclose(pays[profs == 0], 0)

    savegame = save.get_game()
    assert list(savegame.num_samples) == [10]
示例#31
0
def test_all_subgames(players, strategies):
    game = rsgame.BaseGame(players, strategies)
    all_subgames = subgame.all_subgames(game)
    assert game.role_reduce(all_subgames, ufunc=np.logical_or).all(), \
        "Not all subgames were valid"

    distinct = np.unique(utils.axis_to_elem(all_subgames)).size
    assert distinct == all_subgames.shape[0]

    ids = subgame.subgame_id(game, all_subgames)
    distinct_ids = np.unique(ids).size
    assert distinct_ids == all_subgames.shape[0]

    all_subgames2 = subgame.subgame_from_id(game, ids)
    assert np.all(all_subgames == all_subgames2)
示例#32
0
def test_twins(keep_prob, game_desc):
    players, strategies = game_desc
    # Create game and reduction
    game = gamegen.role_symmetric_game(players, strategies)
    game = gamegen.drop_profiles(game, keep_prob)
    red = reduction.Twins(strategies, players)

    # Try to reduce game
    red_game = red.reduce_game(game)

    # Assert that reducing all profiles covers reduced game
    reduced_full_profiles = utils.axis_to_elem(
        red.reduce_profiles(game.profiles))
    reduced_profiles = utils.axis_to_elem(red_game.profiles)
    assert np.setdiff1d(reduced_profiles, reduced_full_profiles).size == 0, \
        "reduced game contained profiles it shouldn't have"

    # Assert that all contributing profiles are in the expansion of the reduced
    # game
    full_profiles = utils.axis_to_elem(game.profiles)
    full_reduced_profiles = utils.axis_to_elem(
        red.expand_profiles(red_game.profiles))
    assert np.setdiff1d(full_reduced_profiles, full_profiles).size == 0, \
        "full game did not have data for all profiles required of reduced"
示例#33
0
def test_dpr(keep_prob, game_desc):
    """Simple test that dpr functions are consistent"""
    players, strategies, red_players = game_desc
    # Create game and reduction
    game = gamegen.role_symmetric_game(players, strategies)
    game = gamegen.drop_profiles(game, keep_prob)
    sgame = gamegen.add_noise(game, 1, 3)
    red = reduction.DeviationPreserving(strategies, players, red_players)

    # Try to reduce game
    assert rsgame.basegame_copy(game) == red.full_game
    assert red.reduce_game(rsgame.basegame_copy(game)) == red.red_game
    red_game = red.reduce_game(game)
    red_game2 = reduction.reduce_game_dpr(game, red_players)
    red_sgame = red.reduce_game(sgame)

    # Assert that reduce_game_dpr produces identical results
    reduced_profiles = utils.axis_to_elem(red_game.profiles)
    reduced_profiles2 = utils.axis_to_elem(red_game2.profiles)
    assert np.setxor1d(reduced_profiles, reduced_profiles2).size == 0, \
        "different reduction functions didn't produce identical results"

    # Assert that reducing all profiles covers reduced game
    reduced_full_profiles = utils.axis_to_elem(
        red.reduce_profiles(game.profiles))
    assert np.setdiff1d(reduced_profiles, reduced_full_profiles).size == 0, \
        "reduced game contained profiles it shouldn't have"
    reduced_sample_profiles = utils.axis_to_elem(red_sgame.profiles)
    assert np.setdiff1d(reduced_sample_profiles,
                        reduced_full_profiles).size == 0, \
        "reduced sample game contained profiles it shouldn't have"
    assert np.setxor1d(reduced_sample_profiles,
                       reduced_profiles).size == 0, \
        "reduced sample game and reduced game had different profiles"

    # Assert that all contributing profiles are in the expansion of the reduced
    # game
    full_profiles = utils.axis_to_elem(game.profiles)
    full_reduced_profiles = utils.axis_to_elem(
        red.expand_profiles(red_game.profiles))
    assert np.setdiff1d(full_reduced_profiles, full_profiles).size == 0, \
        "full game did not have data for all profiles required of reduced"
    full_reduced_sample_profiles = utils.axis_to_elem(
        red.expand_profiles(red_sgame.profiles))
    assert np.setdiff1d(full_reduced_sample_profiles,
                        full_profiles).size == 0, \
        ("full sample game did not have data for all profiles required of "
         "reduced")
    assert np.setxor1d(full_reduced_profiles,
                       full_reduced_sample_profiles).size == 0, \
        "sample game didn't produce identical results"
示例#34
0
def test_random_hierarchical(keep_prob, players, strategies, red_players, _):
    """Test random hierarchical"""
    # Create game and reduction
    game = gamegen.game(players, strategies, keep_prob)
    assert (rsgame.empty(red_players, strategies) ==
            hr.reduce_game(rsgame.empty(players, strategies), red_players))

    # Try to reduce game
    red_game = hr.reduce_game(game, red_players)

    # Assert that reducing all profiles covers reduced game
    reduced_full_profiles = utils.axis_to_elem(
        hr.reduce_profiles(red_game, game.profiles()))
    reduced_profiles = utils.axis_to_elem(red_game.profiles())
    assert np.setxor1d(reduced_profiles, reduced_full_profiles).size == 0, \
        "reduced game contained profiles it shouldn't have"

    # Assert that all contributing profiles are in the expansion of the reduced
    # game. Since hr doesn't add any incomplete profiles, it can't produce any
    full_profiles = utils.axis_to_elem(game.profiles())
    full_reduced_profiles = utils.axis_to_elem(
        hr.expand_profiles(game, red_game.profiles()))
    assert np.setdiff1d(full_reduced_profiles, full_profiles).size == 0, \
        'full game did not have data for all profiles required of reduced'
def _reduce_profiles(red_game, profiles, return_contributions): # pylint: disable=too-many-locals
    """Reduce profiles using dpr

    Parameters
    ----------
    red_game : Game
        Game that reduced profiles will be profiles for.
    profiles : ndarray-like
        The profiles to reduce.
    return_contributions : bool, optional
        If true return ancillary information about where the payoffs come
        from.
    """
    profiles = np.asarray(profiles, int)
    utils.check(
        profiles.shape[-1] == red_game.num_strats,
        'profiles not a valid shape')
    if not profiles.size:
        return np.empty((0, red_game.num_strats), int)

    profiles = profiles.reshape((-1, red_game.num_strats))
    all_full_players = np.add.reduceat(profiles, red_game.role_starts, 1)
    full_players = all_full_players[0]
    utils.check(
        np.all(all_full_players == full_players), 'profiles must be valid')

    num_profs = profiles.shape[0]
    dev_profs = profiles.repeat(np.sum(profiles > 0, 1), 0)
    _, strat_inds = profiles.nonzero()
    dev_profs[np.arange(dev_profs.shape[0]), strat_inds] -= 1
    dev_red_players = _devs(red_game, num_profs)
    mask = (profiles > 0).ravel()

    red_profs, reduced = _common.reduce_profiles(
        red_game, dev_red_players[mask], dev_profs)
    rstrat_inds = strat_inds[reduced]
    red_profs[np.arange(red_profs.shape[0]), rstrat_inds] += 1
    red_profs, red_inds = np.unique(
        utils.axis_to_elem(red_profs), return_inverse=True)
    red_profs = utils.axis_from_elem(red_profs)
    if not return_contributions:
        return red_profs

    full_inds = np.arange(num_profs).repeat(
        red_game.num_strats)[mask][reduced]
    return red_profs, red_inds, full_inds, rstrat_inds
示例#36
0
def _reduce_profiles(red_game, profiles, return_contributions):  # pylint: disable=too-many-locals
    """Reduce profiles using dpr

    Parameters
    ----------
    red_game : Game
        Game that reduced profiles will be profiles for.
    profiles : ndarray-like
        The profiles to reduce.
    return_contributions : bool, optional
        If true return ancillary information about where the payoffs come
        from.
    """
    profiles = np.asarray(profiles, int)
    utils.check(profiles.shape[-1] == red_game.num_strats,
                'profiles not a valid shape')
    if not profiles.size:
        return np.empty((0, red_game.num_strats), int)

    profiles = profiles.reshape((-1, red_game.num_strats))
    all_full_players = np.add.reduceat(profiles, red_game.role_starts, 1)
    full_players = all_full_players[0]
    utils.check(np.all(all_full_players == full_players),
                'profiles must be valid')

    num_profs = profiles.shape[0]
    dev_profs = profiles.repeat(np.sum(profiles > 0, 1), 0)
    _, strat_inds = profiles.nonzero()
    dev_profs[np.arange(dev_profs.shape[0]), strat_inds] -= 1
    dev_red_players = _devs(red_game, num_profs)
    mask = (profiles > 0).ravel()

    red_profs, reduced = _common.reduce_profiles(red_game,
                                                 dev_red_players[mask],
                                                 dev_profs)
    rstrat_inds = strat_inds[reduced]
    red_profs[np.arange(red_profs.shape[0]), rstrat_inds] += 1
    red_profs, red_inds = np.unique(utils.axis_to_elem(red_profs),
                                    return_inverse=True)
    red_profs = utils.axis_from_elem(red_profs)
    if not return_contributions:
        return red_profs

    full_inds = np.arange(num_profs).repeat(red_game.num_strats)[mask][reduced]
    return red_profs, red_inds, full_inds, rstrat_inds
def expand_profiles(full_game, profiles): # pylint: disable=too-many-locals
    """Expand profiles using dpr

    Parameters
    ----------
    full_game : Game
        Game that expanded profiles will be valid for.
    profiles : ndarray-like
        The profiles to expand
    return_contributions : bool, optional
        If specified, returns a boolean array matching the shape is
        returned indicating the payoffs that are needed for the initial
        profiles.
    """
    profiles = np.asarray(profiles, int)
    utils.check(
        profiles.shape[-1] == full_game.num_strats,
        'profiles not a valid shape')
    if not profiles.size:
        return np.empty((0, full_game.num_strats), int)
    profiles = profiles.reshape((-1, full_game.num_strats))
    all_red_players = np.add.reduceat(profiles, full_game.role_starts, 1)
    red_players = all_red_players[0]
    utils.check(
        np.all(all_red_players == red_players), 'profiles must be valid')

    num_profs = profiles.shape[0]
    dev_profs = profiles[:, None] - np.eye(full_game.num_strats, dtype=int)
    dev_profs = np.reshape(dev_profs, (-1, full_game.num_strats))
    dev_full_players = _devs(full_game, num_profs)

    mask = ~np.any(dev_profs < 0, 1)
    devs = (np.eye(full_game.num_strats, dtype=bool)[None]
            .repeat(num_profs, 0)
            .reshape((-1, full_game.num_strats))[mask])
    dev_full_profs = _common.expand_profiles(
        full_game, dev_full_players[mask], dev_profs[mask]) + devs
    ids = utils.axis_to_elem(dev_full_profs)
    return dev_full_profs[np.unique(ids, return_index=True)[1]]
示例#38
0
def expand_profiles(full_game, profiles):  # pylint: disable=too-many-locals
    """Expand profiles using dpr

    Parameters
    ----------
    full_game : Game
        Game that expanded profiles will be valid for.
    profiles : ndarray-like
        The profiles to expand
    return_contributions : bool, optional
        If specified, returns a boolean array matching the shape is
        returned indicating the payoffs that are needed for the initial
        profiles.
    """
    profiles = np.asarray(profiles, int)
    utils.check(profiles.shape[-1] == full_game.num_strats,
                'profiles not a valid shape')
    if not profiles.size:
        return np.empty((0, full_game.num_strats), int)
    profiles = profiles.reshape((-1, full_game.num_strats))
    all_red_players = np.add.reduceat(profiles, full_game.role_starts, 1)
    red_players = all_red_players[0]
    utils.check(np.all(all_red_players == red_players),
                'profiles must be valid')

    num_profs = profiles.shape[0]
    dev_profs = profiles[:, None] - np.eye(full_game.num_strats, dtype=int)
    dev_profs = np.reshape(dev_profs, (-1, full_game.num_strats))
    dev_full_players = _devs(full_game, num_profs)

    mask = ~np.any(dev_profs < 0, 1)
    devs = (np.eye(full_game.num_strats,
                   dtype=bool)[None].repeat(num_profs, 0).reshape(
                       (-1, full_game.num_strats))[mask])
    dev_full_profs = _common.expand_profiles(full_game, dev_full_players[mask],
                                             dev_profs[mask]) + devs
    ids = utils.axis_to_elem(dev_full_profs)
    return dev_full_profs[np.unique(ids, return_index=True)[1]]
示例#39
0
 def __hash__(self):
     return hash(
         (super().__hash__(),
          np.sort(utils.axis_to_elem(self.function_inputs.T)).tobytes()))
示例#40
0
def test_sample_profiles(players, strats, _):
    """Test sample profiles"""
    game = gamegen.game(players, strats)
    profiles = gamegen.sample_profiles(game, 5)
    uprofs = utils.axis_from_elem(np.unique(utils.axis_to_elem(profiles)))
    assert uprofs.shape == (5, game.num_strats)
示例#41
0
def array_set_equals(one, two):
    """Returns true if the unique last dimensions are the same set"""
    return not np.setxor1d(utils.axis_to_elem(one),
                           utils.axis_to_elem(two)).size
示例#42
0
def array_set_equal(arr, brr):
    """Return true if two sets of arrays are equal"""
    return not np.setxor1d(
        utils.axis_to_elem(arr), utils.axis_to_elem(brr)).size