コード例 #1
0
def test_calculate_cost_calculator_with_one_cars():
    solution = Solution(vehicle_routes=np.array([[2, 1, 0], [0, 0, 0]]))
    node_distances = NodeDistances(
        distances=np.array([[0, 1, 2], [3, 0, 5], [6, 7, 0]]))

    calculator = SolutionRestrictionsCalculator(node_distances=node_distances,
                                                vehicle_allowed_distances=None)
    cost = calculator.calculate_cost(solution=solution)

    assert 12 == cost, "All only one route should sum 12"
コード例 #2
0
def test_get_vehicle_consumed_distance():
    solution = Solution(vehicle_routes=np.array([[2, 1, 3, 0], [0, 0, 0, 0]]))
    node_distances = NodeDistances(distances=np.array(
        [[0, 7, 3, 1], [2, 0, 4, 6], [3, 6, 0, 9], [5, 10, 15, 0]]))

    calculator = SolutionRestrictionsCalculator(node_distances=node_distances,
                                                vehicle_allowed_distances=None)
    cost = calculator.get_vehicle_consumed_distance(solution=solution,
                                                    vehicle=0)

    assert 20 == cost, "All only one route should sum 20"
コード例 #3
0
def test_remaining_distance_for_vehicle_returns_negative():
    solution = Solution(vehicle_routes=np.array([[2, 1, 0], [0, 0, 0]]))
    node_distances = NodeDistances(
        distances=np.array([[0, 1, 2], [3, 0, 5], [6, 7, 0]]))
    vehicle_allowed_distances = VehicleAllowedDistances(distances=[10, 7, 0])

    calculator = SolutionRestrictionsCalculator(
        node_distances=node_distances,
        vehicle_allowed_distances=vehicle_allowed_distances)
    remaining_distance = calculator.get_vehicle_remaining_distance(
        solution=solution, vehicle=0)

    assert -2 == remaining_distance, "-2 should be the remaining distance"
コード例 #4
0
def test_update_cost_solution_when_2_routes_change():
    solution1=Solution(vehicle_routes=np.array([[2, 0 , 0, 0],[1,3, 0,0],[0,0,0,0]]))
    solution2=Solution(vehicle_routes=np.array([[2, 0 , 0,0],[1, 0, 0,0],[3,0,0,0]]))
    node_distances=NodeDistances(distances=np.array([[0, 1, 2,20],[3, 0, 5,21],[6, 7, 0,22],[9,1,1,0]]))
    vehicle_allowed_distances=VehicleAllowedDistances(distances=[14, 20, 15])
    calculator=SolutionRestrictionsCalculator(node_distances=node_distances,vehicle_allowed_distances=vehicle_allowed_distances)


    cost=Neighborhood(solution_restrictions_calculator=calculator). \
        _update_solution_cost(old_solution=solution1,new_solution=solution2,vehicles_involved=[1,2])
    

    assert cost==41 , "Update cost should be 41"
コード例 #5
0
ファイル: execution.py プロジェクト: vikical/VRP
    def execute_single_instance_once(self,path_to_node_distances:str, path_to_max_vehicle_distances:str, metaheuristic:str)->():
        """
        Execute a single instance of a problem, just only once.
        The result is a tuple containing:
        (solution, elapsed_time)
        """
        node_distances=NodeDistances(distances=Reader.read_distances_between_nodes_in_file(path_to_file=path_to_node_distances))
        vehicle_allowed_distances=VehicleAllowedDistances(distances=Reader.read_vehicle_allowed_distances_in_file(path_to_file=path_to_max_vehicle_distances))

        solution_restrictions_calculator=SolutionRestrictionsCalculator(node_distances=node_distances, vehicle_allowed_distances=vehicle_allowed_distances)
        metaheu_obj=MetaheuristicFactory.create_metaheuristic(metaheuristic=metaheuristic, solution_restrictions_calculator=solution_restrictions_calculator, \
            init=self.init, search_type=self.search_type, number_iterations=self.number_iterations, memory_size=self.memory_size, max_running_secs=self.max_running_secs)
        
        tic=time.time()
        solution=metaheu_obj.run()
        tac=time.time()
        elapsed_time=tac-tic
        return (solution,elapsed_time)
コード例 #6
0
def test_join_customers_from_one_route_to_another():
    vehicle_routes = np.array([[1, 2, 3, 4, 5, 0, 0, 0],
                               [11, 12, 13, 14, 15, 0, 0, 0]])
    vehicle_allowed_distances = VehicleAllowedDistances(
        distances=np.array([300, 200]))

    solution = Solution(vehicle_routes=vehicle_routes)
    solution_restrictions_calculator = SolutionRestrictionsCalculator(
        node_distances=None,
        vehicle_allowed_distances=vehicle_allowed_distances)

    join_customer = JoinCustomers(
        solution_restrictions_calculator=solution_restrictions_calculator)
    new_solution = join_customer._operation_between_vehicle_routes(
        solution=solution, vehicle1=0, vehicle2=1)

    route1 = new_solution.vehicle_routes[0]
    route2 = new_solution.vehicle_routes[1]

    assert route1[0] == 1, "r1: 1st element should be 1"
    assert route1[1] == 2, "r1: 2nd element should be 2"
    assert route1[2] == 3, "r1: 3rd element should be 3"
    assert route1[3] == 4, "r1: 4th element should be 4"
    assert route1[4] == 5, "r1: 5th element should be 5"
    assert route1[5] == 11, "r1: 6th element should be 11"
    assert route1[6] == 12, "r1: 7th element should be 12"
    assert route1[7] == 13, "r1: 8th element should be 13"

    assert route2[0] == 0, "r2: 1st element should be 0"
    assert route2[1] == 0, "r2: 2nd element should be 0"
    assert route2[2] == 0, "r2: 3rd element should be 0"
    assert route2[3] == 14, "r2: 4th element should be 14"
    assert route2[4] == 15, "r2: 5th element should be 15"
    assert route2[5] == 0, "r2: 6th element should be 0"
    assert route2[6] == 0, "r2: 7th element should be 0"
    assert route2[7] == 0, "r2: 8th element should be 0"
