/// <summary> /// Solves the game by fictitious play and verifies the solution. /// </summary> /// <param name="snapshotAfter">Number of iterations to make an intermediate snapshot after. -1 for no intermediate snapshot.</param> /// <param name="configureSolver"></param> private StrategyTree[] SolveAndVerifyVerifySolution(ActionTree at, ChanceTree ct, double epsilon, bool useLp) { if (useLp) { double[] gv; StrategyTree[] st = EqLp.Solve(at, ct, out gv); VisStrategyTree.Show(st[0], Path.Combine(_outDir, "st-0.gv")); VisStrategyTree.Show(st[1], Path.Combine(_outDir, "st-1.gv")); Console.WriteLine("LP gv: {0}, {1}", gv[0], gv[1]); } FictPlayHelper fp = new FictPlayHelper { Epsilon = epsilon, VisualizeTrees = true, BaseDir = Path.Combine(_outDir, "fp") }; StrategyTree[] eqStrategies = fp.Solve(at, ct); string error; // Verify consistency of strategies for (int p = 0; p < 2; ++p) { Assert.IsTrue(VerifyAbsStrategy.Verify(eqStrategies[p], p, 1e-7, out error), string.Format("Pos {0}: {1}", p, error)); } // Run VerifyEq on the computed strategies. Assert.IsTrue(VerifyEq.Verify(at, ct, eqStrategies, 3 * epsilon, out error), error); return(eqStrategies); }
public void Solve(ActionTree at, HePocketKind[] sbCards, HePocketKind[] bbCards) { Ct = CreateCt(sbCards, bbCards); var gv = new double[2]; Strategies = EqLp.Solve(at, Ct, out gv); GameValues = gv; }
/// <summary> /// This functions simulate a typical use case: create trees in many runs of MC sampling, write them, read again /// and merge into the master tree. The master tree is than verified. /// </summary> private void GenerateAndVerifyCT(string name, GameDefinition gd, IChanceAbstraction[] chanceAbstractions, bool areAbstractionsEqual, int samplesCount, int runsCount, double avRelProbabEps, double avPotShareEps, double eqValEps, bool visualize) { CtMcGen.Tree masterTree = new CtMcGen.Tree(); int rngSeed = (int)DateTime.Now.Ticks; for (int run = 0; run < runsCount; ++run) { CtMcGen.Tree runTree = CtMcGen.Generate(gd, chanceAbstractions, areAbstractionsEqual, samplesCount, rngSeed, null); string fileName = Path.Combine(_outDir, String.Format("{0}-{1}-ct.dat", gd.Name, name)); runTree.Write(fileName); masterTree.Read(fileName); // Do not use the timer anymore because the tests are too fast. rngSeed++; } ChanceTree actCt = masterTree.ConvertToChanceTree(); VisChanceTree.Show(actCt, Path.Combine(_outDir, String.Format("{0}-{1}-ct.gv", gd.Name, name))); VerifyChanceTree.VerifyS(actCt); ChanceTree expCt = CreateChanceTreeByAbstraction.CreateS(gd, chanceAbstractions); Assert.AreEqual(expCt.PlayersCount, actCt.PlayersCount); CompareChanceTrees cmp = new CompareChanceTrees(); cmp.IsVerbose = visualize; cmp.Output = Console.Out; cmp.Compare(expCt, actCt); VisChanceTree.Show(expCt, Path.Combine(_outDir, String.Format("{0}-{1}-ct-exp.gv", gd.Name, name))); Assert.Less(cmp.AverageRelProbabDiff, avRelProbabEps); for (int p = 0; p < chanceAbstractions.Length; ++p) { Assert.Less(cmp.AveragePotShareDiff[p], avRelProbabEps); } ActionTree at = CreateActionTreeByGameDef.Create(gd); double [] actEqValues, expEqValues; EqLp.Solve(at, actCt, out actEqValues); EqLp.Solve(at, expCt, out expEqValues); for (int p = 0; p < chanceAbstractions.Length; ++p) { if (visualize) { Console.WriteLine("Eq pos: {0} exp: {1} act: {2}", p, expEqValues[p], actEqValues[p]); } Assert.AreEqual(expEqValues[p], actEqValues[p], eqValEps); } if (visualize) { Console.WriteLine(); } }
static int Main(string[] args) { if (!Parser.ParseArgumentsWithUsage(args, _cmdLine)) { return(1); } if (_cmdLine.DebuggerLaunch) { Debugger.Launch(); } GameDefinition gd = XmlSerializerExt.Deserialize <GameDefinition>(_cmdLine.GameDef.Get(Props.Global)); string chanceTreeFile = _cmdLine.ChanceTree.Get(Props.Global); ChanceTree ct; if (string.IsNullOrEmpty(chanceTreeFile)) { ct = CreateChanceTreeByGameDef.Create(gd); } else { ct = ChanceTree.Read <ChanceTree>(chanceTreeFile); } ActionTree at = CreateActionTreeByGameDef.Create(gd); double [] values; StrategyTree [] st = EqLp.Solve(at, ct, out values); if (st == null) { Console.WriteLine("Cannot find solution"); return(1); } string output = _cmdLine.Output.Get(Props.Global); string basePath = string.IsNullOrEmpty(output) ? gd.Name : output; string baseDir = Path.GetDirectoryName(basePath); string baseName = Path.GetFileNameWithoutExtension(basePath); for (int p = 0; p < st.Length; ++p) { string fileName = Path.Combine(baseDir, string.Format("{0}-{1}.dat", baseName, p)); Console.WriteLine("Eq value pos {0}: {1}, file: {2}", p, values[p], fileName); st[p].Write(fileName); } return(0); }
private void Solve(TestParams testParams, bool visualize, ConfigureSolver configureSolver) { if (visualize) { VisActionTree.Show(testParams.ActionTree, Path.Combine(_outDir, String.Format("{0}-at.gv", testParams.Name))); VisChanceTree.Show(testParams.ChanceTree, Path.Combine(_outDir, String.Format("{0}-ct.gv", testParams.Name))); } StrategyTree [] eqStrategies = new StrategyTree[testParams.ChanceTree.PlayersCount]; string error; for (int heroPos = 0; heroPos < testParams.ChanceTree.PlayersCount; ++heroPos) { // Create and configure EqLp solver EqLp solver = new EqLp { HeroPosition = heroPos, ChanceTree = testParams.ChanceTree, ActionTree = testParams.ActionTree, }; if (configureSolver != null) { configureSolver(solver); } // Solve EqLp solver.Solve(); eqStrategies[heroPos] = solver.Strategy; if (visualize) { VisStrategyTree.Show(solver.Strategy, Path.Combine(_outDir, string.Format("{0}-eq-{1}.gv", testParams.Name, heroPos))); } // Verify the eq value and strategy Assert.AreEqual(testParams.ExpectedResult[heroPos], solver.Value, testParams.Epsilon, "Wrong eq value"); Assert.IsTrue(VerifyAbsStrategy.Verify(solver.Strategy, solver.HeroPosition, 1e-7, out error), error); } // Verify eq, use another (better) epsilon because EqLp and VerifyEq have better precision // than most of the reference game solvers like OCFR. Assert.IsTrue(VerifyEq.Verify(testParams.ActionTree, testParams.ChanceTree, eqStrategies, 1e-7, out error), error); }
/// <summary> /// Solves the game by fictitious play and verifies the solution. /// </summary> /// <param name="snapshotAfter">Number of iterations to make an intermediate snapshot after. -1 for no intermediate snapshot.</param> /// <param name="configureSolver"></param> private void SolveAndVerifyVerifySolution(TestParams testParams, bool visualize, bool trace, int[] iterCounts, ConfigureSolver configureSolver) { int playersCount = testParams.ChanceTree.PlayersCount; StrategyTree eqStrategy = RunSolver(testParams, visualize, trace, iterCounts, configureSolver); string error; // Verify consistency of strategies for (int p = 0; p < 2; ++p) { Assert.IsTrue(VerifyAbsStrategy.Verify(eqStrategy, p, 1e-7, out error), string.Format("Pos {0}: {1}", p, error)); } // Run VerifyEq on the computed strategies. StrategyTree[] strategies = new StrategyTree[] { eqStrategy, eqStrategy }; Assert.IsTrue(VerifyEq.Verify(testParams.ActionTree, testParams.ChanceTree, strategies, 3 * testParams.Epsilon, out error), error); // // Do a redundant test with EqLp // // Find game values for our solution GameValue gv = new GameValue { ActionTree = testParams.ActionTree, ChanceTree = testParams.ChanceTree, Strategies = new StrategyTree[] { eqStrategy, eqStrategy } }; gv.Solve(); // Solve eq with EqLp double[] expEqValues; StrategyTree[] expStrategies = EqLp.Solve(testParams.ActionTree, testParams.ChanceTree, out expEqValues); // Verify the eq value and strategy for (int p = 0; p < 2; ++p) { if (visualize) { Console.WriteLine("Expected eq value pos {0}: {1}", p, expEqValues[p]); } Assert.AreEqual(expEqValues[p], gv.Values[p], testParams.Epsilon, "Eq value differs from EqLp solution"); } }
public void Test_Eq() { GameDefinition gd = XmlSerializerExt.Deserialize <GameDefinition>("kuhn8.gamedef.xml"); ChanceTree ct = CreateChanceTreeByGameDef.Create(gd); VisChanceTree.Show(ct, "kuhn8-ct.gv"); ActionTree at = CreateActionTreeByGameDef.Create(gd); VisActionTree.Show(at, "kuhn8-at.gv"); double[] values; StrategyTree [] strategies = EqLp.Solve(at, ct, out values); Console.WriteLine("Kuhn8 eq values: {0}, {1}", values[0], values[1]); VisStrategyTree.Show(strategies[0], "kuhn8-eq-0.gv"); VisStrategyTree.Show(strategies[1], "kuhn8-eq-1.gv"); // Make strategy for T same as for Q //strategies[0].Nodes[strategies[0].FindNode("0d0 0p0", null)].Probab = 0.5; //strategies[0].Nodes[strategies[0].FindNode("0d0 0p0 1p1 0p1", null)].Probab = 0.5; //strategies[0].Nodes[strategies[0].FindNode("0d0 0p1", null)].Probab = 0.5; // Make strategy for Q same as for T strategies[0].Nodes[strategies[0].FindNode("0d2 0p0", null)].Probab = 0; strategies[0].Nodes[strategies[0].FindNode("0d2 0p0 1p1 0p1", null)].Probab = 0; strategies[0].Nodes[strategies[0].FindNode("0d2 0p1", null)].Probab = 1; VisStrategyTree.Show(strategies[0], "kuhn8-eq-0-adj.gv"); Br br = new Br { ActionTree = at, ChanceTree = ct, HeroPosition = 1 }; br.Strategies = new StrategyTree[] { strategies[0], null }; br.Solve(); StrategyTree br0 = br.Strategies[1]; Console.WriteLine("Br against pos 0: {0}", br.Value); VisStrategyTree.Show(strategies[1], "kuhn8-eq-br-0.gv"); }
void SolveGame(string runDir, GameDefinition gd, IChanceAbstraction [] chanceAbstractions, double [] brValues) { ChanceTree ct = CreateChanceTreeByAbstraction.CreateS(gd, chanceAbstractions); ActionTree at = CreateActionTreeByGameDef.Create(gd); double[] eqValues; StrategyTree[] eqStrategies = EqLp.Solve(at, ct, out eqValues); string error; for (int p = 0; p < gd.MinPlayers; ++p) { Assert.IsTrue(VerifyAbsStrategy.Verify(eqStrategies[p], p, 1e-7, out error), error); } // Verify eq Assert.IsTrue(VerifyEq.Verify(at, ct, eqStrategies, 1e-7, out error), error); StrategyTree[] brStrategies = new StrategyTree[gd.MinPlayers]; // Find BR for each position for (int heroPos = 0; heroPos < gd.MinPlayers; ++heroPos) { Br br = new Br { HeroPosition = heroPos, ActionTree = at, ChanceTree = ct, Strategies = (StrategyTree[])eqStrategies.Clone() }; br.Solve(); brStrategies[heroPos] = br.Strategies[heroPos]; brValues[heroPos] = br.Value; } MergeAndSaveStrategies(runDir, "", eqStrategies, chanceAbstractions); MergeAndSaveStrategies(runDir, "-br", brStrategies, chanceAbstractions); }