void EnumeratePlayersChanceIndex(Int64 actionTreeNodeIdx, int[] chanceNodes, StrategicState state, Constraint constr) { for (int i = 0; i < _heroVarsInLeaves[actionTreeNodeIdx].Length; ++i) { int chanceNodeIdx = chanceNodes[i]; if (chanceNodeIdx == 0) { // There is no existing cards for this index (a "hole") continue; } int varH = _heroVarsInLeaves[actionTreeNodeIdx][i]; double[] potShares = new double[PLAYERS_COUNT]; UInt16 activePlayers = ActionTree.Nodes[actionTreeNodeIdx].ActivePlayers; //Debug.Assert(round == _roundsCount - 1 || CountBits.Count(activePlayers) == 1, "Must be either chance leaf or single active player"); ChanceTree.Nodes[chanceNodeIdx].GetPotShare(activePlayers, potShares); double chanceProbab = ChanceTree.Nodes[chanceNodeIdx].Probab; double result = state.Pot * potShares[HeroPosition] - state.InPot[HeroPosition]; double coeff = chanceProbab * result; if (varH != -1) { constr.AddVariable(varH, coeff); } else { // Special case - opponent folded before the hero has acted (e.g. small blind folds at the very beginning). // In this case there is no hero variable, and the v-variable is constant. // Constaint has the form: v3 = k3 + k13, or -v3 = -k3 - k13 constr.RightHandSide -= coeff; } } }
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; } } } }
protected bool Step2_OnNodeBegin(TreeNode tree, TreeNode node, List <Context> stack, int depth) { Context context = stack[depth]; _heroNodeCount++; if (node.State.HasPlayerActed(HeroPosition)) { context.HasHeroActedAtLeastOnce = true; } else if (depth > 0) { context.HasHeroActedAtLeastOnce = stack[depth - 1].HasHeroActedAtLeastOnce; node.Var_h = stack[depth - 1].Node.Var_h; } if (node.State.IsPlayerActing(HeroPosition)) { Constraint constr = new Constraint(); if (node.Var_h == -1) { // This is the very first move of the hero in this tree branch, // add constraint Sum(h_child) = 1 constr.RightHandSide = 1; for (int c = 0; c < node.Children.Count; ++c) { node.Children[c].Var_h = Vars.Add("h", node.Children[c].Id); VarHToCard[node.Children[c].Var_h] = node.State.Players[HeroPosition].PrivateCards; constr.AddVariable(node.Children[c].Var_h, 1); } } else { // Add constraint h_prev_move = Sum(h_child) constr.RightHandSide = 0; constr.AddVariable(node.Var_h, -1); for (int c = 0; c < node.Children.Count; ++c) { node.Children[c].Var_h = Vars.Add("h", node.Children[c].Id); VarHToCard[node.Children[c].Var_h] = node.State.Players[HeroPosition].PrivateCards; constr.AddVariable(node.Children[c].Var_h, 1); } } _constraintsEQ.Add(constr); } return(true); }
protected void Step5OnNodeEnd(TreeNode tree, TreeNode node, List <Context> stack, int depth) { Context context = stack[depth]; if (node.Children.Count == 0) { // Terminal nodes, add new variables and constraints: // v6 = res6 * t14 + res15 * t23 node.Var_v = Vars.Add("v", node.Id); Constraint constr = new Constraint(); constr.RightHandSide = 0; for (int i = 0; i < node.TerminalCoeffs_h.Count; i++) { constr.AddVariable(node.TerminalVars_h[i], node.TerminalCoeffs_h[i]); } constr.AddVariable(node.Var_v, -1); _constraintsEQ.Add(constr); } else if (node.State.IsPlayerActing(1 - HeroPosition)) { //v2 = r3 + r8 //r3 + r8 <= v3 //r3 + r8 <= v8 // Add new variables: v_i and r_* node.Var_v = Vars.Add("v", node.Id); List <int> var_r = new List <int>(); for (int i = 0; i < node.Children.Count; i++) { int rIdx = Vars.Add("r", node.Children[i].Id); var_r.Add(rIdx); } // Add 1 eq constraint Constraint constr = new Constraint(); constr.RightHandSide = 0; for (int i = 0; i < var_r.Count; ++i) { constr.AddVariable(var_r[i], 1); } constr.AddVariable(node.Var_v, -1); _constraintsEQ.Add(constr); // For each child add a le constraint for (int i = 0; i < node.Children.Count; i++) { Constraint constrLE = new Constraint(); constrLE.RightHandSide = 0; for (int j = 0; j < var_r.Count; ++j) { constrLE.AddVariable(var_r[j], 1); } constrLE.AddVariable(node.Children[i].Var_v, -1); _constraintsLE.Add(constrLE); } } else { // Sum all the children: // v3 = v4 + v5 node.Var_v = Vars.Add("v", node.Id); Constraint constr = new Constraint(); constr.RightHandSide = 0; for (int i = 0; i < node.Children.Count; i++) { constr.AddVariable(node.Children[i].Var_v, 1); } constr.AddVariable(node.Var_v, -1); _constraintsEQ.Add(constr); } }
void PrepareOpp_OnNodeEnd(StrategyTree tree, PrepareOppContext[] stack, int depth) { PrepareOppContext context = stack[depth]; Int64 n = context.NodeIdx; if (_actionTreeIndex.GetChildrenCount(context.ActionTreeIdx) == 0) { // A leaf, add new variables and constraints: // v6 = k16 * h16 + k26 * h26 Constraint constr = new Constraint(); constr.RightHandSide = 0; constr.AddVariable(context.VarV, -1); _constraintsEQ.Add(constr); int[] chanceNodes = _chanceTreeNodes[context.Round][context.OppChanceIdx]; EnumeratePlayersChanceIndex(context.ActionTreeIdx, chanceNodes, context.State, constr); } if (n == PLAYERS_COUNT) { return; } // Update parent. Int64 pn = stack[depth - 1].NodeIdx; PrepareOppContext parentContext = stack[depth - 1]; Constraint constrEq = parentContext.EqConstr; if (constrEq == null) { // Create new eq constraint in the parent. constrEq = new Constraint(); parentContext.EqConstr = constrEq; constrEq.RightHandSide = 0; constrEq.AddVariable(parentContext.VarV, -1); _constraintsEQ.Add(constrEq); } if (tree.Nodes[n].IsPlayerAction(_oppPosition)) { // v2 = r3 + r8 // Add r-variable for each node where opponent have acted. int varR = _variables.Add("r", (int)n); constrEq.AddVariable(varR, 1); parentContext.ChildVarsR.Add(varR); parentContext.ChildVarsV.Add(context.VarV); } else { Debug.Assert(context.ChildVarsV.Count == context.ChildVarsR.Count); // If it is the node where the opponent is acting, // add le-constraints. // r3 + r8 <= v3 // r3 + r8 <= v8 foreach (int varV in context.ChildVarsV) { Constraint constrLe = new Constraint(); _constraintsLE.Add(constrLe); constrLe.RightHandSide = 0; constrLe.AddVariable(varV, -1); foreach (int varR in context.ChildVarsR) { constrLe.AddVariable(varR, 1); } } // Sum all the children in the parent: // v3 = v4 + v5 constrEq.AddVariable(context.VarV, 1); } }