예제 #1
0
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))
예제 #2
0
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)