def getPredictionRelative(self): model = load_model("/Users/sean/Documents/Projects/Packing-Algorithm/model/lstm_num_5_layer_128_56_2_epochs_70.h5") pre_train = pd.read_csv("/Users/sean/Documents/Projects/Data/pre_train.csv") # 读取形状 _input = pd.read_csv("/Users/sean/Documents/Projects/Data/input_seq.csv") # 读取输入 _output = pd.read_csv("/Users/sean/Documents/Projects/Data/output_relative_position.csv") # 读取输入 # index=random.randint(4000,5000) index=4500 polys=json.loads(pre_train["polys"][index]) # 形状 X = np.array([json.loads(_input["x_256"][index])]) # 输入 predicted_Y = model.predict(X, verbose=0)[0]*1500 print(predicted_Y) Y=np.array(json.loads(_output["y"][index]))*1500 print(Y) old_centroid=[0,0] for i,poly in enumerate(polys): # 获得初始的中心和预测的位置 centroid_origin=GeoFunc.getPt(Polygon(poly).centroid) centroid_predicted=[Y[i][0]+old_centroid[0],Y[i][1]+old_centroid[1]] # 获得新的形状并更新 new_poly=GeoFunc.getSlide(poly,centroid_predicted[0]-centroid_origin[0],centroid_predicted[1]-centroid_origin[1]) old_centroid=GeoFunc.getPt(Polygon(new_poly).centroid) PltFunc.addPolygon(poly) PltFunc.addPolygonColor(new_poly) PltFunc.showPlt()
def slideToOrigin(self, poly): bottom_pt, min_y = [], 999999999 for pt in poly: if pt[1] < min_y: min_y = pt[1] bottom_pt = [pt[0], pt[1]] GeoFunc.slidePoly(poly, -bottom_pt[0], -bottom_pt[1])
def placePoly(self, index): adjoin = self.polygons[index] # 是否垂直 if self.vertical == True: ifr = packing.PackingUtil.getInnerFitRectangle( self.polygons[index], self.width, self.length) else: ifr = packing.PackingUtil.getInnerFitRectangle( self.polygons[index], self.length, self.width) differ_region = Polygon(ifr) for main_index in range(0, index): main = self.polygons[main_index] if self.NFPAssistant == None: nfp = NFP(main, adjoin, rectangle=self.rectangle).nfp else: nfp = self.NFPAssistant.getDirectNFP(main, adjoin) nfp_poly = Polygon(nfp) try: differ_region = differ_region.difference(nfp_poly) except: print('NFP failure, polys and nfp are:') print([main, adjoin]) print(nfp) self.showAll() self.showPolys([main] + [adjoin] + [nfp]) print('NFP loaded from: ', self.NFPAssistant.history_path) differ = GeoFunc.polyToArr(differ_region) differ_index = self.getBottomLeft(differ) refer_pt_index = GeoFunc.checkTop(adjoin) GeoFunc.slideToPoint(self.polygons[index], adjoin[refer_pt_index], differ[differ_index])
def slideToContainer(self): # 平移部分形状 for index, poly in enumerate(self.polys): right_pt = LPAssistant.getRightPoint(poly) if right_pt[0] > self.cur_length: delta_x = self.cur_length - right_pt[0] GeoFunc.slidePoly(poly, delta_x, 0) top_pt = self.poly_status[index][1] self.poly_status[index][1] = [top_pt[0] + delta_x, top_pt[1]]
def run(self): self.cur_polys.append(GeoFunc.getSlide(self.polys[0], 1000, 1000)) # 加入第一个形状 self.border_left, self.border_right, self.border_bottom, self.border_top = 0, 0, 0, 0 # 初始化包络长方形 self.border_height, self.border_width = 0, 0 for i in range(1, len(self.polys)): # 更新所有的边界情况 self.updateBound() # 计算NFP的合并情况 feasible_border = Polygon(self.cur_polys[0]) for fixed_poly in self.cur_polys: nfp = self.NFPAssistant.getDirectNFP(fixed_poly, self.polys[i]) feasible_border = feasible_border.union(Polygon(nfp)) # 获得所有可行的点 feasible_point = self.chooseFeasiblePoint(feasible_border) # 获得形状的左右侧宽度 poly_left_pt, poly_bottom_pt, poly_right_pt, poly_top_pt = GeoFunc.checkBoundPt( self.polys[i]) poly_left_width, poly_right_width = poly_top_pt[0] - poly_left_pt[ 0], poly_right_pt[0] - poly_top_pt[0] # 逐一遍历NFP上的点,选择可行且宽度变化最小的位置 min_change = 999999999999 target_position = [] for pt in feasible_point: change = min_change if pt[0] - poly_left_width >= self.border_left and pt[ 0] + poly_right_width <= self.border_right: # 形状没有超出边界,此时min_change为负 change = min(self.border_left - pt[0], self.border_left - pt[0]) elif min_change > 0: # 形状超出了左侧或右侧边界,若变化大于0,则需要选择左右侧变化更大的值 change = max(self.border_left - pt[0] + poly_left_width, pt[0] + poly_right_width - self.border_right) else: # 有超出且min_change<=0的时候不需要改变 pass if change < min_change: min_change = change target_position = pt # 平移到最终的位置 reference_point = self.polys[i][GeoFunc.checkTop(self.polys[i])] self.cur_polys.append( GeoFunc.getSlide(self.polys[i], target_position[0] - reference_point[0], target_position[1] - reference_point[1])) self.slideToBottomLeft() self.showResult()
def __init__(self, polys, **kw): self.polys = PolyListProcessor.deleteRedundancy(copy.deepcopy(polys)) self.area_list, self.first_vec_list, self.centroid_list = [], [], [ ] # 作为参考 for poly in self.polys: P = Polygon(poly) self.centroid_list.append(GeoFunc.getPt(P.centroid)) self.area_list.append(int(P.area)) self.first_vec_list.append( [poly[1][0] - poly[0][0], poly[1][1] - poly[0][1]]) self.nfp_list = [[0] * len(self.polys) for i in range(len(self.polys))] self.load_history = False self.history_path = None self.history = None if 'history_path' in kw: self.history_path = kw['history_path'] if 'load_history' in kw: if kw['load_history'] == True: # 从内存中加载history 直接传递pandas的df对象 缩短I/O时间 if 'history' in kw: self.history = kw['history'] self.load_history = True self.loadHistory() self.store_nfp = False if 'store_nfp' in kw: if kw['store_nfp'] == True: self.store_nfp = True self.store_path = None if 'store_path' in kw: self.store_path = kw['store_path'] if 'get_all_nfp' in kw: if kw['get_all_nfp'] == True and self.load_history == False: self.getAllNFP() if 'fast' in kw: # 为BLF进行多进程优化 if kw['fast'] == True: self.res = [[0] * len(self.polys) for i in range(len(self.polys))] #pool=Pool() for i in range(1, len(self.polys)): for j in range(0, i): # 计算nfp(j,i) #self.res[j][i]=pool.apply_async(getNFP,args=(self.polys[j],self.polys[i])) self.nfp_list[j][i] = GeoFunc.getSlide( getNFP(self.polys[j], self.polys[i]), -self.centroid_list[j][0], -self.centroid_list[j][1])
def getLength(self): _max = 0 for i in range(0, len(self.polygons)): if self.vertical == True: extreme_index = GeoFunc.checkTop(self.polygons[i]) extreme = self.polygons[i][extreme_index][1] else: extreme_index = GeoFunc.checkRight(self.polygons[i]) extreme = self.polygons[i][extreme_index][0] if extreme > _max: _max = extreme self.contain_length = _max # PltFunc.addLine([[0,self.contain_length],[self.width,self.contain_length]],color="blue") return _max
def getInnerFitRectangle(poly, x, y): left_index, bottom_index, right_index, top_index = GeoFunc.checkBound( poly) # 获得边界 new_poly = GeoFunc.getSlide(poly, -poly[left_index][0], -poly[bottom_index][1]) # 获得平移后的结果 refer_pt = [new_poly[top_index][0], new_poly[top_index][1]] ifr_width = x - new_poly[right_index][0] ifr_height = y - new_poly[top_index][1] IFR = [ refer_pt, [refer_pt[0] + ifr_width, refer_pt[1]], [refer_pt[0] + ifr_width, refer_pt[1] + ifr_height], [refer_pt[0], refer_pt[1] + ifr_height] ] return IFR
def getDrease(self, criteria): poly_list = [] for poly in self.polys: if criteria == 'length': left, bottom, right, top = GeoFunc.checkBoundValue(poly) poly_list.append([poly, right - left]) elif criteria == 'height': left, bottom, right, top = GeoFunc.checkBoundValue(poly) poly_list.append([poly, top - bottom]) else: poly_list.append([poly, Polygon(poly).area]) poly_list = sorted(poly_list, key=lambda item: item[1], reverse=True) # 排序,包含index dec_polys = [] for item in poly_list: dec_polys.append(item) return dec_polys
def getNFP(self, j, i): # j是固定位置,i是移动位置 row = j * 192 + i * 16 + self.poly_status[j][2] * 4 + self.poly_status[ i][2] bottom_pt = LPAssistant.getBottomPoint(self.polys[j]) delta_x, delta_y = bottom_pt[0], bottom_pt[1] nfp = GeoFunc.getSlide(json.loads(self.fu_pre["nfp"][row]), delta_x, delta_y) return nfp
def getPredictionAbsolute(self): model = load_model("/Users/sean/Documents/Projects/Packing-Algorithm/model/absolute_lstm_num_8_layer_128_56_2_epochs_200.h5") file= pd.read_csv("/Users/sean/Documents/Projects/Data/8_lstm_test.csv") # 读取输入 index=random.randint(3700,4700) index=3000 polys=json.loads(file["polys"][index]) # 形状 X = np.array([json.loads(file["x_256"][index])]) # 输入 predicted_Y = model.predict(X, verbose=0)[0]*4000 for i,poly in enumerate(polys): centroid_origin=GeoFunc.getPt(Polygon(poly).centroid) PltFunc.addPolygon(poly) new_poly=GeoFunc.getSlide(poly,predicted_Y[i][0]-centroid_origin[0],predicted_Y[i][1]-centroid_origin[1]) PltFunc.addPolygonColor(new_poly) PltFunc.showPlt()
def getAllNFP(self): nfp_multi = False if nfp_multi == True: tasks = [(main, adjoin) for main in self.polys for adjoin in self.polys] res = pool.starmap(NFP, tasks) for k, item in enumerate(res): i = k // len(self.polys) j = k % len(self.polys) self.nfp_list[i][j] = GeoFunc.getSlide( item.nfp, -self.centroid_list[i][0], -self.centroid_list[i][1]) else: for i, poly1 in enumerate(self.polys): for j, poly2 in enumerate(self.polys): nfp = NFP(poly1, poly2).nfp #NFP(poly1,poly2).showResult() self.nfp_list[i][j] = GeoFunc.getSlide( nfp, -self.centroid_list[i][0], -self.centroid_list[i][1]) if self.store_nfp == True: self.storeNFP()
def getDirectNFP(self, poly1, poly2, **kw): if 'index' in kw: i = kw['index'][0] j = kw['index'][1] centroid = GeoFunc.getPt(Polygon(self.polys[i]).centroid) else: # 首先获得poly1和poly2的ID i = self.getPolyIndex(poly1) j = self.getPolyIndex(poly2) centroid = GeoFunc.getPt(Polygon(poly1).centroid) # 判断是否计算过并计算nfp if self.nfp_list[i][j] == 0: nfp = NFP(poly1, poly2).nfp #self.nfp_list[i][j]=GeoFunc.getSlide(nfp,-centroid[0],-centroid[1]) if self.store_nfp == True: with open( "/Users/sean/Documents/Projects/Packing-Algorithm/record/nfp.csv", "a+") as csvfile: writer = csv.writer(csvfile) writer.writerows([[poly1, poly2, nfp]]) return nfp else: return GeoFunc.getSlide(self.nfp_list[i][j], centroid[0], centroid[1])
def updateBound(self): ''' 更新包络长方形 ''' border_left, border_bottom, border_right, border_top = GeoFunc.checkBoundValue( self.cur_polys[-1]) if border_left < self.border_left: self.border_left = border_left if border_bottom < self.border_bottom: self.border_bottom = border_bottom if border_right > self.border_right: self.border_right = border_right if border_top > self.border_top: self.border_top = border_top self.border_height = self.border_top - self.border_bottom self.border_width = self.border_right - self.border_left
def getPrerequisite(self, i, orientation, **kw): # 获得全部NFP以及拆分情况 self.all_nfps,self.all_points_target,self.all_edges_target = [],[],[] offline = kw['offline'] for j, item in enumerate(self.polys): # 两个相等的情况,跳过否则会计算错误 if j == i: self.all_nfps.append([]) self.all_points_target.append([]) self.all_edges_target.append([]) continue # 预处理的情况 points_target, edges_target, nfp = [], [], [] if offline == True: row = j * 192 + i * 16 + self.poly_status[j][ 2] * 4 + orientation bottom_pt = LPAssistant.getBottomPoint(self.polys[j]) delta_x, delta_y = bottom_pt[0], bottom_pt[1] nfp = GeoFunc.getSlide(json.loads(self.fu_pre["nfp"][row]), delta_x, delta_y) else: nfp = LPAssistant.deleteOnline( self.NFPAssistant.getDirectNFP( self.polys[j], self.polys[i])) # NFP可能有同一直线上的点 # 计算对应目标函数 for pt_index in range(len(nfp)): edges_target.append( LPAssistant.getTargetFunction( [nfp[pt_index - 1], nfp[pt_index]])) points_target.append([nfp[pt_index][0], nfp[pt_index][1]]) # 添加上去 self.all_nfps.append(nfp) self.all_edges_target.append(edges_target) self.all_points_target.append(points_target) # 获取IFR self.target_poly = self.all_polygons[i][orientation] self.ifr = PackingUtil.getInnerFitRectangle(self.target_poly, self.cur_length, self.width) self.IFR = Polygon(self.ifr) self.final_IFR = Polygon(self.ifr)
def minimizeOverlap(self): start_time = time.time() # 记录引导检索的相关内容 self.miu = [[1] * len(self.polys) for _ in range(len(self.polys))] self.initialOverlap() # 记录重叠变化情况 self.overlap_reocrd = [] # 检索次数限制/超出倍数退出 it, N = 0, 50 minimal_overlap = self.getTotalOverlap() cur_overlap = minimal_overlap print("初始重叠:", cur_overlap) # 限定计算次数 print("开始一次检索") while it < N: print("it:", it) # 获得随机序列并逐一检索 permutation = np.arange(len(self.polys)) np.random.shuffle(permutation) for i in range(len(self.polys)): # 选择特定形状 choose_index = permutation[i] # 通过重叠判断是否需要计算 with_overlap = False for item in self.pair_overlap[choose_index]: if item > 0: with_overlap = True break if with_overlap == False: continue # 获得当前的最小的深度(调整后),如果没有重叠,直接下一个 self.getPrerequisite(choose_index, self.poly_status[choose_index][2], offline=True) cur_min_depth = self.getPolyDepeth(choose_index) # 记录最优情况,默认是当前情况 original_position = self.poly_status[choose_index][1] best_position, best_orientation, best_depth = self.poly_status[ choose_index][1], self.poly_status[choose_index][ 2], cur_min_depth # print("当前最低高度:",best_depth) print("测试第", i, "个形状") # 遍历四个角度的最优值 for orientation in [0, 1, 2, 3]: # print("测试角度:",90*orientation,"度") self.getPrerequisite(choose_index, orientation, offline=True) self.getProblemLP() new_position, new_depth = self.searchBestPosition( choose_index) # 获得最优位置 if new_depth < best_depth: best_position, best_orientation, best_depth = copy.deepcopy( new_position), orientation, new_depth # 如果有变化状态则需要更新overlap以及移动形状 if best_position != original_position: print("本次检索最低深度:", best_depth) # 更新记录的位置 self.poly_status[choose_index][1] = copy.deepcopy( best_position) self.poly_status[choose_index][2] = best_orientation # 获取形状顶部位置并平移过去 new_poly = copy.deepcopy( self.all_polygons[choose_index][best_orientation]) top_point = LPAssistant.getTopPoint(new_poly) GeoFunc.slidePoly(new_poly, best_position[0] - top_point[0], best_position[1] - top_point[1]) # 更新形状与重叠情况 self.polys[choose_index] = new_poly self.updateOverlap(choose_index) # self.showPolys() # 计算新方案的重叠情况 cur_overlap = self.getTotalOverlap() self.overlap_reocrd.append(cur_overlap) if cur_overlap < bias: print("没有重叠,本次检索结束") break elif cur_overlap < minimal_overlap: minimal_overlap = cur_overlap it = 0 print("\n当前重叠:", cur_overlap, "\n") it = it + 1 self.updateMiu() # 超出检索次数 if it == N: print("超出更新次数/超出倍数") # self.showPolys() end_time = time.time() print("本轮耗时:", end_time - start_time) print("最终结果:", self.polys) print("当前状态:", self.poly_status) with open( "/Users/sean/Documents/Projects/Packing-Algorithm/record/fu_result.csv", "a+") as csvfile: writer = csv.writer(csvfile) writer.writerows([[ time.asctime(time.localtime(time.time())), end_time - start_time, self.cur_length, self.total_area / (self.cur_length * self.width), cur_overlap, self.poly_status, self.polys ]]) self.showPolys() self.plotRecord("Overlap Record:", self.overlap_reocrd)
def slideToBottomLeft(self): '''移到最左下角位置''' for poly in self.cur_polys: GeoFunc.slidePoly(poly, -self.border_left, -self.border_bottom)
def placeFirstPoly(self): poly = self.polygons[0] left_index, bottom_index, right_index, top_index = GeoFunc.checkBound( poly) # 获得边界 GeoFunc.slidePoly(poly, -poly[left_index][0], -poly[bottom_index][1]) # 平移到左下角