ortools路由模型(VRP)的解,如何作为精确求解的初始解?Python代码

1. 解析路由模型解的内容,生成线路。

  • 客户的运输线路和顺序。
routes = []
for route_nbr in range(self.routing.vehicles()):
    index = self.routing.Start(route_nbr)
    route = [self.manager.IndexToNode(index)]
    while not self.routing.IsEnd(index):
         index = solution.Value(self.routing.NextVar(index))
         route.append(self.manager.IndexToNode(index))
         routes.append(route)
  • 客户的到达时间、等待时间
time_dimension = self.routing.GetDimensionOrDie('Time')
cumul_datas = []
for i in range(self.data["params"]["vehicle_nums"]):
    cumul_data = []
    _times = {}
    # 返回车辆的开始索引
    index = self.routing.Start(i)
    _times["wait_time"] = 0
    _times["arrive_time"] = solution.Min(time_dimension.CumulVar(index))
    cumul_data.append(_times)
    while not self.routing.IsEnd(index):
         # 返回下一个节点
         index = solution.Value(self.routing.NextVar(index))
         _times = {}
         # 下一个节点的等待时间
         _times["wait_time"] = solution.Min(time_dimension.SlackVar(index)) if not self.routing.IsEnd(index) else 0
           # 下一个节点的到达时间
         _times["arrive_time"] = solution.Min(time_dimension.CumulVar(index))
         cumul_data.append(_times)
         cumul_datas.append(cumul_data)
  • 客户的早晚到时间 
for i in range(len(routes)):
    route = routes[i]
    for j in range(len(route)):
          index = route[j]
          if index == 0:
                route_times[i][j]["early_hours"] = 0
                route_times[i][j]["late_hours"] = 0
          else:
                route_times[i][j]["early_hours"] = max(0, self.data["time_windows"][index][0] - route_times[i][j]["arrive_time"])
                route_times[i][j]["late_hours"] = max(0, route_times[i][j]["arrive_time"] - self.data["time_windows"][index][1])

 2. 转换为精确求解需要的形式。

ini_solution = {}   # 储存初始解
vehicle_ids = []    # 储存车辆信息
# 字典形式保存初始解
_x_value, _t_value, _w_value, _e_value, _l_value = {}, {}, {}, {}, {}
for i in range(len(routes)):
    if len(routes[i]) > 2:
          vehicle_ids.append(i)
          route = routes[i]
          route_times = all_times[i]
          for j in range(1, len(route)):
              if j > 0:
                   _x_value[(route[j - 1], route[j], start_vehicle_id)] = 1
                   _t_value[(route[j - 1], start_vehicle_id)] = route_times[j - 1]["arrive_time"]
                   _w_value[(route[j - 1], start_vehicle_id)] = route_times[j - 1]["wait_time"]
                   _e_value[(route[j - 1], start_vehicle_id)] = route_times[j - 1]["early_hours"]
                   _l_value[(route[j - 1], start_vehicle_id)] = route_times[j - 1]["late_hours"]
         start_vehicle_id += 1
ini_solution.update({"x_values": _x_value, "t_values": _t_value, "w_values": _w_value, "e_values": _e_value, "l_values": _l_value})
        

