示例#1
0
def draw_route_graph(
    data: dict,
    routing: RoutingModel,
    manager: RoutingIndexManager,
    assignment: Assignment,
    filename: str = 'route.png',
    prog='sfdp',
) -> None:
    """
    Draw a route graph based on the solution of the problem.
    """

    weights = data['weights']
    demands = data['demands']
    time_windows = data['time_windows']
    graph = pgv.AGraph(directed=True)

    def _node(index: int) -> str:
        if index == 0:
            return f'{index}\nDepot'
        return f'{index}\nDemand: {demands[index]}\nRange: {time_windows[index]}'

    for vehicle_id in range(data['num_vehicles']):
        index = routing.Start(vehicle_id)
        while not routing.IsEnd(index):
            node_index = manager.IndexToNode(index)
            next_index = assignment.Value(routing.NextVar(index))
            next_node_index = manager.IndexToNode(next_index)
            weight = weights[node_index][next_node_index]
            graph.add_edge(_node(node_index), _node(next_node_index), weight=weight, label=weight)
            index = next_index

    graph.draw(filename, prog=prog)

    print(f'The route graph has been saved to {filename}.')
示例#2
0
    def _set_capacity_dimension_constraints(
            self, data: VehicleRoutingProblemInstance, routing: RoutingModel,
            manager: RoutingIndexManager):

        if data.courier_capacities is None:
            return

        def demand_callback(index):
            node = manager.IndexToNode(index)
            return data.node_demands[node]

        capacity_callback = routing.RegisterUnaryTransitCallback(
            demand_callback)

        routing.AddDimensionWithVehicleCapacity(
            capacity_callback,
            0,  # waiting time
            data.courier_capacities,  # maximum distance per vehicle
            False,  # Force start cumul to zero.
            self.CAPACITY_DIMENSION_NAME)

        capacity_dimension = routing.GetDimensionOrDie(
            self.CAPACITY_DIMENSION_NAME)

        for courier_idx, start_utilization in enumerate(
                data.start_utilizations):
            node_idx = routing.Start(courier_idx)
            self._set_constraint_on_var(
                node_idx,
                TimeWindowConstraint(node=node_idx,
                                     is_hard=True,
                                     from_time=start_utilization,
                                     to_time=start_utilization),
                capacity_dimension)
示例#3
0
def print_solution(
    data: dict,
    routing: RoutingModel,
    manager: RoutingIndexManager,
    assignment: Assignment,
) -> None:
    """
    Print the solution.
    """

    capacity_dimension = routing.GetDimensionOrDie('Capacity')
    time_dimension = routing.GetDimensionOrDie('Time')
    total_time = 0

    for vehicle_id in range(data['num_vehicles']):
        index = routing.Start(vehicle_id)
        node_props = []

        while not routing.IsEnd(index):
            props = node_properties(manager, assignment, capacity_dimension, time_dimension, index)
            node_props.append(props)
            index = assignment.Value(routing.NextVar(index))

        props = node_properties(manager, assignment, capacity_dimension, time_dimension, index)
        node_props.append(props)
        route_time = assignment.Value(time_dimension.CumulVar(index))
        route = "\n  -> ".join(['[Node %2s: Load(%s) Time(%2s, %s)]' % prop for prop in node_props])
        plan_output = (f'Route for vehicle {vehicle_id}:\n  {route}\n'
                       f'Load of the route: {props[1]}\nTime of the route: {route_time} min\n')
        print(plan_output)

        total_time += route_time

    print(f'Total time of all routes: {total_time} min')
示例#4
0
    def print_solution(data: VehicleRoutingProblemInstance,
                       manager: RoutingIndexManager, routing: RoutingModel,
                       solution: Assignment):
        """Prints assignment on console."""
        time_dimension = routing.GetDimensionOrDie('Duration')
        total_time = 0
        for vehicle_id in range(data.num_plans_to_create):
            start_time = None
            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)
                if start_time is None:
                    start_time = solution.Min(time_var)
                plan_output += '{0} Time({1},{2}) -> '.format(
                    manager.IndexToNode(index), solution.Min(time_var),
                    solution.Max(time_var))
                index = solution.Value(routing.NextVar(index))
            time_var = time_dimension.CumulVar(index)
            plan_output += '{0} Time({1},{2})\n'.format(
                manager.IndexToNode(index), solution.Min(time_var),
                solution.Max(time_var))
            plan_output += f'Start of the route: {start_time}\n'
            plan_output += 'Time of the route: {} sec\n'.format(
                solution.Min(time_var) - start_time)
            print(plan_output)

            total_time += solution.Min(time_var) - start_time
        print('Total time of all routes: {} sec'.format(total_time))
