Пример #1
0
    def __init__(self,
                 pv_peak_power=None,
                 wt_nominal_power=None,
                 battery_capacity=None):

        ## Initialize Problem
        # Three decision variables, two objectives, and four constraints of objectives (top/bottom)
        super(system_optimisation, self).__init__(3, 2, 4)
        self.directions[0] = Problem.MINIMIZE
        self.directions[1] = Problem.MINIMIZE

        # Define the decision variables, Type of value: INTEGER and constraints
        int1 = Integer(1, 5000)  # PV peak Power
        int2 = Integer(1, 5000)  # WT nominal power
        int3 = Integer(1, 5000)  # Battery capacity
        self.types[:] = [int1, int2, int3]
        self.constraints[0] = ">=0"
        self.constraints[1] = "<=0"
        self.constraints[2] = ">=0"
        self.constraints[3] = "<=0"
Пример #2
0
def set_problem_types(config_space, problem, instance_features=None):
    """
    set problem.types for algorithms in platypus (NSGAII, ...)
    """

    if instance_features is not None:
        raise NotImplementedError
    for i, param in enumerate(config_space.get_hyperparameters()):
        if isinstance(param, (CategoricalHyperparameter)):
            n_cats = len(param.choices)
            problem.types[i] = Integer(0, n_cats - 1)
        elif isinstance(param, (OrdinalHyperparameter)):
            n_cats = len(param.sequence)
            problem.types[i] = Integer(0, n_cats - 1)
        elif isinstance(param, UniformFloatHyperparameter):
            problem.types[i] = Real(0, 1)
        elif isinstance(param, UniformIntegerHyperparameter):
            problem.types[i] = Real(0, 1)
        else:
            raise TypeError("Unsupported hyperparameter type %s" % type(param))
 def __init__(self):
     energy_component_type = 0
     self.energy_component_number = {}
     super(TwoStageOpt, self).__init__(
         int(num_components), 2, 1
     )  #To create a problem with five decision variables, two objectives, and one constraint
     if use_solar_PV == 'yes':
         self.energy_component_number['solar_PV'] = energy_component_type
         self.types[energy_component_type] = Integer(
             0, int(roof_top_area / PV_module))  #Decision space for A_solar
         energy_component_type += 1
     if use_wind_turbine == 'yes':
         self.energy_component_number[
             'wind_turbine'] = energy_component_type
         self.types[energy_component_type] = Integer(
             0,
             len(wind_component['Number']) - 1)  #Decision space for A_swept
         energy_component_type += 1
     if use_CHP == 'yes':
         self.energy_component_number['CHP'] = energy_component_type
         self.types[energy_component_type] = Integer(
             0,
             len(CHP_component['Number']) -
             1)  #Decision space for CHP capacity
         energy_component_type += 1
     if use_boilers == 'yes':
         self.energy_component_number['boilers'] = energy_component_type
         self.types[energy_component_type] = Integer(
             0,
             len(boiler_component['Number']) -
             1)  #Decision space for boiler capacity
         energy_component_type += 1
     if use_battery == 'yes':
         self.energy_component_number['battery'] = energy_component_type
         self.types[energy_component_type] = Integer(
             0,
             len(battery_component['Number']) -
             1)  #Decision space for battery capacity
         energy_component_type += 1
     self.constraints[
         0] = ">=0"  #Constraint to make sure heating demand can be satisfied using the boiler and CHP etc.
    def _prune(self):
        problem = Problem(len(self.ensemble_), 2)
        problem.types[:] = Integer(0, 1)
        problem.directions[0] = Problem.MAXIMIZE
        problem.directions[1] = Problem.MAXIMIZE
        problem.function = functools.partial(MCE._evaluate_imbalance,
                                             y_predicts=self._y_predict,
                                             y_true=self._y_valid)

        algorithm = NSGAII(problem)
        algorithm.run(10000)

        solutions = unique(nondominated(algorithm.result))
        objectives = [sol.objectives for sol in solutions]

        def extract_variables(variables):
            extracted = [v[0] for v in variables]
            return extracted

        self._ensemble_quality = self.get_group(
            extract_variables(solutions[objectives.index(
                max(objectives, key=itemgetter(0)))].variables),
            self.ensemble_)
        self._ensemble_diversity = self.get_group(
            extract_variables(solutions[objectives.index(
                max(objectives, key=itemgetter(1)))].variables),
            self.ensemble_)
        self._ensemble_balanced = self.get_group(
            extract_variables(solutions[objectives.index(
                min(objectives, key=lambda i: abs(i[0] - i[1])))].variables),
            self.ensemble_)

        pareto_set, fitnesses = self._genetic_optimalisation(
            optimalisation_type='quality_single')
        self._ensemble_quality_single = self.get_group(
            pareto_set[fitnesses.index(max(fitnesses, key=itemgetter(0)))],
            self.ensemble_)
        # pareto_set, fitnesses = self._genetic_optimalisation(optimalisation_type='diversity_single')
        # self._ensemble_diversity_single = self.get_group(pareto_set[fitnesses.index(min(fitnesses, key=itemgetter(0)))],
        #                                                  self.ensemble_)

        pareto_set, fitnesses = self._genetic_optimalisation(
            optimalisation_type='precision_single')
        self._ensemble_precision_single = self.get_group(
            pareto_set[fitnesses.index(max(fitnesses, key=itemgetter(0)))],
            self.ensemble_)
        pareto_set, fitnesses = self._genetic_optimalisation(
            optimalisation_type='recall_single')
        self._ensemble_recall_single = self.get_group(
            pareto_set[fitnesses.index(max(fitnesses, key=itemgetter(0)))],
            self.ensemble_)
