0001 function rv = have_fcn(tag, rtype)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113 persistent fcns;
0114
0115 action = 'D';
0116 if nargin > 1
0117 if isnumeric(rtype)
0118 action = 'T';
0119 on_off = rtype;
0120 if on_off < 0
0121 TorF = have_fcn(tag);
0122 on_off = ~TorF;
0123 end
0124 else
0125 switch lower(rtype)
0126 case 'get_cache'
0127 action = 'C';
0128 rv = fcns;
0129 case 'set_cache'
0130 action = 'C';
0131 fcns = tag;
0132 case 'clear_cache'
0133 action = 'C';
0134 if strcmpi(tag, 'all')
0135 fcns = struct();
0136 else
0137 fcns = rmfield(fcns, tag);
0138 end
0139 end
0140 end
0141 end
0142
0143 if action == 'T'
0144 if on_off
0145 fcns = rmfield(fcns, tag);
0146 else
0147 if ~isfield(fcns, tag)
0148 TorF = have_fcn(tag);
0149 end
0150 fcns.(tag).av = 0;
0151 end
0152 TorF = have_fcn(tag);
0153
0154 elseif action == 'D'
0155
0156 if ~isfield(fcns, tag)
0157
0158
0159 TorF = 0;
0160 vstr = '';
0161 rdate = '';
0162
0163 switch tag
0164
0165 case 'bpmpd'
0166 TorF = exist('bp', 'file') == 3;
0167 if TorF
0168 v = bpver('all');
0169 vstr = v.Version;
0170 rdate = v.Date;
0171 end
0172 case 'clp'
0173 tmp = have_fcn('opti_clp', 'all');
0174 if tmp.av
0175 TorF = tmp.av;
0176 vstr = tmp.vstr;
0177 rdate = tmp.date;
0178 elseif exist('clp','file') == 2 && exist('mexclp','file') == 3
0179 TorF = 1;
0180 vstr = '';
0181 end
0182 case 'opti_clp'
0183 TorF = exist('opti_clp', 'file') == 2 && exist('clp', 'file') == 3;
0184 if TorF
0185 str = evalc('clp');
0186 pat = 'CLP: COIN-OR Linear Programming \[v([^\s,]+), Built ([^\],])+(,[^\]]*)*\]';
0187 [s,e,tE,m,t] = regexp(str, pat);
0188 if ~isempty(t)
0189 vstr = t{1}{1};
0190 rdate = datestr(t{1}{2}, 'dd-mmm-yyyy');
0191 end
0192 end
0193 case 'cplex'
0194 if exist('cplexqp', 'file')
0195
0196 p = which('cplexqp');
0197 len = length(p) - length('cplexqp.p');
0198 w = what(p(1:len));
0199 for k = 1:length(w.mex)
0200 if regexp(w.mex{k}, 'cplexlink[^\.]*');
0201 TorF = 1;
0202 break;
0203 end
0204 end
0205 end
0206 if TorF
0207 try
0208 cplex = Cplex('null');
0209 vstr = cplex.getVersion;
0210 catch
0211 TorF = 0;
0212 end
0213 end
0214 case 'e4st'
0215 TorF = exist('e4st_ver', 'file') == 2;
0216 if TorF
0217 v = e4st_ver('all');
0218 vstr = v.Version;
0219 rdate = v.Date;
0220 end
0221 case {'fmincon', 'fmincon_ipm', 'intlinprog', 'linprog', ...
0222 'linprog_ds', 'optimoptions', 'quadprog', 'quadprog_ls'}
0223 matlab = have_fcn('matlab');
0224 if ~matlab || (matlab && license('test', 'optimization_toolbox'))
0225 v = ver('optim');
0226 if length(v) > 1
0227 warning('The built-in VER command is behaving strangely, probably as a result of installing a 3rd party toolbox in a directory named ''optim'' on your path. Check each element of the output of ver(''optim'') to find the offending toolbox, then move the toolbox to a more appropriately named directory.');
0228 v = v(1);
0229 end
0230 if isempty(v) || isempty(v.Version)
0231 vstr = '';
0232 rdate = [];
0233 else
0234 vstr = v.Version;
0235 rdate = v.Date;
0236 end
0237 otver = vstr2num(vstr);
0238 switch tag
0239 case 'fmincon'
0240 TorF = (exist('fmincon', 'file') == 2 || ...
0241 exist('fmincon', 'file') == 6) & matlab;
0242 case 'intlinprog'
0243 TorF = exist('intlinprog', 'file') == 2 & matlab;
0244 case 'linprog'
0245 TorF = exist('linprog', 'file') == 2 & matlab;
0246 case 'quadprog'
0247 TorF = exist('quadprog', 'file') == 2;
0248
0249
0250
0251 if ~matlab && otver <= 1.005
0252 TorF = 0;
0253 end
0254 otherwise
0255 if matlab
0256 switch tag
0257 case 'fmincon_ipm'
0258 if otver >= 4
0259 TorF = 1;
0260 end
0261 case 'linprog_ds'
0262 if otver >= 7.001
0263 TorF = 1;
0264 end
0265 case 'optimoptions'
0266 if otver >= 6.003
0267 TorF = 1;
0268 end
0269 case 'quadprog_ls'
0270 if otver >= 6
0271 TorF = 1;
0272 end
0273 end
0274 else
0275 TorF = 0;
0276 end
0277 end
0278 end
0279 case 'glpk'
0280 if exist('glpk','file') == 3
0281 TorF = 1;
0282 str = evalc('glpk');
0283 pat = 'GLPK: GNU Linear Programming Kit \[v([^\s,\]]+).*\]';
0284 [s,e,tE,m,t] = regexp(str, pat);
0285 if ~isempty(t)
0286 vstr = t{1}{1};
0287 end
0288 pat = 'Built ([^\],])+';
0289 [s,e,tE,m,t] = regexp(str, pat);
0290 if ~isempty(t)
0291 rdate = datestr(t{1}{1}, 'dd-mmm-yyyy');
0292 end
0293 elseif exist('glpk','file') == 2
0294 if exist('__glpk__','file') == 3
0295 TorF = 1;
0296 if have_fcn('evalc')
0297 str = evalc('glpk(1, 1, 1, 1, 1, ''U'', ''C'', -1, struct(''msglev'', 3))');
0298 pat = 'GLPK Simplex Optimizer, v([^\s,]+)';
0299 [s,e,tE,m,t] = regexp(str, pat);
0300 if ~isempty(t)
0301 vstr = t{1}{1};
0302 end
0303 end
0304 elseif exist('glpkcc','file') == 3
0305 TorF = 1;
0306 str = evalc('glpk');
0307 pat = 'GLPK Matlab interface\. Version: ([^\s,]+)';
0308 [s,e,tE,m,t] = regexp(str, pat);
0309 if ~isempty(t)
0310 vstr = t{1}{1};
0311 end
0312 end
0313 end
0314 case 'gurobi'
0315 TorF = exist('gurobi', 'file') == 3;
0316 if TorF
0317 try
0318 model = struct( ...
0319 'A', sparse(1), ...
0320 'rhs', 1, ...
0321 'sense', '=', ...
0322 'vtype', 'C', ...
0323 'obj', 1, ...
0324 'modelsense', 'min' ...
0325 );
0326 params = struct( ...
0327 'outputflag', 0 ...
0328 );
0329 result = gurobi(model, params);
0330 vstr = sprintf('%d.%d.%d', result.versioninfo.major, result.versioninfo.minor, result.versioninfo.technical);
0331 catch
0332 TorF = 0;
0333 fprintf('Gurobi Error!\n');
0334
0335 end
0336 end
0337 case 'ipopt'
0338 TorF = exist('ipopt', 'file') == 3;
0339 if TorF
0340 if have_fcn('evalc')
0341 str = evalc('qps_ipopt([],[1; 1],[1 1],[2],[2],[1; 1],[1; 1],[1; 1],struct(''verbose'', 2))');
0342 pat = 'Ipopt version ([^\s,]+)';
0343 [s,e,tE,m,t] = regexp(str, pat);
0344 if ~isempty(t)
0345 vstr = t{1}{1};
0346 if vstr2num(vstr) >= 3.011 && ...
0347 ~exist('ipopt_auxdata', 'file')
0348 TorF = 0;
0349 warning('Improper installation of IPOPT. Version %s detected, but IPOPT_AUXDATA.M is missing.', vstr);
0350 end
0351 end
0352 else
0353 try
0354
0355 x = feval('qps_ipopt', [],[1; 1],[1 1],[2],[2],[1; 1],[1; 1],[1; 1],struct('verbose', 0));
0356 if ~isequal(x, [1;1])
0357 TorF = 0;
0358 end
0359 catch
0360 TorF = 0;
0361 end
0362 end
0363 end
0364 case 'knitro'
0365 tmp = have_fcn('knitromatlab', 'all');
0366 if tmp.av
0367 TorF = tmp.av;
0368 vstr = tmp.vstr;
0369 rdate = tmp.date;
0370 else
0371 tmp = have_fcn('ktrlink', 'all');
0372 if tmp.av
0373 TorF = tmp.av;
0374 vstr = tmp.vstr;
0375 rdate = tmp.date;
0376 end
0377 end
0378 case {'knitromatlab', 'ktrlink'}
0379
0380
0381 TorF = exist(tag, 'file') == 2;
0382 if TorF
0383 try
0384 str = evalc(['[x fval] = ' tag '(@(x)1,1);']);
0385 end
0386 TorF = exist('fval', 'var') && fval == 1;
0387 if TorF
0388 pat = 'KNITRO ([^\s]+)\n|Knitro ([^\s]+)\n';
0389 [s,e,tE,m,t] = regexp(str, pat);
0390 if ~isempty(t)
0391 vstr = t{1}{1};
0392 end
0393 end
0394 end
0395 case 'matlab'
0396 v = ver('matlab');
0397 if length(v) > 1
0398 warning('The built-in VER command is behaving strangely, probably as a result of installing a 3rd party toolbox in a directory named ''matlab'' on your path. Check each element of the output of ver(''matlab'') to find the offending toolbox, then move the toolbox to a more appropriately named directory.');
0399 v = v(1);
0400 end
0401 if ~isempty(v) && isfield(v, 'Version') && ~isempty(v.Version)
0402 TorF = 1;
0403 vstr = v.Version;
0404 rdate = v.Date;
0405 end
0406 case 'minopf'
0407 TorF = exist('minopf', 'file') == 3;
0408 if TorF
0409 v = minopfver('all');
0410 vstr = v.Version;
0411 rdate = v.Date;
0412 end
0413 case 'most'
0414 TorF = exist('most', 'file') == 2;
0415 if TorF
0416 v = mostver('all');
0417 vstr = v.Version;
0418 rdate = v.Date;
0419 end
0420 case 'mosek'
0421 TorF = exist('mosekopt', 'file') == 3;
0422 if TorF
0423
0424
0425
0426 pat = 'Version (\.*\d)+.*Build date: (\d+-\d+-\d+)';
0427 [s,e,tE,m,t] = regexp(evalc('mosekopt'), pat);
0428 if isempty(t)
0429 [r, res] = mosekopt('version');
0430 v = res.version;
0431 vstr = sprintf('%d.%d.%d.%d', ...
0432 v.major, v.minor, v.build, v.revision);
0433 else
0434 vstr = t{1}{1};
0435 rdate = datestr(t{1}{2}, 'dd-mmm-yyyy');
0436 end
0437 end
0438 case 'smartmarket'
0439 TorF = exist('runmarket', 'file') == 2;
0440 if TorF
0441 v = mpver('all');
0442 vstr = v.Version;
0443 rdate = v.Date;
0444 end
0445 case 'syngrid'
0446 TorF = exist('syngrid', 'file') == 2;
0447 if TorF
0448 v = sgver('all');
0449 vstr = v.Version;
0450 rdate = v.Date;
0451 end
0452 case 'octave'
0453 TorF = exist('OCTAVE_VERSION', 'builtin') == 5;
0454 if TorF
0455 v = ver('octave');
0456 vstr = v.Version;
0457 rdate = v.Date;
0458 end
0459 case 'pardiso'
0460 TorF = have_fcn('pardiso_object') || have_fcn('pardiso_legacy');
0461 case {'pdipmopf', 'scpdipmopf', 'tralmopf'}
0462 if have_fcn('matlab')
0463 vn = have_fcn('matlab', 'vnum');
0464
0465
0466
0467 if vn >= 6.005
0468 switch tag
0469 case 'pdipmopf'
0470 TorF = exist('pdipmopf', 'file') == 3;
0471 case 'scpdipmopf'
0472 TorF = exist('scpdipmopf', 'file') == 3;
0473 case 'tralmopf'
0474
0475
0476 if vn >= 7.003
0477 TorF = exist('tralmopf', 'file') == 3;
0478 end
0479 end
0480 end
0481 if TorF
0482 v = feval([tag 'ver'], 'all');
0483 vstr = v.Version;
0484 rdate = v.Date;
0485 end
0486 end
0487 case 'sdp_pf'
0488 TorF = have_fcn('yalmip') && exist('mpoption_info_sdp_pf', 'file') == 2;
0489 if TorF
0490 v = sdp_pf_ver('all');
0491 vstr = v.Version;
0492 rdate = v.Date;
0493 end
0494 case 'yalmip'
0495 TorF = exist('yalmip','file') == 2;
0496 if TorF
0497 vstr = yalmip('version');
0498 if length(vstr) == 8
0499 yr = str2num(vstr(1:4));
0500 mo = str2num(vstr(5:6));
0501 dy = str2num(vstr(7:8));
0502 rdate = datestr([yr mo dy 0 0 0], 'dd-mmm-yyyy');
0503 end
0504 end
0505 case 'sdpt3'
0506 TorF = exist('sdpt3','file') == 2;
0507 if TorF && have_fcn('evalc')
0508 str = evalc('help sdpt3');
0509 pat = 'version\s+([^\s]+).*Last Modified: ([^\n]+)\n';
0510 [s,e,tE,m,t] = regexp(str, pat);
0511 if ~isempty(t)
0512 vstr = t{1}{1};
0513 rdate = datestr(t{1}{2}, 'dd-mmm-yyyy');
0514 end
0515 end
0516 case 'sedumi'
0517 TorF = exist('sedumi','file') == 2;
0518 if TorF && have_fcn('evalc')
0519 warn_state = warning;
0520 str = evalc('x = sedumi([1 1], 1, [1;2])');
0521 warning(warn_state);
0522 pat = 'SeDuMi\s+([^\s]+)';
0523 [s,e,tE,m,t] = regexp(str, pat);
0524 if ~isempty(t)
0525 vstr = t{1}{1};
0526 end
0527 end
0528
0529
0530 case 'catchme'
0531 if have_fcn('octave')
0532 if have_fcn('octave', 'vnum') > 3.006
0533 TorF = 1;
0534 end
0535 else
0536 if have_fcn('matlab', 'vnum') > 7.004
0537 TorF = 1;
0538 end
0539 end
0540 case 'evalc'
0541 if have_fcn('matlab')
0542 TorF = 1;
0543 end
0544 case 'ipopt_auxdata'
0545 if have_fcn('ipopt')
0546 vn = have_fcn('ipopt', 'vnum');
0547 if ~isempty(vn)
0548 if vn >= 3.011
0549 TorF = 1;
0550 else
0551 TorF = 0;
0552 end
0553
0554
0555 elseif exist('ipopt_auxdata', 'file')
0556 TorF = 1;
0557 else
0558 TorF = 0;
0559 end
0560 else
0561 TorF = 0;
0562 end
0563 case 'lu_vec'
0564 if have_fcn('matlab') && have_fcn('matlab', 'vnum') < 7.003
0565 TorF = 0;
0566 else
0567 TorF = 1;
0568 end
0569 case 'pardiso_object'
0570 TorF = exist('pardiso', 'file') == 2;
0571 if TorF
0572 try
0573 id = 1;
0574 A = sparse([1 2; 3 4]);
0575 b = [1;1];
0576 p = pardiso(id, 11, 0);
0577 p.factorize(id, A);
0578 x = p.solve(id, A, b);
0579 p.free(id);
0580 p.clear();
0581 if any(x ~= [-1; 1])
0582 TorF = 0;
0583 end
0584 catch
0585 TorF = 0;
0586 end
0587 end
0588 case 'pardiso_legacy'
0589 TorF = exist('pardisoinit', 'file') == 3 && ...
0590 exist('pardisoreorder', 'file') == 3 && ...
0591 exist('pardisofactor', 'file') == 3 && ...
0592 exist('pardisosolve', 'file') == 3 && ...
0593 exist('pardisofree', 'file') == 3;
0594 if TorF
0595 try
0596 A = sparse([1 2; 3 4]);
0597 b = [1;1];
0598 info = pardisoinit(11, 0);
0599 info = pardisoreorder(A, info, false);
0600
0601
0602
0603
0604
0605
0606 info = pardisofactor(A, info, false);
0607 [x, info] = pardisosolve(A, b, info, false);
0608 pardisofree(info);
0609 if any(x ~= [-1; 1])
0610 TorF = 0;
0611 end
0612 catch
0613 TorF = 0;
0614 end
0615 end
0616 case 'regexp_split'
0617 if have_fcn('matlab') && have_fcn('matlab', 'vnum') >= 7.003
0618 TorF = 1;
0619 elseif have_fcn('octave', 'vnum') >= 3.008
0620 TorF = 1;
0621 end
0622 case 'rithmaticker'
0623 TorF = exist('rithmaticker', 'file') == 2;
0624 if TorF
0625 vstr = '3.1.4';
0626 rdate = datestr([2019 5 30 0 0 0], 'dd-mmm-yyyy');
0627 end
0628
0629
0630 otherwise
0631 warning('have_fcn: unknown functionality ''%s''', tag);
0632 vstr = 'unknown';
0633 end
0634
0635
0636 fcns.(tag).av = TorF;
0637 fcns.(tag).vstr = vstr;
0638 if isempty(vstr)
0639 fcns.(tag).vnum = [];
0640 else
0641 fcns.(tag).vnum = vstr2num(vstr);
0642 end
0643 fcns.(tag).date = rdate;
0644 end
0645 end
0646
0647
0648 if action ~= 'C' || nargout
0649 if nargin < 2 || action == 'T'
0650 rv = fcns.(tag).av;
0651 else
0652 switch lower(rtype)
0653 case 'vstr'
0654 rv = fcns.(tag).vstr;
0655 case 'vnum'
0656 rv = fcns.(tag).vnum;
0657 case 'date'
0658 rv = fcns.(tag).date;
0659 case 'all'
0660 rv = fcns.(tag);
0661 end
0662 end
0663 end
0664
0665 function num = vstr2num(vstr)
0666
0667
0668 pat = '\.?(\d+)';
0669 [s,e,tE,m,t] = regexp(vstr, pat);
0670 b = 1;
0671 num = 0;
0672 for k = 1:length(t)
0673 num = num + b * str2num(t{k}{1});
0674 b = b / 1000;
0675 end