问题简述
1.单个残骸定位:确定用于精确测定单个空中火箭残骸音爆位置的最少监测设备数量,并计算指定数据中的残骸位置。
2.多个残骸定位:开发一个模型来分析和确定哪些震动波数据来自哪个残骸,并确定在空中有多个残骸同时发生音爆时的残骸位置和时间。
算法思路
根据遗传算法进行近似解的寻找。
#问题一
import numpy as np
from itertools import combinations
latition_dis=111263
longtition_dis=97304
'''初始化探测器'''
class detector():
def __init__(self,latitude,longtitude,high,time):
#经度:longtitude
#纬度:latitude
#高度:high
#时间:time
self.loc=(latitude,longtitude)
self.h=high
self.t=time
self.v=343 #声速
# '''计算距离'''
# def cal_distance(self,point,high):
# return (distance(self.loc,point)**2+high**2)**0.5
'''计算总适应度'''
def cal_fit(self,x,y,high,t):
fitness=((((x-self.loc[1])*longtition_dis)**2+((y-self.loc[0])*latition_dis)**2+(high-self.h)**2)**0.5/self.v+t-self.t)**2
return fitness
'''计算适应度函数'''
def cal_fitness(self,x,y,high,t):
fits=[]
for i in range(len(x)):
fitness=1/((((x[i]-self.loc[1])*longtition_dis)**2+((y[i]-self.loc[0])*latition_dis)**2+(high[i]-self.h)**2)**0.5/self.v+t[i]-self.t)**2
fits.append(fitness)
return np.array(fits)
'''以下为遗传算法'''
'''解码'''
def translateDNA(pop):
x_pop=pop[:,::4]#第一列为x
y_pop=pop[:,1::4]#第二列为y
h_pop=pop[:,2::4]#第三列为h
t_pop=pop[:,3::4]#第四列为t
x = x_pop.dot(2**np.arange(DNA_SIZE)[::-1])/float(2**DNA_SIZE-1)*(X_BOUND[1]-X_BOUND[0])+X_BOUND[0]
y = y_pop.dot(2**np.arange(DNA_SIZE)[::-1])/float(2**DNA_SIZE-1)*(Y_BOUND[1]-Y_BOUND[0])+Y_BOUND[0]
h = h_pop.dot(2**np.arange(DNA_SIZE)[::-1])/float(2**DNA_SIZE-1)*(H_BOUND[1]-H_BOUND[0])+H_BOUND[0]
t = t_pop.dot(2**np.arange(DNA_SIZE)[::-1])/float(2**DNA_SIZE-1)*(T_BOUND[1]-T_BOUND[0])+T_BOUND[0]
return x,y,h,t
'''单点交叉'''
def crossover_and_mutation(pop, CROSSOVER_RATE = 0.8):
new_pop = []
for father in pop:
child = father
if np.random.rand() < CROSSOVER_RATE:
mother = pop[np.random.randint(POP_SIZE)]
cross_points = np.random.randint(low=0, high=DNA_SIZE*4)
child[cross_points:] = mother[cross_points:]
mutation(child)
new_pop.append(child)
return new_pop
'''位点变异'''
def mutation(child, MUTATION_RATE=0.003):
if np.random.rand() < MUTATION_RATE:
mutate_point = np.random.randint(0, DNA_SIZE*4)
child[mutate_point] = child[mutate_point]^1
'''轮盘赌'''
def select(pop, fitness):
idx = np.random.choice(np.arange(POP_SIZE), size=POP_SIZE, replace=True,p=(fitness)/(fitness.sum()) )
return pop[idx]
'''计算适应度'''
def get_fitness(pop,i):
x,y,h,t=translateDNA(pop)
#计算到四个探测器的适应度
fitness=dectors[i[0]].cal_fitness(x,y,h,t)+dectors[i[1]].cal_fitness(x,y,h,t)\
+dectors[i[2]].cal_fitness(x,y,h,t)+dectors[i[3]].cal_fitness(x,y,h,t)\
+dectors[i[4]].cal_fitness(x,y,h,t)
return fitness
'''显示信息'''
def print_info(pop,i):
fitness = get_fitness(pop,i)
max_fitness_index = np.argmax(fitness)
x,y,h,t = translateDNA(pop)
print(i)
print("(x, y,h,t):", (x[max_fitness_index], y[max_fitness_index],h[max_fitness_index],t[max_fitness_index]))
print("max_fitness:", fitness[max_fitness_index])
total=0
for j in range(7):
total+=dectors[j].cal_fit(x[max_fitness_index], y[max_fitness_index],h[max_fitness_index],t[max_fitness_index])
print("total_fitness:",total)
return total
dectors=[]
longtitudes=[110.241,110.780,110.712,110.251,110.524,110.467,110.047]
latitudes=[27.204,27.456,27.785,27.825,27.617,28.921,27.121]
highs=[824,727,742,850,786,678,575]
times=[100.767,112.220,188.020,258.985,118.443,266.871,163.024]
'''创建7个探测器'''
for i in range(7):
dectors.append(detector(latitudes[i],longtitudes[i],highs[i],times[i]))
a=[0,1,2,3,4,5,6]
b=list(combinations(a,5))
DNA_SIZE = 24 #DNA长度
POP_SIZE = 400 #种群大小
CROSSOVER_RATE = 0.8 #交叉概率
MUTATION_RATE = 0.005 #变异概率
N_GENERATIONS = 500 #迭代次数
X_BOUND = [110, 111] #x的范围
Y_BOUND = [27, 28] #y的范围
H_BOUND= [500,1000] #h的范围
T_BOUND= [0,100.767] #t的范围
pop = np.random.randint(2, size=(POP_SIZE, DNA_SIZE*4)) #随机产生初始种群的二进制矩阵
totallist=[]
for i in b:
for _ in range(N_GENERATIONS):
x,y,h,t = translateDNA(pop)
pop = np.array(crossover_and_mutation(pop, CROSSOVER_RATE))
fitness = get_fitness(pop,i)
pop = select(pop, fitness)
totallist.append(print_info(pop,i))
print(totallist)
得到结果可视化后的示意图
多残骸定位可以增加DNA支链数量,时间匹配可以采取模拟算法进行搜索。