3. 以ortools为例,初始解赋值。

        solution = self.initial_solutions
        if self.solver_name == "cp_sat":
            variables = self.model._CpModel__model.variables
        if self.solver_name != "cp_sat":
            variables = self.model.variables()
        pattern = re.compile(r'[(](.*?)[)]', re.S)
        if solution is not None:
            x_values = solution["x_values"]
            w_values = solution["w_values"]
            t_values = solution["t_values"]
            e_values = solution["e_values"]
            l_values = solution["l_values"]
            all_vars = []
            all_values = []
            for i, field in enumerate(variables):
                if self.solver_name == "cp_sat":
                    name = field.name
                if self.solver_name != "cp_sat":
                    name = variables[i].name()
                if len(re.findall(pattern, name)) > 0:
                    key = tuple([int(i) for i in re.findall(pattern, name)[0].split(",")])
                    if "x" in name:
                        if x_values.get(key, None):
                            if self.solver_name == "cp_sat":
                                self.model.AddHint(i, x_values.get(key))
                            if self.solver_name != "cp_sat":
                                all_vars.append(self.model.variable(i))
                                all_values.append(x_values.get(key))
                        else:
                            if self.solver_name == "cp_sat":
                                self.model.AddHint(i, 0)
                            if self.solver_name != "cp_sat":
                                all_vars.append(self.model.variable(i))
                                all_values.append(0)
                    elif "w" in name:
                        if w_values.get(key, None):
                            if self.solver_name == "cp_sat":
                                self.model.AddHint(i, w_values.get(key))
                            if self.solver_name != "cp_sat":
                                all_vars.append(self.model.variable(i))
                                all_values.append(w_values.get(key))
                    elif "t" in name:
                        if t_values.get(key, None):
                            if self.solver_name == "cp_sat":
                                self.model.AddHint(i, t_values.get(key))
                            if self.solver_name != "cp_sat":
                                all_vars.append(self.model.variable(i))
                                all_values.append(t_values.get(key))
                    elif "e" in name:
                        if e_values.get(key, None):
                            if self.solver_name == "cp_sat":
                                self.model.AddHint(i, e_values.get(key))
                            if self.solver_name != "cp_sat":
                                all_vars.append(self.model.variable(i))
                                all_values.append(e_values.get(key))
                    elif "l" in name:
                        if l_values.get(key, None):
                            if self.solver_name == "cp_sat":
                                self.model.AddHint(i, l_values.get(key))
                            if self.solver_name != "cp_sat":
                                all_vars.append(self.model.variable(i))
                                all_values.append(l_values.get(key))
                    else:
                        pass
            if self.solver_name != "cp_sat":
                self.model.SetHint(all_vars, all_values)

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是使用NSGA-II算法求解多目标VRP问题的Python代码: ```python import numpy as np import random # 定义车辆容量 vehicle_capacity = 10 # 定义货物数量 num_of_customers = 20 # 定义客户坐标 customers = np.random.rand(num_of_customers, 2) # 定义距离矩阵 dist_matrix = np.zeros((num_of_customers, num_of_customers)) for i in range(num_of_customers): for j in range(num_of_customers): dist_matrix[i][j] = np.linalg.norm(customers[i] - customers[j]) # 定义NSGA-II算法参数 pop_size = 100 max_gen = 200 pc = 0.9 pm = 1.0 / num_of_customers alpha = 1 class Individual: def __init__(self): self.chromosome = [] self.fitness = [] self.rank = 0 self.distance = 0 def __lt__(self, other): if self.rank != other.rank: return self.rank < other.rank else: return self.distance > other.distance # 初始化种群 population = [] for i in range(pop_size): ind = Individual() ind.chromosome = [0] + random.sample(range(1, num_of_customers), num_of_customers - 1) population.append(ind) # 定义快速非支配排序函数 def fast_non_dominated_sort(population): S = [[] for i in range(len(population))] front = [[]] n = [0 for i in range(len(population))] rank = [0 for i in range(len(population))] for p in range(len(population)): S[p] = [] n[p] = 0 for q in range(len(population)): if population[p].fitness[0] < population[q].fitness[0] and population[p].fitness[1] < population[q].fitness[1]: if q not in S[p]: S[p].append(q) elif population[q].fitness[0] < population[p].fitness[0] and population[q].fitness[1] < population[p].fitness[1]: n[p] += 1 if n[p] == 0: population[p].rank = 0 if p not in front[0]: front[0].append(p) i = 0 while front[i]: Q = [] for p in front[i]: for q in S[p]: n[q] -= 1 if n[q] == 0: population[q].rank = i + 1 if q not in Q: Q.append(q) i += 1 front.append(Q) return front[:-1] # 定义拥挤度计算函数 def crowding_distance(population, front): for i in range(len(front)): for ind in front[i]: ind.distance = 0 for m in range(len(population[0].fitness)): front = sorted(front, key=lambda ind: ind.fitness[m]) population[front[0]].distance = float('inf') population[front[-1]].distance = float('inf') for i in range(1, len(front) - 1): population[front[i]].distance += (population[front[i + 1]].fitness[m] - population[front[i - 1]].fitness[m]) # 定义选择函数 def selection(population): tournament_size = 2 selected = [] for i in range(pop_size): tournament = random.sample(population, tournament_size) winner = min(tournament) selected.append(winner) return selected # 定义交叉函数 def crossover(parent1, parent2): child1 = Individual() child2 = Individual() child1.chromosome = [-1] * (num_of_customers + 1) child2.chromosome = [-1] * (num_of_customers + 1) r1 = random.randint(1, num_of_customers - 1) r2 = random.randint(r1, num_of_customers - 1) for i in range(r1, r2 + 1): child1.chromosome[i] = parent1.chromosome[i] child2.chromosome[i] = parent2.chromosome[i] j = 0 k = 0 for i in range(num_of_customers): if parent2.chromosome[i + 1] not in child1.chromosome[r1:r2 + 1]: child1.chromosome[j] = parent2.chromosome[i + 1] j += 1 if parent1.chromosome[i + 1] not in child2.chromosome[r1:r2 + 1]: child2.chromosome[k] = parent1.chromosome[i + 1] k += 1 for i in range(num_of_customers): if child1.chromosome[i] == -1: child1.chromosome[i] = parent2.chromosome[i + 1] if child2.chromosome[i] == -1: child2.chromosome[i] = parent1.chromosome[i + 1] child1.chromosome[-1] = 0 child2.chromosome[-1] = 0 return child1, child2 # 定义变异函数 def mutation(individual): for i in range(num_of_customers): if random.random() < pm: j = random.randint(0, num_of_customers - 1) c1 = individual.chromosome[i + 1] c2 = individual.chromosome[j + 1] individual.chromosome[i + 1] = c2 individual.chromosome[j + 1] = c1 return individual # 定义求解函数 def solve(): for i in range(max_gen): offsprings = [] for j in range(int(pop_size / 2)): parent1, parent2 = random.sample(population, 2) if random.random() < pc: child1, child2 = crossover(parent1, parent2) else: child1 = parent1 child2 = parent2 child1 = mutation(child1) child2 = mutation(child2) offsprings += [child1, child2] population += offsprings for ind in population: ind.fitness = [0, 0] for i in range(len(ind.chromosome) - 1): ind.fitness[0] += dist_matrix[ind.chromosome[i]][ind.chromosome[i + 1]] ind.fitness[1] += 1 ind.fitness[1] -= 1 fronts = fast_non_dominated_sort(population) for i in range(len(fronts)): crowding_distance(population, fronts[i]) population = sorted(population, reverse=True) population = population[:pop_size] return population # 调用求解函数 population = solve() # 输出结果 for i in range(len(population)): if population[i].rank == 0: print('Solution {}:'.format(i + 1)) print(' Route: {}'.format(population[i].chromosome)) print(' Distance: {}'.format(population[i].fitness[0])) print(' Num of vehicles: {}'.format(population[i].fitness[1])) ``` 在代码中,先定义了车辆容量、货物数量、客户坐标和距离矩阵等参数。然后定义了Individual类来表示种群中的个体,包括染色体、适应度、排名和拥挤度等属性。接着定义了快速非支配排序和拥挤度计算函数,用于进行多目标优化。最后定义了选择、交叉、变异和求解函数,用于进行遗传算法求解。在求解函数中,使用NSGA-II算法对种群进行进化,并输出最优的路径和距离等信息。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值