Scippy

SoPlex

Sequential object-oriented simPlex

soplexmain.cpp
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the class library */
4 /* SoPlex --- the Sequential object-oriented simPlex. */
5 /* */
6 /* Copyright (C) 1996-2020 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 soplexmain.cpp
17  * @brief Command line interface of SoPlex LP solver
18  */
19 
20 #include <assert.h>
21 #include <math.h>
22 #include <string.h>
23 
24 #include <iostream>
25 #include <iomanip>
26 #include <fstream>
27 #include <memory>
28 
29 #include <boost/program_options.hpp>
30 #include <exception>
31 #include <boost/exception/diagnostic_information.hpp>
32 #include <boost/exception/exception.hpp>
33 
34 #include "soplex.h"
35 #include "soplex/validation.h"
36 #include "soplex/statistics.h"
37 #include "soplex/args.hpp" // For argument parsing
38 
39 
40 #ifdef SOPLEX_WITH_EGLIB
41 extern "C" {
42 #include "soplex/EGlib.h"
43 }
44 #else
45 #define EGlpNumStart() {}
46 #define EGlpNumClear() {}
47 #endif
48 
49 using namespace soplex;
50 
51 // function prototype
52 int main(int argc, char* argv[]);
53 
54 /// performs external feasibility check with real type
55 ///@todo implement external check; currently we use the internal methods for convenience
56 
57 template <class R>
58 static
60 {
61  if(soplex.hasPrimal())
62  {
63  R boundviol;
64  R rowviol;
65  R sumviol;
66 
67  if(soplex.getBoundViolation(boundviol, sumviol) && soplex.getRowViolation(rowviol, sumviol))
68  {
69  MSG_INFO1(soplex.spxout,
70  R maxviol = boundviol > rowviol ? boundviol : rowviol;
71  bool feasible = (maxviol <= soplex.realParam(SoPlexBase<R>::FEASTOL));
72  soplex.spxout << "Primal solution " << (feasible ? "feasible" : "infeasible")
73  << " in original problem (max. violation = " << std::scientific << maxviol
74  << std::setprecision(8) << std::fixed << ").\n");
75  }
76  else
77  {
78  MSG_INFO1(soplex.spxout, soplex.spxout << "Could not check primal solution.\n");
79  }
80  }
81  else
82  {
83  MSG_INFO1(soplex.spxout, soplex.spxout << "No primal solution available.\n");
84  }
85 
86  if(soplex.hasDual())
87  {
88  R redcostviol;
89  R dualviol;
90  R sumviol;
91 
92  if(soplex.getRedCostViolation(redcostviol, sumviol) && soplex.getDualViolation(dualviol, sumviol))
93  {
94  MSG_INFO1(soplex.spxout,
95  R maxviol = redcostviol > dualviol ? redcostviol : dualviol;
96  bool feasible = (maxviol <= soplex.realParam(SoPlexBase<R>::OPTTOL));
97  soplex.spxout << "Dual solution " << (feasible ? "feasible" : "infeasible")
98  << " in original problem (max. violation = " << std::scientific << maxviol
99  << std::setprecision(8) << std::fixed << ").\n"
100  );
101  }
102  else
103  {
104  MSG_INFO1(soplex.spxout, soplex.spxout << "Could not check dual solution.\n");
105  }
106  }
107  else
108  {
109  MSG_INFO1(soplex.spxout, soplex.spxout << "No dual solution available.\n");
110  }
111 }
112 
113 /// performs external feasibility check with rational type
114 ///@todo implement external check; currently we use the internal methods for convenience
115 template <class R>
117 {
118  if(soplex.hasPrimal())
119  {
120  Rational boundviol;
121  Rational rowviol;
122  Rational sumviol;
123 
124  if(soplex.getBoundViolationRational(boundviol, sumviol)
125  && soplex.getRowViolationRational(rowviol, sumviol))
126  {
127  MSG_INFO1(soplex.spxout,
128  Rational maxviol = boundviol > rowviol ? boundviol : rowviol;
129  bool feasible = (maxviol <= soplex.realParam(SoPlexBase<R>::FEASTOL));
130  soplex.spxout << "Primal solution " << (feasible ? "feasible" : "infeasible") <<
131  " in original problem (max. violation = " << rationalToString(maxviol) << ").\n"
132  );
133  }
134  else
135  {
136  MSG_INFO1(soplex.spxout, soplex.spxout << "Could not check primal solution.\n");
137  }
138  }
139  else
140  {
141  MSG_INFO1(soplex.spxout, soplex.spxout << "No primal solution available.\n");
142  }
143 
144  if(soplex.hasDual())
145  {
146  Rational redcostviol;
147  Rational dualviol;
148  Rational sumviol;
149 
150  if(soplex.getRedCostViolationRational(redcostviol, sumviol)
151  && soplex.getDualViolationRational(dualviol, sumviol))
152  {
153  MSG_INFO1(soplex.spxout,
154  Rational maxviol = redcostviol > dualviol ? redcostviol : dualviol;
155  bool feasible = (maxviol <= soplex.realParam(SoPlexBase<R>::OPTTOL));
156  soplex.spxout << "Dual solution " << (feasible ? "feasible" : "infeasible") <<
157  " in original problem (max. violation = " << rationalToString(maxviol) << ").\n"
158  );
159  }
160  else
161  {
162  MSG_INFO1(soplex.spxout, soplex.spxout << "Could not check dual solution.\n");
163  }
164  }
165  else
166  {
167  MSG_INFO1(soplex.spxout, soplex.spxout << "No dual solution available.\n");
168  }
169 }
170 
171 /// performs external feasibility check according to check mode
172 template <class R>
174 {
178  {
179  checkSolutionRational(soplex);
180  }
181  else
182  {
183  checkSolutionReal(soplex);
184  }
185 
186  MSG_INFO1(soplex.spxout, soplex.spxout << "\n");
187 }
188 
189 template <class R>
190 static
192  bool real = true, bool rational = false)
193 {
194  int printprec;
195  int printwidth;
196  printprec = (int) - log10(Real(Param::epsilon()));
197  printwidth = printprec + 10;
198 
199  if(real)
200  {
201  VectorBase<R> primal(soplex.numCols());
202 
203  if(soplex.getPrimalRay(primal))
204  {
205  MSG_INFO1(soplex.spxout, soplex.spxout << "\nPrimal ray (name, value):\n";)
206 
207  for(int i = 0; i < soplex.numCols(); ++i)
208  {
209  if(isNotZero(primal[i]))
210  {
211  MSG_INFO1(soplex.spxout, soplex.spxout << colnames[i] << "\t"
212  << std::setw(printwidth) << std::setprecision(printprec)
213  << primal[i] << std::endl;)
214  }
215  }
216 
217  MSG_INFO1(soplex.spxout, soplex.spxout << "All other entries are zero (within "
218  << std::setprecision(1) << std::scientific << Param::epsilon()
219  << std::setprecision(8) << std::fixed
220  << ")." << std::endl;)
221  }
222  else if(soplex.isPrimalFeasible() && soplex.getPrimal(primal))
223  {
224  int nNonzeros = 0;
225  MSG_INFO1(soplex.spxout, soplex.spxout << "\nPrimal solution (name, value):\n";)
226 
227  for(int i = 0; i < soplex.numCols(); ++i)
228  {
229  if(isNotZero(primal[i]))
230  {
231  MSG_INFO1(soplex.spxout, soplex.spxout << colnames[i] << "\t"
232  << std::setw(printwidth) << std::setprecision(printprec)
233  << primal[i] << std::endl;)
234  ++nNonzeros;
235  }
236  }
237 
238  MSG_INFO1(soplex.spxout, soplex.spxout << "All other variables are zero (within "
239  << std::setprecision(1) << std::scientific << Param::epsilon()
240  << std::setprecision(8) << std::fixed
241  << "). Solution has " << nNonzeros << " nonzero entries." << std::endl;)
242  }
243  else
244  MSG_INFO1(soplex.spxout, soplex.spxout << "No primal information available.\n")
245  }
246 
247  if(rational)
248  {
249  VectorRational primal(soplex.numCols());
250 
251  if(soplex.getPrimalRayRational(primal))
252  {
253  MSG_INFO1(soplex.spxout, soplex.spxout << "\nPrimal ray (name, value):\n";)
254 
255  for(int i = 0; i < soplex.numCols(); ++i)
256  {
257  if(primal[i] != (Rational) 0)
258  {
259  MSG_INFO1(soplex.spxout, soplex.spxout << colnames[i] << "\t"
260  << std::setw(printwidth) << std::setprecision(printprec)
261  << primal[i] << std::endl;)
262  }
263  }
264 
265  MSG_INFO1(soplex.spxout, soplex.spxout << "All other entries are zero." << std::endl;)
266  }
267 
268  if(soplex.isPrimalFeasible() && soplex.getPrimalRational(primal))
269  {
270  int nNonzeros = 0;
271  MSG_INFO1(soplex.spxout, soplex.spxout << "\nPrimal solution (name, value):\n";)
272 
273  for(int i = 0; i < soplex.numColsRational(); ++i)
274  {
275  if(primal[i] != (Rational) 0)
276  {
277  MSG_INFO1(soplex.spxout, soplex.spxout << colnames[i] << "\t" << primal[i] << std::endl;)
278  ++nNonzeros;
279  }
280  }
281 
282  MSG_INFO1(soplex.spxout, soplex.spxout << "All other variables are zero. Solution has "
283  << nNonzeros << " nonzero entries." << std::endl;)
284  }
285  else
286  MSG_INFO1(soplex.spxout, soplex.spxout << "No primal (rational) solution available.\n")
287 
288  }
289 }
290 
291 template <class R>
292 static
294  bool real = true, bool rational = false)
295 {
296  int printprec;
297  int printwidth;
298  printprec = (int) - log10(Real(Param::epsilon()));
299  printwidth = printprec + 10;
300 
301  if(real)
302  {
303  VectorBase<R> dual(soplex.numRows());
304 
305  if(soplex.getDualFarkas(dual))
306  {
307  MSG_INFO1(soplex.spxout, soplex.spxout << "\nDual ray (name, value):\n";)
308 
309  for(int i = 0; i < soplex.numRows(); ++i)
310  {
311  if(isNotZero(dual[i]))
312  {
313  MSG_INFO1(soplex.spxout, soplex.spxout << rownames[i] << "\t"
314  << std::setw(printwidth) << std::setprecision(printprec)
315  << dual[i] << std::endl;)
316  }
317  }
318 
319  MSG_INFO1(soplex.spxout, soplex.spxout << "All other entries are zero (within "
320  << std::setprecision(1) << std::scientific << Param::epsilon()
321  << std::setprecision(8) << std::fixed << ")." << std::endl;)
322  }
323  else if(soplex.isDualFeasible() && soplex.getDual(dual))
324  {
325  MSG_INFO1(soplex.spxout, soplex.spxout << "\nDual solution (name, value):\n";)
326 
327  for(int i = 0; i < soplex.numRows(); ++i)
328  {
329  if(isNotZero(dual[i]))
330  {
331  MSG_INFO1(soplex.spxout, soplex.spxout << rownames[i] << "\t"
332  << std::setw(printwidth) << std::setprecision(printprec)
333  << dual[i] << std::endl;)
334  }
335  }
336 
337  MSG_INFO1(soplex.spxout, soplex.spxout << "All other dual values are zero (within "
338  << std::setprecision(1) << std::scientific << Param::epsilon()
339  << std::setprecision(8) << std::fixed << ")." << std::endl;)
340 
341  VectorBase<R> redcost(soplex.numCols());
342 
343  if(soplex.getRedCost(redcost))
344  {
345  MSG_INFO1(soplex.spxout, soplex.spxout << "\nReduced costs (name, value):\n";)
346 
347  for(int i = 0; i < soplex.numCols(); ++i)
348  {
349  if(isNotZero(redcost[i]))
350  {
351  MSG_INFO1(soplex.spxout, soplex.spxout << colnames[i] << "\t"
352  << std::setw(printwidth) << std::setprecision(printprec)
353  << redcost[i] << std::endl;)
354  }
355  }
356 
357  MSG_INFO1(soplex.spxout, soplex.spxout << "All other reduced costs are zero (within "
358  << std::setprecision(1) << std::scientific << Param::epsilon()
359  << std::setprecision(8) << std::fixed << ")." << std::endl;)
360  }
361  }
362  else
363  MSG_INFO1(soplex.spxout, soplex.spxout << "No dual information available.\n")
364  }
365 
366  if(rational)
367  {
368  VectorRational dual(soplex.numRows());
369 
370  if(soplex.getDualFarkasRational(dual))
371  {
372  MSG_INFO1(soplex.spxout, soplex.spxout << "\nDual ray (name, value):\n";)
373 
374  for(int i = 0; i < soplex.numRows(); ++i)
375  {
376  if(dual[i] != (Rational) 0)
377  {
378  MSG_INFO1(soplex.spxout, soplex.spxout << rownames[i] << "\t"
379  << std::setw(printwidth)
380  << std::setprecision(printprec)
381  << dual[i] << std::endl;)
382  }
383  }
384 
385  MSG_INFO1(soplex.spxout, soplex.spxout << "All other entries are zero." << std::endl;)
386  }
387 
388  if(soplex.isDualFeasible() && soplex.getDualRational(dual))
389  {
390  MSG_INFO1(soplex.spxout, soplex.spxout << "\nDual solution (name, value):\n";)
391 
392  for(int i = 0; i < soplex.numRowsRational(); ++i)
393  {
394  if(dual[i] != (Rational) 0)
395  MSG_INFO1(soplex.spxout, soplex.spxout << rownames[i] << "\t" << dual[i] << std::endl;)
396  }
397 
398  MSG_INFO1(soplex.spxout, soplex.spxout << "All other dual values are zero." << std::endl;)
399 
400  VectorRational redcost(soplex.numCols());
401 
402  if(soplex.getRedCostRational(redcost))
403  {
404  MSG_INFO1(soplex.spxout, soplex.spxout << "\nReduced costs (name, value):\n";)
405 
406  for(int i = 0; i < soplex.numCols(); ++i)
407  {
408  if(redcost[i] != (Rational) 0)
409  MSG_INFO1(soplex.spxout, soplex.spxout << colnames[i] << "\t" << redcost[i] << std::endl;)
410  }
411 
412  MSG_INFO1(soplex.spxout, soplex.spxout << "All other reduced costs are zero." << std::endl;)
413  }
414  }
415  else
416  MSG_INFO1(soplex.spxout, soplex.spxout << "No dual (rational) solution available.\n")
417  }
418 }
419 
420 
421 /// runs SoPlexBase command line
422 int main(int argc, char* argv[])
423 {
424  ///@todo the EGlib version info should be printed after the SoPlexBase version info
425  // initialize EGlib's GMP memory management before any rational numbers are created
426  EGlpNumStart();
427 
428  auto retVal = parseArgsAndRun(argc, argv);
429 
430  // because EGlpNumClear() calls mpq_clear() for all mpq_t variables, we need to destroy all objects of class Rational
431  // beforehand; hence all Rational objects and all data that uses Rational objects must be allocated dynamically via
432  // spx_alloc() and freed here; disabling the list memory is crucial
434  EGlpNumClear();
435 
436  return retVal;
437 }
438 
439 // Runs SoPlex with the parsed boost variables map
440 template <class R>
441 int soplex::runSoPlex(const po::variables_map& vm)
442 {
444  Validation<R> validation;
445 
446  // Stores different names
447  std::string lpfilename, readbasname, writebasname, writefilename, writedualfilename, loadsetname,
448  savesetname, diffsetname;
449 
450  // Will be used inside as conditions for if statements
451  bool printPrimal = false;
452  bool printPrimalRational = false;
453  bool printDual = false;
454  bool printDualRational = false;
455  bool displayStatistics = false;
456  bool checkSol = false;
457 
458  int returnValue = 0;
459 
460  // For optional argument the following helper function would assign the correct value to the correct variable
461  auto readIntoString = [&vm](std::string & var, const std::string str)
462  {
463  if(vm.count(str))
464  {
465  var = vm[str].as<std::string>();
466  }
467  };
468 
469  readIntoString(lpfilename, "lpfile");
470  readIntoString(readbasname, "readbas");
471  readIntoString(writebasname, "writebas");
472  readIntoString(writefilename, "writefile");
473  readIntoString(writedualfilename, "writedual");
474  readIntoString(loadsetname, "loadset");
475  readIntoString(savesetname, "saveset");
476  readIntoString(diffsetname, "diffset");
477 
478  try
479  {
480  NameSet rownames;
481  NameSet colnames;
482 
483  // A smart pointer for the readingTime. With a custom deleter too.
484  // create default timer (CPU time)
485  std::unique_ptr<Timer, std::function<void(Timer*)>> readingTime(TimerFactory::createTimer(
486  Timer::USER_TIME), [](Timer * ptr)
487  {
488  // custom deleter
489  ptr->~Timer();
490  spx_free(ptr);
491  });
492 
493  soplex.printVersion();
494  MSG_INFO1(soplex.spxout, soplex.spxout << SOPLEX_COPYRIGHT << std::endl << std::endl);
495 
496 
497  if(vm.count("readmode"))
498  {
499  soplex.setIntParam(soplex.READMODE, vm["readmode"].as<int>());
500  }
501 
502  // --solvemode=<value> : choose solving mode (0* - floating-point solve, 1 - auto, 2 - force iterative refinement, 3 - multiprecision)
503  if(vm.count("solvemode"))
504  {
505  auto solvemode = vm["solvemode"].as<int>();
506 
507  // The parameter int:solvemode determines if we are doing a Real or
508  // Rational solve. Whereas the parameter solvemode determines if we do
509  // a Real SoPlex or Templated Boost Soplex.
510  if(solvemode == 3)
511  {
512  MSG_INFO1(soplex.spxout, soplex.spxout << "Solving with increased precision." << std::endl);
513  soplex.setIntParam(soplex.SOLVEMODE, vm["int:solvemode"].as<int>());
514  }
515  else if(solvemode == 4)
516  {
517  MSG_INFO1(soplex.spxout, soplex.spxout << "Solving with Quad precision." << std::endl);
518  soplex.setIntParam(soplex.SOLVEMODE, vm["int:solvemode"].as<int>());
519  }
520  else
521  {
522  soplex.setIntParam(soplex.SOLVEMODE, vm["solvemode"].as<int>());
523  }
524 
525  // if the LP is parsed rationally and might be solved rationally, we choose automatic syncmode such that
526  // the rational LP is kept after reading
527 
528  if(soplex.intParam(soplex.READMODE) == soplex.READMODE_RATIONAL
529  && soplex.intParam(soplex.SOLVEMODE) != soplex.SOLVEMODE_REAL)
530  {
531  soplex.setIntParam(soplex.SYNCMODE, soplex.SYNCMODE_AUTO);
532  }
533 
534  }
535 
536  // --extsol=<value> : external solution for soplex to use for validation
537  if(vm.count("extsol"))
538  {
539  auto input = vm["extsol"].as<std::string>();
540 
541  validation.updateExternalSolution(input);
542  }
543 
544  // settings file format arguments are handled at the beginning.
545 
546  // -t<s> : set time limit to <s> seconds
547  if(vm.count("time"))
548  {
549  soplex.setRealParam(soplex.TIMELIMIT, vm["time"].as<int>());
550  }
551 
552  // -i<n> : set iteration limit to <n>
553  if(vm.count("iterlimit"))
554  {
555  soplex.setIntParam(soplex.ITERLIMIT, vm["iterlimit"].as<int>());
556  }
557 
558  // -f<eps> : set primal feasibility tolerance to <eps>
559  if(vm.count("primfeastol"))
560  {
561  soplex.setRealParam(soplex.FEASTOL, vm["primfeastol"].as<Real>());
562  }
563 
564  // -o<eps> : set dual feasibility (optimality) tolerance to <eps>
565  if(vm.count("dualfeastol"))
566  {
567  soplex.setRealParam(soplex.OPTTOL, vm["dualfeastol"].as<Real>());
568  }
569 
570  // l<eps> : set validation tolerance to <eps>
571  if(vm.count("valtol"))
572  {
573  auto str = vm["valtol"].as<std::string>();
574  validation.updateValidationTolerance(str);
575  }
576 
577  // -s<value> : choose simplifier/presolver (0 - off, 1* - auto)
578  if(vm.count("simplifier"))
579  {
580  soplex.setIntParam(soplex.SIMPLIFIER, vm["simplifier"].as<int>());
581  }
582 
583  // -g<value> : choose scaling (0 - off, 1 - uni-equilibrium, 2* - bi-equilibrium, 3 - geometric, 4 - iterated geometric, 5 - least squares, 6 - geometric-equilibrium)
584  if(vm.count("scaler"))
585  {
586  soplex.setIntParam(soplex.SCALER, vm["scaler"].as<int>());
587  }
588 
589  // -p<value> : choose pricing (0* - auto, 1 - dantzig, 2 - parmult, 3 - devex, 4 - quicksteep, 5 - steep)
590  if(vm.count("pricer"))
591  {
592  soplex.setIntParam(soplex.PRICER, vm["pricer"].as<int>());
593  }
594 
595  // -r<value> : choose ratio tester (0 - textbook, 1 - harris, 2* - fast, 3 - boundflipping)
596  if(vm.count("ratiotester"))
597  {
598  soplex.setIntParam(soplex.RATIOTESTER, vm["ratiotester"].as<int>());
599  }
600 
601  // -v<level> : set verbosity to <level> (0 - error, 3 - normal, 5 - high)
602  if(vm.count("verbosity"))
603  {
604  soplex.setIntParam(soplex.VERBOSITY, vm["verbosity"].as<int>());
605  }
606 
607  // -x : print primal solution
608  if(vm.count("printprimal"))
609  {
610  printPrimal = true;
611  }
612 
613  // -X : print primal solution with rationals
614  if(vm.count("printprimratsol"))
615  {
616  printPrimalRational = true;
617  }
618 
619  // -y : print dual multipliers
620  if(vm.count("printdualmult"))
621  {
622  printDual = true;
623  }
624 
625  // -Y : print dual multipliers with rationals
626  if(vm.count("printdualmultrational"))
627  {
628  printDualRational = true;
629  }
630 
631  // -q : display detailed statistics
632  if(vm.count("dispstat"))
633  {
634  displayStatistics = true;
635  }
636 
637  // -c : perform final check of optimal solution in original problem
638  if(vm.count("checkfinal"))
639  {
640  checkSol = true;
641  }
642 
643  if(vm.count("loadset"))
644  {
645  // This is more of a hack. The actual reading happens inside args.hpp
646  // This is here because 1. the spxout object is not available there.
647  // 2. It has to be displayed after the soplex intro banner
648  MSG_INFO1(soplex.spxout, soplex.spxout << "Loading settings file <" <<
649  vm["loadset"].as<std::string>() << "> . . .\n");
650  }
651 
652  // We do a ranged for loop for every element in array intParam,
653  // realParam and boolParam. Afterwards, we do a search for it in the
654  // variables map, which is like a std::map. I think the count part may
655  // be redundant because in the args.hpp in the
656  // options_description::add_options(), I'm already specifying the
657  // default value. But the soplex::settings object already has this
658  // default value; one of them is redundant. The variables_map::value()
659  // will return a boost::any object.
660  //
661  // Notes: There is a tricky situation here. Take the parameters
662  // int:solvemode and solvemode, they are supposed to represent the same
663  // intParam. Recall that we give preference to values from command line
664  // vs values from settings file. So if --int:solvemode=1 is passed from
665  // command line, it would get a preference over int:solvemode from the
666  // settings. But if you give solvemode=1 in the command line, then the
667  // value from settings file will be given priority.
668 
669  for(int i = 0; i < SoPlexBase<R>::INTPARAM_COUNT; ++i)
670  {
671  const auto str = "int:" + soplex._currentSettings->intParam.name[i];
672 
673  if(vm.count(str))
674  {
675  soplex.parseSettingsString(str, vm[str].value());
676  }
677  }
678 
679  for(int i = 0; i < SoPlexBase<R>::REALPARAM_COUNT; ++i)
680  {
681  const auto str = "real:" + soplex._currentSettings->realParam.name[i];
682 
683  if(vm.count(str))
684  {
685  soplex.parseSettingsString(str, vm[str].value());
686  }
687  }
688 
689  for(int i = 0; i < SoPlexBase<R>::BOOLPARAM_COUNT; ++i)
690  {
691  const auto str = "bool:" + soplex._currentSettings->boolParam.name[i];
692 
693  if(vm.count(str))
694  {
695  soplex.parseSettingsString(str, vm[str].value());
696  }
697  }
698 
699  // I didn't write the loop for rationalParams, because currently there are
700  // no rationalParams.
701 
702 
703 
704 
705  // For random seed
706  if(vm.count("uint:random_seed"))
707  {
708  soplex.setRandomSeed(vm["uint:random_seed"].as<unsigned int>());
709  }
710 
711  MSG_INFO1(soplex.spxout, soplex.printUserSettings(););
712 
713  // TODO: How is the following code supposed to work?
714  // no LP file was given and no settings files are written
715  if(lpfilename.empty() && savesetname.empty() && diffsetname.empty())
716  {
717  BOOST_THROW_EXCEPTION(
718  std::invalid_argument("Empty lpfilename, save setings name and diff settings name"));
719  }
720 
721  // ensure that syncmode is not manual
722  if(soplex.intParam(soplex.SYNCMODE) == soplex.SYNCMODE_MANUAL)
723  {
724  BOOST_THROW_EXCEPTION(
725  std::invalid_argument("Error: manual synchronization is invalid on command line. Change parameter int:syncmode"));
726  }
727 
728  // save settings files
729  if(!savesetname.empty())
730  {
731  MSG_INFO1(soplex.spxout, soplex.spxout << "Saving parameters to settings file <" << savesetname <<
732  "> . . .\n");
733 
734  if(!soplex.saveSettingsFile(savesetname.c_str(), false, vm["solvemode"].as<int>()))
735  {
736  MSG_ERROR(std::cerr << "Error writing parameters to file <" << savesetname << ">\n");
737  }
738  }
739 
740  if(!diffsetname.empty())
741  {
742  MSG_INFO1(soplex.spxout, soplex.spxout << "Saving modified parameters to settings file <" <<
743  diffsetname << "> . . .\n");
744 
745  if(!soplex.saveSettingsFile(diffsetname.c_str(), true))
746  {
747  MSG_ERROR(std::cerr << "Error writing modified parameters to file <" << diffsetname << ">\n");
748  }
749  }
750 
751  // no LP file given: exit after saving settings
752  if(lpfilename.empty())
753  {
754  // This means that soplex didn't have any of the required parameters
755  if(loadsetname.empty() && savesetname.empty() && diffsetname.empty())
756  {
757  MSG_INFO1(soplex.spxout, soplex.spxout << "\n");
758  BOOST_THROW_EXCEPTION(
759  std::invalid_argument("No lpfile, settings file, save settings file or diff settings file"));
760  }
761 
762  return 0;
763  }
764 
765  // measure time for reading LP file and basis file
766  readingTime->start();
767 
768  // if the LP is parsed rationally and might be solved rationally, we choose automatic syncmode such that
769  // the rational LP is kept after reading
770  if(soplex.intParam(soplex.READMODE) == soplex.READMODE_RATIONAL
771  && soplex.intParam(soplex.SOLVEMODE) != soplex.SOLVEMODE_REAL)
772  {
773  soplex.setIntParam(soplex.SYNCMODE, soplex.SYNCMODE_AUTO);
774  }
775 
776  // read LP from input file
777  MSG_INFO1(soplex.spxout, soplex.spxout << "Reading "
778  << (soplex.intParam(soplex.READMODE) == soplex.READMODE_REAL ? "(real)" : "(rational)")
779  << " LP file <" << lpfilename << "> . . .\n");
780 
781  if(!soplex.readFile(lpfilename.c_str(), &rownames, &colnames))
782  {
783  BOOST_THROW_EXCEPTION(std::runtime_error("Error while reading lpfile: " + lpfilename));
784  }
785 
786  // write LP if specified
787  if(!writefilename.empty())
788  {
789  if(!soplex.writeFile(writefilename.c_str(), &rownames, &colnames))
790  {
791  BOOST_THROW_EXCEPTION(std::runtime_error("Error in writing to file: " + writefilename));
792  }
793  else
794  {
795  MSG_INFO1(soplex.spxout, soplex.spxout << "Written LP to file <" << writefilename << ">.\n\n");
796  }
797  }
798 
799  // write dual LP if specified
800  if(!writedualfilename.empty())
801  {
802  if(!soplex.writeDualFileReal(writedualfilename.c_str(), &rownames, &colnames))
803  {
804  BOOST_THROW_EXCEPTION(std::runtime_error("Error while writing dual file: " + writedualfilename));
805  }
806  else
807  {
808  MSG_INFO1(soplex.spxout, soplex.spxout << "Written dual LP to file <" << writedualfilename <<
809  ">.\n\n");
810  }
811  }
812 
813  // read basis file if specified
814  if(!readbasname.empty())
815  {
816  MSG_INFO1(soplex.spxout, soplex.spxout << "Reading basis file <" << readbasname << "> . . . ");
817 
818  if(!soplex.readBasisFile(readbasname.c_str(), &rownames, &colnames))
819  {
820  BOOST_THROW_EXCEPTION(std::runtime_error("Error while reading file: " + readbasname));
821  }
822  }
823 
824  readingTime->stop();
825 
826  MSG_INFO1(soplex.spxout,
827  std::streamsize prec = soplex.spxout.precision();
828  soplex.spxout << "Reading took "
829  << std::fixed << std::setprecision(2) << readingTime->time()
830  << std::scientific << std::setprecision(int(prec))
831  << " seconds.\n\n");
832 
833  MSG_INFO1(soplex.spxout, soplex.spxout << "LP has " << soplex.numRows() << " rows "
834  << soplex.numCols() << " columns and " << soplex.numNonzeros() << " nonzeros.\n\n");
835 
836  // solve the LP
837  soplex.optimize();
838 
839  // print solution, check solution, and display statistics
840  printPrimalSolution(soplex, colnames, rownames, printPrimal, printPrimalRational);
841  printDualSolution(soplex, colnames, rownames, printDual, printDualRational);
842 
843  if(checkSol)
844  checkSolution<R>(soplex); // The type needs to get fixed here
845 
846  if(displayStatistics)
847  {
848  MSG_INFO1(soplex.spxout, soplex.spxout << "Statistics\n==========\n\n");
850  }
851 
852  if(validation.validate)
853  validation.validateSolveReal(soplex);
854 
855  // write basis file if specified
856  if(!writebasname.empty())
857  {
858  if(!soplex.hasBasis())
859  {
860  MSG_WARNING(soplex.spxout, soplex.spxout <<
861  "No basis information available. Could not write file <" << writebasname << ">\n\n");
862  }
863  else if(!soplex.writeBasisFile(writebasname.c_str(), &rownames, &colnames))
864  {
865  BOOST_THROW_EXCEPTION(std::runtime_error("Error while writing file: " + writebasname));
866  }
867  else
868  {
869  MSG_INFO1(soplex.spxout, soplex.spxout << "Written basis information to file <" << writebasname <<
870  ">.\n\n");
871  }
872  }
873  }
874  catch(const SPxException& x) // There could be an exception from boost?
875  {
876  MSG_ERROR(std::cerr << "Exception caught: " << x.what() << "\n");
877  returnValue = 1;
878  }
879  catch(...)
880  {
881  std::cout << "Generic exception: " << boost::current_exception_diagnostic_information() << "\n";
882  returnValue = 1;
883  }
884 
885  return returnValue;
886 }
887 
bool writeFile(const char *filename, const NameSet *rowNames=0, const NameSet *colNames=0, const DIdxSet *intvars=0, const bool unscale=true) const
Templated write function Real writes real LP to file; LP or MPS format is chosen from the extension i...
#define EGlpNumStart()
Definition: soplexmain.cpp:45
bool getBoundViolationRational(Rational &maxviol, Rational &sumviol)
Dense vector.Class VectorBase provides dense linear algebra vectors. Internally, VectorBase wraps std...
Definition: dsvectorbase.h:28
automatic sync of real and rational LP
Definition: soplex.h:1245
bool getDualRational(VectorRational &vector)
int numNonzeros() const
returns number of nonzeros
type of ratio test
Definition: soplex.h:1033
int numRowsRational() const
virtual ~Timer()
Definition: timer.h:124
bool getPrimalRational(VectorRational &vector)
dual feasibility tolerance
Definition: soplex.h:1333
bool writeDualFileReal(const char *filename, const NameSet *rowNames=0, const NameSet *colNames=0, const DIdxSet *intvars=0) const
writes the dual of the real LP to file; LP or MPS format is chosen from the extension in filename; if...
bool isDualFeasible() const
is stored dual solution feasible?
bool updateValidationTolerance(const std::string &tolerance)
updates the tolerance used for validation
static void checkSolutionReal(SoPlexBase< R > &soplex)
performs external feasibility check with real type
Definition: soplexmain.cpp:59
bool getDual(VectorBase< R > &vector)
gets the dual solution vector if available; returns true on success
SPxSolverBase< R >::Status optimize()
optimize the given LP
bool writeBasisFile(const char *filename, const NameSet *rowNames=0, const NameSet *colNames=0, const bool cpxFormat=false) const
writes basis information to filename; if rowNames and colNames are NULL, default names are used; retu...
bool getRowViolationRational(Rational &maxviol, Rational &sumviol)
Wrapper for GMP type mpq_class.We wrap mpq_class so that we can replace it by a double type if GMP is...
Definition: rational.h:62
static void disableListMem()
disables list memory
Definition: rational.cpp:351
type of scaler
Definition: soplex.h:1024
std::ostream & getStream(const Verbosity &verbosity) const
Returns the stream for the specified verbosity level.
Definition: spxout.h:157
bool getPrimalRay(VectorBase< R > &vector)
gets the primal ray if available; returns true on success
bool hasBasis() const
is an advanced starting basis available?
bool getRedCostViolation(R &maxviol, R &sumviol)
gets violation of reduced costs; returns true on success
void validateSolveReal(SoPlexBase< R > &soplex)
validates the soplex solution using the external solution
virtual const std::string what() const
returns exception message
Definition: exceptions.h:57
#define EGlpNumClear()
Definition: soplexmain.cpp:46
apply standard floating-point algorithm
Definition: soplex.h:1265
double Real
Definition: spxdefines.h:227
int main(int argc, char *argv[])
runs SoPlexBase command line
Definition: soplexmain.cpp:422
bool getDualViolationRational(Rational &maxviol, Rational &sumviol)
bool getRedCostRational(VectorRational &vector)
int intParam(const IntParam param) const
returns integer parameter value
bool getDualFarkas(VectorBase< R > &vector)
gets the Farkas proof if available; returns true on success
#define MSG_ERROR(x)
Prints out message x if the verbosity level is at least SPxOut::ERROR.
Definition: spxdefines.h:123
Real realParam(const RealParam param) const
returns real parameter value
iteration limit (-1 if unlimited)
Definition: soplex.h:1006
bool getBoundViolation(R &maxviol, R &sumviol)
gets violation of bounds; returns true on success
primal feasibility tolerance
Definition: soplex.h:1330
bool hasDual() const
deprecated: use hasSol() instead
Definition: soplex.h:614
Class for collecting statistical information.
bool saveSettingsFile(const char *filename, const bool onlyChanged=false, int solvemode=1) const
writes settings file; returns true on success
bool getPrimal(VectorBase< R > &vector)
gets the primal solution vector if available; returns true on success
bool readBasisFile(const char *filename, const NameSet *rowNames=0, const NameSet *colNames=0)
reads basis information from filename and returns true on success; if rowNames and colNames are NULL...
bool hasPrimal() const
deprecated: use hasSol() instead
Definition: soplex.h:608
bool getDualFarkasRational(VectorRational &vector)
int numCols() const
Templated function that returns number of columns.
void setRandomSeed(unsigned int seed)
set the random seeds of the solver instance
static void checkSolutionRational(SoPlexBase< R > &soplex)
performs external feasibility check with rational type
Definition: soplexmain.cpp:116
void printStatistics(std::ostream &os)
prints complete statistics
bool getRedCostViolationRational(Rational &maxviol, Rational &sumviol)
static Timer * createTimer(Timer::TYPE ttype)
create timers and allocate memory for them
Definition: timerfactory.h:44
bool setRealParam(const RealParam param, const Real value, const bool init=true)
sets real parameter value; returns true on success
Preconfigured SoPlex LP solver.
static Real epsilon()
Definition: spxdefines.cpp:55
Set of strings.Class NameSet implements a symbol or name table. It allows to store or remove names (i...
Definition: nameset.h:61
bool getDualViolation(R &maxviol, R &sumviol)
gets violation of dual multipliers; returns true on success
type of simplifier
Definition: soplex.h:1021
void checkSolution(SoPlexBase< R > &soplex)
performs external feasibility check according to check mode
Definition: soplexmain.cpp:173
bool validate
should the soplex solution be validated?
Definition: validation.h:34
Exception base class.This class implements a base class for our SoPlex exceptions We provide a what()...
Definition: exceptions.h:32
Everything should be within this namespace.
static void printPrimalSolution(SoPlexBase< R > &soplex, NameSet &colnames, NameSet &rownames, bool real=true, bool rational=false)
Definition: soplexmain.cpp:191
mode for iterative refinement strategy
Definition: soplex.h:1042
bool getRowViolation(R &maxviol, R &sumviol)
gets violation of constraints; returns true on success
int numRows() const
returns number of rows
time limit in seconds (INFTY if unlimited)
Definition: soplex.h:1351
user sync of real and rational LP
Definition: soplex.h:1248
#define MSG_WARNING(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::WARNING.
Definition: spxdefines.h:125
mode for reading LP files
Definition: soplex.h:1039
std::streamsize precision() const
Definition: spxout.h:139
static void printDualSolution(SoPlexBase< R > &soplex, NameSet &colnames, NameSet &rownames, bool real=true, bool rational=false)
Definition: soplexmain.cpp:293
bool readFile(const char *filename, NameSet *rowNames=0, NameSet *colNames=0, DIdxSet *intVars=0)
reads LP file in LP or MPS format according to READMODE parameter; gets row names, column names, and integer variables if desired; returns true on success
void printVersion() const
prints version and compilation options
bool updateExternalSolution(const std::string &solution)
updates the external solution used for validation
bool getPrimalRayRational(VectorRational &vector)
standard floating-point parsing
Definition: soplex.h:1255
#define MSG_INFO1(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::INFO1.
Definition: spxdefines.h:127
verbosity level
Definition: soplex.h:1018
int numColsRational() const
bool isPrimalFeasible() const
is stored primal solution feasible?
Validation object for soplex solutions.
type of pricer
Definition: soplex.h:1030
#define SOPLEX_COPYRIGHT
Definition: spxdefines.h:57
std::string rationalToString(const Rational &r, const int precision)
convert rational number to string
Definition: rational.cpp:1858
bool setIntParam(const IntParam param, const int value, const bool init=true)
sets integer parameter value; returns true on success
mode for synchronizing real and rational LP
Definition: soplex.h:1036
Wrapper for the system time query methods.
Definition: timer.h:76
void spx_free(T &p)
Release memory.
Definition: spxalloc.h:111
bool getRedCost(VectorBase< R > &vector)
gets the vector of reduced cost values if available; returns true on success
Settings * _currentSettings
Definition: soplex.h:1626
void printUserSettings()
print non-default parameter values