title: Vehicle routing problem with time windows at different start and end depot
body: <p>I am trying to write a trip planner for which I am using Google's ORtools. The problem that I am trying to solve is that each vehicle has a different start and end depot and all the services have a different start and end time. Even the depots have a different start and end time, which need to be added as a constraint. I have been following there two examples from google's documentation: </p>
  
  <ul>
  <li><a href="https://developers.google.com/optimization/routing/routing_tasks" rel="nofollow noreferrer">https://developers.google.com/optimization/routing/routing_tasks</a> and </li>
  <li><a href="https://developers.google.com/optimization/routing/vrptw" rel="nofollow noreferrer">https://developers.google.com/optimization/routing/vrptw</a> </li>
  </ul>
  
  <p>I have scoured through all of documentations that are available for ortools, but have not been able to find a reason as to why this error is occurring. According to the documentation, what I am trying to do is possible and the code that I have written should give a correct result. </p>
  
  <p>Here is a sample code of what I am doing:</p>
  
  <pre><code>"""Simple Vehicles Routing Problem."""
  
  from __future__ import print_function
  from ortools.constraint_solver import routing_enums_pb2
  from ortools.constraint_solver import pywrapcp
  
  
  def create_data_model():
      """Stores the data for the problem."""
      data = {}
      data['time_matrix'] = [
          [0, 6, 7, 9, 7, 3, 6, 2, 3, 2, 6, 6, 4, 4, 5, 9, 7, 0],
          [6, 0, 8, 3, 2, 6, 8, 4, 8, 8, 13, 7, 5, 8, 12, 12, 14, 6],
          [7, 8, 0, 11, 10, 6, 3, 9, 5, 8, 4, 15, 14, 13, 9, 18, 9, 15],
          [9, 3, 11, 0, 3, 7, 10, 6, 10, 10, 14, 6, 7, 9, 14, 6, 16, 14],
          [7, 2, 10, 3, 0, 6, 9, 4, 8, 9, 13, 4, 6, 8, 12, 8, 14, 9],
          [3, 6, 6, 7, 6, 0, 2, 8, 2, 2, 7, 9, 7, 7, 6, 12, 8, 3],
          [6, 8, 3, 10, 9, 2, 0, 6, 2, 5, 4, 12, 10, 10, 6, 11, 5, 10],
          [2, 4, 9, 6, 4, 8, 6, 0, 4, 4, 8, 5, 4, 13, 7, 8, 10, 12],
          [3, 8, 5, 10, 8, 2, 2, 4, 0, 3, 4, 9, 8, 7, 3, 13, 6, 5],
          [2, 8, 8, 10, 9, 2, 5, 4, 3, 0, 4, 6, 5, 4, 3, 9, 5, 8],
          [6, 13, 4, 14, 13, 7, 4, 8, 4, 4, 0, 10, 9, 8, 4, 13, 4, 9],
          [6, 7, 15, 6, 4, 9, 12, 5, 9, 6, 10, 0, 1, 3, 7, 13, 10, 11],
          [4, 5, 14, 7, 6, 7, 10, 4, 8, 5, 9, 1, 0, 2, 16, 4, 8, 1],
          [4, 8, 13, 9, 8, 7, 10, 13, 7, 4, 8, 3, 2, 0, 4, 5, 6, 2],
          [5, 12, 9, 14, 12, 6, 6, 7, 3, 3, 4, 7, 16, 4, 0, 9, 12, 4],
          [9, 12, 18, 6, 8, 12, 11, 8, 13, 9, 13, 13, 4, 5, 9, 0, 9, 10],
          [7, 14, 9, 16, 14, 8, 5, 10, 6, 5, 4, 10, 8, 6, 12, 9, 0, 13],
          [0, 6, 15, 14, 9, 3, 10, 12, 5, 8, 9, 11, 1, 2, 4, 10, 13, 0]
      ]
      data['time_windows'] = [
          (0, 22),  # depot
          (7, 12),  # 1
          (10, 15),  # 2
          (6, 8),  # 3
          (10, 13),  # 4
          (0, 5),  # 5
          (5, 10),  # 6
          (0, 4),  # 7
          (5, 7),  # 8
          (0, 3),  # 9
          (10, 16),  # 10
          (10, 15),  # 11
          (0, 9),  # 12
          (5, 10),  # 13
          (7, 10),  # 14
          (10, 15),  # 15
          (11, 15),  # 16
          (18, 25)  # 17
      ]
      data['num_days'] = 3
      data['start'] = [0,0,0]#, 0, 0, 0]  # ,17,0,17]
      data['end'] = [17,17,17]#, 17, 17, 17]
      return data
  
  def print_solution(data, manager, routing, assignment):
      # prints the final routing solution on the console
      time_dimension = routing.GetDimensionOrDie('Time')
      total_time = 0
      for vehicle_id in range(data['num_days']):
          index = routing.Start(vehicle_id)
          plan_output = 'Route for vehicle {}:\n'.format(vehicle_id)
          while not routing.IsEnd(index):
              time_var = time_dimension.CumulVar(index)
              plan_output += '{0} Time({1},{2}) -&gt; '.format(
                  manager.IndexToNode(index), assignment.Min(time_var),
                  assignment.Max(time_var))
              index = assignment.Value(routing.NextVar(index))
          time_var = time_dimension.CumulVar(index)
          plan_output += '{0} Time({1},{2})\n'.format(
              manager.IndexToNode(index), assignment.Min(time_var),
              assignment.Max(time_var))
          plan_output += 'Time of the route: {}min\n'.format(
              assignment.Min(time_var))
          print(plan_output)
          total_time += assignment.Min(time_var)
      print('Total time of all routes: {}min'.format(total_time))
  
  
  def main():
      """Entry point of the program."""
      # Instantiate the data problem.
      data = create_data_model()
  
      # Create the routing index manager.
      manager = pywrapcp.RoutingIndexManager(len(data['time_matrix']), data['num_days'], data['start'], data['end'])
  
      # Create Routing Model.
      routing = pywrapcp.RoutingModel(manager)
  
  
      # Create and register a transit callback.
      def time_callback(from_index, to_index):
          """Returns the distance between the two nodes."""
          # Convert from routing variable Index to distance matrix NodeIndex.
          from_node = manager.IndexToNode(from_index)
          to_node = manager.IndexToNode(to_index)
          return data['time_matrix'][from_node][to_node]
  
      transit_callback_index = routing.RegisterTransitCallback(time_callback)
  
      # Define cost of each arc.
      routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)
  
      # Add time constraint.
      dimension_name = 'time'
      routing.AddDimension(
          transit_callback_index,
          30,  # no slack
          1000000000,  # vehicle maximum travel distance
          False,  # start cumul to zero
          dimension_name)
      time_dimension = routing.GetDimensionOrDie(dimension_name)
      # add time window constraints
      for location_idx, time_window in enumerate(data['time_windows']):
          if location_idx == 17 or location_idx == 0:
              continue
          index = manager.NodeToIndex(location_idx)
          time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1])
      # Add time window constraints for each vehicle start node.
      for vehicle_id in range(data['num_days']):
          index = routing.Start(vehicle_id)
          end_index = routing.End(vehicle_id)
          print(end_index)
          time_dimension.CumulVar(index).SetRange(data['time_windows'][0][0],
                                                  data['time_windows'][0][1])
          time_dimension.CumulVar(end_index).SetRange(data['time_windows'][17][0],
                                                      data['time_windows'][17][1])
  
      for i in range(data['num_days']):
          routing.AddVariableMinimizedByFinalizer(time_dimension.CumulVar(routing.Start(i)))
          routing.AddVariableMinimizedByFinalizer(time_dimension.CumulVar(routing.End(i)))
  
      time_dimension.SetSpanCostCoefficientForAllVehicles(200)
  
      # Setting first solution heuristic.
      search_parameters = pywrapcp.DefaultRoutingSearchParameters()
      search_parameters.first_solution_strategy = (
          routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)
  
      # Solve the problem.
      solution = routing.SolveWithParameters(search_parameters)
      print(solution)
      # Print solution on console.
      if solution:
          print_solution(data, manager, routing, solution)
  
  
  if __name__ == '__main__':
      main()
  </code></pre>
  
  <p>Every time I run the code for more than 2 vehicles this is the error that I am getting:</p>
  
  <pre><code>RuntimeError: SWIG std::function invocation failed.
  
  The above exception was the direct cause of the following exception:
  
  Traceback (most recent call last):
    File "/Users/travelapp/PycharmProjects/TravelApp/venv/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py", line 2136, in &lt;lambda&gt;
      __setattr__ = lambda self, name, value: _swig_setattr(self, Assignment, name, value)
    File "/Users/travelapp/PycharmProjects/TravelApp/venv/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py", line 71, in _swig_setattr
      return _swig_setattr_nondynamic(self, class_type, name, value, 0)
    File "/Users/travelapp/PycharmProjects/TravelApp/venv/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py", line 55, in _swig_setattr_nondynamic
      if type(value).__name__ == 'SwigPyObject':
  SystemError: &lt;class 'type'&gt; returned a result with an error set
  
  The above exception was the direct cause of the following exception:
  
  Traceback (most recent call last):
    File "/Users/travelapp/Library/Preferences/PyCharmCE2019.1/scratches/scratch.py", line 150, in &lt;module&gt;
      main()
    File "/Users/travelapp/Library/Preferences/PyCharmCE2019.1/scratches/scratch.py", line 142, in main
      solution = routing.SolveWithParameters(search_parameters)
    File "/Users/travelapp/PycharmProjects/TravelApp/venv/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py", line 3464, in SolveWithParameters
      return _pywrapcp.RoutingModel_SolveWithParameters(self, search_parameters, solutions)
  SystemError: &lt;built-in function RoutingModel_SolveWithParameters&gt; returned a result with an error set
  </code></pre>
  
  <p>For 1 or 2 vehicles I am getting <code>None</code> as the solution. This may be due to infeasibility of a trip for 2 vehicles.</p>