parameters: ()
docstring: To allow the dropping of orders, we add disjunctions to all the customer
      nodes. Each disjunction is a list of 1 index, which allows that customer to
      be active or not, with a penalty if not. The penalty should be larger
      than the cost of servicing that customer, or it will always be dropped!
docstring_summary: To allow the dropping of orders, we add disjunctions to all the customer
      nodes. Each disjunction is a list of 1 index, which allows that customer to
      be active or not, with a penalty if not. The penalty should be larger
      than the cost of servicing that customer, or it will always be dropped!
docstring_tokens: To allow the dropping of orders we add disjunctions to all the customer nodes . Each disjunction is a list of 1 index which allows that customer to be active or not with a penalty if not . The penalty should be larger than the cost of servicing that customer or it will always be dropped!
function: def main():
      # Create a set of customer, (and depot) stops.
      customers = Customers(
          num_stops=50,
          min_demand=1,
          max_demand=15,
          box_size=40,
          min_tw=3,
          max_tw=6)
  
      # Create a list of inhomgenious vehicle capacities as integer units.
      capacity = [50, 75, 100, 125, 150, 175, 200, 250]
  
      # Create a list of inhomogeneous fixed vehicle costs.
      cost = [int(100 + 2 * np.sqrt(c)) for c in capacity]
  
      # Create a set of vehicles, the number set by the length of capacity.
      vehicles = Vehicles(capacity=capacity, cost=cost)
  
      # check to see that the problem is feasible, if we don't have enough
      # vehicles to cover the demand, there is no point in going further.
      assert (customers.get_total_demand() < vehicles.get_total_capacity())
  
      # Set the starting nodes, and create a callback fn for the starting node.
      start_fn = vehicles.return_starting_callback(
          customers, sameStartFinish=False)
  
      # Create the routing index manager.
      manager = pywrapcp.RoutingIndexManager(
          customers.number,  # int number
          vehicles.number,  # int number
          vehicles.starts,  # List of int start depot
          vehicles.ends)  # List of int end depot
  
      customers.set_manager(manager)
  
      # Set model parameters
      model_parameters = pywrapcp.DefaultRoutingModelParameters()
  
      # The solver parameters can be accessed from the model parameters. For example :
      #   model_parameters.solver_parameters.CopyFrom(
      #       pywrapcp.Solver.DefaultSolverParameters())
      #    model_parameters.solver_parameters.trace_propagation = True
  
      # Make the routing model instance.
      routing = pywrapcp.RoutingModel(manager, model_parameters)
  
      parameters = pywrapcp.DefaultRoutingSearchParameters()
      # Setting first solution heuristic (cheapest addition).
      parameters.first_solution_strategy = (
          routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)
      # Routing: forbids use of TSPOpt neighborhood, (this is the default behaviour)
      parameters.local_search_operators.use_tsp_opt = pywrapcp.BOOL_FALSE
      # Disabling Large Neighborhood Search, (this is the default behaviour)
      parameters.local_search_operators.use_path_lns = pywrapcp.BOOL_FALSE
      parameters.local_search_operators.use_inactive_lns = pywrapcp.BOOL_FALSE
  
      parameters.time_limit.seconds = 10
      parameters.use_full_propagation = True
      #parameters.log_search = True
  
      # Create callback fns for distances, demands, service and transit-times.
      dist_fn = customers.return_dist_callback()
      dist_fn_index = routing.RegisterTransitCallback(dist_fn)
  
      dem_fn = customers.return_dem_callback()
      dem_fn_index = routing.RegisterUnaryTransitCallback(dem_fn)
  
      # Create and register a transit callback.
      serv_time_fn = customers.make_service_time_call_callback()
      transit_time_fn = customers.make_transit_time_callback()
      def tot_time_fn(from_index, to_index):
          """
          The time function we want is both transit time and service time.
          """
          # Convert from routing variable Index to distance matrix NodeIndex.
          from_node = manager.IndexToNode(from_index)
          to_node = manager.IndexToNode(to_index)
          return serv_time_fn(from_node, to_node) + transit_time_fn(from_node, to_node)
  
      tot_time_fn_index = routing.RegisterTransitCallback(tot_time_fn)
  
      # Set the cost function (distance callback) for each arc, homogeneous for
      # all vehicles.
      routing.SetArcCostEvaluatorOfAllVehicles(dist_fn_index)
  
      # Set vehicle costs for each vehicle, not homogeneous.
      for veh in vehicles.vehicles:
          routing.SetFixedCostOfVehicle(veh.cost, int(veh.index))
  
      # Add a dimension for vehicle capacities
      null_capacity_slack = 0
      routing.AddDimensionWithVehicleCapacity(
          dem_fn_index,  # demand callback
          null_capacity_slack,
          capacity,  # capacity array
          True,
          'Capacity')
      # Add a dimension for time and a limit on the total time_horizon
      routing.AddDimension(
          tot_time_fn_index,  # total time function callback
          customers.time_horizon,
          customers.time_horizon,
          True,
          'Time')
  
      time_dimension = routing.GetDimensionOrDie('Time')
      for cust in customers.customers:
          if cust.tw_open is not None:
              time_dimension.CumulVar(manager.NodeToIndex(cust.index)).SetRange(
                  cust.tw_open.seconds, cust.tw_close.seconds)
      """
       To allow the dropping of orders, we add disjunctions to all the customer
      nodes. Each disjunction is a list of 1 index, which allows that customer to
      be active or not, with a penalty if not. The penalty should be larger
      than the cost of servicing that customer, or it will always be dropped!
      """
      # To add disjunctions just to the customers, make a list of non-depots.
      non_depot = set(range(customers.number))
      non_depot.difference_update(vehicles.starts)
      non_depot.difference_update(vehicles.ends)
      penalty = 400000  # The cost for dropping a node from the plan.
      nodes = [routing.AddDisjunction([manager.NodeToIndex(c)], penalty) for c in non_depot]
  
      # This is how you would implement partial routes if you already knew part
      # of a feasible solution for example:
      # partial = np.random.choice(list(non_depot), size=(4,5), replace=False)
  
      # routing.CloseModel()
      # partial_list = [partial[0,:].tolist(),
      #                 partial[1,:].tolist(),
      #                 partial[2,:].tolist(),
      #                 partial[3,:].tolist(),
      #                 [],[],[],[]]
      # print(routing.ApplyLocksToAllVehicles(partial_list, False))
  
      # Solve the problem !
      assignment = routing.SolveWithParameters(parameters)
  
      # The rest is all optional for saving, printing or plotting the solution.
      if assignment:
          ## save the assignment, (Google Protobuf format)
          #save_file_base = os.path.realpath(__file__).split('.')[0]
          #if routing.WriteAssignment(save_file_base + '_assignment.ass'):
          #    print('succesfully wrote assignment to file ' + save_file_base +
          #          '_assignment.ass')
  
          print('The Objective Value is {0}'.format(assignment.ObjectiveValue()))
  
          plan_output, dropped = vehicle_output_string(manager, routing, assignment)
          print(plan_output)
          print('dropped nodes: ' + ', '.join(dropped))
  
          # you could print debug information like this:
          # print(routing.DebugOutputAssignment(assignment, 'Capacity'))
  
          vehicle_routes = {}
          for veh in range(vehicles.number):
              vehicle_routes[veh] = build_vehicle_route(manager, routing, assignment,
                                                        customers, veh)
  
          # Plotting of the routes in matplotlib.
          fig = plt.figure()
          ax = fig.add_subplot(111)
          # Plot all the nodes as black dots.
          clon, clat = zip(*[(c.lon, c.lat) for c in customers.customers])
          ax.plot(clon, clat, 'k.')
          # plot the routes as arrows
          plot_vehicle_routes(vehicle_routes, ax, customers, vehicles)
          plt.show()
  
      else:
          print('No assignment')
