def bar_multi_GA(nx=20, ny=20, volume_frac=0.5, parent=400, generation=100, path="data"): PATH = os.path.join(path, "bar_nx_{}_ny_{}".format(nx, ny), "gen_{}_pa_{}".format(generation, parent)) os.makedirs(PATH, exist_ok=True) start = time.time() def objective(vars): y_1, y_2, y_3, x_4, nodes, widths = convert_var_to_arg(vars) edges = make_6_bar_edges(nx, ny, y_1, y_2, y_3, x_4, nodes, widths) rho = make_bar_structure(nx, ny, edges) volume = np.sum(rho) / (nx * ny) return [calc_E(rho), calc_G(rho)], [volume] def convert_var_to_arg(vars): y_1 = vars[0] y_2 = vars[1] y_3 = vars[2] x_4 = vars[3] node_y_indexes = vars[4:4 + 6 * 3] node_x_indexes = vars[4 + 6 * 3:4 + 6 * 3 * 2] nodes = np.stack([node_x_indexes, node_y_indexes], axis=1) widths = vars[4 + 6 * 3 * 2:] return y_1, y_2, y_3, x_4, nodes, widths # 2変数2目的の問題 problem = Problem(4 + 6 * 3 * 2 + 6 * 4, 2, 1) # 最小化or最大化を設定 problem.directions[:] = Problem.MAXIMIZE # 決定変数の範囲を設定 x_index_const = Integer(1, nx) # x座標に関する制約 y_index_const = Integer(1, ny) # y座標に関する制約 bar_constraint = Real(0, ny / 2) # バーの幅に関する制約 problem.types[0:3] = y_index_const problem.types[3] = x_index_const problem.types[4:4 + 6 * 3] = y_index_const problem.types[4 + 6 * 3:4 + 6 * 3 * 2] = x_index_const problem.types[4 + 6 * 3 * 2:] = bar_constraint problem.constraints[:] = "<=" + str(volume_frac) problem.function = objective problem.directions[:] = Problem.MAXIMIZE algorithm = NSGAII(problem, population_size=parent, variator=CompoundOperator(SBX(), HUX(), PM(), BitFlip())) algorithm.run(generation) # グラフを描画 fig = plt.figure() plt.scatter([s.objectives[0] for s in algorithm.result], [s.objectives[1] for s in algorithm.result], c="blue", label="infeasible solution") plt.scatter([s.objectives[0] for s in algorithm.result if s.feasible], [s.objectives[1] for s in algorithm.result if s.feasible], c="red", label='feasible solution') # 非劣解をとりだす nondominated_solutions = nondominated(algorithm.result) plt.scatter( [s.objectives[0] for s in nondominated_solutions if s.feasible], [s.objectives[1] for s in nondominated_solutions if s.feasible], c="green", label="pareto solution") plt.legend(loc='lower left') plt.xlabel("$E$") plt.ylabel("$G$") fig.savefig(os.path.join(PATH, "graph.png")) plt.close() for solution in [s for s in nondominated_solutions if s.feasible]: vars_list = [] for j in solution.variables[:3]: vars_list.append(y_index_const.decode(j)) vars_list.append(x_index_const.decode(solution.variables[3])) for j in solution.variables[4:4 + 6 * 3]: vars_list.append(y_index_const.decode(j)) for j in solution.variables[4 + 6 * 3:4 + 6 * 3 * 2]: vars_list.append(x_index_const.decode(j)) for j in solution.variables[4 + 6 * 3 * 2:]: vars_list.append(bar_constraint.decode(j)) y_1, y_2, y_3, x_4, nodes, widths = convert_var_to_arg(vars_list) edges = make_6_bar_edges(nx, ny, y_1, y_2, y_3, x_4, nodes, widths) image = make_bar_structure(nx, ny, edges) np.save( os.path.join( PATH, 'E_{}_G_{}.npy'.format(solution.objectives[0], solution.objectives[1])), image) convert_folder_npy_to_image(PATH) elapsed_time = time.time() - start with open("time.txt", mode='a') as f: f.writelines("bar_nx_{}_ny_{}_gen_{}_pa_{}:{}sec\n".format( nx, ny, generation, parent, elapsed_time))
def run(parent, generation, save_interval, save_dir="GA/result"): def objective(vars): # TODO condition edges_indicesの中身は左の方が右よりも小さいということをassertする gene_nodes_pos, gene_edges_thickness, gene_adj_element = convert_var_to_arg(vars) return [calculate_efficiency(gene_nodes_pos, gene_edges_thickness, gene_adj_element)] def make_adj_triu_matrix(adj_element, node_num, condition_edges_indices): """隣接情報を示す遺伝子から,edge_indicesを作成する関数 """ adj_matrix = np.zeros((node_num, node_num)) adj_matrix[np.triu_indices(node_num, 1)] = adj_element adj_matrix[(condition_edges_indices[:, 0], condition_edges_indices[:, 1])] = 1 edge_indices = np.stack(np.where(adj_matrix), axis=1) return edge_indices def make_edge_thick_triu_matrix(gene_edges_thickness, node_num, condition_edges_indices, condition_edges_thickness, edges_indices): """edge_thicknessを示す遺伝子から,condition_edge_thicknessを基にedges_thicknessを作成する関数 """ tri = np.zeros((node_num, node_num)) tri[np.triu_indices(node_num, 1)] = gene_edges_thickness tri[(condition_edges_indices[:, 0], condition_edges_indices[:, 1])] = condition_edges_thickness edges_thickness = tri[(edges_indices[:, 0], edges_indices[:, 1])] return edges_thickness def convert_var_to_arg(vars): nodes_pos = np.array(vars[0:gene_node_pos_num]) nodes_pos = nodes_pos.reshape([int(gene_node_pos_num / 2), 2]) edges_thickness = vars[gene_node_pos_num:gene_node_pos_num + gene_edge_thickness_num] adj_element = vars[gene_node_pos_num + gene_edge_thickness_num: gene_node_pos_num + gene_edge_thickness_num + gene_edge_indices_num] return nodes_pos, edges_thickness, adj_element def calculate_efficiency(gene_nodes_pos, gene_edges_thickness, gene_adj_element, np_save_path=False): condition_nodes_pos, input_nodes, input_vectors, output_nodes, \ output_vectors, frozen_nodes, condition_edges_indices, condition_edges_thickness\ = make_main_node_edge_info(*condition(), condition_edge_thickness=0.2) # make edge_indices edges_indices = make_adj_triu_matrix(gene_adj_element, node_num, condition_edges_indices) # make nodes_pos nodes_pos = np.concatenate([condition_nodes_pos, gene_nodes_pos]) # 条件ノードが含まれている部分グラフを抽出 G = nx.Graph() G.add_nodes_from(np.arange(len(nodes_pos))) G.add_edges_from(edges_indices) condition_node_list = input_nodes + output_nodes + frozen_nodes trigger = 0 # 条件ノードが全て接続するグラフが存在するとき,トリガーを発動する for c in nx.connected_components(G): sg = G.subgraph(c) # 部分グラフ if set(condition_node_list) <= set(sg.nodes): # 条件ノードが全て含まれているか edges_indices = np.array(sg.edges) trigger = 1 break if trigger == 0: # ペナルティを発動する return -10.0 # make edges_thickness edges_thickness = make_edge_thick_triu_matrix(gene_edges_thickness, node_num, condition_edges_indices, condition_edges_thickness, edges_indices) env = BarFemGym(nodes_pos, input_nodes, input_vectors, output_nodes, output_vectors, frozen_nodes, edges_indices, edges_thickness, frozen_nodes) env.reset() efficiency = env.calculate_simulation() if np_save_path: env.render(save_path=os.path.join(np_save_path, "image.png")) np.save(os.path.join(np_save_path, "nodes_pos.npy"), nodes_pos) np.save(os.path.join(np_save_path, "edges_indices.npy"), edges_indices) np.save(os.path.join(np_save_path, "edges_thickness.npy"), edges_thickness) return float(efficiency) node_num = 85 parent = (node_num * 2 + int(node_num * (node_num - 1) / 2) * 2) # 本来ならこれの10倍 PATH = os.path.join(save_dir, "parent_{}_gen_{}".format(parent, generation)) os.makedirs(PATH, exist_ok=True) condition_node_num = 10 gene_node_pos_num = (node_num - condition_node_num) * 2 gene_edge_thickness_num = int(node_num * (node_num - 1) / 2) gene_edge_indices_num = gene_edge_thickness_num # 2変数2目的の問題 problem = Problem(gene_node_pos_num + gene_edge_thickness_num + gene_edge_indices_num, 1) # 最小化or最大化を設定 problem.directions[:] = Problem.MAXIMIZE # 決定変数の範囲を設定 coord_const = Real(0, 1) edge_const = Real(0.1, 1) # バグが無いように0.1にする adj_constraint = Integer(0, 1) problem.types[0:gene_node_pos_num] = coord_const problem.types[gene_node_pos_num:gene_node_pos_num + gene_edge_thickness_num] = edge_const problem.types[gene_node_pos_num + gene_edge_thickness_num: gene_node_pos_num + gene_edge_thickness_num + gene_edge_indices_num] = adj_constraint problem.function = objective algorithm = NSGAII(problem, population_size=parent, variator=CompoundOperator(SBX(), HUX(), PM(), BitFlip())) history = [] for i in tqdm(range(generation)): algorithm.step() nondominated_solutions = nondominated(algorithm.result) efficiency_results = [s.objectives[0] for s in nondominated_solutions] max_efficiency = max(efficiency_results) history.append(max_efficiency) epochs = np.arange(i + 1) + 1 result_efficiency = np.array(history) fig = plt.figure() ax = fig.add_subplot(1, 1, 1) ax.plot(epochs, result_efficiency, label='efficiency') ax.set_xlim(1, max(epochs)) ax.set_xlabel('epoch') ax.legend() ax.set_title("efficiency curve") plt.savefig(os.path.join(PATH, "history.png")) plt.close() if i % save_interval == 0: save_dir = os.path.join(PATH, str(i)) max_index = efficiency_results.index(max_efficiency) max_solution = nondominated_solutions[max_index] vars = [] vars.extend([coord_const.decode(i) for i in max_solution.variables[0:gene_node_pos_num]]) vars.extend([edge_const.decode(i) for i in max_solution.variables[gene_node_pos_num:gene_node_pos_num + gene_edge_thickness_num]]) vars.extend([adj_constraint.decode(i) for i in max_solution.variables[gene_node_pos_num + gene_edge_thickness_num: gene_node_pos_num + gene_edge_thickness_num + gene_edge_indices_num]]) gene_nodes_pos, gene_edges_thickness, gene_adj_element = convert_var_to_arg(vars) calculate_efficiency(gene_nodes_pos, gene_edges_thickness, gene_adj_element, np_save_path=save_dir) np.save(os.path.join(save_dir, "history.npy"), history)