Ejemplo n.º 1
0
def main():
    """Solve the CVRP problem."""
    # Instantiate the data problem.
    data = create_data_model()
    # compute_geometry.load_config()
    
    # use specified demand factor
    demand_factor_range = [input_data["options"]["demand_factor"]]
    print("using default demand factor: ", list(demand_factor_range))

    geometry.init_random(False)

    for i_df, df in enumerate(demand_factor_range):
        data['demands'] = [int(d) * df
                           for d in input_data["demands"]]
        routes_vect = []
       
        data['distance_matrix'] = compute_geometry.compute_distance_matrix_wrapper()


        # Create the routing index manager.
        # manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),
        #                                        data['num_vehicles'], data['depot'])

        manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),
                                                data['num_vehicles'], data['starts'],
                                                data['ends'])

        # Create Routing Model.
        routing = pywrapcp.RoutingModel(manager)

        # Create and register a transit callback.

        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['distance_matrix'][from_node][to_node]

        transit_callback_index = routing.RegisterTransitCallback(
            distance_callback)

        # Define cost of each arc.
        routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)

        # Add Capacity constraint.

        def demand_callback(from_index):
            """Returns the demand of the node."""
            # Convert from routing variable Index to demands NodeIndex.
            from_node = manager.IndexToNode(from_index)
            return data['demands'][from_node]

        demand_callback_index = routing.RegisterUnaryTransitCallback(
            demand_callback)

        routing.AddDimensionWithVehicleCapacity(
            demand_callback_index,
            0,  # null capacity slack
            data['vehicle_capacities'],  # vehicle maximum capacities
            True,  # start cumul to zero
            'Capacity')

        # Add the maximum distance travel constraint for each vehicle:
        routing.AddDimensionWithVehicleCapacity(
            transit_callback_index,
            0,  # null capacity slack
            # vehicle fuel / max daily/travel distance
            data['vehicle_fuel'],
            True,  # start cumul to zero
            'DailyDistance')

        # Allow to drop nodes.
        penalty = 10000
        for node in range(1, len(data['distance_matrix'])):
            routing.AddDisjunction([manager.NodeToIndex(node)], penalty)

        # Setting first solution heuristic.
        search_parameters = pywrapcp.DefaultRoutingSearchParameters()
        search_parameters.first_solution_strategy = (
            routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)

        # search_parameters.first_solution_strategy = (
        #     routing_enums_pb2.FirstSolutionStrategy.AUTOMATIC)

        search_parameters.local_search_metaheuristic = (
            routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)

        time_limit = 1
        search_parameters.time_limit.FromSeconds(time_limit)

        # Total Distance of all routes: 18041m
        # Total Load of all routes: 47

        print("running solver max time limit: " + str(time_limit))


        print(coords[len(vehicles):])
        print(len(coords[len(vehicles):]))
        print(vehicles)

        # quit()

        # Solve the problem.
        assignment = routing.SolveWithParameters(search_parameters)

        if assignment:
            # Print solution on console.

            routes = plot_routes.print_solution(
                data, manager, routing, assignment)

            print('The Objective Value is {0}'.format(assignment.ObjectiveValue()))

            # you could print debug information like this:
            # print(routing.DebugOutputAssignment(assignment, 'Capacity'))

            vehicle_routes = {}
            for veh in range(len(vehicles)):
                vehicle_routes[veh] = build_vehicle_route(manager, routing, assignment,
                                                        coords, veh)

            print(vehicle_routes)
            # quit()

            # coords[len(vehicles):]
            fig = plotter.plot_vehicle_routes_wrapper(vehicle_routes,coords,data['starts'],data['ends'],0.1)
            fig.savefig("figs/routes.png", dpi=300)