Пример #5
0
 def __init__(self, universe: Universe, buying_power: float):
     # Initialize Problem parent class with the number of assets as the number
     # of variables, 1 objective function, and 1 contraint respectively.
     super(OptPortfolio, self).__init__(universe.count, 1, 1)
     self.universe = universe
     self.ticker_set = [asset.Ticker for asset in universe.UniverseSet]
     self.universe_historical_data = gen_universe_hist_data(
         universe.UniverseSet, 'Adj_Close')
     self.buying_power = buying_power
     # Specify variables as an integer from [0,1]
     self.typeInt = Integer(0, 1)
     self.types[:] = self.typeInt
     # Specify the contraint equation to equal 0
     self.constraints[:] = "==0"
     self.directions[:] = Problem.MAXIMIZE
Пример #6
0
 def __init__(self):
     super(Belegundu, self).__init__(7, 3, 15)
     self.types[:] = [
         Integer(0, 1),
         Integer(0, 1),
         Integer(0, 1),
         Integer(0, 1),
         Integer(0, 1),
         Integer(0, 1),
         Integer(0, 1)
     ]
     self.constraints[:] = [
         "==0", "<=0", "<=0", "<=0", "<=0", "<=0", "<=0", "<=0", ">=0",
         ">=0", ">=0", ">=0", ">=0", ">=0", ">=0"
     ]
    def __init__(self, requirements, budget, weight):
        super(SingleObjReleaseProblem, self).__init__(len(requirements), 1, 1)
        self.requirements = requirements
        self.types[:] = Integer(0, 1)
        self.constraints[:] = '<=' + str(budget)
        self.directions[0] = self.MAXIMIZE
        self.weight = weight

        max_value = -1
        max_cost = -1

        for req in self.requirements:
            if req.value > max_value:
                max_value = req.value
            if req.cost > max_cost:
                max_cost = req.cost

        for req in self.requirements:
            req.value = req.value / max_value
            req.cost = req.cost / max_cost
Пример #8
0
    mound = mound * 100  # mound/min(mound)

    pltvm.plt_scen_objectives(scenario_names, num_scenarios,
                              [energy, subs, mound])

if plot_opt:
    ''' 
    The optimize option runs an optimization problem with the model using the recharge decisions and objectives defined above
    If the run_optimization is not activated, previous results are loaded from the file indicated above
    '''
    if run_optimization:

        nfe = 0
        problem = Problem(recharge_decisions, recharge_objectives)
        problem.directions[:] = Problem.MINIMIZE
        wwtp_int = Integer(0, 74)  # Number of wastewater treatment plants
        basin_int = Integer(0, 10)  # Number of recharge basins
        leak_int = Integer(0, 100)  # 0 to 100% leak repair
        problem.types[:] = [wwtp_int, basin_int, leak_int]
        problem.function = objective_function()
        algorithm = NSGAII(problem)
        algorithm.run(max_nfes)

        results_list = []
        variable_list = []
        int_list = [wwtp_int, basin_int, leak_int]

        for r, results in enumerate(algorithm.result):
            results_list.append(results.objectives[:])
            var_list = []
            for v, var in enumerate(results.variables):
