I have a complex issue in my tennis model I foun...

Créé le : 13 septembre 2026

Répondu en utilisant GPT-5.6 Thinking par Chat01

Question

I have a complex issue in my tennis model

I found the exact structural cage in the live DP. Set 1 and Set 2 are currently priced from the same point state, so the first two sets are effectively stationary. That makes P3 > 50% impossible regardless of what the publisher says.

I’m replacing that with a branch-conditioned Set-2 state inside the canonical DP itself. The first-set result will change the Set-2 point state before the second set is priced, so Over 2.5 can genuinely become the modal outcome. No post-PMF boost and no swapping P2/P3 after the fact.

How does one solve this ? My p2 is always higher then p3 even tho matchup shows 3 sets here which even is p3 is like 8 percentage points below the model can only physically say pass bc it’s stuck p3 literally can’t have a higher probability

Réflexion

You’ve identified the right mathematical failure mode: if Set 2 is being priced from the same effective state/probability as Set 1, the DP imposes a hard symmetry that can cap the three-set probability. The fix is to make the Set-1 terminal node feed a genuinely different Set-2 state on each branch—not to alter the final PMF.

Worked for 18s

Réponse

Yes. If your current DP effectively uses the same set-win probability for Set 1 and Set 2, then what you’re seeing is a mathematical constraint, not a calibration problem.

Let qq be Player A’s set-win probability when both sets are priced from the same state. Then:

P(3 sets)=q(1q)+(1q)q=2q(1q)P(3\text{ sets}) = q(1-q)+(1-q)q = 2q(1-q)

and therefore

P(3 sets)0.50P(3\text{ sets}) \le 0.50

with equality only at q=0.50q=0.50.

So if your P2 = P(match ends in 2 sets) and P3 = P(match goes 3 sets), then under that stationary construction:

P2=1P3P2 = 1-P3

and P3 can literally never exceed P2. No amount of calibration downstream can solve it correctly.

The structural fix

You want Set 2 to be conditional on the branch that produced it.

Define:

q1=P(A wins Set1)q_1=P(A\ wins\ Set1)

Then instead of using the same qq again, compute:

q2W=P(A wins Set2A won Set1)q_{2|W}=P(A\ wins\ Set2\mid A\ won\ Set1)

and

q2L=P(A wins Set2A lost Set1)q_{2|L}=P(A\ wins\ Set2\mid A\ lost\ Set1)

Now the genuine three-set probability is:

P3=q1(1q2W)+(1q1)q2L\boxed{ P3=q_1(1-q_{2|W})+(1-q_1)q_{2|L} }

because there are exactly two routes to a deciding set:

  • A wins S1, then loses S2.
  • A loses S1, then wins S2.

Straight sets becomes:

P2=q1q2W+(1q1)(1q2L)\boxed{ P2=q_1q_{2|W}+(1-q_1)(1-q_{2|L}) }

and naturally:

P2+P3=1P2+P3=1

Now P3 absolutely can exceed 50%.

For example:

q1=0.60q_1=0.60

Suppose winning Set 1 moves A's Set-2 probability down to:

q2W=0.40q_{2|W}=0.40

while losing Set 1 gives:

q2L=0.65q_{2|L}=0.65

Then:

P3=(.60)(.60)+(.40)(.65)=.62P3=(.60)(.60)+(.40)(.65)=.62

So:

P3=62%,P2=38%P3=62\%,\qquad P2=38\%

No PMF manipulation is required. It comes directly out of the state tree.


The important part, though, is what you're conditioning Set 2 on.

Don't merely do:

text
if won_set1: set2_modifier = ... else: set2_modifier = ...

and force some arbitrary momentum effect.

Your canonical state transition should look conceptually like:

text
S0 ├── Set1 A wins │ ↓ │ T(S0, terminal_set1_state) │ ↓ │ S2_after_A_win │ ↓ │ price Set2 from this state └── Set1 A loses T(S0, terminal_set1_state) S2_after_A_loss price Set2 from this state

