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