def getLengthRanked(self): length_results = [] self.fitness_sum = 0 if self.ga_multi == True: tasks = [[pop] for pop in self.pop] pool = multiprocessing.Pool() results = pool.starmap(self.getLength, tasks) for i in range(0, len(self.pop)): # print("length:",results[i]) self.fitness_sum += 1000 / results[i] length_results.append([ i, results[i], 1000 / results[i], PolyListProcessor.getPolyListIndex(self.pop[i]) ]) else: for i in range(0, len(self.pop)): length = self.getLength(self.pop[i]) self.fitness_sum += 1000 / length length_results.append([ i, length, 1000 / length, PolyListProcessor.getPolyListIndex(self.pop[i]) ]) self.fitness_ranked = sorted(length_results, key=operator.itemgetter(1)) # 排序,包含index
def newPolyList(self): choose_id = int(random.random() * len(self.new_poly_list)) '''进行交换和旋转的操作,暂时不允许旋转''' if random.random()<=1: self.new_poly_list=PolyListProcessor.randomSwap(self.cur_poly_list,choose_id) else: self.new_poly_list=PolyListProcessor.randomRotate(self.cur_poly_list,self.min_angle,choose_id)
def mutate(self,individual): for swapped in range(len(individual)): if(random.random() < self.mutate_rate): # 首先是交换位置 if random.random()<=0.5: individual=PolyListProcessor.randomSwap(individual,swapped) else: individual=PolyListProcessor.randomRotate(individual,self.minimal_rotation,swapped) return individual
def breed(self,parent1, parent2): geneA,geneB = random.randint(0,len(parent1)-1), random.randint(0,len(parent1)-1) start_gene,end_gene = min(geneA, geneB),max(geneA, geneB) parent1_index = PolyListProcessor.getPolyListIndex(parent1) parent2_index = PolyListProcessor.getPolyListIndex(parent2) child1_index = parent1_index[start_gene:end_gene] # 截取一部分 child2_index = [item for item in parent2_index if item not in child1_index] # 截取剩余部分 return PolyListProcessor.getPolysByIndex(child1_index,self.poly_list) + PolyListProcessor.getPolysByIndex(child2_index,self.poly_list)
def geneticAlgorithm(self): self.pop = [] # 种群记录 self.length_record = [] # 记录高度 self.lowest_length_record = [] # 记录全局高度 self.global_best_sequence = [] # 全局最优序列 self.global_lowest_length = 9999999999 # 全局最低高度 # 初步的随机数组 for i in range(0, self.pop_size): _list=copy.deepcopy(self.poly_list) random.shuffle(_list) self.pop.append(_list) # 持续获得下一代 for i in range(0, self.generations): print("############################ Compute the ",i+1,"th generation #######################################") self.getLengthRanked() # 高度排列 self.getNextGeneration() # 获得下一代 # 高度记录与最低高度处理 self.length_record.append(self.fitness_ranked[0][1]) if self.fitness_ranked[0][1]<self.global_lowest_length: self.global_lowest_length=self.fitness_ranked[0][1] self.global_best_sequence=self.pop[self.fitness_ranked[0][0]] self.lowest_length_record.append(self.global_lowest_length) # print(self.global_lowest_length) # print("Final length: " + str(self.global_lowest_length)) blf=BottomLeftFill(self.width,PolyListProcessor.getPolysVertices(self.global_best_sequence),NFPAssistant=self.NFPAssistant) blf.showAll()
def __init__(self,width,poly_list,nfp_asst=None,generations=10,pop_size=20): self.width=width self.minimal_rotation=360 # 最小的旋转角度 self.poly_list=poly_list self.ga_multi=False # 开了多进程反而更慢 if self.ga_multi: multiprocessing.set_start_method('spawn',True) self.elite_size=10 # 每一代选择个数 self.mutate_rate=0.1 # 变异概率 self.generations=generations # 代数 self.pop_size=pop_size # 每一代的个数 self.history_index_list=[] self.history_length_list=[] if nfp_asst: self.NFPAssistant=nfp_asst else: self.NFPAssistant=NFPAssistant(PolyListProcessor.getPolysVertices(poly_list),get_all_nfp=True) self.geneticAlgorithm() self.plotRecord()
def getLength(self, poly_list): length = PolyListProcessor.packingLength( poly_list, self.history_index_list, self.history_length_list, self.width, NFPAssistant=self.NFPAssistant) return length
def getGA(width, poly, nfp_asst, generations=10): polys_GA = PolyListProcessor.getPolyObjectList(poly, [0]) ga = GA(width, polys_GA, nfp_asst=nfp_asst, generations=generations, pop_size=10) origin = ga.length_record[0] best = ga.global_lowest_length return origin - best
def packingLength(poly_list,history_index_list,history_length_list,width,**kw): polys=PolyListProcessor.getPolysVertices(poly_list) index_list=PolyListProcessor.getPolyListIndex(poly_list) length=0 check_index=PolyListProcessor.getIndex(index_list,history_index_list) if check_index>=0: length=history_length_list[check_index] else: try: if 'NFPAssistant' in kw: blf=BottomLeftFill(width,polys,NFPAssistant=kw['NFPAssistant']) # blf.showAll() length=blf.contain_length else: length=BottomLeftFill(width,polys).contain_length except: print('出现Self-intersection') length=99999 history_index_list.append(index_list) history_length_list.append(length) return length
def __init__(self,poly_list): self.min_angle=360 # 允许旋转的最小角度 self.width=1500 # 排列的宽度 self.temp_now=200 # 起始温度 2000 self.temp_end=1e-5 # 结束温度 1e-20 self.dec_rate=0.7 # 降温速率 0.995 self.loop_times=5 # 内循环次数 self.cur_poly_list=poly_list # 当前的序列 self.new_poly_list=poly_list # 生成新的序列 self.history_index_list=[] # 运行过的index序列 self.history_length_list=[] # 运行结果 self.NFPAssistant=NFPAssistant(PolyListProcessor.getPolysVertices(poly_list),get_all_nfp=True) self.run()
def __init__(self,poly_list): # 初始设置 self.width=1500 # 初始化数据,NFP辅助函数 polys=PolyListProcessor.getPolysVertices(poly_list) self.NFPAssistant=NFPAssistant(polys,get_all_nfp=False) # 获得最优解 blf=BottomLeftFill(self.width,polys,NFPAssistant=self.NFPAssistant) self.best_height=blf.contain_height self.cur_height=blf.contain_height # 当前的poly_list均为已经排样的情况 self.best_poly_list=copy.deepcopy(poly_list) self.cur_poly_list=copy.deepcopy(poly_list) self.run()
def BLFwithSequence(test_path, width, seq_path=None, GA_algo=False): if seq_path != None: f = open(seq_path, 'r') seqs = f.readlines() data = np.load(test_path, allow_pickle=True) test_name = test_path.split('_xy')[0] height = [] if GA_algo: p = Pool() multi_res = [] for i, line in enumerate(tqdm(data)): polys_final = [] if seq_path != None: # 指定序列 seq = seqs[i].split(' ') else: # 随机序列 seq = np.array(range(len(line))) np.random.shuffle(seq) for j in range(len(line)): if seq_path != None: index = int(seq[j]) else: index = seq[j] polys_final.append(line[index]) nfp_asst = NFPAssistant(polys_final, load_history=True, history_path='record/{}/{}.csv'.format( test_name, i)) #nfp_asst=None if GA_algo == True: # 遗传算法 polys_GA = PolyListProcessor.getPolyObjectList(polys_final, [0]) multi_res.append( p.apply_async(GA, args=(width, polys_GA, nfp_asst))) else: blf = BottomLeftFill(width, polys_final, NFPAssistant=nfp_asst) #blf.showAll() height.append(blf.getLength()) if GA_algo: p.close() p.join() for res in multi_res: height.append(res.get().global_lowest_length) return height
def run(self): initial_length = packingLength(self.cur_poly_list, self.history_index_list, self.history_length_list, self.width) global_lowest_length_list = [] # 记录每个温度下最最低高度,理论上会下降 temp_lowest_length_list = [] # 每个温度下的平衡高度 global_best_list = copy.deepcopy(self.cur_poly_list) # 用于记录历史上最好蓄力 global_lowest_length = initial_length # 全局最低高度 temp_best_list = copy.deepcopy(self.cur_poly_list) # 局部温度下的最低 temp_lowest_length = initial_length # 局部温度下的最低 unchange_times = 0 # 开始循环寻找 while self.temp_now > self.temp_end: print("当前温度:", self.temp_now) old_lowest_length = global_lowest_length # 统计未更改次数 cur_length = packingLength(self.cur_poly_list, self.history_index_list, self.history_length_list, self.width, NFPAssistant=self.NFPAssistant) # 在某个温度下进行一定次数的寻找 for i in range(self.loop_times): self.newPolyList() new_length = packingLength(self.new_poly_list, self.history_index_list, self.history_length_list, self.width, NFPAssistant=self.NFPAssistant) delta_length = new_length - cur_length if delta_length < 0: # 当前温度下如果高度更低则接受 temp_best_list = self.cur_poly_list = copy.deepcopy( self.new_poly_list) temp_lowest_length = new_length # 修改为新的高度 cur_length = new_length if new_length < global_lowest_length: # 如果新的高度小于最低的高度则修改最低高度 global_lowest_length = new_length global_best_list = copy.deepcopy(self.new_poly_list) elif np.random.random() < np.exp( -delta_length / self.temp_now): # 按照一定概率修改,并作为下一次检索基础 self.poly_list = copy.deepcopy(self.new_poly_list) cur_length = new_length else: pass # 否则不进行修改 print("当前温度最低长度:", temp_lowest_length) print("最低长度:", global_lowest_length) if old_lowest_length == global_lowest_length: unchange_times += 1 if unchange_times > 15: break else: unchange_times = 0 self.cur_poly_list = copy.deepcopy( temp_best_list) # 某温度下检索结束后取该温度下最优值 self.temp_now *= self.dec_rate #退火 global_lowest_length_list.append( global_lowest_length) # 全局的在每个温度下的最低高度,理论上一直在降低 temp_lowest_length_list.append(temp_lowest_length) # 每个温度下的最低高度 # print('结束温度的局部最优的序列:',temp_best_list) print('结束温度的局部最优高度:', temp_lowest_length) # print('最好序列:',global_best_list) print('最好序列高度:', global_lowest_length) PolyListProcessor.showPolyList(self.width, global_best_list) self.showBestResult(temp_lowest_length_list, global_lowest_length_list)
# print('结束温度的局部最优的序列:',temp_best_list) print('结束温度的局部最优高度:', temp_lowest_length) # print('最好序列:',global_best_list) print('最好序列高度:', global_lowest_length) PolyListProcessor.showPolyList(self.width, global_best_list) self.showBestResult(temp_lowest_length_list, global_lowest_length_list) def showBestResult(self, list1, list2): plt.figure(1) plt.subplot(311) plt.plot(list1) #每个温度下平衡路径长度 plt.subplot(312) plt.plot(list2) #每个温度下最好路径长度 plt.grid() plt.show() if __name__ == '__main__': starttime = datetime.datetime.now() polys = getData(6) all_rotation = [0] # 禁止旋转 poly_list = PolyListProcessor.getPolyObjectList(polys, all_rotation) SA(poly_list) endtime = datetime.datetime.now() print(endtime - starttime)
def getProblemLP(self): # 获得目标区域 self.ifr_points = [] self.target_areas = [[], [], [], [], [], [], [], [], []] self.last_index = [[], [], [], [], [], [], [], [], []] # 获得两个NFP在IFR中重叠的情况 self.nfp_overlap_pair = [[i] for i in range(len(self.all_nfps))] for i in range(len(self.all_nfps) - 1): for j in range(i + 1, len(self.all_nfps)): overlap, overlap_poly = self.polysOverlapIFR( self.all_nfps[i], self.all_nfps[j]) if overlap == True: self.nfp_overlap_pair[i].append(j) self.nfp_overlap_pair[j].append(i) self.target_areas[1].append([overlap_poly, i, j]) self.last_index[1].append([i, j]) # 分别添加i,j # 切去一维重叠情况 for i, nfp in enumerate(self.all_nfps): # 删除与IFR重叠区域 new_region = Polygon(nfp).intersection(self.IFR) self.final_IFR = self.final_IFR.difference(Polygon(nfp)) # 删除与其他NFP拆分的重叠 for j in self.nfp_overlap_pair[i][1:]: P = Polygon(self.all_nfps[j]) new_region = new_region.difference(P) # 在目标区域增加情况,首先排除点和直线,以及面积过小 if new_region.is_empty != True and new_region.geom_type != "Point" and new_region.geom_type != "LineString" and new_region.area > bias: self.target_areas[0].append( [LPAssistant.processRegion(new_region), i]) # 删除直线/顶点情况 else: self.target_areas[0].append([]) self.last_index[0].append([]) # 增加IFR的计算 if self.final_IFR.is_empty != True and self.final_IFR.geom_type != "Point" and self.final_IFR.geom_type != "LineString" and self.final_IFR.area > bias: self.ifr_points = LPAssistant.processRegion(self.final_IFR) # 获得后续的重叠 for i in range(2, len(self.target_areas)): # 遍历上一阶段计算的结果 for j, target_area in enumerate(self.target_areas[i - 1]): area, P1 = target_area[0], Polygon(target_area[0]) # 获得当前目标可行解 all_possible_target = [] # 如果大于三个,只需要计算最后加入的,否则是第一个 if i >= 3: all_possible_target = self.nfp_overlap_pair[ target_area[-1]] else: all_possible_target = self.nfp_overlap_pair[ target_area[1]] + self.nfp_overlap_pair[target_area[2]] all_possible_target = PolyListProcessor.deleteRedundancy( all_possible_target) # 删除所有更小的,保证正序,获得判断这些形状是否会重叠,若有则添加并求解目标区域 all_possible_target_larger = LPAssistant.deleteTarget( all_possible_target, [ i for i in range( 0, max(item for item in target_area[1:]) + 1) ]) for possible_target in all_possible_target_larger: P2 = Polygon(self.all_nfps[possible_target]) # 只有相交才进一步计算 if P1.intersects(P2): inter = P1.intersection(P2) if inter.area > bias: self.last_index[i].append([j]) self.target_areas[i].append( [LPAssistant.processRegion(inter)] + target_area[1:] + [possible_target]) # 删除已经有的,遍历计算重叠 all_possible_target_difference = LPAssistant.deleteTarget( all_possible_target, [item for item in target_area[1:]]) new_region = self.cutFrontRegion( all_possible_target_difference, P1) if new_region.is_empty != True and new_region.geom_type != "Point" and new_region.geom_type != "LineString" and new_region.area > bias: target_area[0] = LPAssistant.processRegion(new_region) else: self.target_areas[i - 1][j] = [] # 如果该轮没有计算出重叠则停止 if self.target_areas[i] == []: self.max_overlap = i # print("至多",i,"个形状重叠,计算完成") break
self.showBestResult(temp_lowest_length_list, global_lowest_length_list) def showBestResult(self, list1, list2): plt.figure(1) plt.subplot(311) plt.plot(list1) #每个温度下平衡路径长度 plt.subplot(312) plt.plot(list2) #每个温度下最好路径长度 plt.grid() plt.show() if __name__ == '__main__': starttime = datetime.datetime.now() # polys=getConvex(num=5) polys = getData() print(len(polys)) poly_list = PolyListProcessor.getPolyObjectList(polys + polys + polys, [0]) # TOPOS(polys,1500) nfp_assistant = NFPAssistant(polys, store_nfp=False, get_all_nfp=True, load_history=True) GA(760, poly_list, nfp_asst=nfp_assistant) # SA(poly_list) # GetBestSeq(1000,getConvex(num=5),"decrease") endtime = datetime.datetime.now() print(endtime - starttime) bfl.showAll()