Python SciPy.Optimize构建SCED约束字典报错咨询
问题原因
你遇到的两个报错和逻辑问题根源有三个:
LinearConstraint触发未知类型错误:该类构造器要求第一个参数为线性系数矩阵/线性算子,满足约束形式lb ≤ A @ x ≤ ub,直接传入决策变量切片不符合参数格式要求。NonlinearConstraint触发无属性A错误:一方面该类的第一个参数必须是输入决策变量、返回约束值的可调用函数,你直接传入数组切片本身参数非法;另一方面这类纯单变量边界约束是线性约束,部分求解器处理约束时会优先读取线性约束专属的A系数矩阵属性,非线性约束对象没有该属性,自然抛出属性错误。用非线性约束承载线性关系本身就会大幅拉低求解效率,完全不适合SCED这类大规模线性规划场景。- 约束生成逻辑存在严重bug:你写的三个约束生成函数,在双层for循环的第一次迭代(即t=0、g=0时)就直接return结果,最终只生成了1组3条约束,全时段、其余机组的几百上千条约束全部丢失,根本不符合建模需求。
正确实现方案
你需要的分段出力上下界是最基础的线性边界约束,不需要用非线性约束接口,根据建模习惯选以下任意一种方式实现即可:
方案1:直接通过变量边界传入(效率最高,推荐)
如果约束是给单个决策变量设置上下界,直接构造Bounds对象传入求解器即可,不需要单独构造约束对象,性能最优:
import numpy as np from scipy.optimize import Bounds # 先根据你的决策变量展平规则计算总变量数,示例为T个时段、G台机组、每台4段出力的场景 T = len(LOAD) G = len(GEN) SEG = 4 n_vars = T * G * SEG # 初始化所有变量默认上下界,无界的场景可以设为±np.inf lb = np.full(n_vars, -np.inf) ub = np.full(n_vars, np.inf) for t in range(T): for g in range(G): # 计算每个分段变量在展平后的一维索引,根据你自己的变量排列顺序调整即可 idx_seg2 = t * G * SEG + g * SEG + 1 idx_seg3 = t * G * SEG + g * SEG + 2 idx_seg4 = t * G * SEG + g * SEG + 3 # 给各段设置上下界 lb[idx_seg2] = 0 ub[idx_seg2] = P2Max[g] lb[idx_seg3] = 0 ub[idx_seg3] = P3Max[g] lb[idx_seg4] = 0 ub[idx_seg4] = P4Max[g] var_bounds = Bounds(lb=lb, ub=ub) # 求解时把var_bounds传给bounds参数即可
方案2:显式构造LinearConstraint(适合线性组合类约束场景)
如果后续需要加功率平衡、线路潮流这类多变量线性组合的约束,可以统一用LinearConstraint构造,注意第一个参数必须是系数矩阵,大规模问题优先用稀疏矩阵降低内存占用:
import numpy as np from scipy.optimize import LinearConstraint from scipy.sparse import csr_matrix T = len(LOAD) G = len(GEN) SEG = 4 n_vars = T * G * SEG A_data = [] A_row = [] A_col = [] con_lb = [] con_ub = [] current_row = 0 for t in range(T): for g in range(G): idx_seg2 = t * G * SEG + g * SEG + 1 idx_seg3 = t * G * SEG + g * SEG + 2 idx_seg4 = t * G * SEG + g * SEG + 3 # 第二段约束 A_data.append(1) A_row.append(current_row) A_col.append(idx_seg2) con_lb.append(0) con_ub.append(P2Max[g]) current_row += 1 # 第三段约束 A_data.append(1) A_row.append(current_row) A_col.append(idx_seg3) con_lb.append(0) con_ub.append(P3Max[g]) current_row += 1 # 第四段约束 A_data.append(1) A_row.append(current_row) A_col.append(idx_seg4) con_lb.append(0) con_ub.append(P4Max[g]) current_row += 1 # 构造稀疏系数矩阵 A = csr_matrix((A_data, (A_row, A_col)), shape=(current_row, n_vars)) seg_constraints = LinearConstraint(A=A, lb=np.array(con_lb), ub=np.array(con_ub)) # 把seg_constraints和其他约束一起放到约束元组里传入求解器即可
建模注意事项
- 不要在循环内部第一次迭代就return,要把所有时段、所有主体的约束全部收集完成后,再统一传入求解器。
- SCED属于大规模线性规划问题,所有线性约束优先用线性接口实现,尽量用稀疏矩阵存储系数,能把求解速度提升几个数量级。
- 单变量上下界优先用
Bounds传入,比单独构造线性约束的求解效率更高。
内容的提问来源于stack exchange,提问作者Demetra Salls
相关产品推荐
相关产品推荐