コード例 #7
0
 def __init__(self, node_distances: NodeDistances,
              vehicle_allowed_distances: VehicleAllowedDistances):
     self.node_distances = node_distances
     self.vehicle_allowed_distances = vehicle_allowed_distances
     self.solution_restrictions_calculator=SolutionRestrictionsCalculator(node_distances=node_distances, \
         vehicle_allowed_distances=vehicle_allowed_distances)
コード例 #8
0
class SolutionInitializer(object):
    """
    Initializes a solution. 
    """
    def __init__(self, node_distances: NodeDistances,
                 vehicle_allowed_distances: VehicleAllowedDistances):
        self.node_distances = node_distances
        self.vehicle_allowed_distances = vehicle_allowed_distances
        self.solution_restrictions_calculator=SolutionRestrictionsCalculator(node_distances=node_distances, \
            vehicle_allowed_distances=vehicle_allowed_distances)

    def init_randomly(self) -> Solution:
        """
        For each customer we randomly select a vehicle. If the fleet contains vehicles which cannot performe a certain
        trip, it may lead to unfeasible solutions.
        We reject invalid solutions, so we will try till a valid ones is obtained randomly.
        """
        return self.__init_solution(
            initializing_function=self.__assign_nodes_randomly)

    def init_one_node_to_one_vehicle(self) -> Solution:
        """
        We assign randomly one node to one vehicle.
        This should lead to a valid solution. However we will check it and look for another solution in case we found 
        a no-valid one.
        """
        return self.__init_solution(
            initializing_function=self.__assign_one_node_to_one_vehicle)

    def init_vehicles_with_group_nodes_sequentially(self) -> Solution:
        """
        We assign nodes sequeantially to vehicles till they reach their restriction.
        This should lead to a valid solution. However we will check it and look for another solution in case we found 
        a no-valid one.
        """
        return self.__init_solution(
            initializing_function=self.
            __assign_group_nodes_sequentially_to_vehicles)

    def __init_solution(self, initializing_function) -> Solution:
        """
        Initializing the solution, using the function passed as parameter to create the vehicle routes.
        After 100 attempts we consider an error must be happening and a exception is raised.
        """
        attempt = 0
        solution_is_valid = False
        while solution_is_valid == False:
            if attempt >= 100:
                raise Exception("Initial VALID solution not found after " +
                                str(attempt) + " attempts.")
            attempt = attempt + 1
            vehicle_routes = initializing_function()
            solution = Solution(vehicle_routes=vehicle_routes)
            solution_is_valid = self.solution_restrictions_calculator.check_if_solution_is_valid(
                solution=solution)

        solution.is_valid = True
        solution.cost = self.solution_restrictions_calculator.calculate_cost(
            solution=solution)

        return solution

    def __assign_nodes_randomly(self) -> np.ndarray:
        """
        Assign nodes randomly
        """
        num_vehicles = self.vehicle_allowed_distances.get_number_of_vehicles()
        num_nodes = self.node_distances.get_number_of_nodes()
        vehicle_routes = np.zeros([num_vehicles, num_nodes], dtype=int)

        for node in range(1, num_nodes):
            vehicle = random.randint(0, num_vehicles - 1)
            route = vehicle_routes[vehicle]
            available_indexes = np.where(route == 0)[0]
            index = available_indexes[0]
            vehicle_routes[vehicle][index] = node

        return vehicle_routes

    def __assign_group_nodes_sequentially_to_vehicles(self) -> np.ndarray:
        """
        We assign nodes sequeantially to vehicles till they reach their restriction.
        This will lead to a valid solution.
        """
        allowed_distances = self.vehicle_allowed_distances.distances
        num_nodes = self.node_distances.get_number_of_nodes()
        vehicle_routes = np.zeros([len(allowed_distances), num_nodes],
                                  dtype=int)

        vehicle = 0
        index_node = 0
        node_list = list(range(1, num_nodes))
        random.shuffle(node_list)
        for node in node_list:  #we suffle from 1 in order to ignore depot (=0)
            #Asign and check if valid
            vehicle_routes[vehicle][index_node] = node
            remaining_distance=self.solution_restrictions_calculator.get_remaining_distance(route=vehicle_routes[vehicle], \
                node_distances=self.node_distances, allowed_distance=allowed_distances[vehicle])

            #If no valid, undo the assignmment and move to next vehicle.
            if remaining_distance < 0:
                vehicle_routes[vehicle][index_node] = 0
                vehicle = vehicle + 1
                index_node = 0
                vehicle_routes[vehicle][index_node] = node

            #Move to next index.
            index_node = index_node + 1

        return vehicle_routes

    def __assign_one_node_to_one_vehicle(self) -> np.ndarray:
        """
        As Clark and Wright, we assign one node to one vehicle.
        """
        num_vehicles = self.vehicle_allowed_distances.get_number_of_vehicles()
        num_nodes = self.node_distances.get_number_of_nodes()
        vehicle_routes = np.zeros([num_vehicles, num_nodes], dtype=int)
        suffled_customers = np.array(range(1, num_nodes), dtype=int)
        random.shuffle(suffled_customers)

        for index in range(0, num_vehicles):
            vehicle_routes[index][0] = suffled_customers[index]

        return vehicle_routes