Comparing MATLAB’s Optimization Toobox with Gurobi’s Python Interface Brian Pochinski UW-Milwaukee The Optimization Toolbox put out by MATLAB is able to solve a number of optimization problems including linear programming, quadratic programming, non-linear programming, constrained optimization and unconstrained optimization (“mathworks optimization”, 2014 http://www.mathworks.com/help/optim/functionlist.html). However, there are alternatives to the Optimization Toolbox. One such option is using the Gurobi Optimizer. Gurobi can interface with Python, C, C++, Java, R, and even MATLAB (Gurobi Optimizer Reference Manual, 2013). The present report will compare the use of the Optimization Toolbox with the Gurobi Python interface. Three examples will be presented. The first example is a linear programming problem, the second example is a binary integer programming problem, and the third will be a quadratic programming problem. Linear Programming MATLAB is able to solve linear programming problems with linprog which is part of the Optimization Toolbox. Mathworks offers information on linprog at “mathworks optimization” (2014) http://www.mathworks.com/help/optim/ug/linprog.html where the following example can be found. Find x that minimizes f(x) = –5x1 – 4x2 –6x3, subject to x1 – x2 + x3 ≤ 20 3x1 + 2x2 + 4x3 ≤ 42 3x1 + 2x2 ≤ 30 0 ≤ x1, 0 ≤ x2, 0 ≤ x3. f = [-5; -4; -6]; A = [1 -1 1 3 2 4 3 2 0]; b = [20; 42; 30]; lb = zeros(3,1); [x,fval,exitflag,output,lambda] = linprog(f,A,b,[],[],lb) As can be seen in the example, the f vector is the objective function we are trying to minimize. The A matrix is for the left side of the inequality contstraints and the b vector is for the right side inequality constraints. Had there been equality constraints, they would be represented by an Aeq matrix and a beq vector. The lb vector represents the lower bounds and if there were upper bounds they would be represented by a ub vector. Running this script will return the following output which shows the minimum value is -78 when X1 is 0, X2 is 15, and X3 is 3. >> lp Optimization terminated. x= 0.0000 15.0000 3.0000 fval = -78.0000 exitflag = 1 output = iterations: 6 algorithm: 'large-scale: interior point' cgiterations: 0 message: 'Optimization terminated.' constrviolation: 0 firstorderopt: 5.8705e-10 lambda = ineqlin: [3x1 double] eqlin: [0x1 double] upper: [3x1 double] lower: [3x1 double] You could do the same problem using the Gurobi Python interface. The Gurobi Optimizer Quick Start Guide (2013) offers an example and detailed description on how you could formulate an optimization problem. Adjusting the script allows you to solve the linear programming problems that can be solved with linprog. The following script solves the same linprog example from above: from gurobipy import * try: m = Model("mip1") x = m.addVar(vtype=GRB.CONTINUOUS, name="x") y = m.addVar(vtype=GRB.CONTINUOUS, name="y") z = m.addVar(vtype=GRB.CONTINUOUS, name="z") m.update() m.setObjective(-5 * x - 4 * y - 6 * z, GRB.MINIMIZE) m.addConstr(x - y + z <= 20, "c0") m.addConstr(3 * x + 2 * y + 4 * z <= 42, "c1") m.addConstr(3 * x + 2 * y <= 30, "c2") m.addConstr(x >= 0, "c3") m.addConstr(y >= 0, "c4") m.addConstr(z >= 0, "c5") m.optimize() for v in m.getVars(): print('%s %g' % (v.varName, v.x)) print('Obj: %g' % m.objVal) except GurobiError: print('Error reported') Gurobi Python scripts must begin with from gurobipy import * so that python can import Gurobi functions and classes. Creating the model m = Model("mip1") allows the user to do linear programming, integer programming, or binary integer programming. Variables are created using the syntax x = m.addVar(vtype=GRB.CONTINUOUS, name="x"). This simply specifies the variables that will be in our object function and constraints. Integer programming could be done by replacing CONTINUOUS WITH INTEGER and binary integer programming could be done by replacing CONTINUOUS with BINARY. Using m.update() in your script is only required if you will be doing modification later on, but it is not very important for our purposes. The objective function is called using m.setObjective(-5 * x - 4 * y - 6 * z, GRB.MINIMIZE). This is analogous to the f matrix in MATLAB. It is possible to do maximization problems by replacing MINIMIZE with MAXIMIZE. Constraints are added using m.addConstr(x - y + z <= 20, "c0"). The Gurobi Python interface can use =, <=, or >=. The constraints are analogous to the A and Aeq matrices and the b and beq vectors in MATLAB. Adding a name such as “c0” is optional and is simply for the user’s convenience. Finally, using m.optimize() tells the Gurobi Python interface we want to optimize the minimization or maximization problem. Running the script yields the following output: Optimize a model with 6 rows, 3 columns and 11 nonzeros Presolve removed 3 rows and 0 columns Presolve time: 0.00s Presolved: 3 rows, 3 columns, 8 nonzeros Iteration Objective Primal Inf. Dual Inf. Time 0 -1.7318800e+02 2.254400e+01 0.000000e+00 0s 3 -7.8000000e+01 0.000000e+00 0.000000e+00 0s Solved in 3 iterations and 0.01 seconds Optimal objective -7.800000000e+01 x0 y 15 z3 Obj: -78 This is the same solution found with linprog. The minimum value is -78 when X1 is 0, X2 is 15, and X3 is 3. One slight advantage offered by the Gurobi Python interface is that it can perform minimization or maximization problems avoiding any potential errors that could occur when changing a minimization problem to a maximization problem or vice-versa. Binary Integer Programming MATLAB’s Optimization Toolbox can also solve binary integer programming problems with bintprog. MATLAB offers information regarding bintprog and the following example at “mathworks optimization”, (2014) http://www.mathworks.com/help/optim/ug/bintprog.html. To minimize the function f(x) = –9x1 – 5x2 – 6x3 – 4x4, subject to the constraints where x1, x2, x3, and x4 are binary integers, enter the following commands f = [-9; -5; -6; -4]; A = [6 3 5 2; 0 0 1 1; -1 0 1 0; 0 -1 0 1]; b = [9; 1; 0; 0]; [x,fval] = bintprog(f,A,b) This is very similar to the linprog example already discussed. The only real difference is you are calling bintprog instead of linprog. You once again could add equality constraints with Aeq and beq and you could also add lower and upper bounds with lb and ub, respectively. Running the script reveals the following output which shows that the minimum value is -14 when X1 and X2 are equal to 1 and X3 and X4 are equal to 0. >> bp Optimization terminated. x= 1 1 0 0 fval = -14 As discussed earlier, The Gurobi Optimizer Quick Start Guide (2013) offers an example and detailed description on how you could formulate an optimization problem. Not only can the example be easily modified for linear programming, but it can also easily be adjusted for binary integer programming. The following script shows how to solve the previous bintprog example with the Gurobi Python interface: from gurobipy import * try: m = Model("mip1") w = m.addVar(vtype=GRB.BINARY, name="w") x = m.addVar(vtype=GRB.BINARY, name="x") y = m.addVar(vtype=GRB.BINARY, name="y") z = m.addVar(vtype=GRB.BINARY, name="z") m.update() m.setObjective(-9 * w - 5 * x - 6 * y - 4 * z, GRB.MINIMIZE) m.addConstr(6 * w + 3 * x + 5 * y + 2 * z <= 9, "c0") m.addConstr(y + z <= 1, "c1") m.addConstr(-1 * w + y <= 0) m.addConstr(-1 * x + z <= 0) m.optimize() for v in m.getVars(): print('%s %g' % (v.varName, v.x)) print('Obj: %g' % m.objVal) except GurobiError: print('Error reported') The only difference between this script and the first Gurobi Python script is that the objective functions and the constraints have changed and we have changed CONTINUOUS to BINARY in our variables. Conveniently, the Gurobi Python interface allows a combination of continuous, binary or even integer values for the variables in on a single script. Quadratic Programming Because not all optimization problems linear, MATLAB also offers the quadratic programming with the call quadprog. The major difference between linprog and quadprog is that quadprog uses an additional H matrix to represent the quadratic in the equation. More information regarding quadprog can be found at“mathworks optimization” (2014) http://www.mathworks.com/help/optim/ug/quadprog.html. In math 314 we discussed an example of the following quadratic programming problem (Wade, 2014): Minimize 5X(1)^2 – 2X(1)*X(2) + 5X(2)^2 Subject to X(1) + X(2) = 1 X(1) >= 0 X(2) >= 0 This is the MATLAB script and subsequent output for this quadratic programming problem: %EX3 f = [0 0]'; H = [10 -2; -2 10]; A = []; b = []; Aeq = [1 1]; beq = [1]; lb = [0 0]; ub = []; [x,fval] = quadprog(H,f,A,b,Aeq,beq,lb,ub) >> qpEX3 Optimization terminated. x= 0.5000 0.5000 fval = 2.0000 The f vector contains 0s because we have no linear part in our objective function. The 10s in the H matix come from our 5X(1)^2 and 5X(2)^2 and -2s come from -2X(1)*X(2). Everything else is the same as in linprog and bintprog. The Gurobi Python interface can also handle quadratic programming problems. The Gurobi Optimizer Example Tour (2013) offers an example script that can solve quadratic programming problems. Making slight adjustments allows you to solve a number of differnt quadratic programming problems. To solve a quadratic problem you must call the model “qp”. Lower bounds and upper bounds can be specified in your variables using lb and ub, respectively. Alternatively, you could include the upper and lower bounds inthe constraints. The quadratic programming problem discussed in class and solved above with quadprog can also be solved with the following Gurobi Python interface script: from gurobipy import * m = Model("qp") x = m.addVar(lb=0, name="x") y = m.addVar(lb=0, name="y") m.update() obj = 5*x*x - 2*x*y + 5*y*y m.setObjective(obj) m.addConstr(x + y <= 1, "c0") m.addConstr(x + y >= 1, "c1") m.optimize() for v in m.getVars(): print('%s %g' % (v.varName, v.x)) print('Obj: %g' % obj.getValue()) x.vType = GRB.CONTINUOUS y.vType = GRB.CONTINUOUS m.optimize() for v in m.getVars(): print('%s %g' % (v.varName, v.x)) print('Obj: %g' % obj.getValue()) Running this script gets the same answer as quadprog and the following output: Optimize a model with 2 rows, 2 columns and 4 nonzeros Model has 3 quadratic objective terms Presolve removed 1 rows and 0 columns Presolve time: 0.01s Presolved: 1 rows, 2 columns, 2 nonzeros Presolved model has 3 quadratic objective terms Ordering time: 0.00s Barrier statistics: Free vars : 1 AA' NZ : 1.000e+00 Factor NZ : 3.000e+00 Factor Ops : 5.000e+00 (less than 1 second per iteration) Threads : 1 Objective Iter Primal Dual Residual Primal Dual Compl Time 0 3.02003332e+05 -3.02003332e+05 1.25e+03 1.71e-06 1.00e+06 0s 1 3.47945551e+04 -3.64480440e+04 6.13e+01 8.41e-08 7.53e+04 0s 2 5.52349085e+00 -2.52066306e+03 5.12e-01 7.02e-10 1.91e+03 0s 3 4.44502731e+00 -3.13406218e+02 5.12e-07 8.88e-16 1.59e+02 0s 4 4.39306098e+00 -6.72971833e+00 1.71e-08 4.44e-16 5.56e+00 0s 5 2.90008045e+00 -1.15036959e+01 1.73e-14 1.11e-16 7.20e+00 0s 6 2.10426620e+00 7.60772624e-01 1.11e-16 2.22e-16 6.72e-01 0s 7 2.00010512e+00 1.93973288e+00 2.22e-15 1.53e-16 3.02e-02 0s 8 2.00000000e+00 1.99993957e+00 2.22e-16 2.22e-16 3.02e-05 0s 9 2.00000000e+00 1.99999994e+00 2.22e-16 2.22e-16 3.02e-08 0s 10 2.00000000e+00 2.00000000e+00 5.55e-17 1.96e-16 3.03e-11 0s Barrier solved model in 10 iterations and 0.07 seconds Optimal objective 2.00000000e+00 x 0.5 y 0.5 Obj: 2 While the Optimization Toolbox offers much convenience, there are alternative ways to go about optimization. Not only can you interface Gurobi with Python, but also with other languages such as C, C++, Java, R, and even MATLAB (Gurobi Optimizer Reference Manual, 2013). Gurobi can handle a number of optimization problems including linear programming, binary integer programming, integer programming, and quadratic programming. References Gurobi Optimizer Example Tour. (2013). Version 5.6. Retrieved from http://www.gurobi.com/documentation/5.6/example-tour/examples.pdf. Gurobi Optimizer Quick Start Guide. (2013). Version 5.6. Retrieved from http://www.gurobi.com/documentation/5.6/quick-start-guide/quickstart.pdf. Gurobi Optimizer Reference Manual. ( 2013). Version 5.6. Retrieved from http://www.gurobi.com/documentation/5.6/reference-manual/refman.pdf. “Mathworks Optimization” (2014). Functionlist. Retrieved from http://www.mathworks.com/help/optim/functionlist.html. “Mathworks Optimization” (2014). Bintprog. Retrieved from http://www.mathworks.com/help/optim/ug/bintprog.html. “Mathworks Optimization” (2014). Linprog. Retrieved from http://www.mathworks.com/help/optim/ug/linprog.html. Wade, B. (2014). Math 314. Mathametical Programming and Optimization. Lecture conducted at UWMilwaukee. Milwaukee, WI.