示例#5
0
文件: cvrp.py 项目: anhpngt/chariots
    def from_cvrp_solution(cls, data_model: DataModel,
                           manager: pywrapcp.RoutingIndexManager,
                           routing: pywrapcp.RoutingModel,
                           assignment) -> 'Optional[List[VehicleRoute]]':
        if not assignment:
            return None

        res = []  # type: List[VehicleRoute]
        for vehicle_id in range(data_model.vehicle_number):
            index = routing.Start(vehicle_id)
            route_indices = []  # type: List[int]
            route_distance = 0  # float
            route_load = 0  # float

            while not routing.IsEnd(index):
                node_index = manager.IndexToNode(index)
                route_indices.append(node_index)
                route_load += data_model.demands[node_index]

                previous_index = index
                index = assignment.Value(routing.NextVar(index))
                route_distance += routing.GetArcCostForVehicle(
                    previous_index, index, vehicle_id)

            route_indices.append(0)  # returns to depot
            res.append(
                cls(data_model, vehicle_id, route_indices, route_distance,
                    route_load))

        current_app.logger.debug('CVRP Solution:\n{res}')
        return res
    def apply(self, manager:  pywrapcp.RoutingModel, routing: pywrapcp.RoutingModel, data_model: DataModel):
        def distance_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_model.distance_matrix[from_node][to_node]

        transit_callback_index = routing.RegisterTransitCallback(distance_callback)
        routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)

        dimension_name = 'Distance'
        routing.AddDimension(
            transit_callback_index,
            0,  # no slack
            3000,  # vehicle maximum travel distance
            True,  # start cumul to zero
            dimension_name)
        distance_dimension = routing.GetDimensionOrDie(dimension_name)
        distance_dimension.SetGlobalSpanCostCoefficient(100)

        for i in range(data_model.number_of_engineers):
            routing.AddVariableMinimizedByFinalizer(
                distance_dimension.CumulVar(routing.Start(i)))
            routing.AddVariableMinimizedByFinalizer(
                distance_dimension.CumulVar(routing.End(i)))

        return routing
示例#7
0
def print_solution(
	data: dict,
	routing: RoutingModel,
	manager: RoutingIndexManager,
	assignment: Assignment,
) -> None:
	capacity_dimension = routing.GetDimensionOrDie('Capacity')
	time_dimension = None
	total_cost = 0
	if 'time_windows' in data.keys():
		time_dimension = routing.GetDimensionOrDie('Time')
		total_time = 0

	for vehicle_id in range(data['num_vehicles']):
		index = routing.Start(vehicle_id)
		node_props = []

		while not routing.IsEnd(index):
			props = node_properties(data, manager, assignment, capacity_dimension, time_dimension, index)
			node_props.append(props)
			index = assignment.Value(routing.NextVar(index))

		props = node_properties(data, manager, assignment, capacity_dimension, time_dimension, index)
		node_props.append(props)

		# arc weight
		cost = 0 
		node_indexes = [prop[0] for prop in node_props]
		for i in range(len(node_indexes)-1):
			idx_from = node_indexes[i]
			idx_to = node_indexes[i+1]
			cost += data['dist_mat'][idx_from][idx_to]
		total_cost += cost

		if 'time_windows' in data.keys():
			route_time = assignment.Value(time_dimension.CumulVar(index))
			route = "\n  -> ".join(['[Node %2s(%s)TW(%2s, %2s): Vehicle Load(%2s) and Arrived(%2s)]' % prop for prop in node_props])
			plan_output = (f'Route for vehicle {vehicle_id}:\n     {route}\n'
						   f'Cost: {cost}\nLoad: {props[-1]}\nTime: {route_time} min\n')
			print(plan_output)

			total_time += route_time
		else:
			route = "\n  -> ".join(['[Node %2s(%s): Vehicle Load(%2s)]' % prop for prop in node_props])
			plan_output = (f'Route for vehicle {vehicle_id}:\n     {route}\n'
						   f'Cost: {cost}\nLoad: {props[-1]}\n')
			print(plan_output)

	print(f'Total cost of all routes: {total_cost}\n')
	return total_cost
	if 'time_windows' in data.keys():
		print('*** format ***: \n[Node node_index(demand)TW(Time Window min, max): Vehicle Load(accumulated load) and Arrived(time)]')
		print(f'Total time of all routes: {total_time} min')
示例#8
0
    def _set_time_dimension_constraints(
            self, routing: RoutingModel, manager: RoutingIndexManager,
            dimension_name: str,
            start_time_windows: List[TimeWindowConstraint],
            node_time_windows: List[TimeWindowConstraint],
            num_plans_to_create: int):

        # ========= TIME WINDOW =========
        time_dimension = routing.GetDimensionOrDie(dimension_name)
        for constraint in start_time_windows:
            index = routing.Start(constraint.node)
            self._set_constraint_on_var(index, constraint, time_dimension)

        for constraint in node_time_windows:
            index = manager.NodeToIndex(constraint.node)
            self._set_constraint_on_var(index, constraint, time_dimension)

        # Instantiate route start and end times to produce feasible times.
        for i in range(num_plans_to_create):
            routing.AddVariableMinimizedByFinalizer(
                time_dimension.CumulVar(routing.Start(i)))
            routing.AddVariableMinimizedByFinalizer(
                time_dimension.CumulVar(routing.End(i)))
