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