NSGA-Ⅱ求解多目标VRP问题的python代码
时间: 2023-08-11 13:06:44 浏览: 519
以下是使用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算法对种群进行进化,并输出最优解的路径和距离等信息。
阅读全文