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