Saturday, July 9, 2011

Tyre Strategy: First Guess at a Strategy Model

Following on from a comment to How do you calcluate and optimal tyre stategy by Malcolm33, I had a go a putting together a Python script to identify the relative penalties accruing from different strategies compared to completing the race using an ideal, non-degrading tyre.

# Strategy Calculator
# Inspired by comment by Malcolm33 to 
# http://f1datajunkie.blogspot.com/2011/06/how-do-you-calculate-optimal-pit-stop.html?showComment=1309963019997#c2438489699153529837

tyredegradation={}
#Use a really crude tyre model for now: tyre degrades at additive rate 'phase 1 degradation' per lap
# until start of phase 2, then at incremental phase 2 degradation per lap
#The bias term rate base lap time of each tyre relative to best performing tyre
#tyremodel: bias, phase1 degradation, start of phase2, phase2 degradation
tyredegradation['H']=(1,0.05,99,0.05)
tyredegradation['S']=(0,0.1,15,0.5)
pitloss=12
pitstop=4
laps=52

pitTime=pitloss+pitstop

#If I'm right in remembering sum of i from 1 to N is 0.5*N(N+1)...
def stintTime(lapstodo,tyremodel):
 bias,ph1d,ph2s,ph2d=tyremodel
 if lapstodo < ph2s:
  t=bias*lapstodo+0.5*lapstodo*(lapstodo+1)*ph1d
 else:
  xlap1=ph2s-1
  xlap2=lapstodo-ph2s+1
  t=bias*lapstodo+ph1d*0.5*xlap1*(xlap1+1)+ph2d*0.5*xlap2*(xlap2+1)
 return t

#The strategy calculations sum the total "lost time" compared to completing race on best tyre
# with no pitstops, bias or degradation
#Strategies are calculated for each tyre combination and each possible stop combination
 
#One stop
strategies=[('H','S'),('S','H')]

for strategy in strategies:
 min=999
 t=0
 print "Strategy",strategy
 tph1,tph2=strategy
 for lap in range(1,laps-1):
  tp1=stintTime(lap,tyredegradation[tph1])
  tp2=stintTime(laps-lap,tyredegradation[tph2])
  t=tp1+pitTime+tp2
  #print 'One stop: stop on lap',lap,'timeloss:',t,'from phase 1',tp1,', phase 2',tp2
  if t < min:
   opt=(lap,t)
   min=t
 print 'Optimal 1-stop on',strategy,opt


#Two stop
strategies=[['H','S','S'],['H','S','H'],['H','H','S'],['S','S','H'],['S','H','S'],['S','H','H']]

for strategy in strategies:
 min=999
 t=0
 print "Strategy",strategy
 tph1,tph2,tph3=strategy
 for endstint1 in range(1,laps-1):
  for endstint2 in range(endstint1+1,laps):
   tp1=stintTime(endstint1,tyredegradation[tph1])
   tp2=stintTime(endstint2-endstint1,tyredegradation[tph2])
   tp3=stintTime(laps-endstint2,tyredegradation[tph3])
   
   t=tp1+pitTime+tp2+pitTime+tp3
   #print 'One stop: stop on lap',lap,'timeloss:',t,'from phase 1',tp1,', phase 2',tp2
   if t < min:
    opt=(endstint1,endstint2,t)
    min=t
 print 'Optimal 2-stop on',strategy,opt

#Three stop
strategies=[['H','S','S','S'],['H','S','S','H'],['H','S','H','S'],['H','S','H','H'],['H','H','H','S'],['H','H','S','H'],['H','H','S','S'],['S','H','H','H'],['S','H','H','S'],['S','H','S','H'],['S','H','S','S'],['S','S','S','H'],['S','S','H','S'],['S','S','H','H']]

for strategy in strategies:
 min=999
 t=0
 print "Strategy",strategy
 tph1,tph2,tph3,tph4=strategy
 for endstint1 in range(1,laps-2):
  for endstint2 in range(endstint1+1,laps-1):
   for endstint3 in range(endstint2+1,laps):
   
    tp1=stintTime(endstint1,tyredegradation[tph1])
    tp2=stintTime(endstint2-endstint1,tyredegradation[tph2])
    tp3=stintTime(endstint3-endstint2,tyredegradation[tph3])
    tp4=stintTime(laps-endstint3,tyredegradation[tph4])
    
    t=tp1+pitTime+tp2+pitTime+tp3+pitTime+tp4
    #print 'One stop: stop on lap',lap,'timeloss:',t,'from phase 1',tp1,', phase 2',tp2
    if t < min:
     opt=(endstint1,endstint2,endstint3,t)
     min=t
 print 'Optimal 3-stop on',strategy,opt

