Beispiel #1
0
        private void CompareNodes(ChanceTreeNode *pNode0, ChanceTreeNode *pNode1)
        {
            double probab0 = pNode0->Probab;
            double probab1 = pNode1->Probab;

            double probabDiff = Math.Abs(probab0 - probab1);

            SumProbabDiff += probabDiff;
            MaxProbabDiff  = Math.Max(MaxProbabDiff, probabDiff);

            double relProbabDiff = (probab0 + probab1) != 0 ? probabDiff / (probab0 + probab1) / 2 : 0;

            SumRelProbabDiff += relProbabDiff;
            MaxRelProbabDiff  = Math.Max(MaxRelProbabDiff, relProbabDiff);

            UInt16[] activePlayers;
            activePlayers = ActivePlayers.Get(_playersCount, 2, _playersCount);

            double[] potShares0 = new double[_playersCount];
            double[] potShares1 = new double[_playersCount];
            foreach (UInt16 ap in activePlayers)
            {
                pNode0->GetPotShare(ap, potShares0);
                pNode1->GetPotShare(ap, potShares1);

                for (int p = 0; p < _playersCount; ++p)
                {
                    double potShareDiff = Math.Abs(potShares0[p] - potShares1[p]);
                    SumPotShareDiff[p] += potShareDiff;
                    MaxPotShareDiff[p]  = Math.Max(MaxPotShareDiff[p], potShareDiff);
                }
            }
        }
Beispiel #2
0
        public void Test_GetActivePlayers()
        {
            UInt16[] ap;
            // Total: 0
            ap = ActivePlayers.Get(0, 0, 0);
            Assert.AreEqual(1, ap.Length);
            Array.Sort(ap);
            Assert.AreEqual(0, ap[0]);

            // Total: 1
            ap = ActivePlayers.Get(1, 0, 0);
            Assert.AreEqual(1, ap.Length);
            Array.Sort(ap);
            Assert.AreEqual(0, ap[0]);
            ap = ActivePlayers.Get(1, 0, 1);
            Assert.AreEqual(2, ap.Length);
            Array.Sort(ap);
            Assert.AreEqual(0, ap[0]);
            Assert.AreEqual(1, ap[1]);

            // Total: 2
            ap = ActivePlayers.Get(2, 0, 0);
            Assert.AreEqual(1, ap.Length);
            Array.Sort(ap);
            Assert.AreEqual(0, ap[0]);

            ap = ActivePlayers.Get(2, 0, 1);
            Assert.AreEqual(3, ap.Length);
            Array.Sort(ap);
            Assert.AreEqual(0, ap[0]);
            Assert.AreEqual(1, ap[1]);
            Assert.AreEqual(2, ap[2]);

            ap = ActivePlayers.Get(2, 1, 1);
            Assert.AreEqual(2, ap.Length);
            Array.Sort(ap);
            Assert.AreEqual(1, ap[0]);
            Assert.AreEqual(2, ap[1]);

            ap = ActivePlayers.Get(2, 0, 2);
            Assert.AreEqual(4, ap.Length);
            Array.Sort(ap);
            Assert.AreEqual(0, ap[0]);
            Assert.AreEqual(1, ap[1]);
            Assert.AreEqual(2, ap[2]);
            Assert.AreEqual(3, ap[3]);

            // Total: 3
            ap = ActivePlayers.Get(3, 2, 2);
            Assert.AreEqual(3, ap.Length);
            Array.Sort(ap);
            Assert.AreEqual(3, ap[0]);
            Assert.AreEqual(5, ap[1]);
            Assert.AreEqual(6, ap[2]);

            ap = ActivePlayers.Get(3, 3, 3);
            Assert.AreEqual(1, ap.Length);
            Array.Sort(ap);
            Assert.AreEqual(7, ap[0]);
        }
        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);
                    }
                }
            }
        }
        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));
                }
            }
        }
        public static ChanceTree FromTxt(TextReader r)
        {
            int ln = 0;
            int serializationFormat = int.Parse(TextDumpHelper.ReadTag(r, ref ln, "SeralizationFormat"));

            if (serializationFormat > SERIALIZATION_FORMAT)
            {
                throw new ApplicationException(String.Format("Line {0}: serialization format {1} is not supported by this version, max supported {2}",
                                                             ln, serializationFormat, SERIALIZATION_FORMAT));
            }
            string value;

            value = TextDumpHelper.ReadTag(r, ref ln, "Version");

            StringReader sr = new StringReader(value);
            BdsVersion   v;

            XmlSerializerExt.Deserialize(out v, sr);
            Int64      nodesCount  = Int64.Parse(TextDumpHelper.ReadTag(r, ref ln, "NodesCount"));
            int        roundsCount = int.Parse(TextDumpHelper.ReadTag(r, ref ln, "RoundsCount"));
            ChanceTree t           = new ChanceTree(nodesCount);

            t.SetNodesMemory(0); // Clear memory to ensure zeros at unused fields
            t.Version.CopyFrom(v);

            char [] separators = new char[] { ' ', '\t' };
            for (Int64 n = 0; n < nodesCount; ++n)
            {
                Int64 id = Int64.Parse(TextDumpHelper.ReadTag(r, ref ln, "Id"));
                if (id != n)
                {
                    throw new ApplicationException(String.Format("Line {0}: wrong node id '{1}', expected '{2}'", ln, id, n));
                }
                byte depth = byte.Parse(TextDumpHelper.ReadTag(r, ref ln, "D"));
                t.SetDepth(n, depth);
                t.Nodes[n].Position = int.Parse(TextDumpHelper.ReadTag(r, ref ln, "P"));
                t.Nodes[n].Card     = int.Parse(TextDumpHelper.ReadTag(r, ref ln, "C"));
                t.Nodes[n].Probab   = TextDumpHelper.BinStringToDouble(TextDumpHelper.ReadTag(r, ref ln, "Pr"));
                if (depth == t.PlayersCount * roundsCount)
                {
                    double[] potShare          = new double[t.PlayersCount];
                    UInt16[] activePlayerMasks = ActivePlayers.Get(t.PlayersCount, 2, t.PlayersCount);
                    for (int a = 0; a < activePlayerMasks.Length; ++a)
                    {
                        value = TextDumpHelper.ReadTag(r, ref ln, "Ps");
                        string[] parts = value.Split(separators, StringSplitOptions.RemoveEmptyEntries);
                        if (parts.Length != t.PlayersCount + 1)
                        {
                            throw new ApplicationException(
                                      String.Format("Line {0}: wrong number of values: '{1}', expected '{2}'", ln,
                                                    parts.Length, t.PlayersCount + 1));
                        }
                        UInt16 activePlayers = UInt16.Parse(parts[0], NumberStyles.AllowHexSpecifier);
                        for (int i = 1; i < parts.Length; ++i)
                        {
                            potShare[i - 1] = TextDumpHelper.BinStringToDouble(parts[i]);
                        }
                        t.Nodes[n].SetPotShare(activePlayers, potShare);
                    }
                }
            }
            return(t);
        }
        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();
            }
        }