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))))
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)
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))))
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)
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))
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))
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]
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 _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 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)