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