public override void CopyFrom(PocketData Source) { RaiseCallFoldData _Source = Source as RaiseCallFoldData; for (int i = 0; i < Pocket.N; i++) { Raise[i] = _Source.Raise[i]; Call[i] = _Source.Call[i]; } }
public number ChanceToActWithExclusion(PocketData pdf, PocketData chance, int ExcludedPocketIndex) { var pocket = Pocket.Pockets[ExcludedPocketIndex]; int c1 = pocket.Cards[0], c2 = pocket.Cards[1]; number Chance = TotalChance - TotalChance_OneCardFixed[c1] - TotalChance_OneCardFixed[c2] + pdf[ExcludedPocketIndex] * chance[ExcludedPocketIndex]; number Mass = TotalMass - TotalMass_OneCardFixed[c1] - TotalMass_OneCardFixed[c2] + pdf[ExcludedPocketIndex]; if (Mass < Tools.eps) return 0; else return Chance / Mass; }
public void ChanceToActPrecomputation(PocketData pdf, PocketData chance, CommunityNode community) { ResetTotal(); number val, mass; Pocket pocket; for (int p = 0; p < Pocket.N; p++) { if (!community.AvailablePocket[p]) continue; mass = pdf[p]; val = mass * chance[p]; TotalChance += val; TotalMass += mass; pocket = Pocket.Pockets[p]; int c1 = pocket.Cards[0], c2 = pocket.Cards[1]; TotalChance_OneCardFixed[c1] += val; TotalChance_OneCardFixed[c2] += val; TotalMass_OneCardFixed[c1] += mass; TotalMass_OneCardFixed[c2] += mass; } }
public virtual void CopyFrom(PocketData Source) { for (int i = 0; i < Pocket.N; i++) data[i] = Source[i]; }
public virtual void SwitchWith(PocketData other) { for (int i = 0; i < Pocket.N; i++) { number temp = other[i]; other[i] = data[i]; data[i] = temp; } }
public virtual void MultiLinear(int n, int pocket, double[] weight, PocketData[] data) { number result = 0; for (int i = 0; i < n; i++) result += (number)weight[i] * data[i][pocket]; this[pocket] = result; }
public virtual void Linear(int pocket, number t1, PocketData data1, number t2, PocketData data2, number t3, PocketData data3) { this[pocket] = t1 * data1[pocket] + t2 * data2[pocket] + t3 * data3[pocket]; }
public virtual void Linear(int pocket, number t1, PocketData data1, number t2, PocketData data2) { //t1 = .5 * (t1 + Node.__t); //t2 = .5 * (t2 + (1 - Node.__t)); this[pocket] = t1 * data1[pocket] + t2 * data2[pocket]; }
void CalculateBestAgainst_Naive(Player Opponent) { // First decide strategy for children nodes. RecursiveBest(Opponent); // For each pocket we might have, calculate what we should do. PocketData UpdatedP = new PocketData(); for (int p1 = 0; p1 < Pocket.N; p1++) { if (!MyCommunity.AvailablePocket[p1]) continue; // Update the opponent's pocket PDF using the new information, // (which is that we now know which pocket we have). UpdateOnExclusion(PocketP, UpdatedP, p1); // Calculate the EV assuming we proceed to a branch. // Loop through each possible opponent pocket and then each possible branch, // summing up the EV of each branch times the probability of arriving there. number TotalWeight = 0, BranchEV = 0; number[] BranchPDF = new number[Branches.Count]; for (int p2 = 0; p2 < Pocket.N; p2++) { if (!MyCommunity.AvailablePocket[p2]) continue; // All branches not overlapping our pocket or the opponent's pocket are equally likely. int BranchIndex = 0; foreach (Node Branch in Branches) { BranchIndex++; if (!Branch.MyCommunity.AvailablePocket[p1] || !Branch.MyCommunity.AvailablePocket[p2]) continue; number Weight = Branch.Weight; BranchEV += UpdatedP[p2] * Weight * Branch.EV[p1]; TotalWeight += UpdatedP[p2] * Weight; BranchPDF[BranchIndex - 1] += UpdatedP[p2] * Weight; } } Assert.ZeroOrOne(BranchPDF.Sum()); Assert.ZeroOrOne(TotalWeight); Assert.That(BranchEV >= -DerivedSetup.MaxPot - Tools.eps && BranchEV <= DerivedSetup.MaxPot + Tools.eps); EV[p1] = BranchEV; Assert.IsNum(EV[p1]); } }
protected override void Initialize() { S = new PocketData(); B = new PocketData(); if (MakeHold) Hold = new PocketData(); CreateBranches(); }
public RaiseCallFoldData() { this.Raise = this; this.Call = new PocketData(); }
public override void Linear(int pocket, number t1, PocketData data1, number t2, PocketData data2, number t3, PocketData data3) { base.Linear(pocket, t1, data1, t2, data2, t3, data3); Call.Linear(pocket, t1, ((RaiseCallFoldData)data1).Call, t2, ((RaiseCallFoldData)data2).Call, t3, ((RaiseCallFoldData)data3).Call); }
public void ProbabilityPrecomputation(PocketData pdf, CommunityNode community) { ResetMass(); number mass; Pocket pocket; for (int p = 0; p < Pocket.N; p++) { if (!community.AvailablePocket[p]) continue; mass = pdf[p]; TotalMass += mass; pocket = Pocket.Pockets[p]; int c1 = pocket.Cards[0], c2 = pocket.Cards[1]; TotalMass_OneCardFixed[c1] += mass; TotalMass_OneCardFixed[c2] += mass; } }
/// <summary> /// Takes in a pocket PDF and updates it based on new information, /// the new information being that a particular pocket should be excluded. /// </summary> /// <param name="P">The prior PDF</param> /// <param name="UpdatedP">The posterior PDF</param> /// <param name="ExcludePocketIndex">The index of the excluded pocket.</param> public void UpdateOnExclusion(PocketData P, PocketData UpdatedP, int ExcludePocketIndex) { number TotalWeight = 0; for (int p = 0; p < Pocket.N; p++) { if (!MyCommunity.AvailablePocket[p]) continue; // If this pocket overlaps with the excluded pocket, // then the probability of seeing it is 0. if (PocketPocketOverlap(p, ExcludePocketIndex)) { UpdatedP[p] = 0; continue; } UpdatedP[p] = P[p]; TotalWeight += P[p]; } if (TotalWeight == 0) return; for (int p = 0; p < Pocket.N; p++) UpdatedP[p] /= TotalWeight; }
public void Update(PocketData PreviousPDF, PocketData Strategy, PocketData Destination) { number ChanceToProceed = 0; for (int p = 0; p < Pocket.N; p++) { if (MyCommunity.AvailablePocket[p]) ChanceToProceed += PreviousPDF[p] * Strategy[p]; } Assert.AlmostPos(ChanceToProceed); if (ChanceToProceed <= 0) ChanceToProceed = 1; // Calculate the Pocket PDF assuming opponent proceeded. for (int p = 0; p < Pocket.N; p++) Destination[p] = PreviousPDF[p] * Strategy[p] / ChanceToProceed; }
/// <summary> /// Given a strategy to act or not act for each pocket, /// and assuming we know the PDF of the pockets, calculate /// the chance action is taken. /// </summary> /// <param name="pdf">The PDF of pockets.</param> /// <param name="chance">The chance to act for each pocket.</param> /// <param name="ExcludePocketIndex">Index of a pre-existing pocket. Exclude all pockets overlapping this pocket.</param> /// <returns>The overall chance to act.</returns> public number TotalChance(PocketData pdf, PocketData chance, int ExcludePocketIndex) { number RaiseChance = 0; number weight = 0; for (int p = 0; p < Pocket.N; p++) { if (!MyCommunity.AvailablePocket[p]) continue; if (PocketPocketOverlap(p, ExcludePocketIndex)) continue; weight += pdf[p]; RaiseChance += pdf[p] * chance[p]; } if (weight == 0) { Assert.That(RaiseChance == 0); return 0; } return RaiseChance / weight; }
/// <summary> /// Given a strategy to act or not act for each pocket, /// and assuming we know the PDF of the pockets, calculate /// the chance action is taken. /// </summary> /// <param name="pdf">The PDF of pockets.</param> /// <param name="chance">The chance to act for each pocket.</param> /// <returns>The overall chance to act.</returns> public number TotalChance(PocketData pdf, PocketData chance) { number RaiseChance = 0; for (int p = 0; p < Pocket.N; p++) RaiseChance += pdf[p] * chance[p]; return RaiseChance; }
//static number[] IntersectP = new number[Card.N]; void CalculateBestAgainst_SingleCardOptimized(Player Opponent) { RecursiveBest(Opponent); // Calculate P(Opponent pocket intersects a given card) for (int c = 0; c < Card.N; c++) { if (BranchesByIndex[c] == null) continue; IntersectP[c] = 0; for (int c2 = 0; c2 < Card.N; c2++) { if (c == c2) continue; int p = Game.PocketLookup[c, c2]; if (!MyCommunity.AvailablePocket[p]) continue; IntersectP[c] += PocketP[p]; } } Data.ProbabilityPrecomputation(PocketP, MyCommunity); // For each pocket we might have, calculate what we should do. PocketData UpdatedP = new PocketData(); for (int p1 = 0; p1 < Pocket.N; p1++) { if (!MyCommunity.AvailablePocket[p1]) continue; number BranchEV = 0; for (int c = 0; c < Card.N; c++) { Node Branch = BranchesByIndex[c]; if (Branch == null) continue; if (!Branch.MyCommunity.AvailablePocket[p1]) continue; // Find opponent pockets that intersect our pocket and the community card c var Pocket1 = Pocket.Pockets[p1]; int p2_1 = Game.PocketLookup[Pocket1.Cards[0], c]; int p2_2 = Game.PocketLookup[Pocket1.Cards[1], c]; number Correction = Data.MassAfterExclusion(PocketP, p1); number Pr = Correction - IntersectP[c] + PocketP[p2_1] + PocketP[p2_2]; if (Pr <= Tools.eps) continue; Assert.That(Correction > Tools.eps); Pr /= Correction; Assert.AlmostProbability(Pr); Assert.That(Branch.Weight > 0); Assert.IsNum(Pr); Pr = Tools.Restrict(Pr); BranchEV += Branch.EV[p1] * Pr * Branch.Weight; } EV[p1] = BranchEV; Assert.IsNum(EV[p1]); } }
public override void SwitchWith(PocketData other) { RaiseCallFoldData _other = other as RaiseCallFoldData; Assert.That(_other != null); base.SwitchWith(other); Call.SwitchWith(_other.Call); }
public number MassAfterExclusion(PocketData pdf, int ExcludedPocketIndex) { var pocket = Pocket.Pockets[ExcludedPocketIndex]; int c1 = pocket.Cards[0], c2 = pocket.Cards[1]; number Mass = TotalMass - TotalMass_OneCardFixed[c1] - TotalMass_OneCardFixed[c2] + pdf[ExcludedPocketIndex]; return Mass; }
public void MakeScratchSpace() { if (Phase == BettingPhase.PreFlop || Phase == BettingPhase.Flop) { // Initialize HoldEV and HoldPocketP, both arrays of PocketDatas int NumData = MaxDepth + Flop.N + Card.N + Card.N; HoldEV = new PocketData[NumData]; HoldPocketP = new PocketData[NumData]; for (int i = 0; i < NumData; i++) { HoldEV[i] = new PocketData(); HoldPocketP[i] = new PocketData(); } // Initialize rest of scratch space Data = new Optimize(); Data2 = new Optimize(); NotS = new PocketData(); IntersectP = new number[Card.N]; } else { // Copy scratch space from parent community node HoldEV = Parent.HoldEV; HoldPocketP = Parent.HoldPocketP; Data = Parent.Data; Data2 = Parent.Data2; NotS = Parent.NotS; IntersectP = Parent.IntersectP; } }
public virtual void InverseOf(PocketData Source) { for (int i = 0; i < Pocket.N; i++) data[i] = ((number)1) - Source[i]; }
public override void CalculateBestAgainst(Player Opponent) { /* Naive implementation. O(N^4) */ if (DerivedSetup.Naive) { // For each pocket we might have, calculate EV. PocketData UpdatedP = new PocketData(); uint PocketValue1, PocketValue2; for (int p1 = 0; p1 < Pocket.N; p1++) { if (!MyCommunity.AvailablePocket[p1]) continue; PocketValue1 = PocketValue[p1]; Assert.That(PocketValue1 < uint.MaxValue); // Update the opponent's pocket PDF using the new information, // (which is that we now know which pocket we have). UpdateOnExclusion(PocketP, UpdatedP, p1); OpCount++; number ShowdownEV = 0; for (int p2 = 0; p2 < Pocket.N; p2++) { if (!MyCommunity.AvailablePocket[p2]) continue; PocketValue2 = PocketValue[p2]; Assert.That(PocketValue2 < uint.MaxValue); if (PocketValue1 == PocketValue2) continue; else if (PocketValue1 > PocketValue2) ShowdownEV += UpdatedP[p2] * Pot; else ShowdownEV -= UpdatedP[p2] * Pot; } EV[p1] = ShowdownEV; Assert.IsNum(EV[p1]); } } else /* Asymptotically optimal implementation. O(N^2) */ { RiverCommunity River = (RiverCommunity)MyCommunity; Data.ProbabilityPrecomputation(PocketP, MyCommunity); number Correction; int _p1; // For each pocket we might have, calculate the chance to win. Data.ResetSummed(); _p1 = 0; while (_p1 < Pocket.N) { int p1 = River.SortedPockets[_p1]; if (!MyCommunity.AvailablePocket[p1]) { _p1++; continue; } // Find next highest pocket int NextHighest = _p1 + 1; uint CurrentPocketValue = River.PocketValue[p1]; while (NextHighest < Pocket.N && River.SortedPocketValue[NextHighest] == CurrentPocketValue) NextHighest++; // For all pockets of equal value, calculate the chance to win for (int EqualValuedPocket = _p1; EqualValuedPocket < NextHighest; EqualValuedPocket++) { int p = River.SortedPockets[EqualValuedPocket]; if (!MyCommunity.AvailablePocket[p]) continue; var pocket1 = Pocket.Pockets[p]; int c1 = pocket1.Cards[0], c2 = pocket1.Cards[1]; number ChanceToWin = Data.SummedChance - Data.SummedChance_OneCardFixed[c1] - Data.SummedChance_OneCardFixed[c2]; Correction = Data.MassAfterExclusion(PocketP, p); if (Correction < Tools.eps) { ChanceToWin = 0; } else { ChanceToWin /= Correction; } EV[p] = ChanceToWin * Pot; Assert.IsNum(EV[p]); } // Total the probability mass of our opponent having a hand with equal value for (int EqualValuedPocket = _p1; EqualValuedPocket < NextHighest; EqualValuedPocket++) { int p = River.SortedPockets[EqualValuedPocket]; if (!MyCommunity.AvailablePocket[p]) continue; var pocket1 = Pocket.Pockets[p]; int c1 = pocket1.Cards[0], c2 = pocket1.Cards[1]; number P = PocketP[p]; Data.SummedChance += P; Data.SummedChance_OneCardFixed[c1] += P; Data.SummedChance_OneCardFixed[c2] += P; } _p1 = NextHighest; } // For each pocket we might have, calculate the chance to lose. Data.ResetSummed(); _p1 = Pocket.N - 1; while (_p1 > 0) { int p1 = River.SortedPockets[_p1]; if (!MyCommunity.AvailablePocket[p1]) { _p1--; continue; } // Find next highest pocket int NextLowest = _p1 - 1; uint CurrentPocketValue = River.PocketValue[p1]; while (NextLowest >= 0 && River.SortedPocketValue[NextLowest] == CurrentPocketValue) NextLowest--; // For all pockets of equal value, calculate the chance to win for (int EqualValuedPocket = _p1; EqualValuedPocket > NextLowest; EqualValuedPocket--) { int p = River.SortedPockets[EqualValuedPocket]; if (!MyCommunity.AvailablePocket[p]) continue; var pocket1 = Pocket.Pockets[p]; int c1 = pocket1.Cards[0], c2 = pocket1.Cards[1]; number ChanceToLose = Data.SummedChance - Data.SummedChance_OneCardFixed[c1] - Data.SummedChance_OneCardFixed[c2]; Correction = Data.MassAfterExclusion(PocketP, p); if (Correction < Tools.eps) ChanceToLose = 0; else ChanceToLose /= Correction; EV[p] -= ChanceToLose * Pot; Assert.IsNum(EV[p]); } // Total the probability mass of our opponent having a hand with equal value for (int EqualValuedPocket = _p1; EqualValuedPocket > NextLowest; EqualValuedPocket--) { int p = River.SortedPockets[EqualValuedPocket]; if (!MyCommunity.AvailablePocket[p]) continue; var pocket1 = Pocket.Pockets[p]; int c1 = pocket1.Cards[0], c2 = pocket1.Cards[1]; number P = PocketP[p]; Data.SummedChance += P; Data.SummedChance_OneCardFixed[c1] += P; Data.SummedChance_OneCardFixed[c2] += P; } _p1 = NextLowest; } } }
void CalculateBestAgainst_FlopSuitReduced(Player Opponent) { System.Threading.Tasks.Parallel.ForEach(Branches, node => node.CalculateBestAgainst(Opponent)); //foreach (Node node in Branches) // node.CalculateBestAgainst(Opponent); // For each pocket we might have, calculate what we should do. PocketData UpdatedP = new PocketData(); for (int p1 = 0; p1 < Pocket.N; p1++) { if (!MyCommunity.AvailablePocket[p1]) continue; // Update the opponent's pocket PDF using the new information, // (which is that we now know which pocket we have). UpdateOnExclusion(PocketP, UpdatedP, p1); // Calculate the EV assuming we proceed to a branch. // Loop through each possible opponent pocket and then each possible branch, // summing up the EV of each branch times the probability of arriving there. number TotalWeight = 0, BranchEV = 0; number[] BranchPDF = new number[Branches.Count]; for (int p2 = 0; p2 < Pocket.N; p2++) { if (!MyCommunity.AvailablePocket[p2]) continue; // All branches not overlapping our pocket or the opponent's pocket are equally likely. // However, because we have grouped some branches together we weight representative branches more heavily. int b = 0; foreach (Node Branch in Branches) { b++; if (Branch.MyCommunity.NewCollision(p1) || Branch.MyCommunity.NewCollision(p2)) continue; FlopRoot FlopBranch = (FlopRoot)Branch; FlopRoot _Branch = FlopBranch.Representative; int _p1 = FlopBranch.MyFlop.PocketMap[p1]; //Assert.AlmostEqual(Branch.EV[p1], _Branch.EV[_p1], .05); number Weight = _Branch.Weight; BranchEV += UpdatedP[p2] * Weight * _Branch.EV[_p1]; TotalWeight += UpdatedP[p2] * Weight; BranchPDF[b - 1] += UpdatedP[p2] * Weight; } } Assert.ZeroOrOne(BranchPDF.Sum()); Assert.ZeroOrOne(TotalWeight); Assert.That(BranchEV >= -DerivedSetup.MaxPot - Tools.eps && BranchEV <= DerivedSetup.MaxPot + Tools.eps); EV[p1] = BranchEV; Assert.IsNum(EV[p1]); } }