#Times in seconds
# Create the data.
planning_horizon=24*60*60
data = create_data_array(planning_horizon)
locations = data[0]
demands = data[1]
start_times = data[2]
num_locations = len(locations)
depots=len(df_depots)
num_vehicles_perdepot=10
num_vehicles = num_vehicles_perdepot*depots #Per depot
#additional_vehicle_cost=1882 #meters-worth
cost_per_km=1.7 #dollars
search_time_limit = 300*1000 #milliseconds -> 5 minutes
# Create routing model.
if num_locations > 0:
# The number of nodes of the VRP is num_locations.
# Nodes are indexed from 0 to tsp_size - 1. By default the start of
# a route is node 0.
vehicle_depots=[locations.iloc[x]['objectid'] for x in xrange(0,depots)for y in xrange(0,num_vehicles_perdepot)]
routing = pywrapcp.RoutingModel(num_locations, num_vehicles,
[x for x in xrange(0,depots)\
for y in xrange(0,num_vehicles_perdepot)],
[x for x in xrange(0,depots)\
for y in xrange(0,num_vehicles_perdepot)])
search_parameters = pywrapcp.RoutingModel.DefaultSearchParameters()
search_parameters.time_limit_ms = search_time_limit
#search_parameters.log_search = True
# Set first solution heuristic: the
# method for finding a first solution to the problem.
search_parameters.first_solution_strategy = (
routing_enums_pb2.FirstSolutionStrategy.GLOBAL_CHEAPEST_ARC)
#FirstSolutionStrategy.PATH_CHEAPEST_ARC
# The 'PATH_CHEAPEST_ARC' method does the following:
# Starting from a route "start" node, connect it to the node which produces the
# cheapest route segment, then extend the route by iterating on the last
# node added to the route.
# Put callbacks to the distance function here.
dist_between_locations = CreateDistanceCallback(locations)
dist_callback = dist_between_locations.Distance
routing.SetArcCostEvaluatorOfAllVehicles(dist_callback)
demands_at_locations = CreateDemandCallback(demands)
demands_callback = demands_at_locations.Demand
# Add capacity dimension constraints.
vehicle_capacity = 50000;
null_capacity_slack = 0;
fix_start_cumul_to_zero = True
capacity = "Capacity"
#routing.AddDimension(demands_callback, null_capacity_slack, vehicle_capacity,
# fix_start_cumul_to_zero, capacity)
# Adding time dimension constraints.
#time_per_demand_unit = 5 * 60 # 5 minutes for pickup
horizon = planning_horizon #Set maximum time for any.
time = "Time"
#tw_duration = 30 * 60 # 30 minutes
speed = 70*1000/(60.0*60) # meter/ second
service_times = CreateServiceTimeCallback(demands, speed)
service_time_callback = service_times.ServiceTime
total_times = CreateTotalTimeCallback(service_time_callback, dist_callback, speed)
total_time_callback = total_times.TotalTime
# Note: In this case fix_start_cumul_to_zero is set to False,
# because some vehicles start their routes after time 0, due to resource constraints.
# Add a dimension for time and a limit on the total time_horizon
fix_start_cumul_to_zero = False
routing.AddDimension(total_time_callback, # total time function callback
horizon,
horizon,
fix_start_cumul_to_zero,
time)
time_dimension = routing.GetDimensionOrDie("Time")
#for order in range(1, num_locations):
# start = start_times[order]
# time_dimension.CumulVar(order).SetRange(start, start + tw_duration)
print "here- disjunction"
# Add disjunction - Support reverse nodes
for item in locations[~locations.objectid.isin(df_depots.objectid.unique())].drop_duplicates('objectid').index:
obj_id=locations.loc[item]['objectid']
print locations[locations.objectid==obj_id].index.tolist()
routing.AddDisjunction(locations[locations.objectid==obj_id].index.tolist())
# Solve, displays a solution if any.
assignment = routing.SolveWithParameters(search_parameters)
#Print solution
if assignment:
#prepare DataFrame output
locations['Route_Depot']=''
locations['Route_Number']=0
# Solution distance.
#Not distance exactly given the cost of adding new vehicles is taken as a distance metric
#print "Total distance of all routes: {:,.2f} km\n".format(assignment.ObjectiveValue()/1000.0)
print "Total cost of all routes: ${:,.2f}".format(cost_per_km*assignment.ObjectiveValue()/1000.0)
print "Does not factor in cost of additional passengers ($0.70 each)\n"
# Display solution.
#capacity_dimension = routing.GetDimensionOrDie(capacity);
time_dimension = routing.GetDimensionOrDie(time);
for vehicle_nbr in range(num_vehicles):
index = routing.Start(int(vehicle_nbr))
plan_output = 'Route {0}:'.format(vehicle_nbr)
while not routing.IsEnd(index):
node_index = routing.IndexToNode(index)
#load_var = capacity_dimension.CumulVar(index)
time_var = time_dimension.CumulVar(index)
plan_output += \
" \n{node_index} StartTime({tmin}) ServTime {serv_time}s-> ".format(
node_index=node_index, #locations.iloc[node_index]['objectid'],
tmin=str(assignment.Value(time_var)),
serv_time=service_times.ServiceTime(node_index))
#For every point except route start
if not routing.IsStart(index):
locations.set_value(node_index,'Route_Depot',vehicle_depots[vehicle_nbr])
locations.set_value(node_index,'Route_Number',vehicle_nbr)
index = assignment.Value(routing.NextVar(index))
node_index = routing.IndexToNode(index) # Convert index to node
#load_var = capacity_dimension.CumulVar(index)
time_var = time_dimension.CumulVar(index)
plan_output += \
" \n{node_index} StartTime({tmin}) ServTime {serv_time}s".format(
node_index=node_index, #locations.iloc[node_index]['objectid'],
tmin=str(assignment.Value(time_var)),
serv_time=service_times.ServiceTime(node_index))
#print plan_output
#print "\n"