def test_null_payoff(): """Test that null payoff warnings are detected""" json_data = { 'players': {'role': 1}, 'strategies': {'role': ['strat']}, 'profiles': [{'role': [['strat', 1, None]]}], } with warnings.catch_warnings(): warnings.simplefilter('error') with pytest.raises(UserWarning): gameio.read_game(json_data)
def test_dominance_1(): run('dom', '-h') string, _ = run('dom', '-i', GAME) game, serial = gameio.read_game(json.loads(string)) assert serial == SERIAL assert game == GAME_DATA
def test_json_copy_game(players, strategies): game1 = gamegen.role_symmetric_game(players, strategies) serial = gamegen.serializer(game1) game2, _ = gameio.read_game(serial.to_game_json(game1)) assert game1 == game2 assert np.all(game1.profiles == game2.profiles) assert np.allclose(game1.payoffs, game2.payoffs)
def main(args): game, serial = gameio.read_game(json.load(args.input)) prof_func = TYPE[args.type] payoffs = [prof_func(game, serial, serial.from_prof_json(prof)) for prof in scriptutils.load_profiles(args.profiles)] json.dump(payoffs, args.output) args.output.write('\n')
def test_subgame_extract_2(): with tempfile.NamedTemporaryFile('w') as sub: subg = [False, True, True, False, False, False, False, False, False] json.dump([SERIAL.to_subgame_json(subg)], sub) sub.flush() string, _ = run('sub', '-i', GAME, '-f', sub.name) game, serial = gameio.read_game(json.loads(string)[0]) assert serial == subgame.subserializer(SERIAL, subg) assert game == subgame.subgame(GAME_DATA, subg)
def main(args): game, serial = gameio.read_game(json.load(args.input)) prof_func = TYPE[args.type] regrets = [prof_func(game, serial, serial.from_mix_json(prof, verify=False)) for prof in scriptutils.load_profiles(args.profiles)] json.dump(regrets, args.output) args.output.write('\n')
def test_sorted_strategy(_): with open('test/hard_nash_game_1.json') as f: _, conv = gameio.read_game(json.load(f)) assert all(a < b for a, b in zip(conv.role_names[:-1], conv.role_names[1:])), \ "loaded json game didn't have sorted roles" assert all(all(a < b for a, b in zip(strats[:-1], strats[1:])) for strats in conv.strat_names), \ "loaded json game didn't have sorted strategies"
def main(args): game, serial = gameio.read_game(json.load(args.input)) sub_mask = dominance.iterated_elimination(game, args.criterion, args.unconditional) if args.strategies: res = {r: list(s) for r, s in serial.to_subgame_json(sub_mask).items()} json.dump(res, args.output) else: sub_game = subgame.subgame(game, sub_mask) sub_serial = subgame.subserializer(serial, sub_mask) json.dump(sub_serial.to_game_json(sub_game), args.output) args.output.write('\n')
def test_hard_nash(): with open('test/hard_nash_game_1.json') as f: game, conv = gameio.read_game(json.load(f)) eqa = nash.mixed_nash(game) expected = conv.from_prof_json({ 'background': { 'markov:rmin_30000_rmax_30000_thresh_0.001_priceVarEst_1e6': 0.5407460907477768, 'markov:rmin_500_rmax_1000_thresh_0.8_priceVarEst_1e9': 0.45925390925222315 }, 'hft': { 'trend:trendLength_5_profitDemanded_50_expiration_50': 1.0 } }) assert np.isclose(game.trim_mixture_support(eqa), expected, atol=1e-4, rtol=1e-4).all(1).any(), \ "Didn't find equilibrium in known hard instance"
def main(args): game, serial = gameio.read_game(json.load(args.input)) if args.type == 'pure': equilibria = nash.pure_nash(game, args.regret) if args.one and not equilibria: equilibria = nash.min_regret_profile(game)[None] elif args.type == 'mixed': rep_args = { 'max_iters': args.max_iterations, 'converge_thresh': args.convergence } equilibria = nash.mixed_nash(game, args.regret, args.distance, random_restarts=args.random_mixtures, grid_points=args.grid_points, at_least_one=args.one, processes=args.processes, replicator=rep_args, optimize={}) equilibria = game.trim_mixture_support(equilibria, args.support) elif args.type == 'min-reg-prof': equilibria = nash.min_regret_profile(game)[None] elif args.type == 'min-reg-grid': equilibria = nash.min_regret_grid_mixture( game, args.grid_points)[None] equilibria = game.trim_mixture_support(equilibria, args.support) elif args.type == 'min-reg-rand': equilibria = nash.min_regret_rand_mixture( game, args.random_mixtures)[None] equilibria = game.trim_mixture_support(equilibria, args.support) elif args.type == 'rand': equilibria = game.random_mixtures(args.random_mixtures) equilibria = game.trim_mixture_support(equilibria, args.support) else: raise ValueError('Unknown command given: {0}'.format(args.type)) # pragma: no cover # noqa json.dump([serial.to_prof_json(eqm) for eqm in equilibria], args.output) args.output.write('\n')
def main(args): game, serial = gameio.read_game(json.load(args.input)) mix = serial.from_mix_json(json.load(args.mix)) if args.deviations: profs = (game.random_deviator_profiles(mix, args.num) .reshape((-1, game.num_role_strats))) dev_names = itertools.cycle(itertools.chain.from_iterable( ((r, s) for s in ses) for r, ses in zip(serial.role_names, serial.strat_names))) for prof, (devrole, devstrat) in zip(profs, dev_names): json.dump(dict( devrole=devrole, devstrat=devstrat, profile=serial.to_prof_json(prof)), args.output) args.output.write('\n') else: for prof in game.random_profiles(args.num, mix): json.dump(serial.to_prof_json(prof), args.output) args.output.write('\n')
def main(args): game, serial = gameio.read_game(json.load(args.input)) # Collect all subgames subgames = [] if args.detect: subgames.extend(subgame.maximal_subgames(game)) for sub_file in args.subgame_file: subgames.extend(serial.from_subgame_json(spec) for spec in json.load(sub_file)) subgames.extend(parse_text_spec(serial, spec) for spec in args.text_spec) subgames.extend(parse_index_spec(serial, spec) for spec in args.index_spec) if args.no_extract: json.dump([serial.to_subgame_json(sub) for sub in subgames], args.output) else: json.dump([ subgame.subserializer(serial, sub).to_game_json( subgame.subgame(game, sub)) for sub in subgames], args.output) args.output.write('\n')
def main(args): game, serial = gameio.read_game(json.load(args.input)) game = GAME_TYPE[args.type](game) OUTPUT_TYPE[args.format](game, serial, args.output) args.output.write('\n')
def test_dominance_5(): string, _ = run('dom', '-cneverbr', '-i', GAME) gameio.read_game(json.loads(string))
def test_game_from_json(json_): gameio.read_game(json_)
def test_game_equality(jgame): game, serial = gameio.read_game(jgame) assert rsgame.game_copy(game) == rsgame.game_copy(GAME) assert serial == SERIAL
def test_gamegen_2(): string, _ = run('gen', 'ursym', '3', '4', '4', '3') gameio.read_game(json.loads(string))
def create(args): game, serial = gameio.read_game(json.load(args.input)) dist = Noise.distributions[args.distribution] return gamegen.add_noise_width(game, args.num_samples, args.max_width, dist), serial
def test_reduction_4(): string, _ = run('red', '-ttr', '-i', GAME) game, serial = gameio.read_game(json.loads(string)) red = reduction.Twins([2, 7], [6, 1]) assert serial == SERIAL assert game == red.reduce_game(GAME_DATA)
def test_gamegen_3(): string, _ = run('gen', 'noise', 'uniform', '1.5', '5', input=GAME_STR) gameio.read_game(json.loads(string))
def main(args): game, serial = gameio.read_game(json.load(args.input)) if args.dpr: red_players = serial.from_role_json(dict(zip( args.dpr[::2], map(int, args.dpr[1::2])))) red = reduction.DeviationPreserving(game.num_strategies, game.num_players, red_players) redgame = red.reduce_game(game, True) else: redgame = game redserial = serial if args.dominance: domsub = dominance.iterated_elimination(redgame, 'strictdom') redgame = subgame.subgame(redgame, domsub) redserial = subgame.subserializer(redserial, domsub) if args.subgames: subgames = subgame.maximal_subgames(redgame) else: subgames = np.ones(redgame.num_role_strats, bool)[None] methods = { 'replicator': { 'max_iters': args.max_iters, 'converge_thresh': args.converge_thresh}, 'optimize': {}} noeq_subgames = [] candidates = [] for submask in subgames: subg = subgame.subgame(redgame, submask) subeqa = nash.mixed_nash( subg, regret_thresh=args.regret_thresh, dist_thresh=args.dist_thresh, processes=args.processes, **methods) eqa = subgame.translate(subg.trim_mixture_support( subeqa, supp_thresh=args.supp_thresh), submask) if eqa.size: for eqm in eqa: if not any(linalg.norm(eqm - eq) < args.dist_thresh for eq in candidates): candidates.append(eqm) else: noeq_subgames.append(submask) # pragma: no cover equilibria = [] unconfirmed = [] unexplored = [] for eqm in candidates: support = eqm > 0 gains = regret.mixture_deviation_gains(redgame, eqm) role_gains = redgame.role_reduce(gains, ufunc=np.fmax) gain = np.nanmax(role_gains) if np.isnan(gains).any() and gain <= args.regret_thresh: # Not fully explored but might be good unconfirmed.append((eqm, gain)) elif np.any(role_gains > args.regret_thresh): # There are deviations, did we explore them? dev_inds = ([np.argmax(gs == mg) for gs, mg in zip(redgame.role_split(gains), role_gains)] + redgame.role_starts)[role_gains > args.regret_thresh] for dind in dev_inds: devsupp = support.copy() devsupp[dind] = True if not np.all(devsupp <= subgames, -1).any(): unexplored.append((devsupp, dind, gains[dind], eqm)) else: # Equilibrium! equilibria.append((eqm, np.max(gains))) # Output Game args.output.write('Game Analysis\n') args.output.write('=============\n') args.output.write(serial.to_game_printstr(game)) args.output.write('\n\n') if args.dpr is not None: args.output.write('With DPR reduction: ') args.output.write(' '.join(args.dpr)) args.output.write('\n\n') if args.dominance: num = np.sum(~domsub) if num: args.output.write('Found {:d} dominated strateg{}\n'.format( num, 'y' if num == 1 else 'ies')) args.output.write(serial.to_subgame_printstr(~domsub)) args.output.write('\n') else: args.output.write('Found no dominated strategies\n\n') if args.subgames: num = subgames.shape[0] if num: args.output.write( 'Found {:d} maximal complete subgame{}\n\n'.format( num, '' if num == 1 else 's')) else: args.output.write('Found no complete subgames\n\n') args.output.write('\n') # Output social welfare args.output.write('Social Welfare\n') args.output.write('--------------\n') welfare, profile = regret.max_pure_social_welfare(game) if profile is None: args.output.write('There was no profile with complete payoff data\n\n') else: args.output.write('\nMaximum social welfare profile:\n') args.output.write(serial.to_prof_printstr(profile)) args.output.write('Welfare: {:.4f}\n\n'.format(welfare)) if game.num_roles > 1: for role, welfare, profile in zip( serial.role_names, *regret.max_pure_social_welfare(game, True)): args.output.write('Maximum "{}" welfare profile:\n'.format( role)) args.output.write(serial.to_prof_printstr(profile)) args.output.write('Welfare: {:.4f}\n\n'.format(welfare)) args.output.write('\n') # Output Equilibria args.output.write('Equilibria\n') args.output.write('----------\n') if equilibria: args.output.write('Found {:d} equilibri{}\n\n'.format( len(equilibria), 'um' if len(equilibria) == 1 else 'a')) for i, (eqm, reg) in enumerate(equilibria, 1): args.output.write('Equilibrium {:d}:\n'.format(i)) args.output.write(redserial.to_mix_printstr(eqm)) args.output.write('Regret: {:.4f}\n\n'.format(reg)) else: args.output.write('Found no equilibria\n\n') # pragma: no cover args.output.write('\n') # Output No-equilibria Subgames args.output.write('No-equilibria Subgames\n') args.output.write('----------------------\n') if noeq_subgames: # pragma: no cover args.output.write('Found {:d} no-equilibria subgame{}\n\n'.format( len(noeq_subgames), '' if len(noeq_subgames) == 1 else 's')) noeq_subgames.sort(key=lambda x: x.sum()) for i, subg in enumerate(noeq_subgames, 1): args.output.write('No-equilibria subgame {:d}:\n'.format(i)) args.output.write(redserial.to_subgame_printstr(subg)) args.output.write('\n') else: args.output.write('Found no no-equilibria subgames\n\n') args.output.write('\n') # Output Unconfirmed Candidates args.output.write('Unconfirmed Candidate Equilibria\n') args.output.write('--------------------------------\n') if unconfirmed: args.output.write('Found {:d} unconfirmed candidate{}\n\n'.format( len(unconfirmed), '' if len(unconfirmed) == 1 else 's')) unconfirmed.sort(key=lambda x: ((x[0] > 0).sum(), x[1])) for i, (eqm, reg_bound) in enumerate(unconfirmed, 1): args.output.write('Unconfirmed candidate {:d}:\n'.format(i)) args.output.write(redserial.to_mix_printstr(eqm)) args.output.write('Regret at least: {:.4f}\n\n'.format(reg_bound)) else: args.output.write('Found no unconfirmed candidate equilibria\n\n') args.output.write('\n') # Output Unexplored Subgames args.output.write('Unexplored Best-response Subgames\n') args.output.write('---------------------------------\n') if unexplored: min_supp = min(supp.sum() for supp, _, _, _ in unexplored) args.output.write( 'Found {:d} unexplored best-response subgame{}\n'.format( len(unexplored), '' if len(unexplored) == 1 else 's')) args.output.write( 'Smallest unexplored subgame has support {:d}\n\n'.format( min_supp)) unexplored.sort(key=lambda x: (x[0].sum(), -x[2])) for i, (sub, dev, gain, eqm) in enumerate(unexplored, 1): args.output.write('Unexplored subgame {:d}:\n'.format(i)) args.output.write(redserial.to_subgame_printstr(sub)) args.output.write('{:.4f} for deviating to {} from:\n'.format( gain, redserial.strat_name(dev))) args.output.write(redserial.to_mix_printstr(eqm)) args.output.write('\n') else: args.output.write('Found no unexplored best-response subgames\n\n') args.output.write('\n') # Output json data args.output.write('Json Data\n') args.output.write('=========\n') json_data = { 'equilibria': [redserial.to_mix_json(eqm) for eqm, _ in equilibria]} json.dump(json_data, args.output) args.output.write('\n')
def test_reduction_3(): string, _ = run('red', '-thr', '-s', '2', '1', '-i', GAME) game, serial = gameio.read_game(json.loads(string)) red = reduction.Hierarchical([2, 7], [6, 1], [2, 1]) assert serial == SERIAL assert game == red.reduce_game(GAME_DATA)
def test_dominance_4(): string, _ = run('dom', '-cstrictdom', '-i', GAME) gameio.read_game(json.loads(string))
def test_known_fail_case(): with open('test/hard_nash_game_1.json') as f: game, _ = gameio.read_game(json.load(f)) dominance.iterated_elimination(game, 'neverbr')
def test_gamegen_5(): string, _ = run('gen', 'noise', 'bimodal', '1.5', '5', '-i', GAME) gameio.read_game(json.loads(string))
def test_json_copy_game(players, strategies): game1 = gamegen.role_symmetric_game(players, strategies) serial = gamegen.game_serializer(game1) game2, _ = gameio.read_game(game1.to_json(serial)) assert game1 == game2
def main(args): game, serial = gameio.read_game(json.load(args.input)) # create gpgame lgame = gpgame.PointGPGame(game) # mixed strategy nash equilibria search methods = { 'replicator': { 'max_iters': args.max_iters, 'converge_thresh': args.converge_thresh}} mixed_equilibria = game.trim_mixture_support( nash.mixed_nash(lgame, regret_thresh=args.regret_thresh, dist_thresh=args.dist_thresh, processes=args.processes, at_least_one=True, **methods), args.supp_thresh) equilibria = [(eqm, regret.mixture_regret(lgame, eqm)) for eqm in mixed_equilibria] # Output game args.output.write('Game Learning\n') args.output.write('=============\n') args.output.write(game.to_str(serial)) args.output.write('\n\n') # Output social welfare args.output.write('Social Welfare\n') args.output.write('--------------\n') welfare, profile = game.get_max_social_welfare() if profile is None: args.output.write('There was no profile with complete payoff data\n\n') else: args.output.write('\nMaximum social welfare profile:\n') args.output.write(serial.to_prof_printstring(profile)) args.output.write('Welfare: {:.4f}\n\n'.format(welfare)) if game.num_roles > 1: for role, welfare, profile in zip( serial.role_names, *game.get_max_social_welfare(True)): args.output.write('Maximum "{}" welfare profile:\n'.format( role)) args.output.write(serial.to_prof_printstring(profile)) args.output.write('Welfare: {:.4f}\n\n'.format(welfare)) args.output.write('\n') # Output Equilibria args.output.write('Equilibria\n') args.output.write('----------\n') if equilibria: args.output.write('Found {:d} equilibri{}\n\n'.format( len(equilibria), 'um' if len(equilibria) == 1 else 'a')) for i, (eqm, reg) in enumerate(equilibria, 1): args.output.write('Equilibrium {:d}:\n'.format(i)) args.output.write(serial.to_prof_printstring(eqm)) args.output.write('Regret: {:.4f}\n\n'.format(reg)) else: args.output.write('Found no equilibria\n\n') args.output.write('\n') # Output json data args.output.write('Json Data\n') args.output.write('=========\n') json_data = { 'equilibria': [serial.to_prof_json(eqm) for eqm, _ in equilibria]} json.dump(json_data, args.output) args.output.write('\n')
def test_gamegen_6(): string, _ = run('gen', 'noise', 'gaussian', '1.5', '5', '-i', GAME) gameio.read_game(json.loads(string))
def main(args): data, serial = gameio.read_game(json.load(args.input)) game = gpgame.BaseGPGame(data) pickle.dump(game, args.output) pickle.dump(serial, args.output)
def test_reduction_5(): string, _ = run('red', '-tidr', '-i', GAME) game, serial = gameio.read_game(json.loads(string)) assert serial == SERIAL assert game == GAME_DATA