public void Test_Convert() { GameDefinition gd = XmlSerializerExt.Deserialize <GameDefinition>( Props.Global.Expand("${bds.DataDir}ai.pkr.metastrategy/leduc-he.gamedef.xml")); string testDir = UTHelper.GetTestResourceDir(Assembly.GetExecutingAssembly()); ChanceTree ct1 = CreateChanceTreeByGameDef.Create(gd); // DumpChanceTree.ToTxt(ct1, Console.Out); MemoryStream ms = new MemoryStream(); using (TextWriter tw = new StreamWriter(ms)) { DumpChanceTree.ToTxt(ct1, tw); } byte[] buf = ms.ToArray(); ms = new MemoryStream(buf); ChanceTree ct2; using (TextReader tr = new StreamReader(ms)) { ct2 = DumpChanceTree.FromTxt(tr); } Assert.AreEqual(ct1.Version, ct2.Version); Assert.AreEqual(ct1.NodesCount, ct2.NodesCount); int roundsCount = ct1.CalculateRoundsCount(); double[] potShare1 = new double[ct1.PlayersCount]; double[] potShare2 = new double[ct1.PlayersCount]; for (Int64 n = 0; n < ct2.NodesCount; ++n) { Assert.AreEqual(ct1.GetDepth(n), ct2.GetDepth(n)); Assert.AreEqual(ct1.Nodes[n].Position, ct2.Nodes[n].Position); Assert.AreEqual(ct1.Nodes[n].Card, ct2.Nodes[n].Card); Assert.AreEqual(ct1.Nodes[n].Probab, ct2.Nodes[n].Probab); if (ct1.GetDepth(n) == ct1.PlayersCount * roundsCount) { UInt16 [] activePlayerMasks = ActivePlayers.Get(ct1.PlayersCount, 2, ct1.PlayersCount); foreach (UInt16 ap in activePlayerMasks) { ct1.Nodes[n].GetPotShare(ap, potShare1); ct2.Nodes[n].GetPotShare(ap, potShare2); Assert.AreEqual(potShare1, potShare2); } } } }
private void PrepareHero() { _maxCard = new int[PLAYERS_COUNT][]; _chanceIndexSizes = new int[PLAYERS_COUNT][]; _heroVarsInLeaves = new int[ActionTree.NodesCount][]; _roundsCount = ChanceTree.CalculateRoundsCount(); for (int p = 0; p < PLAYERS_COUNT; ++p) { _maxCard[p] = new int[_roundsCount].Fill(int.MinValue); _chanceIndexSizes[p] = new int[_roundsCount].Fill(int.MinValue); } for (Int64 n = 1; n < ChanceTree.NodesCount; ++n) { int round = (ChanceTree.GetDepth(n) - 1) / PLAYERS_COUNT; if (_maxCard[ChanceTree.Nodes[n].Position][round] < ChanceTree.Nodes[n].Card) { _maxCard[ChanceTree.Nodes[n].Position][round] = ChanceTree.Nodes[n].Card; } } for (int p = 0; p < PLAYERS_COUNT; ++p) { _chanceIndexSizes[p][0] = _maxCard[p][0] + 1; for (int r = 1; r < _roundsCount; ++r) { _chanceIndexSizes[p][r] = _chanceIndexSizes[p][r - 1] * (_maxCard[p][r] + 1); } } _actionTreeIndex = new UFTreeChildrenIndex(ActionTree); for (Int64 n = 1; n < ActionTree.NodesCount; ++n) { if (_actionTreeIndex.GetChildrenCount(n) == 0) { // This is a leaf int round = ActionTree.Nodes[n].Round; _heroVarsInLeaves[n] = new int[_chanceIndexSizes[HeroPosition][round]].Fill(-1); } } // Create hero variables WalkUFTreePP <StrategyTree, PrepareHeroVarsContext> wt = new WalkUFTreePP <StrategyTree, PrepareHeroVarsContext>(); wt.OnNodeBegin = PrepareHero_OnNodeBegin; wt.Walk(Strategy, PLAYERS_COUNT); }
public static void ToTxt(ChanceTree t, TextWriter w) { int roundsCount = t.CalculateRoundsCount(); if (t.PlayersCount != 2) { throw new ApplicationException("Only 2 players are supported"); } w.WriteLine("SeralizationFormat {0}", SERIALIZATION_FORMAT); XmlWriterSettings s = new XmlWriterSettings { Indent = false, NewLineChars = "" }; w.Write("Version "); XmlSerializerExt.Serialize(t.Version, w, s); w.WriteLine(); w.WriteLine("NodesCount {0}", t.NodesCount); w.WriteLine("RoundsCount {0}", roundsCount); double [] potShare = new double[t.PlayersCount]; for (Int64 n = 0; n < t.NodesCount; ++n) { w.WriteLine("Id {0}", n); byte depth = t.GetDepth(n); w.WriteLine("D {0}", depth); w.WriteLine("P {0}", t.Nodes[n].Position); w.WriteLine("C {0}", t.Nodes[n].Card); w.WriteLine("Pr {0}", TextDumpHelper.DoubleToBinString(t.Nodes[n].Probab)); if (depth == roundsCount * t.PlayersCount) { UInt16 [] activePlayerMasks = ActivePlayers.Get(t.PlayersCount, 2, t.PlayersCount); foreach (UInt16 ap in activePlayerMasks) { t.Nodes[n].GetPotShare(ap, potShare); w.Write("Ps {0:X}", ap); foreach (double ps in potShare) { w.Write(" {0}", TextDumpHelper.DoubleToBinString(ps)); } w.WriteLine(); } } } }
public void Test_Kuhn() { GameDefinition gd = XmlSerializerExt.Deserialize <GameDefinition>( Props.Global.Expand("${bds.DataDir}ai.pkr.metastrategy/kuhn.gamedef.xml")); IChanceAbstraction[] abstractions = new IChanceAbstraction [] { new KuhnChanceAbstraction(), new KuhnChanceAbstraction() }; ChanceTree ct = CreateChanceTreeByGameDef.Create(gd); ChanceTree act = CreateChanceTreeByAbstraction.CreateS(gd, abstractions); VerifyChanceTree.VerifyS(act); VisChanceTree.Show(act, Path.Combine(_outDir, gd.Name + "-abct.gv")); UInt16[] activePlayersOne = ActivePlayers.Get(gd.MinPlayers, 1, 1); UInt16[] activePlayersAll = ActivePlayers.Get(gd.MinPlayers, 1, gd.MinPlayers); int maxDepth = gd.RoundsCount * gd.MinPlayers; Assert.AreEqual(act.PlayersCount, gd.MinPlayers); Assert.AreEqual(ct.NodesCount, act.NodesCount); double[] expPotShares = new double[gd.MinPlayers]; double[] actPotShares = new double[gd.MinPlayers]; for (int i = 0; i < ct.NodesCount; ++i) { Assert.AreEqual(ct.Nodes[i].Position, act.Nodes[i].Position); Assert.AreEqual(ct.Nodes[i].Card, act.Nodes[i].Card); // Kuhn abstraction has the same card Assert.AreEqual(ct.Nodes[i].Probab, act.Nodes[i].Probab); if (i == 0) { continue; } UInt16[] activePlayers = ct.GetDepth(i) == maxDepth ? activePlayersAll : activePlayersOne; foreach (UInt16 ap in activePlayers) { ct.Nodes[i].GetPotShare(ap, expPotShares); act.Nodes[i].GetPotShare(ap, actPotShares); Assert.AreEqual(expPotShares, actPotShares, String.Format("Node: {0}, ap: {1}", i, ap)); } } }
private void Prepare() { _playersCount = Strategies.Length; _maxCard = new int[_playersCount][]; _spArrayLengths = new int[_playersCount][]; _spArrays = new double[_playersCount][][].Fill(i => new double[ActionTree.NodesCount][]); if (PrepareVis) { _visLeaveValues = new double[_playersCount][][].Fill(i => new double[ActionTree.NodesCount][]); } _gameValues = new double[_playersCount]; _roundsCount = ChanceTree.CalculateRoundsCount(); for (int p = 0; p < _playersCount; ++p) { _maxCard[p] = new int[_roundsCount].Fill(int.MinValue); _spArrayLengths[p] = new int[_roundsCount].Fill(int.MinValue); } for (Int64 n = 1; n < ChanceTree.NodesCount; ++n) { int round = (ChanceTree.GetDepth(n) - 1) / _playersCount; if (_maxCard[ChanceTree.Nodes[n].Position][round] < ChanceTree.Nodes[n].Card) { _maxCard[ChanceTree.Nodes[n].Position][round] = ChanceTree.Nodes[n].Card; } } for (int p = 0; p < _playersCount; ++p) { _spArrayLengths[p][0] = _maxCard[p][0] + 1; for (int r = 1; r < _roundsCount; ++r) { _spArrayLengths[p][r] = _spArrayLengths[p][r - 1] * (_maxCard[p][r] + 1); } } _actionTreeIndex = new UFTreeChildrenIndex(ActionTree); for (Int64 n = 1; n < ActionTree.NodesCount; ++n) { if (_actionTreeIndex.GetChildrenCount(n) == 0) { // This is a leaf int round = ActionTree.Nodes[n].Round; for (int p = 0; p < _playersCount; ++p) { _spArrays[p][n] = new double[_spArrayLengths[p][round]]; if (PrepareVis) { _visLeaveValues[p][n] = new double[_spArrayLengths[p][round]]; } } } } for (_curPlayer = 0; _curPlayer < _playersCount; ++_curPlayer) { WalkUFTreePP <StrategyTree, PrepareContext> wt = new WalkUFTreePP <StrategyTree, PrepareContext>(); wt.OnNodeBegin = Prepare_OnNodeBegin; wt.Walk(Strategies[_curPlayer]); } }
private void OnNodeBegin(ChanceTree tree, AnalyzeContext[] stack, int depth) { AnalyzeContext context = stack[depth]; Int64 n = context.NodeIdx; int card = tree.Nodes[n].Card; if (depth > 0) { int round = (depth - 1) / _playersCount; int pos = tree.Nodes[n].Position; if (_seenCards[round][pos].Length <= card) { Array.Resize(ref _seenCards[round][pos], card + 1); } _seenCards[round][pos][card] = true; } bool isLeaf = tree.GetDepth(n) == _maxDepth; if (!isLeaf) { return; } LeavesCount++; bool isZeroNode = false; double probab = tree.Nodes[n].Probab; if (probab == 0) { ZeroChanceLeavesCount++; isZeroNode = true; } UInt16[] activePlayers = ActivePlayers.Get(_playersCount, 2, _playersCount); double[] potShares = new double[_playersCount]; double totalPotShare = 0; foreach (UInt16 ap in activePlayers) { tree.Nodes[n].GetPotShare(ap, potShares); for (int p = 0; p < _playersCount; ++p) { SumPotShares[p] += potShares[p]; totalPotShare += potShares[p]; } } if (probab > 0 && totalPotShare == 0) { ZeroPotSharesCount++; isZeroNode = true; } if (isZeroNode && _zeroNodesLog != null) { _zeroNodesLog.Write("Node: {0,10} probab: {1:0.0000}, total pot share: {2:0.0000} ", n, probab, totalPotShare); for (int i = 1; i <= depth; ++i) { _zeroNodesLog.Write("{0} ", tree.Nodes[stack[i].NodeIdx].ToStrategicString(null)); } _zeroNodesLog.WriteLine(); } }
private void Prepare() { CreateHeroStrategy(); _playersCount = Strategies.Length; _maxCard = new int[_playersCount][]; _chanceIndexSizes = new int[_playersCount][]; _strategicProbabs = new double[_playersCount][][].Fill(i => new double[ActionTree.NodesCount][]); if (PrepareVis) { _visGameValues = new double[Strategies[HeroPosition].NodesCount]; } else { _visGameValues = null; } _roundsCount = ChanceTree.CalculateRoundsCount(); for (int p = 0; p < _playersCount; ++p) { _maxCard[p] = new int[_roundsCount].Fill(int.MinValue); _chanceIndexSizes[p] = new int[_roundsCount].Fill(int.MinValue); } for (Int64 n = 1; n < ChanceTree.NodesCount; ++n) { int round = (ChanceTree.GetDepth(n) - 1) / _playersCount; if (_maxCard[ChanceTree.Nodes[n].Position][round] < ChanceTree.Nodes[n].Card) { _maxCard[ChanceTree.Nodes[n].Position][round] = ChanceTree.Nodes[n].Card; } } for (int p = 0; p < _playersCount; ++p) { _chanceIndexSizes[p][0] = _maxCard[p][0] + 1; for (int r = 1; r < _roundsCount; ++r) { _chanceIndexSizes[p][r] = _chanceIndexSizes[p][r - 1] * (_maxCard[p][r] + 1); } } _actionTreeIndex = new UFTreeChildrenIndex(ActionTree); for (Int64 n = 1; n < ActionTree.NodesCount; ++n) { if (_actionTreeIndex.GetChildrenCount(n) == 0) { // This is a leaf int round = ActionTree.Nodes[n].Round; for (int p = 0; p < _playersCount; ++p) { if (p != HeroPosition) { _strategicProbabs[p][n] = new double[_chanceIndexSizes[p][round]]; } } } } // Fill strategic probability for each player except the hero. for (_curPlayer = 0; _curPlayer < _playersCount; ++_curPlayer) { if (_curPlayer == HeroPosition) { continue; } WalkUFTreePP <StrategyTree, PrepareStrategicProbabsContext> wt = new WalkUFTreePP <StrategyTree, PrepareStrategicProbabsContext>(); wt.OnNodeBegin = PrepareStrategicProbabs_OnNodeBegin; wt.Walk(Strategies[_curPlayer]); } _chanceTreeNodes = new int[_roundsCount][][]; for (int r = 0; r < _roundsCount; ++r) { int oppChanceIndexSize = 1; for (int p = 0; p < _playersCount; ++p) { if (p == HeroPosition) { continue; } oppChanceIndexSize *= _chanceIndexSizes[p][r]; } int size = _chanceIndexSizes[HeroPosition][r]; _chanceTreeNodes[r] = new int[size][]; for (int i = 0; i < size; ++i) { _chanceTreeNodes[r][i] = new int[oppChanceIndexSize]; } } WalkUFTreePP <ChanceTree, PrepareChanceIndexContext> wt1 = new WalkUFTreePP <ChanceTree, PrepareChanceIndexContext>(); wt1.OnNodeBegin = PrepareChanceIndex_OnNodeBegin; wt1.Walk(ChanceTree); }