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