Пример #9
0
 def __init__(self):
     super(my_mo_problem, self).__init__(self.nlinks, 2, 2)
     self.types[:] = [Integer(0, 16)] * self.nlinks
     self.constraints[:] = "<=0"
     self.directions[:] = Problem.MINIMIZE
    
    SIM = Model_Simulator()

    D = len(SIM._sorted_names)
    OBJS = 3
    FEs = 15000
    POPSIZE = 100
    # DIRECTIONS = [Problem.MAXIMIZE, Problem.MINIMIZE, Problem.MINIMIZE]
    DIRECTIONS = [Problem.MINIMIZE, Problem.MINIMIZE, Problem.MINIMIZE]

    n_reps = 30

    print(" * %d variables, %d objectives" % (D,OBJS))
    print(" * %d individuals, %d MAX_FEs, %d iterations, %d repetitions" % (POPSIZE, FEs, FEs//POPSIZE, n_reps)) 
    problem = Problem(D, OBJS)
    all_types = [Integer(0,2) for _ in range(D)]
    problem.types[:] = all_types
    problem.function = SIM.fitness
    problem.directions[:] = DIRECTIONS
    
    # Experimenter with NSGAII, NSGAIII and SPEA2
    algorithms = [(NSGAII, {"population_size":POPSIZE}),
                (NSGAIII, {"population_size":POPSIZE, "divisions_outer":12}),
                (SPEA2, {"population_size":POPSIZE})
                ]

    # Multi-processing (4 parallel processes)
    with ProcessPoolEvaluator(4) as evaluator:
        results = experiment(algorithms, problem, nfe=FEs, seeds=n_reps , evaluator=evaluator, display_stats=True)

        # As of Platypus v1.0.4, NSGA-III works only with minimization objectives
Пример #11
0
 def to_variables(self):
     return [Integer(0, len(self.categories) - 1)]
Пример #12
0
 def to_variables(self):
     return [
         Integer(self.min_value, self.max_value) for _ in range(self.length)
     ]
Пример #13
0
    def optimize(self):
        """
        Finds the optimized solution for the problem using multi objective
        genetic algorithms to build a pareto front
        """

        # 1
        self.removeCompulsory()

        # 2
        self.computeProfitAndUpdatedContractPrices()

        # 3
        self.computePossibleMoves()

        self.paretoFront = []
        # A PARETO SOLUTION MAKES LESS THAN 150 MOVES AND NO OTHER SOLUTION
        # GETS BETTER VALUES FOR ALL C+2 OBJECTIVES (neither some equal and at
        # least one better)

        def convertVariables2Matrix(x):
            """
            Converts problem variables to a solution matrix
            """
            xy = list(itertools.product(range(self.currentStack.shape[0]), range(self.currentStack.shape[1])))
            variable = [1 if len(self.possibleMoves[x][y]) > 0 else 0 for (x,y) in xy]
            a = []
            i = 0
            for j in range(len(list(variable))):
                if variable[j] == 1:
                    a.append(x[i])
                    i += 1
                else:
                    a.append(0)
            a = np.array(a)
            a = np.reshape(a, [10, 10])
            return a

        def func(x):
            """
            function that evaluates all the objectives of the solution and the
            restriction
            """
            a = convertVariables2Matrix(x)
            result = self.computeResult(a)
            constraint = result[-1]-self.remainingMoves
            return result, [constraint]

        # set of all x, y combinations
        xy = list(itertools.product(range(self.currentStack.shape[0]), range(self.currentStack.shape[1])))

        # the variables of the problem, integers representing how many containers
        # will be deliver from a given (x, y) coordinate
        integers = [Integer(0, len(self.possibleMoves[x][y])) for (x, y) in xy if len(self.possibleMoves[x][y]) > 0]

        # problem definition in platypus
        problem = Problem(len(integers), 4, 1)
        problem.types[:] = integers
        problem.function = func
        problem.directions[:] = Problem.MAXIMIZE
        problem.constraints[:] = "<=0"

        # algorithm choice (NSGAII)
        algorithm = NSGAII(problem)
        algorithm.run(1000000)

        # extracting results from the algorithm
        paretoFront = []
        for solution in algorithm.result:
            if solution.feasible:
                variables = []
                for i in range(len(integers)):
                    variables.append(integers[i].decode(solution.variables[i]))
                a = convertVariables2Matrix(variables)
                paretoFront.append((a, list(solution.objectives)))

        # finding closest solution to average result
        results = np.array([solution[1] for solution in paretoFront])
        averageResult = results.mean(axis=0)
        distances2Mean = []
        for result in results:
            distance2Mean = [((result[i]-averageResult[i])/averageResult)**2 for i in range(len(averageResult))]
            distance2Mean = np.sum(distance2Mean)
            distances2Mean.append(distance2Mean)
        bestIndex = np.argmin(distances2Mean)
        finalSolution = paretoFront[bestIndex][0] + self.moves

        # generating final report
        totalContractPrice = 0
        totalProfits = [0, 0]
        totalDelivered = 0
        movesDetails = []
        for x, y in itertools.product(range(finalSolution.shape[0]), range(finalSolution.shape[1])):
            amount2deliver = finalSolution[x][y]
            topContainer = self.port.getTopContainer(x, y)
            z = topContainer
            while amount2deliver > 0:
                containerID = self.containerStack[x, y, z]

                if containerID in self.promoted2updatedPrice:
                    contractPrice = self.promoted2updatedPrice[containerID]
                    assert contractPrice >= self.containerInfo[containerID][0]
                else:
                    contractPrice = self.containerInfo[containerID][0]
                bussinesValue = self.containerInfo[containerID][1]
                profit = bussinesValue - contractPrice
                totalContractPrice += contractPrice
                totalDelivered += 1
                if self.containerInfo[containerID][2] == "Carrefour":
                    totalProfits[0] += profit
                elif self.containerInfo[containerID][2] == "Metro":
                    totalProfits[1] += profit
                # if containerID in self.promoted2updatedPrice:
                movesDetails.append(f"Deliver container {containerID} from coordinate ({x+1}, {y+1}, {z+1}) with updated price {contractPrice}")
                # else:
                #     movesDetails.append(f"Deliver container {containerID} from coordinate ({x+1}, {y+1}, {z+1})")
                amount2deliver -= 1
                z -= 1
        with open("Final report.txt", 'w') as f:
            for line in movesDetails:
                f.write(line+"\n")
        with open("Final report performance.txt", 'w') as f:
            f.write(f"Total contract prices = {totalContractPrice}\n")
            f.write(f"Carrefour profits = {totalProfits[0]}\n")
            f.write(f"Metro profits = {totalProfits[1]}\n")
            f.write(f"Port Throughput = {totalDelivered}\n")
        print(totalContractPrice, totalProfits, totalDelivered)
Пример #14
0
def grid_multi_GA(nx=20,
                  ny=20,
                  volume_frac=0.5,
                  parent=400,
                  generation=100,
                  path="data"):
    PATH = os.path.join(path, "grid_nx_{}_ny_{}".format(nx, ny),
                        "gen_{}_pa_{}".format(generation, parent))
    os.makedirs(PATH, exist_ok=True)
    start = time.time()

    def objective(vars):
        rho = np.array(vars)
        rho = rho.reshape(ny, nx - 1)
        rho = np.concatenate([rho, np.ones((ny, 1))], 1)
        volume = np.sum(rho) / (nx * ny)

        return [calc_E(rho), calc_G(rho)], [volume]

    # 2変数2目的の問題
    problem = Problem(ny * (nx - 1), 2, 1)
    # 最小化or最大化を設定
    problem.directions[:] = Problem.MAXIMIZE

    # 決定変数の範囲を設定
    int1 = Integer(0, 1)
    problem.types[:] = int1
    problem.constraints[:] = "<=" + str(volume_frac)
    problem.function = objective
    problem.directions[:] = Problem.MAXIMIZE
    algorithm = NSGAII(problem, population_size=parent)
    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]:
        image_list = []
        for j in solution.variables:
            image_list.append(j)
        image = np.array(image_list).reshape(ny, nx - 1)
        image = np.concatenate([image, np.ones((ny, 1))], 1)
        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("grid_nx_{}_ny_{}_gen_{}_pa_{}:{}sec\n".format(
            nx, ny, generation, parent, elapsed_time))
Пример #15
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))
Пример #16
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)