Siamo in una partita di tennis, i due giocatori A e B sono arrivati 6-6 e ora tutto si deciderà al tie-break. Durante la partita, da bravi (ingegneri) matematici, siamo riusciti a stimare due parametri e che descrivono le probabilità, per il giocatore A, di vincere un punto quando lui è al servizio o quando B è al servizio, rispettivamente. Ma eccoci, il giocatore A si sta apprestando ad iniziare il tie-break! sarà lui infatti a iniziare a servire per primo. Dato questo contesto e questi dati, qual è la probabilità che il giocatore A vinca il tie-break?
Da raccontare a parole è molto lunga, quindi vi suggerisco caldamente il video molto dettagliato. L'idea è comunque intanto di decomporre l'evento vittoria nei possibili casi in cui può manifestarsi, ovvero
e poi di studiare ogni termine lavorando con la distribuzione Binomiale. Infatti, una variabile aleatoria ha legge Binomiale di parametri e (e scriviamo ) quando conta il numero di successi che otteniamo quando replichiamo per volte un esperimento che può avere esito di successo con probabilità pari a . Quindi l'idea è di trattare come il numero di volte in cui un giocatore è al servizio o in risposta, mentre come la probabilità dell'evento di "successo", ovvero vincere il punto, ovvero i parametri o .
Per esempio, per vincere 7-0, il giocatore A deve vincere tutti i punti, dei quali 3 sono quando lui è al servizio mentre 4 di quando B è al servizio. Usando quindi la legge binomiale, che ha densità di probabilità , insieme all'indipendenza degli eventi di vincere un punto, si ricava che
Ovviamente questo era il caso facile. Gli altri sono un po' più complicati (c'è da separare il fatto di arrivare a 6 e poi fare l'ultimo punto vincente, e c'è da capire in quanti modi possono distribuirsi i punti per poter vincere con un certo punteggio) ma seguono la stessa logica.
L'ultimo termine di (1), quello riguardo alla vittoria nei casi ad oltranza, segue invece un calcolo interessante che comporta una ricorsione. Infatti, dal pareggio (tipo 6-6) possiamo vincere o vincendo i due punti successivi (arrivando 8-6) o vincendone uno e perdendone uno, tornando ad un nuovo pareggio (7-7), e vincere partendo da questo nuovo pareggio. In questo modo, usando l'indipendenza dei secondi eventi, abbiamo che
da cui possiamo quindi ricavare . Assemblando tutti i pezzi si arriva alla formulazione che ora segue nel codice e relativi grafici, che descrivono la probabilità di vittoria per il giocatore A, indicata come valori sull'asse , in funzione dei parametri e posti sugli assi e , e le sue curve di livello.
using Plots
using Distributions
# 1 2 3 4 5 6 7 8 9 10 11 12
# A B B A A B B A A B B A
function ptiebreak(a::Real,b::Real)
p70 = (pdf(Binomial(3,a),3) * pdf(Binomial(3,b),3))*b
# batte B al 7mo turno
p71 = sum([pdf(Binomial(3,a),i) * pdf(Binomial(4,b),6-i) for i in 2:3])*a
# batte A all'8vo turno
p72 = sum([pdf(Binomial(4,a),i) * pdf(Binomial(4,b),6-i) for i in 2:4])*a
# batte A al 9no turno
p73 = sum([pdf(Binomial(5,a),i) * pdf(Binomial(4,b),6-i) for i in 2:5])*b
# batte B al 10mo turno
p74 = sum([pdf(Binomial(5,a),i) * pdf(Binomial(5,b),6-i) for i in 1:5])*b
# batte B al 11mo turno
p75 = sum([pdf(Binomial(5,a),i) * pdf(Binomial(6,b),6-i) for i in 0:5])*a
# batte A al 12mo turno
p66 = sum([pdf(Binomial(6,a),i) * pdf(Binomial(6,b),6-i) for i in 0:6])
pda66 = a*b/(1-a-b+2*a*b)
ptot = p70+p71+p72+p73+p74+p75+p66*pda66
@assert 0<=ptot<=1
return ptot
end
aa = range(0.01,0.99, step=0.01)
bb = range(0.01,0.99, step=0.01)
p = surface(aa, bb, ptiebreak,camera=(25,20))
xlabel!("a values")
ylabel!("b values")
contourf(aa, bb, ptiebreak)
xlabel!("a values")
ylabel!("b values")
Notiamo anche come le apparentemente strane regole del tie-break, in cui il primo giocatore effettua solo un servizio e da lì in poi ci si alterna due servizi a testa (quindi la sequenza di battute sarebbe A|BB|AA|BB|AA|...) hanno in realtà ha perfettamente senso. Infatti, il tie-break in questo modo è equo: chiunque cominci al servizio non ha alcun vantaggio a priori. Questo lo si vede anche dalla matematica (naturalmente 😉), in cui leggendo il calcolo sempre nella prospettiva di A, ma nel caso in cui fosse B il primo a servire (possiamo modellare questo scenario invertendo i parametri e ), otterremo comunque le stesse probabilità di vittoria.
Usando i numeri decimali classici (i Float64) sembra che escano valori leggermente diversi; ma in realtà sono solo dovuti ad approssimazioni numeriche: passando ad una rappresentazione più precisa (i BigFloat) tutto dovrebbe tornare.
julia> ptiebreak(0.60,0.70)
0.8881752145777776
julia> ptiebreak(0.70,0.60)
0.8881752145777777
julia> 1-ptiebreak(0.4,0.3) # altro controllo, cambiando prospettiva su B
0.8881752145777779
julia> ptiebreak(BigFloat(0.60),BigFloat(0.70))
0.8881752145777777236370136878239485198844074151971728203443474502251501326155067
julia> ptiebreak(BigFloat(0.70),BigFloat(0.60))
0.8881752145777777236370136878239485198844074151971728203443474502251501326155067
Piccola digressione. A questo punto magari vi chiederete: ma perché allora in informatica non si usano sempre i BigFloat o comunque queste rappresentazioni più precise? La risposta è perché ok, sono più precise, ma sono anche molto molto più dispensiose in termini di memoria e tempo di esecuzione,
julia> @time ptiebreak(BigFloat(0.60),BigFloat(0.70))
0.012136 seconds (15.61 k allocations: 573.875 KiB)
0.8881752145777777236370136878239485198844074151971728203443474502251501326155067
julia> @time ptiebreak(0.60,0.70)
0.000018 seconds (6 allocations: 576 bytes)
0.8881752145777776
e anche perché la precisione base è in genere sufficiente. Non sono infatti molti gli scenari in cui i calcoli effettuati da un computer devono avere un così alto livello di precisione.