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 solverparams = structUpdate(solverparams,params);
0094
0095
0096 if isfield(prob, 'csense')
0097 prob.sense = renameparams(prob.csense, {'L','G','E'}, {'<','>','='});
0098 prob = rmfield(prob, {'csense'});
0099 end
0100 if isfield(prob, 'osense')
0101 osense = prob.osense;
0102 prob.modelsense = renameparams(num2str(prob.osense), {'1','-1'}, {'min','max'});
0103 prob = rmfield(prob, {'osense'});
0104 end
0105 [prob.obj, prob.rhs, prob.vtype] = deal(prob.c, prob.b, prob.vartype);
0106 prob = rmfield(prob, {'c','b','vartype'});
0107
0108 resG = gurobi(prob,solverparams);
0109
0110 try
0111
0112 res.full = resG.x;
0113 res.obj = resG.objval;
0114 res.origStat = resG.status;
0115 if isfield(resG,{'pi','rc'})
0116 res.dual = -resG.pi*osense;
0117 res.rcost = -resG.rc*osense;
0118 end
0119 if milp && strcmp(resG.status, 'TIME_LIMIT')
0120
0121
0122 resG.status = 'OPTIMAL';
0123 end
0124 switch resG.status
0125 case 'OPTIMAL'
0126 res.stat = 1;
0127 case 'UNBOUNDED'
0128 res.stat = 2;
0129 otherwise
0130 res.stat = 0;
0131 end
0132 if ~milp
0133 res.vbasis = resG.vbasis;
0134 res.cbasis = resG.cbasis;
0135 else
0136 res.mipgap = resG.mipgap;
0137 end
0138 catch
0139 res.stat = 0;
0140 res.origStat = resG.status;
0141 end
0142
0143 case 'glpk'
0144 solverparams.scale = 1;
0145
0146 solverparams.tolbnd = defaultparams.feasTol;
0147 solverparams.toldj = defaultparams.optTol;
0148 solverparams.tolint = defaultparams.intTol;
0149 solverparams.tolobj = defaultparams.objTol;
0150 solverparams.msglev = 0;
0151 solverparams = structUpdate(solverparams,params);
0152
0153 prob.csense = renameparams(prob.csense, {'L','G','E'}, {'U','L','S'});
0154
0155 if milp
0156 solverparams.tmlim = solverparams.tmlim*10;
0157 solverparams.msglev = 1;
0158 disp('Issues have been observed when using GLPK for MILP solving. Be advised to carefully observe the results, or us another solver.')
0159 end
0160
0161
0162
0163 [ravenDir,currDir]=findRAVENroot();
0164 cd(fullfile(ravenDir,'software','GLPKmex'))
0165 [xopt, fmin, errnum, extra] = glpk(prob.c, prob.A, prob.b, prob.lb, prob.ub, prob.csense, prob.vartype, prob.osense, solverparams);
0166 cd(currDir)
0167
0168 switch errnum
0169 case 5
0170 res.stat = 1;
0171 case 2
0172 res.stat = 2;
0173 otherwise
0174 res.stat = 0;
0175 end
0176 res.origStat = errnum;
0177 res.full = xopt;
0178 res.obj = fmin;
0179 res.dual = -extra.lambda*prob.osense;
0180 res.rcost = -extra.redcosts*prob.osense;
0181
0182 case {'soplex','scip'}
0183 [xopt,fval,exitflag] = scip([], prob.c, prob.A,-prob.b, prob.b, prob.lb, prob.ub, prob.vartype);
0184
0185
0186
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 res.origStat = exitflag;
0236 res.full = xopt;
0237 res.obj = fval;
0238
0239 switch exitflag
0240 case 11
0241 res.stat = 1;
0242 case [5, 6, 7, 8, 9, 10, 13]
0243 res.stat = 2;
0244 otherwise
0245 res.stat = 0;
0246 end
0247 otherwise
0248 error('RAVEN solver not defined or unknown. Try using setRavenSolver(''solver'').');
0249 end
0250 if res.stat>0
0251 res.full=res.full(1:size(prob.a,2));
0252 end
0253 end
0254
0255 function s_merged=structUpdate(s_old,s_new)
0256
0257
0258
0259 s_merged = rmfield(s_old, intersect(fieldnames(s_old), fieldnames(s_new)));
0260 names = [fieldnames(s_merged); fieldnames(s_new)];
0261 s_merged = cell2struct([struct2cell(s_merged); struct2cell(s_new)], names, 1);
0262 end
0263
0264 function paramlist = renameparams(paramlist,old,new)
0265 if ~iscell(paramlist)
0266 wasNoCell = true;
0267 paramlist={paramlist};
0268 else
0269 wasNoCell = false;
0270 end
0271 for i=1:numel(old)
0272 paramlist = regexprep(paramlist,old{i},new{i});
0273 end
0274 if wasNoCell
0275 paramlist=paramlist{1};
0276 end
0277 end