Here's what I get for a 52 lap race using the crude, guesstimated tyre model parameters shown above:
Optimal 1-stop on ('H', 'S') (33, 95.05)
Optimal 1-stop on ('S', 'H') (19, 95.05)
Optimal 2-stop on ['H', 'S', 'S'] (18, 35, 85.55)
Optimal 2-stop on ['H', 'S', 'H'] (18, 35, 96.69999999999999)
Optimal 2-stop on ['H', 'H', 'S'] (18, 35, 96.69999999999999)
Optimal 2-stop on ['S', 'S', 'H'] (17, 34, 85.55)
Optimal 2-stop on ['S', 'H', 'S'] (17, 35, 85.55)
Optimal 2-stop on ['S', 'H', 'H'] (17, 35, 96.69999999999999)
Optimal 3-stop on ['H', 'S', 'S', 'S'] (4, 20, 36, 88.5)
Optimal 3-stop on ['H', 'S', 'S', 'H'] (9, 25, 42, 97.5)
Optimal 3-stop on ['H', 'S', 'H', 'S'] (9, 25, 35, 97.5)
Optimal 3-stop on ['H', 'S', 'H', 'H'] (12, 29, 41, 107.6)
Optimal 3-stop on ['H', 'H', 'H', 'S'] (12, 24, 35, 107.6)
Optimal 3-stop on ['H', 'H', 'S', 'H'] (12, 24, 41, 107.6)
Optimal 3-stop on ['H', 'H', 'S', 'S'] (9, 18, 35, 97.5)
Optimal 3-stop on ['S', 'H', 'H', 'H'] (17, 29, 41, 107.6)
Optimal 3-stop on ['S', 'H', 'H', 'S'] (16, 25, 35, 97.5)
Optimal 3-stop on ['S', 'H', 'S', 'H'] (16, 25, 42, 97.5)
Optimal 3-stop on ['S', 'H', 'S', 'S'] (16, 20, 36, 88.5)
Optimal 3-stop on ['S', 'S', 'S', 'H'] (16, 32, 48, 88.5)
Optimal 3-stop on ['S', 'S', 'H', 'S'] (16, 32, 36, 88.5)
Optimal 3-stop on ['S', 'S', 'H', 'H'] (16, 32, 42, 97.5)

If you think I've messed this model up, please post a critical analysis of it in the comments:-)

A major issue is the simplicity of the tyre model. Even within the tyre model I've used, there may be "issues" with the parameters (incremental degradation rates, bias and phase boundary. Ideally, I'd be able to use practice timing data to tune these values (or even in race timing data), so suggestions for how to go about this would be appreciated. (You can get a link to the timing data as a spreadsheet from the Data page.)

3 comments:

  1. To think about: /undercut/ strategy: if tyre advantage for swithcing to new tyres is A seconds and car is within A seconds of car ahead (or some function depending on guesstimated number of laps before car ahead will be willing to pit), pitting first may give the undercut?

    ReplyDelete
  2. I had been trying to do a similar tyre strategy model as well, but I took a different approach.

    I firstly assumed an "ideal lap" time. This would be the fastest possible time with the perfect tyres and no fuel on board.

    I then assumed that the time added to each lap due to a worsening tyre grew exponentially with the number of laps ran. Hence, I planned two exponential curves (one for primes and one for options).

    Lastly, I considered the weight effect of the fuel in the race, and added a given set of time to each lap.

    For a one stop strategy, I looped the equations much like your code; so for every possible lap to pit, I had a different overall race time time.

    I then tried different order of tyres and compared the values. I am now trying to loop the entire analysis so it could consider using all 7 tyres instead.

    I am sure your tyre model must be more accurate than mine, but to make sure it worked, I tried to keep it simple.

    I think the deal breaker is the weight effect of the on-board fuel. For example,for your two stop strategies, as you were either using two H and one S or two S and one H, you only got two different overall race times: independent of the order you changed the tyres.

    To follow on what Tony Hirst commented, this model only works around the overall racing time, and how to make is as short as possible with absolutely no impact of other incidences on the track (such as traffic, others pitting, race order, weather, driver concentration/mistake, yellow flags, etc...). To model all that, you would need a whole new consideration of "added time" in each lap. In other words, it is simply racing against the clock, rather than against the others on the track.

    ReplyDelete
  3. @rafael I think you're right about there being the possibility of different tyre models, such as the exponential model you suggest. I gues there mat also be a weight effect, which could be accommodated via a weight parameter in the tyre model. I think I need to look again at Ian Horlock's thesis to see what tyre model he used [ http://www.enm.bris.ac.uk/teaching/projects/2008_09/ih5137/ ]?

    ReplyDelete

There seem to be a few issues with posting comments. I think you need to preview your comment before you can submit it... Any problems, send me a message on twitter: @psychemedia