import numpy as np
from pymoo.util.misc import stack
from pymoo.core.problem import Problem
from pymoo.algorithms.moo.nsga2 import NSGA2
from pymoo.factory import get_sampling, get_crossover, get_mutation, get_termination, get_problem
from pymoo.optimize import minimize
from pymoo.visualization.scatter import Scatter
from pymoo.core.problem import ElementwiseProblem, dask_parallelized_eval
from pymoo.core.crossover import Crossover
from pymoo.core.mutation import Mutation
from pymoo.core.sampling import Sampling
from pymoo.algorithms.soo.nonconvex.ga import GA
from pymoo.optimize import minimize
from pymoo.util.display import Display
import matplotlib.pyplot as plt



class MyProblem(Problem):
    def __init__(self):
        super().__init__(n_var=2, # 入力変数の次元
                         n_obj=2, # 目的関数の数
                         n_constr=2, # 制約条件の数
                         xl=np.array([-2,-2]), # 入力変数の下限
                         xu=np.array([2,2]), # 入力変数の上限
                        )
    def _evaluate(self, X, out, *args, **kwargs):
        # 目的関数
        #f1 =(x1^2 + x2^2) <0 → min((x1^2 + x2^2)) → max(-(x1 -1)^2 - x2^2)でもある
        f1 = X[:,0]**2 + X[:,1]**2
        #f2 = (x1 -1)^2 + x2^2 <0 → min((x1 -1)^2 + x2^2) → max(-(x1 -1)^2 - x2^2)でもある
        f2 = (X[:,0]-1)**2 + X[:,1]**2

        # 制約条件
        #g1 = 2(x1 - 0.1)(x1 - 0.9)/0.18 =< 0 
        g1 = 2*(X[:, 0]-0.1) * (X[:, 0]-0.9) / 0.18
        #g2 = -20(x1 - 0.4)(x1 - 0.6)/4.8 =< 0 → 20(x1 - 0.4)(x1 - 0.6)/4.8 >= 0
        g2 = -20*(X[:, 0]-0.4) * (X[:, 0]-0.6) / 4.8
        out["F"] = np.column_stack([f1, f2])
        out["G"] = np.column_stack([g1, g2])

problem = MyProblem()

algorithm = NSGA2(pop_size=100)

res = minimize(problem,
               algorithm,
               ('n_gen', 200),
               seed=1,
               verbose=True)

plot = Scatter()
plot.add(problem.pareto_front(), plot_type="line", color="black", alpha=0.7)
plot.add(res.F, facecolor="none", edgecolor="red")
plot.show()
print("Best solution found: \nX = %s\nF = %s" % (res.X, res.F))