基于遗传算法的航班延误航班调度模型建模
可用作生产调度的课程作业
旅客失望溢出成本定义:因航空公司航班延误导致原航班的旅客不能按照原定计划到达目的地,由于航班延误,给旅客造成不良的出行体验,对航空公司的满意度和信任度大打折扣,导致旅客在下一次选择消费时不考虑该公司的航班而转向其它公司航班或选择乘坐其他交通工具给该公司造成的信用损失和经济损失。
有关旅客失望溢出函数的定义与该航班的乘客人数、飞机票价和乘客失望率有关,其函数式可写为:
式中v表示该航班上的乘客人数,w表示平均票价,u表示旅客失望率。
旅客失望溢出率调查表得出旅客失望率函数如下:
当延误航班上的所有旅客在下一次都不选择该公司的航班时,此时最大失望溢出成本为P=v×w,既失望率为100%。
其中延误航班的运营成本和航班机型以及质量有关系,对于不同的机型,其延误成本为:
其中,a为飞机每小时延误的运营成本,T_i为航班延误时间(小时/h)。
模型参数
我们采用时间段优化模型的思路,以时间点来代替时间段,得到航班精确的起飞时间点。
所涉及的参数或变量如下:
n:起飞航班的数量;
t_i:航班i计划起飞时刻;
e_i:航班i的最早起飞时刻;
l_i:航班i的最晚起飞时刻;
s_i:航班i的从登机口到跑道起飞线之间的滑行时间;
a_i:航班i每小时延误的运营成本;
x_i:航班i实际起飞时刻;
a_f:各航班每小时的运营成本的集合;
T_i:为航班i实际延误时间;
v_i:为航班i的乘客人数;
w_i:为航班i的平均票价;
u_i:为航班i的旅客失望率。
航班延误调度的目的是使延误成本最小化或延误时间最小,其目
标函数如下:
因此在进行航班调度时所需要考虑的约束条件如下:
式6表示延误时间,航班起飞时间超过计划时间既延误;
式7为对第i辆航班的起飞时间约束。
全文资料:https://download.csdn.net/download/qq_43627520/87379847
import random
import numpy as np
import math
from tqdm import tqdm
import matplotlib.pyplot as plt
class GA(object):
# 初始化种群 生成chromosome_length大小的population_size个个体的种群
def __init__(self, population_size, chromosome_length, max_value, pc, pm):
self.population_size = population_size
self.choromosome_length = chromosome_length
# self.population=[[]]
self.max_value = max_value
self.pc = pc
self.pm = pm
self.data_list = np.array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[10000, 13000, 10000, 15000, 14000, 10000, 9000, 11000, 12000, 12000],
[10, 10, 8, 10, 6, 7, 10, 12, 6, 7],
[10, 20, 15, 30, 40, 47, 50, 55, 60, 70],
[220, 200, 240, 220, 180, 180, 200, 240, 160, 200],
[870, 1230, 850, 1600, 760, 960, 480, 830, 1340, 840]])
# self.fitness_value=[]
def rand_list(self):
list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
random.shuffle(list)
return list
def species_origin(self):
population = [[1, 2, 3, 4, 5, 6, 7, 8, 9,10]]
for i in range(self.population_size):
list = self.rand_list()
while list in population:
list = self.rand_list()
population.append(list)
# 将染色体添加到种群中
population = np.array(population)
return population
# 将种群返回,种群是个二维数组,个体和染色体两维
def function(self, population):
# data_list:航班信息表,0代表航班号,1代表运输成本,2代表滑行时间,3代表起飞时刻,4代表旅客人数,5代表平均票价
function_data = []
temporary = np.array(population)
# 获取一条染色体
for i in range(len(temporary)):
now_time = 0
# 获取一个基因
sum_P_i = 0
sum_T_i = 0
for j in range(self.choromosome_length):
gene = temporary[i][j]-1 # 当前染色体下的基因数
now_time += self.data_list[2][gene]
if now_time>self.data_list[3][gene]:
T_i = now_time-self.data_list[3][gene]
u_i = pow((T_i/60)**2,1/3)/29
sum_P_i += self.data_list[4][gene]*self.data_list[5][gene]*u_i + self.data_list[5][gene]*T_i/60
sum_T_i +=T_i
function_data.append(sum_P_i)
return function_data
# 定义适应度
def fitness(self, function_value):
fitness_value = []
for i in range(len(function_value)):
temporary = 1-function_value[i]/sum(function_value)
fitness_value.append(temporary)
# 将适应度添加到列表中
return fitness_value
# 3.选择种群中个体适应度最大的个体
def selection(self, population, fitness_value):
zip_list = zip(fitness_value,population)
sort_zipped = sorted(zip_list, key=lambda x: (x[0]),reverse=True)
result = zip(*sort_zipped)
fitness_value_, population_ = [list(x) for x in result]
population = population_[0:400]
population = np.array(population)
return population
# 4.交叉操作
def crossover(self, population):
# pc是概率阈值,选择单点交叉还是多点交叉,生成新的交叉个体,这里没用
new_population = [x for x in population]
pop_len = len(population)//2
for i in range(pop_len):
if (random.random() < self.pc):
rand_list = []
for j in range(self.choromosome_length):
rand_list.append(random.randint(0,1))
temporary1 = population[i*2]*rand_list
temporary2 = population[i*2+1]*rand_list
#构造子代
for g in range(len(temporary1)):
if temporary1[g]==0:
for c in range(len(population[i*2+1])):
if population[i*2+1][c] in temporary1:
continue
else:
temporary1[g]=population[i*2+1,c]
for g in range(len(temporary2)):
if temporary2[g]==0:
for c in range(len(population[i*2])):
if population[i*2][c] in temporary2:
continue
else:
temporary2[g]=population[i*2,c]
if np.min(temporary2)==0 or np.min(temporary1)==0:
print(rand_list,"f1:",population[i*2],"f2:",population[i*2+1],"c1:",temporary1,"c2:",temporary2)
new_population.append(temporary1)
new_population.append(temporary2)
new_population = np.array(new_population)
return new_population
def mutation(self, population):
new_population = population
for i in range(len(population)):
c_population = population[i].copy()
if (random.random() < self.pm):
m1 = random.randint(0,self.choromosome_length-1)
m2 = random.randint(0,self.choromosome_length-1)
if m1!=m2:
new_population[i][m1] = c_population[m2]
new_population[i][m2] = c_population[m1]
return new_population
# 寻找最好的适应度和个体
def best(self, population, fitness_value):
zip_list = zip(fitness_value, population)
sort_zipped = sorted(zip_list, key=lambda x: (x[0]), reverse=True)
result = zip(*sort_zipped)
fitness_value_, population_ = [list(x) for x in result]
best_individual = population_[0]
best_fitness = fitness_value_[0]
return best_individual, best_fitness
def plot(self, results):
X = []
Y = []
#print(len(results))
for i in range(500):
X.append(i)
Y.append(results[i][0])
plt.plot(X, Y)
plt.show()
def main(self):
results = []
# 种群初始化
population = self.species_origin()
for i in tqdm(range(100)):
function_value = self.function(population)
# print('fit funtion_value:',function_value)
fitness_value = self.fitness(function_value)
# print('fitness_value:',fitness_value)
best_individual, best_fitness = self.best(population, fitness_value)
results.append(best_individual)
# 将最好的个体和最好的适应度保存
s_population = self.selection(population, fitness_value) #新一轮父代选择
c_population = self.crossover(s_population) #新一轮染色体交叉变异
population = self.mutation(c_population) #新一轮染色体交换变异
return results
#self.plot(results)
def test_function(self, population):
# data_list:航班信息表,0代表航班号,1代表运输成本,2代表滑行时间,3代表起飞时刻,4代表旅客人数,5代表平均票价
result_data = []
temporary = np.array(population)
# 获取一条染色体
for i in range(len(temporary)):
now_time = 0
# 获取一个基因
sum_P_i = 0
sum_T_i = 0
for j in range(self.choromosome_length):
gene = temporary[i][j]-1 # 当前染色体下的基因数
now_time += self.data_list[2][gene]
if now_time>self.data_list[3][gene]:
T_i = (now_time-self.data_list[3][gene])
u_i = pow((T_i/60)**2,1/3)/29
sum_P_i += self.data_list[4][gene]*self.data_list[5][gene]*u_i + self.data_list[5][gene]*T_i/60
sum_T_i +=T_i
result_data.append([temporary[i],sum_P_i,sum_T_i])
result_data = np.array(result_data)
best_min = np.min(result_data[:,1])
best_list = []
for x in range(len(result_data[:, 0])):
if result_data[x,1]==best_min:
best_list.append(result_data[x,0])
return best_list
def draw_plt(self,result):
for best_list in result:
now_time = 0
for i in best_list:
plt.barh(i, self.data_list[2][i-1], left=(now_time))
plt.vlines(self.data_list[3][i-1], i-0.5, i+0.5, colors='r')
now_time += self.data_list[2][i - 1]
if now_time > self.data_list[3][i-1]:
plt.hlines(i,self.data_list[3][i-1],now_time) # 横线
plt.vlines(now_time, i - 0.5, i + 0.5)
plt.yticks(np.arange(max(best_list)+1), np.arange(0, max(best_list)+1))
plt.show()
# short_time: 1, 2, 4, 3, 5, 6, 9, 7, 10, 8
# short_money: 3, 2, 4, 5, 6, 8, 9, 10, 1, 7