在电力系统调度、物流路径规划等实际工程问题中,决策者常常面临两阶段决策场景:第一阶段需要提前确定基础设施投资或资源分配方案,第二阶段则需应对不确定因素(如需求波动、设备故障)下的实时调整。这类问题天然具备"决策-观测-响应"的时序特征,传统随机规划方法因依赖精确概率分布而存在局限性,而鲁棒优化通过设定不确定性集合来规避这一弱点。
列约束生成法(Column-and-Constraint Generation, CCG)作为求解两阶段鲁棒优化问题的经典算法,其核心思想是通过主问题(Master Problem)和子问题(Subproblem)的迭代求解,逐步逼近原问题的最优解。主问题负责生成候选的第一阶段决策方案,子问题则针对当前方案寻找最恶劣的不确定性情景,并将对应约束反馈给主问题。这种"切割平面"式的求解策略,特别适合处理具有离散决策变量和复杂耦合约束的工程优化问题。
典型的两阶段鲁棒优化问题可表述为:
code复制min_x c^T x + max_u∈U min_y d^T y
s.t. Ax ≥ b
Wy ≥ h - Tx - Mu
x∈X, y∈Y
其中x为第一阶段决策变量,y为第二阶段决策变量,u为不确定性参数。集合U描述不确定性的可能范围,通常采用多面体或椭球集合来表征。
在MATLAB中构建该模型时,建议采用结构体存储模型参数:
matlab复制model.c = [1; 2; 3]; % 第一阶段成本系数
model.d = [4; 5]; % 第二阶段成本系数
model.A = [1 0 1; 0 1 1]; % 第一阶段约束矩阵
model.W = [1 0; 0 1]; % 第二阶段约束矩阵
model.T = [1 0 0; 0 1 0]; % 耦合约束矩阵
model.U_vertices = [0 1; 1 0]; % 不确定性集合顶点
CCG算法的MATLAB实现核心在于构建主-子问题迭代循环:
matlab复制function [x_opt, obj_val] = CCG_solver(model, max_iter, tol)
% 初始化
LB = -inf; UB = inf;
x_hist = []; u_hist = [];
for k = 1:max_iter
% 主问题求解
[x_k, obj_k] = solve_master(model, x_hist, u_hist);
LB = max(LB, obj_k);
% 子问题求解
[u_k, y_k, sub_obj] = solve_subproblem(model, x_k);
UB = min(UB, model.c'*x_k + sub_obj);
% 收敛判断
if UB - LB < tol
break;
end
% 添加新约束
x_hist = [x_hist, x_k];
u_hist = [u_hist, u_k];
end
x_opt = x_k;
obj_val = UB;
end
关键实现细节:
matlab复制function [x, obj] = solve_master(model, x_hist, u_hist)
n_x = length(model.c);
n_scen = size(x_hist,2);
% 使用YALMIP建模
x = sdpvar(n_x,1);
eta = sdpvar(1,1); % 辅助变量
Constraints = [model.A*x >= model.b];
for s = 1:n_scen
% 添加场景割约束
Constraints = [Constraints, ...
eta >= model.d'*solve_subproblem(model, x_hist(:,s))];
end
optimize(Constraints, model.c'*x + eta);
x = value(x);
obj = value(model.c'*x + eta);
end
matlab复制function [u_opt, y_opt, obj] = solve_subproblem(model, x)
n_u = size(model.U_vertices,2);
n_y = length(model.d);
% 顶点法表示多面体集合
lambda = sdpvar(size(model.U_vertices,1),1);
u = sdpvar(n_u,1);
y = sdpvar(n_y,1);
Constraints = [...
u == model.U_vertices'*lambda, ...
sum(lambda) == 1, lambda >= 0, ...
model.W*y >= model.h - model.T*x - model.M*u];
optimize(Constraints, -model.d'*y);
u_opt = value(u);
y_opt = value(y);
obj = value(model.d'*y_opt);
end
对于高维不确定性集合,直接使用顶点枚举法会导致计算复杂度爆炸。可采用以下改进方案:
matlab复制% 椭球不确定性集合
model.U_norm = @(u) norm(u, 2) <= Gamma;
在子问题中转化为二阶锥约束:
matlab复制Constraints = [model.W*y >= model.h - model.T*x - model.M*u,
norm(u) <= Gamma];
matlab复制% 每个时段的不确定性总量受限
model.U_budget = @(u) sum(abs(u)) <= Gamma;
matlab复制% 使用极端场景初始化
u_hist = [model.U_vertices'; -model.U_vertices'];
matlab复制parfor s = 1:n_scen
[u_k{s}, y_k{s}, sub_obj(s)] = solve_subproblem(model, x_k);
end
[worst_obj, idx] = max(sub_obj);
u_worst = u_k{idx};
matlab复制% 限制相邻迭代解的变化幅度
delta = 0.1;
Constraints = [Constraints, norm(x - x_prev, inf) <= delta];
考虑微电网中光伏容量x的投资决策(第一阶段),面对光伏出力不确定性u∈[0.7, 1.3]倍预测值,需调度柴油发电机y满足负荷需求(第二阶段):
matlab复制model.c = 800; % 光伏单位投资成本
model.d = 1000; % 柴油发电成本
model.A = 1; % 光伏容量上限
model.b = 200; % 最大允许容量
model.W = 1; % 柴油机出力约束
model.h = 150; % 负荷需求
model.T = 1; % 光伏出力贡献
model.M = -1; % 不确定性影响
model.U_vertices = [0.7; 1.3]; % 出力波动范围
通过CCG算法迭代5次后收敛:
code复制迭代1: LB=120000, UB=195000
迭代2: LB=135000, UB=165000
迭代3: LB=142500, UB=157500
迭代4: LB=146250, UB=151875
迭代5: LB=148125, UB=150938 (收敛)
最优容量: x*=148.2 kW
研究预算参数Γ对解的影响:
matlab复制Gamma_range = 0:0.1:1;
results = zeros(length(Gamma_range),3);
for i = 1:length(Gamma_range)
model.U_norm = @(u) norm(u) <= Gamma_range(i);
[x_opt, obj] = CCG_solver(model, 10, 1e-3);
results(i,:) = [Gamma_range(i), x_opt, obj];
end
plot(results(:,1), results(:,2), 'o-');
xlabel('Uncertainty budget Γ');
ylabel('Optimal capacity (kW)');
matlab复制% 将成本系数归一化
max_c = max(abs(model.c));
model.c = model.c / max_c;
model.d = model.d / max_c;
matlab复制Constraints = [Constraints, norm(x, inf) <= 1e6];
matlab复制if any(all(abs(u_hist - u_k') < 1e-4, 2))
warning('Duplicate scenario detected');
break;
end
matlab复制if k > 3 && abs(UB_history(end)-UB_history(end-1)) < tol
% 启用加强切割
add_deep_cut();
end
matlab复制ops = sdpsettings('solver','gurobi','usex0',1);
optimize(Constraints, Objective, ops);
matlab复制% 识别并移除冗余约束
model.A = unique(round(model.A*1e6)/1e6, 'rows');
matlab复制ops = sdpsettings('solver','cplex',...
'cplex.timelimit',3600,...
'cplex.mip.tolerances.mipgap',1e-4);
matlab复制% 嵌套CCG算法
for stage = n_stages:-1:1
[x{stage}, obj(stage)] = CCG_solver(model{stage}, x{stage+1});
end
matlab复制% 基于历史数据构建集合
U_DR = Polyhedron('V', pca(historical_data));
matlab复制% 对区域分解问题并行求解
spmd
local_u = solve_local_subproblem(x_coord);
end
global_u = gcat(local_u, 1);
实际工程应用中,建议结合CPLEX或GUROBI等商业求解器提升大规模问题求解效率。对于特别复杂的问题,可考虑采用Benders分解与拉格朗日松弛的混合策略。在MATLAB实现时,使用YALMIP或CVX等建模工具可显著提升代码可读性和维护性。