示例#9
0
def print_solution(data: dict, routing: pywrapcp.RoutingModel,
                   assignment: pywrapcp.Assignment):
    """
	Print routes on console.
	"""
    capacity_dimension = routing.GetDimensionOrDie('Capacity')
    time_dimension = routing.GetDimensionOrDie('Time')
    total_time = 0
    d = {}
    r = []

    for vehicle_id in range(data['num_vehicles']):
        index = routing.Start(vehicle_id)
        node_props = []

        while not routing.IsEnd(index):
            props = node_properties(routing, assignment, capacity_dimension,
                                    time_dimension, index)
            node_props.append(props)
            index = assignment.Value(routing.NextVar(index))

        props = node_properties(routing, assignment, capacity_dimension,
                                time_dimension, index)
        node_props.append(props)
        route_time = assignment.Value(time_dimension.CumulVar(index))
        route = "\n  -> ".join(['[Node %2s: Load(%s) Time(%2s, %s)]' % prop \
              for prop in node_props])
        plan_output = f'Route for vehicle {vehicle_id}:\n  {route}\n' + \
         f'Load of the route: {props[1]}\nTime of the route: {route_time} min\n'

        # print(plan_output)

        #convert to dict
        ddd = []
        for node in node_props:
            dd = {"node": node[0], "load": node[1], "time": [node[2], node[3]]}
            ddd.append(dd)
        r.append({
            "vehicle_id": vehicle_id,
            "route": ddd,
            "total_time": route_time,
            "load": len(ddd) - 2
        })

        total_time += route_time
    d['solver'] = r
    d['total_time'] = total_time
    # print(f'Total time of all routes: {total_time} min')
    return d
示例#10
0
    def _extract_solution(self, assignment: Assignment, vrp_instance: VehicleRoutingProblemInstance,
                          manager: RoutingIndexManager, routing: RoutingModel) \
            -> VehicleRoutingProblemSolution:
        routes = []
        etas = []
        etds = []

        time_dimension = routing.GetDimensionOrDie(
            self.DURATION_DIMENSION_NAME)
        for vehicle_id in range(vrp_instance.num_plans_to_create):
            index = routing.Start(vehicle_id)

            route = []
            route_etas = []
            route_etds = []

            while not routing.IsEnd(index):
                node = manager.IndexToNode(index)

                if node in vrp_instance.pickup_nodes:
                    this_event_time = vrp_instance.pickup_service_time
                elif node in vrp_instance.drop_nodes:
                    this_event_time = vrp_instance.drop_service_time
                else:
                    this_event_time = 0

                time_var = time_dimension.CumulVar(index)
                eta = assignment.Min(time_var)
                etd = assignment.Max(time_var) + this_event_time

                route.append(node)
                route_etas.append(eta)
                route_etds.append(etd)

                index = assignment.Value(routing.NextVar(index))

            routes.append(route)
            etas.append(route_etas)
            etds.append(route_etds)

        ret = VehicleRoutingProblemSolution(plans=routes, etas=etas, etds=etds)
        return ret
示例#11
0
    def _extract_solution(self, manager: RoutingIndexManager,
                          routing: RoutingModel, assignment: Assignment,
                          indices_to_visit: List[int]) -> Dict[str, Any]:
        """Transform results to a usable format

        Parameters
        ----------
        manager : RoutingIndexManager
            OR-tools' object to manage conversion between NodeIndex and variable index
        routing : RoutingModel
            OR-tools' object for route solving
        assignment : Assignment
            OR-tools' object for mapping from variable to domains
        indices_to_visit : List[int]
            The list of indices corresponding to the desired facilities to visit        

        Returns
        -------
        Dict[str, Any]
            With keys:
            - 'objective', set to objective value (minified distance)
            - 'order', instructions for the order of facilities to visit

        """
        sln = {"objective": assignment.ObjectiveValue()}

        stop_indices = []
        index = routing.Start(0)
        while not routing.IsEnd(index):
            relative_index = manager.IndexToNode(index)
            stop_indices.append(indices_to_visit[relative_index])
            previous_index = index
            index = assignment.Value(routing.NextVar(index))
        relative_index = manager.IndexToNode(index)
        stop_indices.append(indices_to_visit[relative_index])
        sln["order"] = stop_indices
        return sln