1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2 /* */ 3 /* This file is part of the class library */ 4 /* SoPlex --- the Sequential object-oriented simPlex. */ 5 /* */ 6 /* Copyright (c) 1996-2023 Zuse Institute Berlin (ZIB) */ 7 /* */ 8 /* Licensed under the Apache License, Version 2.0 (the "License"); */ 9 /* you may not use this file except in compliance with the License. */ 10 /* You may obtain a copy of the License at */ 11 /* */ 12 /* http://www.apache.org/licenses/LICENSE-2.0 */ 13 /* */ 14 /* Unless required by applicable law or agreed to in writing, software */ 15 /* distributed under the License is distributed on an "AS IS" BASIS, */ 16 /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ 17 /* See the License for the specific language governing permissions and */ 18 /* limitations under the License. */ 19 /* */ 20 /* You should have received a copy of the Apache-2.0 license */ 21 /* along with SoPlex; see the file LICENSE. If not email to soplex@zib.de. */ 22 /* */ 23 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 24 25 /**@file soplex.hpp 26 * @brief General templated functions for SoPlex 27 */ 28 29 /// maximum length of lines in settings file 30 #define SPX_SET_MAX_LINE_LEN 500 31 32 /// default setting for LU refactorization interval 33 #define SOPLEX_REFACTOR_INTERVAL 200 34 35 #ifdef _MSC_VER 36 #define strncasecmp _strnicmp 37 #endif 38 39 #ifndef _MSC_VER 40 #include <strings.h> 41 #endif 42 43 namespace soplex 44 { 45 template <class R> 46 typename SoPlexBase<R>::Settings::IntParam SoPlexBase<R>::Settings::intParam = IntParam(); 47 48 template <class R> 49 typename SoPlexBase<R>::Settings::RealParam SoPlexBase<R>::Settings::realParam = RealParam(); 50 51 template <class R> 52 typename SoPlexBase<R>::Settings::BoolParam SoPlexBase<R>::Settings::boolParam = BoolParam(); 53 54 template <class R> 55 SoPlexBase<R>::Settings::BoolParam::BoolParam() 56 { 57 // should lifting be used to reduce range of nonzero matrix coefficients? 58 name[SoPlexBase<R>::LIFTING] = "lifting"; 59 description[SoPlexBase<R>::LIFTING] = 60 "should lifting be used to reduce range of nonzero matrix coefficients?"; 61 defaultValue[SoPlexBase<R>::LIFTING] = false; 62 63 // should LP be transformed to equality form before a rational solve? 64 name[SoPlexBase<R>::EQTRANS] = "eqtrans"; 65 description[SoPlexBase<R>::EQTRANS] = 66 "should LP be transformed to equality form before a rational solve?"; 67 defaultValue[SoPlexBase<R>::EQTRANS] = false; 68 69 // should dual infeasibility be tested in order to try to return a dual solution even if primal infeasible? 70 name[SoPlexBase<R>::TESTDUALINF] = "testdualinf"; 71 description[SoPlexBase<R>::TESTDUALINF] = 72 "should dual infeasibility be tested in order to try to return a dual solution even if primal infeasible?"; 73 defaultValue[SoPlexBase<R>::TESTDUALINF] = false; 74 75 // should a rational factorization be performed after iterative refinement? 76 name[SoPlexBase<R>::RATFAC] = "ratfac"; 77 description[SoPlexBase<R>::RATFAC] = 78 "should a rational factorization be performed after iterative refinement?"; 79 defaultValue[SoPlexBase<R>::RATFAC] = true; 80 81 // should the decomposition based dual simplex be used to solve the LP? Setting this to true forces the solve mode to 82 // SOLVEMODE_REAL and the basis representation to REPRESENTATION_ROW 83 name[SoPlexBase<R>::USEDECOMPDUALSIMPLEX] = "decompositiondualsimplex"; 84 description[SoPlexBase<R>::USEDECOMPDUALSIMPLEX] = 85 "should the decomposition based dual simplex be used to solve the LP?"; 86 defaultValue[SoPlexBase<R>::USEDECOMPDUALSIMPLEX] = false; 87 88 // should the degeneracy be computed for each basis? 89 name[SoPlexBase<R>::COMPUTEDEGEN] = "computedegen"; 90 description[SoPlexBase<R>::COMPUTEDEGEN] = "should the degeneracy be computed for each basis?"; 91 defaultValue[SoPlexBase<R>::COMPUTEDEGEN] = false; 92 93 // should the dual of the complementary problem be used in the decomposition simplex? 94 name[SoPlexBase<R>::USECOMPDUAL] = "usecompdual"; 95 description[SoPlexBase<R>::USECOMPDUAL] = 96 "should the dual of the complementary problem be used in the decomposition simplex?"; 97 defaultValue[SoPlexBase<R>::USECOMPDUAL] = false; 98 99 /// should row and bound violations be computed explicitly in the update of reduced problem in the decomposition 100 // simplex 101 name[SoPlexBase<R>::EXPLICITVIOL] = "explicitviol"; 102 description[SoPlexBase<R>::EXPLICITVIOL] = 103 "Should violations of the original problem be explicitly computed in the decomposition simplex?"; 104 defaultValue[SoPlexBase<R>::EXPLICITVIOL] = false; 105 106 // should cycling solutions be accepted during iterative refinement? 107 name[SoPlexBase<R>::ACCEPTCYCLING] = "acceptcycling"; 108 description[SoPlexBase<R>::ACCEPTCYCLING] = 109 "should cycling solutions be accepted during iterative refinement?"; 110 defaultValue[SoPlexBase<R>::ACCEPTCYCLING] = false; 111 112 // apply rational reconstruction after each iterative refinement? 113 name[SoPlexBase<R>::RATREC] = "ratrec"; 114 description[SoPlexBase<R>::RATREC] = 115 "apply rational reconstruction after each iterative refinement?"; 116 defaultValue[SoPlexBase<R>::RATREC] = true; 117 118 // round scaling factors for iterative refinement to powers of two? 119 name[SoPlexBase<R>::POWERSCALING] = "powerscaling"; 120 description[SoPlexBase<R>::POWERSCALING] = 121 "round scaling factors for iterative refinement to powers of two?"; 122 defaultValue[SoPlexBase<R>::POWERSCALING] = true; 123 124 // continue iterative refinement with exact basic solution if not optimal? 125 name[SoPlexBase<R>::RATFACJUMP] = "ratfacjump"; 126 description[SoPlexBase<R>::RATFACJUMP] = 127 "continue iterative refinement with exact basic solution if not optimal?"; 128 defaultValue[SoPlexBase<R>::RATFACJUMP] = false; 129 130 // use bound flipping also for row representation? 131 name[SoPlexBase<R>::ROWBOUNDFLIPS] = "rowboundflips"; 132 description[SoPlexBase<R>::ROWBOUNDFLIPS] = "use bound flipping also for row representation?"; 133 defaultValue[SoPlexBase<R>::ROWBOUNDFLIPS] = false; 134 135 // use persistent scaling? 136 name[SoPlexBase<R>::PERSISTENTSCALING] = "persistentscaling"; 137 description[SoPlexBase<R>::PERSISTENTSCALING] = "should persistent scaling be used?"; 138 defaultValue[SoPlexBase<R>::PERSISTENTSCALING] = true; 139 140 // perturb the entire problem or only the relevant bounds of s single pivot? 141 name[SoPlexBase<R>::FULLPERTURBATION] = "fullperturbation"; 142 description[SoPlexBase<R>::FULLPERTURBATION] = 143 "should perturbation be applied to the entire problem?"; 144 defaultValue[SoPlexBase<R>::FULLPERTURBATION] = false; 145 146 /// re-optimize the original problem to get a proof of infeasibility/unboundedness? 147 name[SoPlexBase<R>::ENSURERAY] = "ensureray"; 148 description[SoPlexBase<R>::ENSURERAY] = 149 "re-optimize the original problem to get a proof (ray) of infeasibility/unboundedness?"; 150 defaultValue[SoPlexBase<R>::ENSURERAY] = false; 151 152 /// try to enforce that the optimal solution is a basic solution 153 name[SoPlexBase<Real>::FORCEBASIC] = "forcebasic"; 154 description[SoPlexBase<Real>::FORCEBASIC] = 155 "try to enforce that the optimal solution is a basic solution"; 156 defaultValue[SoPlexBase<Real>::FORCEBASIC] = false; 157 158 name[SoPlexBase<R>::SIMPLIFIER_SINGLETONCOLS] = "simplifier_enable_singletoncols"; 159 description[SoPlexBase<R>::SIMPLIFIER_SINGLETONCOLS] = 160 "enable presolver SingletonCols in PaPILO"; 161 defaultValue[SoPlexBase<R>::SIMPLIFIER_SINGLETONCOLS] = true; 162 163 name[SoPlexBase<R>::SIMPLIFIER_CONSTRAINTPROPAGATION] = "simplifier_enable_propagation"; 164 description[SoPlexBase<R>::SIMPLIFIER_CONSTRAINTPROPAGATION] = 165 "enable presolver ConstraintPropagation in PaPILO"; 166 defaultValue[SoPlexBase<R>::SIMPLIFIER_CONSTRAINTPROPAGATION] = true; 167 168 name[SoPlexBase<R>::SIMPLIFIER_PARALLELROWDETECTION] = "simplifier_enable_parallelrows"; 169 description[SoPlexBase<R>::SIMPLIFIER_PARALLELROWDETECTION] = 170 "enable presolver ParallelRowDetection in PaPILO"; 171 defaultValue[SoPlexBase<R>::SIMPLIFIER_PARALLELROWDETECTION] = true; 172 173 name[SoPlexBase<R>::SIMPLIFIER_PARALLELCOLDETECTION] = "simplifier_enable_parallelcols"; 174 description[SoPlexBase<R>::SIMPLIFIER_PARALLELCOLDETECTION] = 175 "enable presolver ParallelColDetection in PaPILO"; 176 defaultValue[SoPlexBase<R>::SIMPLIFIER_PARALLELCOLDETECTION] = true; 177 178 name[SoPlexBase<R>::SIMPLIFIER_SINGLETONSTUFFING] = "simplifier_enable_stuffing"; 179 description[SoPlexBase<R>::SIMPLIFIER_SINGLETONSTUFFING] = 180 "enable presolver SingletonStuffing in PaPILO"; 181 defaultValue[SoPlexBase<R>::SIMPLIFIER_SINGLETONSTUFFING] = true; 182 183 name[SoPlexBase<R>::SIMPLIFIER_DUALFIX] = "simplifier_enable_dualfix"; 184 description[SoPlexBase<R>::SIMPLIFIER_DUALFIX] = 185 "enable presolver DualFix in PaPILO"; 186 defaultValue[SoPlexBase<R>::SIMPLIFIER_DUALFIX] = true; 187 188 name[SoPlexBase<R>::SIMPLIFIER_FIXCONTINUOUS] = "simplifier_enable_fixcontinuous"; 189 description[SoPlexBase<R>::SIMPLIFIER_FIXCONTINUOUS] = 190 "enable presolver FixContinuous in PaPILO"; 191 defaultValue[SoPlexBase<R>::SIMPLIFIER_FIXCONTINUOUS] = true; 192 193 name[SoPlexBase<R>::SIMPLIFIER_DOMINATEDCOLS] = "simplifier_enable_domcol"; 194 description[SoPlexBase<R>::SIMPLIFIER_DOMINATEDCOLS] = 195 "enable presolver DominatedCols in PaPILO"; 196 defaultValue[SoPlexBase<R>::SIMPLIFIER_DOMINATEDCOLS] = true; 197 198 name[SoPlexBase<R>::ITERATIVE_REFINEMENT] = "iterative_refinement"; 199 description[SoPlexBase<R>::ITERATIVE_REFINEMENT] = 200 "enable iterative refinement"; 201 defaultValue[SoPlexBase<R>::ITERATIVE_REFINEMENT] = true; 202 203 // adapt tolerances to the multiprecision used 204 name[SoPlexBase<R>::ADAPT_TOLS_TO_MULTIPRECISION] = "adapt_tols_to_multiprecision"; 205 description[SoPlexBase<R>::ADAPT_TOLS_TO_MULTIPRECISION] = 206 "adapt tolerances to the multiprecision used"; 207 defaultValue[SoPlexBase<R>::ADAPT_TOLS_TO_MULTIPRECISION] = false; 208 209 name[SoPlexBase<R>::PRECISION_BOOSTING] = "precision_boosting"; 210 description[SoPlexBase<R>::PRECISION_BOOSTING] = 211 "enable precision boosting"; 212 #ifdef SOPLEX_WITH_MPFR 213 defaultValue[SoPlexBase<R>::PRECISION_BOOSTING] = true; 214 #else 215 defaultValue[SoPlexBase<R>::PRECISION_BOOSTING] = false; 216 #endif 217 218 name[SoPlexBase<R>::BOOSTED_WARM_START] = "boosted_warm_start"; 219 description[SoPlexBase<R>::BOOSTED_WARM_START] = 220 "if true, boosted solver starts from last basis, otherwise from slack basis"; 221 defaultValue[SoPlexBase<R>::BOOSTED_WARM_START] = true; 222 223 name[SoPlexBase<R>::RECOVERY_MECHANISM] = "recovery_mechanism"; 224 description[SoPlexBase<R>::RECOVERY_MECHANISM] = 225 "enable recovery mechanism for when the solve fails"; 226 defaultValue[SoPlexBase<R>::RECOVERY_MECHANISM] = false; 227 } 228 229 template <class R> 230 SoPlexBase<R>::Settings::IntParam::IntParam() 231 { 232 // objective sense 233 name[SoPlexBase<R>::OBJSENSE] = "objsense"; 234 description[SoPlexBase<R>::OBJSENSE] = "objective sense (-1 - minimize, +1 - maximize)"; 235 lower[SoPlexBase<R>::OBJSENSE] = -1; 236 upper[SoPlexBase<R>::OBJSENSE] = 1; 237 defaultValue[SoPlexBase<R>::OBJSENSE] = SoPlexBase<R>::OBJSENSE_MAXIMIZE; 238 239 // type of computational form, i.e., column or row representation 240 name[SoPlexBase<R>::REPRESENTATION] = "representation"; 241 description[SoPlexBase<R>::REPRESENTATION] = 242 "type of computational form (0 - auto, 1 - column representation, 2 - row representation)"; 243 lower[SoPlexBase<R>::REPRESENTATION] = 0; 244 upper[SoPlexBase<R>::REPRESENTATION] = 2; 245 defaultValue[SoPlexBase<R>::REPRESENTATION] = SoPlexBase<R>::REPRESENTATION_AUTO; 246 247 // type of algorithm, i.e., primal or dual 248 name[SoPlexBase<R>::ALGORITHM] = "algorithm"; 249 description[SoPlexBase<R>::ALGORITHM] = "type of algorithm (0 - primal, 1 - dual)"; 250 lower[SoPlexBase<R>::ALGORITHM] = 0; 251 upper[SoPlexBase<R>::ALGORITHM] = 1; 252 defaultValue[SoPlexBase<R>::ALGORITHM] = SoPlexBase<R>::ALGORITHM_DUAL; 253 254 // type of LU update 255 name[SoPlexBase<R>::FACTOR_UPDATE_TYPE] = "factor_update_type"; 256 description[SoPlexBase<R>::FACTOR_UPDATE_TYPE] = 257 "type of LU update (0 - eta update, 1 - Forrest-Tomlin update)"; 258 lower[SoPlexBase<R>::FACTOR_UPDATE_TYPE] = 0; 259 upper[SoPlexBase<R>::FACTOR_UPDATE_TYPE] = 1; 260 defaultValue[SoPlexBase<R>::FACTOR_UPDATE_TYPE] = SoPlexBase<R>::FACTOR_UPDATE_TYPE_FT; 261 262 // maximum number of updates without fresh factorization 263 name[SoPlexBase<R>::FACTOR_UPDATE_MAX] = "factor_update_max"; 264 description[SoPlexBase<R>::FACTOR_UPDATE_MAX] = 265 "maximum number of LU updates without fresh factorization (0 - auto)"; 266 lower[SoPlexBase<R>::FACTOR_UPDATE_MAX] = 0; 267 upper[SoPlexBase<R>::FACTOR_UPDATE_MAX] = INT_MAX; 268 defaultValue[SoPlexBase<R>::FACTOR_UPDATE_MAX] = 0; 269 270 // iteration limit (-1 if unlimited) 271 name[SoPlexBase<R>::ITERLIMIT] = "iterlimit"; 272 description[SoPlexBase<R>::ITERLIMIT] = "iteration limit (-1 - no limit)"; 273 lower[SoPlexBase<R>::ITERLIMIT] = -1; 274 upper[SoPlexBase<R>::ITERLIMIT] = INT_MAX; 275 defaultValue[SoPlexBase<R>::ITERLIMIT] = -1; 276 277 // refinement limit (-1 if unlimited) 278 name[SoPlexBase<R>::REFLIMIT] = "reflimit"; 279 description[SoPlexBase<R>::REFLIMIT] = "refinement limit (-1 - no limit)"; 280 lower[SoPlexBase<R>::REFLIMIT] = -1; 281 upper[SoPlexBase<R>::REFLIMIT] = INT_MAX; 282 defaultValue[SoPlexBase<R>::REFLIMIT] = -1; 283 284 // stalling refinement limit (-1 if unlimited) 285 name[SoPlexBase<R>::STALLREFLIMIT] = "stallreflimit"; 286 description[SoPlexBase<R>::STALLREFLIMIT] = "stalling refinement limit (-1 - no limit)"; 287 lower[SoPlexBase<R>::STALLREFLIMIT] = -1; 288 upper[SoPlexBase<R>::STALLREFLIMIT] = INT_MAX; 289 defaultValue[SoPlexBase<R>::STALLREFLIMIT] = -1; 290 291 // display frequency 292 name[SoPlexBase<R>::DISPLAYFREQ] = "displayfreq"; 293 description[SoPlexBase<R>::DISPLAYFREQ] = "display frequency"; 294 lower[SoPlexBase<R>::DISPLAYFREQ] = 1; 295 upper[SoPlexBase<R>::DISPLAYFREQ] = INT_MAX; 296 defaultValue[SoPlexBase<R>::DISPLAYFREQ] = 200; 297 298 // verbosity level 299 name[SoPlexBase<R>::VERBOSITY] = "verbosity"; 300 description[SoPlexBase<R>::VERBOSITY] = 301 "verbosity level (0 - error, 1 - warning, 2 - debug, 3 - normal, 4 - high, 5 - full)"; 302 lower[SoPlexBase<R>::VERBOSITY] = 0; 303 upper[SoPlexBase<R>::VERBOSITY] = 5; 304 defaultValue[SoPlexBase<R>::VERBOSITY] = SoPlexBase<R>::VERBOSITY_NORMAL; 305 //_intParamDefault[SoPlexBase<R>::VERBOSITY] = SoPlexBase<R>::VERBOSITY_FULL; 306 307 // type of simplifier 308 name[SoPlexBase<R>::SIMPLIFIER] = "simplifier"; 309 description[SoPlexBase<R>::SIMPLIFIER] = "simplifier (0 - off, 1 - auto, 2 - PaPILO, 3 - internal)"; 310 lower[SoPlexBase<R>::SIMPLIFIER] = 0; 311 upper[SoPlexBase<R>::SIMPLIFIER] = 3; 312 defaultValue[SoPlexBase<R>::SIMPLIFIER] = SoPlexBase<R>::SIMPLIFIER_INTERNAL; 313 314 // type of scaler 315 name[SoPlexBase<R>::SCALER] = "scaler"; 316 description[SoPlexBase<R>::SCALER] = 317 "scaling (0 - off, 1 - uni-equilibrium, 2 - bi-equilibrium, 3 - geometric, 4 - iterated geometric, 5 - least squares, 6 - geometric-equilibrium)"; 318 lower[SoPlexBase<R>::SCALER] = 0; 319 upper[SoPlexBase<R>::SCALER] = 6; 320 defaultValue[SoPlexBase<R>::SCALER] = SoPlexBase<R>::SCALER_BIEQUI; 321 322 // type of starter used to create crash basis 323 name[SoPlexBase<R>::STARTER] = "starter"; 324 description[SoPlexBase<R>::STARTER] = 325 "crash basis generated when starting from scratch (0 - none, 1 - weight, 2 - sum, 3 - vector)"; 326 lower[SoPlexBase<R>::STARTER] = 0; 327 upper[SoPlexBase<R>::STARTER] = 3; 328 defaultValue[SoPlexBase<R>::STARTER] = SoPlexBase<R>::STARTER_OFF; 329 330 // type of pricer 331 name[SoPlexBase<R>::PRICER] = "pricer"; 332 description[SoPlexBase<R>::PRICER] = 333 "pricing method (0 - auto, 1 - dantzig, 2 - parmult, 3 - devex, 4 - quicksteep, 5 - steep)"; 334 lower[SoPlexBase<R>::PRICER] = 0; 335 upper[SoPlexBase<R>::PRICER] = 5; 336 defaultValue[SoPlexBase<R>::PRICER] = SoPlexBase<R>::PRICER_AUTO; 337 338 // type of ratio test 339 name[SoPlexBase<R>::RATIOTESTER] = "ratiotester"; 340 description[SoPlexBase<R>::RATIOTESTER] = 341 "method for ratio test (0 - textbook, 1 - harris, 2 - fast, 3 - boundflipping)"; 342 lower[SoPlexBase<R>::RATIOTESTER] = 0; 343 upper[SoPlexBase<R>::RATIOTESTER] = 3; 344 defaultValue[SoPlexBase<R>::RATIOTESTER] = SoPlexBase<R>::RATIOTESTER_BOUNDFLIPPING; 345 346 // mode for synchronizing real and rational LP 347 name[SoPlexBase<R>::SYNCMODE] = "syncmode"; 348 description[SoPlexBase<R>::SYNCMODE] = 349 "mode for synchronizing real and rational LP (0 - store only real LP, 1 - auto, 2 - manual)"; 350 lower[SoPlexBase<R>::SYNCMODE] = 0; 351 upper[SoPlexBase<R>::SYNCMODE] = 2; 352 defaultValue[SoPlexBase<R>::SYNCMODE] = SoPlexBase<R>::SYNCMODE_ONLYREAL; 353 354 // mode for reading LP files 355 name[SoPlexBase<R>::READMODE] = "readmode"; 356 description[SoPlexBase<R>::READMODE] = 357 "mode for reading LP files (0 - floating-point, 1 - rational)"; 358 lower[SoPlexBase<R>::READMODE] = 0; 359 upper[SoPlexBase<R>::READMODE] = 1; 360 defaultValue[SoPlexBase<R>::READMODE] = SoPlexBase<R>::READMODE_REAL; 361 362 // mode for iterative refinement strategy 363 name[SoPlexBase<R>::SOLVEMODE] = "solvemode"; 364 description[SoPlexBase<R>::SOLVEMODE] = 365 "mode for iterative refinement strategy (0 - floating-point solve, 1 - auto, 2 - exact rational solve)"; 366 lower[SoPlexBase<R>::SOLVEMODE] = 0; 367 upper[SoPlexBase<R>::SOLVEMODE] = 2; 368 defaultValue[SoPlexBase<R>::SOLVEMODE] = SoPlexBase<R>::SOLVEMODE_AUTO; 369 370 // mode for iterative refinement strategy 371 name[SoPlexBase<R>::CHECKMODE] = "checkmode"; 372 description[SoPlexBase<R>::CHECKMODE] = 373 "mode for a posteriori feasibility checks (0 - floating-point check, 1 - auto, 2 - exact rational check)"; 374 lower[SoPlexBase<R>::CHECKMODE] = 0; 375 upper[SoPlexBase<R>::CHECKMODE] = 2; 376 defaultValue[SoPlexBase<R>::CHECKMODE] = SoPlexBase<R>::CHECKMODE_AUTO; 377 378 // type of timing 379 name[SoPlexBase<R>::TIMER] = "timer"; 380 description[SoPlexBase<R>::TIMER] = 381 "type of timer (1 - cputime, aka. usertime, 2 - wallclock time, 0 - no timing)"; 382 lower[SoPlexBase<R>::TIMER] = 0; 383 upper[SoPlexBase<R>::TIMER] = 2; 384 defaultValue[SoPlexBase<R>::TIMER] = SoPlexBase<R>::TIMER_CPU; 385 386 // mode for hyper sparse pricing 387 name[SoPlexBase<R>::HYPER_PRICING] = "hyperpricing"; 388 description[SoPlexBase<R>::HYPER_PRICING] = 389 "mode for hyper sparse pricing (0 - off, 1 - auto, 2 - always)"; 390 lower[SoPlexBase<R>::HYPER_PRICING] = 0; 391 upper[SoPlexBase<R>::HYPER_PRICING] = 2; 392 defaultValue[SoPlexBase<R>::HYPER_PRICING] = SoPlexBase<R>::HYPER_PRICING_AUTO; 393 394 // minimum number of stalling refinements since last pivot to trigger rational factorization 395 name[SoPlexBase<R>::RATFAC_MINSTALLS] = "ratfac_minstalls"; 396 description[SoPlexBase<R>::RATFAC_MINSTALLS] = 397 "minimum number of stalling refinements since last pivot to trigger rational factorization"; 398 lower[SoPlexBase<R>::RATFAC_MINSTALLS] = 0; 399 upper[SoPlexBase<R>::RATFAC_MINSTALLS] = INT_MAX; 400 defaultValue[SoPlexBase<R>::RATFAC_MINSTALLS] = 2; 401 402 // maximum number of conjugate gradient iterations in least square scaling 403 name[SoPlexBase<R>::LEASTSQ_MAXROUNDS] = "leastsq_maxrounds"; 404 description[SoPlexBase<R>::LEASTSQ_MAXROUNDS] = 405 "maximum number of conjugate gradient iterations in least square scaling"; 406 lower[SoPlexBase<R>::LEASTSQ_MAXROUNDS] = 0; 407 upper[SoPlexBase<R>::LEASTSQ_MAXROUNDS] = INT_MAX; 408 defaultValue[SoPlexBase<R>::LEASTSQ_MAXROUNDS] = 50; 409 410 // mode for solution polishing 411 name[SoPlexBase<R>::SOLUTION_POLISHING] = "solution_polishing"; 412 description[SoPlexBase<R>::SOLUTION_POLISHING] = 413 "mode for solution polishing (0 - off, 1 - max basic slack, 2 - min basic slack)"; 414 lower[SoPlexBase<R>::SOLUTION_POLISHING] = 0; 415 upper[SoPlexBase<R>::SOLUTION_POLISHING] = 2; 416 defaultValue[SoPlexBase<R>::SOLUTION_POLISHING] = SoPlexBase<R>::POLISHING_OFF; 417 418 // the number of iterations before the decomposition simplex initialisation is terminated. 419 name[SoPlexBase<R>::DECOMP_ITERLIMIT] = "decomp_iterlimit"; 420 description[SoPlexBase<R>::DECOMP_ITERLIMIT] = 421 "the number of iterations before the decomposition simplex initialisation solve is terminated"; 422 lower[SoPlexBase<R>::DECOMP_ITERLIMIT] = 1; 423 upper[SoPlexBase<R>::DECOMP_ITERLIMIT] = INT_MAX; 424 defaultValue[SoPlexBase<R>::DECOMP_ITERLIMIT] = 100; 425 426 // maximum number of violated rows added in each iteration of the decomposition simplex 427 name[SoPlexBase<R>::DECOMP_MAXADDEDROWS] = "decomp_maxaddedrows"; 428 description[SoPlexBase<R>::DECOMP_MAXADDEDROWS] = 429 "maximum number of rows that are added to the reduced problem when using the decomposition based simplex"; 430 lower[SoPlexBase<R>::DECOMP_MAXADDEDROWS] = 1; 431 upper[SoPlexBase<R>::DECOMP_MAXADDEDROWS] = INT_MAX; 432 defaultValue[SoPlexBase<R>::DECOMP_MAXADDEDROWS] = 500; 433 434 // maximum number of violated rows added in each iteration of the decomposition simplex 435 name[SoPlexBase<R>::DECOMP_DISPLAYFREQ] = "decomp_displayfreq"; 436 description[SoPlexBase<R>::DECOMP_DISPLAYFREQ] = 437 "the frequency that the decomposition based simplex status output is displayed."; 438 lower[SoPlexBase<R>::DECOMP_DISPLAYFREQ] = 1; 439 upper[SoPlexBase<R>::DECOMP_DISPLAYFREQ] = INT_MAX; 440 defaultValue[SoPlexBase<R>::DECOMP_DISPLAYFREQ] = 50; 441 442 // the verbosity of the decomposition based simplex 443 name[SoPlexBase<R>::DECOMP_VERBOSITY] = "decomp_verbosity"; 444 description[SoPlexBase<R>::DECOMP_VERBOSITY] = 445 "the verbosity of decomposition based simplex (0 - error, 1 - warning, 2 - debug, 3 - normal, 4 - high, 5 - full)."; 446 lower[SoPlexBase<R>::DECOMP_VERBOSITY] = 1; 447 upper[SoPlexBase<R>::DECOMP_VERBOSITY] = 5; 448 defaultValue[SoPlexBase<R>::DECOMP_VERBOSITY] = VERBOSITY_ERROR; 449 450 // printing condition number during the solve 451 name[SoPlexBase<R>::PRINTBASISMETRIC] = "printbasismetric"; 452 description[SoPlexBase<R>::PRINTBASISMETRIC] = 453 "print basis metric during the solve (-1 - off, 0 - condition estimate , 1 - trace, 2 - determinant, 3 - condition)"; 454 lower[SoPlexBase<R>::PRINTBASISMETRIC] = -1; 455 upper[SoPlexBase<R>::PRINTBASISMETRIC] = 3; 456 defaultValue[SoPlexBase<R>::PRINTBASISMETRIC] = -1; 457 458 /// measure time spent in solving steps, e.g. factorization time 459 name[SoPlexBase<R>::STATTIMER] = "stattimer"; 460 description[SoPlexBase<R>::STATTIMER] = 461 "measure for statistics, e.g. factorization time (0 - off, 1 - user time, 2 - wallclock time)"; 462 lower[SoPlexBase<R>::STATTIMER] = 0; 463 upper[SoPlexBase<R>::STATTIMER] = 2; 464 defaultValue[SoPlexBase<R>::STATTIMER] = 1; 465 466 // maximum number of digits for the multiprecision type 467 name[SoPlexBase<R>::MULTIPRECISION_LIMIT] = "multiprecision_limit"; 468 description[SoPlexBase<R>::MULTIPRECISION_LIMIT] = 469 "maximum number of digits for the multiprecision type"; 470 lower[SoPlexBase<R>::MULTIPRECISION_LIMIT] = 50; 471 upper[SoPlexBase<R>::MULTIPRECISION_LIMIT] = INT_MAX; 472 defaultValue[SoPlexBase<R>::MULTIPRECISION_LIMIT] = 300; 473 // if precision is too high, double tolerances are rounded to zero 474 // 300 is very close to the greatest int k such that (double)1e-k != 0 475 476 // at max, after how many simplex pivots do we store the advanced and stable basis, 1 = every iterations 477 name[SoPlexBase<R>::STORE_BASIS_SIMPLEX_FREQ] = "storeBasisSimplexFreq"; 478 description[SoPlexBase<R>::STORE_BASIS_SIMPLEX_FREQ] = 479 "at max, after how many simplex pivots do we store the advanced and stable basis, 1 = every iterations"; 480 lower[SoPlexBase<R>::STORE_BASIS_SIMPLEX_FREQ] = 1; 481 upper[SoPlexBase<R>::STORE_BASIS_SIMPLEX_FREQ] = INT_MAX; 482 defaultValue[SoPlexBase<R>::STORE_BASIS_SIMPLEX_FREQ] = 10000; 483 } 484 485 template <class R> 486 SoPlexBase<R>::Settings::RealParam::RealParam() 487 { 488 // primal feasibility tolerance 489 name[SoPlexBase<R>::FEASTOL] = "feastol"; 490 description[SoPlexBase<R>::FEASTOL] = "primal feasibility tolerance"; 491 lower[SoPlexBase<R>::FEASTOL] = 0.0; 492 upper[SoPlexBase<R>::FEASTOL] = 1.0; 493 defaultValue[SoPlexBase<R>::FEASTOL] = 1e-6; 494 495 // dual feasibility tolerance 496 name[SoPlexBase<R>::OPTTOL] = "opttol"; 497 description[SoPlexBase<R>::OPTTOL] = "dual feasibility tolerance"; 498 lower[SoPlexBase<R>::OPTTOL] = 0.0; 499 upper[SoPlexBase<R>::OPTTOL] = 1.0; 500 defaultValue[SoPlexBase<R>::OPTTOL] = 1e-6; 501 502 ///@todo define suitable values depending on R type 503 // general zero tolerance 504 name[SoPlexBase<R>::EPSILON_ZERO] = "epsilon_zero"; 505 description[SoPlexBase<R>::EPSILON_ZERO] = "general zero tolerance"; 506 lower[SoPlexBase<R>::EPSILON_ZERO] = 0.0; 507 upper[SoPlexBase<R>::EPSILON_ZERO] = 1.0; 508 defaultValue[SoPlexBase<R>::EPSILON_ZERO] = SOPLEX_DEFAULT_EPS_ZERO; 509 510 ///@todo define suitable values depending on R type 511 // zero tolerance used in factorization 512 name[SoPlexBase<R>::EPSILON_FACTORIZATION] = "epsilon_factorization"; 513 description[SoPlexBase<R>::EPSILON_FACTORIZATION] = "zero tolerance used in factorization"; 514 lower[SoPlexBase<R>::EPSILON_FACTORIZATION] = 0.0; 515 upper[SoPlexBase<R>::EPSILON_FACTORIZATION] = 1.0; 516 defaultValue[SoPlexBase<R>::EPSILON_FACTORIZATION] = SOPLEX_DEFAULT_EPS_FACTOR; 517 518 ///@todo define suitable values depending on R type 519 // zero tolerance used in update of the factorization 520 name[SoPlexBase<R>::EPSILON_UPDATE] = "epsilon_update"; 521 description[SoPlexBase<R>::EPSILON_UPDATE] = "zero tolerance used in update of the factorization"; 522 lower[SoPlexBase<R>::EPSILON_UPDATE] = 0.0; 523 upper[SoPlexBase<R>::EPSILON_UPDATE] = 1.0; 524 defaultValue[SoPlexBase<R>::EPSILON_UPDATE] = SOPLEX_DEFAULT_EPS_UPDATE; 525 526 ///@todo define suitable values depending on R type 527 // pivot zero tolerance used in factorization 528 name[SoPlexBase<R>::EPSILON_PIVOT] = "epsilon_pivot"; 529 description[SoPlexBase<R>::EPSILON_PIVOT] = "pivot zero tolerance used in factorization"; 530 lower[SoPlexBase<R>::EPSILON_PIVOT] = 0.0; 531 upper[SoPlexBase<R>::EPSILON_PIVOT] = 1.0; 532 defaultValue[SoPlexBase<R>::EPSILON_PIVOT] = SOPLEX_DEFAULT_EPS_PIVOR; 533 534 ///@todo define suitable values depending on R type 535 // infinity threshold 536 name[SoPlexBase<R>::INFTY] = "infty"; 537 description[SoPlexBase<R>::INFTY] = "infinity threshold"; 538 lower[SoPlexBase<R>::INFTY] = 1e10; 539 upper[SoPlexBase<R>::INFTY] = 1e100; 540 defaultValue[SoPlexBase<R>::INFTY] = SOPLEX_DEFAULT_INFINITY; 541 542 // time limit in seconds (INFTY if unlimited) 543 name[SoPlexBase<R>::TIMELIMIT] = "timelimit"; 544 description[SoPlexBase<R>::TIMELIMIT] = "time limit in seconds"; 545 lower[SoPlexBase<R>::TIMELIMIT] = 0.0; 546 upper[SoPlexBase<R>::TIMELIMIT] = SOPLEX_DEFAULT_INFINITY; 547 defaultValue[SoPlexBase<R>::TIMELIMIT] = SOPLEX_DEFAULT_INFINITY; 548 549 // lower limit on objective value 550 name[SoPlexBase<R>::OBJLIMIT_LOWER] = "objlimit_lower"; 551 description[SoPlexBase<R>::OBJLIMIT_LOWER] = "lower limit on objective value"; 552 lower[SoPlexBase<R>::OBJLIMIT_LOWER] = -SOPLEX_DEFAULT_INFINITY; 553 upper[SoPlexBase<R>::OBJLIMIT_LOWER] = SOPLEX_DEFAULT_INFINITY; 554 defaultValue[SoPlexBase<R>::OBJLIMIT_LOWER] = -SOPLEX_DEFAULT_INFINITY; 555 556 // upper limit on objective value 557 name[SoPlexBase<R>::OBJLIMIT_UPPER] = "objlimit_upper"; 558 description[SoPlexBase<R>::OBJLIMIT_UPPER] = "upper limit on objective value"; 559 lower[SoPlexBase<R>::OBJLIMIT_UPPER] = -SOPLEX_DEFAULT_INFINITY; 560 upper[SoPlexBase<R>::OBJLIMIT_UPPER] = SOPLEX_DEFAULT_INFINITY; 561 defaultValue[SoPlexBase<R>::OBJLIMIT_UPPER] = SOPLEX_DEFAULT_INFINITY; 562 563 // working tolerance for feasibility in floating-point solver during iterative refinement 564 name[SoPlexBase<R>::FPFEASTOL] = "fpfeastol"; 565 description[SoPlexBase<R>::FPFEASTOL] = 566 "working tolerance for feasibility in floating-point solver during iterative refinement"; 567 lower[SoPlexBase<R>::FPFEASTOL] = 0; 568 upper[SoPlexBase<R>::FPFEASTOL] = 1.0; 569 defaultValue[SoPlexBase<R>::FPFEASTOL] = 1e-9; 570 571 // working tolerance for optimality in floating-point solver during iterative refinement 572 name[SoPlexBase<R>::FPOPTTOL] = "fpopttol"; 573 description[SoPlexBase<R>::FPOPTTOL] = 574 "working tolerance for optimality in floating-point solver during iterative refinement"; 575 lower[SoPlexBase<R>::FPOPTTOL] = 0; 576 upper[SoPlexBase<R>::FPOPTTOL] = 1.0; 577 defaultValue[SoPlexBase<R>::FPOPTTOL] = 1e-9; 578 579 // maximum increase of scaling factors between refinements 580 name[SoPlexBase<R>::MAXSCALEINCR] = "maxscaleincr"; 581 description[SoPlexBase<R>::MAXSCALEINCR] = 582 "maximum increase of scaling factors between refinements"; 583 lower[SoPlexBase<R>::MAXSCALEINCR] = 1.0; 584 upper[SoPlexBase<R>::MAXSCALEINCR] = SOPLEX_DEFAULT_INFINITY; 585 defaultValue[SoPlexBase<R>::MAXSCALEINCR] = 1e25; 586 587 // lower threshold in lifting (nonzero matrix coefficients with smaller absolute value will be reformulated) 588 name[SoPlexBase<R>::LIFTMINVAL] = "liftminval"; 589 description[SoPlexBase<R>::LIFTMINVAL] = 590 "lower threshold in lifting (nonzero matrix coefficients with smaller absolute value will be reformulated)"; 591 lower[SoPlexBase<R>::LIFTMINVAL] = 0.0; 592 upper[SoPlexBase<R>::LIFTMINVAL] = 0.1; 593 defaultValue[SoPlexBase<R>::LIFTMINVAL] = 0.000976562; // = 1/1024 594 595 // upper threshold in lifting (nonzero matrix coefficients with larger absolute value will be reformulated) 596 name[SoPlexBase<R>::LIFTMAXVAL] = "liftmaxval"; 597 description[SoPlexBase<R>::LIFTMAXVAL] = 598 "lower threshold in lifting (nonzero matrix coefficients with smaller absolute value will be reformulated)"; 599 lower[SoPlexBase<R>::LIFTMAXVAL] = 10.0; 600 upper[SoPlexBase<R>::LIFTMAXVAL] = SOPLEX_DEFAULT_INFINITY; 601 defaultValue[SoPlexBase<R>::LIFTMAXVAL] = 1024.0; 602 603 // threshold for using sparse pricing (no. of violations need to be smaller than threshold * dimension of problem) 604 name[SoPlexBase<R>::SPARSITY_THRESHOLD] = "sparsity_threshold"; 605 description[SoPlexBase<R>::SPARSITY_THRESHOLD] = 606 "sparse pricing threshold (#violations < dimension * SPARSITY_THRESHOLD activates sparse pricing)"; 607 lower[SoPlexBase<R>::SPARSITY_THRESHOLD] = 0.0; 608 upper[SoPlexBase<R>::SPARSITY_THRESHOLD] = 1.0; 609 defaultValue[SoPlexBase<R>::SPARSITY_THRESHOLD] = 0.6; 610 611 // threshold on number of rows vs. number of columns for switching from column to row representations in auto mode 612 name[SoPlexBase<R>::REPRESENTATION_SWITCH] = "representation_switch"; 613 description[SoPlexBase<R>::REPRESENTATION_SWITCH] = 614 "threshold on number of rows vs. number of columns for switching from column to row representations in auto mode"; 615 lower[SoPlexBase<R>::REPRESENTATION_SWITCH] = 0.0; 616 upper[SoPlexBase<R>::REPRESENTATION_SWITCH] = SOPLEX_DEFAULT_INFINITY; 617 defaultValue[SoPlexBase<R>::REPRESENTATION_SWITCH] = 1.2; 618 619 // geometric frequency at which to apply rational reconstruction 620 name[SoPlexBase<R>::RATREC_FREQ] = "ratrec_freq"; 621 description[SoPlexBase<R>::RATREC_FREQ] = 622 "geometric frequency at which to apply rational reconstruction"; 623 lower[SoPlexBase<R>::RATREC_FREQ] = 1.0; 624 upper[SoPlexBase<R>::RATREC_FREQ] = SOPLEX_DEFAULT_INFINITY; 625 defaultValue[SoPlexBase<R>::RATREC_FREQ] = 1.2; 626 627 // minimal reduction (sum of removed rows/cols) to continue simplification 628 name[SoPlexBase<R>::MINRED] = "minred"; 629 description[SoPlexBase<R>::MINRED] = 630 "minimal reduction (sum of removed rows/cols) to continue simplification"; 631 lower[SoPlexBase<R>::MINRED] = 0.0; 632 upper[SoPlexBase<R>::MINRED] = 1.0; 633 defaultValue[SoPlexBase<R>::MINRED] = 1e-4; 634 635 // refactor threshold for nonzeros in last factorized basis matrix compared to updated basis matrix 636 name[SoPlexBase<R>::REFAC_BASIS_NNZ] = "refac_basis_nnz"; 637 description[SoPlexBase<R>::REFAC_BASIS_NNZ] = 638 "refactor threshold for nonzeros in last factorized basis matrix compared to updated basis matrix"; 639 lower[SoPlexBase<R>::REFAC_BASIS_NNZ] = 1.0; 640 upper[SoPlexBase<R>::REFAC_BASIS_NNZ] = 100.0; 641 defaultValue[SoPlexBase<R>::REFAC_BASIS_NNZ] = 10.0; 642 643 // refactor threshold for fill-in in current factor update compared to fill-in in last factorization 644 name[SoPlexBase<R>::REFAC_UPDATE_FILL] = "refac_update_fill"; 645 description[SoPlexBase<R>::REFAC_UPDATE_FILL] = 646 "refactor threshold for fill-in in current factor update compared to fill-in in last factorization"; 647 lower[SoPlexBase<R>::REFAC_UPDATE_FILL] = 1.0; 648 upper[SoPlexBase<R>::REFAC_UPDATE_FILL] = 100.0; 649 defaultValue[SoPlexBase<R>::REFAC_UPDATE_FILL] = 5.0; 650 651 // refactor threshold for memory growth in factorization since last refactorization 652 name[SoPlexBase<R>::REFAC_MEM_FACTOR] = "refac_mem_factor"; 653 description[SoPlexBase<R>::REFAC_MEM_FACTOR] = 654 "refactor threshold for memory growth in factorization since last refactorization"; 655 lower[SoPlexBase<R>::REFAC_MEM_FACTOR] = 1.0; 656 upper[SoPlexBase<R>::REFAC_MEM_FACTOR] = 10.0; 657 defaultValue[SoPlexBase<R>::REFAC_MEM_FACTOR] = 1.5; 658 659 // accuracy of conjugate gradient method in least squares scaling (higher value leads to more iterations) 660 name[SoPlexBase<R>::LEASTSQ_ACRCY] = "leastsq_acrcy"; 661 description[SoPlexBase<R>::LEASTSQ_ACRCY] = 662 "accuracy of conjugate gradient method in least squares scaling (higher value leads to more iterations)"; 663 lower[SoPlexBase<R>::LEASTSQ_ACRCY] = 1.0; 664 upper[SoPlexBase<R>::LEASTSQ_ACRCY] = SOPLEX_DEFAULT_INFINITY; 665 defaultValue[SoPlexBase<R>::LEASTSQ_ACRCY] = 1000.0; 666 667 // objective offset 668 name[SoPlexBase<R>::OBJ_OFFSET] = "obj_offset"; 669 description[SoPlexBase<R>::OBJ_OFFSET] = "objective offset to be used"; 670 lower[SoPlexBase<R>::OBJ_OFFSET] = -SOPLEX_DEFAULT_INFINITY; 671 upper[SoPlexBase<R>::OBJ_OFFSET] = SOPLEX_DEFAULT_INFINITY; 672 defaultValue[SoPlexBase<R>::OBJ_OFFSET] = 0.0; 673 674 // minimal Markowitz threshold to control sparsity/stability in LU factorization 675 name[SoPlexBase<R>::MIN_MARKOWITZ] = "min_markowitz"; 676 description[SoPlexBase<R>::MIN_MARKOWITZ] = "minimal Markowitz threshold in LU factorization"; 677 lower[SoPlexBase<R>::MIN_MARKOWITZ] = 0.0001; 678 upper[SoPlexBase<R>::MIN_MARKOWITZ] = 0.9999; 679 defaultValue[SoPlexBase<R>::MIN_MARKOWITZ] = 0.01; 680 681 // modification 682 name[SoPlexBase<R>::SIMPLIFIER_MODIFYROWFAC] = "simplifier_modifyrowfac"; 683 description[SoPlexBase<R>::SIMPLIFIER_MODIFYROWFAC] = 684 "modify constraints when the number of nonzeros or rows is at most this factor times the number of nonzeros or rows before presolving"; 685 lower[SoPlexBase<R>::SIMPLIFIER_MODIFYROWFAC] = 0; 686 upper[SoPlexBase<R>::SIMPLIFIER_MODIFYROWFAC] = 1; 687 defaultValue[SoPlexBase<R>::SIMPLIFIER_MODIFYROWFAC] = 1.0; 688 689 // factor by which the precision of the floating-point solver is multiplied 690 name[SoPlexBase<R>::PRECISION_BOOSTING_FACTOR] = "precision_boosting_factor"; 691 description[SoPlexBase<R>::PRECISION_BOOSTING_FACTOR] = 692 "factor by which the precision of the floating-point solver is multiplied"; 693 lower[SoPlexBase<R>::PRECISION_BOOSTING_FACTOR] = 1.0; 694 upper[SoPlexBase<R>::PRECISION_BOOSTING_FACTOR] = 10.0; 695 defaultValue[SoPlexBase<R>::PRECISION_BOOSTING_FACTOR] = 1.5; 696 } 697 698 template <class R> 699 typename SoPlexBase<R>::Settings& SoPlexBase<R>::Settings::operator=(const Settings& settings) 700 { 701 for(int i = 0; i < SoPlexBase<R>::BOOLPARAM_COUNT; i++) 702 _boolParamValues[i] = settings._boolParamValues[i]; 703 704 for(int i = 0; i < SoPlexBase<R>::INTPARAM_COUNT; i++) 705 _intParamValues[i] = settings._intParamValues[i]; 706 707 for(int i = 0; i < SoPlexBase<R>::REALPARAM_COUNT; i++) 708 _realParamValues[i] = settings._realParamValues[i]; 709 710 #ifdef SOPLEX_WITH_RATIONALPARAM 711 712 for(int i = 0; i < SoPlexBase<R>::RATIONALPARAM_COUNT; i++) 713 _rationalParamValues[i] = settings._rationalParamValues[i]; 714 715 #endif 716 717 return *this; 718 } 719 720 721 #ifdef SOPLEX_WITH_RATIONALPARAM 722 SoPlexBase<R>::Settings::RationalParam::RationalParam() {} 723 #endif 724 725 726 template <class R> 727 SoPlexBase<R>::Settings::Settings() 728 { 729 for(int i = 0; i < SoPlexBase<R>::BOOLPARAM_COUNT; i++) 730 _boolParamValues[i] = boolParam.defaultValue[i]; 731 732 for(int i = 0; i < SoPlexBase<R>::INTPARAM_COUNT; i++) 733 _intParamValues[i] = intParam.defaultValue[i]; 734 735 for(int i = 0; i < SoPlexBase<R>::REALPARAM_COUNT; i++) 736 _realParamValues[i] = realParam.defaultValue[i]; 737 738 #ifdef SOPLEX_WITH_RATIONALPARAM 739 740 for(int i = 0; i < SoPlexBase<R>::RATIONALPARAM_COUNT; i++) 741 _rationalParamValues[i] = rationalParam.defaultValue[i]; 742 743 #endif 744 } 745 746 template <class R> 747 SoPlexBase<R>::Settings::Settings(const Settings& settings) 748 { 749 *this = settings; 750 } 751 752 753 #ifdef SOPLEX_WITH_RATIONALPARAM 754 template <class R> 755 SoPlexBase<R>::Settings::RationalParam SoPlexBase<R>::Settings::rationalParam; 756 #endif 757 758 759 /// copy constructor 760 ///@todo improve performance by implementing a separate copy constructor 761 template <class R> 762 SoPlexBase<R>::SoPlexBase(const SoPlexBase<R>& rhs) 763 { 764 // allocate memory as in default constructor 765 _statistics = nullptr; 766 spx_alloc(_statistics); 767 _statistics = new(_statistics) Statistics(); 768 769 _currentSettings = nullptr; 770 spx_alloc(_currentSettings); 771 _currentSettings = new(_currentSettings) Settings(); 772 773 // call assignment operator 774 *this = rhs; 775 } 776 777 778 779 /// destructor 780 template <class R> 781 SoPlexBase<R>::~SoPlexBase() 782 { 783 assert(_isConsistent()); 784 785 // free settings 786 _currentSettings->~Settings(); 787 spx_free(_currentSettings); 788 789 // free statistics 790 _statistics->~Statistics(); 791 spx_free(_statistics); 792 793 // free real LP if different from the LP in the solver 794 assert(_realLP != nullptr); 795 796 if(_realLP != &_solver) 797 { 798 _realLP->~SPxLPBase<R>(); 799 spx_free(_realLP); 800 } 801 802 // free rational LP 803 if(_rationalLP != nullptr) 804 { 805 _rationalLP->~SPxLPRational(); 806 spx_free(_rationalLP); 807 } 808 809 // free unit vectors 810 auto uMatSize = _unitMatrixRational.size(); 811 812 for(decltype(uMatSize) i = 0; i < uMatSize; i++) 813 { 814 if(_unitMatrixRational[i] != nullptr) 815 { 816 _unitMatrixRational[i]->~UnitVectorRational(); 817 spx_free(_unitMatrixRational[i]); 818 } 819 } 820 } 821 822 // For SCIP compatibility 823 template <class R> 824 int SoPlexBase<R>::numRowsReal() const 825 { 826 return numRows(); 827 } 828 829 830 // Wrapper for reverse compatibility 831 template <class R> 832 int SoPlexBase<R>::numColsReal() const 833 { 834 return numCols(); 835 } 836 837 838 // Wrapper function for reverse compatibility 839 template <class R> 840 bool SoPlexBase<R>::getPrimalRayReal(R* vector, int dim) 841 { 842 if(hasPrimalRay() && dim >= numCols()) 843 { 844 _syncRealSolution(); 845 auto& primalRay = _solReal._primalRay; 846 std::copy(primalRay.begin(), primalRay.end(), vector); 847 848 return true; 849 } 850 else 851 return false; 852 853 } 854 855 856 // Wrapper function for reverse compatibility 857 template <class R> 858 bool SoPlexBase<R>::getDualReal(R* p_vector, int dim) // For SCIP 859 { 860 if(hasSol() && dim >= numRows()) 861 { 862 _syncRealSolution(); 863 auto& dual = _solReal._dual; 864 std::copy(dual.begin(), dual.end(), p_vector); 865 866 return true; 867 } 868 else 869 return false; 870 871 } 872 873 874 875 /// wrapper for backwards compatibility 876 template <class R> 877 bool SoPlexBase<R>::getRedCostReal(R* p_vector, int dim) // For SCIP compatibility 878 { 879 if(hasSol() && dim >= numCols()) 880 { 881 _syncRealSolution(); 882 auto& redcost = _solReal._redCost; 883 std::copy(redcost.begin(), redcost.end(), p_vector); 884 885 return true; 886 } 887 else 888 return false; 889 890 } 891 892 893 894 895 // Wrapping the function for reverse Compatibility 896 template <class R> 897 bool SoPlexBase<R>::getDualFarkasReal(R* vector, int dim) 898 { 899 if(hasDualFarkas() && dim >= numRows()) 900 { 901 _syncRealSolution(); 902 auto& dualFarkas = _solReal._dualFarkas; 903 std::copy(dualFarkas.begin(), dualFarkas.end(), vector); 904 905 return true; 906 } 907 else 908 return false; 909 910 } 911 912 913 914 #ifdef SOPLEX_WITH_GMP 915 /// gets the primal solution vector if available; returns true on success (GMP only method) 916 template <class R> 917 bool SoPlexBase<R>::getPrimalRational(mpq_t* vector, const int size) 918 { 919 #ifndef SOPLEX_WITH_BOOST 920 SPX_MSG_ERROR(std::cerr << "ERROR: rational solve without Boost not defined!" << std::endl;) 921 return false; 922 #else 923 assert(size >= numColsRational()); 924 925 if(hasSol()) 926 { 927 _syncRationalSolution(); 928 929 for(int i = 0; i < numColsRational(); i++) 930 mpq_set(vector[i], _solRational._primal[i].backend().data()); 931 932 return true; 933 } 934 else 935 return false; 936 937 #endif 938 } 939 940 941 /// gets the vector of slack values if available; returns true on success (GMP only method) 942 template <class R> 943 bool SoPlexBase<R>::getSlacksRational(mpq_t* vector, const int size) 944 { 945 #ifndef SOPLEX_WITH_BOOST 946 SPX_MSG_ERROR(std::cerr << "ERROR: rational solve without Boost not defined!" << std::endl;) 947 return false; 948 #else 949 assert(size >= numRowsRational()); 950 951 if(hasSol()) 952 { 953 _syncRationalSolution(); 954 955 for(int i = 0; i < numRowsRational(); i++) 956 mpq_set(vector[i], _solRational._slacks[i].backend().data()); 957 958 return true; 959 } 960 else 961 return false; 962 963 #endif 964 } 965 966 967 968 /// gets the primal ray if LP is unbounded; returns true on success (GMP only method) 969 template <class R> 970 bool SoPlexBase<R>::getPrimalRayRational(mpq_t* vector, const int size) 971 { 972 #ifndef SOPLEX_WITH_BOOST 973 SPX_MSG_ERROR(std::cerr << "ERROR: rational solve without Boost not defined!" << std::endl;) 974 return false; 975 #else 976 assert(size >= numColsRational()); 977 978 if(hasPrimalRay()) 979 { 980 _syncRationalSolution(); 981 982 for(int i = 0; i < numColsRational(); i++) 983 mpq_set(vector[i], _solRational._primalRay[i].backend().data()); 984 985 return true; 986 } 987 else 988 return false; 989 990 #endif 991 } 992 993 994 995 /// gets the dual solution vector if available; returns true on success (GMP only method) 996 template <class R> 997 bool SoPlexBase<R>::getDualRational(mpq_t* vector, const int size) 998 { 999 #ifndef SOPLEX_WITH_BOOST 1000 SPX_MSG_ERROR(std::cerr << "ERROR: rational solve without Boost not defined!" << std::endl;) 1001 return false; 1002 #else 1003 assert(size >= numRowsRational()); 1004 1005 if(hasSol()) 1006 { 1007 _syncRationalSolution(); 1008 1009 for(int i = 0; i < numRowsRational(); i++) 1010 mpq_set(vector[i], _solRational._dual[i].backend().data()); 1011 1012 return true; 1013 } 1014 else 1015 return false; 1016 1017 #endif 1018 } 1019 1020 1021 1022 /// gets the vector of reduced cost values if available; returns true on success (GMP only method) 1023 template <class R> 1024 bool SoPlexBase<R>::getRedCostRational(mpq_t* vector, const int size) 1025 { 1026 #ifndef SOPLEX_WITH_BOOST 1027 SPX_MSG_ERROR(std::cerr << "ERROR: rational solve without Boost not defined!" << std::endl;) 1028 return false; 1029 #else 1030 assert(size >= numColsRational()); 1031 1032 if(hasSol()) 1033 { 1034 _syncRationalSolution(); 1035 1036 for(int i = 0; i < numColsRational(); i++) 1037 mpq_set(vector[i], _solRational._redCost[i].backend().data()); 1038 1039 return true; 1040 } 1041 else 1042 return false; 1043 1044 #endif 1045 } 1046 1047 1048 1049 /// gets the Farkas proof if LP is infeasible; returns true on success (GMP only method) 1050 template <class R> 1051 bool SoPlexBase<R>::getDualFarkasRational(mpq_t* vector, const int size) 1052 { 1053 #ifndef SOPLEX_WITH_BOOST 1054 SPX_MSG_ERROR(std::cerr << "ERROR: rational solve without Boost not defined!" << std::endl;) 1055 return false; 1056 #else 1057 assert(size >= numRowsRational()); 1058 1059 if(hasDualFarkas()) 1060 { 1061 _syncRationalSolution(); 1062 1063 for(int i = 0; i < numRowsRational(); i++) 1064 mpq_set(vector[i], _solRational._dualFarkas[i].backend().data()); 1065 1066 return true; 1067 } 1068 else 1069 return false; 1070 1071 #endif 1072 } 1073 #endif 1074 1075 1076 // Alias for writeFile; SCIP 1077 template <class R> 1078 bool SoPlexBase<R>::writeFileReal(const char* filename, const NameSet* rowNames, 1079 const NameSet* colNames, const DIdxSet* intVars, const bool unscale) const 1080 { 1081 return writeFile(filename, rowNames, colNames, intVars, unscale); 1082 } 1083 1084 /// writes rational LP to file; LP or MPS format is chosen from the extension in \p filename; if \p rowNames and \p 1085 /// colNames are \c NULL, default names are used; if \p intVars is not \c NULL, the variables contained in it are 1086 /// marked as integer; returns true on success 1087 /// Here unscale is just a junk variable that is used to match the type with the real write function 1088 template <class R> 1089 bool SoPlexBase<R>::writeFileRational(const char* filename, const NameSet* rowNames, 1090 const NameSet* colNames, const DIdxSet* intVars) const 1091 { 1092 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 1093 return false; 1094 else 1095 { 1096 assert(_rationalLP != 0); 1097 _rationalLP->writeFileLPBase(filename, rowNames, colNames, intVars); 1098 1099 ///@todo implement return value 1100 return true; 1101 } 1102 } 1103 1104 1105 1106 1107 1108 1109 /// writes internal LP, basis information, and parameter settings; if \p rowNames and \p colNames are \c NULL, 1110 /// default names are used 1111 template <class R> 1112 void SoPlexBase<R>::writeStateReal(const char* filename, const NameSet* rowNames, 1113 const NameSet* colNames, const bool cpxFormat) const 1114 { 1115 std::string ofname; 1116 1117 // write parameter settings 1118 ofname = std::string(filename) + ".set"; 1119 saveSettingsFile(ofname.c_str()); 1120 1121 // write problem in MPS/LP format 1122 ofname = std::string(filename) + ((cpxFormat) ? ".lp" : ".mps"); 1123 writeFile(ofname.c_str(), rowNames, colNames, 0); 1124 1125 // write basis 1126 ofname = std::string(filename) + ".bas"; 1127 writeBasisFile(ofname.c_str(), rowNames, colNames, cpxFormat); 1128 } 1129 1130 1131 1132 /// writes internal LP, basis information, and parameter settings; if \p rowNames and \p colNames are \c NULL, 1133 /// default names are used 1134 template <class R> 1135 void SoPlexBase<R>::writeStateRational(const char* filename, const NameSet* rowNames, 1136 const NameSet* colNames, const bool cpxFormat) const 1137 { 1138 std::string ofname; 1139 1140 // write parameter settings 1141 ofname = std::string(filename) + ".set"; 1142 saveSettingsFile(ofname.c_str()); 1143 1144 // write problem in MPS/LP format 1145 ofname = std::string(filename) + ((cpxFormat) ? ".lp" : ".mps"); 1146 writeFileRational(ofname.c_str(), rowNames, colNames, 0); 1147 1148 // write basis 1149 ofname = std::string(filename) + ".bas"; 1150 writeBasisFile(ofname.c_str(), rowNames, colNames, cpxFormat); 1151 } 1152 1153 /// returns number of columns 1154 template <class R> 1155 int SoPlexBase<R>::numCols() const 1156 { 1157 assert(_realLP != nullptr); 1158 return _realLP->nCols(); 1159 } 1160 1161 /// returns number of rows 1162 template <class R> 1163 int SoPlexBase<R>::numRows() const 1164 { 1165 assert(_realLP != nullptr); 1166 return _realLP->nRows(); 1167 } 1168 1169 /// returns number of nonzeros 1170 template <class R> 1171 int SoPlexBase<R>::numNonzeros() const 1172 { 1173 assert(_realLP != 0); 1174 return _realLP->nNzos(); 1175 } 1176 1177 /// gets the primal solution vector if available; returns true on success 1178 template <class R> 1179 bool SoPlexBase<R>::getPrimal(VectorBase<R>& vector) 1180 { 1181 if(hasSol() && vector.dim() >= numCols()) 1182 { 1183 _syncRealSolution(); 1184 _solReal.getPrimalSol(vector); 1185 return true; 1186 } 1187 else 1188 return false; 1189 } 1190 1191 // A custom function for compatibility with scip and avoid making unnecessary 1192 // copies. 1193 template <class R> 1194 bool SoPlexBase<R>::getPrimalReal(R* p_vector, int size) 1195 { 1196 if(hasSol() && size >= numCols()) 1197 { 1198 _syncRealSolution(); 1199 1200 auto& primal = _solReal._primal; 1201 std::copy(primal.begin(), primal.end(), p_vector); 1202 1203 return true; 1204 } 1205 else 1206 return false; 1207 } 1208 1209 /// gets the primal ray if available; returns true on success 1210 template <class R> 1211 bool SoPlexBase<R>::getPrimalRay(VectorBase<R>& vector) 1212 { 1213 if(hasPrimalRay() && vector.dim() >= numCols()) 1214 { 1215 _syncRealSolution(); 1216 _solReal.getPrimalRaySol(vector); 1217 return true; 1218 } 1219 else 1220 return false; 1221 1222 } 1223 1224 1225 /// gets the dual solution vector if available; returns true on success 1226 template <class R> 1227 bool SoPlexBase<R>::getDual(VectorBase<R>& vector) 1228 { 1229 if(hasSol() && vector.dim() >= numRows()) 1230 { 1231 _syncRealSolution(); 1232 _solReal.getDualSol(vector); 1233 return true; 1234 } 1235 else 1236 return false; 1237 } 1238 1239 1240 1241 /// gets the Farkas proof if available; returns true on success 1242 template <class R> 1243 bool SoPlexBase<R>::getDualFarkas(VectorBase<R>& vector) 1244 { 1245 if(hasDualFarkas() && vector.dim() >= numRows()) 1246 { 1247 _syncRealSolution(); 1248 _solReal.getDualFarkasSol(vector); 1249 return true; 1250 } 1251 else 1252 return false; 1253 } 1254 1255 1256 /// gets violation of bounds; returns true on success 1257 template <class R> 1258 bool SoPlexBase<R>::getBoundViolation(R& maxviol, R& sumviol) 1259 { 1260 if(!isPrimalFeasible()) 1261 return false; 1262 1263 _syncRealSolution(); 1264 VectorBase<R>& primal = _solReal._primal; 1265 assert(primal.dim() == numCols()); 1266 1267 maxviol = 0.0; 1268 sumviol = 0.0; 1269 1270 for(int i = numCols() - 1; i >= 0; i--) 1271 { 1272 R lower = _realLP->lowerUnscaled(i); 1273 R upper = _realLP->upperUnscaled(i); 1274 R viol = lower - primal[i]; 1275 1276 if(viol > 0.0) 1277 { 1278 sumviol += viol; 1279 1280 if(viol > maxviol) 1281 maxviol = viol; 1282 } 1283 1284 viol = primal[i] - upper; 1285 1286 if(viol > 0.0) 1287 { 1288 sumviol += viol; 1289 1290 if(viol > maxviol) 1291 maxviol = viol; 1292 } 1293 } 1294 1295 return true; 1296 } 1297 1298 /// gets the vector of reduced cost values if available; returns true on success 1299 template <class R> 1300 bool SoPlexBase<R>::getRedCost(VectorBase<R>& vector) 1301 { 1302 if(hasSol() && vector.dim() >= numCols()) 1303 { 1304 _syncRealSolution(); 1305 _solReal.getRedCostSol(vector); 1306 return true; 1307 } 1308 else 1309 return false; 1310 } 1311 1312 /// gets violation of constraints; returns true on success 1313 template <class R> 1314 bool SoPlexBase<R>::getRowViolation(R& maxviol, R& sumviol) 1315 { 1316 if(!isPrimalFeasible()) 1317 return false; 1318 1319 _syncRealSolution(); 1320 VectorBase<R>& primal = _solReal._primal; 1321 assert(primal.dim() == numCols()); 1322 1323 VectorBase<R> activity(numRows()); 1324 _realLP->computePrimalActivity(primal, activity, true); 1325 maxviol = 0.0; 1326 sumviol = 0.0; 1327 1328 for(int i = numRows() - 1; i >= 0; i--) 1329 { 1330 R lhs = _realLP->lhsUnscaled(i); 1331 R rhs = _realLP->rhsUnscaled(i); 1332 1333 R viol = lhs - activity[i]; 1334 1335 if(viol > 0.0) 1336 { 1337 sumviol += viol; 1338 1339 if(viol > maxviol) 1340 maxviol = viol; 1341 } 1342 1343 viol = activity[i] - rhs; 1344 1345 if(viol > 0.0) 1346 { 1347 sumviol += viol; 1348 1349 if(viol > maxviol) 1350 maxviol = viol; 1351 } 1352 } 1353 1354 return true; 1355 } 1356 1357 /// gets violation of dual multipliers; returns true on success 1358 template <class R> 1359 bool SoPlexBase<R>::getDualViolation(R& maxviol, R& sumviol) 1360 { 1361 if(!hasBasis()) 1362 return false; 1363 1364 _syncRealSolution(); 1365 VectorBase<R>& dual = _solReal._dual; 1366 assert(dual.dim() == numRows()); 1367 1368 maxviol = 0.0; 1369 sumviol = 0.0; 1370 1371 for(int r = numRows() - 1; r >= 0; r--) 1372 { 1373 typename SPxSolverBase<R>::VarStatus rowStatus = basisRowStatus(r); 1374 1375 if(intParam(SoPlexBase<R>::OBJSENSE) == OBJSENSE_MINIMIZE) 1376 { 1377 if(rowStatus != SPxSolverBase<R>::ON_UPPER && rowStatus != SPxSolverBase<R>::FIXED && dual[r] < 0.0) 1378 { 1379 sumviol += -dual[r]; 1380 1381 if(dual[r] < -maxviol) 1382 maxviol = -dual[r]; 1383 } 1384 1385 if(rowStatus != SPxSolverBase<R>::ON_LOWER && rowStatus != SPxSolverBase<R>::FIXED && dual[r] > 0.0) 1386 { 1387 sumviol += dual[r]; 1388 1389 if(dual[r] > maxviol) 1390 maxviol = dual[r]; 1391 } 1392 } 1393 else 1394 { 1395 if(rowStatus != SPxSolverBase<R>::ON_UPPER && rowStatus != SPxSolverBase<R>::FIXED && dual[r] > 0.0) 1396 { 1397 sumviol += dual[r]; 1398 1399 if(dual[r] > maxviol) 1400 maxviol = dual[r]; 1401 } 1402 1403 if(rowStatus != SPxSolverBase<R>::ON_LOWER && rowStatus != SPxSolverBase<R>::FIXED && dual[r] < 0.0) 1404 { 1405 sumviol += -dual[r]; 1406 1407 if(dual[r] < -maxviol) 1408 maxviol = -dual[r]; 1409 } 1410 } 1411 } 1412 1413 return true; 1414 } 1415 1416 /// gets violation of reduced costs; returns true on success 1417 template <class R> 1418 bool SoPlexBase<R>::getRedCostViolation(R& maxviol, R& sumviol) 1419 { 1420 if(!hasBasis()) 1421 return false; 1422 1423 _syncRealSolution(); 1424 VectorBase<R>& redcost = _solReal._redCost; 1425 assert(redcost.dim() == numCols()); 1426 1427 maxviol = 0.0; 1428 sumviol = 0.0; 1429 1430 for(int c = numCols() - 1; c >= 0; c--) 1431 { 1432 typename SPxSolverBase<R>::VarStatus colStatus = basisColStatus(c); 1433 1434 if(intParam(SoPlexBase<R>::OBJSENSE) == OBJSENSE_MINIMIZE) 1435 { 1436 if(colStatus != SPxSolverBase<R>::ON_UPPER && colStatus != SPxSolverBase<R>::FIXED 1437 && redcost[c] < 0.0) 1438 { 1439 sumviol += -redcost[c]; 1440 1441 if(redcost[c] < -maxviol) 1442 maxviol = -redcost[c]; 1443 } 1444 1445 if(colStatus != SPxSolverBase<R>::ON_LOWER && colStatus != SPxSolverBase<R>::FIXED 1446 && redcost[c] > 0.0) 1447 { 1448 sumviol += redcost[c]; 1449 1450 if(redcost[c] > maxviol) 1451 maxviol = redcost[c]; 1452 } 1453 } 1454 else 1455 { 1456 if(colStatus != SPxSolverBase<R>::ON_UPPER && colStatus != SPxSolverBase<R>::FIXED 1457 && redcost[c] > 0.0) 1458 { 1459 sumviol += redcost[c]; 1460 1461 if(redcost[c] > maxviol) 1462 maxviol = redcost[c]; 1463 } 1464 1465 if(colStatus != SPxSolverBase<R>::ON_LOWER && colStatus != SPxSolverBase<R>::FIXED 1466 && redcost[c] < 0.0) 1467 { 1468 sumviol += -redcost[c]; 1469 1470 if(redcost[c] < -maxviol) 1471 maxviol = -redcost[c]; 1472 } 1473 } 1474 } 1475 1476 return true; 1477 } 1478 1479 1480 /// assignment operator 1481 template <class R> 1482 SoPlexBase<R>& SoPlexBase<R>::operator=(const SoPlexBase<R>& rhs) 1483 { 1484 if(this != &rhs) 1485 { 1486 // copy message handler 1487 spxout = rhs.spxout; 1488 1489 // copy statistics 1490 *_statistics = *(rhs._statistics); 1491 1492 // copy settings 1493 *_currentSettings = *(rhs._currentSettings); 1494 1495 // copy solver components 1496 _solver = rhs._solver; 1497 _slufactor = rhs._slufactor; 1498 _simplifierMainSM = rhs._simplifierMainSM; 1499 _simplifierPaPILO = rhs._simplifierPaPILO; 1500 _scalerUniequi = rhs._scalerUniequi; 1501 _scalerBiequi = rhs._scalerBiequi; 1502 _scalerGeo1 = rhs._scalerGeo1; 1503 _scalerGeo8 = rhs._scalerGeo8; 1504 _scalerGeoequi = rhs._scalerGeoequi; 1505 _scalerLeastsq = rhs._scalerLeastsq; 1506 _starterWeight = rhs._starterWeight; 1507 _starterSum = rhs._starterSum; 1508 _starterVector = rhs._starterVector; 1509 _pricerAuto = rhs._pricerAuto; 1510 _pricerDantzig = rhs._pricerDantzig; 1511 _pricerParMult = rhs._pricerParMult; 1512 _pricerDevex = rhs._pricerDevex; 1513 _pricerQuickSteep = rhs._pricerQuickSteep; 1514 _pricerSteep = rhs._pricerSteep; 1515 _ratiotesterTextbook = rhs._ratiotesterTextbook; 1516 _ratiotesterHarris = rhs._ratiotesterHarris; 1517 _ratiotesterFast = rhs._ratiotesterFast; 1518 _ratiotesterBoundFlipping = rhs._ratiotesterBoundFlipping; 1519 _tolerances = rhs._tolerances; 1520 1521 // copy solution data 1522 _status = rhs._status; 1523 _lastSolveMode = rhs._lastSolveMode; 1524 _basisStatusRows = rhs._basisStatusRows; 1525 _basisStatusCols = rhs._basisStatusCols; 1526 1527 if(rhs._hasSolReal) 1528 _solReal = rhs._solReal; 1529 1530 if(rhs._hasSolRational) 1531 _solRational = rhs._solRational; 1532 1533 _solver.setTolerances(_tolerances); 1534 _boostedSolver.setTolerances(_tolerances); 1535 1536 _simplifierMainSM.setTolerances(_tolerances); 1537 _simplifierPaPILO.setTolerances(_tolerances); 1538 1539 // set tolerances for scalers 1540 _scalerUniequi.setTolerances(_tolerances); 1541 _scalerBiequi.setTolerances(_tolerances); 1542 _scalerGeo1.setTolerances(_tolerances); 1543 _scalerGeo8.setTolerances(_tolerances); 1544 _scalerGeoequi.setTolerances(_tolerances); 1545 _scalerLeastsq.setTolerances(_tolerances); 1546 1547 _boostedScalerUniequi.setTolerances(_tolerances); 1548 _boostedScalerBiequi.setTolerances(_tolerances); 1549 _boostedScalerGeo1.setTolerances(_tolerances); 1550 _boostedScalerGeo8.setTolerances(_tolerances); 1551 _boostedScalerGeoequi.setTolerances(_tolerances); 1552 _boostedScalerLeastsq.setTolerances(_tolerances); 1553 1554 // set tolerances for ratio testers 1555 _ratiotesterBoundFlipping.setTolerances(_tolerances); 1556 _ratiotesterFast.setTolerances(_tolerances); 1557 _ratiotesterHarris.setTolerances(_tolerances); 1558 _ratiotesterTextbook.setTolerances(_tolerances); 1559 1560 _boostedRatiotesterBoundFlipping.setTolerances(_tolerances); 1561 _boostedRatiotesterFast.setTolerances(_tolerances); 1562 _boostedRatiotesterHarris.setTolerances(_tolerances); 1563 _boostedRatiotesterTextbook.setTolerances(_tolerances); 1564 1565 // set tolerances for slufactor 1566 _slufactor.setTolerances(_tolerances); 1567 _boostedSlufactor.setTolerances(_tolerances); 1568 1569 // set message handlers in members 1570 _solver.setOutstream(spxout); 1571 1572 1573 _simplifierMainSM.setOutstream(spxout); 1574 _simplifierPaPILO.setOutstream(spxout); 1575 _scalerUniequi.setOutstream(spxout); 1576 _scalerBiequi.setOutstream(spxout); 1577 _scalerGeo1.setOutstream(spxout); 1578 _scalerGeo8.setOutstream(spxout); 1579 _scalerGeoequi.setOutstream(spxout); 1580 _scalerLeastsq.setOutstream(spxout); 1581 1582 // transfer the lu solver 1583 _solver.setBasisSolver(&_slufactor); 1584 1585 // initialize pointers for simplifier, scaler, and starter 1586 setIntParam(SoPlexBase<R>::SIMPLIFIER, intParam(SoPlexBase<R>::SIMPLIFIER), true); 1587 setIntParam(SoPlexBase<R>::SCALER, intParam(SoPlexBase<R>::SCALER), true); 1588 setIntParam(SoPlexBase<R>::STARTER, intParam(SoPlexBase<R>::STARTER), true); 1589 1590 // copy real LP if different from the LP in the solver 1591 if(rhs._realLP != &(rhs._solver)) 1592 { 1593 _realLP = 0; 1594 spx_alloc(_realLP); 1595 _realLP = new(_realLP) SPxLPBase<R>(*(rhs._realLP)); 1596 } 1597 else 1598 _realLP = &_solver; 1599 1600 // copy rational LP 1601 if(rhs._rationalLP == nullptr) 1602 { 1603 if(_rationalLP != nullptr) 1604 { 1605 clearLPRational(); 1606 _rationalLP->~SPxLPRational(); 1607 spx_free(_rationalLP); 1608 } 1609 1610 _rationalLP = nullptr; 1611 } 1612 else 1613 { 1614 assert(intParam(SoPlexBase<R>::SYNCMODE) != SYNCMODE_ONLYREAL); 1615 _rationalLP = 0; 1616 spx_alloc(_rationalLP); 1617 _rationalLP = new(_rationalLP) SPxLPRational(*rhs._rationalLP); 1618 _rowTypes = rhs._rowTypes; 1619 _colTypes = rhs._colTypes; 1620 _rationalPosInfty = rhs._rationalPosInfty; 1621 _rationalNegInfty = rhs._rationalNegInfty; 1622 _rationalLP->setTolerances(rhs._rationalLP->tolerances()); 1623 _rationalLUSolver = rhs._rationalLUSolver; 1624 _rationalLUSolverBind = rhs._rationalLUSolverBind; 1625 } 1626 1627 // copy boolean flags 1628 _isRealLPLoaded = rhs._isRealLPLoaded; 1629 _isRealLPScaled = rhs._isRealLPScaled; 1630 _hasSolReal = rhs._hasSolReal; 1631 _hasSolRational = rhs._hasSolRational; 1632 _hasBasis = rhs._hasBasis; 1633 _applyPolishing = rhs._applyPolishing; 1634 1635 // rational constants do not need to be assigned 1636 #ifdef SOPLEX_WITH_BOOST 1637 _rationalPosone = 1; 1638 _rationalNegone = -1; 1639 _rationalZero = 0; 1640 #endif 1641 } 1642 1643 assert(_isConsistent()); 1644 1645 return *this; 1646 } 1647 1648 /// returns smallest non-zero element in absolute value 1649 template <class R> 1650 R SoPlexBase<R>::minAbsNonzeroReal() const 1651 { 1652 assert(_realLP != 0); 1653 return _realLP->minAbsNzo(); 1654 } 1655 1656 1657 /// returns biggest non-zero element in absolute value 1658 template <class R> 1659 R SoPlexBase<R>::maxAbsNonzeroReal() const 1660 { 1661 assert(_realLP != 0); 1662 return _realLP->maxAbsNzo(); 1663 } 1664 1665 1666 /// returns (unscaled) coefficient 1667 template <class R> 1668 R SoPlexBase<R>::coefReal(int row, int col) const 1669 { 1670 if(_realLP->isScaled()) 1671 { 1672 assert(_scaler); 1673 return _scaler->getCoefUnscaled(*_realLP, row, col); 1674 } 1675 else 1676 return colVectorRealInternal(col)[row]; 1677 } 1678 1679 /// returns vector of row \p i, ignoring scaling 1680 template <class R> 1681 const SVectorBase<R>& SoPlexBase<R>::rowVectorRealInternal(int i) const 1682 { 1683 assert(_realLP != 0); 1684 return _realLP->rowVector(i); 1685 } 1686 1687 /// gets vector of row \p i 1688 template <class R> 1689 void SoPlexBase<R>::getRowVectorReal(int i, DSVectorBase<R>& row) const 1690 { 1691 assert(_realLP); 1692 1693 if(_realLP->isScaled()) 1694 { 1695 assert(_scaler); 1696 row.setMax(_realLP->rowVector(i).size()); 1697 _scaler->getRowUnscaled(*_realLP, i, row); 1698 } 1699 else 1700 row = _realLP->rowVector(i); 1701 } 1702 1703 1704 /// returns right-hand side vector, ignoring scaling 1705 template <class R> 1706 const VectorBase<R>& SoPlexBase<R>::rhsRealInternal() const 1707 { 1708 assert(_realLP != 0); 1709 return _realLP->rhs(); 1710 } 1711 1712 1713 1714 /// gets right-hand side vector 1715 template <class R> 1716 void SoPlexBase<R>::getRhsReal(VectorBase<R>& rhs) const 1717 { 1718 assert(_realLP); 1719 _realLP->getRhsUnscaled(rhs); 1720 } 1721 1722 1723 1724 /// returns right-hand side of row \p i 1725 template <class R> 1726 R SoPlexBase<R>::rhsReal(int i) const 1727 { 1728 assert(_realLP != 0); 1729 return _realLP->rhsUnscaled(i); 1730 } 1731 1732 /// returns left-hand side vector, ignoring scaling 1733 template <class R> 1734 const VectorBase<R>& SoPlexBase<R>::lhsRealInternal() const 1735 { 1736 assert(_realLP != 0); 1737 return _realLP->lhs(); 1738 } 1739 1740 /// gets left-hand side vector 1741 template <class R> 1742 void SoPlexBase<R>::getLhsReal(VectorBase<R>& lhs) const 1743 { 1744 assert(_realLP); 1745 _realLP->getLhsUnscaled(lhs); 1746 } 1747 1748 /// returns left-hand side of row \p i 1749 template <class R> 1750 R SoPlexBase<R>::lhsReal(int i) const 1751 { 1752 assert(_realLP != 0); 1753 return _realLP->lhsUnscaled(i); 1754 } 1755 1756 1757 /// returns inequality type of row \p i 1758 template <class R> 1759 typename LPRowBase<R>::Type SoPlexBase<R>::rowTypeReal(int i) const 1760 { 1761 assert(_realLP != 0); 1762 return _realLP->rowType(i); 1763 } 1764 1765 /// returns vector of col \p i, ignoring scaling 1766 template <class R> 1767 const SVectorBase<R>& SoPlexBase<R>::colVectorRealInternal(int i) const 1768 { 1769 assert(_realLP != 0); 1770 return _realLP->colVector(i); 1771 } 1772 1773 /// gets vector of col \p i 1774 template <class R> 1775 void SoPlexBase<R>::getColVectorReal(int i, DSVectorBase<R>& col) const 1776 { 1777 assert(_realLP); 1778 _realLP->getColVectorUnscaled(i, col); 1779 } 1780 1781 1782 /// returns upper bound vector 1783 template <class R> 1784 const VectorBase<R>& SoPlexBase<R>::upperRealInternal() const 1785 { 1786 assert(_realLP != 0); 1787 return _realLP->upper(); 1788 } 1789 1790 1791 /// returns upper bound of column \p i 1792 template <class R> 1793 R SoPlexBase<R>::upperReal(int i) const 1794 { 1795 assert(_realLP != 0); 1796 return _realLP->upperUnscaled(i); 1797 } 1798 1799 1800 /// gets upper bound vector 1801 template <class R> 1802 void SoPlexBase<R>::getUpperReal(VectorBase<R>& upper) const 1803 { 1804 assert(_realLP != 0); 1805 _realLP->getUpperUnscaled(upper); 1806 } 1807 1808 1809 /// returns lower bound vector 1810 template <class R> 1811 const VectorBase<R>& SoPlexBase<R>::lowerRealInternal() const 1812 { 1813 assert(_realLP != 0); 1814 return _realLP->lower(); 1815 } 1816 1817 1818 1819 /// returns lower bound of column \p i 1820 template <class R> 1821 R SoPlexBase<R>::lowerReal(int i) const 1822 { 1823 assert(_realLP != 0); 1824 return _realLP->lowerUnscaled(i); 1825 } 1826 1827 1828 /// gets lower bound vector 1829 template <class R> 1830 void SoPlexBase<R>::getLowerReal(VectorBase<R>& lower) const 1831 { 1832 assert(_realLP != 0); 1833 _realLP->getLowerUnscaled(lower); 1834 } 1835 1836 1837 /// gets objective function vector 1838 template <class R> 1839 void SoPlexBase<R>::getObjReal(VectorBase<R>& obj) const 1840 { 1841 assert(_realLP != 0); 1842 _realLP->getObjUnscaled(obj); 1843 } 1844 1845 1846 /// returns objective value of column \p i 1847 template <class R> 1848 R SoPlexBase<R>::objReal(int i) const 1849 { 1850 assert(_realLP != 0); 1851 return _realLP->objUnscaled(i); 1852 } 1853 1854 1855 /// returns objective function vector after transformation to a maximization problem; since this is how it is stored 1856 /// internally, this is generally faster 1857 template <class R> 1858 const VectorBase<R>& SoPlexBase<R>::maxObjRealInternal() const 1859 { 1860 assert(_realLP != 0); 1861 return _realLP->maxObj(); 1862 } 1863 1864 1865 /// returns objective value of column \p i after transformation to a maximization problem; since this is how it is 1866 /// stored internally, this is generally faster 1867 template <class R> 1868 R SoPlexBase<R>::maxObjReal(int i) const 1869 { 1870 assert(_realLP != 0); 1871 return _realLP->maxObjUnscaled(i); 1872 } 1873 1874 1875 /// gets number of available dual norms 1876 template <class R> 1877 void SoPlexBase<R>::getNdualNorms(int& nnormsRow, int& nnormsCol) const 1878 { 1879 _solver.getNdualNorms(nnormsRow, nnormsCol); 1880 } 1881 1882 1883 /// gets steepest edge norms and returns false if they are not available 1884 template <class R> 1885 bool SoPlexBase<R>::getDualNorms(int& nnormsRow, int& nnormsCol, R* norms) const 1886 { 1887 return _solver.getDualNorms(nnormsRow, nnormsCol, norms); 1888 } 1889 1890 1891 /// sets steepest edge norms and returns false if that's not possible 1892 template <class R> 1893 bool SoPlexBase<R>::setDualNorms(int nnormsRow, int nnormsCol, R* norms) 1894 { 1895 return _solver.setDualNorms(nnormsRow, nnormsCol, norms); 1896 } 1897 1898 1899 /// pass integrality information about the variables to the solver 1900 template <class R> 1901 void SoPlexBase<R>::setIntegralityInformation(int ncols, int* intInfo) 1902 { 1903 assert(ncols == _solver.nCols() || (ncols == 0 && intInfo == NULL)); 1904 _solver.setIntegralityInformation(ncols, intInfo); 1905 } 1906 1907 1908 template <class R> 1909 int SoPlexBase<R>::numRowsRational() const 1910 { 1911 assert(_rationalLP != 0); 1912 return _rationalLP->nRows(); 1913 } 1914 1915 /// returns number of columns 1916 template <class R> 1917 int SoPlexBase<R>::numColsRational() const 1918 { 1919 assert(_rationalLP != 0); 1920 return _rationalLP->nCols(); 1921 } 1922 1923 /// returns number of nonzeros 1924 template <class R> 1925 int SoPlexBase<R>::numNonzerosRational() const 1926 { 1927 assert(_rationalLP != 0); 1928 return _rationalLP->nNzos(); 1929 } 1930 1931 /// returns smallest non-zero element in absolute value 1932 template <class R> 1933 Rational SoPlexBase<R>::minAbsNonzeroRational() const 1934 { 1935 assert(_rationalLP != 0); 1936 return _rationalLP->minAbsNzo(); 1937 } 1938 1939 /// returns biggest non-zero element in absolute value 1940 template <class R> 1941 Rational SoPlexBase<R>::maxAbsNonzeroRational() const 1942 { 1943 assert(_rationalLP != 0); 1944 return _rationalLP->maxAbsNzo(); 1945 } 1946 1947 /// gets row \p i 1948 template <class R> 1949 void SoPlexBase<R>::getRowRational(int i, LPRowRational& lprow) const 1950 { 1951 assert(_rationalLP != 0); 1952 _rationalLP->getRow(i, lprow); 1953 } 1954 1955 1956 /// gets rows \p start, ..., \p end. 1957 template <class R> 1958 void SoPlexBase<R>::getRowsRational(int start, int end, LPRowSetRational& lprowset) const 1959 { 1960 assert(_rationalLP != 0); 1961 _rationalLP->getRows(start, end, lprowset); 1962 } 1963 1964 1965 1966 /// returns vector of row \p i 1967 template <class R> 1968 const SVectorRational& SoPlexBase<R>::rowVectorRational(int i) const 1969 { 1970 assert(_rationalLP != 0); 1971 return _rationalLP->rowVector(i); 1972 } 1973 1974 /// returns right-hand side vector 1975 template <class R> 1976 const VectorRational& SoPlexBase<R>::rhsRational() const 1977 { 1978 assert(_rationalLP != 0); 1979 return _rationalLP->rhs(); 1980 } 1981 1982 1983 1984 /// returns right-hand side of row \p i 1985 template <class R> 1986 const Rational& SoPlexBase<R>::rhsRational(int i) const 1987 { 1988 assert(_rationalLP != 0); 1989 return _rationalLP->rhs(i); 1990 } 1991 1992 1993 /// returns left-hand side vector 1994 template <class R> 1995 const VectorRational& SoPlexBase<R>::lhsRational() const 1996 { 1997 assert(_rationalLP != 0); 1998 return _rationalLP->lhs(); 1999 } 2000 2001 2002 2003 /// returns left-hand side of row \p i 2004 template <class R> 2005 const Rational& SoPlexBase<R>::lhsRational(int i) const 2006 { 2007 assert(_rationalLP != 0); 2008 return _rationalLP->lhs(i); 2009 } 2010 2011 2012 2013 /// returns inequality type of row \p i 2014 template <class R> 2015 LPRowRational::Type SoPlexBase<R>::rowTypeRational(int i) const 2016 { 2017 assert(_rationalLP != 0); 2018 return _rationalLP->rowType(i); 2019 } 2020 2021 2022 2023 /// gets column \p i 2024 template <class R> 2025 void SoPlexBase<R>::getColRational(int i, LPColRational& lpcol) const 2026 { 2027 assert(_rationalLP != 0); 2028 return _rationalLP->getCol(i, lpcol); 2029 } 2030 2031 2032 2033 /// gets columns \p start, ..., \p end 2034 template <class R> 2035 void SoPlexBase<R>::getColsRational(int start, int end, LPColSetRational& lpcolset) const 2036 { 2037 assert(_rationalLP != 0); 2038 return _rationalLP->getCols(start, end, lpcolset); 2039 } 2040 2041 2042 /// returns vector of column \p i 2043 template <class R> 2044 const SVectorRational& SoPlexBase<R>::colVectorRational(int i) const 2045 { 2046 assert(_rationalLP != 0); 2047 return _rationalLP->colVector(i); 2048 } 2049 2050 2051 2052 /// returns upper bound vector 2053 template <class R> 2054 const VectorRational& SoPlexBase<R>::upperRational() const 2055 { 2056 assert(_rationalLP != 0); 2057 return _rationalLP->upper(); 2058 } 2059 2060 2061 2062 /// returns upper bound of column \p i 2063 template <class R> 2064 const Rational& SoPlexBase<R>::upperRational(int i) const 2065 { 2066 assert(_rationalLP != 0); 2067 return _rationalLP->upper(i); 2068 } 2069 2070 2071 2072 /// returns lower bound vector 2073 template <class R> 2074 const VectorRational& SoPlexBase<R>::lowerRational() const 2075 { 2076 assert(_rationalLP != 0); 2077 return _rationalLP->lower(); 2078 } 2079 2080 /// returns lower bound of column \p i 2081 template <class R> 2082 const Rational& SoPlexBase<R>::lowerRational(int i) const 2083 { 2084 assert(_rationalLP != 0); 2085 return _rationalLP->lower(i); 2086 } 2087 2088 2089 2090 /// gets objective function vector 2091 template <class R> 2092 void SoPlexBase<R>::getObjRational(VectorRational& obj) const 2093 { 2094 assert(_rationalLP != 0); 2095 _rationalLP->getObj(obj); 2096 } 2097 2098 2099 2100 /// gets objective value of column \p i 2101 template <class R> 2102 void SoPlexBase<R>::getObjRational(int i, Rational& obj) const 2103 { 2104 obj = maxObjRational(i); 2105 2106 if(intParam(SoPlexBase<R>::OBJSENSE) == SoPlexBase<R>::OBJSENSE_MINIMIZE) 2107 obj *= -1; 2108 } 2109 2110 2111 2112 /// returns objective value of column \p i 2113 template <class R> 2114 Rational SoPlexBase<R>::objRational(int i) const 2115 { 2116 assert(_rationalLP != 0); 2117 return _rationalLP->obj(i); 2118 } 2119 2120 2121 2122 /// returns objective function vector after transformation to a maximization problem; since this is how it is stored 2123 /// internally, this is generally faster 2124 template <class R> 2125 const VectorRational& SoPlexBase<R>::maxObjRational() const 2126 { 2127 assert(_rationalLP != 0); 2128 return _rationalLP->maxObj(); 2129 } 2130 2131 2132 2133 /// returns objective value of column \p i after transformation to a maximization problem; since this is how it is 2134 /// stored internally, this is generally faster 2135 template <class R> 2136 const Rational& SoPlexBase<R>::maxObjRational(int i) const 2137 { 2138 assert(_rationalLP != 0); 2139 return _rationalLP->maxObj(i); 2140 } 2141 2142 2143 2144 /// adds a single row 2145 template <class R> 2146 void SoPlexBase<R>::addRowReal(const LPRowBase<R>& lprow) 2147 { 2148 assert(_realLP != 0); 2149 2150 _addRowReal(lprow); 2151 2152 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2153 { 2154 _rationalLP->addRow(lprow); 2155 _completeRangeTypesRational(); 2156 } 2157 2158 _invalidateSolution(); 2159 } 2160 2161 2162 2163 /// adds multiple rows 2164 template <class R> 2165 void SoPlexBase<R>::addRowsReal(const LPRowSetBase<R>& lprowset) 2166 { 2167 assert(_realLP != 0); 2168 2169 _addRowsReal(lprowset); 2170 2171 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2172 { 2173 _rationalLP->addRows(lprowset); 2174 _completeRangeTypesRational(); 2175 } 2176 2177 _invalidateSolution(); 2178 } 2179 2180 2181 2182 /// adds a single column 2183 template <class R> 2184 void SoPlexBase<R>::addColReal(const LPColBase<R>& lpcol) 2185 { 2186 assert(_realLP != 0); 2187 2188 _addColReal(lpcol); 2189 2190 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2191 { 2192 _rationalLP->addCol(lpcol); 2193 _completeRangeTypesRational(); 2194 } 2195 2196 _invalidateSolution(); 2197 } 2198 2199 2200 2201 /// adds multiple columns 2202 template <class R> 2203 void SoPlexBase<R>::addColsReal(const LPColSetBase<R>& lpcolset) 2204 { 2205 assert(_realLP != 0); 2206 2207 _addColsReal(lpcolset); 2208 2209 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2210 { 2211 _rationalLP->addCols(lpcolset); 2212 _completeRangeTypesRational(); 2213 } 2214 2215 _invalidateSolution(); 2216 } 2217 2218 2219 2220 /// replaces row \p i with \p lprow 2221 template <class R> 2222 void SoPlexBase<R>::changeRowReal(int i, const LPRowBase<R>& lprow) 2223 { 2224 assert(_realLP != 0); 2225 2226 _changeRowReal(i, lprow); 2227 2228 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2229 { 2230 _rationalLP->changeRow(i, lprow); 2231 _rowTypes[i] = _rangeTypeReal(lprow.lhs(), lprow.rhs()); 2232 _completeRangeTypesRational(); 2233 } 2234 2235 _invalidateSolution(); 2236 } 2237 #ifdef SOPLEX_WITH_GMP 2238 /// adds a single column (GMP only method) 2239 template <class R> 2240 void SoPlexBase<R>::addColRational(const mpq_t* obj, const mpq_t* lower, const mpq_t* colValues, 2241 const int* colIndices, const int colSize, const mpq_t* upper) 2242 { 2243 assert(_rationalLP != 0); 2244 2245 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 2246 return; 2247 2248 _rationalLP->addCol(obj, lower, colValues, colIndices, colSize, upper); 2249 int i = numColsRational() - 1; 2250 _completeRangeTypesRational(); 2251 2252 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2253 _addColReal(R(maxObjRational(i)) * (intParam(SoPlexBase<R>::OBJSENSE) == 2254 SoPlexBase<R>::OBJSENSE_MAXIMIZE ? 1.0 : -1.0), 2255 R(lowerRational(i)), DSVectorBase<R>(_rationalLP->colVector(i)), R(upperRational(i))); 2256 2257 _invalidateSolution(); 2258 } 2259 2260 2261 2262 /// adds a set of columns (GMP only method) 2263 template <class R> 2264 void SoPlexBase<R>::addColsRational(const mpq_t* obj, const mpq_t* lower, const mpq_t* colValues, 2265 const int* colIndices, const int* colStarts, const int* colLengths, const int numCols, 2266 const int numValues, const mpq_t* upper) 2267 { 2268 assert(_rationalLP != 0); 2269 2270 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 2271 return; 2272 2273 _rationalLP->addCols(obj, lower, colValues, colIndices, colStarts, colLengths, numCols, numValues, 2274 upper); 2275 _completeRangeTypesRational(); 2276 2277 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2278 { 2279 LPColSetReal lpcolset; 2280 2281 for(int i = numColsRational() - numCols; i < numColsRational(); i++) 2282 lpcolset.add(R(maxObjRational(i)) * (intParam(SoPlexBase<R>::OBJSENSE) == 2283 SoPlexBase<R>::OBJSENSE_MAXIMIZE ? 1.0 : -1.0), 2284 R(lowerRational(i)), DSVectorBase<R>(_rationalLP->colVector(i)), R(upperRational(i))); 2285 2286 _addColsReal(lpcolset); 2287 } 2288 2289 _invalidateSolution(); 2290 } 2291 #endif 2292 2293 2294 /// changes left-hand side vector for constraints to \p lhs 2295 template <class R> 2296 void SoPlexBase<R>::changeLhsReal(const VectorBase<R>& lhs) 2297 { 2298 assert(_realLP != 0); 2299 2300 _changeLhsReal(lhs); 2301 2302 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2303 { 2304 _rationalLP->changeLhs(VectorRational(lhs)); 2305 2306 for(int i = 0; i < numRowsRational(); i++) 2307 _rowTypes[i] = _rangeTypeRational(_rationalLP->lhs(i), _rationalLP->rhs(i)); 2308 } 2309 2310 _invalidateSolution(); 2311 } 2312 2313 2314 2315 /// changes left-hand side of row \p i to \p lhs 2316 template <class R> 2317 void SoPlexBase<R>::changeLhsReal(int i, const R& lhs) 2318 { 2319 assert(_realLP != 0); 2320 2321 _changeLhsReal(i, lhs); 2322 2323 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2324 { 2325 _rationalLP->changeLhs(i, lhs); 2326 _rowTypes[i] = _rangeTypeRational(_rationalLP->lhs(i), _rationalLP->rhs(i)); 2327 } 2328 2329 _invalidateSolution(); 2330 } 2331 2332 2333 2334 /// changes right-hand side vector to \p rhs 2335 template <class R> 2336 void SoPlexBase<R>::changeRhsReal(const VectorBase<R>& rhs) 2337 { 2338 assert(_realLP != 0); 2339 2340 _changeRhsReal(rhs); 2341 2342 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2343 { 2344 _rationalLP->changeRhs(VectorRational(rhs)); 2345 2346 for(int i = 0; i < numRowsRational(); i++) 2347 _rowTypes[i] = _rangeTypeRational(_rationalLP->lhs(i), _rationalLP->rhs(i)); 2348 } 2349 2350 _invalidateSolution(); 2351 } 2352 2353 2354 2355 /// changes right-hand side of row \p i to \p rhs 2356 template <class R> 2357 void SoPlexBase<R>::changeRhsReal(int i, const R& rhs) 2358 { 2359 assert(_realLP != 0); 2360 2361 _changeRhsReal(i, rhs); 2362 2363 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2364 { 2365 _rationalLP->changeRhs(i, rhs); 2366 _rowTypes[i] = _rangeTypeRational(_rationalLP->lhs(i), _rationalLP->rhs(i)); 2367 } 2368 2369 _invalidateSolution(); 2370 } 2371 2372 2373 /// changes left- and right-hand side vectors 2374 template <class R> 2375 void SoPlexBase<R>::changeRangeReal(const VectorBase<R>& lhs, const VectorBase<R>& rhs) 2376 { 2377 assert(_realLP != 0); 2378 2379 _changeRangeReal(lhs, rhs); 2380 2381 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2382 { 2383 _rationalLP->changeRange(VectorRational(lhs), VectorRational(rhs)); 2384 2385 for(int i = 0; i < numRowsRational(); i++) 2386 _rowTypes[i] = _rangeTypeReal(lhs[i], rhs[i]); 2387 } 2388 2389 _invalidateSolution(); 2390 } 2391 2392 2393 2394 /// changes left- and right-hand side of row \p i 2395 template <class R> 2396 void SoPlexBase<R>::changeRangeReal(int i, const R& lhs, const R& rhs) 2397 { 2398 assert(_realLP != 0); 2399 2400 _changeRangeReal(i, lhs, rhs); 2401 2402 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2403 { 2404 _rationalLP->changeRange(i, lhs, rhs); 2405 _rowTypes[i] = _rangeTypeReal(lhs, rhs); 2406 } 2407 2408 _invalidateSolution(); 2409 } 2410 2411 2412 2413 /// replaces column \p i with \p lpcol 2414 template <class R> 2415 void SoPlexBase<R>::changeColReal(int i, const LPColReal& lpcol) 2416 { 2417 assert(_realLP != 0); 2418 2419 _changeColReal(i, lpcol); 2420 2421 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2422 { 2423 _rationalLP->changeCol(i, lpcol); 2424 _colTypes[i] = _rangeTypeReal(lpcol.lower(), lpcol.upper()); 2425 _completeRangeTypesRational(); 2426 } 2427 2428 _invalidateSolution(); 2429 } 2430 2431 2432 2433 /// changes vector of lower bounds to \p lower 2434 template <class R> 2435 void SoPlexBase<R>::changeLowerReal(const VectorBase<R>& lower) 2436 { 2437 assert(_realLP != 0); 2438 2439 _changeLowerReal(lower); 2440 2441 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2442 { 2443 _rationalLP->changeLower(VectorRational(lower)); 2444 2445 for(int i = 0; i < numColsRational(); i++) 2446 _colTypes[i] = _rangeTypeRational(_rationalLP->lower(i), _rationalLP->upper(i)); 2447 } 2448 2449 2450 _invalidateSolution(); 2451 } 2452 2453 2454 2455 /// changes lower bound of column i to \p lower 2456 template <class R> 2457 void SoPlexBase<R>::changeLowerReal(int i, const R& lower) 2458 { 2459 assert(_realLP != 0); 2460 2461 _changeLowerReal(i, lower); 2462 2463 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2464 { 2465 _rationalLP->changeLower(i, lower); 2466 _colTypes[i] = _rangeTypeRational(_rationalLP->lower(i), _rationalLP->upper(i)); 2467 } 2468 2469 _invalidateSolution(); 2470 } 2471 2472 2473 2474 /// changes vector of upper bounds to \p upper 2475 template <class R> 2476 void SoPlexBase<R>::changeUpperReal(const VectorBase<R>& upper) 2477 { 2478 assert(_realLP != 0); 2479 2480 _changeUpperReal(upper); 2481 2482 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2483 { 2484 _rationalLP->changeUpper(VectorRational(upper)); 2485 2486 for(int i = 0; i < numColsRational(); i++) 2487 _colTypes[i] = _rangeTypeRational(_rationalLP->lower(i), _rationalLP->upper(i)); 2488 } 2489 2490 _invalidateSolution(); 2491 } 2492 2493 2494 2495 /// changes \p i 'th upper bound to \p upper 2496 template <class R> 2497 void SoPlexBase<R>::changeUpperReal(int i, const R& upper) 2498 { 2499 assert(_realLP != 0); 2500 2501 _changeUpperReal(i, upper); 2502 2503 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2504 { 2505 _rationalLP->changeUpper(i, upper); 2506 _colTypes[i] = _rangeTypeRational(_rationalLP->lower(i), _rationalLP->upper(i)); 2507 } 2508 2509 _invalidateSolution(); 2510 } 2511 2512 2513 2514 /// changes vectors of column bounds to \p lower and \p upper 2515 template <class R> 2516 void SoPlexBase<R>::changeBoundsReal(const VectorBase<R>& lower, const VectorBase<R>& upper) 2517 { 2518 assert(_realLP != 0); 2519 2520 _changeBoundsReal(lower, upper); 2521 2522 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2523 { 2524 _rationalLP->changeBounds(VectorRational(lower), VectorRational(upper)); 2525 2526 for(int i = 0; i < numColsRational(); i++) 2527 _colTypes[i] = _rangeTypeReal(lower[i], upper[i]); 2528 } 2529 2530 _invalidateSolution(); 2531 } 2532 2533 2534 2535 /// changes bounds of column \p i to \p lower and \p upper 2536 template <class R> 2537 void SoPlexBase<R>::changeBoundsReal(int i, const R& lower, const R& upper) 2538 { 2539 assert(_realLP != 0); 2540 2541 _changeBoundsReal(i, lower, upper); 2542 2543 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2544 { 2545 _rationalLP->changeBounds(i, lower, upper); 2546 _colTypes[i] = _rangeTypeReal(lower, upper); 2547 } 2548 2549 _invalidateSolution(); 2550 } 2551 2552 2553 /// changes objective function vector to \p obj 2554 template <class R> 2555 void SoPlexBase<R>::changeObjReal(const VectorBase<R>& obj) 2556 { 2557 assert(_realLP != 0); 2558 2559 bool scale = _realLP->isScaled(); 2560 _realLP->changeObj(obj, scale); 2561 2562 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2563 _rationalLP->changeObj(VectorRational(obj)); 2564 2565 _invalidateSolution(); 2566 } 2567 2568 2569 2570 /// changes objective coefficient of column i to \p obj 2571 template <class R> 2572 void SoPlexBase<R>::changeObjReal(int i, const R& obj) 2573 { 2574 assert(_realLP != 0); 2575 2576 bool scale = _realLP->isScaled(); 2577 _realLP->changeObj(i, obj, scale); 2578 2579 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2580 _rationalLP->changeObj(i, obj); 2581 2582 _invalidateSolution(); 2583 } 2584 2585 2586 2587 /// changes matrix entry in row \p i and column \p j to \p val 2588 template <class R> 2589 void SoPlexBase<R>::changeElementReal(int i, int j, const R& val) 2590 { 2591 assert(_realLP != 0); 2592 2593 _changeElementReal(i, j, val); 2594 2595 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2596 _rationalLP->changeElement(i, j, val); 2597 2598 _invalidateSolution(); 2599 } 2600 2601 2602 2603 /// removes row \p i 2604 template <class R> 2605 void SoPlexBase<R>::removeRowReal(int i) 2606 { 2607 assert(_realLP != 0); 2608 2609 _removeRowReal(i); 2610 2611 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2612 { 2613 _rationalLP->removeRow(i); 2614 2615 // only swap elements if not the last one was removed 2616 if(i < _rationalLP->nRows()) 2617 { 2618 _rowTypes[i] = _rowTypes[_rationalLP->nRows()]; 2619 assert(_rowTypes[i] == _rangeTypeRational(lhsRational(i), rhsRational(i))); 2620 } 2621 2622 _rowTypes.reSize(_rationalLP->nRows()); 2623 } 2624 2625 _invalidateSolution(); 2626 } 2627 2628 2629 2630 /// removes all rows with an index \p i such that \p perm[i] < 0; upon completion, \p perm[i] >= 0 indicates the 2631 /// new index where row \p i has been moved to; note that \p perm must point to an array of size at least 2632 /// #numRows() 2633 template <class R> 2634 void SoPlexBase<R>::removeRowsReal(int perm[]) 2635 { 2636 assert(_realLP != 0); 2637 2638 const int oldsize = numRows(); 2639 _removeRowsReal(perm); 2640 2641 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2642 { 2643 _rationalLP->removeRows(perm); 2644 2645 for(int i = 0; i < oldsize; i++) 2646 { 2647 if(perm[i] >= 0) 2648 _rowTypes[perm[i]] = _rowTypes[i]; 2649 } 2650 2651 _rowTypes.reSize(_rationalLP->nRows()); 2652 2653 for(int i = 0; i < numRowsRational(); i++) 2654 { 2655 assert(_rowTypes[i] == _rangeTypeRational(lhsRational(i), rhsRational(i))); 2656 } 2657 } 2658 2659 _invalidateSolution(); 2660 } 2661 2662 2663 2664 /// remove all rows with indices in array \p idx of size \p n; an array \p perm of size #numRows() may be passed 2665 /// as buffer memory 2666 template <class R> 2667 void SoPlexBase<R>::removeRowsReal(int idx[], int n, int perm[]) 2668 { 2669 if(perm == 0) 2670 { 2671 DataArray< int > p(numRows()); 2672 _idxToPerm(idx, n, p.get_ptr(), numRows()); 2673 SoPlexBase<R>::removeRowsReal(p.get_ptr()); 2674 } 2675 else 2676 { 2677 _idxToPerm(idx, n, perm, numRows()); 2678 SoPlexBase<R>::removeRowsReal(perm); 2679 } 2680 } 2681 2682 2683 2684 /// removes rows \p start to \p end including both; an array \p perm of size #numRows() may be passed as buffer 2685 /// memory 2686 template <class R> 2687 void SoPlexBase<R>::removeRowRangeReal(int start, int end, int perm[]) 2688 { 2689 if(perm == 0) 2690 { 2691 DataArray< int > p(numRows()); 2692 _rangeToPerm(start, end, p.get_ptr(), numRows()); 2693 SoPlexBase<R>::removeRowsReal(p.get_ptr()); 2694 } 2695 else 2696 { 2697 _rangeToPerm(start, end, perm, numRows()); 2698 SoPlexBase<R>::removeRowsReal(perm); 2699 } 2700 } 2701 2702 2703 2704 /// removes column i 2705 template <class R> 2706 void SoPlexBase<R>::removeColReal(int i) 2707 { 2708 assert(_realLP != 0); 2709 2710 _removeColReal(i); 2711 2712 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2713 { 2714 _rationalLP->removeCol(i); 2715 2716 // only swap elements if not the last one was removed 2717 if(i < _rationalLP->nCols()) 2718 { 2719 _colTypes[i] = _colTypes[_rationalLP->nCols()]; 2720 assert(_colTypes[i] == _rangeTypeRational(lowerRational(i), upperRational(i))); 2721 } 2722 2723 _colTypes.reSize(_rationalLP->nCols()); 2724 } 2725 2726 _invalidateSolution(); 2727 } 2728 2729 2730 2731 /// removes all columns with an index \p i such that \p perm[i] < 0; upon completion, \p perm[i] >= 0 indicates the 2732 /// new index where column \p i has been moved to; note that \p perm must point to an array of size at least 2733 /// #numColsReal() 2734 template <class R> 2735 void SoPlexBase<R>::removeColsReal(int perm[]) 2736 { 2737 assert(_realLP != 0); 2738 2739 const int oldsize = numCols(); 2740 _removeColsReal(perm); 2741 2742 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2743 { 2744 _rationalLP->removeCols(perm); 2745 2746 for(int i = 0; i < oldsize; i++) 2747 { 2748 if(perm[i] >= 0) 2749 _colTypes[perm[i]] = _colTypes[i]; 2750 } 2751 2752 _colTypes.reSize(_rationalLP->nCols()); 2753 2754 for(int i = 0; i < numColsRational(); i++) 2755 { 2756 assert(_colTypes[i] == _rangeTypeRational(lowerRational(i), upperRational(i))); 2757 } 2758 } 2759 2760 _invalidateSolution(); 2761 } 2762 2763 2764 2765 /// remove all columns with indices in array \p idx of size \p n; an array \p perm of size #numColsReal() may be 2766 /// passed as buffer memory 2767 template <class R> 2768 void SoPlexBase<R>::removeColsReal(int idx[], int n, int perm[]) 2769 { 2770 if(perm == 0) 2771 { 2772 DataArray< int > p(numCols()); 2773 _idxToPerm(idx, n, p.get_ptr(), numCols()); 2774 SoPlexBase<R>::removeColsReal(p.get_ptr()); 2775 } 2776 else 2777 { 2778 _idxToPerm(idx, n, perm, numCols()); 2779 SoPlexBase<R>::removeColsReal(perm); 2780 } 2781 } 2782 2783 2784 2785 /// removes columns \p start to \p end including both; an array \p perm of size #numCols() may be passed as 2786 /// buffer memory 2787 template <class R> 2788 void SoPlexBase<R>::removeColRangeReal(int start, int end, int perm[]) 2789 { 2790 if(perm == 0) 2791 { 2792 DataArray< int > p(numCols()); 2793 _rangeToPerm(start, end, p.get_ptr(), numCols()); 2794 SoPlexBase<R>::removeColsReal(p.get_ptr()); 2795 } 2796 else 2797 { 2798 _rangeToPerm(start, end, perm, numCols()); 2799 SoPlexBase<R>::removeColsReal(perm); 2800 } 2801 } 2802 2803 2804 2805 /// clears the LP 2806 template <class R> 2807 void SoPlexBase<R>::clearLPReal() 2808 { 2809 assert(_realLP != 0); 2810 2811 _realLP->clear(); 2812 _hasBasis = false; 2813 _rationalLUSolver.clear(); 2814 2815 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2816 { 2817 _rationalLP->clear(); 2818 _rowTypes.clear(); 2819 _colTypes.clear(); 2820 } 2821 2822 _invalidateSolution(); 2823 } 2824 2825 2826 2827 /// synchronizes R LP with rational LP, i.e., copies (rounded) rational LP into R LP, if sync mode is manual 2828 template <class R> 2829 void SoPlexBase<R>::syncLPReal() 2830 { 2831 assert(_isConsistent()); 2832 2833 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_MANUAL) 2834 _syncLPReal(); 2835 } 2836 2837 2838 2839 /// adds a single row 2840 template <class R> 2841 void SoPlexBase<R>::addRowRational(const LPRowRational& lprow) 2842 { 2843 assert(_rationalLP != 0); 2844 2845 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 2846 return; 2847 2848 _rationalLP->addRow(lprow); 2849 _completeRangeTypesRational(); 2850 2851 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2852 _addRowReal(lprow); 2853 2854 _invalidateSolution(); 2855 } 2856 2857 2858 2859 #ifdef SOPLEX_WITH_GMP 2860 /// adds a single row (GMP only method) 2861 template <class R> 2862 void SoPlexBase<R>::addRowRational(const mpq_t* lhs, const mpq_t* rowValues, const int* rowIndices, 2863 const int rowSize, const mpq_t* rhs) 2864 { 2865 assert(_rationalLP != 0); 2866 2867 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 2868 return; 2869 2870 _rationalLP->addRow(lhs, rowValues, rowIndices, rowSize, rhs); 2871 _completeRangeTypesRational(); 2872 2873 int i = numRowsRational() - 1; 2874 2875 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2876 _addRowReal(R(lhsRational(i)), DSVectorBase<R>(_rationalLP->rowVector(i)), R(rhsRational(i))); 2877 2878 _invalidateSolution(); 2879 } 2880 2881 2882 2883 /// adds a set of rows (GMP only method) 2884 template <class R> 2885 void SoPlexBase<R>::addRowsRational(const mpq_t* lhs, const mpq_t* rowValues, const int* rowIndices, 2886 const int* rowStarts, const int* rowLengths, const int numRows, const int numValues, 2887 const mpq_t* rhs) 2888 { 2889 assert(_rationalLP != 0); 2890 2891 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 2892 return; 2893 2894 _rationalLP->addRows(lhs, rowValues, rowIndices, rowStarts, rowLengths, numRows, numValues, rhs); 2895 _completeRangeTypesRational(); 2896 2897 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2898 { 2899 LPRowSetBase<R> lprowset; 2900 2901 for(int i = numRowsRational() - numRows; i < numRowsRational(); i++) 2902 lprowset.add(R(lhsRational(i)), DSVectorBase<R>(_rationalLP->rowVector(i)), R(rhsRational(i))); 2903 2904 _addRowsReal(lprowset); 2905 } 2906 2907 _invalidateSolution(); 2908 } 2909 #endif 2910 2911 2912 2913 /// adds multiple rows 2914 template <class R> 2915 void SoPlexBase<R>::addRowsRational(const LPRowSetRational& lprowset) 2916 { 2917 assert(_rationalLP != 0); 2918 2919 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 2920 return; 2921 2922 _rationalLP->addRows(lprowset); 2923 _completeRangeTypesRational(); 2924 2925 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2926 _addRowsReal(lprowset); 2927 2928 _invalidateSolution(); 2929 } 2930 2931 2932 /// adds a single column 2933 template <class R> 2934 void SoPlexBase<R>::addColRational(const LPColRational& lpcol) 2935 { 2936 assert(_rationalLP != 0); 2937 2938 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 2939 return; 2940 2941 _rationalLP->addCol(lpcol); 2942 _completeRangeTypesRational(); 2943 2944 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2945 _addColReal(lpcol); 2946 2947 _invalidateSolution(); 2948 } 2949 2950 2951 2952 2953 2954 /// adds multiple columns 2955 template <class R> 2956 void SoPlexBase<R>::addColsRational(const LPColSetRational& lpcolset) 2957 { 2958 assert(_rationalLP != 0); 2959 2960 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 2961 return; 2962 2963 _rationalLP->addCols(lpcolset); 2964 _completeRangeTypesRational(); 2965 2966 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2967 _addColsReal(lpcolset); 2968 2969 _invalidateSolution(); 2970 } 2971 2972 2973 2974 /// replaces row \p i with \p lprow 2975 template <class R> 2976 void SoPlexBase<R>::changeRowRational(int i, const LPRowRational& lprow) 2977 { 2978 assert(_rationalLP != 0); 2979 2980 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 2981 return; 2982 2983 _rationalLP->changeRow(i, lprow); 2984 _rowTypes[i] = _rangeTypeRational(lprow.lhs(), lprow.rhs()); 2985 _completeRangeTypesRational(); 2986 2987 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 2988 _changeRowReal(i, lprow); 2989 2990 _invalidateSolution(); 2991 } 2992 2993 2994 2995 /// changes left-hand side vector for constraints to \p lhs 2996 template <class R> 2997 void SoPlexBase<R>::changeLhsRational(const VectorRational& lhs) 2998 { 2999 assert(_rationalLP != 0); 3000 3001 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3002 return; 3003 3004 _rationalLP->changeLhs(lhs); 3005 3006 for(int i = 0; i < numRowsRational(); i++) 3007 _rowTypes[i] = _rangeTypeRational(lhs[i], _rationalLP->rhs(i)); 3008 3009 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3010 _changeLhsReal(VectorBase<R>(lhs)); 3011 3012 _invalidateSolution(); 3013 } 3014 3015 3016 3017 /// changes left-hand side of row \p i to \p lhs 3018 template <class R> 3019 void SoPlexBase<R>::changeLhsRational(int i, const Rational& lhs) 3020 { 3021 assert(_rationalLP != 0); 3022 3023 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3024 return; 3025 3026 _rationalLP->changeLhs(i, lhs); 3027 _rowTypes[i] = _rangeTypeRational(lhs, _rationalLP->rhs(i)); 3028 3029 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3030 _changeLhsReal(i, R(lhs)); 3031 3032 _invalidateSolution(); 3033 } 3034 3035 3036 3037 #ifdef SOPLEX_WITH_GMP 3038 /// changes left-hand side of row \p i to \p lhs (GMP only method) 3039 template <class R> 3040 void SoPlexBase<R>::changeLhsRational(int i, const mpq_t* lhs) 3041 { 3042 assert(_rationalLP != 0); 3043 3044 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3045 return; 3046 3047 #ifndef SOPLEX_WITH_BOOST 3048 SPX_MSG_ERROR(std::cerr << "ERROR: rational solve without Boost not defined!" << std::endl;) 3049 #endif 3050 3051 _rationalLP->changeLhs(i, lhs); 3052 _rowTypes[i] = _rangeTypeRational(_rationalLP->lhs(i), _rationalLP->rhs(i)); 3053 3054 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3055 _changeLhsReal(i, R(lhsRational(i))); 3056 3057 _invalidateSolution(); 3058 } 3059 #endif 3060 3061 3062 3063 /// changes right-hand side vector to \p rhs 3064 template <class R> 3065 void SoPlexBase<R>::changeRhsRational(const VectorRational& rhs) 3066 { 3067 assert(_rationalLP != 0); 3068 3069 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3070 return; 3071 3072 _rationalLP->changeRhs(rhs); 3073 3074 for(int i = 0; i < numRowsRational(); i++) 3075 _rowTypes[i] = _rangeTypeRational(_rationalLP->lhs(i), rhs[i]); 3076 3077 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3078 _changeRhsReal(VectorBase<R>(rhs)); 3079 3080 _invalidateSolution(); 3081 } 3082 3083 3084 3085 #ifdef SOPLEX_WITH_GMP 3086 /// changes right-hand side vector to \p rhs (GMP only method) 3087 template <class R> 3088 void SoPlexBase<R>::changeRhsRational(const mpq_t* rhs, int rhsSize) 3089 { 3090 assert(_rationalLP != 0); 3091 3092 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3093 return; 3094 3095 #ifndef SOPLEX_WITH_BOOST 3096 SPX_MSG_ERROR(std::cerr << "ERROR: rational solve without Boost not defined!" << std::endl;) 3097 #endif 3098 3099 for(int i = 0; i < rhsSize; i++) 3100 { 3101 _rationalLP->changeRhs(i, Rational(rhs[i])); 3102 _rowTypes[i] = _rangeTypeRational(_rationalLP->lhs(i), _rationalLP->rhs(i)); 3103 } 3104 3105 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3106 _changeRhsReal(VectorBase<R>(rhsRational())); 3107 3108 _invalidateSolution(); 3109 } 3110 #endif 3111 3112 3113 3114 /// changes right-hand side of row \p i to \p rhs 3115 template <class R> 3116 void SoPlexBase<R>::changeRhsRational(int i, const Rational& rhs) 3117 { 3118 assert(_rationalLP != 0); 3119 3120 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3121 return; 3122 3123 _rationalLP->changeRhs(i, rhs); 3124 _rowTypes[i] = _rangeTypeRational(_rationalLP->lhs(i), rhs); 3125 3126 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3127 _changeRhsReal(i, R(rhs)); 3128 3129 _invalidateSolution(); 3130 } 3131 3132 3133 3134 /// changes left- and right-hand side vectors 3135 template <class R> 3136 void SoPlexBase<R>::changeRangeRational(const VectorRational& lhs, const VectorRational& rhs) 3137 { 3138 assert(_rationalLP != 0); 3139 3140 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3141 return; 3142 3143 _rationalLP->changeRange(lhs, rhs); 3144 3145 for(int i = 0; i < numRowsRational(); i++) 3146 _rowTypes[i] = _rangeTypeRational(lhs[i], rhs[i]); 3147 3148 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3149 _changeRangeReal(VectorBase<R>(lhs), VectorBase<R>(rhs)); 3150 3151 _invalidateSolution(); 3152 } 3153 3154 3155 3156 /// changes left- and right-hand side of row \p i 3157 template <class R> 3158 void SoPlexBase<R>::changeRangeRational(int i, const Rational& lhs, const Rational& rhs) 3159 { 3160 assert(_rationalLP != 0); 3161 3162 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3163 return; 3164 3165 _rationalLP->changeRange(i, lhs, rhs); 3166 _rowTypes[i] = _rangeTypeRational(lhs, rhs); 3167 3168 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3169 _changeRangeReal(i, R(lhs), R(rhs)); 3170 3171 _invalidateSolution(); 3172 } 3173 3174 3175 3176 #ifdef SOPLEX_WITH_GMP 3177 /// changes left-hand side of row \p i to \p lhs (GMP only method) 3178 template <class R> 3179 void SoPlexBase<R>::changeRangeRational(int i, const mpq_t* lhs, const mpq_t* rhs) 3180 { 3181 assert(_rationalLP != 0); 3182 3183 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3184 return; 3185 3186 #ifndef SOPLEX_WITH_BOOST 3187 SPX_MSG_ERROR(std::cerr << "ERROR: rational solve without Boost not defined!" << std::endl;) 3188 #endif 3189 _rationalLP->changeRange(i, lhs, rhs); 3190 _rowTypes[i] = _rangeTypeRational(_rationalLP->lhs(i), _rationalLP->rhs(i)); 3191 3192 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3193 _changeRangeReal(i, R(lhsRational(i)), R(rhsRational(i))); 3194 3195 _invalidateSolution(); 3196 } 3197 #endif 3198 3199 3200 3201 /// replaces column \p i with \p lpcol 3202 template <class R> 3203 void SoPlexBase<R>::changeColRational(int i, const LPColRational& lpcol) 3204 { 3205 assert(_rationalLP != 0); 3206 3207 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3208 return; 3209 3210 _rationalLP->changeCol(i, lpcol); 3211 _colTypes[i] = _rangeTypeRational(lpcol.lower(), lpcol.upper()); 3212 _completeRangeTypesRational(); 3213 3214 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3215 _changeColReal(i, lpcol); 3216 3217 _invalidateSolution(); 3218 } 3219 3220 3221 3222 /// changes vector of lower bounds to \p lower 3223 template <class R> 3224 void SoPlexBase<R>::changeLowerRational(const VectorRational& lower) 3225 { 3226 assert(_rationalLP != 0); 3227 3228 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3229 return; 3230 3231 _rationalLP->changeLower(lower); 3232 3233 for(int i = 0; i < numColsRational(); i++) 3234 _colTypes[i] = _rangeTypeRational(lower[i], _rationalLP->upper(i)); 3235 3236 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3237 _changeLowerReal(VectorBase<R>(lower)); 3238 3239 _invalidateSolution(); 3240 } 3241 3242 3243 3244 /// changes lower bound of column i to \p lower 3245 template <class R> 3246 void SoPlexBase<R>::changeLowerRational(int i, const Rational& lower) 3247 { 3248 assert(_rationalLP != 0); 3249 3250 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3251 return; 3252 3253 _rationalLP->changeLower(i, lower); 3254 _colTypes[i] = _rangeTypeRational(lower, _rationalLP->upper(i)); 3255 3256 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3257 _changeLowerReal(i, R(lower)); 3258 3259 _invalidateSolution(); 3260 } 3261 3262 3263 3264 #ifdef SOPLEX_WITH_GMP 3265 /// changes lower bound of column i to \p lower (GMP only method) 3266 template <class R> 3267 void SoPlexBase<R>::changeLowerRational(int i, const mpq_t* lower) 3268 { 3269 assert(_rationalLP != 0); 3270 3271 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3272 return; 3273 3274 #ifndef SOPLEX_WITH_BOOST 3275 SPX_MSG_ERROR(std::cerr << "ERROR: rational solve without Boost not defined!" << std::endl;) 3276 #endif 3277 _rationalLP->changeLower(i, lower); 3278 _colTypes[i] = _rangeTypeRational(_rationalLP->lower(i), _rationalLP->upper(i)); 3279 3280 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3281 _changeLowerReal(i, R(lowerRational(i))); 3282 3283 _invalidateSolution(); 3284 } 3285 #endif 3286 3287 3288 3289 /// changes vector of upper bounds to \p upper 3290 template <class R> 3291 void SoPlexBase<R>::changeUpperRational(const VectorRational& upper) 3292 { 3293 assert(_rationalLP != 0); 3294 3295 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3296 return; 3297 3298 _rationalLP->changeUpper(upper); 3299 3300 for(int i = 0; i < numColsRational(); i++) 3301 _colTypes[i] = _rangeTypeRational(_rationalLP->lower(i), upper[i]); 3302 3303 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3304 _changeUpperReal(VectorBase<R>(upper)); 3305 3306 _invalidateSolution(); 3307 } 3308 3309 3310 3311 3312 /// changes \p i 'th upper bound to \p upper 3313 template <class R> 3314 void SoPlexBase<R>::changeUpperRational(int i, const Rational& upper) 3315 { 3316 assert(_rationalLP != 0); 3317 3318 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3319 return; 3320 3321 _rationalLP->changeUpper(i, upper); 3322 _colTypes[i] = _rangeTypeRational(_rationalLP->lower(i), upper); 3323 3324 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3325 _changeUpperReal(i, R(upper)); 3326 3327 _invalidateSolution(); 3328 } 3329 3330 3331 3332 #ifdef SOPLEX_WITH_GMP 3333 /// changes upper bound of column i to \p upper (GMP only method) 3334 template <class R> 3335 void SoPlexBase<R>::changeUpperRational(int i, const mpq_t* upper) 3336 { 3337 assert(_rationalLP != 0); 3338 3339 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3340 return; 3341 3342 #ifndef SOPLEX_WITH_BOOST 3343 SPX_MSG_ERROR(std::cerr << "ERROR: rational solve without Boost not defined!" << std::endl;) 3344 #endif 3345 _rationalLP->changeUpper(i, upper); 3346 _colTypes[i] = _rangeTypeRational(_rationalLP->lower(i), _rationalLP->upper(i)); 3347 3348 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3349 _changeUpperReal(i, R(upperRational(i))); 3350 3351 _invalidateSolution(); 3352 } 3353 #endif 3354 3355 3356 3357 /// changes vectors of column bounds to \p lower and \p upper 3358 template <class R> 3359 void SoPlexBase<R>::changeBoundsRational(const VectorRational& lower, const VectorRational& upper) 3360 { 3361 assert(_rationalLP != 0); 3362 3363 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3364 return; 3365 3366 _rationalLP->changeBounds(lower, upper); 3367 3368 for(int i = 0; i < numColsRational(); i++) 3369 _colTypes[i] = _rangeTypeRational(lower[i], upper[i]); 3370 3371 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3372 _changeBoundsReal(VectorBase<R>(lower), VectorBase<R>(upper)); 3373 3374 _invalidateSolution(); 3375 } 3376 3377 3378 3379 /// changes bounds of column \p i to \p lower and \p upper 3380 template <class R> 3381 void SoPlexBase<R>::changeBoundsRational(int i, const Rational& lower, const Rational& upper) 3382 { 3383 assert(_rationalLP != 0); 3384 3385 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3386 return; 3387 3388 _rationalLP->changeBounds(i, lower, upper); 3389 _colTypes[i] = _rangeTypeRational(lower, upper); 3390 3391 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3392 _changeBoundsReal(i, R(lower), R(upper)); 3393 3394 _invalidateSolution(); 3395 } 3396 3397 3398 3399 #ifdef SOPLEX_WITH_GMP 3400 /// changes bounds of column \p i to \p lower and \p upper (GMP only method) 3401 template <class R> 3402 void SoPlexBase<R>::changeBoundsRational(int i, const mpq_t* lower, const mpq_t* upper) 3403 { 3404 assert(_rationalLP != 0); 3405 3406 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3407 return; 3408 3409 #ifndef SOPLEX_WITH_BOOST 3410 SPX_MSG_ERROR(std::cerr << "ERROR: rational solve without Boost not defined!" << std::endl;) 3411 #endif 3412 _rationalLP->changeBounds(i, lower, upper); 3413 _colTypes[i] = _rangeTypeRational(_rationalLP->lower(i), _rationalLP->upper(i)); 3414 3415 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3416 _changeBoundsReal(i, R(lowerRational(i)), R(upperRational(i))); 3417 3418 _invalidateSolution(); 3419 } 3420 #endif 3421 3422 3423 3424 /// changes objective function vector to \p obj 3425 template <class R> 3426 void SoPlexBase<R>::changeObjRational(const VectorRational& obj) 3427 { 3428 assert(_rationalLP != 0); 3429 3430 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3431 return; 3432 3433 _rationalLP->changeObj(obj); 3434 3435 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3436 _realLP->changeObj(VectorBase<R>(obj)); 3437 3438 _invalidateSolution(); 3439 } 3440 3441 3442 3443 /// changes objective coefficient of column i to \p obj 3444 template <class R> 3445 void SoPlexBase<R>::changeObjRational(int i, const Rational& obj) 3446 { 3447 assert(_rationalLP != 0); 3448 3449 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3450 return; 3451 3452 _rationalLP->changeObj(i, obj); 3453 3454 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3455 _realLP->changeObj(i, R(obj)); 3456 3457 _invalidateSolution(); 3458 } 3459 3460 3461 3462 #ifdef SOPLEX_WITH_GMP 3463 /// changes objective coefficient of column i to \p obj (GMP only method) 3464 template <class R> 3465 void SoPlexBase<R>::changeObjRational(int i, const mpq_t* obj) 3466 { 3467 assert(_rationalLP != 0); 3468 3469 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3470 return; 3471 3472 #ifndef SOPLEX_WITH_BOOST 3473 SPX_MSG_ERROR(std::cerr << "ERROR: rational solve without Boost not defined!" << std::endl;) 3474 #endif 3475 _rationalLP->changeObj(i, obj); 3476 3477 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3478 _realLP->changeObj(i, R(objRational(i))); 3479 3480 _invalidateSolution(); 3481 } 3482 #endif 3483 3484 3485 3486 /// changes matrix entry in row \p i and column \p j to \p val 3487 template <class R> 3488 void SoPlexBase<R>::changeElementRational(int i, int j, const Rational& val) 3489 { 3490 assert(_rationalLP != 0); 3491 3492 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3493 return; 3494 3495 _rationalLP->changeElement(i, j, val); 3496 3497 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3498 _changeElementReal(i, j, R(val)); 3499 3500 _invalidateSolution(); 3501 } 3502 3503 3504 #ifdef SOPLEX_WITH_GMP 3505 /// changes matrix entry in row \p i and column \p j to \p val (GMP only method) 3506 template <class R> 3507 void SoPlexBase<R>::changeElementRational(int i, int j, const mpq_t* val) 3508 { 3509 assert(_rationalLP != 0); 3510 3511 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3512 return; 3513 3514 #ifndef SOPLEX_WITH_BOOST 3515 SPX_MSG_ERROR(std::cerr << "ERROR: rational solve without Boost not defined!" << std::endl;) 3516 #endif 3517 _rationalLP->changeElement(i, j, val); 3518 3519 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3520 _changeElementReal(i, j, mpq_get_d(*val)); 3521 3522 _invalidateSolution(); 3523 } 3524 #endif 3525 3526 3527 /// removes row \p i 3528 template <class R> 3529 void SoPlexBase<R>::removeRowRational(int i) 3530 { 3531 assert(_rationalLP != 0); 3532 3533 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3534 return; 3535 3536 _rationalLP->removeRow(i); 3537 3538 // only swap elements if not the last one was removed 3539 if(i < _rationalLP->nRows()) 3540 { 3541 _rowTypes[i] = _rowTypes[_rationalLP->nRows()]; 3542 assert(_rowTypes[i] == _rangeTypeRational(lhsRational(i), rhsRational(i))); 3543 } 3544 3545 _rowTypes.reSize(_rationalLP->nRows()); 3546 3547 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3548 _removeRowReal(i); 3549 3550 _invalidateSolution(); 3551 } 3552 3553 3554 3555 /// removes all rows with an index \p i such that \p perm[i] < 0; upon completion, \p perm[i] >= 0 indicates the new 3556 /// index where row \p i has been moved to; note that \p perm must point to an array of size at least 3557 /// #numRowsRational() 3558 template <class R> 3559 void SoPlexBase<R>::removeRowsRational(int perm[]) 3560 { 3561 assert(_rationalLP != 0); 3562 3563 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3564 return; 3565 3566 const int oldsize = numRowsRational(); 3567 _rationalLP->removeRows(perm); 3568 3569 for(int i = 0; i < oldsize; i++) 3570 { 3571 if(perm[i] >= 0) 3572 _rowTypes[perm[i]] = _rowTypes[i]; 3573 } 3574 3575 _rowTypes.reSize(_rationalLP->nRows()); 3576 3577 for(int i = 0; i < numRowsRational(); i++) 3578 { 3579 assert(_rowTypes[i] == _rangeTypeRational(lhsRational(i), rhsRational(i))); 3580 } 3581 3582 3583 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3584 _removeRowsReal(perm); 3585 3586 _invalidateSolution(); 3587 } 3588 3589 3590 3591 /// remove all rows with indices in array \p idx of size \p n; an array \p perm of size #numRowsRational() may be 3592 /// passed as buffer memory 3593 template <class R> 3594 void SoPlexBase<R>::removeRowsRational(int idx[], int n, int perm[]) 3595 { 3596 if(perm == 0) 3597 { 3598 DataArray< int > p(numRowsRational()); 3599 _idxToPerm(idx, n, p.get_ptr(), numRowsRational()); 3600 SoPlexBase<R>::removeRowsRational(p.get_ptr()); 3601 } 3602 else 3603 { 3604 _idxToPerm(idx, n, perm, numRowsRational()); 3605 SoPlexBase<R>::removeRowsRational(perm); 3606 } 3607 } 3608 3609 3610 3611 /// removes rows \p start to \p end including both; an array \p perm of size #numRowsRational() may be passed as 3612 /// buffer memory 3613 template <class R> 3614 void SoPlexBase<R>::removeRowRangeRational(int start, int end, int perm[]) 3615 { 3616 if(perm == 0) 3617 { 3618 DataArray< int > p(numRowsRational()); 3619 _rangeToPerm(start, end, p.get_ptr(), numRowsRational()); 3620 SoPlexBase<R>::removeRowsRational(p.get_ptr()); 3621 } 3622 else 3623 { 3624 _rangeToPerm(start, end, perm, numRowsRational()); 3625 SoPlexBase<R>::removeRowsRational(perm); 3626 } 3627 } 3628 3629 3630 3631 /// removes column i 3632 template <class R> 3633 void SoPlexBase<R>::removeColRational(int i) 3634 { 3635 assert(_rationalLP != 0); 3636 3637 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3638 return; 3639 3640 _rationalLP->removeCol(i); 3641 3642 // only swap elements if not the last one was removed 3643 if(i < _rationalLP->nCols()) 3644 { 3645 _colTypes[i] = _colTypes[_rationalLP->nCols()]; 3646 assert(_colTypes[i] == _rangeTypeRational(lowerRational(i), upperRational(i))); 3647 } 3648 3649 _colTypes.reSize(_rationalLP->nCols()); 3650 3651 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3652 _removeColReal(i); 3653 3654 _invalidateSolution(); 3655 } 3656 3657 3658 3659 /// removes all columns with an index \p i such that \p perm[i] < 0; upon completion, \p perm[i] >= 0 indicates the 3660 /// new index where column \p i has been moved to; note that \p perm must point to an array of size at least 3661 /// #numColsRational() 3662 template <class R> 3663 void SoPlexBase<R>::removeColsRational(int perm[]) 3664 { 3665 assert(_rationalLP != 0); 3666 3667 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 3668 return; 3669 3670 const int oldsize = numColsRational(); 3671 _rationalLP->removeCols(perm); 3672 3673 for(int i = 0; i < oldsize; i++) 3674 { 3675 if(perm[i] >= 0) 3676 _colTypes[perm[i]] = _colTypes[i]; 3677 } 3678 3679 _colTypes.reSize(_rationalLP->nCols()); 3680 3681 for(int i = 0; i < numColsRational(); i++) 3682 { 3683 assert(_colTypes[i] == _rangeTypeRational(lowerRational(i), upperRational(i))); 3684 } 3685 3686 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3687 _removeColsReal(perm); 3688 3689 _invalidateSolution(); 3690 } 3691 3692 3693 3694 /// remove all columns with indices in array \p idx of size \p n; an array \p perm of size #numColsRational() may be 3695 /// passed as buffer memory 3696 template <class R> 3697 void SoPlexBase<R>::removeColsRational(int idx[], int n, int perm[]) 3698 { 3699 if(perm == 0) 3700 { 3701 DataArray< int > p(numColsRational()); 3702 _idxToPerm(idx, n, p.get_ptr(), numColsRational()); 3703 SoPlexBase<R>::removeColsRational(p.get_ptr()); 3704 } 3705 else 3706 { 3707 _idxToPerm(idx, n, perm, numColsRational()); 3708 SoPlexBase<R>::removeColsRational(perm); 3709 } 3710 } 3711 3712 3713 3714 /// removes columns \p start to \p end including both; an array \p perm of size #numColsRational() may be passed as 3715 /// buffer memory 3716 template <class R> 3717 void SoPlexBase<R>::removeColRangeRational(int start, int end, int perm[]) 3718 { 3719 if(perm == 0) 3720 { 3721 DataArray< int > p(numColsRational()); 3722 _rangeToPerm(start, end, p.get_ptr(), numColsRational()); 3723 SoPlexBase<R>::removeColsRational(p.get_ptr()); 3724 } 3725 else 3726 { 3727 _rangeToPerm(start, end, perm, numColsRational()); 3728 SoPlexBase<R>::removeColsRational(perm); 3729 } 3730 } 3731 3732 3733 3734 /// clears the LP 3735 template <class R> 3736 void SoPlexBase<R>::clearLPRational() 3737 { 3738 assert(_rationalLP != 0); 3739 3740 _rationalLP->clear(); 3741 _rationalLUSolver.clear(); 3742 _rowTypes.clear(); 3743 _colTypes.clear(); 3744 3745 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 3746 { 3747 _realLP->clear(); 3748 _hasBasis = false; 3749 } 3750 3751 _invalidateSolution(); 3752 } 3753 3754 3755 3756 /// synchronizes rational LP with R LP, i.e., copies R LP to rational LP, if sync mode is manual 3757 template <class R> 3758 void SoPlexBase<R>::syncLPRational() 3759 { 3760 assert(_isConsistent()); 3761 3762 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_MANUAL) 3763 _syncLPRational(); 3764 } 3765 3766 /// returns the current solver status 3767 template <class R> 3768 typename SPxSolverBase<R>::Status SoPlexBase<R>::status() const 3769 { 3770 return _status; 3771 } 3772 3773 /// returns the current basis status 3774 template <class R> 3775 typename SPxBasisBase<R>::SPxStatus SoPlexBase<R>::basisStatus() const 3776 { 3777 if(!hasBasis()) 3778 return SPxBasisBase<R>::NO_PROBLEM; 3779 else 3780 return _solver.getBasisStatus(); 3781 } 3782 3783 3784 /// returns the objective value if a primal or dual solution is available 3785 template <class R> 3786 R SoPlexBase<R>::objValueReal() 3787 { 3788 assert(OBJSENSE_MAXIMIZE == 1); 3789 assert(OBJSENSE_MINIMIZE == -1); 3790 3791 if(status() == SPxSolverBase<R>::UNBOUNDED) 3792 return realParam(SoPlexBase<R>::INFTY) * intParam(SoPlexBase<R>::OBJSENSE); 3793 else if(status() == SPxSolverBase<R>::INFEASIBLE) 3794 return -realParam(SoPlexBase<R>::INFTY) * intParam(SoPlexBase<R>::OBJSENSE); 3795 else if(hasSol()) 3796 { 3797 _syncRealSolution(); 3798 return _solReal._objVal; 3799 } 3800 else 3801 return 0.0; 3802 } 3803 3804 3805 /// returns the objective value if a primal or dual solution is available 3806 template <class R> 3807 Rational SoPlexBase<R>::objValueRational() 3808 { 3809 assert(OBJSENSE_MAXIMIZE == 1); 3810 assert(OBJSENSE_MINIMIZE == -1); 3811 3812 if(this->status() == SPxSolverBase<R>::UNBOUNDED) 3813 { 3814 if(intParam(SoPlexBase<R>::OBJSENSE) == OBJSENSE_MAXIMIZE) 3815 return _rationalPosInfty; 3816 else 3817 return _rationalNegInfty; 3818 } 3819 else if(this->status() == SPxSolverBase<R>::INFEASIBLE) 3820 { 3821 if(intParam(SoPlexBase<R>::OBJSENSE) == OBJSENSE_MAXIMIZE) 3822 return _rationalNegInfty; 3823 else 3824 return _rationalPosInfty; 3825 } 3826 else if(hasSol()) 3827 { 3828 _syncRationalSolution(); 3829 return _solRational._objVal; 3830 } 3831 else 3832 return _rationalZero; 3833 } 3834 3835 /// Is stored primal solution feasible? 3836 template <class R> 3837 bool SoPlexBase<R>::isPrimalFeasible() const 3838 { 3839 return (_hasSolReal && _solReal.isPrimalFeasible()) || (_hasSolRational 3840 && _solRational.isPrimalFeasible()); 3841 } 3842 3843 /// is a solution available (not necessarily feasible)? 3844 template <class R> 3845 bool SoPlexBase<R>::hasSol() const 3846 { 3847 return _hasSolReal || _hasSolRational; 3848 } 3849 3850 /// is a primal unbounded ray available? 3851 template <class R> 3852 bool SoPlexBase<R>::hasPrimalRay() const 3853 { 3854 return (_hasSolReal && _solReal.hasPrimalRay()) || (_hasSolRational && _solRational.hasPrimalRay()); 3855 } 3856 3857 3858 /// is stored dual solution feasible? 3859 template <class R> 3860 bool SoPlexBase<R>::isDualFeasible() const 3861 { 3862 return (_hasSolReal && _solReal.isDualFeasible()) || (_hasSolRational 3863 && _solRational.isDualFeasible()); 3864 3865 } 3866 3867 /// is Farkas proof of infeasibility available? 3868 template <class R> 3869 bool SoPlexBase<R>::hasDualFarkas() const 3870 { 3871 return (_hasSolReal && _solReal.hasDualFarkas()) || (_hasSolRational 3872 && _solRational.hasDualFarkas()); 3873 } 3874 3875 /// gets the vector of slack values if available; returns true on success 3876 template <class R> 3877 bool SoPlexBase<R>::getSlacksReal(VectorBase<R>& vector) 3878 { 3879 if(hasSol() && vector.dim() >= numRows()) 3880 { 3881 _syncRealSolution(); 3882 _solReal.getSlacks(vector); 3883 return true; 3884 } 3885 else 3886 return false; 3887 } 3888 3889 template <class R> 3890 bool SoPlexBase<R>::getSlacksReal(R* p_vector, int dim) 3891 { 3892 if(hasSol() && dim >= numRows()) 3893 { 3894 _syncRealSolution(); 3895 3896 auto& slacks = _solReal._slacks; 3897 std::copy(slacks.begin(), slacks.end(), p_vector); 3898 3899 return true; 3900 } 3901 else 3902 return false; 3903 } 3904 3905 3906 /// gets the primal solution vector if available; returns true on success 3907 template <class R> 3908 bool SoPlexBase<R>::getPrimalRational(VectorBase<Rational>& vector) 3909 { 3910 if(_rationalLP != 0 && hasSol() && vector.dim() >= numColsRational()) 3911 { 3912 _syncRationalSolution(); 3913 _solRational.getPrimalSol(vector); 3914 return true; 3915 } 3916 else 3917 return false; 3918 } 3919 3920 3921 /// gets the vector of slack values if available; returns true on success 3922 template <class R> 3923 bool SoPlexBase<R>::getSlacksRational(VectorRational& vector) 3924 { 3925 if(_rationalLP != 0 && hasSol() && vector.dim() >= numRowsRational()) 3926 { 3927 _syncRationalSolution(); 3928 _solRational.getSlacks(vector); 3929 return true; 3930 } 3931 else 3932 return false; 3933 } 3934 3935 template <class R> 3936 bool SoPlexBase<R>::getPrimalRayRational(VectorBase<Rational>& vector) 3937 { 3938 if(_rationalLP != 0 && hasPrimalRay() && vector.dim() >= numColsRational()) 3939 { 3940 _syncRationalSolution(); 3941 _solRational.getPrimalRaySol(vector); 3942 return true; 3943 } 3944 else 3945 return false; 3946 } 3947 3948 3949 3950 /// gets the dual solution vector if available; returns true on success 3951 template <class R> 3952 bool SoPlexBase<R>::getDualRational(VectorBase<Rational>& vector) 3953 { 3954 if(_rationalLP != 0 && hasSol() && vector.dim() >= numRowsRational()) 3955 { 3956 _syncRationalSolution(); 3957 _solRational.getDualSol(vector); 3958 return true; 3959 } 3960 else 3961 return false; 3962 } 3963 3964 3965 3966 /// gets the vector of reduced cost values if available; returns true on success 3967 template <class R> 3968 bool SoPlexBase<R>::getRedCostRational(VectorRational& vector) 3969 { 3970 if(_rationalLP != 0 && hasSol() && vector.dim() >= numColsRational()) 3971 { 3972 _syncRationalSolution(); 3973 _solRational.getRedCostSol(vector); 3974 return true; 3975 } 3976 else 3977 return false; 3978 } 3979 3980 /// gets the Farkas proof if LP is infeasible; returns true on success 3981 template <class R> 3982 bool SoPlexBase<R>::getDualFarkasRational(VectorBase<Rational>& vector) 3983 { 3984 if(_rationalLP != 0 && hasDualFarkas() && vector.dim() >= numRowsRational()) 3985 { 3986 _syncRationalSolution(); 3987 _solRational.getDualFarkasSol(vector); 3988 return true; 3989 } 3990 else 3991 return false; 3992 } 3993 3994 3995 3996 /// gets violation of bounds; returns true on success 3997 template <class R> 3998 bool SoPlexBase<R>::getBoundViolationRational(Rational& maxviol, Rational& sumviol) 3999 { 4000 if(!isPrimalFeasible()) 4001 return false; 4002 4003 // if we have to synchronize, we do not measure time, because this would affect the solving statistics 4004 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 4005 _syncLPRational(false); 4006 4007 _syncRationalSolution(); 4008 VectorRational& primal = _solRational._primal; 4009 assert(primal.dim() == numColsRational()); 4010 4011 maxviol = 0; 4012 sumviol = 0; 4013 4014 for(int i = numColsRational() - 1; i >= 0; i--) 4015 { 4016 Rational viol = lowerRational(i) - primal[i]; 4017 4018 if(viol > 0) 4019 { 4020 sumviol += viol; 4021 4022 if(viol > maxviol) 4023 { 4024 maxviol = viol; 4025 SPxOut::debug(this, "increased bound violation for column {}: {} lower: {}, primal {}\n", i, 4026 viol.str(), lowerRational(i).str(), primal[i].str()); 4027 } 4028 } 4029 4030 viol = primal[i] - upperRational(i); 4031 4032 if(viol > 0) 4033 { 4034 sumviol += viol; 4035 4036 if(viol > maxviol) 4037 { 4038 maxviol = viol; 4039 SPxOut::debug(this, "increased bound violation for column {}: {} upper: {}, primal {}\n", i, 4040 viol.str(), upperRational(i).str(), primal[i].str()); 4041 } 4042 } 4043 } 4044 4045 return true; 4046 } 4047 4048 4049 4050 /// gets violation of constraints; returns true on success 4051 template <class R> 4052 bool SoPlexBase<R>::getRowViolationRational(Rational& maxviol, Rational& sumviol) 4053 { 4054 if(!isPrimalFeasible()) 4055 return false; 4056 4057 // if we have to synchronize, we do not measure time, because this would affect the solving statistics 4058 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 4059 _syncLPRational(false); 4060 4061 _syncRationalSolution(); 4062 VectorRational& primal = _solRational._primal; 4063 assert(primal.dim() == numColsRational()); 4064 4065 VectorRational activity(numRowsRational()); 4066 _rationalLP->computePrimalActivity(primal, activity); 4067 maxviol = 0; 4068 sumviol = 0; 4069 4070 for(int i = numRowsRational() - 1; i >= 0; i--) 4071 { 4072 Rational viol = lhsRational(i) - activity[i]; 4073 4074 if(viol > 0) 4075 { 4076 sumviol += viol; 4077 4078 if(viol > maxviol) 4079 { 4080 maxviol = viol; 4081 SPxOut::debug(this, "increased constraint violation for row {}: {} lhs: {}, activity: {}\n", i, 4082 viol.str(), lhsRational(i).str(), activity[i].str()); 4083 } 4084 } 4085 4086 viol = activity[i] - rhsRational(i); 4087 4088 if(viol > 0) 4089 { 4090 sumviol += viol; 4091 4092 if(viol > maxviol) 4093 { 4094 maxviol = viol; 4095 SPxOut::debug(this, "increased constraint violation for row {}: {} rhs: {}, activity: {}\n", i, 4096 viol.str(), rhsRational(i).str(), activity[i].str()); 4097 } 4098 } 4099 } 4100 4101 return true; 4102 } 4103 4104 4105 4106 /// gets violation of reduced costs; returns true on success 4107 template <class R> 4108 bool SoPlexBase<R>::getRedCostViolationRational(Rational& maxviol, Rational& sumviol) 4109 { 4110 if(!isPrimalFeasible() || !isDualFeasible()) 4111 return false; 4112 4113 // if we have to synchronize, we do not measure time, because this would affect the solving statistics 4114 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 4115 _syncLPRational(false); 4116 4117 _syncRationalSolution(); 4118 VectorRational& redcost = _solRational._redCost; 4119 assert(redcost.dim() == numColsRational()); 4120 4121 maxviol = 0; 4122 sumviol = 0; 4123 4124 for(int c = numCols() - 1; c >= 0; c--) 4125 { 4126 assert(!_hasBasis || basisColStatus(c) != SPxSolverBase<R>::UNDEFINED); 4127 4128 if(_colTypes[c] == RANGETYPE_FIXED) 4129 { 4130 assert(lowerRational(c) == upperRational(c)); 4131 continue; 4132 } 4133 4134 // since the rational solution may be translated from a floating-point solve, feasibility and consistency of the 4135 // basis must not necessarily hold exactly, even within tolerances; hence the following assertions are relaxed by 4136 // a factor of two 4137 assert(!_hasBasis || basisColStatus(c) != SPxSolverBase<R>::ON_LOWER 4138 || spxAbs(Rational(_solRational._primal[c] - lowerRational(c))) <= 2 * _rationalFeastol); 4139 assert(!_hasBasis || basisColStatus(c) != SPxSolverBase<R>::ON_UPPER 4140 || spxAbs(Rational(_solRational._primal[c] - upperRational(c))) <= 2 * _rationalFeastol); 4141 assert(!_hasBasis || basisColStatus(c) != SPxSolverBase<R>::FIXED 4142 || spxAbs(Rational(_solRational._primal[c] - lowerRational(c))) <= 2 * _rationalFeastol); 4143 assert(!_hasBasis || basisColStatus(c) != SPxSolverBase<R>::FIXED 4144 || spxAbs(Rational(_solRational._primal[c] - upperRational(c))) <= 2 * _rationalFeastol); 4145 4146 if(intParam(SoPlexBase<R>::OBJSENSE) == OBJSENSE_MINIMIZE) 4147 { 4148 if(_solRational._primal[c] != upperRational(c) && redcost[c] < 0) 4149 { 4150 sumviol += -redcost[c]; 4151 4152 if(redcost[c] < -maxviol) 4153 { 4154 SPxOut::debug(this, "increased reduced cost violation for column {} not on upper bound: {}\n", c, 4155 (static_cast<Rational>(-redcost[c])).str()); 4156 maxviol = -redcost[c]; 4157 } 4158 } 4159 4160 if(_solRational._primal[c] != lowerRational(c) && redcost[c] > 0) 4161 { 4162 sumviol += redcost[c]; 4163 4164 if(redcost[c] > maxviol) 4165 { 4166 SPxOut::debug(this, "increased reduced cost violation for column {} not on lower bound: {}\n", c, 4167 (redcost[c]).str()); 4168 maxviol = redcost[c]; 4169 } 4170 } 4171 } 4172 else 4173 { 4174 if(_solRational._primal[c] != upperRational(c) && redcost[c] > 0) 4175 { 4176 sumviol += redcost[c]; 4177 4178 if(redcost[c] > maxviol) 4179 { 4180 SPxOut::debug(this, "increased reduced cost violation for column {} not on upper bound: {}\n", c, 4181 (redcost[c]).str()); 4182 maxviol = redcost[c]; 4183 } 4184 } 4185 4186 if(_solRational._primal[c] != lowerRational(c) && redcost[c] < 0) 4187 { 4188 sumviol += -redcost[c]; 4189 4190 if(redcost[c] < -maxviol) 4191 { 4192 SPxOut::debug(this, "increased reduced cost violation for column {} not on lower bound: {}\n", c, 4193 (static_cast<Rational>(-redcost[c])).str()); 4194 maxviol = -redcost[c]; 4195 } 4196 } 4197 } 4198 } 4199 4200 return true; 4201 } 4202 4203 4204 4205 /// gets violation of dual multipliers; returns true on success 4206 template <class R> 4207 bool SoPlexBase<R>::getDualViolationRational(Rational& maxviol, Rational& sumviol) 4208 { 4209 if(!isDualFeasible() || !isPrimalFeasible()) 4210 return false; 4211 4212 // if we have to synchronize, we do not measure time, because this would affect the solving statistics 4213 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 4214 _syncLPRational(false); 4215 4216 _syncRationalSolution(); 4217 VectorRational& dual = _solRational._dual; 4218 assert(dual.dim() == numRowsRational()); 4219 4220 maxviol = 0; 4221 sumviol = 0; 4222 4223 for(int r = numRows() - 1; r >= 0; r--) 4224 { 4225 assert(!_hasBasis || basisRowStatus(r) != SPxSolverBase<R>::UNDEFINED); 4226 4227 if(_rowTypes[r] == RANGETYPE_FIXED) 4228 { 4229 assert(lhsRational(r) == rhsRational(r)); 4230 continue; 4231 } 4232 4233 // since the rational solution may be translated from a floating-point solve, feasibility and consistency of the 4234 // basis must not necessarily hold exactly, even within tolerances; hence the following assertions are relaxed by 4235 // a factor of two 4236 assert(!_hasBasis || basisRowStatus(r) != SPxSolverBase<R>::ON_LOWER 4237 || spxAbs(Rational(_solRational._slacks[r] - lhsRational(r))) <= 2 * _rationalFeastol); 4238 assert(!_hasBasis || basisRowStatus(r) != SPxSolverBase<R>::ON_UPPER 4239 || spxAbs(Rational(_solRational._slacks[r] - rhsRational(r))) <= 2 * _rationalFeastol); 4240 assert(!_hasBasis || basisRowStatus(r) != SPxSolverBase<R>::FIXED 4241 || spxAbs(Rational(_solRational._slacks[r] - lhsRational(r))) <= 2 * _rationalFeastol); 4242 assert(!_hasBasis || basisRowStatus(r) != SPxSolverBase<R>::FIXED 4243 || spxAbs(Rational(_solRational._slacks[r] - rhsRational(r))) <= 2 * _rationalFeastol); 4244 4245 if(intParam(SoPlexBase<R>::OBJSENSE) == OBJSENSE_MINIMIZE) 4246 { 4247 if(_solRational._slacks[r] < rhsRational(r) - _rationalFeastol && dual[r] < 0) 4248 { 4249 sumviol += -dual[r]; 4250 4251 if(dual[r] < -maxviol) 4252 { 4253 SPxOut::debug(this, 4254 "increased dual violation for row {} not on upper bound: {} (slack = {}, status = {}, lhs = {}, rhs = {})\n", 4255 r, (static_cast<Rational>(-dual[r])).str(), _solRational._slacks[r].str(), basisRowStatus(r), 4256 lhsRational(r).str(), 4257 rhsRational(r).str()); 4258 maxviol = -dual[r]; 4259 } 4260 } 4261 4262 if(_solRational._slacks[r] > lhsRational(r) + _rationalFeastol && dual[r] > 0) 4263 { 4264 sumviol += dual[r]; 4265 4266 if(dual[r] > maxviol) 4267 { 4268 SPxOut::debug(this, 4269 "increased dual violation for row {} not on lower bound: {} (slack = {}, status = {}, lhs = {}, rhs = {})\n", 4270 r, dual[r].str(), _solRational._slacks[r].str(), basisRowStatus(r), lhsRational(r).str(), 4271 rhsRational(r)); 4272 maxviol = dual[r]; 4273 } 4274 } 4275 } 4276 else 4277 { 4278 if(_solRational._slacks[r] < rhsRational(r) - _rationalFeastol && dual[r] > 0) 4279 { 4280 sumviol += dual[r]; 4281 4282 if(dual[r] > maxviol) 4283 { 4284 SPxOut::debug(this, 4285 "increased dual violation for row {} not on upper bound: {} (slack = {}, status = {}, lhs = {}, rhs = {})\n", 4286 r, dual[r].str(), _solRational._slacks[r].str(), basisRowStatus(r), lhsRational(r).str(), 4287 rhsRational(r)); 4288 maxviol = dual[r]; 4289 } 4290 } 4291 4292 if(_solRational._slacks[r] > lhsRational(r) + _rationalFeastol && dual[r] < 0) 4293 { 4294 sumviol += -dual[r]; 4295 4296 if(dual[r] < -maxviol) 4297 { 4298 SPxOut::debug(this, 4299 "increased dual violation for row {} not on lower bound: {} (slack = {}, status = {}, lhs = {}, rhs = {})\n", 4300 r, (static_cast<Rational>(-dual[r])).str(), _solRational._slacks[r].str(), basisRowStatus(r), 4301 lhsRational(r).str(), 4302 rhsRational(r)); 4303 maxviol = -dual[r]; 4304 } 4305 } 4306 } 4307 } 4308 4309 return true; 4310 } 4311 4312 4313 /// get size of primal solution 4314 template <class R> 4315 int SoPlexBase<R>::totalSizePrimalRational(const int base) 4316 { 4317 if(hasSol() || hasPrimalRay()) 4318 { 4319 _syncRationalSolution(); 4320 return _solRational.totalSizePrimal(base); 4321 } 4322 else 4323 return 0; 4324 } 4325 4326 4327 4328 /// get size of dual solution 4329 template <class R> 4330 int SoPlexBase<R>::totalSizeDualRational(const int base) 4331 { 4332 if(hasSol() || hasDualFarkas()) 4333 { 4334 _syncRationalSolution(); 4335 return _solRational.totalSizeDual(base); 4336 } 4337 else 4338 return 0; 4339 } 4340 4341 4342 4343 /// get size of least common multiple of denominators in primal solution 4344 template <class R> 4345 int SoPlexBase<R>::dlcmSizePrimalRational(const int base) 4346 { 4347 if(hasSol() || hasPrimalRay()) 4348 { 4349 _syncRationalSolution(); 4350 return _solRational.dlcmSizePrimal(base); 4351 } 4352 else 4353 return 0; 4354 } 4355 4356 4357 4358 /// get size of least common multiple of denominators in dual solution 4359 template <class R> 4360 int SoPlexBase<R>::dlcmSizeDualRational(const int base) 4361 { 4362 if(hasSol() || hasDualFarkas()) 4363 { 4364 _syncRationalSolution(); 4365 return _solRational.dlcmSizeDual(base); 4366 } 4367 else 4368 return 0; 4369 } 4370 4371 4372 4373 /// get size of largest denominator in primal solution 4374 template <class R> 4375 int SoPlexBase<R>::dmaxSizePrimalRational(const int base) 4376 { 4377 if(hasSol() || hasPrimalRay()) 4378 { 4379 _syncRationalSolution(); 4380 return _solRational.dmaxSizePrimal(base); 4381 } 4382 else 4383 return 0; 4384 } 4385 4386 4387 4388 /// get size of largest denominator in dual solution 4389 template <class R> 4390 int SoPlexBase<R>::dmaxSizeDualRational(const int base) 4391 { 4392 if(hasSol() || hasDualFarkas()) 4393 { 4394 _syncRationalSolution(); 4395 return _solRational.dmaxSizeDual(base); 4396 } 4397 else 4398 return 0; 4399 } 4400 4401 /// is an advanced starting basis available? 4402 template <class R> 4403 bool SoPlexBase<R>::hasBasis() const 4404 { 4405 return _hasBasis; 4406 } 4407 4408 4409 4410 /// returns basis status for a single row 4411 template <class R> 4412 typename SPxSolverBase<R>::VarStatus SoPlexBase<R>::basisRowStatus(int row) const 4413 { 4414 assert(row >= 0); 4415 assert(row < numRows()); 4416 4417 // if no basis is available, return slack basis; if index is out of range, return basic status as for a newly 4418 // added row 4419 if(!hasBasis() || row < 0 || row >= numRows()) 4420 return SPxSolverBase<R>::BASIC; 4421 // if the real LP is loaded, ask solver 4422 else if(_isRealLPLoaded) 4423 { 4424 return _solver.getBasisRowStatus(row); 4425 } 4426 // if the real LP is not loaded, the basis is stored in the basis arrays of this class 4427 else 4428 { 4429 assert(row < _basisStatusRows.size()); 4430 return _basisStatusRows[row]; 4431 } 4432 } 4433 4434 4435 4436 /// returns basis status for a single column 4437 template <class R> 4438 typename SPxSolverBase<R>::VarStatus SoPlexBase<R>::basisColStatus(int col) const 4439 { 4440 assert(col >= 0); 4441 assert(col < numCols()); 4442 4443 // if index is out of range, return nonbasic status as for a newly added unbounded column 4444 if(col < 0 || col >= numCols()) 4445 { 4446 return SPxSolverBase<R>::ZERO; 4447 } 4448 // if no basis is available, return slack basis 4449 else if(!hasBasis()) 4450 { 4451 if(lowerReal(col) > -realParam(SoPlexBase<R>::INFTY)) 4452 return SPxSolverBase<R>::ON_LOWER; 4453 else if(upperReal(col) < realParam(SoPlexBase<R>::INFTY)) 4454 return SPxSolverBase<R>::ON_UPPER; 4455 else 4456 return SPxSolverBase<R>::ZERO; 4457 } 4458 // if the real LP is loaded, ask solver 4459 else if(_isRealLPLoaded) 4460 { 4461 return _solver.getBasisColStatus(col); 4462 } 4463 // if the real LP is not loaded, the basis is stored in the basis arrays of this class 4464 else 4465 { 4466 assert(col < _basisStatusCols.size()); 4467 return _basisStatusCols[col]; 4468 } 4469 } 4470 4471 4472 4473 /// gets current basis 4474 template <class R> 4475 void SoPlexBase<R>::getBasis(typename SPxSolverBase<R>::VarStatus rows[], 4476 typename SPxSolverBase<R>::VarStatus cols[]) const 4477 { 4478 // if no basis is available, return slack basis 4479 if(!hasBasis()) 4480 { 4481 for(int i = numRows() - 1; i >= 0; i--) 4482 rows[i] = SPxSolverBase<R>::BASIC; 4483 4484 for(int i = numCols() - 1; i >= 0; i--) 4485 { 4486 if(lowerReal(i) > -realParam(SoPlexBase<R>::INFTY)) 4487 cols[i] = SPxSolverBase<R>::ON_LOWER; 4488 else if(upperReal(i) < realParam(SoPlexBase<R>::INFTY)) 4489 cols[i] = SPxSolverBase<R>::ON_UPPER; 4490 else 4491 cols[i] = SPxSolverBase<R>::ZERO; 4492 } 4493 } 4494 // if the real LP is loaded, ask solver 4495 else if(_isRealLPLoaded) 4496 { 4497 (void)_solver.getBasis(rows, cols); 4498 } 4499 // if the real LP is not loaded, the basis is stored in the basis arrays of this class 4500 else 4501 { 4502 assert(numRows() == _basisStatusRows.size()); 4503 assert(numCols() == _basisStatusCols.size()); 4504 4505 for(int i = numRows() - 1; i >= 0; i--) 4506 rows[i] = _basisStatusRows[i]; 4507 4508 for(int i = numCols() - 1; i >= 0; i--) 4509 cols[i] = _basisStatusCols[i]; 4510 } 4511 } 4512 4513 4514 4515 /// returns the indices of the basic columns and rows; basic column n gives value n, basic row m gives value -1-m 4516 /// note: the order of the indices might not coincide with the actual order when using ROW representation 4517 template <class R> 4518 void SoPlexBase<R>::getBasisInd(int* bind) const 4519 { 4520 // if no basis is available, return slack basis 4521 if(!hasBasis()) 4522 { 4523 for(int i = 0; i < numRows(); ++i) 4524 bind[i] = -1 - i; 4525 } 4526 // if the real LP is not loaded, the basis is stored in the basis arrays of this class 4527 else if(!_isRealLPLoaded) 4528 { 4529 int k = 0; 4530 4531 assert(numRows() == _basisStatusRows.size()); 4532 assert(numCols() == _basisStatusCols.size()); 4533 4534 for(int i = 0; i < numRows(); ++i) 4535 { 4536 if(_basisStatusRows[i] == SPxSolverBase<R>::BASIC) 4537 { 4538 bind[k] = -1 - i; 4539 k++; 4540 } 4541 } 4542 4543 for(int j = 0; j < numCols(); ++j) 4544 { 4545 if(_basisStatusCols[j] == SPxSolverBase<R>::BASIC) 4546 { 4547 bind[k] = j; 4548 k++; 4549 } 4550 } 4551 4552 assert(k == numRows()); 4553 } 4554 // if the real LP is loaded, the basis is stored in the solver and we need to distinguish between column and row 4555 // representation; ask the solver itself which representation it has, since the REPRESENTATION parameter of this 4556 // class might be set to automatic 4557 else if(_solver.rep() == SPxSolverBase<R>::COLUMN) 4558 { 4559 for(int i = 0; i < numRows(); ++i) 4560 { 4561 SPxId id = _solver.basis().baseId(i); 4562 bind[i] = (id.isSPxColId() ? _solver.number(id) : - 1 - _solver.number(id)); 4563 } 4564 } 4565 // for row representation, return the complement of the row basis; for this, we need to loop through all rows and columns 4566 else 4567 { 4568 assert(_solver.rep() == SPxSolverBase<R>::ROW); 4569 4570 int k = 0; 4571 4572 for(int i = 0; i < numRows(); ++i) 4573 { 4574 if(!_solver.isRowBasic(i)) 4575 { 4576 bind[k] = -1 - i; 4577 k++; 4578 } 4579 } 4580 4581 for(int j = 0; j < numCols(); ++j) 4582 { 4583 if(!_solver.isColBasic(j)) 4584 { 4585 bind[k] = j; 4586 k++; 4587 } 4588 } 4589 4590 assert(k == numRows()); 4591 } 4592 } 4593 4594 4595 /** compute one of several matrix metrics based on the diagonal of the LU factorization 4596 * type = 0: max/min ratio 4597 * type = 1: trace of U (sum of diagonal elements) 4598 * type = 2: determinant (product of diagonal elements) 4599 */ 4600 template <class R> 4601 bool SoPlexBase<R>::getBasisMetric(R& condition, int type) 4602 { 4603 _ensureRealLPLoaded(); 4604 4605 if(!_isRealLPLoaded) 4606 return false; 4607 4608 if(_solver.basis().status() == SPxBasisBase<R>::NO_PROBLEM) 4609 { 4610 return false; 4611 } 4612 4613 condition = _solver.getBasisMetric(type); 4614 4615 return true; 4616 } 4617 4618 /// computes an estimated condition number for the current basis matrix using the power method; returns true on success 4619 template <class R> 4620 bool SoPlexBase<R>::getEstimatedCondition(R& condition) 4621 { 4622 _ensureRealLPLoaded(); 4623 4624 if(!_isRealLPLoaded) 4625 return false; 4626 4627 if(_solver.basis().status() == SPxBasisBase<R>::NO_PROBLEM) 4628 return false; 4629 4630 condition = _solver.basis().getEstimatedCondition(); 4631 4632 return true; 4633 } 4634 4635 /// computes the exact condition number for the current basis matrix using the power method; returns true on success 4636 template <class R> 4637 bool SoPlexBase<R>::getExactCondition(R& condition) 4638 { 4639 _ensureRealLPLoaded(); 4640 4641 if(!_isRealLPLoaded) 4642 return false; 4643 4644 if(_solver.basis().status() == SPxBasisBase<R>::NO_PROBLEM) 4645 return false; 4646 4647 condition = _solver.basis().getExactCondition(); 4648 4649 return true; 4650 } 4651 4652 /// computes row r of basis inverse; returns true on success 4653 template <class R> 4654 bool SoPlexBase<R>::getBasisInverseRowReal(int r, R* coef, int* inds, int* ninds, bool unscale) 4655 { 4656 assert(r >= 0); 4657 assert(r < numRows()); 4658 assert(coef != 0); 4659 4660 if(!hasBasis() || r < 0 || r >= numRows()) 4661 return false; 4662 4663 _ensureRealLPLoaded(); 4664 4665 if(!_isRealLPLoaded) 4666 return false; 4667 4668 // we need to distinguish between column and row representation; ask the solver itself which representation it 4669 // has, since the REPRESENTATION parameter of this class might be set to automatic 4670 if(_solver.rep() == SPxSolverBase<R>::COLUMN) 4671 { 4672 int idx; 4673 SSVectorBase<R> x(numRows(), this->tolerances()); 4674 4675 try 4676 { 4677 /* unscaling required? */ 4678 if(unscale && _solver.isScaled()) 4679 { 4680 /* for information on the unscaling procedure see spxscaler.h */ 4681 4682 int scaleExp; 4683 DSVectorBase<R> rhs(_solver.unitVector(r)); 4684 4685 // apply scaling \tilde{C} to rhs 4686 if(_solver.basis().baseId(r).isSPxColId()) 4687 scaleExp = _scaler->getColScaleExp(_solver.number(_solver.basis().baseId(r))); 4688 else 4689 scaleExp = - _scaler->getRowScaleExp(_solver.number(_solver.basis().baseId(r))); 4690 4691 rhs *= spxLdexp(1.0, scaleExp); 4692 4693 _solver.basis().coSolve(x, rhs); 4694 x.setup(); 4695 int size = x.size(); 4696 4697 //apply scaling R to solution vector 4698 for(int i = 0; i < size; i++) 4699 { 4700 scaleExp = _scaler->getRowScaleExp(x.index(i)); 4701 x.scaleValue(x.index(i), scaleExp); 4702 } 4703 } 4704 else 4705 { 4706 _solver.basis().coSolve(x, _solver.unitVector(r)); 4707 } 4708 } 4709 catch(const SPxException& E) 4710 { 4711 SPX_MSG_INFO1(spxout, spxout << "Caught exception <" << E.what() << 4712 "> while computing basis inverse row.\n"); 4713 return false; 4714 } 4715 4716 // copy sparse data to dense result vector based on coef array 4717 if(ninds != 0 && inds != 0) 4718 { 4719 // during solving SoPlexBase may have destroyed the sparsity structure so we need to restore it 4720 x.setup(); 4721 *ninds = x.size(); 4722 4723 for(int i = 0; i < *ninds; ++i) 4724 { 4725 idx = x.index(i); 4726 coef[idx] = x[idx]; 4727 // set sparsity pattern of coef array 4728 inds[i] = idx; 4729 } 4730 } 4731 else 4732 { 4733 std::copy(x.vec().begin(), x.vec().end(), coef); 4734 4735 if(ninds != NULL) 4736 *ninds = -1; 4737 } 4738 } 4739 else 4740 { 4741 assert(_solver.rep() == SPxSolverBase<R>::ROW); 4742 4743 // @todo should rhs be a reference? 4744 DSVectorBase<R> rhs(numCols()); 4745 SSVectorBase<R> y(numCols(), this->tolerances()); 4746 int* bind = 0; 4747 int index; 4748 4749 // get ordering of column basis matrix 4750 spx_alloc(bind, numRows()); 4751 getBasisInd(bind); 4752 4753 // get vector corresponding to requested index r 4754 index = bind[r]; 4755 4756 // r corresponds to a basic row 4757 if(index < 0) 4758 { 4759 // transform index to actual row index 4760 index = -index - 1; 4761 4762 // should be a valid row index and in the column basis matrix, i.e., not basic w.r.t. row representation 4763 assert(index >= 0); 4764 assert(index < numRows()); 4765 assert(!_solver.isRowBasic(index)); 4766 4767 // get row vector 4768 rhs = _solver.rowVector(index); 4769 rhs *= -1.0; 4770 4771 if(unscale && _solver.isScaled()) 4772 { 4773 for(int i = 0; i < rhs.size(); ++i) 4774 rhs.value(i) = spxLdexp(rhs.value(i), -_scaler->getRowScaleExp(index)); 4775 } 4776 } 4777 // r corresponds to a basic column 4778 else 4779 { 4780 // should be a valid column index and in the column basis matrix, i.e., not basic w.r.t. row representation 4781 assert(index < numCols()); 4782 assert(!_solver.isColBasic(index)); 4783 4784 // get unit vector 4785 rhs = UnitVectorBase<R>(index); 4786 4787 if(unscale && _solver.isScaled()) 4788 rhs *= spxLdexp(1.0, _scaler->getColScaleExp(index)); 4789 } 4790 4791 // solve system "y B = rhs", where B is the row basis matrix 4792 try 4793 { 4794 _solver.basis().solve(y, rhs); 4795 } 4796 catch(const SPxException& E) 4797 { 4798 SPX_MSG_INFO1(spxout, spxout << "Caught exception <" << E.what() << 4799 "> while computing basis inverse row.\n"); 4800 return false; 4801 } 4802 4803 // initialize result vector x as zero 4804 memset(coef, 0, (unsigned int)numRows() * sizeof(R)); 4805 4806 // add nonzero entries 4807 for(int i = 0; i < numCols(); ++i) 4808 { 4809 SPxId id = _solver.basis().baseId(i); 4810 4811 if(id.isSPxRowId()) 4812 { 4813 assert(_solver.number(id) >= 0); 4814 assert(_solver.number(id) < numRows()); 4815 assert(bind[r] >= 0 || _solver.number(id) != index); 4816 4817 int rowindex = _solver.number(id); 4818 coef[rowindex] = y[i]; 4819 4820 if(unscale && _solver.isScaled()) 4821 coef[rowindex] = spxLdexp(y[i], _scaler->getRowScaleExp(rowindex)); 4822 } 4823 } 4824 4825 // if r corresponds to a row vector, we have to add a 1 at position r 4826 if(bind[r] < 0) 4827 { 4828 assert(coef[index] == 0.0); 4829 coef[index] = 1.0; 4830 } 4831 4832 // @todo implement returning of sparsity information like in column wise case 4833 if(ninds != NULL) 4834 *ninds = -1; 4835 4836 // free memory 4837 spx_free(bind); 4838 } 4839 4840 return true; 4841 } 4842 4843 4844 4845 /// computes column c of basis inverse; returns true on success 4846 /// @todo does not work correctly for the row representation 4847 template <class R> 4848 bool SoPlexBase<R>::getBasisInverseColReal(int c, R* coef, int* inds, int* ninds, bool unscale) 4849 { 4850 assert(c >= 0); 4851 assert(c < numRows()); 4852 assert(coef != 0); 4853 4854 if(!hasBasis() || c < 0 || c >= numRows()) 4855 return false; 4856 4857 _ensureRealLPLoaded(); 4858 4859 if(!_isRealLPLoaded) 4860 return false; 4861 4862 // we need to distinguish between column and row representation; ask the solver itself which representation it 4863 // has, since the REPRESENTATION parameter of this class might be set to automatic 4864 if(_solver.rep() == SPxSolverBase<R>::COLUMN) 4865 { 4866 int idx; 4867 SSVectorBase<R> x(numRows(), this->tolerances()); 4868 4869 try 4870 { 4871 /* unscaling required? */ 4872 if(unscale && _solver.isScaled()) 4873 { 4874 /* for information on the unscaling procedure see spxscaler.h */ 4875 4876 int scaleExp = _scaler->getRowScaleExp(c); 4877 DSVectorBase<R> rhs(_solver.unitVector(c)); 4878 rhs *= spxLdexp(1.0, scaleExp); 4879 4880 _solver.basis().solve(x, rhs); 4881 4882 x.setup(); 4883 int size = x.size(); 4884 4885 for(int i = 0; i < size; i++) 4886 { 4887 if(_solver.basis().baseId(x.index(i)).isSPxColId()) 4888 { 4889 idx = _solver.number(_solver.basis().baseId(x.index(i))); 4890 scaleExp = _scaler->getColScaleExp(idx); 4891 x.scaleValue(x.index(i), scaleExp); 4892 } 4893 else 4894 { 4895 idx = _solver.number(_solver.basis().baseId(x.index(i))); 4896 scaleExp = - _scaler->getRowScaleExp(idx); 4897 x.scaleValue(x.index(i), scaleExp); 4898 } 4899 } 4900 } 4901 else 4902 { 4903 _solver.basis().solve(x, _solver.unitVector(c)); 4904 } 4905 } 4906 catch(const SPxException& E) 4907 { 4908 SPX_MSG_INFO1(spxout, spxout << "Caught exception <" << E.what() << 4909 "> while computing basis inverse row.\n"); 4910 return false; 4911 } 4912 4913 // copy sparse data to dense result vector based on coef array 4914 if(ninds != 0 && inds != 0) 4915 { 4916 // SoPlexBase may have destroyed the sparsity structure so we need to restore it 4917 x.setup(); 4918 *ninds = x.size(); 4919 4920 for(int i = 0; i < *ninds; ++i) 4921 { 4922 idx = x.index(i); 4923 coef[idx] = x[idx]; 4924 // set sparsity pattern of coef array 4925 inds[i] = idx; 4926 } 4927 } 4928 else 4929 { 4930 std::copy(x.vec().begin(), x.vec().end(), coef); 4931 4932 if(ninds != 0) 4933 *ninds = -1; 4934 } 4935 } 4936 else 4937 { 4938 assert(_solver.rep() == SPxSolverBase<R>::ROW); 4939 4940 // @todo should rhs be a reference? 4941 int* bind = 0; 4942 int index; 4943 4944 // get indices of column basis matrix (not in correct order!) 4945 spx_alloc(bind, numRows()); 4946 getBasisInd(bind); 4947 4948 index = bind[c]; 4949 // index = c >= numColsReal() ? 0 : c; 4950 4951 // initialize result vector x as zero 4952 memset(coef, 0, (unsigned int)numRows() * sizeof(Real)); 4953 4954 if(!_solver.isRowBasic(c)) 4955 { 4956 // this column of B^-1 is just a unit column 4957 for(int i = 0; i < numRows(); i++) 4958 { 4959 if(bind[i] < 0 && -bind[i] - 1 == c) 4960 coef[i] = 1.0; 4961 } 4962 } 4963 else 4964 { 4965 SSVectorBase<R> x(numCols(), this->tolerances()); 4966 4967 for(int k = 0; k < numCols(); k++) 4968 { 4969 if(c == _solver.number(_solver.basis().baseId(k)) && _solver.basis().baseId(k).isSPxRowId()) 4970 { 4971 index = k; 4972 break; 4973 } 4974 } 4975 4976 try 4977 { 4978 if(unscale && _solver.isScaled()) 4979 { 4980 int scaleExp = -_scaler->getRowScaleExp(index); 4981 DSVectorBase<R> rhs(1); 4982 rhs.add(index, spxLdexp(1.0, scaleExp)); 4983 _solver.basis().coSolve(x, rhs); 4984 x.setup(); 4985 int size = x.size(); 4986 4987 // apply scaling based on \tilde{C} 4988 for(int i = 0; i < size; i++) 4989 { 4990 int idx = bind[x.index(i)]; 4991 4992 if(idx < 0) 4993 { 4994 idx = -idx - 1; 4995 scaleExp = _scaler->getRowScaleExp(idx); 4996 } 4997 else 4998 scaleExp = - _scaler->getColScaleExp(idx); 4999 5000 spxLdexp(x.value(i), scaleExp); 5001 } 5002 } 5003 else 5004 { 5005 _solver.basis().coSolve(x, _solver.unitVector(index)); 5006 } 5007 } 5008 catch(const SPxException& E) 5009 { 5010 SPX_MSG_INFO1(spxout, spxout << "Caught exception <" << E.what() << 5011 "> while computing basis inverse column.\n"); 5012 return false; 5013 } 5014 5015 // add nonzero entries into result vector 5016 for(int i = 0; i < numRows(); i++) 5017 { 5018 int idx = bind[i]; 5019 5020 if(idx < 0) 5021 { 5022 // convert to proper row index 5023 idx = - idx - 1; 5024 // should be a valid row index, basic in the column basis 5025 assert(idx >= 0); 5026 assert(idx < numRows()); 5027 assert(!_solver.isRowBasic(idx)); 5028 5029 if(unscale && _solver.isScaled()) 5030 { 5031 DSVectorBase<R> r_unscaled(numCols()); 5032 _solver.getRowVectorUnscaled(idx, r_unscaled); 5033 coef[i] = - (r_unscaled * x); 5034 } 5035 else 5036 coef[i] = - (_solver.rowVector(idx) * x); 5037 5038 if(unscale && _solver.isScaled()) 5039 coef[i] = spxLdexp(coef[i], _scaler->getRowScaleExp(idx)); 5040 } 5041 else 5042 { 5043 // should be a valid column index, basic in the column basis 5044 assert(idx >= 0); 5045 assert(idx < numCols()); 5046 assert(!_solver.isColBasic(idx)); 5047 5048 if(unscale && _solver.isScaled()) 5049 coef[i] = spxLdexp(x[idx], _scaler->getColScaleExp(idx)); 5050 else 5051 coef[i] = x[idx]; 5052 } 5053 } 5054 } 5055 5056 // @todo implement returning of sparsity information like in column wise case 5057 if(ninds != NULL) 5058 *ninds = -1; 5059 5060 // free memory 5061 spx_free(bind); 5062 } 5063 5064 return true; 5065 } 5066 5067 5068 5069 /// computes dense solution of basis matrix B * sol = rhs; returns true on success 5070 template <class R> 5071 bool SoPlexBase<R>::getBasisInverseTimesVecReal(R* rhs, R* sol, bool unscale) 5072 { 5073 VectorBase<R> v(numRows(), rhs); 5074 VectorBase<R> x(numRows(), sol); 5075 5076 if(!hasBasis()) 5077 return false; 5078 5079 _ensureRealLPLoaded(); 5080 5081 if(!_isRealLPLoaded) 5082 return false; 5083 5084 // we need to distinguish between column and row representation; ask the solver itself which representation it 5085 // has, since the REPRESENTATION parameter of this class might be set to automatic; in the column case we can use 5086 // the existing factorization 5087 if(_solver.rep() == SPxSolverBase<R>::COLUMN) 5088 { 5089 // solve system "x = B^-1 * v" 5090 try 5091 { 5092 /* unscaling required? */ 5093 if(unscale && _solver.isScaled()) 5094 { 5095 /* for information on the unscaling procedure see spxscaler.h */ 5096 int scaleExp; 5097 int idx; 5098 5099 for(int i = 0; i < v.dim(); ++i) 5100 { 5101 if(isNotZero(v[i], this->tolerances()->epsilon())) 5102 { 5103 scaleExp = _scaler->getRowScaleExp(i); 5104 v[i] = spxLdexp(v[i], scaleExp); 5105 } 5106 } 5107 5108 _solver.basis().solve(x, v); 5109 5110 for(int i = 0; i < x.dim(); i++) 5111 { 5112 if(isNotZero(x[i], this->tolerances()->epsilon())) 5113 { 5114 idx = _solver.number(_solver.basis().baseId(i)); 5115 5116 if(_solver.basis().baseId(i).isSPxColId()) 5117 scaleExp = _scaler->getColScaleExp(idx); 5118 else 5119 scaleExp = - _scaler->getRowScaleExp(idx); 5120 5121 x[i] = spxLdexp(x[i], scaleExp); 5122 } 5123 } 5124 } 5125 else 5126 { 5127 _solver.basis().solve(x, v); 5128 } 5129 } 5130 catch(const SPxException& E) 5131 { 5132 SPX_MSG_INFO1(spxout, spxout << "Caught exception <" << E.what() << 5133 "> while solving with basis matrix.\n"); 5134 return false; 5135 } 5136 } 5137 else 5138 { 5139 assert(_solver.rep() == SPxSolverBase<R>::ROW); 5140 5141 DSVectorBase<R> rowrhs(numCols()); 5142 SSVectorBase<R> y(numCols(), this->tolerances()); 5143 int* bind = 0; 5144 5145 bool adaptScaling = unscale && _realLP->isScaled(); 5146 int scaleExp; 5147 int idx; 5148 5149 // get ordering of column basis matrix 5150 spx_alloc(bind, numRows()); 5151 getBasisInd(bind); 5152 5153 // fill right-hand side for row-based system 5154 for(int i = 0; i < numCols(); ++i) 5155 { 5156 SPxId id = _solver.basis().baseId(i); 5157 5158 if(id.isSPxRowId()) 5159 { 5160 assert(_solver.number(id) >= 0); 5161 assert(_solver.number(id) < numRows()); 5162 5163 if(adaptScaling) 5164 { 5165 idx = _solver.number(id); 5166 scaleExp = _scaler->getRowScaleExp(idx); 5167 rowrhs.add(i, spxLdexp(v[idx], scaleExp)); 5168 } 5169 else 5170 rowrhs.add(i, v[_solver.number(id)]); 5171 } 5172 else 5173 { 5174 assert(rowrhs[i] == 0.0); 5175 } 5176 } 5177 5178 // solve system "B y = rowrhs", where B is the row basis matrix 5179 try 5180 { 5181 _solver.basis().coSolve(y, rowrhs); 5182 } 5183 catch(const SPxException& E) 5184 { 5185 SPX_MSG_INFO1(spxout, spxout << "Caught exception <" << E.what() << 5186 "> while solving with basis matrix.\n"); 5187 return false; 5188 } 5189 5190 // fill result w.r.t. order given by bind 5191 for(int i = 0; i < numRows(); ++i) 5192 { 5193 int index; 5194 5195 index = bind[i]; 5196 5197 if(index < 0) 5198 { 5199 index = -index - 1; 5200 5201 // should be a valid row index and in the column basis matrix, i.e., not basic w.r.t. row representation 5202 assert(index >= 0); 5203 assert(index < numRows()); 5204 assert(!_solver.isRowBasic(index)); 5205 5206 x[i] = v[index] - (rowVectorRealInternal(index) * VectorBase<R>(numCols(), y.get_ptr())); 5207 5208 if(adaptScaling) 5209 { 5210 scaleExp = -_scaler->getRowScaleExp(index); 5211 x[i] = spxLdexp(x[i], scaleExp); 5212 } 5213 } 5214 else 5215 { 5216 // should be a valid column index and in the column basis matrix, i.e., not basic w.r.t. row representation 5217 assert(index >= 0); 5218 assert(index < numCols()); 5219 assert(!_solver.isColBasic(index)); 5220 5221 if(adaptScaling) 5222 { 5223 scaleExp = _scaler->getColScaleExp(index); 5224 x[i] = spxLdexp(y[index], scaleExp); 5225 } 5226 else 5227 x[i] = y[index]; 5228 } 5229 } 5230 5231 // free memory 5232 spx_free(bind); 5233 } 5234 5235 std::copy(v.vec().begin(), v.vec().end(), rhs); 5236 std::copy(x.vec().begin(), x.vec().end(), sol); 5237 5238 return true; 5239 } 5240 5241 5242 5243 /// multiply with basis matrix; B * vec (inplace) 5244 template <class R> 5245 bool SoPlexBase<R>::multBasis(R* vec, bool unscale) 5246 { 5247 if(!hasBasis()) 5248 return false; 5249 5250 _ensureRealLPLoaded(); 5251 5252 if(!_isRealLPLoaded) 5253 return false; 5254 5255 if(_solver.rep() == SPxSolverBase<R>::COLUMN) 5256 { 5257 int basisdim = numRows(); 5258 5259 if(unscale && _solver.isScaled()) 5260 { 5261 /* for information on the unscaling procedure see spxscaler.h */ 5262 5263 int scaleExp; 5264 5265 for(int i = 0; i < basisdim; ++i) 5266 { 5267 if(isNotZero(vec[i], this->tolerances()->epsilon())) 5268 { 5269 if(_solver.basis().baseId(i).isSPxColId()) 5270 scaleExp = - _scaler->getColScaleExp(_solver.number(_solver.basis().baseId(i))); 5271 else 5272 scaleExp = _scaler->getRowScaleExp(_solver.number(_solver.basis().baseId(i))); 5273 5274 vec[i] = spxLdexp(vec[i], scaleExp); 5275 } 5276 } 5277 5278 // create VectorBase<R> from input values 5279 VectorBase<R> x(basisdim, vec); 5280 5281 _solver.basis().multBaseWith(x); 5282 std::copy(x.vec().begin(), x.vec().end(), vec); 5283 5284 for(int i = 0; i < basisdim; ++i) 5285 { 5286 scaleExp = _scaler->getRowScaleExp(i); 5287 vec[i] = spxLdexp(vec[i], -scaleExp); 5288 } 5289 } 5290 else 5291 { 5292 // create VectorBase<R> from input values 5293 VectorBase<R> x(basisdim, vec); 5294 _solver.basis().multBaseWith(x); 5295 std::copy(x.vec().begin(), x.vec().end(), vec); 5296 } 5297 } 5298 else 5299 { 5300 int colbasisdim = numRows(); 5301 5302 DSVectorBase<R> y(colbasisdim); 5303 5304 y.clear(); 5305 5306 // create VectorBase<R> from input values 5307 VectorBase<R> x(colbasisdim, vec); 5308 5309 int* bind = 0; 5310 int index; 5311 5312 // get ordering of column basis matrix 5313 spx_alloc(bind, colbasisdim); 5314 getBasisInd(bind); 5315 5316 // temporarily create the column basis and multiply every column with x 5317 for(int i = 0; i < colbasisdim; ++i) 5318 { 5319 if(isNotZero(x[i], this->tolerances()->epsilon())) 5320 { 5321 // get vector corresponding to requested index i 5322 index = bind[i]; 5323 5324 // r corresponds to a row vector 5325 if(index < 0) 5326 { 5327 // transform index to actual row index 5328 index = -index - 1; 5329 5330 // should be a valid row index and in the column basis matrix, i.e., not basic w.r.t. row representation 5331 assert(index >= 0); 5332 assert(index < numRows()); 5333 assert(!_solver.isRowBasic(index)); 5334 5335 y.add(x[i] * UnitVectorBase<R>(index)); 5336 } 5337 // r corresponds to a column vector 5338 else 5339 { 5340 // should be a valid column index and in the column basis matrix, i.e., not basic w.r.t. row representation 5341 assert(index < numCols()); 5342 assert(!_solver.isColBasic(index)); 5343 5344 if(unscale && _solver.isScaled()) 5345 { 5346 DSVectorBase<R> col; 5347 _solver.getColVectorUnscaled(index, col); 5348 y.add(x[i] * col); 5349 } 5350 5351 y.add(x[i] * _solver.colVector(index)); 5352 } 5353 } 5354 } 5355 5356 spx_free(bind); 5357 x = y; 5358 std::copy(x.vec().begin(), x.vec().end(), vec); 5359 } 5360 5361 return true; 5362 } 5363 5364 5365 5366 /// multiply with transpose of basis matrix; vec * B^T (inplace) 5367 template <class R> 5368 bool SoPlexBase<R>::multBasisTranspose(R* vec, bool unscale) 5369 { 5370 if(!hasBasis()) 5371 return false; 5372 5373 _ensureRealLPLoaded(); 5374 5375 if(!_isRealLPLoaded) 5376 return false; 5377 5378 if(_solver.rep() == SPxSolverBase<R>::COLUMN) 5379 { 5380 int basisdim = numRows(); 5381 5382 if(unscale && _solver.isScaled()) 5383 { 5384 /* for information on the unscaling procedure see spxscaler.h */ 5385 5386 int scaleExp; 5387 5388 for(int i = 0; i < basisdim; ++i) 5389 { 5390 if(isNotZero(vec[i], this->tolerances()->epsilon())) 5391 { 5392 scaleExp = - _scaler->getRowScaleExp(i); 5393 vec[i] = spxLdexp(vec[i], scaleExp); 5394 } 5395 } 5396 5397 // create VectorBase<R> from input values 5398 VectorBase<R> x(basisdim, vec); 5399 _solver.basis().multWithBase(x); 5400 std::copy(x.vec().begin(), x.vec().end(), vec); 5401 5402 for(int i = 0; i < basisdim; ++i) 5403 { 5404 if(isNotZero(vec[i], this->tolerances()->epsilon())) 5405 { 5406 if(_solver.basis().baseId(i).isSPxColId()) 5407 scaleExp = - _scaler->getColScaleExp(_solver.number(_solver.basis().baseId(i))); 5408 else 5409 scaleExp = _scaler->getRowScaleExp(_solver.number(_solver.basis().baseId(i))); 5410 5411 vec[i] = spxLdexp(vec[i], scaleExp); 5412 } 5413 } 5414 } 5415 else 5416 { 5417 // create VectorBase<R> from input values 5418 VectorBase<R> x(basisdim, vec); 5419 _solver.basis().multWithBase(x); 5420 std::copy(x.vec().begin(), x.vec().end(), vec); 5421 } 5422 } 5423 else 5424 { 5425 int colbasisdim = numRows(); 5426 5427 DSVectorBase<R> y(colbasisdim); 5428 5429 // create VectorBase<R> from input values 5430 VectorBase<R> x(colbasisdim, vec); 5431 5432 int* bind = 0; 5433 int index; 5434 5435 // get ordering of column basis matrix 5436 spx_alloc(bind, colbasisdim); 5437 getBasisInd(bind); 5438 5439 // temporarily create the column basis and multiply every column with x 5440 for(int i = 0; i < colbasisdim; ++i) 5441 { 5442 // get vector corresponding to requested index i 5443 index = bind[i]; 5444 5445 // r corresponds to a row vector 5446 if(index < 0) 5447 { 5448 // transform index to actual row index 5449 index = -index - 1; 5450 5451 // should be a valid row index and in the column basis matrix, i.e., not basic w.r.t. row representation 5452 assert(index >= 0); 5453 assert(index < numRows()); 5454 assert(!_solver.isRowBasic(index)); 5455 5456 y.add(i, x * UnitVectorBase<R>(index)); 5457 } 5458 // r corresponds to a column vector 5459 else 5460 { 5461 // should be a valid column index and in the column basis matrix, i.e., not basic w.r.t. row representation 5462 assert(index < numCols()); 5463 assert(!_solver.isColBasic(index)); 5464 5465 if(unscale && _solver.isScaled()) 5466 { 5467 DSVectorBase<R> col; 5468 _solver.getColVectorUnscaled(index, col); 5469 y.add(i, x * col); 5470 } 5471 else 5472 y.add(i, x * _solver.colVector(index)); 5473 } 5474 } 5475 5476 spx_free(bind); 5477 x = y; 5478 std::copy(x.vec().begin(), x.vec().end(), vec); 5479 } 5480 5481 return true; 5482 } 5483 5484 5485 5486 /// compute rational basis inverse; returns true on success 5487 template <class R> 5488 bool SoPlexBase<R>::computeBasisInverseRational() 5489 { 5490 if(!hasBasis()) 5491 { 5492 _rationalLUSolver.clear(); 5493 assert(_rationalLUSolver.status() == SLinSolverRational::UNLOADED); 5494 return false; 5495 } 5496 5497 if(_rationalLUSolver.status() == SLinSolverRational::UNLOADED 5498 || _rationalLUSolver.status() == SLinSolverRational::TIME) 5499 { 5500 _rationalLUSolverBind.reSize(numRowsRational()); 5501 getBasisInd(_rationalLUSolverBind.get_ptr()); 5502 _computeBasisInverseRational(); 5503 } 5504 5505 if(_rationalLUSolver.status() == SLinSolverRational::OK) 5506 return true; 5507 5508 return false; 5509 } 5510 5511 5512 5513 /// gets an array of indices for the columns of the rational basis matrix; bind[i] >= 0 means that the i-th column of 5514 /// the basis matrix contains variable bind[i]; bind[i] < 0 means that the i-th column of the basis matrix contains 5515 /// the slack variable for row -bind[i]-1; performs rational factorization if not available; returns true on success 5516 template <class R> 5517 bool SoPlexBase<R>::getBasisIndRational(DataArray<int>& bind) 5518 { 5519 if(_rationalLUSolver.status() != SLinSolverRational::OK) 5520 computeBasisInverseRational(); 5521 5522 if(_rationalLUSolver.status() != SLinSolverRational::OK) 5523 return false; 5524 5525 bind = _rationalLUSolverBind; 5526 assert(bind.size() == numRowsRational()); 5527 return true; 5528 } 5529 5530 5531 5532 /// computes row r of basis inverse; performs rational factorization if not available; returns true on success 5533 template <class R> 5534 bool SoPlexBase<R>::getBasisInverseRowRational(const int r, SSVectorRational& vec) 5535 { 5536 if(_rationalLUSolver.status() != SLinSolverRational::OK) 5537 computeBasisInverseRational(); 5538 5539 if(_rationalLUSolver.status() != SLinSolverRational::OK) 5540 return false; 5541 5542 try 5543 { 5544 vec.reDim(numRowsRational()); 5545 _rationalLUSolver.solveLeft(vec, *_unitVectorRational(r)); 5546 } 5547 catch(const SPxException& E) 5548 { 5549 SPX_MSG_INFO1(spxout, spxout << "Caught exception <" << E.what() << 5550 "> while computing rational basis inverse row.\n"); 5551 return false; 5552 } 5553 5554 return true; 5555 } 5556 5557 /// computes column c of basis inverse; performs rational factorization if not available; returns true on success 5558 template <class R> 5559 bool SoPlexBase<R>::getBasisInverseColRational(const int c, SSVectorRational& vec) 5560 { 5561 if(_rationalLUSolver.status() != SLinSolverRational::OK) 5562 computeBasisInverseRational(); 5563 5564 if(_rationalLUSolver.status() != SLinSolverRational::OK) 5565 return false; 5566 5567 try 5568 { 5569 vec.reDim(numRowsRational()); 5570 _rationalLUSolver.solveRight(vec, *_unitVectorRational(c)); 5571 } 5572 catch(const SPxException& E) 5573 { 5574 SPX_MSG_INFO1(spxout, spxout << "Caught exception <" << E.what() << 5575 "> while computing rational basis inverse column.\n"); 5576 return false; 5577 } 5578 5579 return true; 5580 } 5581 5582 5583 5584 /// computes solution of basis matrix B * sol = rhs; performs rational factorization if not available; returns true 5585 /// on success 5586 template <class R> 5587 bool SoPlexBase<R>::getBasisInverseTimesVecRational(const SVectorRational& rhs, 5588 SSVectorRational& sol) 5589 { 5590 if(_rationalLUSolver.status() != SLinSolverRational::OK) 5591 computeBasisInverseRational(); 5592 5593 if(_rationalLUSolver.status() != SLinSolverRational::OK) 5594 return false; 5595 5596 try 5597 { 5598 sol.reDim(numRowsRational()); 5599 _rationalLUSolver.solveRight(sol, rhs); 5600 } 5601 catch(const SPxException& E) 5602 { 5603 SPX_MSG_INFO1(spxout, spxout << "Caught exception <" << E.what() << 5604 "> during right solve with rational basis inverse.\n"); 5605 return false; 5606 } 5607 5608 return true; 5609 } 5610 5611 5612 5613 /// sets starting basis via arrays of statuses 5614 template <class R> 5615 void SoPlexBase<R>::setBasis(const typename SPxSolverBase<R>::VarStatus rows[], 5616 const typename SPxSolverBase<R>::VarStatus cols[]) 5617 { 5618 _rationalLUSolver.clear(); 5619 5620 if(_isRealLPLoaded) 5621 { 5622 assert(numRows() == _solver.nRows()); 5623 assert(numCols() == _solver.nCols()); 5624 5625 _solver.setBasis(rows, cols); 5626 _hasBasis = (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM); 5627 } 5628 else 5629 { 5630 _basisStatusRows.reSize(numRows()); 5631 _basisStatusCols.reSize(numCols()); 5632 5633 for(int i = numRows() - 1; i >= 0; i--) 5634 _basisStatusRows[i] = rows[i]; 5635 5636 for(int j = numCols() - 1; j >= 0; j--) 5637 _basisStatusCols[j] = cols[j]; 5638 5639 _hasBasis = true; 5640 } 5641 } 5642 5643 5644 5645 /// clears starting basis 5646 template <class R> 5647 void SoPlexBase<R>::clearBasis() 5648 { 5649 _solver.reLoad(); 5650 _status = _solver.status(); 5651 _hasBasis = false; 5652 _rationalLUSolver.clear(); 5653 } 5654 5655 5656 5657 /// number of iterations since last call to solve 5658 template <class R> 5659 int SoPlexBase<R>::numIterations() const 5660 { 5661 return _statistics->iterations; 5662 } 5663 5664 /// number of precision boosts since last call to solve 5665 template <class R> 5666 int SoPlexBase<R>::numPrecisionBoosts() const 5667 { 5668 return _statistics->precBoosts; 5669 } 5670 5671 /// number of iterations in higher precision since last call to solve 5672 template <class R> 5673 int SoPlexBase<R>::numIterationsBoosted() const 5674 { 5675 return _statistics->boostedIterations; 5676 } 5677 5678 /// time spen in higher precision since last call to solve 5679 template <class R> 5680 Real SoPlexBase<R>::precisionBoostTime() const 5681 { 5682 return _statistics->extendedPrecisionTime->time(); 5683 } 5684 5685 /// time spent in last call to solve 5686 template <class R> 5687 Real SoPlexBase<R>::solveTime() const 5688 { 5689 return _statistics->solvingTime->time(); 5690 } 5691 5692 5693 5694 /// statistical information in form of a string 5695 template <class R> 5696 std::string SoPlexBase<R>::statisticString() const 5697 { 5698 std::stringstream s; 5699 s << "Factorizations : " << std::setw(10) << _statistics->luFactorizationsReal << std::endl 5700 << " Time spent : " << std::setw(10) << std::fixed << std::setprecision( 5701 2) << _statistics->luFactorizationTimeReal << std::endl 5702 << "Solves : " << std::setw(10) << _statistics->luSolvesReal << std::endl 5703 << " Time spent : " << std::setw(10) << _statistics->luSolveTimeReal << std::endl 5704 << "Solution time : " << std::setw(10) << std::fixed << std::setprecision( 5705 2) << solveTime() << std::endl 5706 << "Iterations : " << std::setw(10) << numIterations() << std::endl; 5707 5708 return s.str(); 5709 } 5710 5711 5712 5713 /// name of starter 5714 template <class R> 5715 const char* SoPlexBase<R>::getStarterName() 5716 { 5717 if(_starter) 5718 return _starter->getName(); 5719 else 5720 return "none"; 5721 } 5722 5723 5724 5725 /// name of simplifier 5726 template <class R> 5727 const char* SoPlexBase<R>::getSimplifierName() 5728 { 5729 if(_simplifier) 5730 return _simplifier->getName(); 5731 else 5732 return "none"; 5733 } 5734 5735 5736 5737 /// name of scaling method after simplifier 5738 template <class R> 5739 const char* SoPlexBase<R>::getScalerName() 5740 { 5741 if(_scaler) 5742 return _scaler->getName(); 5743 else 5744 return "none"; 5745 } 5746 5747 5748 5749 /// name of currently loaded pricer 5750 template <class R> 5751 const char* SoPlexBase<R>::getPricerName() 5752 { 5753 return _solver.pricer()->getName(); 5754 } 5755 5756 5757 5758 /// name of currently loaded ratiotester 5759 template <class R> 5760 const char* SoPlexBase<R>::getRatiotesterName() 5761 { 5762 return _solver.ratiotester()->getName(); 5763 } 5764 5765 5766 /// returns boolean parameter value 5767 template <class R> 5768 bool SoPlexBase<R>::boolParam(const BoolParam param) const 5769 { 5770 assert(param >= 0); 5771 assert(param < SoPlexBase<R>::BOOLPARAM_COUNT); 5772 return _currentSettings->_boolParamValues[param]; 5773 } 5774 5775 /// returns integer parameter value 5776 template <class R> 5777 int SoPlexBase<R>::intParam(const IntParam param) const 5778 { 5779 assert(param >= 0); 5780 assert(param < INTPARAM_COUNT); 5781 return _currentSettings->_intParamValues[param]; 5782 } 5783 5784 /// returns real parameter value 5785 template <class R> 5786 Real SoPlexBase<R>::realParam(const RealParam param) const 5787 { 5788 assert(param >= 0); 5789 assert(param < REALPARAM_COUNT); 5790 return _currentSettings->_realParamValues[param]; 5791 } 5792 5793 #ifdef SOPLEX_WITH_RATIONALPARAM 5794 /// returns rational parameter value 5795 Rational SoPlexBase<R>::rationalParam(const RationalParam param) const 5796 { 5797 assert(param >= 0); 5798 assert(param < RATIONALPARAM_COUNT); 5799 return _currentSettings->_rationalParamValues[param]; 5800 } 5801 #endif 5802 5803 5804 5805 /// returns current parameter settings 5806 template <class R> 5807 const typename SoPlexBase<R>::Settings& SoPlexBase<R>::settings() const 5808 { 5809 return *_currentSettings; 5810 } 5811 5812 /// returns current tolerances 5813 template <class R> const std::shared_ptr<Tolerances> SoPlexBase<R>::tolerances() const 5814 { 5815 return _tolerances; 5816 } 5817 5818 5819 5820 /// sets boolean parameter value; returns true on success 5821 template <class R> 5822 bool SoPlexBase<R>::setBoolParam(const BoolParam param, const bool value, const bool init) 5823 { 5824 assert(param >= 0); 5825 assert(param < SoPlexBase<R>::BOOLPARAM_COUNT); 5826 assert(init || _isConsistent()); 5827 5828 if(!init && value == boolParam(param)) 5829 return true; 5830 5831 switch(param) 5832 { 5833 case LIFTING: 5834 break; 5835 5836 case EQTRANS: 5837 break; 5838 5839 case TESTDUALINF: 5840 break; 5841 5842 case RATFAC: 5843 break; 5844 5845 case USEDECOMPDUALSIMPLEX: 5846 break; 5847 5848 case COMPUTEDEGEN: 5849 break; 5850 5851 case USECOMPDUAL: 5852 break; 5853 5854 case EXPLICITVIOL: 5855 break; 5856 5857 case ACCEPTCYCLING: 5858 break; 5859 5860 case RATREC: 5861 break; 5862 5863 case POWERSCALING: 5864 break; 5865 5866 case RATFACJUMP: 5867 break; 5868 5869 case ROWBOUNDFLIPS: 5870 _ratiotesterBoundFlipping.useBoundFlipsRow(value); 5871 break; 5872 5873 case PERSISTENTSCALING: 5874 break; 5875 5876 case FULLPERTURBATION: 5877 _solver.useFullPerturbation(value); 5878 break; 5879 5880 case ENSURERAY: 5881 break; 5882 5883 case FORCEBASIC: 5884 break; 5885 5886 case SIMPLIFIER_SINGLETONCOLS: 5887 #ifdef SOPLEX_WITH_PAPILO 5888 _simplifierPaPILO.setEnableSingletonCols(value); 5889 #else 5890 SPX_MSG_INFO1(spxout, spxout << 5891 "Setting Parameter simplifier_enable_singleton_cols is only possible if SoPlex is build with PaPILO\n"); 5892 return false; 5893 #endif 5894 break; 5895 5896 case SIMPLIFIER_CONSTRAINTPROPAGATION: 5897 #ifdef SOPLEX_WITH_PAPILO 5898 _simplifierPaPILO.setEnablePropagation(value); 5899 #else 5900 SPX_MSG_INFO1(spxout, spxout << 5901 "Setting Parameter simplifier_enable_propagation is only possible if SoPlex is build with PaPILO\n"); 5902 return false; 5903 #endif 5904 break; 5905 5906 case SIMPLIFIER_PARALLELROWDETECTION: 5907 #ifdef SOPLEX_WITH_PAPILO 5908 _simplifierPaPILO.setEnableParallelRows(value); 5909 #else 5910 SPX_MSG_INFO1(spxout, spxout << 5911 "Setting Parameter simplifier_enable_parallelrows is only possible if SoPlex is build with PaPILO\n"); 5912 return false; 5913 #endif 5914 break; 5915 5916 case SIMPLIFIER_PARALLELCOLDETECTION: 5917 #ifdef SOPLEX_WITH_PAPILO 5918 _simplifierPaPILO.setEnableParallelCols(value); 5919 #else 5920 SPX_MSG_INFO1(spxout, spxout << 5921 "Setting Parameter simplifier_enable_parallelcols is only possible if SoPlex is build with PaPILO\n"); 5922 return false; 5923 #endif 5924 break; 5925 5926 case SIMPLIFIER_SINGLETONSTUFFING: 5927 #ifdef SOPLEX_WITH_PAPILO 5928 _simplifierPaPILO.setEnableStuffing(value); 5929 #else 5930 SPX_MSG_INFO1(spxout, spxout << 5931 "Setting Parameter simplifier_enable_stuffing is only possible if SoPlex is build with PaPILO\n"); 5932 return false; 5933 #endif 5934 break; 5935 5936 case SIMPLIFIER_DUALFIX: 5937 #ifdef SOPLEX_WITH_PAPILO 5938 _simplifierPaPILO.setEnableDualFix(value); 5939 #else 5940 SPX_MSG_INFO1(spxout, spxout << 5941 "Setting Parameter simplifier_enable_dualfix is only possible if SoPlex is build with PaPILO\n"); 5942 return false; 5943 #endif 5944 break; 5945 5946 case SIMPLIFIER_FIXCONTINUOUS: 5947 #ifdef SOPLEX_WITH_PAPILO 5948 _simplifierPaPILO.setEnableFixContinuous(value); 5949 #else 5950 SPX_MSG_INFO1(spxout, spxout << 5951 "Setting Parameter simplifier_enable_fixcontinuous is only possible if SoPlex is build with PaPILO\n"); 5952 return false; 5953 #endif 5954 break; 5955 5956 case SIMPLIFIER_DOMINATEDCOLS: 5957 #ifdef SOPLEX_WITH_PAPILO 5958 _simplifierPaPILO.setEnableDomCols(value); 5959 #else 5960 SPX_MSG_INFO1(spxout, spxout << 5961 "Setting Parameter simplifier_enable_domcol is only possible if SoPlex is build with PaPILO\n"); 5962 return false; 5963 #endif 5964 break; 5965 5966 case ITERATIVE_REFINEMENT: 5967 break; 5968 5969 case ADAPT_TOLS_TO_MULTIPRECISION: 5970 break; 5971 5972 case PRECISION_BOOSTING: 5973 #ifndef SOPLEX_WITH_MPFR 5974 SPX_MSG_INFO1(spxout, spxout << 5975 "Setting Parameter precision_boosting is only possible if SoPlex is build with MPFR\n"); 5976 return false; 5977 #endif 5978 break; 5979 5980 case BOOSTED_WARM_START: 5981 break; 5982 5983 case RECOVERY_MECHANISM: 5984 break; 5985 5986 default: 5987 return false; 5988 } 5989 5990 _currentSettings->_boolParamValues[param] = value; 5991 return true; 5992 } 5993 5994 /// sets integer parameter value; returns true on success 5995 template <class R> 5996 bool SoPlexBase<R>::setIntParam(const IntParam param, const int value, const bool init) 5997 { 5998 assert(param >= 0); 5999 assert(param < INTPARAM_COUNT); 6000 assert(init || _isConsistent()); 6001 6002 if(!init && value == intParam(param)) 6003 return true; 6004 6005 // check for a valid parameter value wrt bounds 6006 if(value < _currentSettings->intParam.lower[param] 6007 || value > _currentSettings->intParam.upper[param]) 6008 return false; 6009 6010 switch(param) 6011 { 6012 // objective sense 6013 case SoPlexBase<R>::OBJSENSE: 6014 if(value != SoPlexBase<R>::OBJSENSE_MAXIMIZE && value != SoPlexBase<R>::OBJSENSE_MINIMIZE) 6015 return false; 6016 6017 _realLP->changeSense(value == SoPlexBase<R>::OBJSENSE_MAXIMIZE ? SPxLPBase<R>::MAXIMIZE : 6018 SPxLPBase<R>::MINIMIZE); 6019 6020 if(_rationalLP != 0) 6021 _rationalLP->changeSense(value == SoPlexBase<R>::OBJSENSE_MAXIMIZE ? SPxLPRational::MAXIMIZE : 6022 SPxLPRational::MINIMIZE); 6023 6024 _invalidateSolution(); 6025 break; 6026 6027 // type of computational form, i.e., column or row representation 6028 case SoPlexBase<R>::REPRESENTATION: 6029 if(value != SoPlexBase<R>::REPRESENTATION_COLUMN && value != SoPlexBase<R>::REPRESENTATION_ROW 6030 && value != SoPlexBase<R>::REPRESENTATION_AUTO) 6031 return false; 6032 6033 break; 6034 6035 // type of algorithm, i.e., primal or dual 6036 case SoPlexBase<R>::ALGORITHM: 6037 // decide upon entering/leaving at solve time depending on representation 6038 break; 6039 6040 // type of LU update 6041 case SoPlexBase<R>::FACTOR_UPDATE_TYPE: 6042 if(value != SoPlexBase<R>::FACTOR_UPDATE_TYPE_ETA && value != SoPlexBase<R>::FACTOR_UPDATE_TYPE_FT) 6043 return false; 6044 6045 _slufactor.setUtype(value == SoPlexBase<R>::FACTOR_UPDATE_TYPE_ETA ? SLUFactor<R>::ETA : 6046 SLUFactor<R>::FOREST_TOMLIN); 6047 break; 6048 6049 // maximum number of updates before fresh factorization 6050 case SoPlexBase<R>::FACTOR_UPDATE_MAX: 6051 if(value == 0) 6052 _solver.basis().setMaxUpdates(SOPLEX_REFACTOR_INTERVAL); 6053 else 6054 _solver.basis().setMaxUpdates(value); 6055 6056 break; 6057 6058 // iteration limit (-1 if unlimited) 6059 case SoPlexBase<R>::ITERLIMIT: 6060 break; 6061 6062 // refinement limit (-1 if unlimited) 6063 case SoPlexBase<R>::REFLIMIT: 6064 break; 6065 6066 // stalling refinement limit (-1 if unlimited) 6067 case SoPlexBase<R>::STALLREFLIMIT: 6068 break; 6069 6070 // display frequency 6071 case SoPlexBase<R>::DISPLAYFREQ: 6072 _solver.setDisplayFreq(value); 6073 break; 6074 6075 // verbosity level 6076 case SoPlexBase<R>::VERBOSITY: 6077 switch(value) 6078 { 6079 case 0: 6080 spxout.setVerbosity(SPxOut::ERROR); 6081 break; 6082 6083 case 1: 6084 spxout.setVerbosity(SPxOut::WARNING); 6085 break; 6086 6087 case 2: 6088 spxout.setVerbosity(SPxOut::DEBUG); 6089 break; 6090 6091 case 3: 6092 spxout.setVerbosity(SPxOut::INFO1); 6093 break; 6094 6095 case 4: 6096 spxout.setVerbosity(SPxOut::INFO2); 6097 break; 6098 6099 case 5: 6100 spxout.setVerbosity(SPxOut::INFO3); 6101 break; 6102 } 6103 6104 break; 6105 6106 // type of simplifier 6107 case SoPlexBase<R>::SIMPLIFIER: 6108 #ifndef SOPLEX_WITH_MPFR 6109 _boostedSimplifier = nullptr; 6110 #endif 6111 6112 switch(value) 6113 { 6114 case SIMPLIFIER_OFF: 6115 _simplifier = nullptr; 6116 #ifdef SOPLEX_WITH_MPFR 6117 _boostedSimplifier = nullptr; 6118 #endif 6119 break; 6120 6121 case SIMPLIFIER_INTERNAL: 6122 case SIMPLIFIER_AUTO: 6123 _simplifier = &_simplifierMainSM; 6124 assert(_simplifier != 0); 6125 #ifdef SOPLEX_WITH_MPFR 6126 _boostedSimplifier = &_boostedSimplifierMainSM; 6127 assert(_boostedSimplifier != 0); 6128 #endif 6129 break; 6130 6131 case SIMPLIFIER_PAPILO: 6132 #ifdef SOPLEX_WITH_PAPILO 6133 _simplifier = &_simplifierPaPILO; 6134 assert(_simplifier != 0); 6135 #ifdef SOPLEX_WITH_MPFR 6136 _boostedSimplifier = &_boostedSimplifierPaPILO; 6137 assert(_boostedSimplifier != 0); 6138 #endif 6139 break; 6140 #else 6141 _simplifier = &_simplifierMainSM; 6142 assert(_simplifier != 0); 6143 #ifdef SOPLEX_WITH_MPFR 6144 _boostedSimplifier = &_boostedSimplifierMainSM; 6145 assert(_boostedSimplifier != 0); 6146 #endif 6147 return false; 6148 #endif 6149 6150 default: 6151 return false; 6152 } 6153 6154 if(_simplifier != nullptr) 6155 _simplifier->setTolerances(this->_tolerances); 6156 6157 if(_boostedSimplifier != nullptr) 6158 _boostedSimplifier->setTolerances(this->_tolerances); 6159 6160 break; 6161 6162 // type of scaler 6163 case SoPlexBase<R>::SCALER: 6164 #ifndef SOPLEX_WITH_MPFR 6165 _boostedScaler = nullptr; 6166 #endif 6167 6168 switch(value) 6169 { 6170 case SCALER_OFF: 6171 _scaler = nullptr; 6172 #ifdef SOPLEX_WITH_MPFR 6173 _boostedScaler = nullptr; 6174 #endif 6175 break; 6176 6177 case SCALER_UNIEQUI: 6178 _scaler = &_scalerUniequi; 6179 #ifdef SOPLEX_WITH_MPFR 6180 _boostedScaler = &_boostedScalerUniequi; 6181 #endif 6182 break; 6183 6184 case SCALER_BIEQUI: 6185 _scaler = &_scalerBiequi; 6186 #ifdef SOPLEX_WITH_MPFR 6187 _boostedScaler = &_boostedScalerBiequi; 6188 #endif 6189 break; 6190 6191 case SCALER_GEO1: 6192 _scaler = &_scalerGeo1; 6193 #ifdef SOPLEX_WITH_MPFR 6194 _boostedScaler = &_boostedScalerGeo1; 6195 #endif 6196 break; 6197 6198 case SCALER_GEO8: 6199 _scaler = &_scalerGeo8; 6200 #ifdef SOPLEX_WITH_MPFR 6201 _boostedScaler = &_boostedScalerGeo8; 6202 #endif 6203 break; 6204 6205 case SCALER_LEASTSQ: 6206 _scaler = &_scalerLeastsq; 6207 #ifdef SOPLEX_WITH_MPFR 6208 _boostedScaler = &_boostedScalerLeastsq; 6209 #endif 6210 break; 6211 6212 case SCALER_GEOEQUI: 6213 _scaler = &_scalerGeoequi; 6214 #ifdef SOPLEX_WITH_MPFR 6215 _boostedScaler = &_boostedScalerGeoequi; 6216 #endif 6217 break; 6218 6219 default: 6220 return false; 6221 } 6222 6223 if(_scaler != nullptr) 6224 _scaler->setTolerances(this->_tolerances); 6225 6226 if(_boostedScaler != nullptr) 6227 _boostedScaler->setTolerances(this->_tolerances); 6228 6229 break; 6230 6231 // type of starter used to create crash basis 6232 case SoPlexBase<R>::STARTER: 6233 switch(value) 6234 { 6235 case STARTER_OFF: 6236 _starter = nullptr; 6237 break; 6238 6239 case STARTER_WEIGHT: 6240 _starter = &_starterWeight; 6241 break; 6242 6243 case STARTER_SUM: 6244 _starter = &_starterSum; 6245 break; 6246 6247 case STARTER_VECTOR: 6248 _starter = &_starterVector; 6249 break; 6250 6251 default: 6252 return false; 6253 } 6254 6255 if(_starter != nullptr) 6256 _starter->setTolerances(this->_tolerances); 6257 6258 _solver.setStarter(_starter, false); 6259 break; 6260 6261 // type of pricer 6262 case SoPlexBase<R>::PRICER: 6263 switch(value) 6264 { 6265 case PRICER_AUTO: 6266 _solver.setPricer(&_pricerAuto); 6267 #ifdef SOPLEX_WITH_MPFR 6268 _boostedSolver.setPricer(&_boostedPricerAuto); 6269 #endif 6270 break; 6271 6272 case PRICER_DANTZIG: 6273 _solver.setPricer(&_pricerDantzig); 6274 #ifdef SOPLEX_WITH_MPFR 6275 _boostedSolver.setPricer(&_boostedPricerDantzig); 6276 #endif 6277 break; 6278 6279 case PRICER_PARMULT: 6280 _solver.setPricer(&_pricerParMult); 6281 #ifdef SOPLEX_WITH_MPFR 6282 _boostedSolver.setPricer(&_boostedPricerParMult); 6283 #endif 6284 break; 6285 6286 case PRICER_DEVEX: 6287 _solver.setPricer(&_pricerDevex); 6288 #ifdef SOPLEX_WITH_MPFR 6289 _boostedSolver.setPricer(&_boostedPricerDevex); 6290 #endif 6291 break; 6292 6293 case PRICER_QUICKSTEEP: 6294 _solver.setPricer(&_pricerQuickSteep); 6295 #ifdef SOPLEX_WITH_MPFR 6296 _boostedSolver.setPricer(&_boostedPricerQuickSteep); 6297 #endif 6298 break; 6299 6300 case PRICER_STEEP: 6301 _solver.setPricer(&_pricerSteep); 6302 #ifdef SOPLEX_WITH_MPFR 6303 _boostedSolver.setPricer(&_boostedPricerSteep); 6304 #endif 6305 break; 6306 6307 default: 6308 return false; 6309 } 6310 6311 break; 6312 6313 // mode for synchronizing real and rational LP 6314 case SoPlexBase<R>::SYNCMODE: 6315 switch(value) 6316 { 6317 case SYNCMODE_ONLYREAL: 6318 if(_rationalLP != 0) 6319 { 6320 _rationalLP->~SPxLPRational(); 6321 spx_free(_rationalLP); 6322 } 6323 6324 break; 6325 6326 case SYNCMODE_AUTO: 6327 if(intParam(param) == SYNCMODE_ONLYREAL) 6328 _syncLPRational(); 6329 6330 break; 6331 6332 case SYNCMODE_MANUAL: 6333 _ensureRationalLP(); 6334 assert(_realLP != 0); 6335 _rationalLP->changeSense(_realLP->spxSense() == SPxLPBase<R>::MINIMIZE ? SPxLPRational::MINIMIZE : 6336 SPxLPRational::MAXIMIZE); 6337 break; 6338 6339 default: 6340 return false; 6341 } 6342 6343 break; 6344 6345 // mode for reading LP files; nothing to do but change the value if valid 6346 case SoPlexBase<R>::READMODE: 6347 switch(value) 6348 { 6349 #ifndef SOPLEX_WITH_BOOST 6350 6351 case READMODE_REAL: 6352 break; 6353 6354 case READMODE_RATIONAL: 6355 SPX_MSG_ERROR(std::cerr << "ERROR: rational solve without Boost not defined!" << std::endl;) 6356 return false; 6357 #else 6358 6359 case READMODE_REAL: 6360 case READMODE_RATIONAL: 6361 break; 6362 #endif 6363 6364 default: 6365 return false; 6366 } 6367 6368 break; 6369 6370 // mode for iterative refinement strategy; nothing to do but change the value if valid 6371 case SoPlexBase<R>::SOLVEMODE: 6372 switch(value) 6373 { 6374 #ifndef SOPLEX_WITH_BOOST 6375 6376 case SOLVEMODE_REAL: 6377 case SOLVEMODE_AUTO: 6378 break; 6379 6380 case SOLVEMODE_RATIONAL: 6381 SPX_MSG_ERROR(std::cerr << "ERROR: rational solve without Boost not defined!" << std::endl;) 6382 return false; 6383 #else 6384 6385 case SOLVEMODE_REAL: 6386 case SOLVEMODE_AUTO: 6387 case SOLVEMODE_RATIONAL: 6388 6389 break; 6390 #endif 6391 6392 default: 6393 return false; 6394 } 6395 6396 break; 6397 6398 // mode for a posteriori feasibility checks; nothing to do but change the value if valid 6399 case SoPlexBase<R>::CHECKMODE: 6400 switch(value) 6401 { 6402 case CHECKMODE_REAL: 6403 case CHECKMODE_AUTO: 6404 case CHECKMODE_RATIONAL: 6405 break; 6406 6407 default: 6408 return false; 6409 } 6410 6411 break; 6412 6413 // type of ratio test 6414 case SoPlexBase<R>::RATIOTESTER: 6415 switch(value) 6416 { 6417 case RATIOTESTER_TEXTBOOK: 6418 _solver.setTester(&_ratiotesterTextbook); 6419 #ifdef SOPLEX_WITH_MPFR 6420 _boostedSolver.setTester(&_boostedRatiotesterTextbook); 6421 #endif 6422 break; 6423 6424 case RATIOTESTER_HARRIS: 6425 _solver.setTester(&_ratiotesterHarris); 6426 #ifdef SOPLEX_WITH_MPFR 6427 _boostedSolver.setTester(&_boostedRatiotesterHarris); 6428 #endif 6429 break; 6430 6431 case RATIOTESTER_FAST: 6432 _solver.setTester(&_ratiotesterFast); 6433 #ifdef SOPLEX_WITH_MPFR 6434 _boostedSolver.setTester(&_boostedRatiotesterFast); 6435 #endif 6436 break; 6437 6438 case RATIOTESTER_BOUNDFLIPPING: 6439 _solver.setTester(&_ratiotesterBoundFlipping); 6440 #ifdef SOPLEX_WITH_MPFR 6441 _boostedSolver.setTester(&_boostedRatiotesterBoundFlipping); 6442 #endif 6443 break; 6444 6445 default: 6446 return false; 6447 } 6448 6449 break; 6450 6451 // type of timer 6452 case SoPlexBase<R>::TIMER: 6453 switch(value) 6454 { 6455 case TIMER_OFF: 6456 _solver.setTiming(Timer::OFF); 6457 break; 6458 6459 case TIMER_CPU: 6460 _solver.setTiming(Timer::USER_TIME); 6461 break; 6462 6463 case TIMER_WALLCLOCK: 6464 _solver.setTiming(Timer::WALLCLOCK_TIME); 6465 break; 6466 6467 default: 6468 return false; 6469 } 6470 6471 break; 6472 6473 // mode of hyper pricing 6474 case SoPlexBase<R>::HYPER_PRICING: 6475 switch(value) 6476 { 6477 case HYPER_PRICING_OFF: 6478 case HYPER_PRICING_AUTO: 6479 case HYPER_PRICING_ON: 6480 break; 6481 6482 default: 6483 return false; 6484 } 6485 6486 break; 6487 6488 // minimum number of stalling refinements since last pivot to trigger rational factorization 6489 case SoPlexBase<R>::RATFAC_MINSTALLS: 6490 break; 6491 6492 // maximum number of conjugate gradient iterations in least square scaling 6493 case SoPlexBase<R>::LEASTSQ_MAXROUNDS: 6494 if(_scaler) 6495 _scaler->setIntParam(value); 6496 6497 break; 6498 6499 // mode of solution polishing 6500 case SoPlexBase<R>::SOLUTION_POLISHING: 6501 switch(value) 6502 { 6503 case POLISHING_OFF: 6504 _solver.setSolutionPolishing(SPxSolverBase<R>::POLISH_OFF); 6505 break; 6506 6507 case POLISHING_INTEGRALITY: 6508 _solver.setSolutionPolishing(SPxSolverBase<R>::POLISH_INTEGRALITY); 6509 break; 6510 6511 case POLISHING_FRACTIONALITY: 6512 _solver.setSolutionPolishing(SPxSolverBase<R>::POLISH_FRACTIONALITY); 6513 break; 6514 6515 default: 6516 return false; 6517 } 6518 6519 break; 6520 6521 // the decomposition based simplex parameter settings 6522 case DECOMP_ITERLIMIT: 6523 break; 6524 6525 case DECOMP_MAXADDEDROWS: 6526 break; 6527 6528 case DECOMP_DISPLAYFREQ: 6529 break; 6530 6531 case DECOMP_VERBOSITY: 6532 break; 6533 6534 // printing of condition n 6535 case PRINTBASISMETRIC: 6536 _solver.setMetricInformation(value); 6537 break; 6538 6539 case STATTIMER: 6540 setTimings((Timer::TYPE) value); 6541 break; 6542 6543 // maximum number of digits for the multiprecision type 6544 case SoPlexBase<R>::MULTIPRECISION_LIMIT: 6545 break; 6546 6547 case SoPlexBase<R>::STORE_BASIS_SIMPLEX_FREQ: 6548 // attributes in solvers need to be updated 6549 _solver.setStoreBasisFreqForBoosting(value); 6550 _boostedSolver.setStoreBasisFreqForBoosting(value); 6551 break; 6552 6553 default: 6554 return false; 6555 } 6556 6557 _currentSettings->_intParamValues[param] = value; 6558 return true; 6559 } 6560 6561 /// sets real parameter value; returns true on success 6562 template <class R> 6563 bool SoPlexBase<R>::setRealParam(const RealParam param, const Real value, const bool init) 6564 { 6565 assert(param >= 0); 6566 assert(param < REALPARAM_COUNT); 6567 assert(init || _isConsistent()); 6568 6569 if(!init && value == realParam(param)) 6570 return true; 6571 6572 if(value < _currentSettings->realParam.lower[param] 6573 || value > _currentSettings->realParam.upper[param]) 6574 return false; 6575 6576 // required to set a different feastol or opttol 6577 Real tmp_value = value; 6578 6579 switch(param) 6580 { 6581 // primal feasibility tolerance; passed to the floating point solver only when calling solve() 6582 case SoPlexBase<R>::FEASTOL: 6583 #ifndef SOPLEX_WITH_BOOST 6584 if(value < SOPLEX_DEFAULT_EPS_PIVOR) 6585 { 6586 SPX_MSG_WARNING(spxout, spxout << "Cannot set feasibility tolerance to small value " << value << 6587 " without GMP - using " << SOPLEX_DEFAULT_EPS_PIVOR << ".\n"); 6588 _rationalFeastol = SOPLEX_DEFAULT_EPS_PIVOR; 6589 this->_tolerances->setFeastol(SOPLEX_DEFAULT_EPS_PIVOR); 6590 break; 6591 } 6592 6593 #endif 6594 _rationalFeastol = value; 6595 this->_tolerances->setFeastol(value); 6596 break; 6597 6598 // dual feasibility tolerance; passed to the floating point solver only when calling solve() 6599 case SoPlexBase<R>::OPTTOL: 6600 #ifndef SOPLEX_WITH_GMP 6601 if(value < SOPLEX_DEFAULT_EPS_PIVOR) 6602 { 6603 SPX_MSG_WARNING(spxout, spxout << "Cannot set optimality tolerance to small value " << value << 6604 " without GMP - using " << SOPLEX_DEFAULT_EPS_PIVOR << ".\n"); 6605 _rationalOpttol = SOPLEX_DEFAULT_EPS_PIVOR; 6606 this->_tolerances->setOpttol(SOPLEX_DEFAULT_EPS_PIVOR); 6607 break; 6608 } 6609 6610 #endif 6611 _rationalOpttol = value; 6612 this->_tolerances->setOpttol(value); 6613 break; 6614 6615 // general zero tolerance 6616 case SoPlexBase<R>::EPSILON_ZERO: 6617 _tolerances->setEpsilon(Real(value)); 6618 break; 6619 6620 // zero tolerance used in factorization 6621 case SoPlexBase<R>::EPSILON_FACTORIZATION: 6622 _tolerances->setEpsilonFactorization(Real(value)); 6623 break; 6624 6625 // zero tolerance used in update of the factorization 6626 case SoPlexBase<R>::EPSILON_UPDATE: 6627 _tolerances->setEpsilonUpdate(Real(value)); 6628 break; 6629 6630 // pivot zero tolerance used in factorization (declare numerical singularity for small LU pivots) 6631 case SoPlexBase<R>::EPSILON_PIVOT: 6632 _tolerances->setEpsilonPivot(Real(value)); 6633 break; 6634 6635 // infinity threshold 6636 case SoPlexBase<R>::INFTY: 6637 #ifdef SOPLEX_WITH_BOOST 6638 _rationalPosInfty = value; 6639 // boost is treating -value as an expression and not just a number<T> So 6640 // doing -val won't work since Rational doesn't have an operator= that 6641 // accepts boost expressions. 0-value is a simple fix. 6642 6643 // @todo Implement expression template? 6644 // A work around to avoid expression template 6645 _rationalNegInfty = value; 6646 _rationalNegInfty = -_rationalNegInfty; 6647 #endif 6648 6649 if(intParam(SoPlexBase<R>::SYNCMODE) != SYNCMODE_ONLYREAL) 6650 _recomputeRangeTypesRational(); 6651 6652 break; 6653 6654 // time limit in seconds (INFTY if unlimited) 6655 case SoPlexBase<R>::TIMELIMIT: 6656 break; 6657 6658 // lower limit on objective value is set in solveReal() 6659 case SoPlexBase<R>::OBJLIMIT_LOWER: 6660 break; 6661 6662 // upper limit on objective value is set in solveReal() 6663 case SoPlexBase<R>::OBJLIMIT_UPPER: 6664 break; 6665 6666 // working tolerance for feasibility in floating-point solver 6667 case SoPlexBase<R>::FPFEASTOL: 6668 this->_tolerances->setFloatingPointFeastol(value); 6669 break; 6670 6671 // working tolerance for optimality in floating-point solver 6672 case SoPlexBase<R>::FPOPTTOL: 6673 this->_tolerances->setFloatingPointOpttol(value); 6674 break; 6675 6676 // maximum increase of scaling factors between refinements 6677 case SoPlexBase<R>::MAXSCALEINCR: 6678 _rationalMaxscaleincr = value; 6679 break; 6680 6681 // lower threshold in lifting (nonzero matrix coefficients with smaller absolute value will be reformulated) 6682 case SoPlexBase<R>::LIFTMINVAL: 6683 break; 6684 6685 // upper threshold in lifting (nonzero matrix coefficients with larger absolute value will be reformulated) 6686 case SoPlexBase<R>::LIFTMAXVAL: 6687 break; 6688 6689 // threshold for sparse pricing 6690 case SoPlexBase<R>::SPARSITY_THRESHOLD: 6691 break; 6692 6693 // threshold on number of rows vs. number of columns for switching from column to row representations in auto mode 6694 case SoPlexBase<R>::REPRESENTATION_SWITCH: 6695 break; 6696 6697 // geometric frequency at which to apply rational reconstruction 6698 case SoPlexBase<R>::RATREC_FREQ: 6699 break; 6700 6701 // minimal reduction (sum of removed rows/cols) to continue simplification 6702 case SoPlexBase<R>::MINRED: 6703 break; 6704 6705 case SoPlexBase<R>::REFAC_BASIS_NNZ: 6706 break; 6707 6708 case SoPlexBase<R>::REFAC_UPDATE_FILL: 6709 break; 6710 6711 case SoPlexBase<R>::REFAC_MEM_FACTOR: 6712 break; 6713 6714 // accuracy of conjugate gradient method in least squares scaling (higher value leads to more iterations) 6715 case SoPlexBase<R>::LEASTSQ_ACRCY: 6716 if(_scaler) 6717 _scaler->setRealParam(value); 6718 6719 break; 6720 6721 // objective offset 6722 case SoPlexBase<R>::OBJ_OFFSET: 6723 if(_realLP) 6724 _realLP->changeObjOffset(value); 6725 6726 if(_rationalLP) 6727 _rationalLP->changeObjOffset(value); 6728 6729 break; 6730 6731 case SoPlexBase<R>::MIN_MARKOWITZ: 6732 _slufactor.setMarkowitz(value); 6733 break; 6734 6735 case SoPlexBase<R>::SIMPLIFIER_MODIFYROWFAC: 6736 #ifdef SOPLEX_WITH_PAPILO 6737 _simplifierPaPILO.setModifyConsFrac(value); 6738 #else 6739 6740 if(!init) 6741 { 6742 SPX_MSG_INFO1(spxout, spxout << 6743 "Setting Parameter modifyrowfrac is only possible if SoPlex is build with PaPILO\n"); 6744 } 6745 6746 return false; 6747 #endif 6748 break; 6749 6750 // factor by which the precision of the floating-point solver is multiplied 6751 case SoPlexBase<R>::PRECISION_BOOSTING_FACTOR: 6752 break; 6753 6754 default: 6755 return false; 6756 } 6757 6758 _currentSettings->_realParamValues[param] = tmp_value; 6759 return true; 6760 } 6761 6762 6763 #ifdef SOPLEX_WITH_RATIONALPARAM 6764 /// sets rational parameter value; returns true on success 6765 template <class R> 6766 bool SoPlexBase<R>::setRationalParam(const RationalParam param, const Rational value, 6767 const bool init) 6768 { 6769 assert(param >= 0); 6770 assert(param < RATIONALPARAM_COUNT); 6771 assert(init || _isConsistent()); 6772 6773 if(!init && value == rationalParam(param)) 6774 return true; 6775 6776 if(value < _currentSettings->rationalParam.lower[param] 6777 || value > _currentSettings->rationalParam.upper[param]) 6778 return false; 6779 6780 switch(param) 6781 { 6782 default: 6783 // currently, there are no rational-valued parameters 6784 return false; 6785 } 6786 6787 _currentSettings->_rationalParamValues[param] = value; 6788 return true; 6789 } 6790 #endif 6791 6792 6793 6794 /// sets parameter settings; returns true on success 6795 template <class R> 6796 bool SoPlexBase<R>::setSettings(const Settings& newSettings, const bool init) 6797 { 6798 assert(init || _isConsistent()); 6799 6800 bool success = true; 6801 6802 *_currentSettings = newSettings; 6803 6804 for(int i = 0; i < SoPlexBase<R>::BOOLPARAM_COUNT; i++) 6805 success &= setBoolParam((BoolParam)i, _currentSettings->_boolParamValues[i], init); 6806 6807 for(int i = 0; i < SoPlexBase<R>::INTPARAM_COUNT; i++) 6808 success &= setIntParam((IntParam)i, _currentSettings->_intParamValues[i], init); 6809 6810 for(int i = 0; i < SoPlexBase<R>::REALPARAM_COUNT; i++) 6811 success &= setRealParam((RealParam)i, _currentSettings->_realParamValues[i], init); 6812 6813 #ifdef SOPLEX_WITH_RATIONALPARAM 6814 6815 for(int i = 0; i < SoPlexBase<R>::RATIONALPARAM_COUNT; i++) 6816 success &= setRationalParam((RationalParam)i, _currentSettings->_rationalParamValues[i], init); 6817 6818 #endif 6819 6820 assert(_isConsistent()); 6821 6822 return success; 6823 } 6824 6825 /// resets default parameter settings 6826 template <class R> 6827 void SoPlexBase<R>::resetSettings(const bool quiet, const bool init) 6828 { 6829 for(int i = 0; i < SoPlexBase<R>::BOOLPARAM_COUNT; i++) 6830 setBoolParam((BoolParam)i, _currentSettings->boolParam.defaultValue[i], init); 6831 6832 for(int i = 0; i < SoPlexBase<R>::INTPARAM_COUNT; i++) 6833 setIntParam((IntParam)i, _currentSettings->intParam.defaultValue[i], init); 6834 6835 for(int i = 0; i < SoPlexBase<R>::REALPARAM_COUNT; i++) 6836 setRealParam((RealParam)i, _currentSettings->realParam.defaultValue[i], init); 6837 6838 #ifdef SOPLEX_WITH_RATIONALPARAM 6839 6840 for(int i = 0; i < SoPlexBase<R>::RATIONALPARAM_COUNT; i++) 6841 success &= setRationalParam((RationalParam)i, _currentSettings->rationalParam.defaultValue[i], 6842 init); 6843 6844 #endif 6845 } 6846 6847 /// print non-default parameter values 6848 template <class R> 6849 void SoPlexBase<R>::printUserSettings() 6850 { 6851 bool printedValue = false; 6852 6853 SPxOut::setFixed(spxout.getCurrentStream()); 6854 6855 for(int i = 0; i < SoPlexBase<R>::BOOLPARAM_COUNT; i++) 6856 { 6857 if(_currentSettings->_boolParamValues[i] == _currentSettings->boolParam.defaultValue[i]) 6858 continue; 6859 6860 spxout << "bool:" << _currentSettings->boolParam.name[i] << " = " << 6861 (_currentSettings->_boolParamValues[i] ? "true\n" : "false\n"); 6862 printedValue = true; 6863 } 6864 6865 for(int i = 0; i < SoPlexBase<R>::INTPARAM_COUNT; i++) 6866 { 6867 if(_currentSettings->_intParamValues[i] == _currentSettings->intParam.defaultValue[i]) 6868 continue; 6869 6870 spxout << "int:" << _currentSettings->intParam.name[i] << " = " << 6871 _currentSettings->_intParamValues[i] << "\n"; 6872 printedValue = true; 6873 } 6874 6875 SPxOut::setScientific(spxout.getCurrentStream()); 6876 6877 for(int i = 0; i < SoPlexBase<R>::REALPARAM_COUNT; i++) 6878 { 6879 if(_currentSettings->_realParamValues[i] == _currentSettings->realParam.defaultValue[i]) 6880 continue; 6881 6882 spxout << "real:" << _currentSettings->realParam.name[i] << " = " << 6883 _currentSettings->_realParamValues[i] << "\n"; 6884 printedValue = true; 6885 } 6886 6887 #ifdef SOPLEX_WITH_RATIONALPARAM 6888 6889 for(int i = 0; i < SoPlexBase<R>::RATIONALPARAM_COUNT; i++) 6890 { 6891 if(_currentSettings->_rationalParamValues[i] == _currentSettings->rationalParam.defaultValue[i]) 6892 continue; 6893 6894 spxout << "rational:" << _currentSettings->rationalParam.name[i] << " = " << 6895 _currentSettings->_rationalParamValues[i] << "\n"; 6896 printedValue = true; 6897 } 6898 6899 #endif 6900 6901 if(_solver.random.getSeed() != SOPLEX_DEFAULT_RANDOM_SEED) 6902 { 6903 spxout << "uint:random_seed = " << _solver.random.getSeed() << "\n"; 6904 printedValue = true; 6905 } 6906 6907 if(printedValue) 6908 spxout << std::endl; 6909 } 6910 6911 /// prints status 6912 template <class R> 6913 void SoPlexBase<R>::printStatus(std::ostream& os, typename SPxSolverBase<R>::Status stat) 6914 { 6915 os << "SoPlex status : "; 6916 6917 switch(stat) 6918 { 6919 case SPxSolverBase<R>::ERROR: 6920 os << "error [unspecified]"; 6921 break; 6922 6923 case SPxSolverBase<R>::NO_RATIOTESTER: 6924 os << "error [no ratiotester loaded]"; 6925 break; 6926 6927 case SPxSolverBase<R>::NO_PRICER: 6928 os << "error [no pricer loaded]"; 6929 break; 6930 6931 case SPxSolverBase<R>::NO_SOLVER: 6932 os << "error [no linear solver loaded]"; 6933 break; 6934 6935 case SPxSolverBase<R>::NOT_INIT: 6936 os << "error [not initialized]"; 6937 break; 6938 6939 case SPxSolverBase<R>::ABORT_CYCLING: 6940 os << "solving aborted [cycling]"; 6941 break; 6942 6943 case SPxSolverBase<R>::ABORT_TIME: 6944 os << "solving aborted [time limit reached]"; 6945 break; 6946 6947 case SPxSolverBase<R>::ABORT_ITER: 6948 os << "solving aborted [iteration limit reached]"; 6949 break; 6950 6951 case SPxSolverBase<R>::ABORT_VALUE: 6952 os << "solving aborted [objective limit reached]"; 6953 break; 6954 6955 case SPxSolverBase<R>::NO_PROBLEM: 6956 os << "no problem loaded"; 6957 break; 6958 6959 case SPxSolverBase<R>::REGULAR: 6960 os << "basis is regular"; 6961 break; 6962 6963 case SPxSolverBase<R>::SINGULAR: 6964 os << "basis is singular"; 6965 break; 6966 6967 case SPxSolverBase<R>::OPTIMAL: 6968 os << "problem is solved [optimal]"; 6969 break; 6970 6971 case SPxSolverBase<R>::UNBOUNDED: 6972 os << "problem is solved [unbounded]"; 6973 break; 6974 6975 case SPxSolverBase<R>::INFEASIBLE: 6976 os << "problem is solved [infeasible]"; 6977 break; 6978 6979 case SPxSolverBase<R>::INForUNBD: 6980 os << "problem is solved [infeasible or unbounded]"; 6981 break; 6982 6983 case SPxSolverBase<R>::OPTIMAL_UNSCALED_VIOLATIONS: 6984 os << "problem is solved [optimal with unscaled violations]"; 6985 break; 6986 6987 default: 6988 case SPxSolverBase<R>::UNKNOWN: 6989 os << "unknown"; 6990 break; 6991 } 6992 6993 os << "\n"; 6994 } 6995 6996 6997 /// prints version and compilation options 6998 template <class R> 6999 void SoPlexBase<R>::printVersion() const 7000 { 7001 // do not use preprocessor directives within the SPX_MSG_INFO1 macro 7002 #if (SOPLEX_SUBVERSION > 0) 7003 SPX_MSG_INFO1(spxout, spxout << "SoPlex version " << SOPLEX_VERSION / 100 7004 << "." << (SOPLEX_VERSION % 100) / 10 7005 << "." << SOPLEX_VERSION % 10 7006 << "." << SOPLEX_SUBVERSION); 7007 #else 7008 SPX_MSG_INFO1(spxout, spxout << "SoPlex version " << SOPLEX_VERSION / 100 7009 << "." << (SOPLEX_VERSION % 100) / 10 7010 << "." << SOPLEX_VERSION % 10); 7011 #endif 7012 7013 #ifndef NDEBUG 7014 SPX_MSG_INFO1(spxout, spxout << " [mode: debug]"); 7015 #else 7016 SPX_MSG_INFO1(spxout, spxout << " [mode: optimized]"); 7017 #endif 7018 7019 SPX_MSG_INFO1(spxout, spxout << " [precision: " << (int)sizeof(R) << " byte]"); 7020 7021 #ifdef SOPLEX_WITH_GMP 7022 #ifdef mpir_version 7023 SPX_MSG_INFO1(spxout, spxout << " [rational: MPIR " << mpir_version << "]"); 7024 #else 7025 SPX_MSG_INFO1(spxout, spxout << " [rational: GMP " << gmp_version << "]"); 7026 #endif 7027 #else 7028 SPX_MSG_INFO1(spxout, spxout << " [rational: long double]"); 7029 #endif 7030 7031 7032 #ifdef SOPLEX_WITH_PAPILO 7033 SPX_MSG_INFO1(spxout, spxout << " [PaPILO " << PAPILO_VERSION_MAJOR << "." << PAPILO_VERSION_MINOR 7034 << "." << PAPILO_VERSION_PATCH); 7035 #ifdef PAPILO_GITHASH_AVAILABLE 7036 SPX_MSG_INFO1(spxout, spxout << " {" << PAPILO_GITHASH << "}"); 7037 #endif 7038 SPX_MSG_INFO1(spxout, spxout << "]\n"); 7039 #else 7040 SPX_MSG_INFO1(spxout, spxout << " [PaPILO: not available]"); 7041 #endif 7042 7043 SPX_MSG_INFO1(spxout, spxout << " [githash: " << getGitHash() << "]\n"); 7044 } 7045 7046 7047 /// checks if real LP and rational LP are in sync; dimensions will always be compared, 7048 /// vector and matrix values only if the respective parameter is set to true. 7049 /// If quiet is set to true the function will only display which vectors are different. 7050 template <class R> 7051 bool SoPlexBase<R>::areLPsInSync(const bool checkVecVals, const bool checkMatVals, 7052 const bool quiet) const 7053 { 7054 #ifndef SOPLEX_WITH_BOOST 7055 SPX_MSG_ERROR(std::cerr << "ERROR: rational solve without Boost not defined!" << std::endl;) 7056 return false; 7057 #else 7058 bool result = true; 7059 bool nRowsMatch = true; 7060 bool nColsMatch = true; 7061 bool rhsDimMatch = true; 7062 bool lhsDimMatch = true; 7063 bool maxObjDimMatch = true; 7064 bool upperDimMatch = true; 7065 bool lowerDimMatch = true; 7066 7067 // compare number of Rows 7068 if(_realLP->nRows() != _rationalLP->nRows()) 7069 { 7070 SPX_MSG_INFO1(spxout, spxout << 7071 "The number of Rows in the R LP does not match the one in the Rational LP." 7072 << " R LP: " << _realLP->nRows() << " Rational LP: " << _rationalLP->nRows() << std::endl); 7073 result = false; 7074 nRowsMatch = false; 7075 } 7076 7077 // compare number of Columns 7078 if(_realLP->nCols() != _rationalLP->nCols()) 7079 { 7080 SPX_MSG_INFO1(spxout, spxout << 7081 "The number of Columns in the R LP does not match the one in the Rational LP." 7082 << " R LP: " << _realLP->nCols() << " Rational LP: " << _rationalLP->nCols() << std::endl); 7083 result = false; 7084 nColsMatch = false; 7085 } 7086 7087 // compare number of nonZeros 7088 if(_realLP->nNzos() != _rationalLP->nNzos()) 7089 { 7090 SPX_MSG_INFO1(spxout, spxout << 7091 "The number of nonZeros in the R LP does not match the one in the Rational LP." 7092 << " R LP: " << _realLP->nNzos() << " Rational LP: " << _rationalLP->nNzos() << std::endl); 7093 result = false; 7094 } 7095 7096 // compare the dimensions of the right hand side vectors 7097 if(_realLP->rhs().dim() != _rationalLP->rhs().dim()) 7098 { 7099 SPX_MSG_INFO1(spxout, spxout << 7100 "The dimension of the right hand side vector of the R LP does not match the one of the Rational LP." 7101 << " R LP: " << _realLP->rhs().dim() << " Rational LP: " << _rationalLP->rhs().dim() << std::endl); 7102 result = false; 7103 rhsDimMatch = false; 7104 7105 } 7106 7107 // compare the dimensions of the left hand side vectors 7108 if(_realLP->lhs().dim() != _rationalLP->lhs().dim()) 7109 { 7110 SPX_MSG_INFO1(spxout, spxout << 7111 "The dimension of the left hand side vector of the R LP does not match the one of the Rational LP." 7112 << " R LP: " << _realLP->lhs().dim() << " Rational LP: " << _rationalLP->lhs().dim() << std::endl); 7113 result = false; 7114 lhsDimMatch = false; 7115 } 7116 7117 // compare the dimensions of the objective function vectors 7118 if(_realLP->maxObj().dim() != _rationalLP->maxObj().dim()) 7119 { 7120 SPX_MSG_INFO1(spxout, spxout << 7121 "The dimension of the objective function vector of the R LP does not match the one of the Rational LP." 7122 << " R LP: " << _realLP->maxObj().dim() << " Rational LP: " << _rationalLP->maxObj().dim() << 7123 std::endl); 7124 result = false; 7125 maxObjDimMatch = false; 7126 } 7127 7128 // compare the sense 7129 if((int)_realLP->spxSense() != (int)_rationalLP->spxSense()) 7130 { 7131 SPX_MSG_INFO1(spxout, spxout << 7132 "The objective function sense of the R LP does not match the one of the Rational LP." 7133 << " Real LP: " << (_realLP->spxSense() == SPxLPBase<R>::MINIMIZE ? "MIN" : "MAX") 7134 << " Rational LP: " << (_rationalLP->spxSense() == SPxLPRational::MINIMIZE ? "MIN" : "MAX") << 7135 std::endl); 7136 result = false; 7137 } 7138 7139 // compare the dimensions of upper bound vectors 7140 if(_realLP->upper().dim() != _rationalLP->upper().dim()) 7141 { 7142 SPX_MSG_INFO1(spxout, spxout << 7143 "The dimension of the upper bound vector of the R LP does not match the one of the Rational LP." 7144 << " R LP: " << _realLP->upper().dim() << " Rational LP: " << _rationalLP->upper().dim() << 7145 std::endl); 7146 result = false; 7147 upperDimMatch = false; 7148 } 7149 7150 // compare the dimensions of the objective function vectors 7151 if(_realLP->lower().dim() != _rationalLP->lower().dim()) 7152 { 7153 SPX_MSG_INFO1(spxout, spxout << 7154 "The dimension of the lower bound vector of the R LP does not match the one of the Rational LP." 7155 << " R LP: " << _realLP->lower().dim() << " Rational LP: " << _rationalLP->lower().dim() << 7156 std::endl); 7157 result = false; 7158 lowerDimMatch = false; 7159 } 7160 7161 // compares the values of the rhs, lhs, maxObj, upper, lower vectors 7162 if(checkVecVals) 7163 { 7164 bool rhsValMatch = true; 7165 bool lhsValMatch = true; 7166 bool maxObjValMatch = true; 7167 bool upperValMatch = true; 7168 bool lowerValMatch = true; 7169 7170 // compares the values of the right hand side vectors 7171 if(rhsDimMatch) 7172 { 7173 for(int i = 0; i < _realLP->rhs().dim(); i++) 7174 { 7175 if(((_realLP->rhs()[i] >= R(realParam(SoPlexBase<R>::INFTY))) 7176 != (_rationalLP->rhs()[i] >= _rationalPosInfty)) 7177 || (_realLP->rhs()[i] < R(realParam(SoPlexBase<R>::INFTY)) 7178 && _rationalLP->rhs()[i] < _rationalPosInfty 7179 && !isAdjacentTo(_rationalLP->rhs()[i], (double)_realLP->rhs()[i]))) 7180 { 7181 if(!quiet) 7182 { 7183 SPX_MSG_INFO1(spxout, spxout << "Entries number " << i << 7184 " of the right hand side vectors don't match." 7185 << " R LP: " << _realLP->rhs()[i] << " Rational LP: " << _rationalLP->rhs()[i] << std::endl); 7186 } 7187 7188 rhsValMatch = false; 7189 result = false; 7190 } 7191 } 7192 7193 if(!rhsValMatch && quiet) 7194 { 7195 SPX_MSG_INFO1(spxout, spxout << "The values of the right hand side vectors don't match." << 7196 std::endl); 7197 } 7198 } 7199 7200 // compares the values of the left hand side vectors 7201 if(lhsDimMatch) 7202 { 7203 for(int i = 0; i < _realLP->lhs().dim(); i++) 7204 { 7205 if(((_realLP->lhs()[i] <= R(-realParam(SoPlexBase<R>::INFTY))) 7206 != (_rationalLP->lhs()[i] <= _rationalNegInfty)) 7207 || (_realLP->lhs()[i] > R(-realParam(SoPlexBase<R>::INFTY)) 7208 && _rationalLP->lhs()[i] > _rationalNegInfty 7209 && !isAdjacentTo(_rationalLP->lhs()[i], (double)_realLP->lhs()[i]))) 7210 { 7211 if(!quiet) 7212 { 7213 SPX_MSG_INFO1(spxout, spxout << "Entries number " << i << 7214 " of the left hand side vectors don't match." 7215 << " R LP: " << _realLP->lhs()[i] << " Rational LP: " << _rationalLP->lhs()[i] << std::endl); 7216 } 7217 7218 lhsValMatch = false; 7219 result = false; 7220 } 7221 } 7222 7223 if(!lhsValMatch && quiet) 7224 { 7225 SPX_MSG_INFO1(spxout, spxout << "The values of the left hand side vectors don't match." << 7226 std::endl); 7227 } 7228 } 7229 7230 // compares the values of the objective function vectors 7231 if(maxObjDimMatch) 7232 { 7233 for(int i = 0; i < _realLP->maxObj().dim(); i++) 7234 { 7235 if(!isAdjacentTo(_rationalLP->maxObj()[i], (double)_realLP->maxObj()[i])) 7236 { 7237 if(!quiet) 7238 { 7239 SPX_MSG_INFO1(spxout, spxout << "Entries number " << i << 7240 " of the objective function vectors don't match." 7241 << " R LP: " << _realLP->maxObj()[i] << " Rational LP: " << _rationalLP->maxObj()[i] << std::endl); 7242 } 7243 7244 maxObjValMatch = false; 7245 result = false; 7246 } 7247 } 7248 7249 if(!maxObjValMatch && quiet) 7250 { 7251 SPX_MSG_INFO1(spxout, spxout << "The values of the objective function vectors don't match." << 7252 std::endl); 7253 } 7254 } 7255 7256 // compares the values of the upper bound vectors 7257 if(upperDimMatch) 7258 { 7259 for(int i = 0; i < _realLP->upper().dim(); i++) 7260 { 7261 if(((_realLP->upper()[i] >= R(realParam(SoPlexBase<R>::INFTY))) 7262 != (_rationalLP->upper()[i] >= _rationalPosInfty)) 7263 || (_realLP->upper()[i] < R(realParam(SoPlexBase<R>::INFTY)) 7264 && _rationalLP->upper()[i] < _rationalPosInfty 7265 && !isAdjacentTo(_rationalLP->upper()[i], (double)_realLP->upper()[i]))) 7266 { 7267 if(!quiet) 7268 { 7269 SPX_MSG_INFO1(spxout, spxout << "Entries number " << i << " of the upper bound vectors don't match." 7270 << " R LP: " << _realLP->upper()[i] << " Rational LP: " << _rationalLP->upper()[i] << std::endl); 7271 } 7272 7273 upperValMatch = false; 7274 result = false; 7275 } 7276 } 7277 7278 if(!upperValMatch && quiet) 7279 { 7280 SPX_MSG_INFO1(spxout, spxout << "The values of the upper bound vectors don't match." << std::endl); 7281 } 7282 } 7283 7284 // compares the values of the lower bound vectors 7285 if(lowerDimMatch) 7286 { 7287 for(int i = 0; i < _realLP->lower().dim(); i++) 7288 { 7289 if(((_realLP->lower()[i] <= R(-realParam(SoPlexBase<R>::INFTY))) 7290 != (_rationalLP->lower()[i] <= _rationalNegInfty)) 7291 || (_realLP->lower()[i] >= R(-realParam(SoPlexBase<R>::INFTY)) 7292 && _rationalLP->lower()[i] > _rationalNegInfty 7293 && !isAdjacentTo(_rationalLP->lower()[i], (double)_realLP->lower()[i]))) 7294 { 7295 if(!quiet) 7296 { 7297 SPX_MSG_INFO1(spxout, spxout << "Entries number " << i << " of the lower bound vectors don't match." 7298 << " R LP: " << _realLP->lower()[i] << " Rational LP: " << _rationalLP->lower()[i] << std::endl); 7299 } 7300 7301 lowerValMatch = false; 7302 result = false; 7303 } 7304 } 7305 7306 if(!lowerValMatch && quiet) 7307 { 7308 SPX_MSG_INFO1(spxout, spxout << "The values of the lower bound vectors don't match." << std::endl); 7309 } 7310 } 7311 } 7312 7313 // compare the values of the matrix 7314 if(checkMatVals && nRowsMatch && nColsMatch) 7315 { 7316 bool matrixValMatch = true; 7317 7318 for(int i = 0; i < _realLP->nCols() ; i++) 7319 { 7320 for(int j = 0; j < _realLP->nRows() ; j++) 7321 { 7322 if(!isAdjacentTo(_rationalLP->colVector(i)[j], (double)_realLP->colVector(i)[j])) 7323 { 7324 if(!quiet) 7325 { 7326 SPX_MSG_INFO1(spxout, spxout << "Entries number " << j << " of column number " << i << 7327 " don't match." 7328 << " R LP: " << _realLP->colVector(i)[j] << " Rational LP: " << _rationalLP->colVector( 7329 i)[j] << std::endl); 7330 } 7331 7332 matrixValMatch = false; 7333 result = false; 7334 } 7335 } 7336 } 7337 7338 if(!matrixValMatch && quiet) 7339 { 7340 SPX_MSG_INFO1(spxout, spxout << "The values of the matrices don't match." << std::endl); 7341 } 7342 } 7343 7344 return result; 7345 #endif 7346 } 7347 7348 7349 7350 /// set the random seed of the solver instance 7351 template <class R> 7352 void SoPlexBase<R>::setRandomSeed(unsigned int seed) 7353 { 7354 _solver.random.setSeed(seed); 7355 } 7356 7357 7358 7359 /// returns the current random seed of the solver instance or the one stored in the settings 7360 template <class R> 7361 unsigned int SoPlexBase<R>::randomSeed() const 7362 { 7363 return _solver.random.getSeed(); 7364 } 7365 7366 7367 7368 /// extends sparse vector to hold newmax entries if and only if it holds no more free entries 7369 template <class R> 7370 void SoPlexBase<R>::_ensureDSVectorRationalMemory(DSVectorRational& vec, const int newmax) const 7371 { 7372 assert(newmax > vec.size()); 7373 7374 if(vec.size() >= vec.max()) 7375 vec.setMax(newmax); 7376 } 7377 7378 7379 7380 /// creates a permutation for removing rows/columns from an array of indices 7381 template <class R> 7382 void SoPlexBase<R>::_idxToPerm(int* idx, int idxSize, int* perm, int permSize) const 7383 { 7384 assert(idx != 0); 7385 assert(idxSize >= 0); 7386 assert(perm != 0); 7387 assert(permSize >= 0); 7388 7389 for(int i = 0; i < permSize; i++) 7390 perm[i] = i; 7391 7392 for(int i = 0; i < idxSize; i++) 7393 { 7394 assert(idx[i] >= 0); 7395 assert(idx[i] < permSize); 7396 perm[idx[i]] = -1; 7397 } 7398 } 7399 7400 7401 7402 /// creates a permutation for removing rows/columns from a range of indices 7403 template <class R> 7404 void SoPlexBase<R>::_rangeToPerm(int start, int end, int* perm, int permSize) const 7405 { 7406 assert(perm != 0); 7407 assert(permSize >= 0); 7408 7409 for(int i = 0; i < permSize; i++) 7410 perm[i] = (i < start || i > end) ? i : -1; 7411 } 7412 7413 7414 /// checks consistency 7415 template <class R> 7416 bool SoPlexBase<R>::_isBoostedConsistent() const 7417 { 7418 assert(_statistics != 0); 7419 assert(_currentSettings != 0); 7420 7421 assert(_rationalLP != 0 || intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL); 7422 7423 ///@todo precision-boosting _realLP not used in _boostedSolver 7424 #ifdef SOPLEX_DISABLED_CODE 7425 assert(_realLP != 0); 7426 7427 assert(_realLP != &_boostedSolver || _isRealLPLoaded); 7428 assert(_realLP == &_boostedSolver || !_isRealLPLoaded); 7429 7430 assert(!_hasBasis || _isRealLPLoaded || _basisStatusRows.size() == numRows()); 7431 assert(!_hasBasis || _isRealLPLoaded || _basisStatusCols.size() == numCols()); 7432 #endif 7433 7434 assert(!_hasBasis || _basisStatusRows.size() == numRows()); 7435 assert(!_hasBasis || _basisStatusCols.size() == numCols()); 7436 7437 assert(_rationalLUSolver.status() == SLinSolverRational::UNLOADED || _hasBasis); 7438 assert(_rationalLUSolver.status() == SLinSolverRational::UNLOADED 7439 || _rationalLUSolver.dim() == _rationalLUSolverBind.size()); 7440 assert(_rationalLUSolver.status() == SLinSolverRational::UNLOADED 7441 || _rationalLUSolver.dim() == numRowsRational()); 7442 7443 assert(_rationalLP == 0 || _colTypes.size() == numColsRational()); 7444 assert(_rationalLP == 0 || _rowTypes.size() == numRowsRational()); 7445 7446 return true; 7447 } 7448 7449 7450 /// checks consistency 7451 template <class R> 7452 bool SoPlexBase<R>::_isConsistent() const 7453 { 7454 assert(_statistics != 0); 7455 assert(_currentSettings != 0); 7456 7457 assert(_realLP != 0); 7458 assert(_rationalLP != 0 || intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL); 7459 7460 assert(_realLP != &_solver || _isRealLPLoaded); 7461 assert(_realLP == &_solver || !_isRealLPLoaded); 7462 7463 assert(!_hasBasis || _isRealLPLoaded || _basisStatusRows.size() == numRows()); 7464 assert(!_hasBasis || _isRealLPLoaded || _basisStatusCols.size() == numCols()); 7465 assert(_rationalLUSolver.status() == SLinSolverRational::UNLOADED || _hasBasis); 7466 assert(_rationalLUSolver.status() == SLinSolverRational::UNLOADED 7467 || _rationalLUSolver.dim() == _rationalLUSolverBind.size()); 7468 assert(_rationalLUSolver.status() == SLinSolverRational::UNLOADED 7469 || _rationalLUSolver.dim() == numRowsRational()); 7470 7471 assert(_rationalLP == 0 || _colTypes.size() == numColsRational()); 7472 assert(_rationalLP == 0 || _rowTypes.size() == numRowsRational()); 7473 7474 return true; 7475 } 7476 7477 7478 7479 /// should solving process be stopped? 7480 template <class R> 7481 bool SoPlexBase<R>::_isSolveStopped(bool& stoppedTime, bool& stoppedIter) const 7482 { 7483 assert(_statistics != 0); 7484 7485 stoppedTime = (realParam(TIMELIMIT) < realParam(INFTY) 7486 && _statistics->solvingTime->time() >= realParam(TIMELIMIT)); 7487 stoppedIter = (intParam(ITERLIMIT) >= 0 && _statistics->iterations >= intParam(ITERLIMIT)) 7488 || (intParam(REFLIMIT) >= 0 && _statistics->refinements >= intParam(REFLIMIT)) 7489 || (intParam(STALLREFLIMIT) >= 0 && _statistics->stallRefinements >= intParam(STALLREFLIMIT)); 7490 7491 return stoppedTime || stoppedIter; 7492 } 7493 7494 7495 7496 /// determines RangeType from real bounds 7497 template <class R> 7498 typename SoPlexBase<R>::RangeType SoPlexBase<R>::_rangeTypeReal(const R& lower, 7499 const R& upper) const 7500 { 7501 assert(lower <= upper); 7502 7503 if(lower <= R(-infinity)) 7504 { 7505 if(upper >= R(infinity)) 7506 return RANGETYPE_FREE; 7507 else 7508 return RANGETYPE_UPPER; 7509 } 7510 else 7511 { 7512 if(upper >= R(infinity)) 7513 return RANGETYPE_LOWER; 7514 else if(lower == upper) 7515 return RANGETYPE_FIXED; 7516 else 7517 return RANGETYPE_BOXED; 7518 } 7519 } 7520 7521 7522 7523 /// determines RangeType from rational bounds 7524 template <class R> 7525 typename SoPlexBase<R>::RangeType SoPlexBase<R>::_rangeTypeRational(const Rational& lower, 7526 const Rational& upper) const 7527 { 7528 assert(lower <= upper); 7529 7530 if(lower <= _rationalNegInfty) 7531 { 7532 if(upper >= _rationalPosInfty) 7533 return RANGETYPE_FREE; 7534 else 7535 return RANGETYPE_UPPER; 7536 } 7537 else 7538 { 7539 if(upper >= _rationalPosInfty) 7540 return RANGETYPE_LOWER; 7541 else if(lower == upper) 7542 return RANGETYPE_FIXED; 7543 else 7544 return RANGETYPE_BOXED; 7545 } 7546 } 7547 7548 7549 7550 /// switches RANGETYPE_LOWER to RANGETYPE_UPPER and vice versa 7551 template <class R> 7552 typename SoPlexBase<R>::RangeType SoPlexBase<R>::_switchRangeType(const typename 7553 SoPlexBase<R>::RangeType& 7554 rangeType) const 7555 { 7556 if(rangeType == RANGETYPE_LOWER) 7557 return RANGETYPE_UPPER; 7558 else if(rangeType == RANGETYPE_UPPER) 7559 return RANGETYPE_LOWER; 7560 else 7561 return rangeType; 7562 } 7563 7564 7565 7566 /// checks whether RangeType corresponds to finite lower bound 7567 template <class R> 7568 bool SoPlexBase<R>::_lowerFinite(const RangeType& rangeType) const 7569 { 7570 return (rangeType == RANGETYPE_LOWER || rangeType == RANGETYPE_BOXED 7571 || rangeType == RANGETYPE_FIXED); 7572 } 7573 7574 7575 7576 /// checks whether RangeType corresponds to finite upper bound 7577 template <class R> 7578 bool SoPlexBase<R>::_upperFinite(const RangeType& rangeType) const 7579 { 7580 return (rangeType == RANGETYPE_UPPER || rangeType == RANGETYPE_BOXED 7581 || rangeType == RANGETYPE_FIXED); 7582 } 7583 7584 7585 7586 /// adds a single row to the R LP and adjusts basis 7587 template <class R> 7588 void SoPlexBase<R>::_addRowReal(const LPRowBase<R>& lprow) 7589 { 7590 assert(_realLP != 0); 7591 7592 bool scale = _realLP->isScaled(); 7593 _realLP->addRow(lprow, scale); 7594 7595 if(_isRealLPLoaded) 7596 _hasBasis = (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM); 7597 else if(_hasBasis) 7598 _basisStatusRows.append(SPxSolverBase<R>::BASIC); 7599 7600 _rationalLUSolver.clear(); 7601 } 7602 7603 7604 7605 /// adds a single row to the R LP and adjusts basis 7606 template <class R> 7607 void SoPlexBase<R>::_addRowReal(R lhs, const SVectorBase<R>& lprow, R rhs) 7608 { 7609 assert(_realLP != 0); 7610 7611 bool scale = _realLP->isScaled(); 7612 _realLP->addRow(lhs, lprow, rhs, scale); 7613 7614 if(_isRealLPLoaded) 7615 _hasBasis = (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM); 7616 else if(_hasBasis) 7617 _basisStatusRows.append(SPxSolverBase<R>::BASIC); 7618 7619 _rationalLUSolver.clear(); 7620 } 7621 7622 7623 7624 /// adds multiple rows to the R LP and adjusts basis 7625 template <class R> 7626 void SoPlexBase<R>::_addRowsReal(const LPRowSetBase<R>& lprowset) 7627 { 7628 assert(_realLP != 0); 7629 7630 bool scale = _realLP->isScaled(); 7631 _realLP->addRows(lprowset, scale); 7632 7633 if(_isRealLPLoaded) 7634 _hasBasis = (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM); 7635 else if(_hasBasis) 7636 _basisStatusRows.append(lprowset.num(), SPxSolverBase<R>::BASIC); 7637 7638 _rationalLUSolver.clear(); 7639 } 7640 7641 7642 /// adds a single column to the R LP and adjusts basis 7643 template <class R> 7644 void SoPlexBase<R>::_addColReal(const LPColReal& lpcol) 7645 { 7646 assert(_realLP != 0); 7647 7648 bool scale = _realLP->isScaled(); 7649 _realLP->addCol(lpcol, scale); 7650 7651 if(_isRealLPLoaded) 7652 _hasBasis = (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM); 7653 else if(_hasBasis) 7654 { 7655 if(lpcol.lower() > -realParam(SoPlexBase<R>::INFTY)) 7656 _basisStatusCols.append(SPxSolverBase<R>::ON_LOWER); 7657 else if(lpcol.upper() < realParam(SoPlexBase<R>::INFTY)) 7658 _basisStatusCols.append(SPxSolverBase<R>::ON_UPPER); 7659 else 7660 _basisStatusCols.append(SPxSolverBase<R>::ZERO); 7661 } 7662 7663 _rationalLUSolver.clear(); 7664 } 7665 7666 7667 7668 /// adds a single column to the R LP and adjusts basis 7669 template <class R> 7670 void SoPlexBase<R>::_addColReal(R obj, R lower, const SVectorBase<R>& lpcol, R upper) 7671 { 7672 assert(_realLP != 0); 7673 7674 bool scale = _realLP->isScaled(); 7675 _realLP->addCol(obj, lower, lpcol, upper, scale); 7676 7677 if(_isRealLPLoaded) 7678 _hasBasis = (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM); 7679 else if(_hasBasis) 7680 _basisStatusRows.append(SPxSolverBase<R>::BASIC); 7681 7682 _rationalLUSolver.clear(); 7683 } 7684 7685 7686 /// adds multiple columns to the R LP and adjusts basis 7687 template <class R> 7688 void SoPlexBase<R>::_addColsReal(const LPColSetReal& lpcolset) 7689 { 7690 assert(_realLP != 0); 7691 7692 bool scale = _realLP->isScaled(); 7693 _realLP->addCols(lpcolset, scale); 7694 7695 if(_isRealLPLoaded) 7696 _hasBasis = (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM); 7697 else if(_hasBasis) 7698 { 7699 for(int i = 0; i < lpcolset.num(); i++) 7700 { 7701 if(lpcolset.lower(i) > -realParam(SoPlexBase<R>::INFTY)) 7702 _basisStatusCols.append(SPxSolverBase<R>::ON_LOWER); 7703 else if(lpcolset.upper(i) < realParam(SoPlexBase<R>::INFTY)) 7704 _basisStatusCols.append(SPxSolverBase<R>::ON_UPPER); 7705 else 7706 _basisStatusCols.append(SPxSolverBase<R>::ZERO); 7707 } 7708 } 7709 7710 _rationalLUSolver.clear(); 7711 } 7712 7713 7714 /// replaces row \p i with \p lprow and adjusts basis 7715 template <class R> 7716 void SoPlexBase<R>::_changeRowReal(int i, const LPRowBase<R>& lprow) 7717 { 7718 assert(_realLP != 0); 7719 7720 bool scale = _realLP->isScaled(); 7721 _realLP->changeRow(i, lprow, scale); 7722 7723 if(_isRealLPLoaded) 7724 _hasBasis = (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM); 7725 else if(_hasBasis) 7726 { 7727 if(_basisStatusRows[i] != SPxSolverBase<R>::BASIC) 7728 _hasBasis = false; 7729 else if(_basisStatusRows[i] == SPxSolverBase<R>::ON_LOWER 7730 && lprow.lhs() <= -realParam(SoPlexBase<R>::INFTY)) 7731 _basisStatusRows[i] = (lprow.rhs() < realParam(SoPlexBase<R>::INFTY)) ? SPxSolverBase<R>::ON_UPPER : 7732 SPxSolverBase<R>::ZERO; 7733 else if(_basisStatusRows[i] == SPxSolverBase<R>::ON_UPPER 7734 && lprow.rhs() >= realParam(SoPlexBase<R>::INFTY)) 7735 _basisStatusRows[i] = (lprow.lhs() > -realParam(SoPlexBase<R>::INFTY)) ? 7736 SPxSolverBase<R>::ON_LOWER : SPxSolverBase<R>::ZERO; 7737 } 7738 7739 _rationalLUSolver.clear(); 7740 } 7741 7742 7743 7744 /// changes left-hand side vector for constraints to \p lhs and adjusts basis 7745 template <class R> 7746 void SoPlexBase<R>::_changeLhsReal(const VectorBase<R>& lhs) 7747 { 7748 assert(_realLP != 0); 7749 7750 bool scale = _realLP->isScaled(); 7751 _realLP->changeLhs(lhs, scale); 7752 7753 if(_isRealLPLoaded) 7754 _hasBasis = (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM); 7755 else if(_hasBasis) 7756 { 7757 for(int i = numRows() - 1; i >= 0; i--) 7758 { 7759 if(_basisStatusRows[i] == SPxSolverBase<R>::ON_LOWER && lhs[i] <= -realParam(SoPlexBase<R>::INFTY)) 7760 _basisStatusRows[i] = (rhsReal(i) < realParam(SoPlexBase<R>::INFTY)) ? SPxSolverBase<R>::ON_UPPER : 7761 SPxSolverBase<R>::ZERO; 7762 } 7763 } 7764 7765 _rationalLUSolver.clear(); 7766 } 7767 7768 /// changes left-hand side of row \p i to \p lhs and adjusts basis 7769 template <class R> 7770 void SoPlexBase<R>::_changeLhsReal(int i, const R& lhs) 7771 { 7772 assert(_realLP != 0); 7773 7774 bool scale = _realLP->isScaled(); 7775 _realLP->changeLhs(i, lhs, scale); 7776 7777 if(_isRealLPLoaded) 7778 { 7779 _hasBasis = (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM); 7780 } 7781 else if(_hasBasis && _basisStatusRows[i] == SPxSolverBase<R>::ON_LOWER 7782 && lhs <= -realParam(SoPlexBase<R>::INFTY)) 7783 _basisStatusRows[i] = (rhsReal(i) < realParam(SoPlexBase<R>::INFTY)) ? SPxSolverBase<R>::ON_UPPER : 7784 SPxSolverBase<R>::ZERO; 7785 7786 _rationalLUSolver.clear(); 7787 } 7788 7789 7790 7791 /// changes right-hand side vector to \p rhs and adjusts basis 7792 template <class R> 7793 void SoPlexBase<R>::_changeRhsReal(const VectorBase<R>& rhs) 7794 { 7795 assert(_realLP != 0); 7796 7797 bool scale = _realLP->isScaled(); 7798 _realLP->changeRhs(rhs, scale); 7799 7800 if(_isRealLPLoaded) 7801 { 7802 _hasBasis = (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM); 7803 } 7804 else if(_hasBasis) 7805 { 7806 for(int i = numRows() - 1; i >= 0; i--) 7807 { 7808 if(_basisStatusRows[i] == SPxSolverBase<R>::ON_UPPER && rhs[i] >= realParam(SoPlexBase<R>::INFTY)) 7809 _basisStatusRows[i] = (lhsReal(i) > -realParam(SoPlexBase<R>::INFTY)) ? SPxSolverBase<R>::ON_LOWER : 7810 SPxSolverBase<R>::ZERO; 7811 } 7812 } 7813 7814 _rationalLUSolver.clear(); 7815 } 7816 7817 7818 7819 /// changes right-hand side of row \p i to \p rhs and adjusts basis 7820 template <class R> 7821 void SoPlexBase<R>::_changeRhsReal(int i, const R& rhs) 7822 { 7823 assert(_realLP != 0); 7824 7825 bool scale = _realLP->isScaled(); 7826 _realLP->changeRhs(i, rhs, scale); 7827 7828 if(_isRealLPLoaded) 7829 { 7830 _hasBasis = (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM); 7831 } 7832 else if(_hasBasis && _basisStatusRows[i] == SPxSolverBase<R>::ON_UPPER 7833 && rhs >= realParam(SoPlexBase<R>::INFTY)) 7834 _basisStatusRows[i] = (lhsReal(i) > -realParam(SoPlexBase<R>::INFTY)) ? SPxSolverBase<R>::ON_LOWER : 7835 SPxSolverBase<R>::ZERO; 7836 7837 _rationalLUSolver.clear(); 7838 } 7839 7840 7841 7842 /// changes left- and right-hand side vectors and adjusts basis 7843 template <class R> 7844 void SoPlexBase<R>::_changeRangeReal(const VectorBase<R>& lhs, const VectorBase<R>& rhs) 7845 { 7846 assert(_realLP != 0); 7847 7848 bool scale = _realLP->isScaled(); 7849 _realLP->changeRange(lhs, rhs, scale); 7850 7851 if(_isRealLPLoaded) 7852 { 7853 _hasBasis = (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM); 7854 } 7855 else if(_hasBasis) 7856 { 7857 for(int i = numRows() - 1; i >= 0; i--) 7858 { 7859 if(_basisStatusRows[i] == SPxSolverBase<R>::ON_LOWER && lhs[i] <= -realParam(SoPlexBase<R>::INFTY)) 7860 _basisStatusRows[i] = (rhs[i] < realParam(SoPlexBase<R>::INFTY)) ? SPxSolverBase<R>::ON_UPPER : 7861 SPxSolverBase<R>::ZERO; 7862 else if(_basisStatusRows[i] == SPxSolverBase<R>::ON_UPPER 7863 && rhs[i] >= realParam(SoPlexBase<R>::INFTY)) 7864 _basisStatusRows[i] = (lhs[i] > -realParam(SoPlexBase<R>::INFTY)) ? SPxSolverBase<R>::ON_LOWER : 7865 SPxSolverBase<R>::ZERO; 7866 } 7867 } 7868 7869 _rationalLUSolver.clear(); 7870 } 7871 7872 7873 7874 /// changes left- and right-hand side of row \p i and adjusts basis 7875 template <class R> 7876 void SoPlexBase<R>::_changeRangeReal(int i, const R& lhs, const R& rhs) 7877 { 7878 assert(_realLP != 0); 7879 7880 bool scale = _realLP->isScaled(); 7881 _realLP->changeRange(i, lhs, rhs, scale); 7882 7883 if(_isRealLPLoaded) 7884 { 7885 _hasBasis = (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM); 7886 } 7887 else if(_hasBasis) 7888 { 7889 if(_basisStatusRows[i] == SPxSolverBase<R>::ON_LOWER && lhs <= -realParam(SoPlexBase<R>::INFTY)) 7890 _basisStatusRows[i] = (rhs < realParam(SoPlexBase<R>::INFTY)) ? SPxSolverBase<R>::ON_UPPER : 7891 SPxSolverBase<R>::ZERO; 7892 else if(_basisStatusRows[i] == SPxSolverBase<R>::ON_UPPER && rhs >= realParam(SoPlexBase<R>::INFTY)) 7893 _basisStatusRows[i] = (lhs > -realParam(SoPlexBase<R>::INFTY)) ? SPxSolverBase<R>::ON_LOWER : 7894 SPxSolverBase<R>::ZERO; 7895 } 7896 7897 _rationalLUSolver.clear(); 7898 } 7899 7900 7901 7902 /// replaces column \p i with \p lpcol and adjusts basis 7903 template <class R> 7904 void SoPlexBase<R>::_changeColReal(int i, const LPColReal& lpcol) 7905 { 7906 assert(_realLP != 0); 7907 7908 bool scale = _realLP->isScaled(); 7909 _realLP->changeCol(i, lpcol, scale); 7910 7911 if(_isRealLPLoaded) 7912 { 7913 _hasBasis = (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM); 7914 } 7915 else if(_hasBasis) 7916 { 7917 if(_basisStatusCols[i] == SPxSolverBase<R>::BASIC) 7918 _hasBasis = false; 7919 else if(_basisStatusCols[i] == SPxSolverBase<R>::ON_LOWER 7920 && lpcol.lower() <= -realParam(SoPlexBase<R>::INFTY)) 7921 _basisStatusCols[i] = (lpcol.upper() < realParam(SoPlexBase<R>::INFTY)) ? 7922 SPxSolverBase<R>::ON_UPPER : SPxSolverBase<R>::ZERO; 7923 else if(_basisStatusCols[i] == SPxSolverBase<R>::ON_UPPER 7924 && lpcol.upper() >= realParam(SoPlexBase<R>::INFTY)) 7925 _basisStatusCols[i] = (lpcol.lower() > -realParam(SoPlexBase<R>::INFTY)) ? 7926 SPxSolverBase<R>::ON_LOWER : SPxSolverBase<R>::ZERO; 7927 } 7928 7929 _rationalLUSolver.clear(); 7930 } 7931 7932 7933 7934 /// changes vector of lower bounds to \p lower and adjusts basis 7935 template <class R> 7936 void SoPlexBase<R>::_changeLowerReal(const VectorBase<R>& lower) 7937 { 7938 assert(_realLP != 0); 7939 7940 bool scale = _realLP->isScaled(); 7941 _realLP->changeLower(lower, scale); 7942 7943 if(_isRealLPLoaded) 7944 { 7945 _hasBasis = (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM); 7946 } 7947 else if(_hasBasis) 7948 { 7949 for(int i = numCols() - 1; i >= 0; i--) 7950 { 7951 if(_basisStatusCols[i] == SPxSolverBase<R>::ON_LOWER 7952 && lower[i] <= -realParam(SoPlexBase<R>::INFTY)) 7953 _basisStatusCols[i] = (upperReal(i) < realParam(SoPlexBase<R>::INFTY)) ? 7954 SPxSolverBase<R>::ON_UPPER : SPxSolverBase<R>::ZERO; 7955 } 7956 } 7957 7958 _rationalLUSolver.clear(); 7959 } 7960 7961 7962 7963 /// changes lower bound of column i to \p lower and adjusts basis 7964 template <class R> 7965 void SoPlexBase<R>::_changeLowerReal(int i, const R& lower) 7966 { 7967 assert(_realLP != 0); 7968 7969 bool scale = _realLP->isScaled(); 7970 _realLP->changeLower(i, lower, scale); 7971 7972 if(_isRealLPLoaded) 7973 { 7974 _hasBasis = (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM); 7975 } 7976 else if(_hasBasis && _basisStatusCols[i] == SPxSolverBase<R>::ON_LOWER 7977 && lower <= -realParam(SoPlexBase<R>::INFTY)) 7978 _basisStatusCols[i] = (upperReal(i) < realParam(SoPlexBase<R>::INFTY)) ? 7979 SPxSolverBase<R>::ON_UPPER : SPxSolverBase<R>::ZERO; 7980 7981 _rationalLUSolver.clear(); 7982 } 7983 7984 7985 7986 /// changes vector of upper bounds to \p upper and adjusts basis 7987 template <class R> 7988 void SoPlexBase<R>::_changeUpperReal(const VectorBase<R>& upper) 7989 { 7990 assert(_realLP != 0); 7991 7992 bool scale = _realLP->isScaled(); 7993 _realLP->changeUpper(upper, scale); 7994 7995 if(_isRealLPLoaded) 7996 { 7997 _hasBasis = (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM); 7998 } 7999 else if(_hasBasis) 8000 { 8001 for(int i = numCols() - 1; i >= 0; i--) 8002 { 8003 if(_basisStatusCols[i] == SPxSolverBase<R>::ON_UPPER && upper[i] >= realParam(SoPlexBase<R>::INFTY)) 8004 _basisStatusCols[i] = (lowerReal(i) > -realParam(SoPlexBase<R>::INFTY)) ? 8005 SPxSolverBase<R>::ON_LOWER : SPxSolverBase<R>::ZERO; 8006 } 8007 } 8008 8009 _rationalLUSolver.clear(); 8010 } 8011 8012 8013 8014 /// changes \p i 'th upper bound to \p upper and adjusts basis 8015 template <class R> 8016 void SoPlexBase<R>::_changeUpperReal(int i, const R& upper) 8017 { 8018 assert(_realLP != 0); 8019 8020 bool scale = _realLP->isScaled(); 8021 _realLP->changeUpper(i, upper, scale); 8022 8023 if(_isRealLPLoaded) 8024 { 8025 _hasBasis = (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM); 8026 } 8027 else if(_hasBasis && _basisStatusCols[i] == SPxSolverBase<R>::ON_UPPER 8028 && upper >= realParam(SoPlexBase<R>::INFTY)) 8029 _basisStatusCols[i] = (lowerReal(i) > -realParam(SoPlexBase<R>::INFTY)) ? 8030 SPxSolverBase<R>::ON_LOWER : SPxSolverBase<R>::ZERO; 8031 8032 _rationalLUSolver.clear(); 8033 } 8034 8035 8036 8037 /// changes vectors of column bounds to \p lower and \p upper and adjusts basis 8038 template <class R> 8039 void SoPlexBase<R>::_changeBoundsReal(const VectorBase<R>& lower, const VectorBase<R>& upper) 8040 { 8041 assert(_realLP != 0); 8042 8043 bool scale = _realLP->isScaled(); 8044 _realLP->changeBounds(lower, upper, scale); 8045 8046 if(_isRealLPLoaded) 8047 { 8048 _hasBasis = (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM); 8049 } 8050 else if(_hasBasis) 8051 { 8052 for(int i = numCols() - 1; i >= 0; i--) 8053 { 8054 if(_basisStatusCols[i] == SPxSolverBase<R>::ON_LOWER 8055 && lower[i] <= -realParam(SoPlexBase<R>::INFTY)) 8056 _basisStatusCols[i] = (upper[i] < realParam(SoPlexBase<R>::INFTY)) ? SPxSolverBase<R>::ON_UPPER : 8057 SPxSolverBase<R>::ZERO; 8058 else if(_basisStatusCols[i] == SPxSolverBase<R>::ON_UPPER 8059 && upper[i] >= realParam(SoPlexBase<R>::INFTY)) 8060 _basisStatusCols[i] = (lower[i] > -realParam(SoPlexBase<R>::INFTY)) ? SPxSolverBase<R>::ON_LOWER : 8061 SPxSolverBase<R>::ZERO; 8062 } 8063 } 8064 8065 _rationalLUSolver.clear(); 8066 } 8067 8068 8069 8070 /// changes bounds of column \p i to \p lower and \p upper and adjusts basis 8071 template <class R> 8072 void SoPlexBase<R>::_changeBoundsReal(int i, const R& lower, const R& upper) 8073 { 8074 assert(_realLP != 0); 8075 8076 bool scale = _realLP->isScaled(); 8077 _realLP->changeBounds(i, lower, upper, scale); 8078 8079 if(_isRealLPLoaded) 8080 { 8081 _hasBasis = (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM); 8082 } 8083 else if(_hasBasis) 8084 { 8085 if(_basisStatusCols[i] == SPxSolverBase<R>::ON_LOWER && lower <= -realParam(SoPlexBase<R>::INFTY)) 8086 _basisStatusCols[i] = (upper < realParam(SoPlexBase<R>::INFTY)) ? SPxSolverBase<R>::ON_UPPER : 8087 SPxSolverBase<R>::ZERO; 8088 else if(_basisStatusCols[i] == SPxSolverBase<R>::ON_UPPER 8089 && upper >= realParam(SoPlexBase<R>::INFTY)) 8090 _basisStatusCols[i] = (lower > -realParam(SoPlexBase<R>::INFTY)) ? SPxSolverBase<R>::ON_LOWER : 8091 SPxSolverBase<R>::ZERO; 8092 } 8093 8094 _rationalLUSolver.clear(); 8095 } 8096 8097 8098 8099 /// changes matrix entry in row \p i and column \p j to \p val and adjusts basis 8100 template <class R> 8101 void SoPlexBase<R>::_changeElementReal(int i, int j, const R& val) 8102 { 8103 assert(_realLP != 0); 8104 8105 bool scale = _realLP->isScaled(); 8106 _realLP->changeElement(i, j, val, scale); 8107 8108 if(_isRealLPLoaded) 8109 { 8110 _hasBasis = (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM); 8111 } 8112 else if(_hasBasis) 8113 { 8114 if(_basisStatusRows[i] != SPxSolverBase<R>::BASIC && _basisStatusCols[i] == SPxSolverBase<R>::BASIC) 8115 _hasBasis = false; 8116 } 8117 8118 _rationalLUSolver.clear(); 8119 } 8120 8121 8122 8123 /// removes row \p i and adjusts basis 8124 template <class R> 8125 void SoPlexBase<R>::_removeRowReal(int i) 8126 { 8127 assert(_realLP != 0); 8128 8129 _realLP->removeRow(i); 8130 8131 if(_isRealLPLoaded) 8132 { 8133 _hasBasis = (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM); 8134 } 8135 else if(_hasBasis) 8136 { 8137 if(_basisStatusRows[i] != SPxSolverBase<R>::BASIC) 8138 _hasBasis = false; 8139 else 8140 { 8141 _basisStatusRows[i] = _basisStatusRows[_basisStatusRows.size() - 1]; 8142 _basisStatusRows.removeLast(); 8143 } 8144 } 8145 8146 _rationalLUSolver.clear(); 8147 } 8148 8149 8150 8151 /// removes all rows with an index \p i such that \p perm[i] < 0; upon completion, \p perm[i] >= 0 indicates the 8152 /// new index where row \p i has been moved to; note that \p perm must point to an array of size at least 8153 /// #numRows() 8154 template <class R> 8155 void SoPlexBase<R>::_removeRowsReal(int perm[]) 8156 { 8157 assert(_realLP != 0); 8158 8159 _realLP->removeRows(perm); 8160 8161 if(_isRealLPLoaded) 8162 { 8163 _hasBasis = (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM); 8164 } 8165 else if(_hasBasis) 8166 { 8167 for(int i = numRows() - 1; i >= 0 && _hasBasis; i--) 8168 { 8169 if(perm[i] < 0 && _basisStatusRows[i] != SPxSolverBase<R>::BASIC) 8170 _hasBasis = false; 8171 else if(perm[i] >= 0 && perm[i] != i) 8172 { 8173 assert(perm[i] < numRows()); 8174 assert(perm[perm[i]] < 0); 8175 8176 _basisStatusRows[perm[i]] = _basisStatusRows[i]; 8177 } 8178 } 8179 8180 if(_hasBasis) 8181 _basisStatusRows.reSize(numRows()); 8182 } 8183 8184 _rationalLUSolver.clear(); 8185 } 8186 8187 8188 8189 /// removes column i 8190 template <class R> 8191 void SoPlexBase<R>::_removeColReal(int i) 8192 { 8193 assert(_realLP != 0); 8194 8195 _realLP->removeCol(i); 8196 8197 if(_isRealLPLoaded) 8198 { 8199 _hasBasis = (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM); 8200 } 8201 else if(_hasBasis) 8202 { 8203 if(_basisStatusCols[i] == SPxSolverBase<R>::BASIC) 8204 _hasBasis = false; 8205 else 8206 { 8207 _basisStatusCols[i] = _basisStatusCols[_basisStatusCols.size() - 1]; 8208 _basisStatusCols.removeLast(); 8209 } 8210 } 8211 8212 _rationalLUSolver.clear(); 8213 } 8214 8215 8216 8217 /// removes all columns with an index \p i such that \p perm[i] < 0; upon completion, \p perm[i] >= 0 indicates the 8218 /// new index where column \p i has been moved to; note that \p perm must point to an array of size at least 8219 /// #numCols() 8220 template <class R> 8221 void SoPlexBase<R>::_removeColsReal(int perm[]) 8222 { 8223 assert(_realLP != 0); 8224 8225 _realLP->removeCols(perm); 8226 8227 if(_isRealLPLoaded) 8228 { 8229 _hasBasis = (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM); 8230 } 8231 else if(_hasBasis) 8232 { 8233 for(int i = numCols() - 1; i >= 0 && _hasBasis; i--) 8234 { 8235 if(perm[i] < 0 && _basisStatusCols[i] == SPxSolverBase<R>::BASIC) 8236 _hasBasis = false; 8237 else if(perm[i] >= 0 && perm[i] != i) 8238 { 8239 assert(perm[i] < numCols()); 8240 assert(perm[perm[i]] < 0); 8241 8242 _basisStatusCols[perm[i]] = _basisStatusCols[i]; 8243 } 8244 } 8245 8246 if(_hasBasis) 8247 _basisStatusCols.reSize(numCols()); 8248 } 8249 8250 _rationalLUSolver.clear(); 8251 } 8252 8253 8254 8255 /// invalidates solution 8256 template <class R> 8257 void SoPlexBase<R>::_invalidateSolution() 8258 { 8259 ///@todo maybe this should be done individually at the places when this method is called 8260 _status = SPxSolverBase<R>::UNKNOWN; 8261 8262 _solReal.invalidate(); 8263 _hasSolReal = false; 8264 8265 _solRational.invalidate(); 8266 _hasSolRational = false; 8267 } 8268 8269 8270 8271 /// enables simplifier and scaler 8272 template <class R> 8273 void SoPlexBase<R>::_enableSimplifierAndScaler() 8274 { 8275 // type of simplifier 8276 switch(intParam(SoPlexBase<R>::SIMPLIFIER)) 8277 { 8278 case SIMPLIFIER_OFF: 8279 _simplifier = 0; 8280 #ifdef SOPLEX_WITH_MPFR 8281 _boostedSimplifier = 0; 8282 #endif 8283 break; 8284 8285 case SIMPLIFIER_AUTO: 8286 case SIMPLIFIER_INTERNAL: 8287 _simplifier = &_simplifierMainSM; 8288 assert(_simplifier != 0); 8289 _simplifier->setMinReduction(realParam(MINRED)); 8290 #ifdef SOPLEX_WITH_MPFR 8291 _boostedSimplifier = &_boostedSimplifierMainSM; 8292 assert(_boostedSimplifier != 0); 8293 _boostedSimplifier->setMinReduction(realParam(MINRED)); 8294 #endif 8295 break; 8296 8297 case SIMPLIFIER_PAPILO: 8298 #ifdef SOPLEX_WITH_PAPILO 8299 _simplifier = &_simplifierPaPILO; 8300 assert(_simplifier != 0); 8301 #ifdef SOPLEX_WITH_MPFR 8302 _boostedSimplifier = &_boostedSimplifierPaPILO; 8303 assert(_boostedSimplifier != 0); 8304 #endif 8305 #else 8306 _simplifier = &_simplifierMainSM; 8307 assert(_simplifier != 0); 8308 _simplifier->setMinReduction(realParam(MINRED)); 8309 #ifdef SOPLEX_WITH_MPFR 8310 _boostedSimplifier = &_boostedSimplifierMainSM; 8311 assert(_boostedSimplifier != 0); 8312 _boostedSimplifier->setMinReduction(realParam(MINRED)); 8313 #endif // !SOPLEX_WITH_MPFR 8314 #endif // SOPLEX_WITH_PAPILO 8315 break; 8316 8317 default: 8318 break; 8319 } 8320 8321 // type of scaler 8322 switch(intParam(SoPlexBase<R>::SCALER)) 8323 { 8324 case SCALER_OFF: 8325 _scaler = 0; 8326 #ifdef SOPLEX_WITH_MPFR 8327 _boostedScaler = 0; 8328 #endif 8329 break; 8330 8331 case SCALER_UNIEQUI: 8332 _scaler = &_scalerUniequi; 8333 #ifdef SOPLEX_WITH_MPFR 8334 _boostedScaler = &_boostedScalerUniequi; 8335 #endif 8336 break; 8337 8338 case SCALER_BIEQUI: 8339 _scaler = &_scalerBiequi; 8340 #ifdef SOPLEX_WITH_MPFR 8341 _boostedScaler = &_boostedScalerBiequi; 8342 #endif 8343 break; 8344 8345 case SCALER_GEO1: 8346 _scaler = &_scalerGeo1; 8347 #ifdef SOPLEX_WITH_MPFR 8348 _boostedScaler = &_boostedScalerGeo1; 8349 #endif 8350 break; 8351 8352 case SCALER_GEO8: 8353 _scaler = &_scalerGeo8; 8354 #ifdef SOPLEX_WITH_MPFR 8355 _boostedScaler = &_boostedScalerGeo8; 8356 #endif 8357 break; 8358 8359 case SCALER_LEASTSQ: 8360 _scaler = &_scalerLeastsq; 8361 #ifdef SOPLEX_WITH_MPFR 8362 _boostedScaler = &_boostedScalerLeastsq; 8363 #endif 8364 break; 8365 8366 case SCALER_GEOEQUI: 8367 _scaler = &_scalerGeoequi; 8368 #ifdef SOPLEX_WITH_MPFR 8369 _boostedScaler = &_boostedScalerGeoequi; 8370 #endif 8371 break; 8372 8373 default: 8374 break; 8375 } 8376 } 8377 8378 8379 8380 /// disables simplifier and scaler 8381 template <class R> 8382 void SoPlexBase<R>::_disableSimplifierAndScaler() 8383 { 8384 _simplifier = 0; 8385 #ifdef SOPLEX_WITH_MPFR 8386 _boostedSimplifier = 0; 8387 #endif 8388 8389 // preserve scaler when persistent scaling is used 8390 if(!_isRealLPScaled) 8391 { 8392 _scaler = 0; 8393 #ifdef SOPLEX_WITH_MPFR 8394 _boostedScaler = 0; 8395 #endif 8396 } 8397 else 8398 assert(boolParam(SoPlexBase<R>::PERSISTENTSCALING)); 8399 } 8400 8401 8402 8403 /// ensures that the rational LP is available; performs no sync 8404 template <class R> 8405 void SoPlexBase<R>::_ensureRationalLP() 8406 { 8407 if(_rationalLP == 0) 8408 { 8409 spx_alloc(_rationalLP); 8410 _rationalLP = new(_rationalLP) SPxLPRational(); 8411 _rationalLP->setOutstream(spxout); 8412 _rationalLP->setTolerances(this->tolerances()); 8413 } 8414 } 8415 8416 8417 8418 /// ensures that the R LP and the basis are loaded in the solver; performs no sync 8419 template <class R> 8420 void SoPlexBase<R>::_ensureRealLPLoaded() 8421 { 8422 if(!_isRealLPLoaded) 8423 { 8424 assert(_realLP != &_solver); 8425 8426 _solver.loadLP(*_realLP); 8427 _realLP->~SPxLPBase<R>(); 8428 spx_free(_realLP); 8429 _realLP = &_solver; 8430 _isRealLPLoaded = true; 8431 8432 if(_hasBasis) 8433 { 8434 ///@todo this should not fail even if the basis is invalid (wrong dimension or wrong number of basic 8435 /// entries); fix either in SPxSolverBase or in SPxBasisBase 8436 assert(_basisStatusRows.size() == numRows()); 8437 assert(_basisStatusCols.size() == numCols()); 8438 _solver.setBasis(_basisStatusRows.get_const_ptr(), _basisStatusCols.get_const_ptr()); 8439 _hasBasis = (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM); 8440 } 8441 } 8442 } 8443 8444 8445 8446 /// call floating-point solver and update statistics on iterations etc. 8447 template <class R> 8448 void SoPlexBase<R>::_solveBoostedRealLPAndRecordStatistics(volatile bool* interrupt) 8449 { 8450 8451 ///@todo precision-boosting add arg SPxSolverBase<S> solver (idea for the future) 8452 bool _hadBasis = _hasBasis; 8453 8454 // set time and iteration limit 8455 if(intParam(SoPlexBase<R>::ITERLIMIT) < realParam(SoPlexBase<R>::INFTY)) 8456 _boostedSolver.setTerminationIter(intParam(SoPlexBase<R>::ITERLIMIT) - _statistics->iterations); 8457 else 8458 _boostedSolver.setTerminationIter(-1); 8459 8460 if(realParam(SoPlexBase<R>::TIMELIMIT) < realParam(SoPlexBase<R>::INFTY)) 8461 _boostedSolver.setTerminationTime(Real(realParam(SoPlexBase<R>::TIMELIMIT)) - 8462 _statistics->solvingTime->time()); 8463 else 8464 _boostedSolver.setTerminationTime(Real(realParam(SoPlexBase<R>::INFTY))); 8465 8466 // ensure that tolerances are not too small 8467 R mintol = 1e4 * _solver.epsilon(); 8468 8469 if(this->tolerances()->floatingPointFeastol() < mintol) 8470 this->tolerances()->setFloatingPointFeastol(Real(mintol)); 8471 8472 if(this->tolerances()->floatingPointOpttol() < mintol) 8473 this->tolerances()->setFloatingPointOpttol(Real(mintol)); 8474 8475 // set correct representation 8476 if((intParam(SoPlexBase<R>::REPRESENTATION) == SoPlexBase<R>::REPRESENTATION_COLUMN 8477 || (intParam(SoPlexBase<R>::REPRESENTATION) == SoPlexBase<R>::REPRESENTATION_AUTO 8478 && (_boostedSolver.nCols() + 1) * realParam(SoPlexBase<R>::REPRESENTATION_SWITCH) >= 8479 (_boostedSolver.nRows() + 1))) 8480 && _boostedSolver.rep() != SPxSolverBase<BP>::COLUMN) 8481 { 8482 _boostedSolver.setRep(SPxSolverBase<BP>::COLUMN); 8483 } 8484 else if((intParam(SoPlexBase<R>::REPRESENTATION) == SoPlexBase<R>::REPRESENTATION_ROW 8485 || (intParam(SoPlexBase<R>::REPRESENTATION) == SoPlexBase<R>::REPRESENTATION_AUTO 8486 && (_boostedSolver.nCols() + 1) * realParam(SoPlexBase<R>::REPRESENTATION_SWITCH) < 8487 (_boostedSolver.nRows() + 1))) 8488 && _boostedSolver.rep() != SPxSolverBase<BP>::ROW) 8489 { 8490 _boostedSolver.setRep(SPxSolverBase<BP>::ROW); 8491 } 8492 8493 // set correct type 8494 if(((intParam(ALGORITHM) == SoPlexBase<R>::ALGORITHM_PRIMAL 8495 && _boostedSolver.rep() == SPxSolverBase<BP>::COLUMN) 8496 || (intParam(ALGORITHM) == SoPlexBase<R>::ALGORITHM_DUAL 8497 && _boostedSolver.rep() == SPxSolverBase<BP>::ROW)) 8498 && _boostedSolver.type() != SPxSolverBase<BP>::ENTER) 8499 { 8500 _boostedSolver.setType(SPxSolverBase<BP>::ENTER); 8501 } 8502 else if(((intParam(ALGORITHM) == SoPlexBase<R>::ALGORITHM_DUAL 8503 && _boostedSolver.rep() == SPxSolverBase<BP>::COLUMN) 8504 || (intParam(ALGORITHM) == SoPlexBase<R>::ALGORITHM_PRIMAL 8505 && _boostedSolver.rep() == SPxSolverBase<BP>::ROW)) 8506 && _boostedSolver.type() != SPxSolverBase<BP>::LEAVE) 8507 { 8508 _boostedSolver.setType(SPxSolverBase<BP>::LEAVE); 8509 } 8510 8511 // set pricing modes 8512 _boostedSolver.setSparsePricingFactor(realParam(SoPlexBase<R>::SPARSITY_THRESHOLD)); 8513 8514 if((intParam(SoPlexBase<R>::HYPER_PRICING) == SoPlexBase<R>::HYPER_PRICING_ON) 8515 || ((intParam(SoPlexBase<R>::HYPER_PRICING) == SoPlexBase<R>::HYPER_PRICING_AUTO) 8516 && (_boostedSolver.nRows() + _boostedSolver.nCols() > SOPLEX_HYPERPRICINGTHRESHOLD))) 8517 _boostedSolver.hyperPricing(true); 8518 else if(intParam(SoPlexBase<R>::HYPER_PRICING) == SoPlexBase<R>::HYPER_PRICING_OFF) 8519 _boostedSolver.hyperPricing(false); 8520 8521 _boostedSolver.setNonzeroFactor(realParam(SoPlexBase<R>::REFAC_BASIS_NNZ)); 8522 _boostedSolver.setFillFactor(realParam(SoPlexBase<R>::REFAC_UPDATE_FILL)); 8523 _boostedSolver.setMemFactor(realParam(SoPlexBase<R>::REFAC_MEM_FACTOR)); 8524 8525 // call floating-point solver and catch exceptions 8526 _statistics->simplexTime->start(); 8527 8528 try 8529 { 8530 _boostedSolver.solve(interrupt); 8531 } 8532 catch(const SPxException& E) 8533 { 8534 SPX_MSG_INFO1(spxout, spxout << "Caught exception <" << E.what() << "> while solving Real LP.\n"); 8535 _status = SPxSolverBase<R>::ERROR; 8536 } 8537 catch(...) 8538 { 8539 SPX_MSG_INFO1(spxout, spxout << "Caught unknown exception while solving Real LP.\n"); 8540 _status = SPxSolverBase<R>::ERROR; 8541 } 8542 8543 _statistics->simplexTime->stop(); 8544 8545 // invalidate rational factorization of basis if pivots have been performed 8546 if(_boostedSolver.iterations() > 0) 8547 _rationalLUSolver.clear(); 8548 8549 ///@todo precision-boosting currently no need to record statistics for the boosted solver 8550 // record statistics 8551 _statistics->iterations += _boostedSolver.iterations(); 8552 _statistics->iterationsPrimal += _boostedSolver.primalIterations(); 8553 _statistics->iterationsFromBasis += _hadBasis ? _boostedSolver.iterations() : 0; 8554 _statistics->iterationsPolish += _boostedSolver.polishIterations(); 8555 _statistics->boundflips += _boostedSolver.boundFlips(); 8556 _statistics->boostedIterations += _boostedSolver.iterations(); 8557 _statistics->boostedIterationsPrimal += _boostedSolver.primalIterations(); 8558 _statistics->boostedIterationsFromBasis += _hadBasis ? _boostedSolver.iterations() : 0; 8559 _statistics->boostedIterationsPolish += _boostedSolver.polishIterations(); 8560 _statistics->boostedBoundflips += _boostedSolver.boundFlips(); 8561 _statistics->multTimeSparse += _boostedSolver.multTimeSparse->time(); 8562 _statistics->multTimeFull += _boostedSolver.multTimeFull->time(); 8563 _statistics->multTimeColwise += _boostedSolver.multTimeColwise->time(); 8564 _statistics->multTimeUnsetup += _boostedSolver.multTimeUnsetup->time(); 8565 _statistics->multSparseCalls += _boostedSolver.multSparseCalls; 8566 _statistics->multFullCalls += _boostedSolver.multFullCalls; 8567 _statistics->multColwiseCalls += _boostedSolver.multColwiseCalls; 8568 _statistics->multUnsetupCalls += _boostedSolver.multUnsetupCalls; 8569 _statistics->luFactorizationTimeReal += _slufactor.getFactorTime(); 8570 _statistics->luSolveTimeReal += _slufactor.getSolveTime(); 8571 _statistics->luFactorizationsReal += _slufactor.getFactorCount(); 8572 _statistics->luSolvesReal += _slufactor.getSolveCount(); 8573 _slufactor.resetCounters(); 8574 8575 _statistics->degenPivotsPrimal += _boostedSolver.primalDegeneratePivots(); 8576 _statistics->degenPivotsDual += _boostedSolver.dualDegeneratePivots(); 8577 _statistics->sumDualDegen += R(_boostedSolver.sumDualDegeneracy()); 8578 _statistics->sumPrimalDegen += R(_boostedSolver.sumPrimalDegeneracy()); 8579 } 8580 8581 8582 /// call floating-point solver and update statistics on iterations etc. 8583 template <class R> 8584 void SoPlexBase<R>::_solveRealLPAndRecordStatistics(volatile bool* interrupt) 8585 { 8586 bool _hadBasis = _hasBasis; 8587 8588 // set time and iteration limit 8589 if(intParam(SoPlexBase<R>::ITERLIMIT) < realParam(SoPlexBase<R>::INFTY)) 8590 _solver.setTerminationIter(intParam(SoPlexBase<R>::ITERLIMIT) - _statistics->iterations); 8591 else 8592 _solver.setTerminationIter(-1); 8593 8594 if(realParam(SoPlexBase<R>::TIMELIMIT) < realParam(SoPlexBase<R>::INFTY)) 8595 _solver.setTerminationTime(Real(realParam(SoPlexBase<R>::TIMELIMIT)) - 8596 _statistics->solvingTime->time()); 8597 else 8598 _solver.setTerminationTime(Real(realParam(SoPlexBase<R>::INFTY))); 8599 8600 // ensure that tolerances are not too small 8601 R mintol = 1e4 * _solver.epsilon(); 8602 8603 if(this->tolerances()->floatingPointFeastol() < mintol) 8604 this->tolerances()->setFloatingPointFeastol(Real(mintol)); 8605 8606 if(this->tolerances()->floatingPointOpttol() < mintol) 8607 this->tolerances()->setFloatingPointOpttol(Real(mintol)); 8608 8609 // set correct representation 8610 if((intParam(SoPlexBase<R>::REPRESENTATION) == SoPlexBase<R>::REPRESENTATION_COLUMN 8611 || (intParam(SoPlexBase<R>::REPRESENTATION) == SoPlexBase<R>::REPRESENTATION_AUTO 8612 && (_solver.nCols() + 1) * realParam(SoPlexBase<R>::REPRESENTATION_SWITCH) >= 8613 (_solver.nRows() + 1))) 8614 && _solver.rep() != SPxSolverBase<R>::COLUMN) 8615 { 8616 _solver.setRep(SPxSolverBase<R>::COLUMN); 8617 } 8618 else if((intParam(SoPlexBase<R>::REPRESENTATION) == SoPlexBase<R>::REPRESENTATION_ROW 8619 || (intParam(SoPlexBase<R>::REPRESENTATION) == SoPlexBase<R>::REPRESENTATION_AUTO 8620 && (_solver.nCols() + 1) * realParam(SoPlexBase<R>::REPRESENTATION_SWITCH) < (_solver.nRows() + 1))) 8621 && _solver.rep() != SPxSolverBase<R>::ROW) 8622 { 8623 _solver.setRep(SPxSolverBase<R>::ROW); 8624 } 8625 8626 // set correct type 8627 if(((intParam(ALGORITHM) == SoPlexBase<R>::ALGORITHM_PRIMAL 8628 && _solver.rep() == SPxSolverBase<R>::COLUMN) 8629 || (intParam(ALGORITHM) == SoPlexBase<R>::ALGORITHM_DUAL && _solver.rep() == SPxSolverBase<R>::ROW)) 8630 && _solver.type() != SPxSolverBase<R>::ENTER) 8631 { 8632 _solver.setType(SPxSolverBase<R>::ENTER); 8633 } 8634 else if(((intParam(ALGORITHM) == SoPlexBase<R>::ALGORITHM_DUAL 8635 && _solver.rep() == SPxSolverBase<R>::COLUMN) 8636 || (intParam(ALGORITHM) == SoPlexBase<R>::ALGORITHM_PRIMAL 8637 && _solver.rep() == SPxSolverBase<R>::ROW)) 8638 && _solver.type() != SPxSolverBase<R>::LEAVE) 8639 { 8640 _solver.setType(SPxSolverBase<R>::LEAVE); 8641 } 8642 8643 // set pricing modes 8644 _solver.setSparsePricingFactor(realParam(SoPlexBase<R>::SPARSITY_THRESHOLD)); 8645 8646 if((intParam(SoPlexBase<R>::HYPER_PRICING) == SoPlexBase<R>::HYPER_PRICING_ON) 8647 || ((intParam(SoPlexBase<R>::HYPER_PRICING) == SoPlexBase<R>::HYPER_PRICING_AUTO) 8648 && (_solver.nRows() + _solver.nCols() > SOPLEX_HYPERPRICINGTHRESHOLD))) 8649 _solver.hyperPricing(true); 8650 else if(intParam(SoPlexBase<R>::HYPER_PRICING) == SoPlexBase<R>::HYPER_PRICING_OFF) 8651 _solver.hyperPricing(false); 8652 8653 _solver.setNonzeroFactor(realParam(SoPlexBase<R>::REFAC_BASIS_NNZ)); 8654 _solver.setFillFactor(realParam(SoPlexBase<R>::REFAC_UPDATE_FILL)); 8655 _solver.setMemFactor(realParam(SoPlexBase<R>::REFAC_MEM_FACTOR)); 8656 8657 // call floating-point solver and catch exceptions 8658 _statistics->simplexTime->start(); 8659 8660 try 8661 { 8662 _solver.solve(interrupt); 8663 } 8664 catch(const SPxException& E) 8665 { 8666 SPX_MSG_INFO1(spxout, spxout << "Caught exception <" << E.what() << "> while solving Real LP.\n"); 8667 _status = SPxSolverBase<R>::ERROR; 8668 } 8669 catch(...) 8670 { 8671 SPX_MSG_INFO1(spxout, spxout << "Caught unknown exception while solving Real LP.\n"); 8672 _status = SPxSolverBase<R>::ERROR; 8673 } 8674 8675 _statistics->simplexTime->stop(); 8676 8677 // invalidate rational factorization of basis if pivots have been performed 8678 if(_solver.iterations() > 0) 8679 _rationalLUSolver.clear(); 8680 8681 // record statistics 8682 _statistics->iterations += _solver.iterations(); 8683 _statistics->iterationsPrimal += _solver.primalIterations(); 8684 _statistics->iterationsFromBasis += _hadBasis ? _solver.iterations() : 0; 8685 _statistics->iterationsPolish += _solver.polishIterations(); 8686 _statistics->boundflips += _solver.boundFlips(); 8687 _statistics->multTimeSparse += _solver.multTimeSparse->time(); 8688 _statistics->multTimeFull += _solver.multTimeFull->time(); 8689 _statistics->multTimeColwise += _solver.multTimeColwise->time(); 8690 _statistics->multTimeUnsetup += _solver.multTimeUnsetup->time(); 8691 _statistics->multSparseCalls += _solver.multSparseCalls; 8692 _statistics->multFullCalls += _solver.multFullCalls; 8693 _statistics->multColwiseCalls += _solver.multColwiseCalls; 8694 _statistics->multUnsetupCalls += _solver.multUnsetupCalls; 8695 _statistics->luFactorizationTimeReal += _slufactor.getFactorTime(); 8696 _statistics->luSolveTimeReal += _slufactor.getSolveTime(); 8697 _statistics->luFactorizationsReal += _slufactor.getFactorCount(); 8698 _statistics->luSolvesReal += _slufactor.getSolveCount(); 8699 _slufactor.resetCounters(); 8700 8701 _statistics->degenPivotsPrimal += _solver.primalDegeneratePivots(); 8702 _statistics->degenPivotsDual += _solver.dualDegeneratePivots(); 8703 _statistics->sumDualDegen += _solver.sumDualDegeneracy(); 8704 _statistics->sumPrimalDegen += _solver.sumPrimalDegeneracy(); 8705 } 8706 8707 8708 8709 /// reads R LP in LP or MPS format from file and returns true on success; gets row names, column names, and 8710 /// integer variables if desired 8711 template <class R> 8712 bool SoPlexBase<R>::_readFileReal(const char* filename, NameSet* rowNames, NameSet* colNames, 8713 DIdxSet* intVars) 8714 { 8715 assert(_realLP != 0); 8716 8717 // clear statistics 8718 _statistics->clearAllData(); 8719 8720 // update status 8721 clearBasis(); 8722 _invalidateSolution(); 8723 _status = SPxSolverBase<R>::UNKNOWN; 8724 8725 // start timing 8726 _statistics->readingTime->start(); 8727 8728 // read 8729 bool success = _realLP->readFile(filename, rowNames, colNames, intVars); 8730 8731 // stop timing 8732 _statistics->readingTime->stop(); 8733 8734 if(success) 8735 { 8736 setIntParam(SoPlexBase<R>::OBJSENSE, 8737 (_realLP->spxSense() == SPxLPBase<R>::MAXIMIZE ? SoPlexBase<R>::OBJSENSE_MAXIMIZE : 8738 SoPlexBase<R>::OBJSENSE_MINIMIZE), true); 8739 _realLP->changeObjOffset(realParam(SoPlexBase<R>::OBJ_OFFSET)); 8740 8741 // if sync mode is auto, we have to copy the (rounded) R LP to the rational LP; this is counted to sync time 8742 // and not to reading time 8743 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 8744 _syncLPRational(); 8745 } 8746 else 8747 clearLPReal(); 8748 8749 return success; 8750 } 8751 8752 8753 8754 /// reads rational LP in LP or MPS format from file and returns true on success; gets row names, column names, and 8755 /// integer variables if desired 8756 template <class R> 8757 bool SoPlexBase<R>::_readFileRational(const char* filename, NameSet* rowNames, NameSet* colNames, 8758 DIdxSet* intVars) 8759 { 8760 // clear statistics 8761 _statistics->clearAllData(); 8762 8763 // start timing 8764 _statistics->readingTime->start(); 8765 8766 // update status 8767 clearBasis(); 8768 _invalidateSolution(); 8769 _status = SPxSolverBase<R>::UNKNOWN; 8770 8771 // read 8772 _ensureRationalLP(); 8773 bool success = _rationalLP->readFile(filename, rowNames, colNames, intVars); 8774 8775 // stop timing 8776 _statistics->readingTime->stop(); 8777 8778 if(success) 8779 { 8780 setIntParam(SoPlexBase<R>::OBJSENSE, 8781 (_rationalLP->spxSense() == SPxLPRational::MAXIMIZE ? SoPlexBase<R>::OBJSENSE_MAXIMIZE : 8782 SoPlexBase<R>::OBJSENSE_MINIMIZE), true); 8783 _rationalLP->changeObjOffset(realParam(SoPlexBase<R>::OBJ_OFFSET)); 8784 _recomputeRangeTypesRational(); 8785 8786 // if sync mode is auto, we have to copy the (rounded) R LP to the rational LP; this is counted to sync time 8787 // and not to reading time 8788 if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_AUTO) 8789 _syncLPReal(); 8790 // if a rational LP file is read, but only the (rounded) R LP should be kept, we have to free the rational LP 8791 else if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 8792 { 8793 _syncLPReal(); 8794 _rationalLP->~SPxLPRational(); 8795 spx_free(_rationalLP); 8796 } 8797 } 8798 else 8799 clearLPRational(); 8800 8801 return success; 8802 } 8803 8804 8805 8806 /// completes range type arrays after adding columns and/or rows 8807 template <class R> 8808 void SoPlexBase<R>::_completeRangeTypesRational() 8809 { 8810 // we use one method for bot columns and rows, because during column/row addition, rows/columns can be added 8811 // implicitly 8812 for(int i = _colTypes.size(); i < numColsRational(); i++) 8813 _colTypes.append(_rangeTypeRational(_rationalLP->lower(i), _rationalLP->upper(i))); 8814 8815 for(int i = _rowTypes.size(); i < numRowsRational(); i++) 8816 _rowTypes.append(_rangeTypeRational(_rationalLP->lhs(i), _rationalLP->rhs(i))); 8817 } 8818 8819 8820 8821 /// recomputes range types from scratch using R LP 8822 template <class R> 8823 void SoPlexBase<R>::_recomputeRangeTypesReal() 8824 { 8825 _rowTypes.reSize(numRows()); 8826 8827 for(int i = 0; i < numRows(); i++) 8828 _rowTypes[i] = _rangeTypeReal(_realLP->lhs(i), _realLP->rhs(i)); 8829 8830 _colTypes.reSize(numCols()); 8831 8832 for(int i = 0; i < numCols(); i++) 8833 _colTypes[i] = _rangeTypeReal(_realLP->lower(i), _realLP->upper(i)); 8834 } 8835 8836 8837 8838 /// recomputes range types from scratch using rational LP 8839 template <class R> 8840 void SoPlexBase<R>::_recomputeRangeTypesRational() 8841 { 8842 _rowTypes.reSize(numRowsRational()); 8843 8844 for(int i = 0; i < numRowsRational(); i++) 8845 _rowTypes[i] = _rangeTypeRational(_rationalLP->lhs(i), _rationalLP->rhs(i)); 8846 8847 _colTypes.reSize(numColsRational()); 8848 8849 for(int i = 0; i < numColsRational(); i++) 8850 _colTypes[i] = _rangeTypeRational(_rationalLP->lower(i), _rationalLP->upper(i)); 8851 } 8852 8853 8854 8855 /// synchronizes R LP with rational LP, i.e., copies (rounded) rational LP into R LP, without looking at the sync mode 8856 template <class R> 8857 void SoPlexBase<R>::_syncLPReal(bool time) 8858 { 8859 // start timing 8860 if(time) 8861 _statistics->syncTime->start(); 8862 8863 // copy LP 8864 if(_isRealLPLoaded) 8865 _solver.loadLP((SPxLPBase<R>)(*_rationalLP)); 8866 else 8867 *_realLP = *_rationalLP; 8868 8869 ///@todo try loading old basis 8870 _hasBasis = false; 8871 _rationalLUSolver.clear(); 8872 8873 // stop timing 8874 if(time) 8875 _statistics->syncTime->stop(); 8876 } 8877 8878 8879 8880 /// synchronizes rational LP with R LP, i.e., copies R LP to rational LP, without looking at the sync mode 8881 template <class R> 8882 void SoPlexBase<R>::_syncLPRational(bool time) 8883 { 8884 // start timing 8885 if(time) 8886 _statistics->syncTime->start(); 8887 8888 // copy LP 8889 _ensureRationalLP(); 8890 *_rationalLP = *_realLP; 8891 _recomputeRangeTypesRational(); 8892 8893 // stop timing 8894 if(time) 8895 _statistics->syncTime->stop(); 8896 } 8897 8898 8899 8900 /// synchronizes rational solution with R solution, i.e., copies (rounded) rational solution to R solution 8901 template <class R> 8902 void SoPlexBase<R>::_syncRealSolution() 8903 { 8904 if(_hasSolRational && !_hasSolReal) 8905 { 8906 _solReal = _solRational; 8907 _hasSolReal = true; 8908 } 8909 } 8910 8911 8912 8913 /// synchronizes R solution with rational solution, i.e., copies R solution to rational solution 8914 template <class R> 8915 void SoPlexBase<R>::_syncRationalSolution() 8916 { 8917 if(_hasSolReal && !_hasSolRational) 8918 { 8919 _solRational = _solReal; 8920 _hasSolRational = true; 8921 } 8922 } 8923 8924 8925 8926 /// returns pointer to a constant unit vector available until destruction of the SoPlexBase class 8927 template <class R> 8928 const UnitVectorRational* SoPlexBase<R>::_unitVectorRational(const int i) 8929 { 8930 assert(i >= 0); 8931 8932 if(i < 0) 8933 return 0; 8934 else if(i >= _unitMatrixRational.size()) 8935 _unitMatrixRational.append(i + 1 - _unitMatrixRational.size(), (UnitVectorRational*)0); 8936 8937 assert(i < _unitMatrixRational.size()); 8938 8939 if(_unitMatrixRational[i] == 0) 8940 { 8941 spx_alloc(_unitMatrixRational[i]); 8942 new(_unitMatrixRational[i]) UnitVectorRational(i); 8943 } 8944 8945 assert(_unitMatrixRational[i] != 0); 8946 8947 return _unitMatrixRational[i]; 8948 } 8949 8950 8951 8952 /// parses one line in a settings file and returns true on success; note that the string is modified 8953 template <class R> 8954 bool SoPlexBase<R>::_parseSettingsLine(char* line, const int lineNumber) 8955 { 8956 assert(line != 0); 8957 8958 bool success = true; 8959 8960 // find the start of the parameter type 8961 while(*line == ' ' || *line == '\t' || *line == '\r') 8962 line++; 8963 8964 if(*line == '\0' || *line == '\n' || *line == '#') 8965 return true; 8966 8967 char* paramTypeString = line; 8968 8969 // find the end of the parameter type 8970 while(*line != ' ' && *line != '\t' && *line != '\r' && *line != '\n' && *line != '#' 8971 && *line != '\0' && *line != ':') 8972 line++; 8973 8974 if(*line == ':') 8975 { 8976 *line = '\0'; 8977 line++; 8978 } 8979 else 8980 { 8981 *line = '\0'; 8982 line++; 8983 8984 // search for the ':' char in the line 8985 while(*line == ' ' || *line == '\t' || *line == '\r') 8986 line++; 8987 8988 if(*line != ':') 8989 { 8990 SPX_MSG_INFO1(spxout, spxout << 8991 "Error parsing settings file: no ':' separating parameter type and name in line " << lineNumber << 8992 ".\n"); 8993 return false; 8994 } 8995 8996 line++; 8997 } 8998 8999 // find the start of the parameter name 9000 while(*line == ' ' || *line == '\t' || *line == '\r') 9001 line++; 9002 9003 if(*line == '\0' || *line == '\n' || *line == '#') 9004 { 9005 SPX_MSG_INFO1(spxout, spxout << "Error parsing settings file: no parameter name in line " << 9006 lineNumber << ".\n"); 9007 return false; 9008 } 9009 9010 char* paramName = line; 9011 9012 // find the end of the parameter name 9013 while(*line != ' ' && *line != '\t' && *line != '\r' && *line != '\n' && *line != '#' 9014 && *line != '\0' && *line != '=') 9015 line++; 9016 9017 if(*line == '=') 9018 { 9019 *line = '\0'; 9020 line++; 9021 } 9022 else 9023 { 9024 *line = '\0'; 9025 line++; 9026 9027 // search for the '=' char in the line 9028 while(*line == ' ' || *line == '\t' || *line == '\r') 9029 line++; 9030 9031 if(*line != '=') 9032 { 9033 SPX_MSG_INFO1(spxout, spxout << "Error parsing settings file: no '=' after parameter name in line " 9034 << lineNumber << ".\n"); 9035 return false; 9036 } 9037 9038 line++; 9039 } 9040 9041 // find the start of the parameter value string 9042 while(*line == ' ' || *line == '\t' || *line == '\r') 9043 line++; 9044 9045 if(*line == '\0' || *line == '\n' || *line == '#') 9046 { 9047 SPX_MSG_INFO1(spxout, spxout << "Error parsing settings file: no parameter value in line " << 9048 lineNumber << ".\n"); 9049 return false; 9050 } 9051 9052 char* paramValueString = line; 9053 9054 // find the end of the parameter value string 9055 while(*line != ' ' && *line != '\t' && *line != '\r' && *line != '\n' && *line != '#' 9056 && *line != '\0') 9057 line++; 9058 9059 if(*line != '\0') 9060 { 9061 // check, if the rest of the line is clean 9062 *line = '\0'; 9063 line++; 9064 9065 while(*line == ' ' || *line == '\t' || *line == '\r') 9066 line++; 9067 9068 if(*line != '\0' && *line != '\n' && *line != '#') 9069 { 9070 SPX_MSG_INFO1(spxout, spxout << "Error parsing settings file: additional character '" << *line << 9071 "' after parameter value in line " << lineNumber << ".\n"); 9072 return false; 9073 } 9074 } 9075 9076 // check whether we have a bool parameter 9077 if(strncmp(paramTypeString, "bool", 4) == 0) 9078 { 9079 for(int param = 0; ; param++) 9080 { 9081 if(param >= SoPlexBase<R>::BOOLPARAM_COUNT) 9082 { 9083 SPX_MSG_INFO1(spxout, spxout << "Error parsing settings file: unknown parameter name <" << paramName 9084 << "> in line " << lineNumber << ".\n"); 9085 return false; 9086 } 9087 else if(strncmp(paramName, _currentSettings->boolParam.name[param].c_str(), 9088 SPX_SET_MAX_LINE_LEN) == 0) 9089 { 9090 if(strncasecmp(paramValueString, "true", 4) == 0 9091 || strncasecmp(paramValueString, "TRUE", 4) == 0 9092 || strncasecmp(paramValueString, "t", 4) == 0 9093 || strncasecmp(paramValueString, "T", 4) == 0 9094 || strtol(paramValueString, NULL, 4) == 1) 9095 { 9096 success = setBoolParam((SoPlexBase<R>::BoolParam)param, true); 9097 break; 9098 } 9099 else if(strncasecmp(paramValueString, "false", 5) == 0 9100 || strncasecmp(paramValueString, "FALSE", 5) == 0 9101 || strncasecmp(paramValueString, "f", 5) == 0 9102 || strncasecmp(paramValueString, "F", 5) == 0 9103 || strtol(paramValueString, NULL, 5) == 0) 9104 { 9105 success = setBoolParam((SoPlexBase<R>::BoolParam)param, false); 9106 break; 9107 } 9108 else 9109 { 9110 SPX_MSG_INFO1(spxout, spxout << "Error parsing settings file: invalid value <" << paramValueString 9111 << "> for bool parameter <" << paramName << "> in line " << lineNumber << ".\n"); 9112 return false; 9113 } 9114 } 9115 } 9116 9117 return success; 9118 } 9119 9120 // check whether we have an integer parameter 9121 if(strncmp(paramTypeString, "int", 3) == 0) 9122 { 9123 for(int param = 0; ; param++) 9124 { 9125 if(param >= SoPlexBase<R>::INTPARAM_COUNT) 9126 { 9127 SPX_MSG_INFO1(spxout, spxout << "Error parsing settings file: unknown parameter name <" << paramName 9128 << "> in line " << lineNumber << ".\n"); 9129 return false; 9130 } 9131 else if(strncmp(paramName, _currentSettings->intParam.name[param].c_str(), 9132 SPX_SET_MAX_LINE_LEN) == 0) 9133 { 9134 int value; 9135 value = std::stoi(paramValueString); 9136 9137 if(setIntParam((SoPlexBase<R>::IntParam)param, value, false)) 9138 break; 9139 else 9140 { 9141 SPX_MSG_INFO1(spxout, spxout << "Error parsing settings file: invalid value <" << paramValueString 9142 << "> for int parameter <" << paramName << "> in line " << lineNumber << ".\n"); 9143 return false; 9144 } 9145 } 9146 } 9147 9148 return true; 9149 } 9150 9151 // check whether we have a R parameter 9152 if(strncmp(paramTypeString, "real", 4) == 0) 9153 { 9154 for(int param = 0; ; param++) 9155 { 9156 if(param >= SoPlexBase<R>::REALPARAM_COUNT) 9157 { 9158 SPX_MSG_INFO1(spxout, spxout << "Error parsing settings file: unknown parameter name <" << paramName 9159 << "> in line " << lineNumber << ".\n"); 9160 return false; 9161 } 9162 else if(strncmp(paramName, _currentSettings->realParam.name[param].c_str(), 9163 SPX_SET_MAX_LINE_LEN) == 0) 9164 { 9165 Real value; 9166 9167 #ifdef WITH_LONG_DOUBLE 9168 value = std::stold(paramValueString); 9169 #else 9170 #ifdef WITH_FLOAT 9171 value = std::stof(paramValueString); 9172 #else 9173 value = std::stod(paramValueString); 9174 #endif 9175 #endif 9176 9177 if(setRealParam((SoPlexBase<R>::RealParam)param, value)) 9178 break; 9179 else 9180 { 9181 SPX_MSG_INFO1(spxout, spxout << "Error parsing settings file: invalid value <" << paramValueString 9182 << "> for R parameter <" << paramName << "> in line " << lineNumber << ".\n"); 9183 return false; 9184 } 9185 } 9186 } 9187 9188 return true; 9189 } 9190 9191 #ifdef SOPLEX_WITH_RATIONALPARAM 9192 9193 // check whether we have a rational parameter 9194 if(strncmp(paramTypeString, "rational", 8) == 0) 9195 { 9196 for(int param = 0; ; param++) 9197 { 9198 if(param >= SoPlexBase<R>::RATIONALPARAM_COUNT) 9199 { 9200 SPX_MSG_INFO1(spxout, spxout << "Error parsing settings file: unknown parameter name <" << paramName 9201 << "> in line " << lineNumber << ".\n"); 9202 return false; 9203 } 9204 else if(strncmp(paramName, _currentSettings->rationalParam.name[param].c_str(), 9205 SPX_SET_MAX_LINE_LEN) == 0) 9206 { 9207 Rational value; 9208 9209 if(readStringRational(paramValueString, value) 9210 && setRationalParam((SoPlexBase<R>::RationalParam)param, value)) 9211 break; 9212 else 9213 { 9214 SPX_MSG_INFO1(spxout, spxout << "Error parsing settings file: invalid value <" << paramValueString 9215 << "> for rational parameter <" << paramName << "> in line " << lineNumber << ".\n"); 9216 return false; 9217 } 9218 } 9219 } 9220 9221 return true; 9222 } 9223 9224 #endif 9225 9226 // check whether we have the random seed 9227 if(strncmp(paramTypeString, "uint", 4) == 0) 9228 { 9229 if(strncmp(paramName, "random_seed", 11) == 0) 9230 { 9231 unsigned int value; 9232 unsigned long parseval; 9233 9234 parseval = std::stoul(paramValueString); 9235 9236 if(parseval > UINT_MAX) 9237 { 9238 value = UINT_MAX; 9239 SPX_MSG_WARNING(spxout, spxout << "Converting number greater than UINT_MAX to uint.\n"); 9240 } 9241 else 9242 value = (unsigned int) parseval; 9243 9244 setRandomSeed(value); 9245 return true; 9246 } 9247 9248 SPX_MSG_INFO1(spxout, spxout << "Error parsing settings file for uint parameter <random_seed>.\n"); 9249 return false; 9250 } 9251 9252 SPX_MSG_INFO1(spxout, spxout << "Error parsing settings file: invalid parameter type <" << 9253 paramTypeString << "> for parameter <" << paramName << "> in line " << lineNumber << ".\n"); 9254 9255 return false; 9256 } 9257 9258 /// default constructor 9259 template <class R> 9260 SoPlexBase<R>::SoPlexBase() 9261 : _statistics(0) 9262 , _currentSettings(0) 9263 , _scalerUniequi(false) 9264 , _scalerBiequi(true) 9265 , _scalerGeo1(false, 1) 9266 , _scalerGeo8(false, 8) 9267 , _scalerGeoequi(true) 9268 , _scalerLeastsq() 9269 , _simplifier(0) 9270 , _scaler(nullptr) 9271 , _starter(0) 9272 , _rationalLP(0) 9273 , _unitMatrixRational(0) 9274 , _status(SPxSolverBase<R>::UNKNOWN) 9275 , _hasBasis(false) 9276 , _hasSolReal(false) 9277 , _hasSolRational(false) 9278 , _rationalPosone(1) 9279 , _rationalNegone(-1) 9280 , _rationalZero(0) 9281 { 9282 _tolerances = std::make_shared<Tolerances>(); 9283 _solver.setTolerances(_tolerances); 9284 _boostedSolver.setTolerances(_tolerances); 9285 // set tolerances for scalers 9286 _scalerUniequi.setTolerances(_tolerances); 9287 _scalerBiequi.setTolerances(_tolerances); 9288 _scalerGeo1.setTolerances(_tolerances); 9289 _scalerGeo8.setTolerances(_tolerances); 9290 _scalerGeoequi.setTolerances(_tolerances); 9291 _scalerLeastsq.setTolerances(_tolerances); 9292 9293 _boostedScalerUniequi.setTolerances(_tolerances); 9294 _boostedScalerBiequi.setTolerances(_tolerances); 9295 _boostedScalerGeo1.setTolerances(_tolerances); 9296 _boostedScalerGeo8.setTolerances(_tolerances); 9297 _boostedScalerGeoequi.setTolerances(_tolerances); 9298 _boostedScalerLeastsq.setTolerances(_tolerances); 9299 9300 // set tolerances for ratio testers 9301 _ratiotesterBoundFlipping.setTolerances(_tolerances); 9302 _ratiotesterFast.setTolerances(_tolerances); 9303 _ratiotesterHarris.setTolerances(_tolerances); 9304 _ratiotesterTextbook.setTolerances(_tolerances); 9305 9306 _boostedRatiotesterBoundFlipping.setTolerances(_tolerances); 9307 _boostedRatiotesterFast.setTolerances(_tolerances); 9308 _boostedRatiotesterHarris.setTolerances(_tolerances); 9309 _boostedRatiotesterTextbook.setTolerances(_tolerances); 9310 9311 // set tolerances for slufactor 9312 _slufactor.setTolerances(_tolerances); 9313 _boostedSlufactor.setTolerances(_tolerances); 9314 // transfer message handler 9315 _solver.setOutstream(spxout); 9316 _scalerUniequi.setOutstream(spxout); 9317 _scalerBiequi.setOutstream(spxout); 9318 _scalerGeo1.setOutstream(spxout); 9319 _scalerGeo8.setOutstream(spxout); 9320 _scalerGeoequi.setOutstream(spxout); 9321 _scalerLeastsq.setOutstream(spxout); 9322 9323 // give lu factorization to solver 9324 _solver.setBasisSolver(&_slufactor); 9325 9326 #ifdef SOPLEX_WITH_MPFR 9327 // set initial precision 9328 BP::default_precision(_initialPrecision); 9329 9330 _boostedSolver.setOutstream(spxout); 9331 _boostedScalerUniequi.setOutstream(spxout); 9332 _boostedScalerBiequi.setOutstream(spxout); 9333 _boostedScalerGeo1.setOutstream(spxout); 9334 _boostedScalerGeo8.setOutstream(spxout); 9335 _boostedScalerGeoequi.setOutstream(spxout); 9336 _boostedScalerLeastsq.setOutstream(spxout); 9337 9338 _boostedSolver.setBasisSolver(&_boostedSlufactor); 9339 9340 _lastStallPrecBoosts = 0; 9341 _factorSolNewBasisPrecBoost = true; 9342 _nextRatrecPrecBoost = 0; 9343 _prevIterations = 0; 9344 9345 _switchedToBoosted = false; 9346 9347 _certificateMode = 0; 9348 _hasOldBasis = false; 9349 _hasOldFeasBasis = false; 9350 _hasOldUnbdBasis = false; 9351 9352 _boostingLimitReached = false; 9353 #endif 9354 9355 // the R LP is initially stored in the solver; the rational LP is constructed, when the parameter SYNCMODE is 9356 // initialized in setSettings() below 9357 _realLP = &_solver; 9358 _isRealLPLoaded = true; 9359 _isRealLPScaled = false; 9360 _applyPolishing = false; 9361 _optimizeCalls = 0; 9362 _unscaleCalls = 0; 9363 _realLP->setOutstream(spxout); 9364 _currentProb = DECOMP_ORIG; 9365 9366 // initialize statistics 9367 spx_alloc(_statistics); 9368 _statistics = new(_statistics) Statistics(); 9369 9370 // initialize parameter settings to default 9371 spx_alloc(_currentSettings); 9372 _currentSettings = new(_currentSettings) Settings(); 9373 setSettings(*_currentSettings, true); 9374 9375 _lastSolveMode = intParam(SoPlexBase<R>::SOLVEMODE); 9376 9377 _simplifierPaPILO.setOutstream(spxout); 9378 9379 assert(_isConsistent()); 9380 } 9381 9382 9383 9384 /// reads settings file; returns true on success 9385 template <class R> 9386 bool SoPlexBase<R>::loadSettingsFile(const char* filename) 9387 { 9388 assert(filename != 0); 9389 9390 // start timing 9391 _statistics->readingTime->start(); 9392 9393 SPX_MSG_INFO1(spxout, spxout << "Loading settings file <" << filename << "> . . .\n"); 9394 9395 // open file 9396 spxifstream file(filename); 9397 9398 if(!file) 9399 { 9400 SPX_MSG_INFO1(spxout, spxout << "Error opening settings file.\n"); 9401 return false; 9402 } 9403 9404 // read file 9405 char line[SPX_SET_MAX_LINE_LEN]; 9406 int lineNumber = 0; 9407 bool readError = false; 9408 bool parseError = false; 9409 9410 while(!readError && !parseError) 9411 { 9412 lineNumber++; 9413 readError = !file.getline(line, sizeof(line)); 9414 9415 if(!readError) 9416 parseError = !_parseSettingsLine(line, lineNumber); 9417 } 9418 9419 readError = readError && !file.eof(); 9420 9421 if(readError && strlen(line) == SPX_SET_MAX_LINE_LEN - 1) 9422 { 9423 SPX_MSG_INFO1(spxout, spxout << "Error reading settings file: line " << lineNumber << 9424 " in settings file exceeds " << SPX_SET_MAX_LINE_LEN - 2 << " characters.\n"); 9425 } 9426 else if(readError) 9427 { 9428 SPX_MSG_INFO1(spxout, spxout << "Error reading settings file: line " << lineNumber << ".\n"); 9429 } 9430 9431 // stop timing 9432 _statistics->readingTime->stop(); 9433 9434 return !readError; 9435 } 9436 9437 9438 /// parses one setting string and returns true on success 9439 template <class R> 9440 bool SoPlexBase<R>::parseSettingsString(char* string) 9441 { 9442 assert(string != 0); 9443 9444 bool success = true; 9445 9446 if(string == 0) 9447 return false; 9448 9449 char parseString[SPX_SET_MAX_LINE_LEN]; 9450 spxSnprintf(parseString, SPX_SET_MAX_LINE_LEN - 1, "%s", string); 9451 9452 char* line = parseString; 9453 9454 // find the start of the parameter type 9455 while(*line == ' ' || *line == '\t' || *line == '\r') 9456 line++; 9457 9458 if(*line == '\0' || *line == '\n' || *line == '#') 9459 return true; 9460 9461 char* paramTypeString = line; 9462 9463 // find the end of the parameter type 9464 while(*line != ' ' && *line != '\t' && *line != '\r' && *line != '\n' && *line != '#' 9465 && *line != '\0' && *line != ':') 9466 line++; 9467 9468 if(*line == ':') 9469 { 9470 *line = '\0'; 9471 line++; 9472 } 9473 else 9474 { 9475 *line = '\0'; 9476 line++; 9477 9478 // search for the ':' char in the line 9479 while(*line == ' ' || *line == '\t' || *line == '\r') 9480 line++; 9481 9482 if(*line != ':') 9483 { 9484 SPX_MSG_INFO1(spxout, spxout << 9485 "Error parsing setting string: no ':' separating parameter type and name.\n"); 9486 return false; 9487 } 9488 9489 line++; 9490 } 9491 9492 // find the start of the parameter name 9493 while(*line == ' ' || *line == '\t' || *line == '\r') 9494 line++; 9495 9496 if(*line == '\0' || *line == '\n' || *line == '#') 9497 { 9498 SPX_MSG_INFO1(spxout, spxout << "Error parsing setting string: no parameter name.\n"); 9499 return false; 9500 } 9501 9502 char* paramName = line; 9503 9504 // find the end of the parameter name 9505 while(*line != ' ' && *line != '\t' && *line != '\r' && *line != '\n' && *line != '#' 9506 && *line != '\0' && *line != '=') 9507 line++; 9508 9509 if(*line == '=') 9510 { 9511 *line = '\0'; 9512 line++; 9513 } 9514 else 9515 { 9516 *line = '\0'; 9517 line++; 9518 9519 // search for the '=' char in the line 9520 while(*line == ' ' || *line == '\t' || *line == '\r') 9521 line++; 9522 9523 if(*line != '=') 9524 { 9525 SPX_MSG_INFO1(spxout, spxout << "Error parsing setting string: no '=' after parameter name.\n"); 9526 return false; 9527 } 9528 9529 line++; 9530 } 9531 9532 // find the start of the parameter value string 9533 while(*line == ' ' || *line == '\t' || *line == '\r') 9534 line++; 9535 9536 if(*line == '\0' || *line == '\n' || *line == '#') 9537 { 9538 SPX_MSG_INFO1(spxout, spxout << "Error parsing setting string: no parameter value.\n"); 9539 return false; 9540 } 9541 9542 char* paramValueString = line; 9543 9544 // find the end of the parameter value string 9545 while(*line != ' ' && *line != '\t' && *line != '\r' && *line != '\n' && *line != '#' 9546 && *line != '\0') 9547 line++; 9548 9549 if(*line != '\0') 9550 { 9551 // check, if the rest of the line is clean 9552 *line = '\0'; 9553 line++; 9554 9555 while(*line == ' ' || *line == '\t' || *line == '\r') 9556 line++; 9557 9558 if(*line != '\0' && *line != '\n' && *line != '#') 9559 { 9560 SPX_MSG_INFO1(spxout, spxout << "Error parsing setting string: additional character '" << *line << 9561 "' after parameter value.\n"); 9562 return false; 9563 } 9564 } 9565 9566 // check whether we have a bool parameter 9567 if(strncmp(paramTypeString, "bool", 4) == 0) 9568 { 9569 for(int param = 0; ; param++) 9570 { 9571 if(param >= SoPlexBase<R>::BOOLPARAM_COUNT) 9572 { 9573 SPX_MSG_INFO1(spxout, spxout << "Error parsing setting string: unknown parameter name <" << 9574 paramName << ">.\n"); 9575 return false; 9576 } 9577 else if(strncmp(paramName, _currentSettings->boolParam.name[param].c_str(), 9578 SPX_SET_MAX_LINE_LEN) == 0) 9579 { 9580 if(strncasecmp(paramValueString, "true", 4) == 0 9581 || strncasecmp(paramValueString, "TRUE", 4) == 0 9582 || strncasecmp(paramValueString, "t", 4) == 0 9583 || strncasecmp(paramValueString, "T", 4) == 0 9584 || strtol(paramValueString, NULL, 4) == 1) 9585 { 9586 success = setBoolParam((SoPlexBase<R>::BoolParam)param, true); 9587 break; 9588 } 9589 else if(strncasecmp(paramValueString, "false", 5) == 0 9590 || strncasecmp(paramValueString, "FALSE", 5) == 0 9591 || strncasecmp(paramValueString, "f", 5) == 0 9592 || strncasecmp(paramValueString, "F", 5) == 0 9593 || strtol(paramValueString, NULL, 5) == 0) 9594 { 9595 success = setBoolParam((SoPlexBase<R>::BoolParam)param, false); 9596 break; 9597 } 9598 else 9599 { 9600 SPX_MSG_INFO1(spxout, spxout << "Error parsing setting string: invalid value <" << paramValueString 9601 << "> for bool parameter <" << paramName << ">.\n"); 9602 return false; 9603 } 9604 } 9605 } 9606 9607 return success; 9608 } 9609 9610 // check whether we have an integer parameter 9611 if(strncmp(paramTypeString, "int", 3) == 0) 9612 { 9613 for(int param = 0; ; param++) 9614 { 9615 if(param >= SoPlexBase<R>::INTPARAM_COUNT) 9616 { 9617 SPX_MSG_INFO1(spxout, spxout << "Error parsing setting string: unknown parameter name <" << 9618 paramName << ">.\n"); 9619 return false; 9620 } 9621 else if(strncmp(paramName, _currentSettings->intParam.name[param].c_str(), 9622 SPX_SET_MAX_LINE_LEN) == 0) 9623 { 9624 int value; 9625 value = std::stoi(paramValueString); 9626 9627 if(setIntParam((SoPlexBase<R>::IntParam)param, value, false)) 9628 break; 9629 else 9630 { 9631 SPX_MSG_INFO1(spxout, spxout << "Error parsing setting string: invalid value <" << paramValueString 9632 << "> for int parameter <" << paramName << ">.\n"); 9633 return false; 9634 } 9635 } 9636 } 9637 9638 return true; 9639 } 9640 9641 // check whether we have a real parameter 9642 if(strncmp(paramTypeString, "real", 4) == 0) 9643 { 9644 for(int param = 0; ; param++) 9645 { 9646 if(param >= SoPlexBase<R>::REALPARAM_COUNT) 9647 { 9648 SPX_MSG_INFO1(spxout, spxout << "Error parsing setting string: unknown parameter name <" << 9649 paramName << ">.\n"); 9650 return false; 9651 } 9652 else if(strncmp(paramName, _currentSettings->realParam.name[param].c_str(), 9653 SPX_SET_MAX_LINE_LEN) == 0) 9654 { 9655 Real value; 9656 #ifdef WITH_LONG_DOUBLE 9657 value = std::stold(paramValueString); 9658 #else 9659 #ifdef WITH_FLOAT 9660 value = std::stof(paramValueString); 9661 #else 9662 value = std::stod(paramValueString); 9663 #endif 9664 #endif 9665 9666 if(setRealParam((SoPlexBase<R>::RealParam)param, value)) 9667 break; 9668 else 9669 { 9670 SPX_MSG_INFO1(spxout, spxout << "Error parsing setting string: invalid value <" << paramValueString 9671 << "> for real parameter <" << paramName << ">.\n"); 9672 return false; 9673 } 9674 } 9675 } 9676 9677 return true; 9678 } 9679 9680 #ifdef SOPLEX_WITH_RATIONALPARAM 9681 9682 // check whether we have a rational parameter 9683 if(strncmp(paramTypeString, "rational", 8) == 0) 9684 { 9685 for(int param = 0; ; param++) 9686 { 9687 if(param >= SoPlexBase<R>::RATIONALPARAM_COUNT) 9688 { 9689 SPX_MSG_INFO1(spxout, spxout << "Error parsing setting string: unknown parameter name <" << 9690 paramName << ">.\n"); 9691 return false; 9692 } 9693 else if(strncmp(paramName, _currentSettings->rationalParam.name[param].c_str(), 9694 SPX_SET_MAX_LINE_LEN) == 0) 9695 { 9696 Rational value; 9697 9698 if(readStringRational(paramValueString, value) 9699 && setRationalParam((SoPlexBase<R>::RationalParam)param, value)) 9700 break; 9701 else 9702 { 9703 SPX_MSG_INFO1(spxout, spxout << "Error parsing setting string: invalid value <" << paramValueString 9704 << "> for rational parameter <" << paramName << ">.\n"); 9705 return false; 9706 } 9707 } 9708 } 9709 9710 return true; 9711 } 9712 9713 #endif 9714 9715 // check whether we have the random seed 9716 if(strncmp(paramTypeString, "uint", 4) == 0) 9717 { 9718 if(strncmp(paramName, "random_seed", 11) == 0) 9719 { 9720 unsigned int value; 9721 unsigned long parseval; 9722 9723 parseval = std::stoul(paramValueString); 9724 9725 if(parseval > UINT_MAX) 9726 { 9727 value = UINT_MAX; 9728 SPX_MSG_WARNING(spxout, spxout << "Converting number greater than UINT_MAX to uint.\n"); 9729 } 9730 else 9731 value = (unsigned int) parseval; 9732 9733 setRandomSeed(value); 9734 return true; 9735 } 9736 9737 SPX_MSG_INFO1(spxout, spxout << "Error parsing setting string for uint parameter <random_seed>.\n"); 9738 return false; 9739 } 9740 9741 SPX_MSG_INFO1(spxout, spxout << "Error parsing setting string: invalid parameter type <" << 9742 paramTypeString << "> for parameter <" << paramName << ">.\n"); 9743 9744 return false; 9745 } 9746 9747 /// writes settings file; returns true on success 9748 template <class R> 9749 bool SoPlexBase<R>::saveSettingsFile(const char* filename, const bool onlyChanged, 9750 int solvemode) const 9751 { 9752 assert(filename != 0); 9753 9754 std::ofstream file(filename); 9755 SPxOut::setScientific(file, 16); 9756 9757 if(!file.good()) 9758 return false; 9759 9760 file.setf(std::ios::left); 9761 9762 SPxOut::setFixed(file); 9763 9764 file << "# SoPlexBase version " << SOPLEX_VERSION / 100 << "." << (SOPLEX_VERSION / 10) % 10 << "." 9765 << SOPLEX_VERSION % 10; 9766 #if SOPLEX_SUBVERSION > 0 9767 file << "." << SOPLEX_SUBVERSION; 9768 #endif 9769 file << "\n"; 9770 9771 for(int i = 0; i < SoPlexBase<R>::BOOLPARAM_COUNT; i++) 9772 { 9773 if(onlyChanged 9774 && _currentSettings->_boolParamValues[i] == _currentSettings->boolParam.defaultValue[i]) 9775 continue; 9776 9777 file << "\n"; 9778 file << "# " << _currentSettings->boolParam.description[i] << "\n"; 9779 file << "# range {true, false}, default " << (_currentSettings->boolParam.defaultValue[i] ? 9780 "true\n" : "false\n"); 9781 file << "bool:" << _currentSettings->boolParam.name[i] << " = " << 9782 (_currentSettings->_boolParamValues[i] ? "true\n" : "false\n"); 9783 } 9784 9785 for(int i = 0; i < SoPlexBase<R>::INTPARAM_COUNT; i++) 9786 { 9787 if(onlyChanged 9788 && _currentSettings->_intParamValues[i] == _currentSettings->intParam.defaultValue[i]) 9789 continue; 9790 9791 file << "\n"; 9792 file << "# " << _currentSettings->intParam.description[i] << "\n"; 9793 file << "# range [" << _currentSettings->intParam.lower[i] << "," << 9794 _currentSettings->intParam.upper[i] 9795 << "], default " << _currentSettings->intParam.defaultValue[i] << "\n"; 9796 file << "int:" << _currentSettings->intParam.name[i] << " = " << 9797 _currentSettings->_intParamValues[i] << "\n"; 9798 } 9799 9800 SPxOut::setScientific(file); 9801 9802 for(int i = 0; i < SoPlexBase<R>::REALPARAM_COUNT; i++) 9803 { 9804 if(onlyChanged 9805 && _currentSettings->_realParamValues[i] == _currentSettings->realParam.defaultValue[i]) 9806 continue; 9807 9808 file << "\n"; 9809 file << "# " << _currentSettings->realParam.description[i] << "\n"; 9810 file << "# range [" << _currentSettings->realParam.lower[i] << "," << 9811 _currentSettings->realParam.upper[i] 9812 << "], default " << _currentSettings->realParam.defaultValue[i] << "\n"; 9813 file << "real:" << _currentSettings->realParam.name[i] << " = " << 9814 _currentSettings->_realParamValues[i] << "\n"; 9815 } 9816 9817 #ifdef SOPLEX_WITH_RATIONALPARAM 9818 9819 for(int i = 0; i < SoPlexBase<R>::RATIONALPARAM_COUNT; i++) 9820 { 9821 if(onlyChanged 9822 && _currentSettings->_rationalParamValues[i] == _currentSettings->rationalParam.defaultValue[i]) 9823 continue; 9824 9825 file << "\n"; 9826 file << "# " << _currentSettings->rationalParam.description[i] << "\n"; 9827 file << "# range [" << _currentSettings->rationalParam.lower[i] << "," << 9828 _currentSettings->rationalParam.upper[i] 9829 << "], default " << _currentSettings->rationalParam.defaultValue[i] << "\n"; 9830 file << "rational:" << _currentSettings->rationalParam.name[i] << " = " << 9831 _currentSettings->_rationalParamValues[i] << "\n"; 9832 } 9833 9834 #endif 9835 9836 if(!onlyChanged || _solver.random.getSeed() != SOPLEX_DEFAULT_RANDOM_SEED) 9837 { 9838 file << "\n"; 9839 file << "# initial random seed used for perturbation\n"; 9840 file << "# range [0, " << UINT_MAX << "], default " << SOPLEX_DEFAULT_RANDOM_SEED << "\n"; 9841 file << "uint:random_seed = " << _solver.random.getSeed() << "\n"; 9842 } 9843 9844 return true; 9845 } 9846 9847 9848 9849 /// reads LP file in LP or MPS format according to READMODE parameter; gets row names, column names, and 9850 /// integer variables if desired; returns true on success 9851 9852 template <class R> 9853 bool SoPlexBase<R>::readFile(const char* filename, NameSet* rowNames, NameSet* colNames, 9854 DIdxSet* intVars) 9855 { 9856 bool success = false; 9857 9858 if(intParam(SoPlexBase<R>::READMODE) == READMODE_REAL) 9859 success = _readFileReal(filename, rowNames, colNames, intVars); 9860 else 9861 success = _readFileRational(filename, rowNames, colNames, intVars); 9862 9863 // storing the row and column names for use in the DBDS print basis methods 9864 _rowNames = rowNames; 9865 _colNames = colNames; 9866 9867 return success; 9868 } 9869 9870 9871 9872 /// writes R LP to file; LP or MPS format is chosen from the extension in \p filename; if \p rowNames and \p 9873 /// colNames are \c NULL, default names are used; if \p intVars is not \c NULL, the variables contained in it are 9874 /// marked as integer; returns true on success 9875 template <class R> 9876 bool SoPlexBase<R>::writeFile(const char* filename, const NameSet* rowNames, 9877 const NameSet* colNames, const DIdxSet* intVars, const bool unscale) const 9878 { 9879 ///@todo implement return value 9880 if(unscale && _realLP->isScaled()) 9881 { 9882 SPX_MSG_INFO3(spxout, spxout << "copy LP to write unscaled original problem" << std::endl;) 9883 SPxLPBase<R>* origLP; 9884 origLP = nullptr; 9885 spx_alloc(origLP); 9886 origLP = new(origLP) SPxLPBase<R>(*_realLP); 9887 origLP->unscaleLP(); 9888 origLP->writeFileLPBase(filename, rowNames, colNames, intVars); 9889 origLP->~SPxLPBase<R>(); 9890 spx_free(origLP); 9891 } 9892 else 9893 _realLP->writeFileLPBase(filename, rowNames, colNames, intVars); 9894 9895 return true; 9896 } 9897 9898 9899 /// writes the dual of the R LP to file; LP or MPS format is chosen from the extension in \p filename; 9900 /// if \p rowNames and \p colNames are \c NULL, default names are used; if \p intVars is not \c NULL, 9901 /// the variables contained in it are marked as integer; returns true on success 9902 template <class R> 9903 bool SoPlexBase<R>::writeDualFileReal(const char* filename, const NameSet* rowNames, 9904 const NameSet* colNames, const DIdxSet* intVars) const 9905 { 9906 SPxLPBase<R> dualLP; 9907 _realLP->buildDualProblem(dualLP); 9908 dualLP.setOutstream(spxout); 9909 9910 // swap colnames and rownames 9911 dualLP.writeFileLPBase(filename, colNames, rowNames); 9912 return true; 9913 } 9914 9915 9916 9917 /// reads basis information from \p filename and returns true on success; if \p rowNames and \p colNames are \c NULL, 9918 /// default names are assumed; returns true on success 9919 template <class R> 9920 bool SoPlexBase<R>::readBasisFile(const char* filename, const NameSet* rowNames, 9921 const NameSet* colNames) 9922 { 9923 clearBasis(); 9924 /// @todo can't we just remove the else code? 9925 #if 1 9926 assert(filename != 0); 9927 assert(_realLP != 0); 9928 9929 // start timing 9930 _statistics->readingTime->start(); 9931 9932 // read 9933 if(!_isRealLPLoaded) 9934 { 9935 assert(_realLP != &_solver); 9936 9937 _solver.loadLP(*_realLP); 9938 _realLP->~SPxLPBase<R>(); 9939 spx_free(_realLP); 9940 _realLP = &_solver; 9941 _isRealLPLoaded = true; 9942 } 9943 9944 _hasBasis = _solver.readBasisFile(filename, rowNames, colNames); 9945 assert(_hasBasis == (_solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM)); 9946 9947 // stop timing 9948 _statistics->readingTime->stop(); 9949 9950 return _hasBasis; 9951 #else 9952 // this is alternative code for reading bases without the SPxSolverBase class 9953 assert(filename != 0); 9954 9955 // start timing 9956 _statistics->readingTime->start(); 9957 9958 // read 9959 spxifstream file(filename); 9960 9961 if(!file) 9962 return false; 9963 9964 // get problem size 9965 int numRows = numRows(); 9966 int numCols = numCols(); 9967 9968 // prepare column names 9969 const NameSet* colNamesPtr = colNames; 9970 NameSet* tmpColNames = 0; 9971 9972 if(colNames == 0) 9973 { 9974 std::stringstream name; 9975 9976 spx_alloc(tmpColNames); 9977 tmpColNames = new(tmpColNames) NameSet(); 9978 tmpColNames->reMax(numCols); 9979 9980 for(int j = 0; j < numCols; ++j) 9981 { 9982 name << "x" << j; 9983 tmpColNames->add(name.str().c_str()); 9984 } 9985 9986 colNamesPtr = tmpColNames; 9987 } 9988 9989 // prepare row names 9990 const NameSet* rowNamesPtr = rowNames; 9991 NameSet* tmpRowNames = 0; 9992 9993 if(rowNamesPtr == 0) 9994 { 9995 std::stringstream name; 9996 9997 spx_alloc(tmpRowNames); 9998 tmpRowNames = new(tmpRowNames) NameSet(); 9999 tmpRowNames->reMax(numRows); 10000 10001 for(int i = 0; i < numRows; ++i) 10002 { 10003 name << "C" << i; 10004 tmpRowNames->add(name.str().c_str()); 10005 } 10006 10007 rowNamesPtr = tmpRowNames; 10008 } 10009 10010 // initialize with default slack basis 10011 _basisStatusRows.reSize(numRows); 10012 _basisStatusCols.reSize(numCols); 10013 10014 for(int i = 0; i < numRows; i++) 10015 _basisStatusRows[i] = SPxSolverBase<R>::BASIC; 10016 10017 for(int i = 0; i < numCols; i++) 10018 { 10019 if(lowerRealInternal(i) == upperRealInternal(i)) 10020 _basisStatusCols[i] = SPxSolverBase<R>::FIXED; 10021 else if(lowerRealInternal(i) <= double(-realParam(SoPlexBase<R>::INFTY)) 10022 && upperRealInternal(i) >= double(realParam(SoPlexBase<R>::INFTY))) 10023 _basisStatusCols[i] = SPxSolverBase<R>::ZERO; 10024 else if(lowerRealInternal(i) <= double(-realParam(SoPlexBase<R>::INFTY))) 10025 _basisStatusCols[i] = SPxSolverBase<R>::ON_UPPER; 10026 else 10027 _basisStatusCols[i] = SPxSolverBase<R>::ON_LOWER; 10028 } 10029 10030 // read basis 10031 MPSInput mps(file); 10032 10033 if(mps.readLine() && (mps.field0() != 0) && !strcmp(mps.field0(), "NAME")) 10034 { 10035 while(mps.readLine()) 10036 { 10037 int c = -1; 10038 int r = -1; 10039 10040 if(mps.field0() != 0 && !strcmp(mps.field0(), "ENDATA")) 10041 { 10042 mps.setSection(MPSInput::ENDATA); 10043 break; 10044 } 10045 10046 if(mps.field1() == 0 || mps.field2() == 0) 10047 break; 10048 10049 if((c = colNamesPtr->number(mps.field2())) < 0) 10050 break; 10051 10052 if(*mps.field1() == 'X') 10053 { 10054 if(mps.field3() == 0 || (r = rowNamesPtr->number(mps.field3())) < 0) 10055 break; 10056 } 10057 10058 if(!strcmp(mps.field1(), "XU")) 10059 { 10060 _basisStatusCols[c] = SPxSolverBase<R>::BASIC; 10061 10062 if(_rowTypes[r] == SoPlexBase<R>::RANGETYPE_LOWER) 10063 _basisStatusRows[r] = SPxSolverBase<R>::ON_LOWER; 10064 else if(_rowTypes[r] == SoPlexBase<R>::RANGETYPE_FIXED) 10065 _basisStatusRows[r] = SPxSolverBase<R>::FIXED; 10066 else 10067 _basisStatusRows[r] = SPxSolverBase<R>::ON_UPPER; 10068 } 10069 else if(!strcmp(mps.field1(), "XL")) 10070 { 10071 _basisStatusCols[c] = SPxSolverBase<R>::BASIC; 10072 10073 if(_rowTypes[r] == SoPlexBase<R>::RANGETYPE_UPPER) 10074 _basisStatusRows[r] = SPxSolverBase<R>::ON_UPPER; 10075 else if(_rowTypes[r] == SoPlexBase<R>::RANGETYPE_FIXED) 10076 _basisStatusRows[r] = SPxSolverBase<R>::FIXED; 10077 else 10078 _basisStatusRows[r] = SPxSolverBase<R>::ON_LOWER; 10079 } 10080 else if(!strcmp(mps.field1(), "UL")) 10081 { 10082 _basisStatusCols[c] = SPxSolverBase<R>::ON_UPPER; 10083 } 10084 else if(!strcmp(mps.field1(), "LL")) 10085 { 10086 _basisStatusCols[c] = SPxSolverBase<R>::ON_LOWER; 10087 } 10088 else 10089 { 10090 mps.syntaxError(); 10091 break; 10092 } 10093 } 10094 } 10095 10096 if(rowNames == 0) 10097 { 10098 tmpRowNames->~NameSet(); 10099 spx_free(tmpRowNames); 10100 } 10101 10102 if(colNames == 0) 10103 { 10104 tmpColNames->~NameSet(); 10105 spx_free(tmpColNames); 10106 } 10107 10108 _hasBasis = !mps.hasError(); 10109 10110 // stop timing 10111 _statistics->readingTime->stop(); 10112 10113 return _hasBasis; 10114 #endif 10115 } 10116 10117 10118 /// solves the LP 10119 /// R specialization of the optimize function 10120 template <class R> 10121 typename SPxSolverBase<R>::Status SoPlexBase<R>::optimize(volatile bool* interrupt) 10122 { 10123 assert(_isConsistent()); 10124 10125 // clear statistics 10126 _statistics->clearSolvingData(); 10127 10128 // the solution is no longer valid 10129 _invalidateSolution(); 10130 10131 // if the decomposition based dual simplex flag is set to true 10132 if(boolParam(SoPlexBase<R>::USEDECOMPDUALSIMPLEX)) 10133 { 10134 setIntParam(SoPlexBase<R>::SOLVEMODE, SOLVEMODE_REAL); 10135 setIntParam(SoPlexBase<R>::REPRESENTATION, REPRESENTATION_ROW); 10136 setIntParam(SoPlexBase<R>::ALGORITHM, ALGORITHM_DUAL); 10137 //setBoolParam(SoPlexBase<R>::PERSISTENTSCALING, false); 10138 10139 _solver.setComputeDegenFlag(boolParam(COMPUTEDEGEN)); 10140 10141 _solveDecompositionDualSimplex(); 10142 } 10143 // decide whether to solve the rational LP with iterative refinement or call the standard floating-point solver 10144 else if(intParam(SoPlexBase<R>::SOLVEMODE) == SOLVEMODE_REAL 10145 || (intParam(SoPlexBase<R>::SOLVEMODE) == SOLVEMODE_AUTO 10146 && realParam(SoPlexBase<R>::FEASTOL) >= 1e-9 && realParam(SoPlexBase<R>::OPTTOL) >= 1e-9)) 10147 { 10148 // the only tolerances used are the ones for the floating-point solver, so set them to the global tolerances 10149 this->tolerances()->setFloatingPointFeastol(realParam(SoPlexBase<R>::FEASTOL)); 10150 this->tolerances()->setFloatingPointOpttol(realParam(SoPlexBase<R>::OPTTOL)); 10151 10152 // ensure that tolerances are reasonable for the floating-point solver 10153 // todo: refactor to take into account epsilon value instead 10154 if(this->tolerances()->floatingPointFeastol() < 10155 _currentSettings->realParam.lower[SoPlexBase<R>::FPFEASTOL]) 10156 { 10157 SPX_MSG_WARNING(spxout, spxout << 10158 "Cannot call floating-point solver with feasibility tolerance below " 10159 << _currentSettings->realParam.lower[SoPlexBase<R>::FPFEASTOL] << " - relaxing tolerance\n"); 10160 this->_tolerances->setFloatingPointFeastol( 10161 _currentSettings->realParam.lower[SoPlexBase<R>::FPFEASTOL]); 10162 } 10163 10164 if(this->tolerances()->floatingPointOpttol() < 10165 _currentSettings->realParam.lower[SoPlexBase<R>::FPOPTTOL]) 10166 { 10167 SPX_MSG_WARNING(spxout, spxout << 10168 "Cannot call floating-point solver with optimality tolerance below " 10169 << _currentSettings->realParam.lower[SoPlexBase<R>::FPOPTTOL] << " - relaxing tolerance\n"); 10170 this->_tolerances->setFloatingPointOpttol( 10171 _currentSettings->realParam.lower[SoPlexBase<R>::FPOPTTOL]); 10172 } 10173 10174 _solver.setComputeDegenFlag(boolParam(COMPUTEDEGEN)); 10175 _solver.setSolvingForBoosted(false); 10176 10177 _optimize(interrupt); 10178 #ifdef SOPLEX_DEBUG // this check will remove scaling of the realLP 10179 _checkBasisScaling(); 10180 #endif 10181 } 10182 else if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_ONLYREAL) 10183 { 10184 _syncLPRational(); 10185 _optimizeRational(interrupt); 10186 } 10187 else if(intParam(SoPlexBase<R>::SYNCMODE) == SYNCMODE_MANUAL) 10188 { 10189 #ifdef ENABLE_ADDITIONAL_CHECKS 10190 assert(areLPsInSync(true, true, false)); 10191 #else 10192 assert(areLPsInSync(true, false, false)); 10193 #endif 10194 10195 _optimizeRational(interrupt); 10196 10197 #ifdef ENABLE_ADDITIONAL_CHECKS 10198 assert(areLPsInSync(true, true, false)); 10199 #else 10200 assert(areLPsInSync(true, false, false)); 10201 #endif 10202 } 10203 else 10204 { 10205 #ifdef ENABLE_ADDITIONAL_CHECKS 10206 assert(areLPsInSync(true, true, false)); 10207 #else 10208 assert(areLPsInSync(true, false, false)); 10209 #endif 10210 10211 _optimizeRational(interrupt); 10212 } 10213 10214 SPX_MSG_INFO1(spxout, spxout << "\n"; 10215 printShortStatistics(spxout.getStream(SPxOut::INFO1)); 10216 spxout << "\n"); 10217 10218 10219 return status(); 10220 } 10221 10222 10223 // @todo: temporary fix. Needs to be looked later 10224 /// prints complete statistics 10225 template <class R> 10226 void SoPlexBase<R>::printStatistics(std::ostream& os) 10227 { 10228 SPxOut::setFixed(os, 2); 10229 10230 printStatus(os, _status); 10231 10232 os << "Original problem : \n"; 10233 10234 if(boolParam(SoPlexBase<R>::USEDECOMPDUALSIMPLEX)) 10235 printOriginalProblemStatistics(os); 10236 else 10237 { 10238 if(intParam(SoPlexBase<R>::READMODE) == READMODE_REAL) 10239 _realLP->printProblemStatistics(os); 10240 else 10241 _rationalLP->printProblemStatistics(os); 10242 } 10243 10244 os << "Objective sense : " << (intParam(SoPlexBase<R>::OBJSENSE) == 10245 SoPlexBase<R>::OBJSENSE_MINIMIZE ? "minimize\n" : "maximize\n"); 10246 printSolutionStatistics(os); 10247 printSolvingStatistics(os); 10248 } 10249 10250 // @todo temporary fix. Need to think about precision later 10251 /// prints short statistics 10252 template <class R> 10253 void SoPlexBase<R>::printShortStatistics(std::ostream& os) 10254 { 10255 printStatus(os, _status); 10256 SPxOut::setFixed(os, 2); 10257 os << "Solving time (sec) : " << this->_statistics->solvingTime->time() << "\n" 10258 << "Iterations : " << this->_statistics->iterations << "\n"; 10259 SPxOut::setScientific(os); 10260 os << "Objective value : " << objValueReal() << "\n"; 10261 } 10262 // @todo: temporary fix need to worry about precision 10263 /// writes basis information to \p filename; if \p rowNames and \p colNames are \c NULL, default names are used; 10264 /// returns true on success 10265 template <class R> 10266 bool SoPlexBase<R>::writeBasisFile(const char* filename, const NameSet* rowNames, 10267 const NameSet* colNames, const bool cpxFormat) const 10268 { 10269 assert(filename != 0); 10270 10271 if(_isRealLPLoaded) 10272 return _solver.writeBasisFile(filename, rowNames, colNames, cpxFormat); 10273 else 10274 { 10275 std::ofstream file(filename); 10276 10277 if(!file.good()) 10278 return false; 10279 10280 file.setf(std::ios::left); 10281 file << "NAME " << filename << "\n"; 10282 10283 // do not write basis if there is none 10284 if(!_hasBasis) 10285 { 10286 file << "ENDATA\n"; 10287 return true; 10288 } 10289 10290 // start writing 10291 int numRows = _basisStatusRows.size(); 10292 int numCols = _basisStatusCols.size(); 10293 int row = 0; 10294 10295 for(int col = 0; col < numCols; col++) 10296 { 10297 assert(_basisStatusCols[col] != SPxSolverBase<R>::UNDEFINED); 10298 10299 if(_basisStatusCols[col] == SPxSolverBase<R>::BASIC) 10300 { 10301 // find nonbasic row 10302 for(; row < numRows; row++) 10303 { 10304 assert(_basisStatusRows[row] != SPxSolverBase<R>::UNDEFINED); 10305 10306 if(_basisStatusRows[row] != SPxSolverBase<R>::BASIC) 10307 break; 10308 } 10309 10310 assert(row != numRows); 10311 10312 if(_basisStatusRows[row] == SPxSolverBase<R>::ON_UPPER && (!cpxFormat 10313 || _rowTypes[row] == SoPlexBase<R>::RANGETYPE_BOXED)) 10314 file << " XU "; 10315 else 10316 file << " XL "; 10317 10318 file << std::setw(8); 10319 10320 if(colNames != 0 && colNames->has(col)) 10321 file << (*colNames)[col]; 10322 else 10323 file << "x" << col; 10324 10325 file << " "; 10326 10327 if(rowNames != 0 && rowNames->has(row)) 10328 file << (*rowNames)[row]; 10329 else 10330 file << "C" << row; 10331 10332 file << "\n"; 10333 row++; 10334 } 10335 else 10336 { 10337 if(_basisStatusCols[col] == SPxSolverBase<R>::ON_UPPER) 10338 { 10339 file << " UL "; 10340 10341 file << std::setw(8); 10342 10343 if(colNames != 0 && colNames->has(col)) 10344 file << (*colNames)[col]; 10345 else 10346 file << "x" << col; 10347 10348 file << "\n"; 10349 } 10350 } 10351 } 10352 10353 file << "ENDATA\n"; 10354 10355 #ifndef NDEBUG 10356 10357 // check that the remaining rows are basic 10358 for(; row < numRows; row++) 10359 { 10360 assert(_basisStatusRows[row] == SPxSolverBase<R>::BASIC); 10361 } 10362 10363 #endif 10364 10365 return true; 10366 } 10367 } 10368 10369 /// set statistic timers to a certain type, used to turn off statistic time measurement 10370 template <class R> 10371 void SoPlexBase<R>::setTimings(const Timer::TYPE ttype) 10372 { 10373 _slufactor.changeTimer(ttype); 10374 _statistics->readingTime = TimerFactory::switchTimer(_statistics->readingTime, ttype); 10375 _statistics->simplexTime = TimerFactory::switchTimer(_statistics->simplexTime, ttype); 10376 _statistics->syncTime = TimerFactory::switchTimer(_statistics->syncTime, ttype); 10377 _statistics->solvingTime = TimerFactory::switchTimer(_statistics->solvingTime, ttype); 10378 _statistics->preprocessingTime = TimerFactory::switchTimer(_statistics->preprocessingTime, ttype); 10379 _statistics->rationalTime = TimerFactory::switchTimer(_statistics->rationalTime, ttype); 10380 _statistics->transformTime = TimerFactory::switchTimer(_statistics->transformTime, ttype); 10381 _statistics->reconstructionTime = TimerFactory::switchTimer(_statistics->reconstructionTime, ttype); 10382 _statistics->boostingStepTime = TimerFactory::switchTimer(_statistics->boostingStepTime, ttype); 10383 } 10384 10385 /// prints solution statistics 10386 template <class R> 10387 void SoPlexBase<R>::printSolutionStatistics(std::ostream& os) 10388 { 10389 SPxOut::setScientific(os); 10390 10391 if(_lastSolveMode == SOLVEMODE_REAL) 10392 { 10393 os << "Solution (real) : \n" 10394 << " Objective value : " << objValueReal() << "\n"; 10395 } 10396 else if(_lastSolveMode == SOLVEMODE_RATIONAL) 10397 { 10398 os << "Solution (rational) : \n" 10399 << " Objective value : " << objValueRational() << "\n"; 10400 os << "Size (base 2/10) : \n" 10401 << " Total primal : " << totalSizePrimalRational() << " / " << totalSizePrimalRational( 10402 10) << "\n" 10403 << " Total dual : " << totalSizeDualRational() << " / " << totalSizeDualRational(10) << "\n" 10404 << " DLCM primal : " << dlcmSizePrimalRational() << " / " << dlcmSizePrimalRational( 10405 10) << "\n" 10406 << " DLCM dual : " << dlcmSizeDualRational() << " / " << dlcmSizeDualRational(10) << "\n" 10407 << " DMAX primal : " << dmaxSizePrimalRational() << " / " << dmaxSizePrimalRational( 10408 10) << "\n" 10409 << " DMAX dual : " << dmaxSizeDualRational() << " / " << dmaxSizeDualRational(10) << "\n"; 10410 } 10411 else 10412 { 10413 os << "Solution : \n" 10414 << " Objective value : -\n"; 10415 } 10416 10417 if(intParam(CHECKMODE) == CHECKMODE_RATIONAL 10418 || (intParam(CHECKMODE) == CHECKMODE_AUTO && intParam(READMODE) == READMODE_RATIONAL)) 10419 { 10420 Rational maxviol; 10421 Rational sumviol; 10422 10423 os << "Violation (rational): \n"; 10424 10425 if(getBoundViolationRational(maxviol, sumviol)) 10426 os << " Max/sum bound : " << maxviol.str() << " / " << sumviol.str() << "\n"; 10427 else 10428 os << " Max/sum bound : - / -\n"; 10429 10430 if(getRowViolationRational(maxviol, sumviol)) 10431 os << " Max/sum row : " << maxviol.str() << " / " << sumviol.str() << "\n"; 10432 else 10433 os << " Max/sum row : - / -\n"; 10434 10435 if(getRedCostViolationRational(maxviol, sumviol)) 10436 os << " Max/sum redcost : " << maxviol.str() << " / " << sumviol.str() << "\n"; 10437 else 10438 os << " Max/sum redcost : - / -\n"; 10439 10440 if(getDualViolationRational(maxviol, sumviol)) 10441 os << " Max/sum dual : " << maxviol.str() << " / " << sumviol.str() << "\n"; 10442 else 10443 os << " Max/sum dual : - / -\n"; 10444 } 10445 else 10446 { 10447 R maxviol; 10448 R sumviol; 10449 10450 os << "Violations (real) : \n"; 10451 10452 if(getBoundViolation(maxviol, sumviol)) 10453 os << " Max/sum bound : " << maxviol << " / " << sumviol << "\n"; 10454 else 10455 os << " Max/sum bound : - / -\n"; 10456 10457 if(getRowViolation(maxviol, sumviol)) 10458 os << " Max/sum row : " << maxviol << " / " << sumviol << "\n"; 10459 else 10460 os << " Max/sum row : - / -\n"; 10461 10462 if(getRedCostViolation(maxviol, sumviol)) 10463 os << " Max/sum redcost : " << maxviol << " / " << sumviol << "\n"; 10464 else 10465 os << " Max/sum redcost : - / -\n"; 10466 10467 if(getDualViolation(maxviol, sumviol)) 10468 os << " Max/sum dual : " << maxviol << " / " << sumviol << "\n"; 10469 else 10470 os << " Max/sum dual : - / -\n"; 10471 } 10472 } 10473 10474 10475 /// prints statistics on solving process 10476 template <class R> 10477 void SoPlexBase<R>::printSolvingStatistics(std::ostream& os) 10478 { 10479 assert(_statistics != 0); 10480 _statistics->print(os); 10481 } 10482 10483 10484 10485 } // namespace soplex 10486