Thoughts on pothole repair frequency

Problem: The administration of a city receives a signal of existing potholes on some streets, which citizens expect to be filled. We assume that left untreated, each pothole incurs damage on the vehicle passing through it and each vehicle itself contributes to increasing the radius of the pothole (round shape assumed for simplicity). The bigger its radius, the bigger the damage. It is also known that heavier vehicles like vans and trucks increase the size of the potholes more rapidly. Vehicles moving faster through the holes also contribute to their enlargement. Additionally, weather conditions like excessive heat, rain and snow degrade the road quality as well. We are given the average traffic count on a given street and the avg. probability with which cars pass through the potholes. What the administration wants to know is the optimal interval at which the potholes should be filled.

from math import pi class Vehicle: def __init__(self, avg_vehicle_weight_kg, avg_speed_through_potholes_kmh, pothole_increase_factor, avg_annual_daily_traffic, avg_suspension_damage_cost, avg_vehicle_age, avg_vehicle_purchase_cost): kmh_to_m_s = 1000/3600 self.avg_vehicle_weight_kg = avg_vehicle_weight_kg self.avg_speed_through_potholes_m_s = avg_speed_through_potholes_kmh * kmh_to_m_s self.pothole_increase_factor = pothole_increase_factor self.avg_annual_daily_traffic = avg_annual_daily_traffic self.avg_suspension_damage_cost = avg_suspension_damage_cost self.avg_vehicle_age = avg_vehicle_age self.avg_vehicle_purchase_cost = avg_vehicle_purchase_cost def pothole_type(pothole_radius): pothole_types_radius_sizes_m = { 'small': [0.1, 0.2], 'small-to-medium': [0.2, 0.3], 'medium': [0.3, 0.4], 'medium-to-large': [0.4, 0.6], 'large': [0.6, 99999999999999] } for k, v in pothole_types_radius_sizes_m.items(): if v[0] < pothole_radius <= v[1]: return k asphalt_cost_m2_dollar = 40 avg_pothole_inspection_cost_dollar = 50 # Initial pothole sizes (on a single street) and their estimated repair cost pothole_radiuses_m = [0.11, 0.22, 0.31, 0.42, 0.22, 0.15, 0.36, 0.52, 0.44, 0.25, 0.27, 0.64, 0.29, 0.14, 0.16, 0.19, 0.84] number_of_potholes = len(pothole_radiuses_m) initial_area_potholes = pi*(sum([r**2 for r in pothole_radiuses_m])) initial_asphalt_cost = initial_area_potholes * asphalt_cost_m2_dollar all_potholes_inspection_cost = number_of_potholes * avg_pothole_inspection_cost_dollar # Driver behavior related avg_probability_of_passing_through_pothole = 0.4 # Assume that degradation rate of small potholes is much slower than of big ones (independent of vehicle type passing over) passthrough_pothole_size_increase_factor = { 'small': 1.01, 'small-to-medium': 1.05, 'medium': 1.1, 'medium-to-large': 1.2, 'large': 1.4 } # Weather related excessive_heat_days_in_year, rainy_days_in_year, snow_days_in_year = 160, 210, 28 avg_heat_duration_hours, avg_rain_duration_hours, avg_snow_duration_hours = 6, 2.4, 4.2 weather_conditions_pothole_increase_factor = { 'heat': 1.6, 'rain': 1.8, 'snow': 2.35 } # Pothole-to-car damage pothole_to_car_damage_factor = { 'small': 1, 'small-to-medium': 1.4, 'medium': 1.8, 'medium-to-large': 2.6, 'large': 4.8 } # avg_vehicle_weight_kg, avg_speed_through_potholes_kmh, pothole_increase_factor, avg_annual_daily_traffic, avg_suspension_damage_cost, avg_vehicle_age, avg_vehicle_purchase_cost car = Vehicle(2000, 38.6, 1, 31780, 3000, 11.2, 35560) van = Vehicle(4000, 27.8, 2.2, 12110, 5600, 6.7, 68000) truck = Vehicle(8000, 19.8, 4.8, 5800, 12000, 7.8, 155000) current_asphalt_cost = initial_asphalt_cost total_vehicle_damage_cost = all_potholes_inspection_cost day = 0 # Main idea: Assume that when the sum of the delta cost of filling the potholes (after cost - before cost) and the total pothole inspection costs becomes smaller than the cost of the damage incurred, it becomes economically feasible to fill them. while (current_asphalt_cost - initial_asphalt_cost) <= (total_vehicle_damage_cost - all_potholes_inspection_cost): for idx, pothole_radius in enumerate(pothole_radiuses_m): # Determine type of pothole ph_type = pothole_type(pothole_radius) ph_passthrough_factor = passthrough_pothole_size_increase_factor[ph_type] pothole_to_car_damage = pothole_to_car_damage_factor[ph_type] # Add degradation due to driver behavior driver_contribution = (car.avg_speed_through_potholes_m_s + van.avg_speed_through_potholes_m_s + truck.avg_speed_through_potholes_m_s) * avg_probability_of_passing_through_pothole # Add degradation due to vehicle characteristics vehicles_contribution = [] for vehicle in [car, van, truck]: vehicles_contribution.append(vehicle.avg_vehicle_weight_kg/1000 * vehicle.pothole_increase_factor * vehicle.avg_annual_daily_traffic) vehicles_contribution = sum(vehicles_contribution) # Add degradation due to weather weather_contribution = [] for weather_type, yearly_days, daily_duration in zip(['heat', 'rain', 'snow'], [excessive_heat_days_in_year, rainy_days_in_year, snow_days_in_year], [avg_heat_duration_hours, avg_rain_duration_hours, avg_snow_duration_hours]): weather_contribution.append((yearly_days/365) * (daily_duration/24) * weather_conditions_pothole_increase_factor[weather_type]) weather_contribution = sum(weather_contribution) # Add degradation due to pothole characteristics vehicles_passed = sum([vehicle.avg_annual_daily_traffic for vehicle in [car, van, truck]]) pothole_characteristics_contribution = vehicles_passed * ph_passthrough_factor # Update pothole sizes pothole_radiuses_m[idx] += (driver_contribution + vehicles_contribution + weather_contribution + pothole_characteristics_contribution) # Add to vehicle damage cost total_vehicle_dmg_cost = [] for vehicle in [car, van, truck]: total_vehicle_dmg_cost.append((pothole_to_car_damage * vehicle.avg_suspension_damage_cost * vehicle.avg_vehicle_purchase_cost * vehicle.avg_annual_daily_traffic) / vehicle.avg_vehicle_age) total_vehicle_damage_cost += sum(total_vehicle_dmg_cost) current_asphalt_cost = pi*(sum([r**2 for r in pothole_radiuses_m])) day += 1 # Debug #print(current_asphalt_cost - initial_asphalt_cost) #print(total_vehicle_damage_cost - all_potholes_inspection_cost) print('Optimal pothole fill interval: %ddays' % (day)) # Optimal pothole fill interval: 17days

Note: To compute this, a lot of assumptions have been made, so this can serve as a model only. A real-world situation will have different parameters, which may be used and combined in different ways. Yet, a more intensive traffic would necessitate faster pothole repair, since the pothole sizes will grow faster and they will also incur a lot more damage to more cars. Another interesting aspect is that the average vehicle age and value may also influence how frequently the administration chooses to fill the existing potholes.