示例#1
0
    def nearby_profs(self, prof, num_devs):
        """Returns profiles reachable by at most num_devs deviations"""
        # XXX this is the bottleneck for gpgame.neighbor_EVs. It seems like
        # there should be some clever way to speed it up.
        assert num_devs >= 0
        dev_players = utils.acomb(self.num_roles, num_devs, True)
        mask = np.all(dev_players <= self.num_players, 1)
        dev_players = dev_players[mask]
        supp = prof > 0
        sub = subgame.subgame(rsgame.BaseGame(self), supp)

        profs = [prof[None]]
        for players in dev_players:
            to_dev_profs = rsgame.BaseGame(
                players, self.num_strategies).all_profiles()
            from_dev_profs = subgame.translate(
                rsgame.BaseGame(players, sub.num_strategies).all_profiles(),
                supp)
            before_devs = prof - from_dev_profs
            before_devs = before_devs[np.all(before_devs >= 0, 1)]
            before_devs = utils.unique_axis(before_devs)
            nearby = before_devs[:, None] + to_dev_profs
            nearby.shape = (-1, self.num_role_strats)
            profs.append(utils.unique_axis(nearby))
        profs = np.concatenate(profs)
        return utils.unique_axis(profs)
示例#2
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
示例#3
0
def add_profiles(game, prob_or_count=1.0, distribution=default_distribution):
    """Add profiles to a base game

    Parameters
    ----------
    distribution : (shape) -> ndarray, optional
        Distribution function to draw profiles from.
    prob_or_count : float or int, optional
        If a float, the probability to add a profile from the full game. If an
        int, the number of profiles to add.
    independent : bool, optional
        If true then each profile has `prob` probability of being added, else
        `num_all_profiles * prob` profiles will be kept.
    """
    # First turn input into number of profiles to compute
    num_profs = game.num_all_profiles
    if isinstance(prob_or_count, float):
        assert 0 <= prob_or_count <= 1
        if num_profs <= np.iinfo(int).max:
            num = rand.binomial(num_profs, prob_or_count)
        else:
            num = round(float(num_profs * prob_or_count))
    else:
        assert 0 <= prob_or_count <= num_profs
        num = prob_or_count

    # Generate profiles based number and size of game

    # Ratio of the expected number of profiles we'd have to draw at random to
    # produce num unique relative to the number of total profiles
    ratio = sps.digamma(float(num_profs)) - sps.digamma(float(num_profs - num))
    if num == num_profs:
        profiles = game.all_profiles()
    elif num == 0:
        profiles = np.empty((0, game.num_role_strats), int)
    elif ratio >= 1:
        inds = rand.choice(num_profs, num, replace=False)
        profiles = game.all_profiles()[inds]
    else:
        profiles = np.empty((0, game.num_role_strats), int)
        num_per = max(round(float(ratio * num_profs)), num)  # Max => underflow
        mix = game.uniform_mixture()
        while profiles.shape[0] < num:
            profiles = np.concatenate([profiles,
                                       game.random_profiles(num_per, mix)])
            profiles = utils.unique_axis(profiles)
        inds = rand.choice(profiles.shape[0], num, replace=False)
        profiles = profiles[inds]

    # Fill out game with profiles
    payoffs = np.zeros(profiles.shape)
    mask = profiles > 0
    payoffs[mask] = distribution(mask.sum())
    return rsgame.game_copy(game, profiles, payoffs, False)
示例#4
0
    def reduce_profiles(self, profiles, return_contributions=False):
        """Reduces a set of profiles

        If `return_contributions` returns ancillary information.

        Returns
        -------
        red_profs
            The reduced profiles
        red_inds
            Index in red_profs for each payoff value that was reduced.
        full_inds
            Index into profiles for each payoff value that was reduced.
        strat_inds
            Index into a profile for the index of each payoff.  Parallel with
            red_inds and full_inds.
        """
        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)
        red_profs, reduced = _reduce_rsym_profiles(
            self.full_game, dev_profs[mask], dev_full_players[mask],
            dev_red_players[mask])
        devs = np.eye(self.full_game.num_role_strats, dtype=int)[None]\
            .repeat(num_profs, 0)\
            .reshape((-1, self.full_game.num_role_strats))[mask][reduced]
        red_profs += devs
        red_profs, red_inds = utils.unique_axis(red_profs, return_inverse=True)
        if not return_contributions:
            return red_profs
        else:
            full_inds = np.arange(num_profs)[:, None].repeat(
                self.full_game.num_role_strats, 1).flat[mask][reduced]
            strat_inds = devs.nonzero()[1]
            return red_profs, red_inds, full_inds, strat_inds