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-2016 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 #ifndef SOPLEX_LEGACY
20 #include <assert.h>
21 #include <math.h>
22 #include <string.h>
23 
24 #include <iostream>
25 #include <iomanip>
26 #include <fstream>
27 
28 #include "soplex.h"
29 #include "spxgithash.h"
30 #include "timerfactory.h"
31 
32 #ifdef SOPLEX_WITH_EGLIB
33 extern "C" {
34 #include "EGlib.h"
35 }
36 #else
37 #define EGlpNumStart() {}
38 #define EGlpNumClear() {}
39 #endif
40 
41 using namespace soplex;
42 
43 // prints usage and command line options
44 static
45 void printUsage(const char* const argv[], int idx)
46 {
47  const char* usage =
48  "general options:\n"
49  " --readbas=<basfile> read starting basis from file\n"
50  " --writebas=<basfile> write terminal basis to file\n"
51  " --writefile=<lpfile> write LP to file in LP or MPS format depending on extension\n"
52  " --<type>:<name>=<val> change parameter value using syntax of settings file entries\n"
53  " --loadset=<setfile> load parameters from settings file (overruled by command line parameters)\n"
54  " --saveset=<setfile> save parameters to settings file\n"
55  " --diffset=<setfile> save modified parameters to settings file\n"
56  "\n"
57  "limits and tolerances:\n"
58  " -t<s> set time limit to <s> seconds\n"
59  " -i<n> set iteration limit to <n>\n"
60  " -f<eps> set primal feasibility tolerance to <eps>\n"
61  " -o<eps> set dual feasibility (optimality) tolerance to <eps>\n"
62  "\n"
63  "algorithmic settings (* indicates default):\n"
64  " --readmode=<value> choose reading mode for <lpfile> (0* - floating-point, 1 - rational)\n"
65  " --solvemode=<value> choose solving mode (0 - floating-point solve, 1* - auto, 2 - force iterative refinement)\n"
66  " -s<value> choose simplifier/presolver (0 - off, 1* - auto)\n"
67  " -g<value> choose scaling (0 - off, 1 - uni-equilibrium, 2* - bi-equilibrium, 3 - geometric, 4 - iterated geometric)\n"
68  " -p<value> choose pricing (0* - auto, 1 - dantzig, 2 - parmult, 3 - devex, 4 - quicksteep, 5 - steep)\n"
69  " -r<value> choose ratio tester (0 - textbook, 1 - harris, 2 - fast, 3* - boundflipping)\n"
70  "\n"
71  "display options:\n"
72  " -v<level> set verbosity to <level> (0 - error, 3 - normal, 5 - high)\n"
73  " -x print primal solution\n"
74  " -y print dual multipliers\n"
75  " -X print primal solution in rational numbers\n"
76  " -Y print dual multipliers in rational numbers\n"
77  " -q display detailed statistics\n"
78  " -c perform final check of optimal solution in original problem\n"
79  "\n";
80 
81  if( idx <= 0 )
82  std::cerr << "missing input file\n\n";
83  else
84  std::cerr << "invalid option \"" << argv[idx] << "\"\n\n";
85 
86  std::cerr << "usage: " << argv[0] << " " << "[options] <lpfile>\n"
87 #ifdef SOPLEX_WITH_ZLIB
88  << " <lpfile> linear program as .mps[.gz] or .lp[.gz] file\n\n"
89 #else
90  << " <lpfile> linear program as .mps or .lp file\n\n"
91 #endif
92  << usage;
93 }
94 
95 // cleans up C strings
96 static
97 void freeStrings(char*& s1, char*& s2, char*& s3, char*& s4, char*& s5)
98 {
99  if( s1 != 0 )
100  {
101  delete [] s1;
102  s1 = 0;
103  }
104  if( s2 != 0 )
105  {
106  delete [] s2;
107  s2 = 0;
108  }
109  if( s3 != 0 )
110  {
111  delete [] s3;
112  s3 = 0;
113  }
114  if( s4 != 0 )
115  {
116  delete [] s4;
117  s4 = 0;
118  }
119  if( s5 != 0 )
120  {
121  delete [] s5;
122  s5 = 0;
123  }
124 }
125 
126 /// performs external feasibility check with real type
127 ///@todo implement external check; currently we use the internal methods for convenience
128 static
130 {
131  if( soplex.hasPrimal() )
132  {
133  Real boundviol;
134  Real rowviol;
135  Real sumviol;
136 
137  if( soplex.getBoundViolationReal(boundviol, sumviol) && soplex.getRowViolationReal(rowviol, sumviol) )
138  {
139  MSG_INFO1( soplex.spxout,
140  Real maxviol = boundviol > rowviol ? boundviol : rowviol;
141  bool feasible = (maxviol <= soplex.realParam(SoPlex::FEASTOL));
142  soplex.spxout << "Primal solution " << (feasible ? "feasible" : "infeasible") << " in original problem (max. violation = " << maxviol << ").\n"
143  );
144  }
145  else
146  {
147  MSG_INFO1( soplex.spxout, soplex.spxout << "Could not check primal solution.\n" );
148  }
149  }
150  else
151  {
152  MSG_INFO1( soplex.spxout, soplex.spxout << "No primal solution available.\n" );
153  }
154 
155  if( soplex.hasDual() )
156  {
157  Real redcostviol;
158  Real dualviol;
159  Real sumviol;
160 
161  if( soplex.getRedCostViolationReal(redcostviol, sumviol) && soplex.getDualViolationReal(dualviol, sumviol) )
162  {
163  MSG_INFO1( soplex.spxout,
164  Real maxviol = redcostviol > dualviol ? redcostviol : dualviol;
165  bool feasible = (maxviol <= soplex.realParam(SoPlex::OPTTOL));
166  soplex.spxout << "Dual solution " << (feasible ? "feasible" : "infeasible") << " in original problem (max. violation = " << maxviol << ").\n"
167  );
168  }
169  else
170  {
171  MSG_INFO1( soplex.spxout, soplex.spxout << "Could not check dual solution.\n" );
172  }
173  }
174  else
175  {
176  MSG_INFO1( soplex.spxout, soplex.spxout << "No dual solution available.\n" );
177  }
178 }
179 
180 /// performs external feasibility check with rational type
181 ///@todo implement external check; currently we use the internal methods for convenience
182 static
184 {
185  if( soplex.hasPrimal() )
186  {
187  Rational boundviol;
188  Rational rowviol;
189  Rational sumviol;
190 
191  if( soplex.getBoundViolationRational(boundviol, sumviol) && soplex.getRowViolationRational(rowviol, sumviol) )
192  {
193  MSG_INFO1( soplex.spxout,
194  Rational maxviol = boundviol > rowviol ? boundviol : rowviol;
195  bool feasible = (maxviol <= soplex.realParam(SoPlex::FEASTOL));
196  soplex.spxout << "Primal solution " << (feasible ? "feasible" : "infeasible") << " in original problem (max. violation = " << rationalToString(maxviol) << ").\n"
197  );
198  }
199  else
200  {
201  MSG_INFO1( soplex.spxout, soplex.spxout << "Could not check primal solution.\n" );
202  }
203  }
204  else
205  {
206  MSG_INFO1( soplex.spxout, soplex.spxout << "No primal solution available.\n" );
207  }
208 
209  if( soplex.hasDual() )
210  {
211  Rational redcostviol;
212  Rational dualviol;
213  Rational sumviol;
214 
215  if( soplex.getRedCostViolationRational(redcostviol, sumviol) && soplex.getDualViolationRational(dualviol, sumviol) )
216  {
217  MSG_INFO1( soplex.spxout,
218  Rational maxviol = redcostviol > dualviol ? redcostviol : dualviol;
219  bool feasible = (maxviol <= soplex.realParam(SoPlex::OPTTOL));
220  soplex.spxout << "Dual solution " << (feasible ? "feasible" : "infeasible") << " in original problem (max. violation = " << rationalToString(maxviol) << ").\n"
221  );
222  }
223  else
224  {
225  MSG_INFO1( soplex.spxout, soplex.spxout << "Could not check dual solution.\n" );
226  }
227  }
228  else
229  {
230  MSG_INFO1( soplex.spxout, soplex.spxout << "No dual solution available.\n" );
231  }
232 }
233 
234 /// performs external feasibility check according to check mode
235 static
237 {
241  {
242  checkSolutionRational(soplex);
243  }
244  else
245  {
246  checkSolutionReal(soplex);
247  }
248 
249  MSG_INFO1( soplex.spxout, soplex.spxout << "\n" );
250 }
251 
252 /// runs SoPlex command line
253 int main(int argc, char* argv[])
254 {
255  ///@todo the EGlib version info should be printed after the SoPlex version info
256  // initialize EGlib's GMP memory management before any rational numbers are created
257  EGlpNumStart();
258 
259  SoPlex* soplex;
260  NameSet rownames;
261  NameSet colnames;
262  Timer* readingTime;
263  int optidx;
264 
265  const char* lpfilename;
266  char* readbasname = 0;
267  char* writebasname = 0;
268  char* writefilename = 0;
269  char* loadsetname = 0;
270  char* savesetname = 0;
271  char* diffsetname = 0;
272  bool printPrimal = false;
273  bool printPrimalRational = false;
274  bool printDual = false;
275  bool printDualRational = false;
276  bool displayStatistics = false;
277  bool checkSol = false;
278 
279  int returnValue = 0;
280 
281  // create default timer (CPU time)
283  soplex = 0;
284  spx_alloc(soplex);
285  new (soplex) SoPlex();
286 
287  soplex->printVersion();
288  MSG_INFO1( soplex->spxout, soplex->spxout << "Copyright (c) 1996-2016 Konrad-Zuse-Zentrum fuer Informationstechnik Berlin (ZIB)\n\n" );
289 
290  try
291  {
292  // no options were given
293  if( argc <= 1 )
294  {
295  printUsage(argv, 0);
296  returnValue = 1;
297  goto TERMINATE;
298  }
299 
300  // read arguments from command line
301  for( optidx = 1; optidx < argc; optidx++ )
302  {
303  char* option = argv[optidx];
304 
305  // we reached <lpfile>
306  if( option[0] != '-' )
307  break;
308 
309  // option string must start with '-', must contain at least two characters, and exactly two characters if and
310  // only if it is -x, -y, -q, or -c
311  if( option[0] != '-' || option[1] == '\0'
312  || ((option[2] == '\0') != (option[1] == 'x' || option[1] == 'X' || option[1] == 'y' || option[1] == 'Y' || option[1] == 'q' || option[1] == 'c')) )
313  {
314  printUsage(argv, optidx);
315  returnValue = 1;
316  goto TERMINATE_FREESTRINGS;
317  }
318 
319  switch( option[1] )
320  {
321  case '-' :
322  {
323  option = &option[2];
324 
325  // --readbas=<basfile> : read starting basis from file
326  if( strncmp(option, "readbas=", 8) == 0 )
327  {
328  if( readbasname == 0 )
329  {
330  char* filename = &option[8];
331  readbasname = strncpy(new char[strlen(filename) + 1], filename, strlen(filename) + 1);
332  }
333  }
334  // --writebas=<basfile> : write terminal basis to file
335  else if( strncmp(option, "writebas=", 9) == 0 )
336  {
337  if( writebasname == 0 )
338  {
339  char* filename = &option[9];
340  writebasname = strncpy(new char[strlen(filename) + 1], filename, strlen(filename) + 1);
341  }
342  }
343  // --writefile=<lpfile> : write LP to file
344  else if( strncmp(option, "writefile=", 10) == 0 )
345  {
346  if( writefilename == 0 )
347  {
348  char* filename = &option[10];
349  writefilename = strncpy(new char[strlen(filename) + 1], filename, strlen(filename) + 1);
350  }
351  }
352  // --loadset=<setfile> : load parameters from settings file
353  else if( strncmp(option, "loadset=", 8) == 0 )
354  {
355  if( loadsetname == 0 )
356  {
357  char* filename = &option[8];
358  loadsetname = strncpy(new char[strlen(filename) + 1], filename, strlen(filename) + 1);
359  if( !soplex->loadSettingsFile(loadsetname) )
360  {
361  printUsage(argv, optidx);
362  returnValue = 1;
363  goto TERMINATE_FREESTRINGS;
364  }
365  else
366  {
367  // we need to start parsing again because some command line parameters might have been overwritten
368  optidx = 0;
369  }
370  }
371  }
372  // --saveset=<setfile> : save parameters to settings file
373  else if( strncmp(option, "saveset=", 8) == 0 )
374  {
375  if( savesetname == 0 )
376  {
377  char* filename = &option[8];
378  savesetname = strncpy(new char[strlen(filename) + 1], filename, strlen(filename) + 1);
379  }
380  }
381  // --diffset=<setfile> : save modified parameters to settings file
382  else if( strncmp(option, "diffset=", 8) == 0 )
383  {
384  if( diffsetname == 0 )
385  {
386  char* filename = &option[8];
387  diffsetname = strncpy(new char[strlen(filename) + 1], filename, strlen(filename) + 1);
388  }
389  }
390  // --readmode=<value> : choose reading mode for <lpfile> (0* - floating-point, 1 - rational)
391  else if( strncmp(option, "readmode=", 9) == 0 )
392  {
393  if( !soplex->setIntParam(SoPlex::READMODE, option[9] - '0') )
394  {
395  printUsage(argv, optidx);
396  returnValue = 1;
397  goto TERMINATE_FREESTRINGS;
398  }
399  }
400  // --solvemode=<value> : choose solving mode (0* - floating-point solve, 1 - auto, 2 - force iterative refinement)
401  else if( strncmp(option, "solvemode=", 10) == 0 )
402  {
403  if( !soplex->setIntParam(SoPlex::SOLVEMODE, option[10] - '0') )
404  {
405  printUsage(argv, optidx);
406  returnValue = 1;
407  goto TERMINATE_FREESTRINGS;
408  }
409  // if the LP is parsed rationally and might be solved rationally, we choose automatic syncmode such that
410  // the rational LP is kept after reading
413  {
415  }
416  }
417  // --<type>:<name>=<val> : change parameter value using syntax of settings file entries
418  else if( !soplex->parseSettingsString(option) )
419  {
420  printUsage(argv, optidx);
421  returnValue = 1;
422  goto TERMINATE_FREESTRINGS;
423  }
424  break;
425  }
426 
427  case 't' :
428  // -t<s> : set time limit to <s> seconds
429  if( !soplex->setRealParam(SoPlex::TIMELIMIT, atoi(&option[2])) )
430  {
431  printUsage(argv, optidx);
432  returnValue = 1;
433  goto TERMINATE_FREESTRINGS;
434  }
435  break;
436 
437  case 'i' :
438  // -i<n> : set iteration limit to <n>
439  if( !soplex->setIntParam(SoPlex::ITERLIMIT, atoi(&option[2])) )
440  {
441  printUsage(argv, optidx);
442  returnValue = 1;
443  goto TERMINATE_FREESTRINGS;
444  }
445  break;
446 
447  case 'f' :
448  // -f<eps> : set primal feasibility tolerance to <eps>
449  if( !soplex->setRealParam(SoPlex::FEASTOL, atof(&option[2])) )
450  {
451  printUsage(argv, optidx);
452  returnValue = 1;
453  goto TERMINATE_FREESTRINGS;
454  }
455  break;
456 
457  case 'o' :
458  // -o<eps> : set dual feasibility (optimality) tolerance to <eps>
459  if( !soplex->setRealParam(SoPlex::OPTTOL, atof(&option[2])) )
460  {
461  printUsage(argv, optidx);
462  returnValue = 1;
463  goto TERMINATE_FREESTRINGS;
464  }
465  break;
466 
467  case 's' :
468  // -s<value> : choose simplifier/presolver (0 - off, 1* - auto)
469  if( !soplex->setIntParam(SoPlex::SIMPLIFIER, option[2] - '0') )
470  {
471  printUsage(argv, optidx);
472  returnValue = 1;
473  goto TERMINATE_FREESTRINGS;
474  }
475  break;
476 
477  case 'g' :
478  // -g<value> : choose scaling (0 - off, 1 - uni-equilibrium, 2* - bi-equilibrium, 3 - geometric, 4 - iterated geometric)
479  if( !soplex->setIntParam(SoPlex::SCALER, option[2] - '0') )
480  {
481  printUsage(argv, optidx);
482  returnValue = 1;
483  goto TERMINATE_FREESTRINGS;
484  }
485  break;
486 
487  case 'p' :
488  // -p<value> : choose pricing (0* - auto, 1 - dantzig, 2 - parmult, 3 - devex, 4 - quicksteep, 5 - steep)
489  if( !soplex->setIntParam(SoPlex::PRICER, option[2] - '0') )
490  {
491  printUsage(argv, optidx);
492  returnValue = 1;
493  goto TERMINATE_FREESTRINGS;
494  }
495  break;
496 
497  case 'r' :
498  // -r<value> : choose ratio tester (0 - textbook, 1 - harris, 2* - fast, 3 - boundflipping)
499  if( !soplex->setIntParam(SoPlex::RATIOTESTER, option[2] - '0') )
500  {
501  printUsage(argv, optidx);
502  returnValue = 1;
503  goto TERMINATE_FREESTRINGS;
504  }
505  break;
506 
507  case 'v' :
508  // -v<level> : set verbosity to <level> (0 - error, 3 - normal, 5 - high)
509  if( !soplex->setIntParam(SoPlex::VERBOSITY, option[2] - '0') )
510  {
511  printUsage(argv, optidx);
512  returnValue = 1;
513  goto TERMINATE_FREESTRINGS;
514  }
515  break;
516 
517  case 'x' :
518  // -x : print primal solution
519  printPrimal = true;
520  break;
521 
522  case 'X' :
523  // -X : print primal solution with rationals
524  printPrimalRational = true;
525  break;
526 
527  case 'y' :
528  // -y : print dual multipliers
529  printDual = true;
530  break;
531 
532  case 'Y' :
533  // -Y : print dual multipliers with rationals
534  printDualRational = true;
535  break;
536 
537  case 'q' :
538  // -q : display detailed statistics
539  displayStatistics = true;
540  break;
541 
542  case 'c' :
543  // -c : perform final check of optimal solution in original problem
544  checkSol = true;
545  break;
546 
547  //lint -fallthrough
548  default :
549  {
550  printUsage(argv, optidx);
551  returnValue = 1;
552  goto TERMINATE_FREESTRINGS;
553  }
554  }
555  }
556 
557  MSG_INFO1( soplex->spxout, soplex->printUserSettings(); )
558 
559  // no LP file was given and no settings files are written
560  if( optidx >= argc && savesetname == 0 && diffsetname == 0 )
561  {
562  printUsage(argv, 0);
563  returnValue = 1;
564  goto TERMINATE_FREESTRINGS;
565  }
566 
567  // ensure that syncmode is not manual
569  {
570  MSG_ERROR( std::cerr << "Error: manual synchronization is invalid on command line. Change parameter int:syncmode.\n" );
571  returnValue = 1;
572  goto TERMINATE_FREESTRINGS;
573  }
574 
575  // save settings files
576  if( savesetname != 0 )
577  {
578  MSG_INFO1( soplex->spxout, soplex->spxout << "Saving parameters to settings file <" << savesetname << "> . . .\n" );
579  if( !soplex->saveSettingsFile(savesetname, false) )
580  {
581  MSG_ERROR( std::cerr << "Error writing parameters to file <" << savesetname << ">\n" );
582  }
583  }
584  if( diffsetname != 0 )
585  {
586  MSG_INFO1( soplex->spxout, soplex->spxout << "Saving modified parameters to settings file <" << diffsetname << "> . . .\n" );
587  if( !soplex->saveSettingsFile(diffsetname, true) )
588  {
589  MSG_ERROR( std::cerr << "Error writing modified parameters to file <" << diffsetname << ">\n" );
590  }
591  }
592 
593  // no LP file given: exit after saving settings
594  if( optidx >= argc )
595  {
596  if( loadsetname != 0 || savesetname != 0 || diffsetname != 0 )
597  {
598  MSG_INFO1( soplex->spxout, soplex->spxout << "\n" );
599  }
600  goto TERMINATE_FREESTRINGS;
601  }
602 
603  // measure time for reading LP file and basis file
604  readingTime->start();
605 
606  // if the LP is parsed rationally and might be solved rationally, we choose automatic syncmode such that
607  // the rational LP is kept after reading
610  {
612  }
613 
614  // read LP from input file
615  lpfilename = argv[optidx];
616  MSG_INFO1( soplex->spxout, soplex->spxout << "Reading "
617  << (soplex->intParam(SoPlex::READMODE) == SoPlex::READMODE_REAL ? "(real)" : "(rational)")
618  << " LP file <" << lpfilename << "> . . .\n" );
619 
620  if( !soplex->readFile(lpfilename, &rownames, &colnames) )
621  {
622  MSG_ERROR( std::cerr << "Error while reading file <" << lpfilename << ">.\n" );
623  returnValue = 1;
624  goto TERMINATE_FREESTRINGS;
625  }
626 
627  // write LP if specified
628  if( writefilename != 0 )
629  {
630  if( !soplex->writeFileReal(writefilename, &rownames, &colnames) )
631  {
632  MSG_ERROR( std::cerr << "Error while writing file <" << writefilename << ">.\n\n" );
633  returnValue = 1;
634  goto TERMINATE_FREESTRINGS;
635  }
636  else
637  {
638  MSG_INFO1( soplex->spxout, soplex->spxout << "Written LP to file <" << writefilename << ">.\n\n" );
639  }
640  }
641 
642  // read basis file if specified
643  if( readbasname != 0 )
644  {
645  MSG_INFO1( soplex->spxout, soplex->spxout << "Reading basis file <" << readbasname << "> . . . " );
646  if( !soplex->readBasisFile(readbasname, &rownames, &colnames) )
647  {
648  MSG_ERROR( std::cerr << "Error while reading file <" << readbasname << ">.\n" );
649  returnValue = 1;
650  goto TERMINATE_FREESTRINGS;
651  }
652  }
653 
654  readingTime->stop();
655 
656  MSG_INFO1( soplex->spxout,
657  std::streamsize prec = soplex->spxout.precision();
658  soplex->spxout << "Reading took "
659  << std::fixed << std::setprecision(2) << readingTime->time()
660  << std::scientific << std::setprecision(int(prec))
661  << " seconds.\n\n" );
662 
663  MSG_INFO1( soplex->spxout, soplex->spxout << "LP has " << soplex->numRowsReal() << " rows "
664  << soplex->numColsReal() << " columns and " << soplex->numNonzerosReal() << " nonzeros.\n\n" );
665 
666  // solve the LP
667  soplex->solve();
668 
669  // print solution, check solution, and display statistics
670  if( printPrimal )
671  {
672  DVector primal(soplex->numColsReal());
673  if( soplex->getPrimalReal(primal) )
674  {
675  MSG_INFO1( soplex->spxout, soplex->spxout << "\nPrimal solution (name, value):\n"; )
676  for( int i = 0; i < soplex->numColsReal(); ++i )
677  {
678  if ( isNotZero( primal[i] ) )
679  MSG_INFO1( soplex->spxout, soplex->spxout << colnames[i] << "\t"
680  << std::setw(17)
681  << std::setprecision(9)
682  << primal[i] << std::endl; )
683  }
684  MSG_INFO1( soplex->spxout, soplex->spxout << "All other variables are zero (within "
685  << std::setprecision(1) << std::scientific << Param::epsilon()
686  << std::setprecision(8) << std::fixed << ")." << std::endl; )
687  }
688  else
689  MSG_INFO1( soplex->spxout, soplex->spxout << "No primal solution available.")
690  }
691 
692 
693  if( printPrimalRational )
694  {
695  DVectorRational primal(soplex->numColsReal());
696  if( soplex->getPrimalRational(primal) )
697  {
698  MSG_INFO1( soplex->spxout, soplex->spxout << "\nPrimal solution (name, value):\n"; )
699  for( int i = 0; i < soplex->numColsRational(); ++i )
700  {
701  if ( primal[i] != (Rational) 0 )
702  MSG_INFO1( soplex->spxout, soplex->spxout << colnames[i] << "\t"
703  << std::setw(17)
704  << std::setprecision(9)
705  << primal[i] << std::endl; )
706  }
707  MSG_INFO1( soplex->spxout, soplex->spxout << "All other variables are zero." << std::endl; )
708  }
709  else
710  MSG_INFO1( soplex->spxout, soplex->spxout << "No primal (rational) solution available.")
711  }
712 
713 
714  if( printDual )
715  {
716  DVector dual(soplex->numRowsReal());
717  if( soplex->getDualReal(dual) )
718  {
719  MSG_INFO1( soplex->spxout, soplex->spxout << "\nDual multipliers (name, value):\n"; )
720  for( int i = 0; i < soplex->numRowsReal(); ++i )
721  {
722  if ( isNotZero( dual[i] ) )
723  MSG_INFO1( soplex->spxout, soplex->spxout << rownames[i] << "\t"
724  << std::setw(17)
725  << std::setprecision(9)
726  << dual[i] << std::endl; )
727  }
728  MSG_INFO1( soplex->spxout, soplex->spxout << "All other dual values are zero (within "
729  << std::setprecision(1) << std::scientific << Param::epsilon()
730  << std::setprecision(8) << std::fixed << ")." << std::endl; )
731  }
732  else
733  MSG_INFO1( soplex->spxout, soplex->spxout << "No dual solution available.")
734  }
735 
736 
737  if( printDualRational )
738  {
739  DVectorRational dual(soplex->numRowsReal());
740  if( soplex->getDualRational(dual) )
741  {
742  MSG_INFO1( soplex->spxout, soplex->spxout << "\nDual multipliers (name, value):\n"; )
743  for( int i = 0; i < soplex->numRowsRational(); ++i )
744  {
745  if ( dual[i] != (Rational) 0 )
746  MSG_INFO1( soplex->spxout, soplex->spxout << rownames[i] << "\t" << dual[i] << std::endl; )
747  }
748  MSG_INFO1( soplex->spxout, soplex->spxout << "All other dual values are zero." << std::endl; )
749  }
750  else
751  MSG_INFO1( soplex->spxout, soplex->spxout << "No dual (rational) solution available.")
752  }
753 
754 
755  if( checkSol )
756  checkSolution(*soplex);
757 
758  if( displayStatistics )
759  {
760  MSG_INFO1( soplex->spxout, soplex->spxout << "Statistics\n==========\n\n" );
761  soplex->printStatistics(soplex->spxout.getStream(SPxOut::INFO1));
762  }
763 
764  // write basis file if specified
765  if( writebasname != 0 )
766  {
767  if( !soplex->hasBasis() )
768  {
769  MSG_WARNING( soplex->spxout, soplex->spxout << "No basis information available. Could not write file <" << writebasname << ">\n\n" );
770  }
771  else if( !soplex->writeBasisFile(writebasname, &rownames, &colnames) )
772  {
773  MSG_ERROR( std::cerr << "Error while writing file <" << writebasname << ">.\n\n" );
774  returnValue = 1;
775  goto TERMINATE_FREESTRINGS;
776  }
777  else
778  {
779  MSG_INFO1( soplex->spxout, soplex->spxout << "Written basis information to file <" << writebasname << ">.\n\n" );
780  }
781  }
782  }
783  catch( const SPxException& x )
784  {
785  MSG_ERROR( std::cerr << "Exception caught: " << x.what() << "\n" );
786  returnValue = 1;
787  goto TERMINATE_FREESTRINGS;
788  }
789 
790  TERMINATE_FREESTRINGS:
791  freeStrings(readbasname, writebasname, loadsetname, savesetname, diffsetname);
792 
793  TERMINATE:
794  // because EGlpNumClear() calls mpq_clear() for all mpq_t variables, we need to destroy all objects of class Rational
795  // beforehand; hence all Rational objects and all data that uses Rational objects must be allocated dynamically via
796  // spx_alloc() and freed here; disabling the list memory is crucial
797  soplex->~SoPlex();
798  spx_free(soplex);
800  EGlpNumClear();
801  readingTime->~Timer();
802  spx_free(readingTime);
803 
804  return returnValue;
805 }
806 #else
807 #include <assert.h>
808 #include <math.h>
809 #include <string.h>
810 #include <iostream>
811 #include <iomanip>
812 #include <fstream>
813 
814 #include "spxdefines.h"
815 #include "soplex.h"
816 #include "spxsolver.h"
817 
818 #include "timer.h"
819 #include "spxgithash.h"
820 #include "spxpricer.h"
821 #include "spxdantzigpr.h"
822 #include "spxparmultpr.h"
823 #include "spxdevexpr.h"
824 #include "spxhybridpr.h"
825 #include "spxsteeppr.h"
826 #include "spxsteepexpr.h"
827 #include "spxweightpr.h"
828 #include "spxratiotester.h"
829 #include "spxharrisrt.h"
830 #include "spxdefaultrt.h"
831 #include "spxfastrt.h"
832 #include "spxboundflippingrt.h"
833 #include "spxsimplifier.h"
834 #include "spxmainsm.h"
835 #include "spxscaler.h"
836 #include "spxequilisc.h"
837 #include "spxgeometsc.h"
838 #include "spxsumst.h"
839 #include "spxweightst.h"
840 #include "spxvectorst.h"
841 #include "slufactor.h"
842 #include "spxout.h"
843 
844 using namespace soplex;
845 
846 
847 //------------------------------------------------------------------------
848 // for simplicity: store whether we are in check mode:
849 static bool checkMode = false;
850 //------------------------------------------------------------------------
851 
852 
853 //------------------------------------------------------------------------
854 // class MySoPlex
855 //------------------------------------------------------------------------
856 
857 /** LP solver class for the command line. */
858 class MySoPlex : public SoPlex
859 {
860 public:
861  /// default constructor
862  MySoPlex( SPxOut& outstream,
865  : SoPlex(outstream, p_type, p_rep)
866  {}
867  //------------------------------------------------------------------------
868  /// virtual destructor
869  virtual ~MySoPlex()
870  {}
871  //------------------------------------------------------------------------
872  void displayQuality() const
873  {
874  Real maxviol;
875  Real sumviol;
876 
877  if ( checkMode )
878  {
879  MSG_INFO1( (*spxout), (*spxout) << "IEXAMP05 Violations (max/sum)" << std::endl; )
880 
881  m_solver.qualConstraintViolation(maxviol, sumviol);
882 
883  MSG_INFO1( (*spxout), (*spxout) << "IEXAMP06 Constraints :"
884  << std::setw(16) << maxviol << " "
885  << std::setw(16) << sumviol << std::endl; )
886 
887  qualConstraintViolation(maxviol, sumviol);
888 
889  MSG_INFO1( (*spxout), (*spxout) << "IEXAMP07 (unscaled) :"
890  << std::setw(16) << maxviol << " "
891  << std::setw(16) << sumviol << std::endl; )
892 
893  m_solver.qualBoundViolation(maxviol, sumviol);
894 
895  MSG_INFO1( (*spxout), (*spxout) << "IEXAMP08 Bounds :"
896  << std::setw(16) << maxviol << " "
897  << std::setw(16) << sumviol << std::endl; )
898 
899  qualBoundViolation(maxviol, sumviol);
900 
901  MSG_INFO1( (*spxout), (*spxout) << "IEXAMP09 (unscaled) :"
902  << std::setw(16) << maxviol << " "
903  << std::setw(16) << sumviol << std::endl; )
904 
905  if (!m_vanished)
906  {
907  m_solver.qualSlackViolation(maxviol, sumviol);
908 
909  MSG_INFO1( (*spxout), (*spxout) << "IEXAMP10 Slacks :"
910  << std::setw(16) << maxviol << " "
911  << std::setw(16) << sumviol << std::endl; )
912 
913  m_solver.qualRedCostViolation(maxviol, sumviol);
914 
915  MSG_INFO1( (*spxout), (*spxout) << "IEXAMP11 Reduced costs :"
916  << std::setw(16) << maxviol << " "
917  << std::setw(16) << sumviol << std::endl; )
918 #if 0
919  MSG_INFO1( (*spxout), (*spxout) << "IEXAMP12 Proven dual bound:"
920  << std::setw(20)
921  << std::setprecision(20)
922  << m_solver.provedDualbound() << std::endl; )
923 #endif
924  }
925  }
926  else
927  {
928  MSG_INFO1( (*spxout), (*spxout) << "Violations (max/sum)" << std::endl; )
929 
930  m_solver.qualConstraintViolation(maxviol, sumviol);
931 
932  MSG_INFO1( (*spxout), (*spxout) << "Constraints :"
933  << std::setw(16) << maxviol << " "
934  << std::setw(16) << sumviol << std::endl; )
935 
936  qualConstraintViolation(maxviol, sumviol);
937 
938  MSG_INFO1( (*spxout), (*spxout) << " (unscaled) :"
939  << std::setw(16) << maxviol << " "
940  << std::setw(16) << sumviol << std::endl; )
941 
942  m_solver.qualBoundViolation(maxviol, sumviol);
943 
944  MSG_INFO1( (*spxout), (*spxout) << "Bounds :"
945  << std::setw(16) << maxviol << " "
946  << std::setw(16) << sumviol << std::endl; )
947 
948  qualBoundViolation(maxviol, sumviol);
949 
950  MSG_INFO1( (*spxout), (*spxout) << " (unscaled) :"
951  << std::setw(16) << maxviol << " "
952  << std::setw(16) << sumviol << std::endl; )
953 
954  if (!m_vanished)
955  {
956  m_solver.qualSlackViolation(maxviol, sumviol);
957 
958  MSG_INFO1( (*spxout), (*spxout) << "Slacks :"
959  << std::setw(16) << maxviol << " "
960  << std::setw(16) << sumviol << std::endl; )
961 
962  m_solver.qualRedCostViolation(maxviol, sumviol);
963 
964  MSG_INFO1( (*spxout), (*spxout) << "Reduced costs :"
965  << std::setw(16) << maxviol << " "
966  << std::setw(16) << sumviol << std::endl; )
967 #if 0
968  MSG_INFO1( (*spxout), (*spxout) << "Proven dual bound:"
969  << std::setw(20)
970  << std::setprecision(20)
971  << m_solver.provedDualbound() << std::endl; )
972 #endif
973  }
974  }
975  }
976  //------------------------------------------------------------------------
977  void displayInfeasibility() const
978  {
979  assert(m_solver.status() == SPxSolver::INFEASIBLE);
980 
981 #if 0
982  if ( checkMode )
983  {
984  if( m_solver.isProvenInfeasible() )
985  MSG_INFO1( (*spxout), (*spxout) << "IEXAMP13 Infeasibility is proven." << std::endl; )
986  else
987  MSG_INFO1( (*spxout), (*spxout) << "IEXAMP13 Infeasibility could not be proven!" << std::endl; )
988  }
989  else
990  {
991  if ( m_solver.isProvenInfeasible() )
992  {
993  MSG_INFO1( (*spxout), (*spxout) << "Infeasibility is proven." << std::endl; )
994  }
995  else
996  {
997  MSG_INFO1( (*spxout), (*spxout) << "Infeasibility could not be proven!" << std::endl; )
998  }
999  }
1000 #endif
1001  }
1002 };
1003 
1004 
1005 //------------------------------------------------------------------------
1006 // Helpers
1007 //------------------------------------------------------------------------
1008 
1009 static
1010 void print_version_info()
1011 {
1012  const char* banner1 =
1013  "************************************************************************\n"
1014  "* *\n"
1015  "* SoPlex --- the Sequential object-oriented simPlex. *\n"
1016  ;
1017 
1018  const char* banner2 =
1019  "* *\n"
1020  "* Copyright (C) 1996-2016 Konrad-Zuse-Zentrum *\n"
1021  "* fuer Informationstechnik Berlin *\n"
1022  "* *\n"
1023  "* SoPlex is distributed under the terms of the ZIB Academic Licence. *\n"
1024  "* You should have received a copy of the ZIB Academic License *\n"
1025  "* along with SoPlex; If not email to soplex@zib.de. *\n"
1026  "* *\n"
1027  "************************************************************************\n"
1028  ;
1029 
1030  if( !checkMode )
1031  std::cout << banner1;
1032 
1033 #if (SOPLEX_SUBVERSION > 0)
1034  if( !checkMode )
1035  std::cout << "* Version ";
1036  else
1037  std::cout << "SoPlex version ";
1038  std::cout << SOPLEX_VERSION/100 << "."
1039  << (SOPLEX_VERSION % 100)/10 << "."
1040  << SOPLEX_VERSION % 10 << "."
1042  << " - Githash "
1043  << std::setw(13) << std::setiosflags(std::ios::left) << getGitHash();
1044  if( !checkMode )
1045  std::cout << " *\n" << banner2 << std::endl;
1046  else
1047  std::cout << "\n";
1048 #else
1049  if( !checkMode )
1050  std::cout << "* Release ";
1051  else
1052  std::cout << "SoPlex release ";
1053  std::cout << SOPLEX_VERSION/100 << "."
1054  << (SOPLEX_VERSION % 100)/10 << "."
1055  << SOPLEX_VERSION % 10
1056  << " - Githash "
1057  << std::setw(13) << std::setiosflags(std::ios::left) << getGitHash();
1058  if( !checkMode )
1059  std::cout << " *\n" << banner2 << std::endl;
1060  else
1061  std::cout << "\n";
1062 #endif
1063 
1064  /// The following code block is tests and shows compilation parameters.
1065  std::cout << "[NDEBUG:"
1066 #ifdef NDEBUG
1067  << "YES"
1068 #else
1069  << "NO"
1070 #endif
1071  << "]";
1072 
1073  std::cout << "[WITH_WARNINGS:"
1074 #ifdef WITH_WARNINGS
1075  << "YES"
1076 #else
1077  << "NO"
1078 #endif
1079  << "]";
1080 
1081  std::cout << "[ENABLE_ADDITIONAL_CHECKS:"
1082 #ifdef ENABLE_ADDITIONAL_CHECKS
1083  << "YES"
1084 #else
1085  << "NO"
1086 #endif
1087  << "]";
1088 
1089  std::cout << "[ENABLE_CONSISTENCY_CHECKS:"
1090 #ifdef ENABLE_CONSISTENCY_CHECKS
1091  << "YES"
1092 #else
1093  << "NO"
1094 #endif
1095  << "]";
1096 
1097  std::cout << "[SOPLEX_WITH_GMP:"
1098 #ifdef SOPLEX_WITH_GMP
1099  << "YES"
1100 #else
1101  << "NO"
1102 #endif
1103  << "]" << std::endl;
1104 
1105  std::cout << std::endl;
1106 }
1107 
1108 #if 0
1109 static
1110 void print_short_version_info()
1111 {
1112  const char* banner1 =
1113  "************************************************************************\n"
1114  "* SoPlex --- the Sequential object-oriented simPlex. ";
1115  const char* banner2 =
1116  "* Copyright (C) 1996-2016 Konrad-Zuse-Zentrum *\n"
1117  "* fuer Informationstechnik Berlin *\n"
1118  "************************************************************************\n";
1119 
1120  std::cout << banner1;
1121 #if (SOPLEX_SUBVERSION > 0)
1122  std::cout << "Version "
1123  << SOPLEX_VERSION/100 << "."
1124  << (SOPLEX_VERSION % 100)/10 << "."
1125  << SOPLEX_VERSION % 10 << "."
1127  << " *\n";
1128 #else
1129  std::cout << "Release "
1130  << SOPLEX_VERSION/100 << "."
1131  << (SOPLEX_VERSION % 100)/10 << "."
1132  << SOPLEX_VERSION % 10
1133  << " *\n";
1134 #endif
1135  std::cout << banner2 << std::endl;
1136 }
1137 #endif
1138 
1139 //------------------------------------------------------------------------
1140 static
1141 void print_usage_and_exit( const char* const argv[] )
1142 {
1143  const char* usage =
1144  "[options] LPfile [Basfile]\n\n"
1145  " LPfile can be either in MPS or LPF format\n\n"
1146  "options: (*) indicates default\n"
1147  " (!) indicates experimental features which may give wrong results\n"
1148  " -e select entering algorithm (default is leaving)\n"
1149  " -r select row wise representation (default is column)\n"
1150  " -i select Eta-update (default is Forest-Tomlin)\n"
1151  " -x output solution vector\n"
1152  " -y output dual multipliers\n"
1153  " -q display solution quality\n"
1154  " -br read file with starting basis from Basfile\n"
1155  " -bw write file with optimal basis to Basfile\n"
1156  " -l set time limit in seconds\n"
1157  " -L set iteration limit\n"
1158  " -f set primal feasibility tolerance\n"
1159  " -o set optimality, i.e., dual feasibility tolerance\n"
1160  " -d set primal and dual feasibility tolerance to same value\n"
1161  " -zz set general zero tolerance\n"
1162  " -zf set factorization zero tolerance\n"
1163  " -zu set update zero tolerance\n"
1164  " -v set verbosity Level: from 0 (ERROR) to 5 (INFO3), default 3 (INFO1)\n"
1165  " -V show program version\n"
1166  " -C check mode (for check scripts)\n"
1167  " -h show this help\n\n"
1168  "Simplifier: Scaler: Starter: Pricer: Ratiotester:\n"
1169  " -s0 none -g0 none -c0 none* -p0 Textbook -t0 Textbook\n"
1170  " -s1 Main* -g1 uni-Equi -c1 Weight -p1 ParMult -t1 Harris\n"
1171  " -g2 bi-Equi* -c2 Sum -p2 Devex -t2 Fast\n"
1172  " -g3 bi-Equi+Geo1 -c3 Vector -p3 Hybrid! -t3 Bound Flipping*\n"
1173  " -g4 bi-Equi+Geo8 -p4 Steep*\n"
1174  " -p5 Weight\n"
1175  " -p6 SteepExactSetup\n"
1176  ;
1177 
1178  std::cerr << "usage: " << argv[0] << " " << usage << std::endl;
1179  exit(0);
1180 }
1181 
1182 //------------------------------------------------------------------------
1183 static
1184 void check_parameter(const char param, const char* const argv[])
1185 {
1186  if (param == '\0')
1187  print_usage_and_exit( argv );
1188 }
1189 
1190 //------------------------------------------------------------------------
1191 static
1192 void print_algorithm_parameters(
1193  MySoPlex& work,
1194  const SPxSolver::Representation representation,
1195  const SLUFactor::UpdateType update
1196  )
1197 {
1198  if ( checkMode )
1199  {
1200  MSG_INFO1( (*work.spxout), (*work.spxout)
1201  << "IEXAMP12 Feastol = "
1202  << std::setw(16) << work.feastol() << std::endl
1203  << "IEXAMP52 Opttol = "
1204  << std::setw(16) << work.opttol() << std::endl
1205  << "IEXAMP13 Epsilon Zero = "
1206  << std::setw(16) << Param::epsilon() << std::endl
1207  << "IEXAMP37 Epsilon Factor = "
1208  << std::setw(16) << Param::epsilonFactorization() << std::endl
1209  << "IEXAMP38 Epsilon Update = "
1210  << std::setw(16) << Param::epsilonUpdate() << std::endl
1211  << "IEXAMP14 "
1212  << (work.type() == SPxSolver::ENTER ? "Entering" : "Leaving")
1213  << " algorithm" << std::endl
1214  << "IEXAMP15 "
1215  << (representation == SPxSolver::ROW ? "Row" : "Column")
1216  << " representation" << std::endl
1217  << "IEXAMP16 "
1218  << (update == SLUFactor::ETA ? "Eta" : "Forest-Tomlin")
1219  << " update" << std::endl; )
1220  }
1221  else
1222  {
1223  MSG_INFO1( (*work.spxout), (*work.spxout)
1224  << "SoPlex parameters: " << std::endl
1225  << "Feastol = "
1226  << std::setw(16) << work.feastol() << std::endl
1227  << "Opttol = "
1228  << std::setw(16) << work.opttol() << std::endl
1229  << "Epsilon Zero = "
1230  << std::setw(16) << Param::epsilon() << std::endl
1231  << "Epsilon Factor = "
1232  << std::setw(16) << Param::epsilonFactorization() << std::endl
1233  << "Epsilon Update = "
1234  << std::setw(16) << Param::epsilonUpdate() << std::endl
1235  << std::endl
1236  << "algorithm = " << (work.type() == SPxSolver::ENTER ? "Entering" : "Leaving")
1237  << std::endl
1238  << "representation = " << (representation == SPxSolver::ROW ? "Row" : "Column")
1239  << std::endl
1240  << "update = " << (update == SLUFactor::ETA ? "Eta" : "Forest-Tomlin")
1241  << std::endl; )
1242  }
1243 }
1244 
1245 //------------------------------------------------------------------------
1246 static
1247 SPxPricer* get_pricer(const int pricing, SPxOut* spxout)
1248 {
1249  SPxPricer* pricer = 0;
1250  switch(pricing)
1251  {
1252  case 6 :
1253  pricer = new SPxSteepExPR;
1254  break;
1255  case 5 :
1256  pricer = new SPxWeightPR;
1257  break;
1258  case 4 :
1259  pricer = new SPxSteepPR;
1260  break;
1261  case 3 :
1262  pricer = new SPxHybridPR;
1263  break;
1264  case 2 :
1265  pricer = new SPxDevexPR;
1266  break;
1267  case 1 :
1268  pricer = new SPxParMultPR;
1269  break;
1270  case 0 :
1271  /*FALLTHROUGH*/
1272  default :
1273  pricer = new SPxDantzigPR;
1274  break;
1275  }
1276 
1277  assert(pricer != 0);
1278  if ( checkMode )
1279 #ifdef PARTIAL_PRICING
1280  MSG_INFO1( (*spxout), (*spxout) << "IEXAMP17 " << pricer->getName() << " pricing"
1281  << " (partial, size = " << MAX_PRICING_CANDIDATES << ")"
1282  << std::endl; )
1283 #else
1284  MSG_INFO1( (*spxout), (*spxout) << "IEXAMP17 " << pricer->getName() << " pricing"
1285  << std::endl; )
1286 #endif
1287  else
1288 #ifdef PARTIAL_PRICING
1289  MSG_INFO1( (*spxout), (*spxout) << "pricing = " << pricer->getName()
1290  << " (partial, size = " << MAX_PRICING_CANDIDATES << ")"
1291  << std::endl; )
1292 #else
1293  MSG_INFO1( (*spxout), (*spxout) << "pricing = " << pricer->getName()
1294  << std::endl; )
1295 #endif
1296  return pricer;
1297 }
1298 
1299 //------------------------------------------------------------------------
1300 static
1301 SPxRatioTester* get_ratio_tester(const int ratiotest, SPxOut* spxout)
1302 {
1303  SPxRatioTester* ratiotester = 0;
1304  switch(ratiotest)
1305  {
1306  case 3 :
1307  ratiotester = new SPxBoundFlippingRT;
1308  break;
1309  case 2 :
1310  ratiotester = new SPxFastRT;
1311  break;
1312  case 1 :
1313  ratiotester = new SPxHarrisRT;
1314  break;
1315  case 0 :
1316  /*FALLTHROUGH*/
1317  default:
1318  ratiotester = new SPxDefaultRT;
1319  break;
1320  }
1321 
1322  assert(ratiotester != 0);
1323  if ( checkMode )
1324  MSG_INFO1( (*spxout), (*spxout) << "IEXAMP18 " << ratiotester->getName() << " ratiotest" << std::endl; )
1325  else
1326  MSG_INFO1( (*spxout), (*spxout) << "ratiotest = " << ratiotester->getName() << std::endl; )
1327  return ratiotester;
1328 }
1329 
1330 //------------------------------------------------------------------------
1331 static
1332 void get_scalers(
1333  SPxScaler*& prescaler,
1334  SPxScaler*& postscaler,
1335  const int scaling,
1336  SPxOut* spxout
1337  )
1338 {
1339  switch(scaling)
1340  {
1341  case 4:
1342  prescaler = new SPxEquiliSC(true);
1343  postscaler = new SPxGeometSC(8);
1344  break;
1345  case 3:
1346  prescaler = new SPxEquiliSC(true);
1347  postscaler = new SPxGeometSC(1);
1348  break;
1349  case 2 :
1350  prescaler = new SPxEquiliSC(true);
1351  postscaler = 0;
1352  break;
1353  case 1 :
1354  prescaler = new SPxEquiliSC(false);
1355  postscaler = 0;
1356  break;
1357  case 0 :
1358  /*FALLTHROUGH*/
1359  default :
1360  prescaler = 0;
1361  postscaler = 0;
1362  break;
1363  }
1364 
1365  if ( checkMode )
1366  {
1367  MSG_INFO1( (*spxout), (*spxout) << "IEXAMP19 "
1368  << ((prescaler != 0) ? prescaler->getName() : "no")
1369  << " / "
1370  << ((postscaler != 0) ? postscaler->getName() : "no")
1371  << " scaling" << std::endl; )
1372  }
1373  else
1374  {
1375  MSG_INFO1( (*spxout), (*spxout) << "scaling = "
1376  << ((prescaler != 0) ? prescaler->getName() : "no")
1377  << " / "
1378  << ((postscaler != 0) ? postscaler->getName() : "no")
1379  << std::endl; )
1380  }
1381 }
1382 
1383 //------------------------------------------------------------------------
1384 static
1385 SPxSimplifier* get_simplifier(const int simplifying, SPxOut* spxout)
1386 {
1387  SPxSimplifier* simplifier = 0;
1388  switch(simplifying)
1389  {
1390  case 1 :
1391  simplifier = new SPxMainSM;
1392  break;
1393  case 0 :
1394  /*FALLTHROUGH*/
1395  default :
1396  assert(simplifier == 0);
1397  break;
1398  }
1399 
1400  if ( checkMode )
1401  MSG_INFO1( (*spxout), (*spxout) << "IEXAMP20 " << ((simplifier == 0) ? "no" : simplifier->getName()) << " simplifier" << std::endl; )
1402  else
1403  MSG_INFO1( (*spxout), (*spxout) << "simplifier = " << ((simplifier == 0) ? "no" : simplifier->getName()) << std::endl; )
1404  return simplifier;
1405 }
1406 
1407 //------------------------------------------------------------------------
1408 static
1409 SPxStarter* get_starter(const int starting, SPxOut* spxout)
1410 {
1411  SPxStarter* starter = 0;
1412  switch(starting)
1413  {
1414  case 3 :
1415  starter = new SPxVectorST;
1416  break;
1417  case 2 :
1418  starter = new SPxSumST;
1419  break;
1420  case 1 :
1421  starter = new SPxWeightST;
1422  break;
1423  case 0 :
1424  /*FALLTHROUGH*/
1425  default :
1426  break;
1427  }
1428 
1429  if ( checkMode )
1430  MSG_INFO1( (*spxout), (*spxout) << "IEXAMP21 " << ((starter == 0) ? "no" : starter->getName()) << " starter" << std::endl; )
1431  else
1432  MSG_INFO1( (*spxout), (*spxout) << "starter = " << ((starter == 0) ? "no" : starter->getName()) << std::endl; )
1433 
1434  return starter;
1435 }
1436 
1437 //------------------------------------------------------------------------
1438 #ifdef SEND_ALL_OUTPUT_TO_FILES
1439 static
1440 void redirect_output(
1441  std::ostream& myerrstream,
1442  std::ostream& myinfostream
1443  )
1444 {
1445  myerrstream .setf( std::ios::scientific | std::ios::showpoint );
1446  myinfostream.setf( std::ios::scientific | std::ios::showpoint );
1447  spxout.setStream( SPxOut::ERROR, myerrstream );
1448  spxout.setStream( SPxOut::WARNING, myerrstream );
1449  spxout.setStream( SPxOut::INFO1, myinfostream );
1450  spxout.setStream( SPxOut::INFO2, myinfostream );
1451  spxout.setStream( SPxOut::INFO3, myinfostream );
1452  spxout.setStream( SPxOut::DEBUG, myinfostream );
1453 }
1454 #endif
1455 //------------------------------------------------------------------------
1456 static
1457 void read_input_file(
1458  MySoPlex& work,
1459  const char* filename,
1460  NameSet& rownames,
1461  NameSet& colnames)
1462 {
1463  if ( checkMode )
1464  MSG_INFO1( (*work.spxout), (*work.spxout) << "IEXAMP22 loading LP file " << filename << std::endl; )
1465  else
1466  MSG_INFO1( (*work.spxout), (*work.spxout) << "\nLoading LP file " << filename << std::endl; )
1467 
1468  UserTimer timer;
1469  timer.start();
1470 
1471  if ( ! work.readFile(filename, &rownames, &colnames, 0) )
1472  {
1473  if ( checkMode )
1474  MSG_INFO1( (*work.spxout), (*work.spxout) << "EEXAMP23 error while reading file \"" << filename << "\"" << std::endl; )
1475  else
1476  MSG_INFO1( (*work.spxout), (*work.spxout) << "error while reading file \"" << filename << "\"" << std::endl; )
1477  exit(1);
1478  }
1479  assert(work.isConsistent());
1480 
1481  timer.stop();
1482 
1483  if ( checkMode )
1484  {
1485  MSG_INFO1( (*work.spxout), (*work.spxout) << "IEXAMP24 LP has "
1486  << work.nRows() << " rows "
1487  << work.nCols() << " columns "
1488  << work.nNzos() << " nonzeros"
1489  << std::endl; )
1490 
1491  MSG_INFO1( (*work.spxout), (*work.spxout) << "IEXAMP41 LP reading time: " << timer.time() << std::endl; )
1492  }
1493  else
1494  {
1495  MSG_INFO1( (*work.spxout), (*work.spxout) << "LP has "
1496  << work.nRows() << " rows "
1497  << work.nCols() << " columns "
1498  << work.nNzos() << " nonzeros"
1499  << std::endl; )
1500 
1501  MSG_INFO1( (*work.spxout),
1502  std::streamsize prec = (*work.spxout).precision();
1503  (*work.spxout) << "LP reading time: " << std::fixed << std::setprecision(2) << timer.time();
1504  (*work.spxout) << std::scientific << std::setprecision(int(prec)) << std::endl; )
1505  }
1506 }
1507 
1508 //------------------------------------------------------------------------
1509 static
1510 void read_basis_file(
1511  MySoPlex& work ,
1512  const char* filename,
1513  const NameSet* rownames,
1514  const NameSet* colnames)
1515 {
1516  MSG_INFO1( (*work.spxout), (*work.spxout) << "Reading basis from file (disables simplifier)" << std::endl; )
1517  if (!work.readBasisFile(filename, rownames, colnames))
1518  {
1519  if ( checkMode )
1520  MSG_INFO1( (*work.spxout), (*work.spxout) << "EEXAMP25 error while reading file \"" << filename << "\"" << std::endl; )
1521  else
1522  MSG_INFO1( (*work.spxout), (*work.spxout) << "Error while reading file \"" << filename << "\"" << std::endl; )
1523  exit(1);
1524  }
1525 }
1526 
1527 //------------------------------------------------------------------------
1528 static
1529 void solve_LP(MySoPlex& work)
1530 {
1531  UserTimer timer;
1532  timer.start();
1533 
1534  if ( checkMode )
1535  MSG_INFO1( (*work.spxout), (*work.spxout) << "IEXAMP26 solving LP" << std::endl; )
1536  else
1537  MSG_INFO1( (*work.spxout), (*work.spxout) << "\nSolving LP ..." << std::endl; )
1538 
1539  work.solve();
1540  timer.stop();
1541 
1542  MSG_INFO1( (*work.spxout), (*work.spxout) << "\nSoPlex statistics:\n" << work.statistics(); )
1543 }
1544 
1545 //------------------------------------------------------------------------
1546 static
1547 void print_solution_and_status(
1548  MySoPlex& work,
1549  const NameSet& rownames,
1550  const NameSet& colnames,
1551  const int precision,
1552  const bool print_quality,
1553  const bool print_solution,
1554  const bool print_dual,
1555  const bool write_basis,
1556  const char* basisname
1557  )
1558 {
1559  // get the solution status
1560  SPxSolver::Status stat = work.status();
1561 
1562  if ( ! checkMode )
1563  MSG_INFO1( (*work.spxout), (*work.spxout) << std::endl; )
1564  switch (stat)
1565  {
1566  case SPxSolver::OPTIMAL:
1567  if ( checkMode )
1568  MSG_INFO1( (*work.spxout), (*work.spxout) << "IEXAMP29 solution value is: " << std::setprecision( precision ) << work.objValue() << std::endl; )
1569  else
1570  MSG_INFO1( (*work.spxout), (*work.spxout) << "Solution value is: " << std::setprecision( precision ) << work.objValue() << std::endl; )
1571 
1572  if ( print_quality )
1573  work.displayQuality();
1574 
1575  if ( print_solution )
1576  {
1577  DVector objx(work.nCols());
1578 
1579  if( work.getPrimal(objx) != SPxSolver::ERROR )
1580  {
1581  MSG_INFO1( (*work.spxout), (*work.spxout) << std::endl << "Primal solution (name, id, value):" << std::endl; )
1582  for( int i = 0; i < work.nCols(); ++i )
1583  {
1584  if ( isNotZero( objx[i], 0.001 * work.feastol() ) )
1585  MSG_INFO1( (*work.spxout), (*work.spxout) << colnames[ work.cId(i) ] << "\t"
1586  << i << "\t"
1587  << std::setw(17)
1588  << std::setprecision( precision )
1589  << objx[i] << std::endl; )
1590  }
1591  MSG_INFO1( (*work.spxout), (*work.spxout) << "All other variables are zero (within " << std::setprecision(1) << 0.001*work.feastol() << ")." << std::endl; )
1592  }
1593  }
1594  if ( print_dual )
1595  {
1596  DVector objy(work.nRows());
1597  bool allzero = true;
1598 
1599  if( work.getDual(objy) != SPxSolver::ERROR )
1600  {
1601  MSG_INFO1( (*work.spxout), (*work.spxout) << std::endl << "Dual multipliers (name, id, value):" << std::endl; )
1602  for( int i = 0; i < work.nRows(); ++i )
1603  {
1604  if ( isNotZero( objy[i] , 0.001 * work.opttol() ) )
1605  {
1606  MSG_INFO1( (*work.spxout), (*work.spxout) << rownames[ work.rId(i) ] << "\t"
1607  << i << "\t"
1608  << std::setw(17)
1609  << std::setprecision( precision )
1610  << objy[i] << std::endl; )
1611  allzero = false;
1612  }
1613  }
1614 
1615  MSG_INFO1( (*work.spxout), (*work.spxout) << "All " << (allzero ? "" : "other ") << "dual values are zero (within "
1616  << std::setprecision(1) << 0.001*work.opttol() << ")." << std::endl; )
1617 
1618  if( !allzero )
1619  {
1620  if( work.spxSense() == SPxLP::MINIMIZE )
1621  {
1622  MSG_INFO1( (*work.spxout), (*work.spxout) << "Minimizing: a positive/negative value corresponds to left-hand (>=) resp. right-hand (<=) side."
1623  << std::endl; )
1624  }
1625  else
1626  {
1627  MSG_INFO1( (*work.spxout), (*work.spxout) << "Maximizing: a positive/negative value corresponds to right-hand (<=) resp. left-hand (>=) side."
1628  << std::endl; )
1629  }
1630  }
1631  }
1632  }
1633  if ( write_basis )
1634  {
1635  MSG_INFO1( (*work.spxout), (*work.spxout) << "Writing basis of original problem to file " << basisname << std::endl; )
1636  if ( ! work.writeBasisFile( basisname, &rownames, &colnames ) )
1637  {
1638  if ( checkMode )
1639  MSG_INFO1( (*work.spxout), (*work.spxout) << "EEXAMP30 error while writing file \"" << basisname << "\"" << std::endl; )
1640  else
1641  MSG_INFO1( (*work.spxout), (*work.spxout) << "Error while writing file \"" << basisname << "\"" << std::endl; )
1642  }
1643  }
1644  break;
1645  case SPxSolver::UNBOUNDED:
1646  if ( checkMode )
1647  MSG_INFO1( (*work.spxout), (*work.spxout) << "IEXAMP31 LP is unbounded" << std::endl; )
1648  else
1649  MSG_INFO1( (*work.spxout), (*work.spxout) << "LP is unbounded" << std::endl; )
1650 
1651  if ( print_solution )
1652  {
1653  DVector objx(work.nCols());
1654  if( work.getPrimal(objx) != SPxSolver::ERROR )
1655  {
1656  MSG_INFO1( (*work.spxout), (*work.spxout) << std::endl << "Primal solution (name, id, value):" << std::endl; )
1657  for( int i = 0; i < work.nCols(); ++i )
1658  {
1659  if ( isNotZero( objx[i], 0.001 * work.feastol() ) )
1660  MSG_INFO1( (*work.spxout), (*work.spxout) << colnames[ work.cId(i) ] << "\t"
1661  << i << "\t"
1662  << std::setw(17)
1663  << std::setprecision( precision )
1664  << objx[i] << std::endl; )
1665  }
1666  MSG_INFO1( (*work.spxout), (*work.spxout) << "All other variables are zero (within " << std::setprecision(1) << 0.001*work.feastol() << ")." << std::endl; )
1667  }
1668 
1669  DVector objcoef(work.nCols());
1670  DVector ray(work.nCols());
1671  if( work.getPrimalray(ray) != SPxSolver::ERROR )
1672  {
1673  Real rayobjval = 0.0;
1674 
1675  work.getObj(objcoef);
1676 
1677  MSG_INFO1( (*work.spxout), (*work.spxout) << std::endl << "Primal ray (name, id, value):" << std::endl; )
1678  for( int i = 0; i < work.nCols(); ++i )
1679  {
1680  if ( isNotZero( ray[i], 0.001 * work.feastol() ) )
1681  {
1682  rayobjval += ray[i] * objcoef[i];
1683 
1684  MSG_INFO1( (*work.spxout), (*work.spxout) << colnames[ work.cId(i) ] << "\t"
1685  << i << "\t"
1686  << std::setw(17)
1687  << std::setprecision( precision )
1688  << ray[i] << std::endl; )
1689  }
1690  }
1691  MSG_INFO1( (*work.spxout), (*work.spxout) << "All other variables have zero value (within " << std::setprecision(1) << 0.001*work.feastol() << ")." << std::endl; )
1692  MSG_INFO1( (*work.spxout), (*work.spxout) << "Objective change per unit along primal ray is " << rayobjval << "." << std::endl; )
1693  }
1694  }
1695  break;
1696  case SPxSolver::INFEASIBLE:
1697  if ( checkMode )
1698  MSG_INFO1( (*work.spxout), (*work.spxout) << "IEXAMP32 LP is infeasible" << std::endl; )
1699  else
1700  MSG_INFO1( (*work.spxout), (*work.spxout) << "LP is infeasible" << std::endl; )
1701  if ( print_solution )
1702  {
1703  DVector farkasx(work.nRows());
1704 
1705  if( work.getDualfarkas(farkasx) != SPxSolver::ERROR )
1706  {
1707  DVector proofvec(work.nCols());
1708  double lhs;
1709  double rhs;
1710 
1711  lhs = 0.0;
1712  rhs = 0.0;
1713  proofvec.clear();
1714  for( int i = 0; i < work.nRows(); ++i )
1715  {
1716  if ( isNotZero( farkasx[i], 0.001 * work.opttol() ) )
1717  {
1718  MSG_INFO1( (*work.spxout), (*work.spxout) << rownames[ work.rId(i) ] << "\t"
1719  << i << "\t"
1720  << std::setw(16)
1721  << std::setprecision( precision )
1722  << farkasx[i] << "\t"; )
1723  LPRow row;
1724  work.getRow(i, row);
1725  if( row.lhs() > -soplex::infinity )
1726  {
1727  MSG_INFO1( (*work.spxout), (*work.spxout) << row.lhs() << " <= "; );
1728  }
1729  for( int j = 0; j < row.rowVector().size(); ++j )
1730  {
1731  if( row.rowVector().value(j) > 0 )
1732  {
1733  MSG_INFO1( (*work.spxout), (*work.spxout) << "+"; )
1734  }
1735  MSG_INFO1( (*work.spxout), (*work.spxout)
1736  << row.rowVector().value(j) << " "
1737  << colnames[ work.cId(row.rowVector().index(j)) ]
1738  << " "; );
1739  }
1740  if( row.rhs() < soplex::infinity )
1741  {
1742  MSG_INFO1( (*work.spxout), (*work.spxout) << "<= " << row.rhs(); );
1743  }
1744  MSG_INFO1( (*work.spxout), (*work.spxout) << std::endl; )
1745  if( farkasx[i] > 0.0 )
1746  {
1747  lhs += farkasx[i] * row.lhs();
1748  rhs += farkasx[i] * row.rhs();
1749  }
1750  else
1751  {
1752  lhs += farkasx[i] * row.rhs();
1753  rhs += farkasx[i] * row.lhs();
1754  }
1755  SVector vec(row.rowVector());
1756  vec *= farkasx[i];
1757  proofvec += vec;
1758  }
1759  }
1760 
1761  MSG_INFO1( (*work.spxout), (*work.spxout) << "All other row multipliers are zero (within " << std::setprecision(1) << 0.001*work.opttol() << ")." << std::endl; )
1762  MSG_INFO1( (*work.spxout), (*work.spxout) << "Farkas infeasibility proof: \t"; )
1763  MSG_INFO1( (*work.spxout), (*work.spxout) << lhs << " <= "; )
1764 
1765  bool nonzerofound = false;
1766  for( int i = 0; i < work.nCols(); ++i )
1767  {
1768  if ( isNotZero( proofvec[i], 0.001 * work.opttol() ) )
1769  {
1770  if( proofvec[i] > 0 )
1771  {
1772  MSG_INFO1( (*work.spxout), (*work.spxout) << "+"; )
1773  }
1774  MSG_INFO1( (*work.spxout), (*work.spxout) << proofvec[i] << " " << colnames[ work.cId(i) ] << " "; )
1775  nonzerofound = true;
1776  }
1777  }
1778  if( !nonzerofound )
1779  {
1780  MSG_INFO1( (*work.spxout), (*work.spxout) << "0 "; );
1781  }
1782  MSG_INFO1( (*work.spxout), (*work.spxout) << "<= " << rhs << std::endl; );
1783  }
1784  }
1785  if ( print_quality )
1786  work.displayInfeasibility();
1787  if ( write_basis ) // write basis even if we are infeasible
1788  if ( ! work.writeBasisFile( basisname, &rownames, &colnames ) )
1789  {
1790  if ( checkMode )
1791  MSG_INFO1( (*work.spxout), (*work.spxout) << "EEXAMP30 error while writing file \"" << basisname << "\"" << std::endl; )
1792  else
1793  MSG_INFO1( (*work.spxout), (*work.spxout) << "Error while writing file \"" << basisname << "\"" << std::endl; )
1794  }
1795  break;
1797  if ( checkMode )
1798  MSG_INFO1( (*work.spxout), (*work.spxout) << "EEXAMP40 aborted due to cycling" << std::endl; )
1799  else
1800  MSG_INFO1( (*work.spxout), (*work.spxout) << "Aborted due to cycling" << std::endl; )
1801  break;
1802  case SPxSolver::ABORT_TIME:
1803  if ( checkMode )
1804  MSG_INFO1( (*work.spxout), (*work.spxout) << "IEXAMP33 aborted due to time limit" << std::endl; )
1805  else
1806  MSG_INFO1( (*work.spxout), (*work.spxout) << "Aborted due to time limit" << std::endl; )
1807  break;
1808  case SPxSolver::ABORT_ITER:
1809  if ( checkMode )
1810  MSG_INFO1( (*work.spxout), (*work.spxout) << "IEXAMP34 aborted due to iteration limit" << std::endl; )
1811  else
1812  MSG_INFO1( (*work.spxout), (*work.spxout) << "Aborted due to iteration limit" << std::endl; )
1813  break;
1815  if ( checkMode )
1816  MSG_INFO1( (*work.spxout), (*work.spxout) << "IEXAMP35 aborted due to objective value limit" << std::endl; )
1817  else
1818  MSG_INFO1( (*work.spxout), (*work.spxout) << "Aborted due to objective value limit" << std::endl; )
1819  break;
1820  case SPxSolver::SINGULAR:
1821  if ( checkMode )
1822  MSG_INFO1( (*work.spxout), (*work.spxout) << "EEXAMP39 basis is singular" << std::endl; )
1823  else
1824  MSG_INFO1( (*work.spxout), (*work.spxout) << "Basis is singular" << std::endl; )
1825  break;
1826  default:
1827  if ( checkMode )
1828  MSG_INFO1( (*work.spxout), (*work.spxout) << "EEXAMP36 An error occurred during " << "the solution process" << std::endl; )
1829  else
1830  MSG_INFO1( (*work.spxout), (*work.spxout) << "An error occurred during " << "the solution process" << std::endl; )
1831  break;
1832  }
1833  MSG_INFO1( (*work.spxout), (*work.spxout) << std::endl; )
1834 }
1835 
1836 //------------------------------------------------------------------------
1837 static
1838 void clean_up(
1839  SPxScaler*& prescaler,
1840  SPxScaler*& postscaler,
1841  SPxSimplifier*& simplifier,
1842  SPxStarter*& starter,
1843  SPxPricer*& pricer,
1844  SPxRatioTester*& ratiotester,
1845  char*& basisname
1846  )
1847 {
1848  if ( prescaler != 0 )
1849  {
1850  delete prescaler;
1851  prescaler = 0;
1852  }
1853  if ( postscaler != 0 )
1854  {
1855  delete postscaler;
1856  postscaler = 0;
1857  }
1858  if ( simplifier != 0 )
1859  {
1860  delete simplifier;
1861  simplifier = 0;
1862  }
1863  if ( starter != 0 )
1864  {
1865  delete starter;
1866  starter = 0;
1867  }
1868 
1869  assert( pricer != 0 );
1870  delete pricer;
1871  pricer = 0;
1872 
1873  assert( ratiotester != 0 );
1874  delete ratiotester;
1875  ratiotester = 0;
1876 
1877  if ( basisname != 0 )
1878  delete [] basisname;
1879  basisname = 0;
1880 }
1881 
1882 //------------------------------------------------------------------------
1883 // main program
1884 //------------------------------------------------------------------------
1885 
1886 int main(int argc, char* argv[])
1887 {
1888  const char* filename;
1889  char* basisname = 0;
1893  SPxSimplifier* simplifier = 0;
1894  SPxStarter* starter = 0;
1895  SPxPricer* pricer = 0;
1896  SPxRatioTester* ratiotester = 0;
1897  SPxScaler* prescaler = 0;
1898  SPxScaler* postscaler = 0;
1899 
1900  SPxOut spxout;
1901 
1902  try {
1903  NameSet rownames;
1904  NameSet colnames;
1905  int starting = 0;
1906  int pricing = 4;
1907  int ratiotest = 3;
1908  int scaling = 2;
1909  int simplifying = 1;
1910  int iterlimit = -1;
1911  Real timelimit = -1.0;
1912  Real delta = DEFAULT_BND_VIOL;
1913  Real feastol = DEFAULT_BND_VIOL;
1914  Real opttol = DEFAULT_BND_VIOL;
1915  Real epsilon = DEFAULT_EPS_ZERO;
1916  Real epsilon_factor = DEFAULT_EPS_FACTOR;
1917  Real epsilon_update = DEFAULT_EPS_UPDATE;
1918  int verbose = SPxOut::INFO1;
1919  bool print_solution = false;
1920  bool print_dual = false;
1921  bool print_quality = false;
1922  bool read_basis = false;
1923  bool write_basis = false;
1924  int precision;
1925  int optidx;
1926 
1927  for(optidx = 1; optidx < argc; optidx++)
1928  {
1929  if (*argv[optidx] != '-')
1930  break;
1931 
1932  switch(argv[optidx][1])
1933  {
1934  case 'b' :
1935  check_parameter(argv[optidx][2], argv); // use -b{r,w}, not -b
1936  if (argv[optidx][2] == 'r')
1937  read_basis = true;
1938  if (argv[optidx][2] == 'w')
1939  write_basis = true;
1940  break;
1941  case 'c' :
1942  check_parameter(argv[optidx][2], argv); // use -c[0-3], not -c
1943  starting = atoi(&argv[optidx][2]);
1944  break;
1945  case 'd' :
1946  check_parameter(argv[optidx][2], argv); // use -dx, not -d
1947  delta = atof(&argv[optidx][2]);
1948  break;
1949  case 'f' :
1950  check_parameter(argv[optidx][2], argv); // use -fx, not -f
1951  feastol = atof(&argv[optidx][2]);
1952  break;
1953  case 'o' :
1954  check_parameter(argv[optidx][2], argv); // use -ox, not -o
1955  opttol = atof(&argv[optidx][2]);
1956  break;
1957  case 'e':
1958  type = SPxSolver::ENTER;
1959  break;
1960  case 'g' :
1961  check_parameter(argv[optidx][2], argv); // use -g[0-5], not -g
1962  scaling = atoi(&argv[optidx][2]);
1963  break;
1964  case 'i' :
1965  update = SLUFactor::ETA;
1966  break;
1967  case 'l' :
1968  if (argv[optidx][2] == '\0' ) // use -lx, not -l
1969  print_usage_and_exit( argv );
1970  timelimit = atof(&argv[optidx][2]);
1971  break;
1972  case 'L' :
1973  if (argv[optidx][2] == '\0' ) // use -Lx, not -L
1974  print_usage_and_exit( argv );
1975  iterlimit = atoi(&argv[optidx][2]);
1976  break;
1977  case 'p' :
1978  check_parameter(argv[optidx][2], argv); // use -p[0-5], not -p
1979  pricing = atoi(&argv[optidx][2]);
1980  break;
1981  case 'q' :
1982  print_quality = true;
1983  break;
1984  case 'r' :
1985  representation = SPxSolver::ROW;
1986  break;
1987  case 's' :
1988  check_parameter(argv[optidx][2], argv); // use -s[0-4], not -s
1989  simplifying = atoi(&argv[optidx][2]);
1990  break;
1991  case 't' :
1992  check_parameter(argv[optidx][2], argv); // use -r[0-2], not -r
1993  ratiotest = atoi(&argv[optidx][2]);
1994  break;
1995  case 'v' :
1996  check_parameter(argv[optidx][2], argv); // use -v[0-5], not -v
1997  if (argv[optidx][2] >= '0' && argv[optidx][2] <= '9')
1998  verbose = argv[optidx][2] - '0';
1999  break;
2000  case 'V' :
2001  print_version_info();
2002  exit(0);
2003  case 'x' :
2004  print_solution = true;
2005  break;
2006  case 'y' :
2007  print_dual = true;
2008  break;
2009  case 'z' :
2010  check_parameter(argv[optidx][2], argv); // must not be empty
2011  check_parameter(argv[optidx][3], argv); // must not be empty
2012  switch(argv[optidx][2])
2013  {
2014  case 'z' :
2015  epsilon = atof(&argv[optidx][3]);
2016  break;
2017  case 'f' :
2018  epsilon_factor = atof(&argv[optidx][3]);
2019  break;
2020  case 'u' :
2021  epsilon_update = atof(&argv[optidx][3]);
2022  break;
2023  default :
2024  print_usage_and_exit( argv );
2025  }
2026  break;
2027  case 'C' :
2028  checkMode = true;
2029  break;
2030  case 'h' :
2031  case '?' :
2032  print_version_info();
2033  //lint -fallthrough
2034  default :
2035  print_usage_and_exit( argv );
2036  }
2037  }
2038 
2039  // print version
2040  print_version_info();
2041 
2042  // enough arguments?
2043  if ((argc - optidx) < 1 + (read_basis ? 1 : 0) + (write_basis ? 1 : 0))
2044  print_usage_and_exit( argv );
2045  filename = argv[optidx];
2046 
2047  ++optidx;
2048 
2049  // switch off simplifier when using a starting basis
2050  if ( read_basis )
2051  simplifying = 0;
2052 
2053  if ( read_basis || write_basis )
2054  basisname = strcpy( new char[strlen(argv[optidx]) + 1], argv[optidx] );
2055 
2056  // set some algorithm parameters
2057  Param::setEpsilon ( epsilon );
2058  Param::setEpsilonFactorization( epsilon_factor );
2059  Param::setEpsilonUpdate ( epsilon_update );
2060  spxout.setVerbosity ( (SPxOut::Verbosity) verbose );
2061 
2062  // Set the output precision.
2063  precision = int(-log10(std::min(feastol, opttol))) + 1;
2064 
2065  std::cout.setf( std::ios::scientific | std::ios::showpoint );
2066  std::cerr.setf( std::ios::scientific | std::ios::showpoint );
2067 
2068 #ifdef SEND_ALL_OUTPUT_TO_FILES
2069  // Example of redirecting output to different files.
2070  // Default is cerr for errors and warnings, cout for everything else.
2071  std::ofstream myerrstream ( "errwarn.txt" );
2072  std::ofstream myinfostream( "infos.txt" );
2073  redirect_output(myerrstream, myinfostream);
2074 #endif
2075 
2076  // create an instance of MySoPlex
2077  MySoPlex work( spxout, type, representation );
2078  work.setOutstream ( spxout );
2079  work.setUtype ( update );
2080  work.setFeastol ( std::min(feastol, delta) );
2081  work.setOpttol ( std::min(opttol, delta) );
2082  work.setTerminationTime ( timelimit );
2083  work.setTerminationIter ( iterlimit );
2084  print_algorithm_parameters( work, representation, update );
2085  assert( work.isConsistent() );
2086 
2087  // set pricer, starter, simplifier, and ratio tester
2088  work.setPricer ( pricer = get_pricer (pricing, work.spxout) );
2089  work.setStarter ( starter = get_starter (starting, work.spxout) );
2090  work.setSimplifier( simplifier = get_simplifier (simplifying, work.spxout) );
2091  work.setTester ( ratiotester = get_ratio_tester(ratiotest, work.spxout) );
2092  assert(work.isConsistent());
2093 
2094  // set pre- and postscaler
2095  get_scalers(prescaler, postscaler, scaling, work.spxout);
2096  work.setPreScaler (prescaler);
2097  work.setPostScaler(postscaler);
2098  assert(work.isConsistent());
2099 
2100  // read the LP from an input file (.lp or .mps)
2101  read_input_file(work, filename, rownames, colnames);
2102 
2103  // read a basis file if specified
2104  if (read_basis)
2105  read_basis_file(work, basisname, &rownames, &colnames);
2106 
2107  // solve the LP
2108  solve_LP(work);
2109 
2110  // print solution, status, infeasibility system,...
2111  print_solution_and_status(work, rownames, colnames, precision, print_quality,
2112  print_solution, print_dual, write_basis, basisname);
2113 
2114  // clean up
2115  clean_up(prescaler, postscaler, simplifier, starter, pricer, ratiotester, basisname);
2116 
2117  return 0;
2118  }
2119  catch( const SPxException& x )
2120  {
2121  std::cout << "exception caught : " << x.what() << std::endl;
2122  delete [] basisname;
2123  if (simplifier)
2124  delete simplifier;
2125  delete starter;
2126  delete pricer;
2127  delete ratiotester;
2128  delete prescaler;
2129  delete postscaler;
2130  }
2131 }
2132 #endif
Fast shifting ratio test.
bool isNotZero(Real a, Real eps=Param::epsilon())
returns true iff |a| > eps
Definition: spxdefines.h:413
int numColsReal() const
returns number of columns
Definition: soplex.cpp:779
virtual void setStream(const Verbosity &verbosity, std::ostream &stream)
Sets the stream for the specified verbosity level.
Definition: spxout.h:149
UpdateType
Specifies how to perform change method.
Definition: slufactor.h:49
Bound flipping ratio test ("long step dual") for SoPlex.Class SPxBoundFlippingRT provides an implemen...
#define DEFAULT_EPS_FACTOR
Definition: spxdefines.h:215
bool getDualViolationRational(Rational &maxviol, Rational &sumviol)
gets violation of dual multipliers; returns true on success
Definition: soplex.cpp:3430
#define EGlpNumStart()
Definition: soplexmain.cpp:37
static void setEpsilon(Real eps)
Definition: spxdefines.cpp:45
virtual const std::string what() const
returns exception message
Definition: exceptions.h:57
Devex pricer.The Devex Pricer for SoPlex implements an approximate steepest edge pricing, that does without solving an extra linear system and computing the scalar products.
Definition: spxdevexpr.h:43
#define DEFAULT_BND_VIOL
default allowed bound violation
Definition: spxdefines.h:208
Type
Algorithmic type.
Definition: spxsolver.h:124
bool hasBasis() const
is an advanced starting basis available?
Definition: soplex.cpp:3720
type of ratio test
Definition: soplex.h:891
Steepest edge pricer.Class SPxSteepExPR implements a steepest edge pricer to be used with SoPlex...
Definition: spxsteepexpr.h:40
Geometric mean row/column scaling.This SPxScaler implementation performs geometric mean scaling of th...
Definition: spxgeometsc.h:35
verbosity level
Definition: soplex.h:876
bool hasDual() const
is a dual feasible solution available?
Definition: soplex.cpp:2823
apply standard floating-point algorithm
Definition: soplex.h:1093
virtual const char * getName() const
get name of pricer.
Definition: spxpricer.h:109
Abstract pricer base class.
bool getPrimalReal(VectorReal &vector)
gets the primal solution vector if available; returns true on success
Definition: soplex.cpp:2865
SPxSolver::Status solve()
solves the LP
Definition: soplex.cpp:2722
bool getDualRational(VectorRational &vector)
gets the dual solution vector if available; returns true on success
Definition: soplex.cpp:3220
Solution vector based start basis.
time limit in seconds (INFTY if unlimited)
Definition: soplex.h:1166
mode for iterative refinement strategy
Definition: soplex.h:900
virtual Real time() const =0
Representation
LP basis representation.
Definition: spxsolver.h:105
virtual ~SoPlex()
destructor
Definition: soplex.cpp:729
LP geometric mean scaling.
primal feasibility tolerance
Definition: soplex.h:1145
int numRowsReal() const
message handler
Definition: soplex.cpp:770
virtual ~Timer()
Definition: timer.h:124
Abstract ratio test base class.
solve() aborted due to iteration limit.
Definition: spxsolver.h:199
#define SOPLEX_VERSION
Definition: spxdefines.h:42
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...
Definition: soplex.cpp:4516
static Real epsilonUpdate()
Definition: spxdefines.h:269
mode for reading LP files
Definition: soplex.h:897
mode for synchronizing real and rational LP
Definition: soplex.h:894
automatic sync of real and rational LP
Definition: soplex.h:1073
iteration limit (-1 if unlimited)
Definition: soplex.h:864
Implementation of Sparse Linear Solver.
Abstract ratio test base class.Class SPxRatioTester is the virtual base class for computing the ratio...
bool getRowViolationReal(Real &maxviol, Real &sumviol)
gets violation of constraints; returns true on success
Definition: soplex.cpp:2992
bool getRowViolationRational(Rational &maxviol, Rational &sumviol)
gets violation of constraints; returns true on success
Definition: soplex.cpp:3306
static Real epsilonFactorization()
Definition: spxdefines.h:262
SoPlex start basis generation base class.SPxStarter is the virtual base class for classes generating ...
Definition: spxstarter.h:41
int numColsRational() const
returns number of columns
Definition: soplex.cpp:1021
#define DEFAULT_EPS_UPDATE
Definition: spxdefines.h:218
LP has been proven to be primal infeasible.
Definition: spxsolver.h:208
Dantzig pricer.
General methods in LP preprocessing.
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
Definition: soplex.cpp:4475
bool setIntParam(const IntParam param, const int value, const bool quiet=false, const bool init=false)
sets integer parameter value; returns true on success
Definition: soplex.cpp:4939
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:45
static void disableListMem()
disables list memory
Definition: rational.cpp:3083
Devex pricer.
void printStatistics(std::ostream &os)
prints complete statistics
Definition: soplex.cpp:5916
rowwise representation.
Definition: spxsolver.h:107
TimerFactory class.
LP simplification base class.
Real realParam(const RealParam param) const
returns real parameter value
Definition: soplex.cpp:4866
Partial multiple pricing.Class SPxParMultPr is an implementation class for SPxPricer implementing Dan...
Definition: spxparmultpr.h:47
Wrapper for different output streams and verbosity levels.
Steepest edge pricer.
virtual void start()=0
start timer, resume accounting user, system and real time.
Entering Simplex.
Definition: spxsolver.h:134
virtual Real stop()=0
stop timer, return accounted user time.
void spx_alloc(T &p, int n=1)
Allocate memory.
Definition: spxalloc.h:48
#define EGlpNumClear()
Definition: soplexmain.cpp:38
Fast shifting ratio test.Class SPxFastRT is an implementation class of SPxRatioTester providing fast ...
Definition: spxfastrt.h:41
Leaving Simplex.
Definition: spxsolver.h:143
standard floating-point parsing
Definition: soplex.h:1083
type of scaler
Definition: soplex.h:882
double Real
SOPLEX_DEBUG.
Definition: spxdefines.h:200
Weighted pricing.Class SPxWeightPR is an implemantation class of SPxPricer that uses weights for colu...
Definition: spxweightpr.h:41
int main(int argc, char *argv[])
runs SoPlex command line
Definition: soplexmain.cpp:253
virtual const char * getName() const
get name of starter.
Definition: spxstarter.h:88
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...
Definition: soplex.cpp:4707
static void printUsage(const char *const argv[], int idx)
Definition: soplexmain.cpp:45
bool setRealParam(const RealParam param, const Real value, const bool quiet=false, const bool init=false)
sets real parameter value; returns true on success
Definition: soplex.cpp:5245
LP simplification abstract base class.Instances of classes derived from SPxSimplifier may be loaded t...
Definition: spxsimplifier.h:41
LP has been solved to optimality.
Definition: spxsolver.h:206
std::ostream & getStream(const Verbosity &verbosity) const
Returns the stream for the specified verbosity level.
Definition: spxout.h:156
int numRowsRational() const
returns number of rows
Definition: soplex.cpp:1012
bool getDualViolationReal(Real &maxviol, Real &sumviol)
gets violation of dual multipliers; returns true on success
Definition: soplex.cpp:3085
Wrapper for several output streams. A verbosity level is used to decide which stream to use and wheth...
Definition: spxout.h:63
solve() aborted due to time limit.
Definition: spxsolver.h:198
main LP solver class
an error occured.
Definition: spxsolver.h:192
#define DEFAULT_EPS_ZERO
default allowed additive zero: 1.0 + EPS_ZERO == 1.0
Definition: spxdefines.h:212
virtual void setVerbosity(const Verbosity &v)
Definition: spxout.h:111
virtual Real time() const
Definition: usertimer.cpp:100
type of simplifier
Definition: soplex.h:879
void printUserSettings()
print non-default parameter values
Definition: soplex.cpp:5415
static void checkSolutionRational(SoPlex &soplex)
performs external feasibility check with rational type
Definition: soplexmain.cpp:183
#define MSG_ERROR(x)
Prints out message x if the verbosity level is at least SPxOut::ERROR.
Definition: spxdefines.h:109
Abstract pricer base class.Class SPxPricer is a pure virtual class defining the interface for pricer ...
Definition: spxpricer.h:46
bool getPrimalRational(VectorRational &vector)
gets the primal solution vector if available; returns true on success
Definition: soplex.cpp:3175
Solution vector based start basis.This version of SPxWeightST can be used to construct a starting bas...
Definition: spxvectorst.h:44
virtual Real stop()
stop timer, return accounted user time.
Definition: usertimer.cpp:86
#define MSG_INFO1(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::INFO1.
Definition: spxdefines.h:113
Simple heuristic SPxStarter.
user sync of real and rational LP
Definition: soplex.h:1076
virtual const char * getName() const
get name of ratio tester.
bool parseSettingsString(char *line)
parses one setting string and returns true on success; note that string is modified ...
Definition: soplex.cpp:5581
SPxOut spxout
Definition: soplex.h:1215
virtual void start()
start timer, resume accounting user, system and real time.
Definition: usertimer.cpp:72
static Timer * createTimer(Timer::TYPE ttype)
create timers and allocate memory for them
Definition: timerfactory.h:43
(In)equality for LPs.Class LPRowBase provides constraints for linear programs in the form where a is...
Definition: lprowbase.h:45
Preconfigured SoPlex LP solver.
Bound flipping ratio test (long step dual) for SoPlex.
Debugging, floating point type and parameter definitions.
Set of strings.Class NameSet implements a symbol or name table. It allows to store or remove names (i...
Definition: nameset.h:61
Hybrid pricer.The hybrid pricer for SoPlex tries to guess the best pricing strategy to use for pricin...
Definition: spxhybridpr.h:43
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.
Timer class.
returns the current git hash of SoPlex
bool loadSettingsFile(const char *filename)
reads settings file; returns true on success
Definition: soplex.cpp:5532
Dantzig pricer.Class SPxDantzigPR is an implementation class of an SPxPricer implementing Dantzig&#39;s d...
Definition: spxdantzigpr.h:38
bool getRedCostViolationRational(Rational &maxviol, Rational &sumviol)
gets violation of reduced costs; returns true on success
Definition: soplex.cpp:3349
Harris pricing with shifting.
solve() aborted due to detection of cycling.
Definition: spxsolver.h:197
Weighted start basis.
type of pricer
Definition: soplex.h:888
bool getDualReal(VectorReal &vector)
gets the dual solution vector if available; returns true on success
Definition: soplex.cpp:2910
static void checkSolution(SoPlex &soplex)
performs external feasibility check according to check mode
Definition: soplexmain.cpp:236
Steepest edge pricer with exact initialization of weights.
Preconfigured SoPlex LP-solver.
Definition: soplex.h:86
#define MSG_WARNING(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::WARNING.
Definition: spxdefines.h:111
bool writeFileReal(const char *filename, const NameSet *rowNames=0, const NameSet *colNames=0, const DIdxSet *intvars=0) const
writes real LP to file; LP or MPS format is chosen from the extension in filename; if rowNames and co...
Definition: soplex.cpp:4486
LP scaling base class.
static void setEpsilonUpdate(Real eps)
Definition: spxdefines.cpp:55
bool getBoundViolationReal(Real &maxviol, Real &sumviol)
gets violation of bounds; returns true on success
Definition: soplex.cpp:2955
Simple heuristic SPxStarter.Testing version of an SPxVectorST using a very simplistic heuristic to bu...
Definition: spxsumst.h:37
Weighted start basis.Class SPxWeightST is an implementation of a SPxStarter for generating a Simplex ...
Definition: spxweightst.h:56
decide according to READMODE
Definition: soplex.h:1109
void printVersion() const
prints version and compilation options
Definition: soplex.cpp:6002
const char * getGitHash()
Definition: spxgithash.cpp:23
mode for a posteriori feasibility checks
Definition: soplex.h:903
Partial multiple pricing.
Verbosity
Verbosity level.
Definition: spxout.h:72
Textbook ratio test for SoPlex.Class SPxDefaultRT provides an implementation of the textbook ratio te...
Definition: spxdefaultrt.h:42
void clear()
Set vector to 0.
Definition: vectorbase.h:219
virtual const char * getName() const
get name of simplifier.
LP scaler abstract base class.Instances of classes derived from SPxScaler may be loaded to SoPlex in ...
Definition: spxscaler.h:39
std::streamsize precision() const
Definition: spxout.h:138
int intParam(const IntParam param) const
returns integer parameter value
Definition: soplex.cpp:4856
const Real infinity
Definition: spxdefines.cpp:26
bool saveSettingsFile(const char *filename, const bool onlyChanged=false) const
writes settings file; returns true on success
Definition: soplex.cpp:5463
bool getRedCostViolationReal(Real &maxviol, Real &sumviol)
gets violation of reduced costs; returns true on success
Definition: soplex.cpp:3031
#define SOPLEX_SUBVERSION
Definition: spxdefines.h:43
static void freeStrings(char *&s1, char *&s2, char *&s3, char *&s4, char *&s5)
Definition: soplexmain.cpp:97
static void setEpsilonFactorization(Real eps)
Definition: spxdefines.cpp:50
dual feasibility tolerance
Definition: soplex.h:1148
Hybrid pricer.
static void checkSolutionReal(SoPlex &soplex)
performs external feasibility check with real type
Definition: soplexmain.cpp:129
std::string rationalToString(const Rational &r, const int precision)
convert rational number to string
Definition: rational.cpp:3468
Textbook ratio test for SoPlex.
int numNonzerosReal() const
returns number of nonzeros
Definition: soplex.cpp:788
LP euilibrium scaling.
virtual const char * getName() const
get name of scaler.
Definition: spxscaler.cpp:97
Equilibrium row/column scaling.This SPxScaler implementation performs equilibrium scaling of the LPs ...
Definition: spxequilisc.h:35
static Real epsilon()
Definition: spxdefines.h:255
Wrapper for the system time query methods.
Definition: timer.h:76
bool hasPrimal() const
is a primal feasible solution available?
Definition: soplex.cpp:2807
Weighted pricing.
solve() aborted due to objective limit.
Definition: spxsolver.h:200
columnwise representation.
Definition: spxsolver.h:108
void spx_free(T &p)
Release memory.
Definition: spxalloc.h:109
Basis is singular, numerical troubles?
Definition: spxsolver.h:201
Steepest edge pricer.Class SPxSteepPR implements a steepest edge pricer to be used with SoPlex...
Definition: spxsteeppr.h:41
Harris pricing with shifting.Class SPxHarrisRT is a stable implementation of a SPxRatioTester class a...
Definition: spxharrisrt.h:40
bool getBoundViolationRational(Rational &maxviol, Rational &sumviol)
gets violation of bounds; returns true on success
Definition: soplex.cpp:3265
LP simplifier for removing uneccessary row/columns.This SPxSimplifier is mainly based on the paper "P...
Definition: spxmainsm.h:60
LP has been proven to be primal unbounded.
Definition: spxsolver.h:207