├── .gitattributes ├── BDforExample.m ├── CCGforExample.m ├── LICENSE ├── README.md └── Solving two-stage robust optimization problems using a column-and-constraint generation method.pdf /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /BDforExample.m: -------------------------------------------------------------------------------- 1 | %% Benders-dual method for Two-stage Robust Optimization 2 | % Original Problem: min_{y} c'*y + max_{u} min_{x∈F(y,u)} b'*x s.t. A*y>=d, y∈S_y 3 | % where F(y,u)={x∈S_x: G*x >= h - E*y - M*u} 4 | % SP1: max_{u,pi} {(h-E*s_y-Mu)'*pi: G'*pi<=b,u∈U,pi>=0} is solved by Gurobi 5 | % non-convex and produce a cutting plane for MP (but it's not effective since Gurobi non-convex is not that helpful in this problem...) 6 | % [1] Zeng, Bo, and Long Zhao. "Solving two-stage robust optimization problems using a column-and-constraint generation method." Operations Research Letters 41, no. 5 (2013): 457-461. 7 | 8 | clear all 9 | %% Constant and Parameter matrix setting 10 | f = [400, 414, 326]'; 11 | a = [18, 25, 20]'; 12 | C = [22, 33, 24; 13 | 33, 23, 30; 14 | 20, 25, 27]; 15 | b=[22, 33, 24, 33, 23, 30, 20, 25, 27]'; 16 | % # D = [206+40, 274+40, 220+40] 17 | dl = [206, 274, 220]'; 18 | du = [40, 40, 40]'; 19 | G=zeros(6,9); 20 | G(1,1:3)=-ones(1,3); 21 | G(2,4:6)=-ones(1,3); 22 | G(3,7:9)=-ones(1,3); 23 | G(4:6,1:3)=diag(ones(3,1)); 24 | G(4:6,4:6)=diag(ones(3,1)); 25 | G(4:6,7:9)=diag(ones(3,1)); 26 | E=zeros(6,6); 27 | E(1:3,4:6)=diag(ones(3,1)); 28 | M=zeros(6,3); 29 | M(4:6,:)=-diag(du.*ones(3,1)); 30 | h=zeros(6,1); 31 | h(4:6)=dl; 32 | BigM=1e5; 33 | 34 | %% Variable statement 35 | MaxIter=100; % Max iteration 36 | % for i=1:MaxIter 37 | % x{i}=sdpvar(9,MaxIter,'full'); 38 | % end 39 | x=sdpvar(9,1); 40 | y=binvar(3,1); 41 | z=sdpvar(3,1); 42 | pi=sdpvar(6,1); 43 | d=sdpvar(3,1); 44 | g=sdpvar(3,1); 45 | u=binvar(9,1); % ancillary binary variables for BigM on (b-G'*pi).*x==0, u(j)==0 means x(j)==0, (b-G'*pi)(j) free 46 | v=binvar(6,1); % ancillary binary variables for BigM on (G*x-(h-E*y-M*g)).*pi==0, v(i)==0 means pi(i)==0, (G*x-(h-E*y-M*g))(i) free 47 | 48 | %% Benders-dual (cutting plane) algorithm 49 | LB=-inf; 50 | UB=inf; 51 | k=1; 52 | O=[]; 53 | % s_g{1}=[0;0;1]; 54 | eta=sdpvar(1); 55 | Obj_MP2=[f;a]'*[y;z]+eta; 56 | Cons_MP2=[z<=800*y, x>=0, z>=0, eta>=0, sum(z)>=772]; 57 | % sum(z)>=772 is added because we need to ensure Subproblem is feasible 58 | % when s_y and s_z is produced in first-round of MP2. 59 | Cons_MP2=[Cons_MP2, eta>=b'*x]; 60 | ops=sdpsettings('solver','gurobi','verbose',0); 61 | 62 | Epsilon=0.01; 63 | while UB-LB>=Epsilon 64 | % Solve MP2 65 | sol_MP2=optimize(Cons_MP2,Obj_MP2,ops); 66 | s_y=value(y); 67 | s_z=value(z); 68 | s_eta=value(eta); 69 | LB=value(Obj_MP2); 70 | 71 | % % Solve SP1 by Gurobi Non-convex is not effective, since it could 72 | % stuck and time-consuming. 73 | % Obj_SP1 = (h-E*[s_y;s_z]-M*g)'*pi; 74 | % Cons_SP1=[pi>=0, G'*pi<=b, 1>=g>=0, sum(g)<=1.8, g(1)+g(2)<=1.2, d==dl+du.*g]; 75 | % sol_SP1=optimize(Cons_SP1,-Obj_SP1,ops); 76 | % s_g = value(g); 77 | % s_pi = value(pi); 78 | 79 | % Solve SP2 80 | Obj_SP2 = -b'*x; 81 | Cons_SP2 = [pi>=0, x>=0, G'*pi<=b, 1>=g>=0, sum(g)<=1.8, g(1)+g(2)<=1.2, d==dl+du.*g]; 82 | Cons_SP2 = [Cons_SP2, G*x >= h-E*[s_y;s_z]-M*g]; 83 | Cons_SP2 = [Cons_SP2, (h(1:3)-E(1:3,:)*[s_y;s_z]-M(1:3,:)*g)-G(1:3,:)*x <= BigM*(1-v(1:3)), pi<=BigM*v,... 84 | G(4:6,:)*x-(h(4:6)-E(4:6,:)*[s_y;s_z]-M(4:6,:)*g) <= BigM*(1-v(4:6))]; 85 | % !!! Important Note: if we use 86 | % Cons_SP2 = [Cons_SP2, (h-E*[s_y;s_z]-M*g)-G*x(:,k) <= BigM*(1-v)]; 87 | % here, it would not work !!! Because we need 88 | % to put left-hand side of "XXX >= 0" in Big-M method to be "XXX <= BigM*(1-v)". 89 | Cons_SP2 = [Cons_SP2, b-G'*pi <= BigM*(1-u), x<=BigM*u]; 90 | sol_SP2 = optimize(Cons_SP2,Obj_SP2,ops); 91 | s_g=value(g); 92 | s_pi=value(pi); 93 | 94 | % Add constraints in MP2 (unlike CCG algorithm, this time new varialbes are not added in MP2) 95 | if sol_SP2.problem==0 % SP2 is solved 96 | UB=min(UB,[f;a]'*[s_y;s_z]+value(-Obj_SP2)); 97 | display(['Iter ',num2str(k),' g = ',num2str(s_g')]); 98 | Cons_MP2 = [Cons_MP2, eta>=( h - E*[y;z] - M*s_g )'*s_pi]; 99 | else % SP2 is unbounded, not completed yet. Because still don't know how to identify scenario for which Q(s_y)=inf., 100 | Cons_MP2 = [Cons_MP2]; 101 | end 102 | 103 | k=k+1; 104 | display(['UB: ',num2str(UB),' LB: ',num2str(LB)]); 105 | if k>=100 106 | break 107 | end 108 | end -------------------------------------------------------------------------------- /CCGforExample.m: -------------------------------------------------------------------------------- 1 | %% CCG algorithm for Two-stage Robust Optimization 2 | % Original Problem: min_{y} c'*y + max_{u} min_{x∈F(y,u)} b'*x s.t. A*y>=d, y∈S_y 3 | % where F(y,u)={x∈S_x: G*x >= h - E*y - M*u} 4 | % SP2: max_{u in U} min_{x} {b'*x: G*x>=h-E*s_y-Mu, G'*pi<=b, u∈U, pi>=0} is 5 | % solved by its MIP recouse derived by KKT conditions. 6 | % [1] Zeng, Bo, and Long Zhao. "Solving two-stage robust optimization problems using a column-and-constraint generation method." Operations Research Letters 41, no. 5 (2013): 457-461. 7 | 8 | clear all 9 | %% Constant and Parameter matrix setting 10 | f = [400, 414, 326]'; 11 | a = [18, 25, 20]'; 12 | C = [22, 33, 24; 13 | 33, 23, 30; 14 | 20, 25, 27]; 15 | b=[22, 33, 24, 33, 23, 30, 20, 25, 27]'; 16 | dl = [206, 274, 220]'; 17 | du = [40, 40, 40]'; 18 | G=zeros(6,9); 19 | G(1,1:3)=-ones(1,3); 20 | G(2,4:6)=-ones(1,3); 21 | G(3,7:9)=-ones(1,3); 22 | G(4:6,1:3)=diag(ones(3,1)); 23 | G(4:6,4:6)=diag(ones(3,1)); 24 | G(4:6,7:9)=diag(ones(3,1)); 25 | E=zeros(6,6); 26 | E(1:3,4:6)=diag(ones(3,1)); 27 | M=zeros(6,3); 28 | M(4:6,:)=-diag(du.*ones(3,1)); 29 | h=zeros(6,1); 30 | h(4:6)=dl; 31 | BigM=1e5; 32 | 33 | %% Variable statement 34 | MaxIter=100; % Max iteration 35 | % for i=1:MaxIter 36 | % x{i}=sdpvar(9,MaxIter,'full'); 37 | % end 38 | x=sdpvar(9,MaxIter,'full'); 39 | y=binvar(3,1); 40 | z=sdpvar(3,1); 41 | pi=sdpvar(6,1); 42 | d=sdpvar(3,1); 43 | g=sdpvar(3,1); 44 | u=binvar(9,1); % ancillary binary variables for BigM on (b-G'*pi).*x==0, u(j)==0 means x(j)==0, (b-G'*pi)(j) free 45 | v=binvar(6,1); % ancillary binary variables for BigM on (G*x-(h-E*y-M*g)).*pi==0, v(i)==0 means pi(i)==0, (G*x-(h-E*y-M*g))(i) free 46 | 47 | %% CCG algorithm 48 | % Original Problem: min_{y} c'*y + max_{u} min_{x∈F(y,u)} b'*x s.t. A*y>=d, 49 | % y∈S_y 50 | % where F(y,u)={x∈S_x: G*x >= h - E*y - M*u} 51 | % SP2: max_{u,pi} {(h-E*y-Mu)'*pi:G'*pi<=b,u∈U,pi>=0} 52 | LB=-inf; 53 | UB=inf; 54 | k=1; 55 | eta=sdpvar(1); 56 | Obj_MP2=[f;a]'*[y;z]+eta; 57 | Cons_MP2=[z<=800*y, x(:,1)>=0, z>=0, eta>=0, sum(z)>=772]; 58 | % sum(z)>=772 is added because we need to ensure Subproblem is feasible 59 | % when s_y and s_z is produced in first-round of MP2. 60 | % Cons_MP2=[Cons_MP2, eta>=b'*x(:,1)]; 61 | ops=sdpsettings('solver','gurobi','verbose',0); 62 | 63 | Epsilon=0.01; 64 | while UB-LB>=Epsilon 65 | % Solve MP2 66 | sol_MP2=optimize(Cons_MP2,Obj_MP2,ops); 67 | s_y=value(y); 68 | s_z=value(z); 69 | s_eta=value(eta); 70 | LB=value(Obj_MP2); 71 | 72 | % Solve SP2 73 | Obj_SP2 = -b'*x(:,k); 74 | Cons_SP2 = [pi>=0, x(:,k)>=0, G'*pi<=b, 1>=g>=0, sum(g)<=1.8, g(1)+g(2)<=1.2, d==dl+du.*g]; 75 | Cons_SP2 = [Cons_SP2, G*x(:,k) >= h-E*[s_y;s_z]-M*g]; 76 | Cons_SP2 = [Cons_SP2, G*x(:,k)-(h-E*[s_y;s_z]-M*g) <= BigM*(1-v), pi<=BigM*v]; 77 | Cons_SP2 = [Cons_SP2, b-G'*pi <= BigM*(1-u), x(:,k)<=BigM*u]; 78 | sol_SP2 = optimize(Cons_SP2,Obj_SP2,ops); 79 | s_g = value(g); 80 | 81 | % Add constraints and variables "x(:,k+1)" in MP2 82 | if sol_SP2.problem==0 % SP2 is solved 83 | UB=min(UB,[f;a]'*[s_y;s_z]+value(-Obj_SP2)); 84 | display(['Iter ',num2str(k),' g = ',num2str(s_g')]); 85 | Cons_MP2 = [Cons_MP2, eta>=b'*x(:,k+1), E*[y;z]+G*x(:,k+1)>=h-M*s_g, x(:,k+1)>=0]; 86 | % !!! "x(:,k+1)>=0" is important!!! Dont't forget it !!! 87 | else % SP2 is unbounded, not completed yet. Because still don't know how to identify scenario for which Q(y*)=inf., i.e. s_g could not be produced. 88 | Cons_MP2 = [Cons_MP2, eta>=b'*x(:,k+1), E*[y;z]+G*x(:,k+1)>=h-M*s_g, x(:,k+1)>=0]; 89 | end 90 | 91 | k=k+1; 92 | display(['UB: ',num2str(UB),' LB: ',num2str(LB)]); 93 | if k>=100 94 | break 95 | end 96 | end -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Shen Xinwei 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Benders-dual/CCG Algorithm for Two-Stage Robust Optimization 2 | This project contains two MATLAB files explain Benders-dual/Column and Constraints Generation (CCG) Algorithm to solve Two-Stage Robust Optimization (RO) problems, as below (The uncertainty set $\mathcal{U}$ could be a discrete set or a polyhedron.): 3 | ![image](https://user-images.githubusercontent.com/11343667/181718512-b07c68b6-7e4f-4e6f-80cd-9d01cc22c952.png) 4 | - Bold characters (**A,y,x,c,d,u...**) denote matrix/vector in above. 5 | - CCG is proposed in [1]. It's very fashion in optimization for power systems/integrated energy systems and has been cited 1000+ times. 6 | - "BDforExample.m"/"CCGforExample.m" explains benders-dual/CCG to solve Two-Stage RO problems 7 | - The example used in both files are from *4. Case study: robust location-transportation problem* in [1] 8 | - MATLAB optimization modeling tool YALMIP supports constraints writing in the fashion of “Cons = [A*x<=b]”, in which A is a matrix and x, b are vectors, therefore, the codes in both files are easy to read. (at least I believe so...) 9 | - Because they are just like what you can see about the mathematical model in the paper. 10 | # Must-include package 11 | - For both files: **YALMIP**, see (https://yalmip.github.io/) 12 | - Both files are calling GUROBI(https://www.gurobi.com/) to solve the problem, but other solvers (e.g. CPLEX) could be used as well. (see what solvers they support in abovementioned link for YALMIP). 13 | # What you (maybe) can learn 14 | - Basics of Benders-dual/CCG Algorithm to solve Two-Stage RO problems 15 | - A simple way to realize optimization modeling in MATLAB (ONLY ~100 lines are in both .m files) 16 | # What you CANNOT learn 17 | - **How to do in by yourself (just try it by yourself and you would definitely learn more!)** 18 | # Acknowledgement 19 | - [鲁棒优化| C&CG算法求解两阶段鲁棒优化:全网最完整、最详细的【入门-完整推导-代码实现】笔记](https://zhuanlan.zhihu.com/p/534285185). I found some tricky point in it about how to guarantee Master problem could provide initial feasible solution for Subproblem to make both algorithms work (i.e. constraint in MP "sum(z)>=772" in both files), so thanks. 20 | # To be updated/some issue 21 | - When Subproblem is unbounded both file would fail. Because I still don't know how to identify scenario for which Q(y*)=inf. 22 | # Ref 23 | [1] Zeng, Bo, and Long Zhao. "Solving two-stage robust optimization problems using a column-and-constraint generation method." Operations Research Letters 41, no. 5 (2013): 457-461. 24 | -------------------------------------------------------------------------------- /Solving two-stage robust optimization problems using a column-and-constraint generation method.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a280558071/CCG-Algorithm-for-TwoStageRobustOptimization/7ad62da8eeb2445f1021a98040bfacd1d3ad0eea/Solving two-stage robust optimization problems using a column-and-constraint generation method.pdf --------------------------------------------------------------------------------