You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用pymoo求解双目标整数优化问题时遇数组重塑错误求助

解决Pymoo NSGA-II整数变量双目标优化的维度不匹配错误

问题重现

使用Pymoo的NSGA-II求解5个整数变量的双目标优化问题时,出现以下错误:

Exception: ('Problem Error: F can not be set, expected shape (100, 2) but provided (1, 2)', ValueError('cannot reshape array of size 2 into shape (100,2)'))

原代码如下:

import numpy as np
from pymoo.core.problem import ElementwiseProblem
from pymoo.algorithms.moo.nsga2 import NSGA2
# from pymoo.factory import get_sampling, get_crossover, get_mutation
from pymoo.optimize import minimize
from pymoo.operators.sampling.rnd import IntegerRandomSampling
from pymoo.operators.crossover.sbx import SBX
from pymoo.operators.mutation.pm import PM
from pymoo.visualization.scatter import Scatter

# Custom 2-objective, 5-integer optimization problem
class MyProblem(Problem):
    def __init__(self):
        super().__init__(
            n_var=5,
            n_obj=2,
            n_ieq_constr=0,
            xl=np.array([0,0,0,0,0]),  # Lower bounds for variables
            xu=np.array([10,10,10,10,10]),  # Upper bounds for variables
            vtype=int
        )

    def _evaluate(self, x, out, *args, **kwargs):
        # Objective functions
        f1 = np.sum(x ** 2)  # Minimize the sum of squares
        f2 = np.sum((x - 5) ** 2)  # Minimize the sum of squared deviations from 5

        # Assign objectives to the output
        out["F"] = [f1, f2]

# Instantiate the custom problem
problem = MyProblem()

# NSGA-II algorithm setup
algorithm = NSGA2(
    pop_size=100,
    n_offsprings=50,
    sampling=IntegerRandomSampling(),
    crossover=SBX(prob=1.0, eta=3.0),
    mutation=PM(prob=1.0, eta=3.0)
)

# Optimize the problem using NSGA-II
res = minimize(
    problem, 
    algorithm, 
    termination=('n_gen', 100), 
    seed=1,
    save_history=True,
    verbose=True
)

# Visualize the Pareto front
plot = Scatter()
plot.add(problem.pareto_front(), plot_type="line", color="black", alpha=0.7)
plot.add(res.F, color="red", s=30, label="NSGA-II")
plot.show()

错误原因

  1. Problem类继承错误:导入了ElementwiseProblem但继承了未定义的Problem类,且ElementwiseProblem是逐个体评估的,而pymoo.core.problem.Problem要求批量处理所有个体(输入x形状为(pop_size, n_var)),你的_evaluate写法针对单个个体,导致批量处理时维度不匹配。
  2. 交叉变异算子不匹配整数变量:SBX和PM默认处理连续变量,未设置整数类型约束,可能导致变量变为非整数。
  3. 帕累托前沿未定义:自定义问题没有内置pareto_front()方法,直接调用会报错。

修正后的代码

import numpy as np
from pymoo.core.problem import ElementwiseProblem
from pymoo.algorithms.moo.nsga2 import NSGA2
from pymoo.optimize import minimize
from pymoo.operators.sampling.rnd import IntegerRandomSampling
from pymoo.operators.crossover.sbx import SBX
from pymoo.operators.mutation.pm import PM
from pymoo.visualization.scatter import Scatter
from itertools import product

# Custom 2-objective, 5-integer optimization problem
class MyProblem(ElementwiseProblem):
    def __init__(self):
        super().__init__(
            n_var=5,
            n_obj=2,
            n_ieq_constr=0,
            xl=np.array([0,0,0,0,0]),  # Lower bounds for variables
            xu=np.array([10,10,10,10,10]),  # Upper bounds for variables
            vtype=int
        )

    def _evaluate(self, x, out, *args, **kwargs):
        # Objective functions
        f1 = np.sum(x ** 2)  # Minimize the sum of squares
        f2 = np.sum((x - 5) ** 2)  # Minimize the sum of squared deviations from 5

        # Assign objectives as numpy array (shape (2,) for single individual)
        out["F"] = np.array([f1, f2])

# Instantiate the custom problem
problem = MyProblem()

# NSGA-II algorithm setup: Configure SBX and PM for integer variables
algorithm = NSGA2(
    pop_size=100,
    n_offsprings=50,
    sampling=IntegerRandomSampling(),
    # Set vtype=int for SBX to handle integers
    crossover=SBX(prob=1.0, eta=3.0, vtype=int),
    # Set vtype=int for PM to handle integers
    mutation=PM(prob=1.0, eta=3.0, vtype=int)
)

# Optimize the problem using NSGA-II
res = minimize(
    problem, 
    algorithm, 
    termination=('n_gen', 100), 
    seed=1,
    save_history=True,
    verbose=True
)

# Generate true Pareto front for this problem
def true_pareto_front():
    # Pareto optimal solutions have each x_i either 0 or 5 (trade-off between f1 and f2)
    pareto_F = []
    for combo in product([0,5], repeat=5):
        x = np.array(combo)
        f1 = np.sum(x**2)
        f2 = np.sum((x-5)**2)
        pareto_F.append([f1, f2])
    # Remove duplicate points
    pareto_F = np.unique(np.array(pareto_F), axis=0)
    return pareto_F

# Visualize results
plot = Scatter(title="Pareto Front Comparison", legend=True)
plot.add(true_pareto_front(), plot_type="line", color="black", alpha=0.7, label="True Pareto Front")
plot.add(res.F, color="red", s=30, label="NSGA-II Solutions")
plot.show()

关键修改说明

  • 继承正确的Problem类:将class MyProblem(Problem)改为class MyProblem(ElementwiseProblem),匹配逐个体评估的_evaluate实现。
  • 算子适配整数变量:在SBX和PM中添加vtype=int参数,确保交叉变异后输出为整数。
  • 定义真实帕累托前沿:手动生成该问题的帕累托最优解(所有变量取0或5的组合),用于可视化对比。
  • 输出numpy数组:将out["F"] = [f1, f2]改为out["F"] = np.array([f1, f2]),符合ElementwiseProblem的输出格式要求。

内容的提问来源于stack exchange,提问作者Dino Hsu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 13:17:05