protected override void OnTreeBeginFunc(XmlDocument tree, XmlElement root) { int nodesCount = tree.SelectNodes("//*").Count; StrategyTree = new StrategyTree(nodesCount); _nodeId = 0; }
bool CompareNodes(StrategyTree t0, StrategyTree t1, Int64 n) { if (t0.Nodes[n].Position != t1.Nodes[n].Position) { ReportError(n, string.Format("position mismatch: t0:{0} != t1:{1}", t0.Nodes[n].Position, t1.Nodes[n].Position)); } if (n == 0) { return(true); } if (t0.Nodes[n].IsDealerAction != t1.Nodes[n].IsDealerAction) { ReportError(n, "action kind mismatch"); } if (t0.Nodes[n].IsDealerAction) { if (t0.Nodes[n].Card != t1.Nodes[n].Card) { ReportError(n, string.Format("card mismatch: t0:{0} != t1:{1}", t0.Nodes[n].Card, t1.Nodes[n].Card)); } return(true); } if (t0.Nodes[n].Amount != t1.Nodes[n].Amount) { ReportError(n, string.Format("amount mismatch: t0:{0} != t1:{1}", t0.Nodes[n].Amount, t1.Nodes[n].Amount)); } int p = t0.Nodes[n].Position; double probabDiff = Math.Abs(t0.Nodes[n].Probab - t1.Nodes[n].Probab); SumProbabDiff[p] += probabDiff; MaxProbabDiff[p] = Math.Max(probabDiff, MaxProbabDiff[p]); PlayerNodesCount[p]++; return(true); }
public static void ToTxt(StrategyTree t, TextWriter w) { 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); for (Int64 n = 0; n < t.NodesCount; ++n) { w.WriteLine("Id {0}", n); w.WriteLine("D {0}", t.GetDepth(n)); w.WriteLine("P {0}", t.Nodes[n].Position); if (t.Nodes[n].IsDealerAction) { w.WriteLine("C {0}", t.Nodes[n].Card); } else { w.WriteLine("A {0}", TextDumpHelper.DoubleToBinString(t.Nodes[n].Amount)); w.WriteLine("Pr {0}", TextDumpHelper.DoubleToBinString(t.Nodes[n].Probab)); } } }
void PrepareHero_OnNodeBegin(StrategyTree tree, PrepareHeroVarsContext[] stack, int depth) { PrepareHeroVarsContext context = stack[depth]; Int64 n = context.NodeIdx; if (depth == PLAYERS_COUNT) { // Skip blinds context.ActionTreeIdx = PLAYERS_COUNT; } else { context.ActionTreeIdx = stack[depth - 1].ActionTreeIdx; context.Round = stack[depth - 1].Round; context.ChanceIdx = stack[depth - 1].ChanceIdx; context.VarH = stack[depth - 1].VarH; context.EqConstr = null; if (tree.Nodes[n].IsDealerAction) { context.Round++; context.ChanceIdx += CalculateChanceOffset(context.Round, HeroPosition) * tree.Nodes[n].Card; } else { context.ActionTreeIdx = FindActionTreeNodeIdx(tree, n, context.ActionTreeIdx, stack[depth - 1].ChildrenCount - 1); if (tree.Nodes[n].IsPlayerAction(HeroPosition)) { Constraint constr = stack[depth - 1].EqConstr; if (stack[depth - 1].EqConstr == null) { // Create new constraint constr = new Constraint(); stack[depth - 1].EqConstr = constr; _constraintsEQ.Add(constr); if (context.VarH == -1) { // This is the very first move of the hero in this tree branch, // add constraint Sum(h_child) = 1 constr.RightHandSide = 1; } else { // Add constraint h_prev_move = Sum(h_child) constr.RightHandSide = 0; constr.AddVariable(stack[depth - 1].VarH, -1); } } context.VarH = _variables.Add("h", (int)n); constr.AddVariable(context.VarH, 1); } if (_actionTreeIndex.GetChildrenCount(context.ActionTreeIdx) == 0) { // A leaf. _heroVarsInLeaves[context.ActionTreeIdx][context.ChanceIdx] = context.VarH; } } } }
void CalculateBr_OnNodeBegin(StrategyTree tree, CalculateBrContext[] stack, int depth) { CalculateBrContext context = stack[depth]; Int64 n = context.NodeIdx; if (depth > 0) { context.IsBr = stack[depth - 1].IsBr; } if (tree.Nodes[n].IsPlayerAction(HeroPosition)) { // Hero made a move Int64 pn = stack[depth - 1].NodeIdx; if (tree.Nodes[n].Probab == tree.Nodes[pn].Probab && context.IsBr) { tree.Nodes[n].Probab = 1; tree.Nodes[pn].Probab = double.MinValue; context.IsBr = true; } else { context.IsBr = false; tree.Nodes[n].Probab = 0; } } }
public static void ToTxt(StrategyTree t, string fileName) { using (TextWriter w = new StreamWriter(File.Open(fileName, FileMode.Create, FileAccess.Write, FileShare.Write))) { ToTxt(t, w); } }
void CalculateValues_OnNodeBegin(StrategyTree tree, CalculateValuesContext[] stack, int depth) { CalculateValuesContext context = stack[depth]; Int64 n = context.NodeIdx; // We'll use the probability to store game values temporarily. // Initialize with an unique value works both for summing and maximization. tree.Nodes[n].Probab = double.MinValue; if (depth == 0) { context.ActionTreeIdx = 0; context.State = new StrategicState(_playersCount); } else { context.ActionTreeIdx = stack[depth - 1].ActionTreeIdx; context.Round = stack[depth - 1].Round; context.HeroChanceIdx = stack[depth - 1].HeroChanceIdx; if (tree.Nodes[n].IsDealerAction) { context.Round++; context.HeroChanceIdx += CalculateChanceOffset(context.Round, HeroPosition) * tree.Nodes[n].Card; context.State = stack[depth - 1].State; } else { context.ActionTreeIdx = FindActionTreeNodeIdx(tree, n, context.ActionTreeIdx, stack[depth - 1].ChildrenCount - 1); context.State = stack[depth - 1].State.GetNextState(ActionTree.Nodes[context.ActionTreeIdx]); } } }
/// <summary> /// Copies data from src to dst. /// Returns true if everything is OK. If something went wrong, an exception is thrown. /// </summary> public static void Merge(StrategyTree dst, StrategyTree src, int pos) { Comparer comparer = new Comparer(); comparer.Position = pos; if (comparer.Compare(dst, src, comparer.CopyNode)) { return; } string message; switch (comparer.Result) { case ICompareUFTreesDefs.ResultKind.StructureDiffers: message = string.Format("Strategies have different structures at node: {0}", comparer.DiffersAt); break; case ICompareUFTreesDefs.ResultKind.ValueDiffers: message = string.Format("Position or node type mismatch at node: {0}", comparer.DiffersAt); break; default: message = string.Format("Unknown error at node: {0}", comparer.DiffersAt); break; } throw new ApplicationException(message); }
protected override void CustomizeNodeAttributes(UFToUniAdapter aTree, int n, List <Context> stack, int depth, NodeAttributeMap attr) { Context context = stack[depth]; StrategyTree tree = (StrategyTree)aTree.UfTree; base.CustomizeNodeAttributes(aTree, n, stack, depth, attr); string nodeLabel = attr.label; nodeLabel += string.Format("\\ngv:{0:0.000}", Solver._ptExt[Position][n].GameValue); if (!tree.Nodes[n].IsDealerAction && n > 0) { nodeLabel += string.Format("\\ns:{0:0.0000}", tree.Nodes[n].Probab); } if (tree.Nodes[n].IsDealerAction) { nodeLabel += string.Format("\\nc:{0}", tree.Nodes[n].Card); } if (context.IsLeaf) { nodeLabel += string.Format("\\npf:{0:0.0000}", Solver._ptExt[Position][n].PotFactor); nodeLabel += string.Format("\\nati:{0}", Solver._ptExt[Position][n].AtIdx); } if (n == 0) { nodeLabel += string.Format("\\nGV:{0:0.000}", Solver.LastBrValues[Position]); } attr.label = nodeLabel; }
/// <summary> /// Sets fields of the context. Override to customize view or call it in an overriden OnNodeBegin. /// </summary> protected virtual void SetContext(UFToUniAdapter aTree, int aNode, List <ContextT> stack, int depth) { ContextT context = stack[depth]; StrategyTree tree = (StrategyTree)(aTree.UfTree); context.Tree = tree; if (depth == 0) { context.Round = -1; } else { context.Round = stack[depth - 1].Round; } // Deal action => new round. if (tree.Nodes[aNode].IsDealerAction) { context.Round++; } context.Id = aNode.ToString(); context.IsDealerAction = tree.Nodes[aNode].IsDealerAction; context.Position = tree.Nodes[aNode].Position; context.Probab = tree.Nodes[aNode].IsDealerAction ? 0 : tree.Nodes[aNode].Probab; context.ActionLabel = depth == 0 ? "" : tree.Nodes[aNode].ToStrategicString(CardNames); }
double [,] FlattenStrategy(StrategyTree st, int pos, int cardCount, Dictionary <string, int> actionLabelToId) { double[,] result = new double[cardCount, actionLabelToId.Count]; var wt = new WalkUFTreePP <StrategyTree, FlattenStrategyContext>(); wt.OnNodeBegin = (t, s, d) => { Int64 n = s[d].NodeIdx; if (d > 0) { s[d].ActionLabel = s[d - 1].ActionLabel; s[d].Probab = s[d - 1].Probab; s[d].Card = s[d - 1].Card; if (t.Nodes[n].IsDealerAction) { s[d].Card = t.Nodes[n].Card; } else if (d > 2) // Skip blinds { s[d].ActionLabel = s[d].ActionLabel + "/" + String.Format("{0}p{1}", t.Nodes[n].Position, t.Nodes[n].Amount); if (t.Nodes[n].IsPlayerAction(pos)) { s[d].Probab = t.Nodes[n].Probab; double pr = s[d - 1].Probab == 0 ? 0 : s[d].Probab / s[d - 1].Probab; result[s[d].Card, actionLabelToId[s[d].ActionLabel]] = pr; } } } }; wt.Walk(st); return(result); }
/// <summary> /// Compares trees verbose. /// </summary> public static void CompareS(StrategyTree st0, StrategyTree st1) { CompareStrategyTrees comparer = new CompareStrategyTrees { IsVerbose = true }; comparer.Compare(st0, st1); }
protected override void OnTreeBeginFunc(UFToUniAdapter aTree, int aRoot) { StrategyTree tree = (StrategyTree)(aTree.UfTree); GraphAttributes.label = tree.Version.Description; GraphAttributes.fontsize = 20; base.OnTreeBeginFunc(aTree, aRoot); }
/// <summary> /// Runs the analysis in verbose mode. /// </summary> public static void AnalyzeS(StrategyTree st, bool isAbsolute, int position) { AnalyzeStrategyTree analyzer = new AnalyzeStrategyTree { IsVerbose = true, StrategyTree = st, IsAbsolute = isAbsolute, HeroPosition = position }; analyzer.Analyze(); }
public static StrategyTree CreateStrategyTree(GameDefinition gd, int pos) { ChanceTree ct = CreateChanceTreeByGameDef.Create(gd); ChanceTree pct = ExtractPlayerChanceTree.ExtractS(ct, 0); ActionTree at = CreateActionTreeByGameDef.Create(gd); StrategyTree st = CreateStrategyTreeByChanceAndActionTrees.CreateS(pct, at); return(st); }
void CalculateBr_OnNodeEnd(StrategyTree tree, CalculateBrContext[] stack, int depth) { CalculateBrContext context = stack[depth]; Int64 n = context.NodeIdx; if (tree.Nodes[n].IsDealerAction || tree.Nodes[n].Position != HeroPosition) { tree.Nodes[n].Probab = 0; } }
public static void Show(StrategyTree t, string fileName) { using (TextWriter w = new StreamWriter(File.Open(fileName, FileMode.Create))) { VisStrategyTree <VisStrategyTreeContext> vis = new VisStrategyTree <VisStrategyTreeContext> { Output = w }; vis.Show(t); } }
/// <summary> /// Runs FictitiousPlay with the specified parameters. /// Some parameters are set by default (e.g. verbosity), the caller has a chance to overwrite them /// using Configure delegate. /// </summary> public StrategyTree[] Solve(ActionTree at, ChanceTree ct) { int playersCount = 2; DirectoryExt.Delete(BaseDir); Directory.CreateDirectory(BaseDir); string inputDir = Path.Combine(BaseDir, "input"); Directory.CreateDirectory(inputDir); string traceDir = Path.Combine(BaseDir, "trace"); string chanceTreeFile = Path.Combine(inputDir, "ct.dat"); string actionTreeFile = Path.Combine(inputDir, "at.dat"); ct.Write(chanceTreeFile); at.Write(actionTreeFile); if (VisualizeTrees) { VisActionTree.Show(at, actionTreeFile + ".gv"); VisChanceTree.Show(ct, chanceTreeFile + ".gv"); } Solver.ChanceTreeFile = chanceTreeFile; Solver.EqualCa = false; Solver.ActionTreeFile = actionTreeFile; Solver.OutputPath = BaseDir; Solver.SnapshotsCount = 2; Solver.Epsilon = Epsilon; Solver.ThreadsCount = 6; Solver.IsVerbose = true; Solver.IterationVerbosity = 10000; Solver.MaxIterationCount = 1000000000; if (Configure != null) { Configure(Solver); } Solver.Solve(); StrategyTree[] eqStrategies = new StrategyTree[playersCount]; for (int p = 0; p < playersCount; ++p) { string fileName = Solver.CurrentSnapshotInfo.StrategyFile[p]; eqStrategies[p] = StrategyTree.Read <StrategyTree>(fileName); if (VisualizeTrees) { VisStrategyTree.Show(eqStrategies[p], fileName + ".gv"); } } return(eqStrategies); }
public void Test_FindNode() { GameDefinition gd = XmlSerializerExt.Deserialize <GameDefinition>( Props.Global.Expand("${bds.DataDir}ai.pkr.metastrategy/kuhn.gamedef.xml")); StrategyTree st = TreeHelper.CreateStrategyTree(gd, 0); Assert.AreEqual(3, st.FindNode("0dJ", gd.DeckDescr)); Assert.AreEqual(11, st.FindNode("0dJ 0p1 1p1", gd.DeckDescr)); Assert.AreEqual(13, st.FindNode("0dQ 0p0", gd.DeckDescr)); Assert.AreEqual(16, st.FindNode("0d1 0p0 1p1 0p0", null)); }
private uint FindActionTreeNodeIdx(StrategyTree tree, long sNodeIdx, long aNodeIdx, int hintChildIdx) { long actionTreeIdx = _at.FindChildByAmount(aNodeIdx, tree.Nodes[sNodeIdx].Amount, _init.AtChildrenIndex, hintChildIdx); if (actionTreeIdx == -1) { throw new ApplicationException(String.Format("Cannot find action tree node, strategy node {0}", sNodeIdx)); } return((uint)actionTreeIdx); }
protected override void CustomizeEdgeAttributes(UFToUniAdapter aTree, int n, int pn, List <Context> stack, int depth, Vis.EdgeAttributeMap attr) { base.CustomizeEdgeAttributes(aTree, n, pn, stack, depth, attr); StrategyTree tree = (StrategyTree)aTree.UfTree; if (!tree.Nodes[n].IsDealerAction && tree.Nodes[n].Position == Solver.HeroPosition && tree.Nodes[n].Probab == 1.0) { // Hero have chosen this edge - show thick attr.penwidth = 3.0; } }
public static void Show(GameValue solver, int position, string fileName) { StrategyTree t = solver.Strategies[position]; using (TextWriter w = new StreamWriter(File.Open(fileName, FileMode.Create))) { Vis vis = new Vis { Output = w, Solver = solver, Position = position }; vis.Show(t); } }
protected override void OnNodeEndFunc(UFToUniAdapter aTree, int aNode, List <Vis.Context> stack, int depth) { Context context = stack[depth]; StrategyTree tree = (StrategyTree)aTree.UfTree; if (depth > 0) { stack[depth - 1].Value += context.Value; } base.OnNodeEndFunc(aTree, aNode, stack, depth); }
public void Test_LeducHe() { GameDefinition gd = XmlSerializerExt.Deserialize <GameDefinition>( Props.Global.Expand("${bds.DataDir}ai.pkr.metastrategy/leduc-he.gamedef.xml")); for (int pos = 0; pos < gd.MinPlayers; ++pos) { StrategyTree st = TreeHelper.CreateStrategyTree(gd, pos); Assert.AreEqual(st.PlayersCount, gd.MinPlayers); Assert.AreEqual(723, st.NodesCount); } }
public static void Show(Br solver, string fileName) { StrategyTree t = solver.Strategies[solver.HeroPosition]; using (TextWriter w = new StreamWriter(File.Open(fileName, FileMode.Create))) { Vis vis = new Vis { Output = w, Solver = solver }; vis.Show(t); } }
public virtual string GetCardAttribute(UFToUniAdapter t, List <XmlizeTreeContext <int, int> > s, int d) { StrategyTree st = (StrategyTree)t.UfTree; if (!st.Nodes[s[d].Node].IsDealerAction) { return(""); } int card = st.Nodes[s[d].Node].Card; string cardText = DeckDescr != null ? DeckDescr.CardNames[card] : card.ToString(); return(cardText); }
protected override void CustomizeNodeAttributes(UFToUniAdapter aTree, int n, List <Context> stack, int depth, Vis.NodeAttributeMap attr) { base.CustomizeNodeAttributes(aTree, n, stack, depth, attr); StrategyTree tree = (StrategyTree)aTree.UfTree; if (!tree.Nodes[n].IsDealerAction && tree.Nodes[n].Position == Solver.HeroPosition && tree.Nodes[n].Probab != 1.0) { if (IsHtmlColor(attr.fillcolor)) { attr.fillcolor = GradientHtmlColor(attr.fillcolor, Color.FromArgb(255, 200, 200, 200), 0.4); } } }
private long FindActionTreeNodeIdx(StrategyTree tree, long sNodeIdx, long aNodeIdx, int hintChildIdx) { long actionTreeIdx = ActionTree.FindChildByAmount(aNodeIdx, tree.Nodes[sNodeIdx].Amount, _actionTreeIndex, hintChildIdx); if (actionTreeIdx == -1) { throw new ApplicationException( String.Format("Cannot find action tree node for player {0}, strategy node {1}", _curPlayer, sNodeIdx)); } return(actionTreeIdx); }
protected override bool OnNodeBeginFunc(UFToUniAdapter aTree, int n, List <Context> stack, int depth) { Context context = stack[depth]; StrategyTree tree = (StrategyTree)aTree.UfTree; // Set default vis-fields SetContext(aTree, n, stack, depth); if (Solver._visGameValues != null) { context.Value = Solver._visGameValues[n]; } return(base.OnNodeBeginFunc(aTree, n, stack, depth)); }
public static StrategyTree 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 tag, 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")); StrategyTree t = new StrategyTree(nodesCount); t.SetNodesMemory(0); // Clear memory to ensure zeros at probability for dealer. t.Version.CopyFrom(v); 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)); } t.SetDepth(n, byte.Parse(TextDumpHelper.ReadTag(r, ref ln, "D"))); t.Nodes[n].Position = int.Parse(TextDumpHelper.ReadTag(r, ref ln, "P")); TextDumpHelper.Split(TextDumpHelper.ReadLine(r, ref ln), out tag, out value); if (tag == "C") { t.Nodes[n].IsDealerAction = true; t.Nodes[n].Card = int.Parse(value); } else if (tag == "A") { t.Nodes[n].IsDealerAction = false; t.Nodes[n].Amount = TextDumpHelper.BinStringToDouble(value); t.Nodes[n].Probab = TextDumpHelper.BinStringToDouble(TextDumpHelper.ReadTag(r, ref ln, "Pr")); } else { throw new ApplicationException(String.Format("Line {0}: wrong tag '{1}', 'C' or 'A'", ln, tag)); } } return(t); }