Ejemplo n.º 2
0
def main():
    """Solve the CVRP problem."""
    # Instantiate the data problem.
    data = create_data_model()
    # compute_geometry.load_config()
    n_iter = input_data["options"]["n_iter"]

    if input_data["options"]["use_range"]:
        # use demand factor range
        demand_factor_range = input_data["options"]["demand_factor_range"]
        demand_factor_range = range(demand_factor_range[0],
                                    demand_factor_range[1] + 1)
        print("using demand factor range: ", list(demand_factor_range))
    else:
        # use specified demand factor
        demand_factor_range = [input_data["options"]["demand_factor"]]
        print("using default demand factor: ", list(demand_factor_range))

    geometry.init_random(False)

    for i_df, df in enumerate(demand_factor_range):
        data['demands'] = [int(d) * df for d in input_data["demands"]]
        routes_vect = []
        for i in range(n_iter):
            if i == 0:
                data[
                    'distance_matrix'] = compute_geometry.compute_distance_matrix_wrapper(
                    )
            else:
                data[
                    'distance_matrix'] = compute_geometry.get_distance_matrix_with_random_depots(
                    )

            print("iteration: " + str(i) + " with demand factor: " + str(df) +
                  " [" + str(
                      int((i_df * n_iter + i) /
                          (len(demand_factor_range) * n_iter) * 100)) + "%]")

            # Create the routing index manager.
            # manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),
            #                                        data['num_vehicles'], data['depot'])

            manager = pywrapcp.RoutingIndexManager(
                len(data['distance_matrix']), data['num_vehicles'],
                data['starts'], data['ends'])

            # Create Routing Model.
            routing = pywrapcp.RoutingModel(manager)

            # Create and register a transit callback.

            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['distance_matrix'][from_node][to_node]

            transit_callback_index = routing.RegisterTransitCallback(
                distance_callback)

            # Define cost of each arc.
            routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)

            # Add Capacity constraint.

            def demand_callback(from_index):
                """Returns the demand of the node."""
                # Convert from routing variable Index to demands NodeIndex.
                from_node = manager.IndexToNode(from_index)
                return data['demands'][from_node]

            demand_callback_index = routing.RegisterUnaryTransitCallback(
                demand_callback)

            routing.AddDimensionWithVehicleCapacity(
                demand_callback_index,
                0,  # null capacity slack
                data['vehicle_capacities'],  # vehicle maximum capacities
                True,  # start cumul to zero
                'Capacity')

            # Add the maximum distance travel constraint for each vehicle:
            routing.AddDimensionWithVehicleCapacity(
                transit_callback_index,
                0,  # null capacity slack
                # vehicle fuel / max daily/travel distance
                data['vehicle_fuel'],
                True,  # start cumul to zero
                'DailyDistance')

            # Allow to drop nodes.
            penalty = 10000
            for node in range(1, len(data['distance_matrix'])):
                routing.AddDisjunction([manager.NodeToIndex(node)], penalty)

            # Setting first solution heuristic.
            search_parameters = pywrapcp.DefaultRoutingSearchParameters()
            search_parameters.first_solution_strategy = (
                routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)

            # search_parameters.first_solution_strategy = (
            #     routing_enums_pb2.FirstSolutionStrategy.AUTOMATIC)

            search_parameters.local_search_metaheuristic = (
                routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)

            time_limit = 1
            search_parameters.time_limit.FromSeconds(time_limit)

            # Total Distance of all routes: 18041m
            # Total Load of all routes: 47

            print("running solver max time limit: " + str(time_limit))
            # Solve the problem.
            assignment = routing.SolveWithParameters(search_parameters)

            # Print solution on console.
            if assignment:
                routes = plot_routes.print_solution(data, manager, routing,
                                                    assignment)
                routes_vect.append(routes)
                print(routes)

        disp_routes = json.dumps(routes_vect)

        with open("data/routes_sim." + str(df) + ".txt", "w") as f:
            f.write(disp_routes)

        with open("data/routes_sim_info." + str(df) + ".txt", "w") as f:
            sim_info = {"demand_factor": df}
            f.write(json.dumps(sim_info))
