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

基于Pymoo的Excel模型单目标多整数变量优化报错排查

解决Pymoo结合pyWin32优化Excel模型的形状不匹配异常

异常信息

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

During handling of the above exception, another exception occurred:

File "C:\Database\Python\RSG\RSG Opt.py", line 71, in
res = minimize(
^^^^^^^^^
Exception: ('Problem Error: F can not be set, expected shape (100, 1) but provided (1, 1)', ValueError('cannot reshape array of size 1 into shape (100,1)'))

问题原因

你设置了GA的pop_size=100,Pymoo会一次性传入整个种群的100个个体进行评估,此时_evaluate方法的参数x形状为(100, num_vars),但你的代码把x当成单个个体处理,返回的out["F"]仅包含1个值,形状为(1,1),和Pymoo期望的(100,1)不匹配,导致报错。

修正方案

核心修改_evaluate方法,批量处理种群中的每个个体,确保返回的目标值和约束值形状匹配种群大小:

import win32com.client as win32
import numpy as np
from pymoo.core.problem import Problem
from pymoo.algorithms.soo.nonconvex.ga import GA
from pymoo.optimize import minimize

# Connect to Excel
excel = win32.gencache.EnsureDispatch('Excel.Application')
excel.Visible = True  # Keep Excel visible as set

# Reference the active workbook (assuming it's already open)
workbook = excel.ActiveWorkbook

# Prompt for the sheet name and range
sheet_name = input("Enter the sheet name: ")
range_address = input("Enter the variable range address (e.g., A1:B10): ")
target = input("Enter the objective cell address (e.g., A1:B10): ")

# Reference the specified sheet and range
try:
    worksheet = workbook.Sheets(sheet_name)
    variable_range = worksheet.Range(range_address)
    objective_cell = worksheet.Range(target)

except Exception as e:
    print(f"Error: {e}")
    excel.Quit()
    quit()

# Read the number of variables based on the number of rows in the range
num_vars = variable_range.Rows.Count
Vars = np.array(variable_range.Value)
trans_vars = np.transpose(Vars)

# Read the lower bounds from Excel (assuming they are in column -2)
lower_bounds_range = variable_range.GetOffset(0, -2)
lower_bounds = [int(cell.Value) for cell in lower_bounds_range]

# Read the upper bounds from Excel (assuming they are in column -1)
upper_bounds_range = variable_range.GetOffset(0, -1)
upper_bounds = [int(cell.Value) for cell in upper_bounds_range]


# Define the Optimization Problem
class ExcelOptimizationProblem(Problem):
    def __init__(self, num_vars, lower_bounds, upper_bounds):
        super().__init__(n_var=num_vars, n_obj=1, n_constr=1, xl=lower_bounds, xu=upper_bounds, type_var=int)

    def _evaluate(self, x, out, *args, **kwargs):
        # 存储每个个体的目标值
        f_values = []
        # 遍历种群中的每个个体
        for individual in x:
            # 将当前个体的变量值写入Excel
            for i, val in enumerate(individual):
                variable_range.Cells(1, 1).GetOffset(i, 0).Value = val
            # 触发Excel计算
            excel.Calculate()
            # 获取目标值并转换为浮点数
            objective_val = float(objective_cell.Value)
            # 加入列表(取负是因为默认最小化,若需最大化则取负)
            f_values.append(-objective_val)
        
        # 将目标值转换为Pymoo期望的形状:(种群大小, 目标数)
        out["F"] = np.array(f_values).reshape(-1, 1)
        # 约束值匹配种群大小,此处默认所有个体约束为0,可根据实际逻辑修改
        out["G"] = np.zeros((len(x), 1))

problem = ExcelOptimizationProblem(
    num_vars, lower_bounds, upper_bounds
)

algorithm = GA(
    pop_size=100,
    eliminate_duplicates=True)

res = minimize(
    problem, algorithm, ('n_gen', 10), verbose=True
)

print("Best solution found: \nX = %s\nF = %s" % (res.X, res.F))

workbook.Close()
excel.Quit()

补充说明

  • 代码会自动适配pop_size的数值,无需手动调整形状参数
  • 约束值G的逻辑可根据你的实际优化需求修改,只需保证最终形状为(种群大小, 约束数)即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 16:35:32