0001 function res = optimizeProb(prob,params,verbose)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 if nargin<2 || isempty(params)
0013 params=struct();
0014 end
0015 if nargin<3 || isempty(verbose)
0016 verbose = true;
0017 end
0018
0019
0020 global RAVENSOLVER;
0021 if isempty(RAVENSOLVER)
0022 if(~ispref('RAVEN','solver'))
0023 dispEM('RAVEN solver not defined or unknown. Try using setRavenSolver(''solver'').');
0024 else
0025 RAVENSOLVER = getpref('RAVEN','solver');
0026 end
0027 end
0028 solver=RAVENSOLVER;
0029 if ~all(lower(prob.vartype) == 'c')
0030 milp=true;
0031 errorText = 'glpk is not suitable for solving MILPs, ';
0032 switch solver
0033 case 'glpk'
0034 error([errorText 'select a different solver with setRavenSolver().'])
0035 case 'cobra'
0036 if strcmp(CBT_MILP_SOLVER,'glpk')
0037 error([errorText 'select a different solver with changeCobraSolver() or setRavenSolver().'])
0038 end
0039 end
0040 else
0041 milp=false;
0042 end
0043
0044
0045
0046 defaultparams.feasTol = 1e-9;
0047 defaultparams.optTol = 1e-9;
0048 defaultparams.objTol = 1e-6;
0049 defaultparams.timeLimit = 1000;
0050
0051 defaultparams.intTol = 1e-12;
0052 defaultparams.relMipGapTol = 1e-12;
0053 defaultparams.absMipGapTol = 1e-12;
0054 if milp
0055 defaultparams.MIPGap = 1e-12;
0056 defaultparams.Seed = 1;
0057 end
0058 res.obj=[];
0059 switch solver
0060
0061 case 'cobra'
0062 if milp
0063 cparams=struct('timeLimit',1e9,'printLevel',0,'intTol',1e-6,'relMipGapTol',1e-9);
0064 cparams=structUpdate(cparams,params);
0065 res=solveCobraMILP(prob,cparams);
0066 else
0067 res=solveCobraLP(prob);
0068 end
0069 if isfield(res,{'dual','rcost'})
0070 res.dual=res.dual;
0071 res.rcost=res.rcost;
0072 end
0073
0074
0075 case 'gurobi'
0076 if milp
0077 if verbose
0078 solverparams.OutputFlag = 1;
0079 else
0080 solverparams.OutputFlag = 0;
0081 end
0082 solverparams.IntFeasTol = 10^-9;
0083 solverparams.MIPGap = defaultparams.MIPGap;
0084 solverparams.Seed = defaultparams.Seed;
0085 else
0086 solverparams.OutputFlag = 0;
0087 end
0088 solverparams.DisplayInterval= 1;
0089 solverparams.TimeLimit = defaultparams.timeLimit;
0090 solverparams.FeasibilityTol = defaultparams.feasTol;
0091 solverparams.OptimalityTol = defaultparams.optTol;
0092 solverparams.Presolve = 2;
0093 if ~isempty(getCurrentTask)
0094 solverparams.Threads=1;
0095 end
0096 solverparams = structUpdate(solverparams,params);
0097
0098
0099 if isfield(prob, 'csense')
0100 prob.sense = renameparams(prob.csense, {'L','G','E'}, {'<','>','='});
0101 prob = rmfield(prob, {'csense'});
0102 end
0103 if isfield(prob, 'osense')
0104 osense = prob.osense;
0105 prob.modelsense = renameparams(num2str(prob.osense), {'1','-1'}, {'min','max'});
0106 prob = rmfield(prob, {'osense'});
0107 end
0108 [prob.obj, prob.rhs, prob.vtype] = deal(prob.c, prob.b, prob.vartype);
0109 prob = rmfield(prob, {'c','b','vartype'});
0110
0111 resG = gurobi(prob,solverparams);
0112
0113 try
0114
0115 res.full = resG.x;
0116 res.obj = resG.objval;
0117 res.origStat = resG.status;
0118 if isfield(resG,{'pi','rc'})
0119 res.dual = -resG.pi*osense;
0120 res.rcost = -resG.rc*osense;
0121 end
0122 if milp && strcmp(resG.status, 'TIME_LIMIT')
0123
0124
0125 resG.status = 'OPTIMAL';
0126 end
0127 switch resG.status
0128 case 'OPTIMAL'
0129 res.stat = 1;
0130 case 'UNBOUNDED'
0131 res.stat = 2;
0132 otherwise
0133 res.stat = 0;
0134 end
0135 if ~milp
0136 res.vbasis = resG.vbasis;
0137 res.cbasis = resG.cbasis;
0138 else
0139 res.mipgap = resG.mipgap;
0140 end
0141 catch
0142 res.stat = 0;
0143 res.origStat = resG.status;
0144 end
0145
0146 case 'glpk'
0147 solverparams.scale = 1;
0148
0149 solverparams.tolbnd = defaultparams.feasTol;
0150 solverparams.toldj = defaultparams.optTol;
0151 solverparams.tolint = defaultparams.intTol;
0152 solverparams.tolobj = defaultparams.objTol;
0153 solverparams.msglev = 0;
0154 solverparams = structUpdate(solverparams,params);
0155
0156 prob.csense = renameparams(prob.csense, {'L','G','E'}, {'U','L','S'});
0157
0158 if milp
0159 solverparams.tmlim = solverparams.tmlim*10;
0160 solverparams.msglev = 1;
0161 disp('Issues have been observed when using GLPK for MILP solving. Be advised to carefully observe the results, or us another solver.')
0162 end
0163
0164
0165
0166 [ravenDir,currDir]=findRAVENroot();
0167 cd(fullfile(ravenDir,'software','GLPKmex'))
0168 [xopt, fmin, errnum, extra] = glpk(prob.c, prob.A, prob.b, prob.lb, prob.ub, prob.csense, prob.vartype, prob.osense, solverparams);
0169 cd(currDir)
0170
0171 switch errnum
0172 case 5
0173 res.stat = 1;
0174 case 2
0175 res.stat = 2;
0176 otherwise
0177 res.stat = 0;
0178 end
0179 res.origStat = errnum;
0180 res.full = xopt;
0181 res.obj = fmin;
0182 res.dual = -extra.lambda*prob.osense;
0183 res.rcost = -extra.redcosts*prob.osense;
0184
0185 case {'soplex','scip'}
0186 [xopt,fval,exitflag] = scip([], prob.c, prob.A,-prob.b, prob.b, prob.lb, prob.ub, prob.vartype);
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238 res.origStat = exitflag;
0239 res.full = xopt;
0240 res.obj = fval;
0241
0242 switch exitflag
0243 case 11
0244 res.stat = 1;
0245 case [5, 6, 7, 8, 9, 10, 13]
0246 res.stat = 2;
0247 otherwise
0248 res.stat = 0;
0249 end
0250 otherwise
0251 error('RAVEN solver not defined or unknown. Try using setRavenSolver(''solver'').');
0252 end
0253 if res.stat>0
0254 res.full=res.full(1:size(prob.a,2));
0255 end
0256 end
0257
0258 function s_merged=structUpdate(s_old,s_new)
0259
0260
0261
0262 s_merged = rmfield(s_old, intersect(fieldnames(s_old), fieldnames(s_new)));
0263 names = [fieldnames(s_merged); fieldnames(s_new)];
0264 s_merged = cell2struct([struct2cell(s_merged); struct2cell(s_new)], names, 1);
0265 end
0266
0267 function paramlist = renameparams(paramlist,old,new)
0268 if ~iscell(paramlist)
0269 wasNoCell = true;
0270 paramlist={paramlist};
0271 else
0272 wasNoCell = false;
0273 end
0274 for i=1:numel(old)
0275 paramlist = regexprep(paramlist,old{i},new{i});
0276 end
0277 if wasNoCell
0278 paramlist=paramlist{1};
0279 end
0280 end