Ejemplo n.º 3
0
def main():
    # Instantiate the data problem.
    config, input_data, coords, dm = config_loader.load_config()
    depots = input_data["depots"]
    places = input_data["places"]
    vehicles = input_data["vehicles"]
    n_vehicles = len(vehicles)
    options = input_data["options"]
    # just for initial check
    demands = [
        int(d) * options["demand_factor"] for d in input_data["demands"]
    ]
    vehicle_capacities = [int(v["capacity"]) for v in vehicles]
    vehicle_fuel = [int(v["fuel"]) for v in vehicles]

    items = options["items"]

    if options["fixed_vehicles"]:
        n_vehicles = options["n_vehicles"]
        vehicles = [{"id": i + 1} for i in range(n_vehicles)]

    print(items)

    if options["sort_order_msb"]:
        items.sort(key=lambda x: x["weight"], reverse=True)

    print(items)

    sum_demands = sum(demands)
    sum_capacities = sum(vehicle_capacities)

    depot = 0

    # So far, we have assumed that all vehicles start and end at a single location, the depot.
    # You can also set possibly different start and end locations for each vehicle in the problem.
    # To do so, pass two vectors, containing the indices of the start and end locations,
    # as inputs to the RoutingModel method in the main function.
    # Here's how to create the start and end vectors in the data section of the program:

    start_points = [i for i in range(len(depots))]
    end_points = [i for i in range(len(depots))]

    print("sum demands: " + str(sum_demands))
    print("sum capacities: " + str(sum_capacities))

    # compute_geometry.load_config()
    n_iter = options["n_iter"]
    n_epochs = options["n_epochs"]

    if use_external_input:
        df = pd.read_csv('coords_nearby_filtered.csv')

        place_ids = []
        coords = []
        place_ids = df["google_id"]
        coords_lat = [lat for lat in df["lat"]]
        coords_lng = [lng for lng in df["lng"]]
        for i in range(len(coords_lat)):
            coords.append([coords_lat[i], coords_lng[i]])
        place_ids = ["place_id:" + pid for pid in place_ids]
        print(place_ids[0])
        print(coords[0])
        places = place_ids[n_vehicles:]

        if options["fixed_demands"]:
            # only use demand factor
            input_data["demands"] = [1 for p in place_ids]

        place_coords = coords[n_vehicles:]
        compute_geometry.set_coords(coords)

    # quit()

    if options["use_range"]:
        # use demand factor range
        demand_factor_range = options["demand_factor_range"]
        demand_factor_range = range(demand_factor_range[0],
                                    demand_factor_range[1] + 1)
        print("using demand factor range: ", list(demand_factor_range))
    else:
        # use specified demand factor
        demand_factor_range = [options["demand_factor"]]
        print("using default demand factor: ", list(demand_factor_range))

    geometry.init_random(False)

    epoch_results_vect = []

    for epoch in range(n_epochs):
        for i_df, df in enumerate(demand_factor_range):
            demands = [int(d) * df for d in input_data["demands"]]
            demands = demands[n_vehicles:]

            fill_dict = {}

            for i, place in enumerate(places):
                fill_dict[place] = {
                    "place": place,
                    "coords": place_coords[i],
                    "items": [],
                    "item_coords": [],
                    "found": False,
                    "filled": False,
                    "finder": None,
                    "find_index": -1,
                    "total_revisits": 0,
                    "demand": demands[i]
                }

            print(len([k for k in fill_dict]))

            find_index = 0
            compute_geometry.init_random_walk(vehicles, None)

            for i in range(n_iter):
                if i == 0 and use_initial_depots:
                    distance_matrix = compute_geometry.compute_distance_matrix_wrapper(
                    )
                else:
                    distance_matrix = compute_geometry.get_distance_matrix_with_random_walk(
                    )

                print("epoch: " + str(epoch) + ", iteration: " + str(i) +
                      " with demand factor: " + str(df) + " [" + str(
                          int((i_df * n_iter + i) /
                              (len(demand_factor_range) * n_iter) * 100)) +
                      "%]")

                # each agent covers a given range (treasure scan)
                for i_vehicle, v in enumerate(vehicles):
                    if disp_view:
                        print("vehicle: ", i_vehicle)
                    # check nearby places within range
                    found_places = []
                    for j, d in enumerate(distance_matrix[i_vehicle]):
                        if j >= n_vehicles:
                            # print(j,d)
                            if d <= options["scan_radius"]:
                                if disp_view:
                                    print("found: ", d)
                                place = places[j - n_vehicles]
                                dict_place = fill_dict[place]

                                # check if place was already found by another agent
                                if not dict_place["found"]:
                                    dict_place["found"] = True
                                    dict_place["finder"] = vehicles[i_vehicle][
                                        "id"]
                                    dict_place["find_index"] = find_index
                                    found_places.append(dict_place)
                                    find_index += 1
                                else:
                                    dict_place["total_revisits"] += 1
                                    if disp_view:
                                        print("already found: ", d)

                    # assign random items for each agent and found places
                    n_slots = 0
                    for fps in found_places:
                        # check filled items, get number of free slots
                        if not fps["filled"]:
                            n_slots += fps["demand"]

                    if disp_view:
                        print("n_slots: ", n_slots)

                    # generate free slots
                    slots = [None] * n_slots
                    n_items = []

                    # compute number of slots for each item type
                    for item in items:
                        n_items.append(int(n_slots * item["weight"]))

                    # assign items for free slots
                    slots_index = 0
                    for k, n_item in enumerate(n_items):
                        for n in range(n_item):
                            slots[slots_index] = items[k]["item"]
                            slots_index += 1

                    if disp_view:
                        print("n_items: ", n_items)
                        print("filled: ", slots_index)

                    # check unfilled slots, fill with last item type
                    n_unfilled = n_slots - slots_index
                    if slots_index < n_slots:
                        for n in range(n_unfilled):
                            slots[slots_index + n] = items[len(items) -
                                                           1]["item"]

                    # shuffle items/slots
                    slots = shuffle.fisher_yates_shuffle_improved(slots)

                    if disp_view:
                        print(len(slots))

                    slots_index = 0

                    # assign items to actual places
                    for fps in found_places:
                        for d in range(fps["demand"]):
                            if not fps["filled"]:
                                fps["items"].append(slots[slots_index])
                                fps["item_coords"].append(
                                    geometry.get_random_point_in_radius(
                                        fps["coords"],
                                        options["item_coords"]["min_radius"],
                                        options["item_coords"]["max_radius"]))
                                slots_index += 1
                            else:
                                if disp_view:
                                    print("already filled")

                if check_results(items, places, demands, fill_dict, i, epoch,
                                 False, True)[0]:
                    break

            _, epoch_results, map_geometry = check_results(
                items, places, demands, fill_dict, i, epoch, True, False)
            epoch_results_vect.append(epoch_results)

    fig = compute_geometry.plot_random_walk_record()
    output_str = "epoch,places,demand,T,C,S,A,revisits,iterations\n"
    for epoch_results in epoch_results_vect:
        output_str += epoch_results + "\n"
    print(output_str)
    with open("./data/dms_results.csv", "w") as f:
        f.write(output_str)
    map_geometry_str = json.dumps(map_geometry, indent=2)
    with open("./data/dms_map.json", "w") as f:
        f.write(map_geometry_str)

    fig.savefig("./data/random_walk.png", dpi=300)
Ejemplo n.º 4
0
    for i in range(n_vehicles):
        new_coords[i] = geometry.get_random_point_in_radius(
            center_point, 0, max_dist_from_center)

    return new_coords


def main():
    """main function: compute distance matrix for given coords"""

    d_mat = compute_distance_matrix(coords)
    print(d_mat)
    with open(config["matrix_file"], "w") as file:
        for row in d_mat:
            file.write(",".join([str(e) for e in row]) + "\n")


def get_distance_matrix_with_random_depots():
    new_coords = compute_random_points(coords)
    d_mat = compute_distance_matrix(new_coords)
    return d_mat


if __name__ == "__main__":
    # main()
    geometry.init_random(False)
    d_mat = compute_distance_matrix(coords)
    print(d_mat)
    d_mat = get_distance_matrix_with_random_depots()
    print(d_mat)