def _checked_iterated_dominance(self, *args, **kwargs): reduced_game, live_actions = lp_solver.iterated_dominance(*args, **kwargs) if isinstance(reduced_game, pyspiel.MatrixGame): payoffs_shape = [2, reduced_game.num_rows(), reduced_game.num_cols()] else: payoffs_shape = list(reduced_game.shape) self.assertLen(live_actions, payoffs_shape[0]) self.assertListEqual(payoffs_shape[1:], [ np.sum(live_actions_for_player) for live_actions_for_player in live_actions ]) return reduced_game, live_actions
def main(_): game = pyspiel.load_game(FLAGS.game) print("loaded game") # convert game to matrix form if it isn't already a matrix game if not isinstance(game, pyspiel.MatrixGame): game = pyspiel.extensive_to_matrix_game(game) num_rows, num_cols = game.num_rows(), game.num_cols() print("converted to matrix form with shape (%d, %d)" % (num_rows, num_cols)) # use iterated dominance to reduce the space unless the solver is LP (fast) if FLAGS.solver != "linear": if FLAGS.mode == "all": game, _ = lp_solver.iterated_dominance( game, tol=FLAGS.tol, mode=lp_solver.DOMINANCE_STRICT) num_rows, num_cols = game.num_rows(), game.num_cols() print( "discarded strictly dominated actions yielding shape (%d, %d)" % (num_rows, num_cols)) if FLAGS.mode == "one": game, _ = lp_solver.iterated_dominance( game, tol=FLAGS.tol, mode=lp_solver.DOMINANCE_VERY_WEAK) num_rows, num_cols = game.num_rows(), game.num_cols() print( "discarded very weakly dominated actions yielding shape (%d, %d)" % (num_rows, num_cols)) # game is now finalized num_rows, num_cols = game.num_rows(), game.num_cols() row_actions = [game.row_action_name(row) for row in range(num_rows)] col_actions = [game.col_action_name(col) for col in range(num_cols)] row_payoffs, col_payoffs = utils.game_payoffs_array(game) pure_nash = list( zip(*((row_payoffs >= row_payoffs.max(0, keepdims=True) - FLAGS.tol) & (col_payoffs >= col_payoffs.max(1, keepdims=True) - FLAGS.tol) ).nonzero())) if pure_nash: print("found %d pure equilibria" % len(pure_nash)) if FLAGS.mode == "pure": if not pure_nash: print("found no pure equilibria") return print("pure equilibria:") for row, col in pure_nash: print("payoffs %f, %f:" % (row_payoffs[row, col], col_payoffs[row, col])) print("row action:") print(row_actions[row]) print("col action:") print(col_actions[col]) print("") return if FLAGS.mode == "one" and pure_nash: print("pure equilibrium:") row, col = pure_nash[0] print("payoffs %f, %f:" % (row_payoffs[row, col], col_payoffs[row, col])) print("row action:") print(row_actions[row]) print("col action:") print(col_actions[col]) print("") return for row, action in enumerate(row_actions): print("row action %s:" % row) print(action) print("--") for col, action in enumerate(col_actions): print("col action %s:" % col) print(action) print("--") if num_rows == 1 or num_cols == 1: equilibria = itertools.product(np.eye(num_rows), np.eye(num_cols)) elif FLAGS.solver == "linear": if FLAGS.mode != "one" or (row_payoffs + col_payoffs).max() > ( row_payoffs + col_payoffs).min() + FLAGS.tol: raise ValueError( "can't use linear solver for non-constant-sum game or " "for finding all optima!") print("using linear solver") def gen(): p0_sol, p1_sol, _, _ = lp_solver.solve_zero_sum_matrix_game( pyspiel.create_matrix_game(row_payoffs - col_payoffs, col_payoffs - row_payoffs)) yield (np.squeeze(p0_sol, 1), np.squeeze(p1_sol, 1)) equilibria = gen() elif FLAGS.solver == "lrsnash": print("using lrsnash solver") equilibria = lrs_solve(row_payoffs, col_payoffs) elif FLAGS.solver == "nashpy": if FLAGS.mode == "all": print("using nashpy vertex enumeration") equilibria = nashpy.Game(row_payoffs, col_payoffs).vertex_enumeration() else: print("using nashpy Lemke-Howson solver") equilibria = lemke_howson_solve(row_payoffs, col_payoffs) print("equilibria:" if FLAGS.mode == "all" else "an equilibrium:") equilibria = iter(equilibria) # check that there's at least one equilibrium try: equilibria = itertools.chain([next(equilibria)], equilibria) except StopIteration: print("not found!") for row_mixture, col_mixture in equilibria: print("payoffs %f, %f for %s, %s" % (row_mixture.dot(row_payoffs.dot(col_mixture)), row_mixture.dot( col_payoffs.dot(col_mixture)), row_mixture, col_mixture)) if FLAGS.mode == "one": return