function_tokens: def main ( ) : # Create a set of customer, (and depot) stops. customers = Customers ( num_stops = 50 , min_demand = 1 , max_demand = 15 , box_size = 40 , min_tw = 3 , max_tw = 6 ) # Create a list of inhomgenious vehicle capacities as integer units. capacity = [ 50 , 75 , 100 , 125 , 150 , 175 , 200 , 250 ] # Create a list of inhomogeneous fixed vehicle costs. cost = [ int ( 100 + 2 * np . sqrt ( c ) ) for c in capacity ] # Create a set of vehicles, the number set by the length of capacity. vehicles = Vehicles ( capacity = capacity , cost = cost ) # check to see that the problem is feasible, if we don't have enough # vehicles to cover the demand, there is no point in going further. assert ( customers . get_total_demand ( ) < vehicles . get_total_capacity ( ) ) # Set the starting nodes, and create a callback fn for the starting node. start_fn = vehicles . return_starting_callback ( customers , sameStartFinish = False ) # Create the routing index manager. manager = pywrapcp . RoutingIndexManager ( customers . number , # int number vehicles . number , # int number vehicles . starts , # List of int start depot vehicles . ends ) # List of int end depot customers . set_manager ( manager ) # Set model parameters model_parameters = pywrapcp . DefaultRoutingModelParameters ( ) # The solver parameters can be accessed from the model parameters. For example : #   model_parameters.solver_parameters.CopyFrom( #       pywrapcp.Solver.DefaultSolverParameters()) #    model_parameters.solver_parameters.trace_propagation = True # Make the routing model instance. routing = pywrapcp . RoutingModel ( manager , model_parameters ) parameters = pywrapcp . DefaultRoutingSearchParameters ( ) # Setting first solution heuristic (cheapest addition). parameters . first_solution_strategy = ( routing_enums_pb2 . FirstSolutionStrategy . PATH_CHEAPEST_ARC ) # Routing: forbids use of TSPOpt neighborhood, (this is the default behaviour) parameters . local_search_operators . use_tsp_opt = pywrapcp . BOOL_FALSE # Disabling Large Neighborhood Search, (this is the default behaviour) parameters . local_search_operators . use_path_lns = pywrapcp . BOOL_FALSE parameters . local_search_operators . use_inactive_lns = pywrapcp . BOOL_FALSE parameters . time_limit . seconds = 10 parameters . use_full_propagation = True #parameters.log_search = True # Create callback fns for distances, demands, service and transit-times. dist_fn = customers . return_dist_callback ( ) dist_fn_index = routing . RegisterTransitCallback ( dist_fn ) dem_fn = customers . return_dem_callback ( ) dem_fn_index = routing . RegisterUnaryTransitCallback ( dem_fn ) # Create and register a transit callback. serv_time_fn = customers . make_service_time_call_callback ( ) transit_time_fn = customers . make_transit_time_callback ( ) def tot_time_fn ( from_index , to_index ) : """
          The time function we want is both transit time and service time.
          """ # Convert from routing variable Index to distance matrix NodeIndex. from_node = manager . IndexToNode ( from_index ) to_node = manager . IndexToNode ( to_index ) return serv_time_fn ( from_node , to_node ) + transit_time_fn ( from_node , to_node ) tot_time_fn_index = routing . RegisterTransitCallback ( tot_time_fn ) # Set the cost function (distance callback) for each arc, homogeneous for # all vehicles. routing . SetArcCostEvaluatorOfAllVehicles ( dist_fn_index ) # Set vehicle costs for each vehicle, not homogeneous. for veh in vehicles . vehicles : routing . SetFixedCostOfVehicle ( veh . cost , int ( veh . index ) ) # Add a dimension for vehicle capacities null_capacity_slack = 0 routing . AddDimensionWithVehicleCapacity ( dem_fn_index , # demand callback null_capacity_slack , capacity , # capacity array True , 'Capacity' ) # Add a dimension for time and a limit on the total time_horizon routing . AddDimension ( tot_time_fn_index , # total time function callback customers . time_horizon , customers . time_horizon , True , 'Time' ) time_dimension = routing . GetDimensionOrDie ( 'Time' ) for cust in customers . customers : if cust . tw_open is not None : time_dimension . CumulVar ( manager . NodeToIndex ( cust . index ) ) . SetRange ( cust . tw_open . seconds , cust . tw_close . seconds ) # To add disjunctions just to the customers, make a list of non-depots. non_depot = set ( range ( customers . number ) ) non_depot . difference_update ( vehicles . starts ) non_depot . difference_update ( vehicles . ends ) penalty = 400000 # The cost for dropping a node from the plan. nodes = [ routing . AddDisjunction ( [ manager . NodeToIndex ( c ) ] , penalty ) for c in non_depot ] # This is how you would implement partial routes if you already knew part # of a feasible solution for example: # partial = np.random.choice(list(non_depot), size=(4,5), replace=False) # routing.CloseModel() # partial_list = [partial[0,:].tolist(), #                 partial[1,:].tolist(), #                 partial[2,:].tolist(), #                 partial[3,:].tolist(), #                 [],[],[],[]] # print(routing.ApplyLocksToAllVehicles(partial_list, False)) # Solve the problem ! assignment = routing . SolveWithParameters ( parameters ) # The rest is all optional for saving, printing or plotting the solution. if assignment : ## save the assignment, (Google Protobuf format) #save_file_base = os.path.realpath(__file__).split('.')[0] #if routing.WriteAssignment(save_file_base + '_assignment.ass'): #    print('succesfully wrote assignment to file ' + save_file_base + #          '_assignment.ass') print ( 'The Objective Value is {0}' . format ( assignment . ObjectiveValue ( ) ) ) plan_output , dropped = vehicle_output_string ( manager , routing , assignment ) print ( plan_output ) print ( 'dropped nodes: ' + ', ' . join ( dropped ) ) # you could print debug information like this: # print(routing.DebugOutputAssignment(assignment, 'Capacity')) vehicle_routes = { } for veh in range ( vehicles . number ) : vehicle_routes [ veh ] = build_vehicle_route ( manager , routing , assignment , customers , veh ) # Plotting of the routes in matplotlib. fig = plt . figure ( ) ax = fig . add_subplot ( 111 ) # Plot all the nodes as black dots. clon , clat = zip ( * [ ( c . lon , c . lat ) for c in customers . customers ] ) ax . plot ( clon , clat , 'k.' ) # plot the routes as arrows plot_vehicle_routes ( vehicle_routes , ax , customers , vehicles ) plt . show ( ) else : print ( 'No assignment' )