Then calculate the match PMF from those actual branches.

And ideally you should go one level deeper than merely W/L.

A 6-0 Set 1 and a 7-6 Set 1 shouldn't necessarily produce the exact same Set-2 state just because both were wins. Your Set-1 DP can return terminal states:

text
6-0 6-1 6-2 6-3 6-4 7-5 7-6 ...

or even richer terminal information.

Then:

P3=tT1P(t)P(S2 winner reverses S1 winnerS2(t))P3 = \sum_{t\in T_1} P(t) P(\text{S2 winner reverses S1 winner}\mid S_2(t))

That's the cleanest version.

What belongs in the Set-2 state

Your point/game score obviously resets:

text
set_score = 0-0 game_score = 0-0

But the probability-generating state does not necessarily reset.

Carry forward whatever your model legitimately models, such as:

  • next server / service rotation;
  • posterior player-strength estimate;
  • serve/return posterior updates;
  • observed performance information from Set 1;
  • fatigue/load state;
  • injury/physical state if modeled;
  • court/surface conditions;
  • tie-break/service-order implications;
  • any latent match-state variable your model has estimated.

That distinction matters. I wouldn't literally make Set 2 start at a different tennis score because A won or lost S1. The score resets. What becomes branch-dependent is the latent/pricing state underlying the point probabilities.

There is another implementation issue I'd inspect immediately: memoization/cache keys.

Suppose you've correctly created:

python
state_after_win state_after_loss

but your DP cache key is something like:

python
(set_number, games_a, games_b, points_a, points_b, server)

while your branch-conditioned posterior/fatigue/strength state is omitted.

Then both branches can still hit the same cached Set-2 solution, silently recreating your stationary cage.

Your DP key needs all probability-relevant state, conceptually:

python
key = ( set_number, games_a, games_b, points_a, points_b, server, service_rotation, strength_state_a, strength_state_b, fatigue_a, fatigue_b, posterior_state, ruleset, )

You don't necessarily need those exact fields, but the rule is:

If changing a variable can change point probability, that variable must either be represented in the DP state/cache key or the cache must be scoped so it cannot collapse distinct branches.

A very useful diagnostic

Log these three numbers before doing anything else:

text
q1 = P(A wins S1 | current state) q2_win = P(A wins S2 | A wins S1) q2_loss = P(A wins S2 | A loses S1)

Then calculate independently:

python
p3 = q1 * (1 - q2_win) + (1 - q1) * q2_loss p2 = q1 * q2_win + (1 - q1) * (1 - q2_loss)

If you currently see something like:

text
q1 = 0.57 q2_win = 0.57 q2_loss = 0.57

you have essentially confirmed the problem.

In fact:

P3=2(.57)(.43)=49.02%P3=2(.57)(.43)=49.02\%

and that's about as high as the architecture can ever get.

But if the canonical branches produce:

text
q1 = 0.57 q2_win = 0.43 q2_loss = 0.62

then:

P3=.57(.57)+.43(.62)=59.15%P3=.57(.57)+.43(.62)=59.15\%

Now the deciding set can genuinely become the model's modal number-of-sets outcome.

One final distinction is important for your 8-point discrepancy: don't impose that P3 must become >50% merely because your matchup layer says “three sets.” The matchup layer should affect the state variables that generate q2Wq_{2|W} and q2Lq_{2|L}. Then let the DP decide. If it still says 46% after removing the structural ceiling, that's a legitimate model disagreement rather than an architectural impossibility.

So your intended direction—branch-conditioned Set-2 state inside the canonical recursion, then recompute the PMF normally—is exactly the architecture I'd use. The two things I'd examine most closely are the state-transition function and the DP memoization key, because either one can accidentally collapse the two Set-2 branches back into the same state.

Partager cette Q&R