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