[37] | 1 | function [solver,problem] = selectsolver(options,ProblemClass,solvers,socp_are_really_qc); |
---|
| 2 | %SELECTSOLVER Internal function to select solver based on problem category |
---|
| 3 | |
---|
| 4 | % Author Johan Löfberg |
---|
| 5 | % $Id: selectsolver.m,v 1.15 2006/08/17 08:11:22 joloef Exp $ |
---|
| 6 | |
---|
| 7 | problem = 0; |
---|
| 8 | |
---|
| 9 | % UNDOCUMENTED |
---|
| 10 | force_solver = yalmip('solver'); |
---|
| 11 | if length(force_solver)>0 |
---|
| 12 | options.solver = force_solver; |
---|
| 13 | end |
---|
| 14 | % *************************************************** |
---|
| 15 | % Maybe the user is stubborn and wants to pick solver |
---|
| 16 | % *************************************************** |
---|
| 17 | if length(options.solver)>0 & isempty(findstr(options.solver,'*')) |
---|
| 18 | |
---|
| 19 | % Create tags with version also |
---|
| 20 | temp = solvers; |
---|
| 21 | for i = 1:length(temp) |
---|
| 22 | if length(temp(i).version)>0 |
---|
| 23 | temp(i).tag = lower([temp(i).tag '-' temp(i).version]); |
---|
| 24 | end |
---|
| 25 | end |
---|
| 26 | |
---|
| 27 | opsolver = lower(options.solver); |
---|
| 28 | splits = findstr(opsolver,','); |
---|
| 29 | if isempty(splits) |
---|
| 30 | names{1} = opsolver; |
---|
| 31 | else |
---|
| 32 | start = 1; |
---|
| 33 | for i = 1:length(splits) |
---|
| 34 | names{i} = opsolver(start:splits(i)-1); |
---|
| 35 | start = splits(i)+1; |
---|
| 36 | end |
---|
| 37 | names{end+1} = opsolver(start:end); |
---|
| 38 | end |
---|
| 39 | |
---|
| 40 | index1 = []; |
---|
| 41 | index2 = []; |
---|
| 42 | for i = 1:length(names) |
---|
| 43 | index1 = [index1 find(strcmp(lower({solvers.tag}),names{i}))]; |
---|
| 44 | index2 = [index1 find(strcmp(lower({temp.tag}),names{i}))]; |
---|
| 45 | end |
---|
| 46 | if isempty(index1) & isempty(index2) |
---|
| 47 | solver = []; |
---|
| 48 | problem = -3; |
---|
| 49 | return; |
---|
| 50 | else |
---|
| 51 | solvers = solvers(union(index1,index2)); |
---|
| 52 | end |
---|
| 53 | end |
---|
| 54 | |
---|
| 55 | % ************************************************ |
---|
| 56 | % Prune based on objective |
---|
| 57 | % ************************************************ |
---|
| 58 | if ProblemClass.objective.sigmonial |
---|
| 59 | keep = ones(length(solvers),1); |
---|
| 60 | for i = 1:length(solvers) |
---|
| 61 | keep(i) = solvers(i).objective.sigmonial; |
---|
| 62 | end |
---|
| 63 | solvers = solvers(find(keep)); |
---|
| 64 | end |
---|
| 65 | if ProblemClass.objective.polynomial |
---|
| 66 | keep = ones(length(solvers),1); |
---|
| 67 | for i = 1:length(solvers) |
---|
| 68 | keep(i) = solvers(i).constraint.equalities.quadratic | solvers(i).constraint.inequalities.elementwise.quadratic.nonconvex | solvers(i).objective.polynomial | solvers(i).objective.sigmonial; |
---|
| 69 | end |
---|
| 70 | solvers = solvers(find(keep)); |
---|
| 71 | end |
---|
| 72 | if ProblemClass.objective.quadratic.nonconvex |
---|
| 73 | keep = ones(length(solvers),1); |
---|
| 74 | for i = 1:length(solvers) |
---|
| 75 | keep(i) = solvers(i).objective.polynomial | solvers(i).objective.sigmonial | solvers(i).objective.quadratic.nonconvex; |
---|
| 76 | end |
---|
| 77 | solvers = solvers(find(keep)); |
---|
| 78 | end |
---|
| 79 | if ProblemClass.objective.quadratic.convex |
---|
| 80 | keep = ones(length(solvers),1); |
---|
| 81 | for i = 1:length(solvers) |
---|
| 82 | direct = solvers(i).objective.polynomial | solvers(i).objective.sigmonial | solvers(i).objective.quadratic.nonconvex | solvers(i).objective.quadratic.convex; |
---|
| 83 | indirect = solvers(i).constraint.inequalities.semidefinite.linear | solvers(i).constraint.inequalities.secondordercone; |
---|
| 84 | if direct | indirect |
---|
| 85 | keep(i)=1; |
---|
| 86 | else |
---|
| 87 | keep(i)=0; |
---|
| 88 | end |
---|
| 89 | end |
---|
| 90 | solvers = solvers(find(keep)); |
---|
| 91 | end |
---|
| 92 | if ProblemClass.objective.linear |
---|
| 93 | keep = ones(length(solvers),1); |
---|
| 94 | for i = 1:length(solvers) |
---|
| 95 | keep(i) = solvers(i).objective.polynomial | solvers(i).objective.sigmonial | solvers(i).objective.quadratic.nonconvex | solvers(i).objective.quadratic.convex | solvers(i).objective.linear; |
---|
| 96 | end |
---|
| 97 | solvers = solvers(find(keep)); |
---|
| 98 | end |
---|
| 99 | if ProblemClass.objective.maxdet |
---|
| 100 | keep = ones(length(solvers),1); |
---|
| 101 | for i = 1:length(solvers) |
---|
| 102 | keep(i) = solvers(i).objective.maxdet | solvers(i).constraint.inequalities.semidefinite.linear; |
---|
| 103 | end |
---|
| 104 | solvers = solvers(find(keep)); |
---|
| 105 | end |
---|
| 106 | |
---|
| 107 | % ****************************************************** |
---|
| 108 | % Prune based on rank constraints |
---|
| 109 | % ****************************************************** |
---|
| 110 | if ProblemClass.constraint.inequalities.rank |
---|
| 111 | keep = ones(length(solvers),1); |
---|
| 112 | for i = 1:length(solvers) |
---|
| 113 | keep(i) = solvers(i).constraint.inequalities.rank; |
---|
| 114 | end |
---|
| 115 | solvers = solvers(find(keep)); |
---|
| 116 | end |
---|
| 117 | |
---|
| 118 | % ****************************************************** |
---|
| 119 | % Prune based on semidefinite constraints |
---|
| 120 | % ****************************************************** |
---|
| 121 | if ProblemClass.constraint.inequalities.semidefinite.sigmonial |
---|
| 122 | keep = ones(length(solvers),1); |
---|
| 123 | for i = 1:length(solvers) |
---|
| 124 | keep(i) = solvers(i).constraint.inequalities.semidefinite.sigmonial; |
---|
| 125 | end |
---|
| 126 | solvers = solvers(find(keep)); |
---|
| 127 | end |
---|
| 128 | if ProblemClass.constraint.inequalities.semidefinite.polynomial |
---|
| 129 | keep = ones(length(solvers),1); |
---|
| 130 | for i = 1:length(solvers) |
---|
| 131 | keep(i) = solvers(i).constraint.inequalities.semidefinite.sigmonial | solvers(i).constraint.inequalities.semidefinite.polynomial; |
---|
| 132 | end |
---|
| 133 | solvers = solvers(find(keep)); |
---|
| 134 | end |
---|
| 135 | if ProblemClass.constraint.inequalities.semidefinite.quadratic |
---|
| 136 | keep = ones(length(solvers),1); |
---|
| 137 | for i = 1:length(solvers) |
---|
| 138 | keep(i) = solvers(i).constraint.inequalities.semidefinite.sigmonial | solvers(i).constraint.inequalities.semidefinite.polynomial | solvers(i).constraint.inequalities.semidefinite.quadratic; |
---|
| 139 | end |
---|
| 140 | solvers = solvers(find(keep)); |
---|
| 141 | end |
---|
| 142 | if ProblemClass.constraint.inequalities.semidefinite.linear |
---|
| 143 | keep = ones(length(solvers),1); |
---|
| 144 | for i = 1:length(solvers) |
---|
| 145 | keep(i) = solvers(i).constraint.inequalities.semidefinite.sigmonial | solvers(i).constraint.inequalities.semidefinite.polynomial | solvers(i).constraint.inequalities.semidefinite.quadratic | solvers(i).constraint.inequalities.semidefinite.linear; |
---|
| 146 | end |
---|
| 147 | solvers = solvers(find(keep)); |
---|
| 148 | end |
---|
| 149 | |
---|
| 150 | % ****************************************************** |
---|
| 151 | % Prune based on second order cone constraints |
---|
| 152 | % ****************************************************** |
---|
| 153 | if ProblemClass.constraint.inequalities.secondordercone & ~socp_are_really_qc |
---|
| 154 | keep = ones(length(solvers),1); |
---|
| 155 | for i = 1:length(solvers) |
---|
| 156 | keep(i) = solvers(i).constraint.inequalities.secondordercone | solvers(i).constraint.inequalities.semidefinite.linear; |
---|
| 157 | end |
---|
| 158 | solvers = solvers(find(keep)); |
---|
| 159 | end |
---|
| 160 | if ProblemClass.constraint.inequalities.rotatedsecondordercone |
---|
| 161 | keep = ones(length(solvers),1); |
---|
| 162 | for i = 1:length(solvers) |
---|
| 163 | keep(i) = solvers(i).constraint.inequalities.rotatedsecondordercone | solvers(i).constraint.inequalities.secondordercone | solvers(i).constraint.inequalities.semidefinite.linear; |
---|
| 164 | end |
---|
| 165 | solvers = solvers(find(keep)); |
---|
| 166 | end |
---|
| 167 | |
---|
| 168 | % ****************************************************** |
---|
| 169 | % Prune based on element-wise inequality constraints |
---|
| 170 | % ****************************************************** |
---|
| 171 | if ProblemClass.constraint.inequalities.elementwise.sigmonial |
---|
| 172 | keep = ones(length(solvers),1); |
---|
| 173 | for i = 1:length(solvers) |
---|
| 174 | keep(i) = solvers(i).constraint.inequalities.elementwise.sigmonial; |
---|
| 175 | end |
---|
| 176 | solvers = solvers(find(keep)); |
---|
| 177 | end |
---|
| 178 | if ProblemClass.constraint.inequalities.elementwise.polynomial |
---|
| 179 | keep = ones(length(solvers),1); |
---|
| 180 | for i = 1:length(solvers) |
---|
| 181 | keep(i) = solvers(i).constraint.inequalities.elementwise.quadratic.nonconvex | solvers(i).constraint.inequalities.elementwise.sigmonial | solvers(i).constraint.inequalities.elementwise.polynomial; |
---|
| 182 | end |
---|
| 183 | solvers = solvers(find(keep)); |
---|
| 184 | end |
---|
| 185 | if ProblemClass.constraint.inequalities.elementwise.quadratic.nonconvex |
---|
| 186 | keep = ones(length(solvers),1); |
---|
| 187 | for i = 1:length(solvers) |
---|
| 188 | keep(i) = solvers(i).constraint.inequalities.elementwise.sigmonial | solvers(i).constraint.inequalities.elementwise.polynomial | solvers(i).constraint.inequalities.elementwise.quadratic.nonconvex; |
---|
| 189 | end |
---|
| 190 | solvers = solvers(find(keep)); |
---|
| 191 | end |
---|
| 192 | if ProblemClass.constraint.inequalities.elementwise.quadratic.convex | (ProblemClass.constraint.inequalities.secondordercone & socp_are_really_qc) |
---|
| 193 | keep = ones(length(solvers),1); |
---|
| 194 | for i = 1:length(solvers) |
---|
| 195 | keep(i) = solvers(i).constraint.inequalities.elementwise.sigmonial | solvers(i).constraint.inequalities.elementwise.polynomial | solvers(i).constraint.inequalities.elementwise.quadratic.nonconvex | solvers(i).constraint.inequalities.elementwise.quadratic.convex | solvers(i).constraint.inequalities.secondordercone | solvers(i).constraint.inequalities.semidefinite.linear; |
---|
| 196 | end |
---|
| 197 | solvers = solvers(find(keep)); |
---|
| 198 | end |
---|
| 199 | if ProblemClass.constraint.inequalities.elementwise.linear |
---|
| 200 | keep = ones(length(solvers),1); |
---|
| 201 | for i = 1:length(solvers) |
---|
| 202 | keep(i) = solvers(i).constraint.inequalities.elementwise.sigmonial | solvers(i).constraint.inequalities.elementwise.polynomial | solvers(i).constraint.inequalities.semidefinite.quadratic | solvers(i).constraint.inequalities.elementwise.linear; |
---|
| 203 | end |
---|
| 204 | solvers = solvers(find(keep)); |
---|
| 205 | end |
---|
| 206 | |
---|
| 207 | % ****************************************************** |
---|
| 208 | % Prune based on element-wise constraints |
---|
| 209 | % ****************************************************** |
---|
| 210 | if ProblemClass.constraint.equalities.sigmonial |
---|
| 211 | keep = ones(length(solvers),1); |
---|
| 212 | for i = 1:length(solvers) |
---|
| 213 | keep(i) = solvers(i).constraint.inequalities.elementwise.sigmonial | solvers(i).constraint.equalities.sigmonial; |
---|
| 214 | end |
---|
| 215 | solvers = solvers(find(keep)); |
---|
| 216 | end |
---|
| 217 | if ProblemClass.constraint.equalities.polynomial |
---|
| 218 | keep = ones(length(solvers),1); |
---|
| 219 | for i = 1:length(solvers) |
---|
| 220 | indirect = solvers(i).constraint.inequalities.elementwise.quadratic.nonconvex | solvers(i).constraint.inequalities.elementwise.sigmonial | solvers(i).constraint.inequalities.elementwise.polynomial; |
---|
| 221 | indirect = indirect | solvers(i).constraint.inequalities.elementwise.sigmonial | solvers(i).constraint.inequalities.elementwise.polynomial; |
---|
| 222 | direct = solvers(i).constraint.equalities.sigmonial | solvers(i).constraint.equalities.polynomial; |
---|
| 223 | keep(i) = direct | indirect; |
---|
| 224 | end |
---|
| 225 | solvers = solvers(find(keep)); |
---|
| 226 | end |
---|
| 227 | if ProblemClass.constraint.equalities.quadratic |
---|
| 228 | keep = ones(length(solvers),1); |
---|
| 229 | for i = 1:length(solvers) |
---|
| 230 | indirect = solvers(i).constraint.inequalities.elementwise.sigmonial | solvers(i).constraint.inequalities.elementwise.polynomial | solvers(i).constraint.inequalities.elementwise.quadratic.nonconvex; |
---|
| 231 | direct = solvers(i).constraint.equalities.sigmonial | solvers(i).constraint.equalities.polynomial | solvers(i).constraint.equalities.quadratic; |
---|
| 232 | keep(i) = direct | indirect; |
---|
| 233 | end |
---|
| 234 | solvers = solvers(find(keep)); |
---|
| 235 | end |
---|
| 236 | if ProblemClass.constraint.equalities.linear |
---|
| 237 | keep = ones(length(solvers),1); |
---|
| 238 | for i = 1:length(solvers) |
---|
| 239 | indirect = solvers(i).constraint.inequalities.elementwise.linear | solvers(i).constraint.inequalities.elementwise.sigmonial | solvers(i).constraint.inequalities.elementwise.polynomial; |
---|
| 240 | direct = solvers(i).constraint.equalities.linear | solvers(i).constraint.equalities.sigmonial | solvers(i).constraint.equalities.polynomial; |
---|
| 241 | keep(i) = direct | indirect; |
---|
| 242 | end |
---|
| 243 | solvers = solvers(find(keep)); |
---|
| 244 | end |
---|
| 245 | |
---|
| 246 | % ****************************************************** |
---|
| 247 | % Discrete data |
---|
| 248 | % ****************************************************** |
---|
| 249 | if ProblemClass.constraint.integer |
---|
| 250 | keep = ones(length(solvers),1); |
---|
| 251 | for i = 1:length(solvers) |
---|
| 252 | keep(i) = solvers(i).constraint.integer; |
---|
| 253 | end |
---|
| 254 | solvers = solvers(find(keep)); |
---|
| 255 | end |
---|
| 256 | if ProblemClass.constraint.binary |
---|
| 257 | keep = ones(length(solvers),1); |
---|
| 258 | for i = 1:length(solvers) |
---|
| 259 | keep(i) = solvers(i).constraint.integer | solvers(i).constraint.binary; |
---|
| 260 | end |
---|
| 261 | solvers = solvers(find(keep)); |
---|
| 262 | end |
---|
| 263 | |
---|
| 264 | % ****************************************************** |
---|
| 265 | % Parametric problem |
---|
| 266 | % ****************************************************** |
---|
| 267 | keep = ones(length(solvers),1); |
---|
| 268 | for i = 1:length(solvers) |
---|
| 269 | keep(i) = (ProblemClass.parametric == solvers(i).parametric); |
---|
| 270 | end |
---|
| 271 | solvers = solvers(find(keep)); |
---|
| 272 | |
---|
| 273 | % ****************************************************** |
---|
| 274 | % General functions (exp, log,...) |
---|
| 275 | % ****************************************************** |
---|
| 276 | keep = ones(length(solvers),1); |
---|
| 277 | for i = 1:length(solvers) |
---|
| 278 | keep(i) = (ProblemClass.evaluation <= solvers(i).evaluation); |
---|
| 279 | end |
---|
| 280 | solvers = solvers(find(keep)); |
---|
| 281 | |
---|
| 282 | % FIX : UUUUUUGLY |
---|
| 283 | if isempty(solvers) |
---|
| 284 | solver = []; |
---|
| 285 | else |
---|
| 286 | if length(options.solver)>0 |
---|
| 287 | solver = []; |
---|
| 288 | |
---|
| 289 | % FIX : Re-use from above |
---|
| 290 | opsolver = lower(options.solver); |
---|
| 291 | splits = findstr(opsolver,','); |
---|
| 292 | if isempty(splits) |
---|
| 293 | names{1} = opsolver; |
---|
| 294 | else |
---|
| 295 | names = {}; |
---|
| 296 | start = 1; |
---|
| 297 | for i = 1:length(splits) |
---|
| 298 | names{i} = opsolver(start:splits(i)-1); |
---|
| 299 | start = splits(i)+1; |
---|
| 300 | end |
---|
| 301 | names{end+1} = opsolver(start:end); |
---|
| 302 | end |
---|
| 303 | |
---|
| 304 | temp = solvers; |
---|
| 305 | for i = 1:length(temp) |
---|
| 306 | if length(temp(i).version)>0 |
---|
| 307 | temp(i).tag = lower([temp(i).tag '-' temp(i).version]); |
---|
| 308 | end |
---|
| 309 | end |
---|
| 310 | |
---|
| 311 | for i = 1:length(names) |
---|
| 312 | if isequal(names{i},'*') |
---|
| 313 | solver = solvers(1); |
---|
| 314 | break |
---|
| 315 | else |
---|
| 316 | j = find(strcmpi(lower({solvers.tag}),names{i})); |
---|
| 317 | if ~isempty(j) |
---|
| 318 | solver = solvers(j(1)); |
---|
| 319 | break |
---|
| 320 | end |
---|
| 321 | j = find(strcmpi(lower({temp.tag}),names{i})); |
---|
| 322 | if ~isempty(j) |
---|
| 323 | solver = solvers(j(1)); |
---|
| 324 | break |
---|
| 325 | end |
---|
| 326 | end |
---|
| 327 | end |
---|
| 328 | else |
---|
| 329 | solver = solvers(1); |
---|
| 330 | end |
---|
| 331 | end |
---|
| 332 | |
---|
| 333 | if isempty(solver) |
---|
| 334 | if length(options.solver)>0 % User selected available solver, but it is not applicable |
---|
| 335 | problem = -4; |
---|
| 336 | else |
---|
| 337 | problem = -2; |
---|
| 338 | end |
---|
| 339 | end |
---|
| 340 | |
---|
| 341 | % FIX : Hack when chosing the wrong fmincon thingy |
---|
| 342 | if ~isempty(solver) |
---|
| 343 | if (length(options.solver)==0 | isequal(options.solver,'fmincon')) & isequal(solver.tag,'fmincon') & isequal(solver.version,'geometric') |
---|
| 344 | if ~(ProblemClass.objective.sigmonial | ProblemClass.constraint.inequalities.elementwise.sigmonial) |
---|
| 345 | solver.version = 'standard'; |
---|
| 346 | solver.call = 'callfmincon'; |
---|
| 347 | solver.objective.linear = 1; |
---|
| 348 | solver.objective.quadratic.convex = 1; |
---|
| 349 | solver.objective.quadratic.nonconvex = 1; |
---|
| 350 | solver.objective.polynomial = 1; |
---|
| 351 | solver.objective.sigmonial = 1; |
---|
| 352 | solver.constraint.equalities.elementwise.linear = 1; |
---|
| 353 | solver.constraint.equalities.elementwise.quadratic.convex = 1; |
---|
| 354 | solver.constraint.equalities.elementwise.quadratic.nonconvex = 1; |
---|
| 355 | solver.constraint.equalities.elementwise.polynomial = 1; |
---|
| 356 | solver.constraint.equalities.elementwise.sigmonial = 1; |
---|
| 357 | solver.constraint.inequalities.elementwise.linear = 1; |
---|
| 358 | solver.constraint.inequalities.elementwise.quadratic.convex = 1; |
---|
| 359 | solver.constraint.inequalities.elementwise.quadratic.nonconvex = 1; |
---|
| 360 | solver.constraint.inequalities.elementwise.polynomial = 1; |
---|
| 361 | solver.constraint.inequalities.elementwise.sigmonial = 1; |
---|
| 362 | solver.constraint.inequalities.semidefinite.linear = 1; |
---|
| 363 | solver.constraint.inequalities.semidefinite.quadratic = 1; |
---|
| 364 | solver.constraint.inequalities.semidefinite.polynomial = 1; |
---|
| 365 | solver.dual = 1; |
---|
| 366 | end |
---|
| 367 | end |
---|
| 368 | end |
---|
| 369 | |
---|
| 370 | |
---|