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-2018 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SoPlex is distributed under the terms of the ZIB Academic Licence. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SoPlex; see the file COPYING. If not email to soplex@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file soplexmain.cpp
17  * @brief Command line interface of SoPlex LP solver
18  */
19 
20 #include <assert.h>
21 #include <math.h>
22 #include <string.h>
23 
24 #include <iostream>
25 #include <iomanip>
26 #include <fstream>
27 
28 #include "soplex.h"
29 #include "soplex/validation.h"
30 
31 #ifdef SOPLEX_WITH_EGLIB
32 extern "C" {
33 #include "soplex/EGlib.h"
34 }
35 #else
36 #define EGlpNumStart() {}
37 #define EGlpNumClear() {}
38 #endif
39 
40 using namespace soplex;
41 
42 // function prototype
43 int main(int argc, char* argv[]);
44 
45 // prints usage and command line options
46 static
47 void printUsage(const char* const argv[], int idx)
48 {
49  const char* usage =
50  "general options:\n"
51  " --readbas=<basfile> read starting basis from file\n"
52  " --writebas=<basfile> write terminal basis to file\n"
53  " --writefile=<lpfile> write LP to file in LP or MPS format depending on extension\n"
54  " --writedual=<lpfile> write the dual LP to a file in LP or MPS formal depending on extension\n"
55  " --<type>:<name>=<val> change parameter value using syntax of settings file entries\n"
56  " --loadset=<setfile> load parameters from settings file (overruled by command line parameters)\n"
57  " --saveset=<setfile> save parameters to settings file\n"
58  " --diffset=<setfile> save modified parameters to settings file\n"
59  " --extsol=<value> external solution for soplex to use for validation\n"
60  "\n"
61  "limits and tolerances:\n"
62  " -t<s> set time limit to <s> seconds\n"
63  " -i<n> set iteration limit to <n>\n"
64  " -f<eps> set primal feasibility tolerance to <eps>\n"
65  " -o<eps> set dual feasibility (optimality) tolerance to <eps>\n"
66  " -l<eps> set validation 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, 6 - geometric-equilibrium)\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 static
262 void printPrimalSolution(SoPlex& soplex, NameSet& colnames, NameSet& rownames, bool real = true, bool rational = false)
263 {
264  int printprec;
265  int printwidth;
266  printprec = (int) -log10(double(Param::epsilon()));
267  printwidth = printprec + 10;
268 
269  if( real )
270  {
271  DVector primal(soplex.numColsReal());
272  if( soplex.getPrimalRayReal(primal) )
273  {
274  MSG_INFO1( soplex.spxout, soplex.spxout << "\nPrimal ray (name, value):\n"; )
275  for( int i = 0; i < soplex.numColsReal(); ++i )
276  {
277  if ( isNotZero( primal[i] ) )
278  {
279  MSG_INFO1( soplex.spxout, soplex.spxout << colnames[i] << "\t"
280  << std::setw(printwidth) << std::setprecision(printprec)
281  << primal[i] << std::endl; )
282  }
283  }
284  MSG_INFO1( soplex.spxout, soplex.spxout << "All other entries are zero (within "
285  << std::setprecision(1) << std::scientific << Param::epsilon()
286  << std::setprecision(8) << std::fixed
287  << ")." << std::endl; )
288  }
289  else if( soplex.isPrimalFeasible() && soplex.getPrimalReal(primal) )
290  {
291  int nNonzeros = 0;
292  MSG_INFO1( soplex.spxout, soplex.spxout << "\nPrimal solution (name, value):\n"; )
293  for( int i = 0; i < soplex.numColsReal(); ++i )
294  {
295  if ( isNotZero( primal[i] ) )
296  {
297  MSG_INFO1( soplex.spxout, soplex.spxout << colnames[i] << "\t"
298  << std::setw(printwidth) << std::setprecision(printprec)
299  << primal[i] << std::endl; )
300  ++nNonzeros;
301  }
302  }
303  MSG_INFO1( soplex.spxout, soplex.spxout << "All other variables are zero (within "
304  << std::setprecision(1) << std::scientific << Param::epsilon()
305  << std::setprecision(8) << std::fixed
306  << "). Solution has " << nNonzeros << " nonzero entries." << std::endl; )
307  }
308  else
309  MSG_INFO1( soplex.spxout, soplex.spxout << "No primal information available.\n")
310  }
311  if( rational )
312  {
313  DVectorRational primal(soplex.numColsReal());
314 
315  if( soplex.getPrimalRayRational(primal) )
316  {
317  MSG_INFO1( soplex.spxout, soplex.spxout << "\nPrimal ray (name, value):\n"; )
318  for( int i = 0; i < soplex.numColsReal(); ++i )
319  {
320  if( primal[i] != (Rational) 0 )
321  {
322  MSG_INFO1( soplex.spxout, soplex.spxout << colnames[i] << "\t"
323  << std::setw(printwidth) << std::setprecision(printprec)
324  << primal[i] << std::endl; )
325  }
326  }
327  MSG_INFO1( soplex.spxout, soplex.spxout << "All other entries are zero." << std::endl; )
328  }
329 
330  if( soplex.isPrimalFeasible() && soplex.getPrimalRational(primal) )
331  {
332  int nNonzeros = 0;
333  MSG_INFO1( soplex.spxout, soplex.spxout << "\nPrimal solution (name, value):\n"; )
334  for( int i = 0; i < soplex.numColsRational(); ++i )
335  {
336  if ( primal[i] != (Rational) 0 )
337  {
338  MSG_INFO1( soplex.spxout, soplex.spxout << colnames[i] << "\t" << primal[i] << std::endl; )
339  ++nNonzeros;
340  }
341  }
342  MSG_INFO1( soplex.spxout, soplex.spxout << "All other variables are zero. Solution has "
343  << nNonzeros << " nonzero entries." << std::endl; )
344  }
345  else
346  MSG_INFO1( soplex.spxout, soplex.spxout << "No primal (rational) solution available.\n")
347 
348  }
349 }
350 
351 static
352 void printDualSolution(SoPlex& soplex, NameSet& colnames, NameSet& rownames, bool real = true, bool rational = false)
353 {
354  int printprec;
355  int printwidth;
356  printprec = (int) -log10(double(Param::epsilon()));
357  printwidth = printprec + 10;
358 
359  if( real )
360  {
361  DVector dual(soplex.numRowsReal());
362  if( soplex.getDualFarkasReal(dual) )
363  {
364  MSG_INFO1( soplex.spxout, soplex.spxout << "\nDual ray (name, value):\n"; )
365  for( int i = 0; i < soplex.numRowsReal(); ++i )
366  {
367  if ( isNotZero( dual[i] ) )
368  {
369  MSG_INFO1( soplex.spxout, soplex.spxout << rownames[i] << "\t"
370  << std::setw(printwidth) << std::setprecision(printprec)
371  << dual[i] << std::endl; )
372  }
373  }
374  MSG_INFO1( soplex.spxout, soplex.spxout << "All other entries are zero (within "
375  << std::setprecision(1) << std::scientific << Param::epsilon()
376  << std::setprecision(8) << std::fixed << ")." << std::endl; )
377  }
378  else if( soplex.isDualFeasible() && soplex.getDualReal(dual) )
379  {
380  MSG_INFO1( soplex.spxout, soplex.spxout << "\nDual solution (name, value):\n"; )
381  for( int i = 0; i < soplex.numRowsReal(); ++i )
382  {
383  if ( isNotZero( dual[i] ) )
384  {
385  MSG_INFO1( soplex.spxout, soplex.spxout << rownames[i] << "\t"
386  << std::setw(printwidth) << std::setprecision(printprec)
387  << dual[i] << std::endl; )
388  }
389  }
390  MSG_INFO1( soplex.spxout, soplex.spxout << "All other dual values are zero (within "
391  << std::setprecision(1) << std::scientific << Param::epsilon()
392  << std::setprecision(8) << std::fixed << ")." << std::endl; )
393 
394  DVector redcost(soplex.numColsReal());
395  if( soplex.getRedCostReal(redcost) )
396  {
397  MSG_INFO1( soplex.spxout, soplex.spxout << "\nReduced costs (name, value):\n"; )
398  for( int i = 0; i < soplex.numColsReal(); ++i )
399  {
400  if ( isNotZero( redcost[i] ) )
401  {
402  MSG_INFO1( soplex.spxout, soplex.spxout << colnames[i] << "\t"
403  << std::setw(printwidth) << std::setprecision(printprec)
404  << redcost[i] << std::endl; )
405  }
406  }
407  MSG_INFO1( soplex.spxout, soplex.spxout << "All other reduced costs are zero (within "
408  << std::setprecision(1) << std::scientific << Param::epsilon()
409  << std::setprecision(8) << std::fixed << ")." << std::endl; )
410  }
411  }
412  else
413  MSG_INFO1( soplex.spxout, soplex.spxout << "No dual information available.\n")
414  }
415 
416  if( rational )
417  {
418  DVectorRational dual(soplex.numRowsReal());
419  if( soplex.getDualFarkasRational(dual) )
420  {
421  MSG_INFO1( soplex.spxout, soplex.spxout << "\nDual ray (name, value):\n"; )
422  for( int i = 0; i < soplex.numRowsReal(); ++i )
423  {
424  if( dual[i] != (Rational) 0 )
425  {
426  MSG_INFO1( soplex.spxout, soplex.spxout << rownames[i] << "\t"
427  << std::setw(printwidth)
428  << std::setprecision(printprec)
429  << dual[i] << std::endl; )
430  }
431  }
432  MSG_INFO1( soplex.spxout, soplex.spxout << "All other entries are zero." << std::endl; )
433  }
434  if( soplex.isDualFeasible() && soplex.getDualRational(dual) )
435  {
436  MSG_INFO1( soplex.spxout, soplex.spxout << "\nDual solution (name, value):\n"; )
437  for( int i = 0; i < soplex.numRowsRational(); ++i )
438  {
439  if ( dual[i] != (Rational) 0 )
440  MSG_INFO1( soplex.spxout, soplex.spxout << rownames[i] << "\t" << dual[i] << std::endl; )
441  }
442  MSG_INFO1( soplex.spxout, soplex.spxout << "All other dual values are zero." << std::endl; )
443 
444  DVectorRational redcost(soplex.numColsReal());
445  if( soplex.getRedCostRational(redcost) )
446  {
447  MSG_INFO1( soplex.spxout, soplex.spxout << "\nReduced costs (name, value):\n"; )
448  for( int i = 0; i < soplex.numColsReal(); ++i )
449  {
450  if ( redcost[i] != (Rational) 0 )
451  MSG_INFO1( soplex.spxout, soplex.spxout << colnames[i] << "\t" << redcost[i] << std::endl; )
452  }
453  MSG_INFO1( soplex.spxout, soplex.spxout << "All other reduced costs are zero." << std::endl; )
454  }
455  }
456  else
457  MSG_INFO1( soplex.spxout, soplex.spxout << "No dual (rational) solution available.\n")
458  }
459 }
460 
461 
462 
463 /// runs SoPlex command line
464 int main(int argc, char* argv[])
465 {
466  ///@todo the EGlib version info should be printed after the SoPlex version info
467  // initialize EGlib's GMP memory management before any rational numbers are created
468  EGlpNumStart();
469 
470  SoPlex* soplex = 0;
471 
472  Timer* readingTime = 0;
473  Validation* validation = 0;
474  int optidx;
475 
476  const char* lpfilename = 0;
477  char* readbasname = 0;
478  char* writebasname = 0;
479  char* writefilename = 0;
480  char* writedualfilename = 0;
481  char* loadsetname = 0;
482  char* savesetname = 0;
483  char* diffsetname = 0;
484  bool printPrimal = false;
485  bool printPrimalRational = false;
486  bool printDual = false;
487  bool printDualRational = false;
488  bool displayStatistics = false;
489  bool checkSol = false;
490 
491  int returnValue = 0;
492 
493  try
494  {
495  NameSet rownames;
496  NameSet colnames;
497 
498  // create default timer (CPU time)
500  soplex = 0;
501  spx_alloc(soplex);
502  new (soplex) SoPlex();
503 
504  soplex->printVersion();
505  MSG_INFO1( soplex->spxout, soplex->spxout << SOPLEX_COPYRIGHT << std::endl << std::endl );
506 
507  validation = 0;
508  spx_alloc(validation);
509  new (validation) Validation();
510 
511  // no options were given
512  if( argc <= 1 )
513  {
514  printUsage(argv, 0);
515  returnValue = 1;
516  goto TERMINATE;
517  }
518 
519  // read arguments from command line
520  for( optidx = 1; optidx < argc; optidx++ )
521  {
522  char* option = argv[optidx];
523 
524  // we reached <lpfile>
525  if( option[0] != '-' )
526  {
527  lpfilename = argv[optidx];
528  continue;
529  }
530 
531  // option string must start with '-', must contain at least two characters, and exactly two characters if and
532  // only if it is -x, -y, -q, or -c
533  if( option[0] != '-' || option[1] == '\0'
534  || ((option[2] == '\0') != (option[1] == 'x' || option[1] == 'X' || option[1] == 'y' || option[1] == 'Y' || option[1] == 'q' || option[1] == 'c')) )
535  {
536  printUsage(argv, optidx);
537  returnValue = 1;
538  goto TERMINATE_FREESTRINGS;
539  }
540 
541  switch( option[1] )
542  {
543  case '-' :
544  {
545  option = &option[2];
546 
547  // --readbas=<basfile> : read starting basis from file
548  if( strncmp(option, "readbas=", 8) == 0 )
549  {
550  if( readbasname == 0 )
551  {
552  char* filename = &option[8];
553  readbasname = new char[strlen(filename) + 1];
554  spxSnprintf(readbasname, strlen(filename) + 1, "%s", filename);
555  }
556  }
557  // --writebas=<basfile> : write terminal basis to file
558  else if( strncmp(option, "writebas=", 9) == 0 )
559  {
560  if( writebasname == 0 )
561  {
562  char* filename = &option[9];
563  writebasname = new char[strlen(filename) + 1];
564  spxSnprintf(writebasname, strlen(filename) + 1, "%s", filename);
565  }
566  }
567  // --writefile=<lpfile> : write LP to file
568  else if( strncmp(option, "writefile=", 10) == 0 )
569  {
570  if( writefilename == 0 )
571  {
572  char* filename = &option[10];
573  writefilename = new char[strlen(filename) + 1];
574  spxSnprintf(writefilename, strlen(filename) + 1, "%s", filename);
575  }
576  }
577  // --writedual=<lpfile> : write dual LP to a file
578  else if( strncmp(option, "writedual=", 10) == 0 )
579  {
580  if( writedualfilename == 0 )
581  {
582  char* dualfilename = &option[10];
583  writedualfilename = new char[strlen(dualfilename) + 1];
584  spxSnprintf(writedualfilename, strlen(dualfilename) + 1, "%s", dualfilename);
585  }
586  }
587  // --loadset=<setfile> : load parameters from settings file
588  else if( strncmp(option, "loadset=", 8) == 0 )
589  {
590  if( loadsetname == 0 )
591  {
592  char* filename = &option[8];
593  loadsetname = new char[strlen(filename) + 1];
594  spxSnprintf(loadsetname, strlen(filename) + 1, "%s", filename);
595  if( !soplex->loadSettingsFile(loadsetname) )
596  {
597  printUsage(argv, optidx);
598  returnValue = 1;
599  goto TERMINATE_FREESTRINGS;
600  }
601  else
602  {
603  // we need to start parsing again because some command line parameters might have been overwritten
604  optidx = 0;
605  }
606  }
607  }
608  // --saveset=<setfile> : save parameters to settings file
609  else if( strncmp(option, "saveset=", 8) == 0 )
610  {
611  if( savesetname == 0 )
612  {
613  char* filename = &option[8];
614  savesetname = new char[strlen(filename) + 1];
615  spxSnprintf(savesetname, strlen(filename) + 1, "%s", filename);
616  }
617  }
618  // --diffset=<setfile> : save modified parameters to settings file
619  else if( strncmp(option, "diffset=", 8) == 0 )
620  {
621  if( diffsetname == 0 )
622  {
623  char* filename = &option[8];
624  diffsetname = new char[strlen(filename) + 1];
625  spxSnprintf(diffsetname, strlen(filename) + 1, "%s", filename);
626  }
627  }
628  // --readmode=<value> : choose reading mode for <lpfile> (0* - floating-point, 1 - rational)
629  else if( strncmp(option, "readmode=", 9) == 0 )
630  {
631  if( !soplex->setIntParam(SoPlex::READMODE, option[9] - '0') )
632  {
633  printUsage(argv, optidx);
634  returnValue = 1;
635  goto TERMINATE_FREESTRINGS;
636  }
637  }
638  // --solvemode=<value> : choose solving mode (0* - floating-point solve, 1 - auto, 2 - force iterative refinement)
639  else if( strncmp(option, "solvemode=", 10) == 0 )
640  {
641  if( !soplex->setIntParam(SoPlex::SOLVEMODE, option[10] - '0') )
642  {
643  printUsage(argv, optidx);
644  returnValue = 1;
645  goto TERMINATE_FREESTRINGS;
646  }
647  // if the LP is parsed rationally and might be solved rationally, we choose automatic syncmode such that
648  // the rational LP is kept after reading
651  {
653  }
654  }
655  // --extsol=<value> : external solution for soplex to use for validation
656  else if( strncmp(option, "extsol=", 7) == 0 )
657  {
658  char* input = &option[7];
659  if( !validation->updateExternalSolution(input) )
660  {
661  printUsage(argv, optidx);
662  returnValue = 1;
663  goto TERMINATE_FREESTRINGS;
664  }
665  }
666  // --<type>:<name>=<val> : change parameter value using syntax of settings file entries
667  else if( !soplex->parseSettingsString(option) )
668  {
669  printUsage(argv, optidx);
670  returnValue = 1;
671  goto TERMINATE_FREESTRINGS;
672  }
673  break;
674  }
675 
676  case 't' :
677  // -t<s> : set time limit to <s> seconds
678  if( !soplex->setRealParam(SoPlex::TIMELIMIT, atoi(&option[2])) )
679  {
680  printUsage(argv, optidx);
681  returnValue = 1;
682  goto TERMINATE_FREESTRINGS;
683  }
684  break;
685 
686  case 'i' :
687  // -i<n> : set iteration limit to <n>
688  if( !soplex->setIntParam(SoPlex::ITERLIMIT, atoi(&option[2])) )
689  {
690  printUsage(argv, optidx);
691  returnValue = 1;
692  goto TERMINATE_FREESTRINGS;
693  }
694  break;
695 
696  case 'f' :
697  // -f<eps> : set primal feasibility tolerance to <eps>
698  if( !soplex->setRealParam(SoPlex::FEASTOL, atof(&option[2])) )
699  {
700  printUsage(argv, optidx);
701  returnValue = 1;
702  goto TERMINATE_FREESTRINGS;
703  }
704  break;
705 
706  case 'o' :
707  // -o<eps> : set dual feasibility (optimality) tolerance to <eps>
708  if( !soplex->setRealParam(SoPlex::OPTTOL, atof(&option[2])) )
709  {
710  printUsage(argv, optidx);
711  returnValue = 1;
712  goto TERMINATE_FREESTRINGS;
713  }
714  break;
715 
716  case 'l' :
717  // l<eps> : set validation tolerance to <eps>
718  if( !validation->updateValidationTolerance(&option[2]) )
719  {
720  printUsage(argv, optidx);
721  returnValue = 1;
722  goto TERMINATE_FREESTRINGS;
723  }
724  break;
725 
726  case 's' :
727  // -s<value> : choose simplifier/presolver (0 - off, 1* - auto)
728  if( !soplex->setIntParam(SoPlex::SIMPLIFIER, option[2] - '0') )
729  {
730  printUsage(argv, optidx);
731  returnValue = 1;
732  goto TERMINATE_FREESTRINGS;
733  }
734  break;
735 
736  case 'g' :
737  // -g<value> : choose scaling (0 - off, 1 - uni-equilibrium, 2* - bi-equilibrium, 3 - geometric, 4 - iterated geometric, 5 - least squares, 6 - geometric-equilibrium)
738  if( !soplex->setIntParam(SoPlex::SCALER, option[2] - '0') )
739  {
740  printUsage(argv, optidx);
741  returnValue = 1;
742  goto TERMINATE_FREESTRINGS;
743  }
744  break;
745 
746  case 'p' :
747  // -p<value> : choose pricing (0* - auto, 1 - dantzig, 2 - parmult, 3 - devex, 4 - quicksteep, 5 - steep)
748  if( !soplex->setIntParam(SoPlex::PRICER, option[2] - '0') )
749  {
750  printUsage(argv, optidx);
751  returnValue = 1;
752  goto TERMINATE_FREESTRINGS;
753  }
754  break;
755 
756  case 'r' :
757  // -r<value> : choose ratio tester (0 - textbook, 1 - harris, 2* - fast, 3 - boundflipping)
758  if( !soplex->setIntParam(SoPlex::RATIOTESTER, option[2] - '0') )
759  {
760  printUsage(argv, optidx);
761  returnValue = 1;
762  goto TERMINATE_FREESTRINGS;
763  }
764  break;
765 
766  case 'v' :
767  // -v<level> : set verbosity to <level> (0 - error, 3 - normal, 5 - high)
768  if( !soplex->setIntParam(SoPlex::VERBOSITY, option[2] - '0') )
769  {
770  printUsage(argv, optidx);
771  returnValue = 1;
772  goto TERMINATE_FREESTRINGS;
773  }
774  break;
775 
776  case 'x' :
777  // -x : print primal solution
778  printPrimal = true;
779  break;
780 
781  case 'X' :
782  // -X : print primal solution with rationals
783  printPrimalRational = true;
784  break;
785 
786  case 'y' :
787  // -y : print dual multipliers
788  printDual = true;
789  break;
790 
791  case 'Y' :
792  // -Y : print dual multipliers with rationals
793  printDualRational = true;
794  break;
795 
796  case 'q' :
797  // -q : display detailed statistics
798  displayStatistics = true;
799  break;
800 
801  case 'c' :
802  // -c : perform final check of optimal solution in original problem
803  checkSol = true;
804  break;
805 
806  case 'h' :
807  // -h : display all parameters
808  if( !soplex->saveSettingsFile(0, false) )
809  {
810  MSG_ERROR( std::cerr << "Error printing parameters\n" );
811  }
812  break;
813 
814  //lint -fallthrough
815  default :
816  {
817  printUsage(argv, optidx);
818  returnValue = 1;
819  goto TERMINATE_FREESTRINGS;
820  }
821  }
822  }
823 
824  MSG_INFO1( soplex->spxout, soplex->printUserSettings(); )
825 
826  // no LP file was given and no settings files are written
827  if( lpfilename == 0 && savesetname == 0 && diffsetname == 0 )
828  {
829  printUsage(argv, 0);
830  returnValue = 1;
831  goto TERMINATE_FREESTRINGS;
832  }
833 
834  // ensure that syncmode is not manual
836  {
837  MSG_ERROR( std::cerr << "Error: manual synchronization is invalid on command line. Change parameter int:syncmode.\n" );
838  returnValue = 1;
839  goto TERMINATE_FREESTRINGS;
840  }
841 
842  // save settings files
843  if( savesetname != 0 )
844  {
845  MSG_INFO1( soplex->spxout, soplex->spxout << "Saving parameters to settings file <" << savesetname << "> . . .\n" );
846  if( !soplex->saveSettingsFile(savesetname, false) )
847  {
848  MSG_ERROR( std::cerr << "Error writing parameters to file <" << savesetname << ">\n" );
849  }
850  }
851  if( diffsetname != 0 )
852  {
853  MSG_INFO1( soplex->spxout, soplex->spxout << "Saving modified parameters to settings file <" << diffsetname << "> . . .\n" );
854  if( !soplex->saveSettingsFile(diffsetname, true) )
855  {
856  MSG_ERROR( std::cerr << "Error writing modified parameters to file <" << diffsetname << ">\n" );
857  }
858  }
859 
860  // no LP file given: exit after saving settings
861  if( lpfilename == 0 )
862  {
863  if( loadsetname != 0 || savesetname != 0 || diffsetname != 0 )
864  {
865  MSG_INFO1( soplex->spxout, soplex->spxout << "\n" );
866  }
867  goto TERMINATE_FREESTRINGS;
868  }
869 
870  // measure time for reading LP file and basis file
871  readingTime->start();
872 
873  // if the LP is parsed rationally and might be solved rationally, we choose automatic syncmode such that
874  // the rational LP is kept after reading
877  {
879  }
880 
881  // read LP from input file
882  MSG_INFO1( soplex->spxout, soplex->spxout << "Reading "
883  << (soplex->intParam(SoPlex::READMODE) == SoPlex::READMODE_REAL ? "(real)" : "(rational)")
884  << " LP file <" << lpfilename << "> . . .\n" );
885 
886  if( !soplex->readFile(lpfilename, &rownames, &colnames) )
887  {
888  MSG_ERROR( std::cerr << "Error while reading file <" << lpfilename << ">.\n" );
889  returnValue = 1;
890  goto TERMINATE_FREESTRINGS;
891  }
892 
893  // write LP if specified
894  if( writefilename != 0 )
895  {
896  if( !soplex->writeFileReal(writefilename, &rownames, &colnames) )
897  {
898  MSG_ERROR( std::cerr << "Error while writing file <" << writefilename << ">.\n\n" );
899  returnValue = 1;
900  goto TERMINATE_FREESTRINGS;
901  }
902  else
903  {
904  MSG_INFO1( soplex->spxout, soplex->spxout << "Written LP to file <" << writefilename << ">.\n\n" );
905  }
906  }
907 
908  // write dual LP if specified
909  if( writedualfilename != 0 )
910  {
911  if( !soplex->writeDualFileReal(writedualfilename, &rownames, &colnames) )
912  {
913  MSG_ERROR( std::cerr << "Error while writing dual file <" << writedualfilename << ">.\n\n" );
914  returnValue = 1;
915  goto TERMINATE_FREESTRINGS;
916  }
917  else
918  {
919  MSG_INFO1( soplex->spxout, soplex->spxout << "Written dual LP to file <" << writedualfilename << ">.\n\n" );
920  }
921  }
922 
923  // read basis file if specified
924  if( readbasname != 0 )
925  {
926  MSG_INFO1( soplex->spxout, soplex->spxout << "Reading basis file <" << readbasname << "> . . . " );
927  if( !soplex->readBasisFile(readbasname, &rownames, &colnames) )
928  {
929  MSG_ERROR( std::cerr << "Error while reading file <" << readbasname << ">.\n" );
930  returnValue = 1;
931  goto TERMINATE_FREESTRINGS;
932  }
933  }
934 
935  readingTime->stop();
936 
937  MSG_INFO1( soplex->spxout,
938  std::streamsize prec = soplex->spxout.precision();
939  soplex->spxout << "Reading took "
940  << std::fixed << std::setprecision(2) << readingTime->time()
941  << std::scientific << std::setprecision(int(prec))
942  << " seconds.\n\n" );
943 
944  MSG_INFO1( soplex->spxout, soplex->spxout << "LP has " << soplex->numRowsReal() << " rows "
945  << soplex->numColsReal() << " columns and " << soplex->numNonzerosReal() << " nonzeros.\n\n" );
946 
947  // solve the LP
948  soplex->optimize();
949 
950  // print solution, check solution, and display statistics
951  printPrimalSolution(*soplex, colnames, rownames, printPrimal, printPrimalRational);
952  printDualSolution(*soplex, colnames, rownames, printDual, printDualRational);
953 
954  if( checkSol )
955  checkSolution(*soplex);
956 
957  if( displayStatistics )
958  {
959  MSG_INFO1( soplex->spxout, soplex->spxout << "Statistics\n==========\n\n" );
960  soplex->printStatistics(soplex->spxout.getStream(SPxOut::INFO1));
961  }
962 
963  if(validation->validate)
964  validation->validateSolveReal(*soplex);
965 
966  // write basis file if specified
967  if( writebasname != 0 )
968  {
969  if( !soplex->hasBasis() )
970  {
971  MSG_WARNING( soplex->spxout, soplex->spxout << "No basis information available. Could not write file <" << writebasname << ">\n\n" );
972  }
973  else if( !soplex->writeBasisFile(writebasname, &rownames, &colnames) )
974  {
975  MSG_ERROR( std::cerr << "Error while writing file <" << writebasname << ">.\n\n" );
976  returnValue = 1;
977  goto TERMINATE_FREESTRINGS;
978  }
979  else
980  {
981  MSG_INFO1( soplex->spxout, soplex->spxout << "Written basis information to file <" << writebasname << ">.\n\n" );
982  }
983  }
984  }
985  catch( const SPxException& x )
986  {
987  MSG_ERROR( std::cerr << "Exception caught: " << x.what() << "\n" );
988  returnValue = 1;
989  goto TERMINATE_FREESTRINGS;
990  }
991 
992 TERMINATE_FREESTRINGS:
993  freeStrings(readbasname, writebasname, loadsetname, savesetname, diffsetname);
994 
995 TERMINATE:
996  // because EGlpNumClear() calls mpq_clear() for all mpq_t variables, we need to destroy all objects of class Rational
997  // beforehand; hence all Rational objects and all data that uses Rational objects must be allocated dynamically via
998  // spx_alloc() and freed here; disabling the list memory is crucial
999  if( 0 != soplex )
1000  {
1001  soplex->~SoPlex();
1002  spx_free(soplex);
1003  }
1004  if( 0 != validation )
1005  {
1006  validation->~Validation();
1007  spx_free(validation);
1008  }
1010  EGlpNumClear();
1011  if( 0 != readingTime )
1012  {
1013  readingTime->~Timer();
1014  spx_free(readingTime);
1015  }
1016 
1017  return returnValue;
1018 }
bool isNotZero(Real a, Real eps=Param::epsilon())
returns true iff |a| > eps
Definition: spxdefines.h:418
standard floating-point parsing
Definition: soplex.h:1212
void printVersion() const
prints version and compilation options
Definition: soplex.cpp:6877
bool getDualViolationRational(Rational &maxviol, Rational &sumviol)
gets violation of dual multipliers; returns true on success
Definition: soplex.cpp:3561
#define EGlpNumStart()
Definition: soplexmain.cpp:36
int numRowsReal() const
returns number of rows
Definition: soplex.cpp:800
type of ratio test
Definition: soplex.h:993
verbosity level
Definition: soplex.h:978
automatic sync of real and rational LP
Definition: soplex.h:1202
bool getPrimalReal(VectorReal &vector)
gets the primal solution vector if available; returns true on success
Definition: soplex.cpp:2976
int numRowsRational() const
returns number of rows
Definition: soplex.cpp:1092
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:5184
bool getDualRational(VectorRational &vector)
gets the dual solution vector if available; returns true on success
Definition: soplex.cpp:3331
time limit in seconds (INFTY if unlimited)
Definition: soplex.h:1308
mode for iterative refinement strategy
Definition: soplex.h:1002
virtual ~SoPlex()
destructor
Definition: soplex.cpp:759
bool getRedCostRational(VectorRational &vector)
gets the vector of reduced cost values if available; returns true on success
Definition: soplex.cpp:3346
primal feasibility tolerance
Definition: soplex.h:1287
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:5392
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:5199
mode for reading LP files
Definition: soplex.h:999
mode for synchronizing real and rational LP
Definition: soplex.h:996
bool getDualFarkasReal(VectorReal &vector)
gets the Farkas proof if available; returns true on success
Definition: soplex.cpp:3051
iteration limit (-1 if unlimited)
Definition: soplex.h:966
bool getRowViolationReal(Real &maxviol, Real &sumviol)
gets violation of constraints; returns true on success
Definition: soplex.cpp:3105
decide according to READMODE
Definition: soplex.h:1238
bool getRowViolationRational(Rational &maxviol, Rational &sumviol)
gets violation of constraints; returns true on success
Definition: soplex.cpp:3427
bool updateExternalSolution(char *solution)
updates the external solution used for validation
Definition: validation.cpp:25
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:5121
int intParam(const IntParam param) const
returns integer parameter value
Definition: soplex.cpp:5541
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:44
static void disableListMem()
disables list memory
Definition: rational.cpp:3066
void printStatistics(std::ostream &os)
prints complete statistics
Definition: soplex.cpp:6785
std::ostream & getStream(const Verbosity &verbosity) const
Returns the stream for the specified verbosity level.
Definition: spxout.h:157
user sync of real and rational LP
Definition: soplex.h:1205
virtual const std::string what() const
returns exception message
Definition: exceptions.h:57
bool isDualFeasible() const
is stored dual solution feasible?
Definition: soplex.cpp:2931
SPxSolver::Status optimize()
optimize the given LP
Definition: soplex.cpp:2804
virtual void start()=0
start timer, resume accounting user, system and real time.
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:37
bool isPrimalFeasible() const
is stored primal solution feasible?
Definition: soplex.cpp:2907
type of scaler
Definition: soplex.h:984
double Real
Definition: spxdefines.h:218
int main(int argc, char *argv[])
runs SoPlex command line
Definition: soplexmain.cpp:464
bool getPrimalRayReal(VectorReal &vector)
gets the primal ray if available; returns true on success
Definition: soplex.cpp:3006
bool hasPrimal() const
is a primal feasible solution available?
Definition: soplex.cpp:2915
static void printUsage(const char *const argv[], int idx)
Definition: soplexmain.cpp:47
void validateSolveReal(SoPlex &soplex)
validates the soplex solution using the external solution
Definition: validation.cpp:63
bool hasBasis() const
is an advanced starting basis available?
Definition: soplex.cpp:3851
#define MSG_ERROR(x)
Prints out message x if the verbosity level is at least SPxOut::ERROR.
Definition: spxdefines.h:114
bool getDualViolationReal(Real &maxviol, Real &sumviol)
gets violation of dual multipliers; returns true on success
Definition: soplex.cpp:3201
int spxSnprintf(char *t, size_t len, const char *s,...)
safe version of snprintf
Definition: spxdefines.h:460
type of simplifier
Definition: soplex.h:981
void printUserSettings()
print non-default parameter values
Definition: soplex.cpp:6222
static void checkSolutionRational(SoPlex &soplex)
performs external feasibility check with rational type
Definition: soplexmain.cpp:192
static void printPrimalSolution(SoPlex &soplex, NameSet &colnames, NameSet &rownames, bool real=true, bool rational=false)
Definition: soplexmain.cpp:262
int numColsRational() const
returns number of columns
Definition: soplex.cpp:1101
bool getPrimalRational(VectorRational &vector)
gets the primal solution vector if available; returns true on success
Definition: soplex.cpp:3286
bool getRedCostReal(VectorReal &vector)
gets the vector of reduced cost values if available; returns true on success
Definition: soplex.cpp:3036
Real realParam(const RealParam param) const
returns real parameter value
Definition: soplex.cpp:5551
virtual Real time() const =0
bool hasDual() const
is a dual feasible solution available?
Definition: soplex.cpp:2939
bool parseSettingsString(char *line)
parses one setting string and returns true on success; note that string is modified ...
Definition: soplex.cpp:6415
SPxOut spxout
Definition: soplex.h:1457
static Timer * createTimer(Timer::TYPE ttype)
create timers and allocate memory for them
Definition: timerfactory.h:44
static void printDualSolution(SoPlex &soplex, NameSet &colnames, NameSet &rownames, bool real=true, bool rational=false)
Definition: soplexmain.cpp:352
Preconfigured SoPlex LP solver.
apply standard floating-point algorithm
Definition: soplex.h:1222
static Real epsilon()
Definition: spxdefines.cpp:45
Set of strings.Class NameSet implements a symbol or name table. It allows to store or remove names (i...
Definition: nameset.h:61
bool validate
should the soplex solution be validated?
Definition: validation.h:32
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:5991
bool loadSettingsFile(const char *filename)
reads settings file; returns true on success
Definition: soplex.cpp:6366
int numNonzerosReal() const
returns number of nonzeros
Definition: soplex.cpp:818
bool getRedCostViolationRational(Rational &maxviol, Rational &sumviol)
gets violation of reduced costs; returns true on success
Definition: soplex.cpp:3480
type of pricer
Definition: soplex.h:990
bool getDualReal(VectorReal &vector)
gets the dual solution vector if available; returns true on success
Definition: soplex.cpp:3021
static void checkSolution(SoPlex &soplex)
performs external feasibility check according to check mode
Definition: soplexmain.cpp:245
Preconfigured SoPlex LP-solver.
Definition: soplex.h:89
#define MSG_WARNING(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::WARNING.
Definition: spxdefines.h:116
std::streamsize precision() const
Definition: spxout.h:139
bool getBoundViolationReal(Real &maxviol, Real &sumviol)
gets violation of bounds; returns true on success
Definition: soplex.cpp:3066
bool writeFileReal(const char *filename, const NameSet *rowNames=0, const NameSet *colNames=0, const DIdxSet *intvars=0, const bool unscale=true) const
writes real LP to file; LP or MPS format is chosen from the extension in filename; if rowNames and co...
Definition: soplex.cpp:5139
mode for a posteriori feasibility checks
Definition: soplex.h:1005
~Validation()
default destructor
Definition: validation.h:49
bool getDualFarkasRational(VectorRational &vector)
gets the Farkas proof if LP is infeasible; returns true on success
Definition: soplex.cpp:3361
#define MSG_INFO1(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::INFO1.
Definition: spxdefines.h:118
Validation object for soplex solutions.
bool getRedCostViolationReal(Real &maxviol, Real &sumviol)
gets violation of reduced costs; returns true on success
Definition: soplex.cpp:3147
static void freeStrings(char *&s1, char *&s2, char *&s3, char *&s4, char *&s5)
Definition: soplexmain.cpp:102
#define SOPLEX_COPYRIGHT
Definition: spxdefines.h:48
bool getPrimalRayRational(VectorRational &vector)
gets the primal ray if LP is unbounded; returns true on success
Definition: soplex.cpp:3316
dual feasibility tolerance
Definition: soplex.h:1290
bool setIntParam(const IntParam param, const int value, const bool init=true)
sets integer parameter value; returns true on success
Definition: soplex.cpp:5637
bool saveSettingsFile(const char *filename, const bool onlyChanged=false) const
writes settings file; returns true on success
Definition: soplex.cpp:6281
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:3451
bool updateValidationTolerance(char *tolerance)
updates the tolerance used for validation
Definition: validation.cpp:49
int numColsReal() const
returns number of columns
Definition: soplex.cpp:809
Wrapper for the system time query methods.
Definition: timer.h:76
void spx_free(T &p)
Release memory.
Definition: spxalloc.h:109
bool getBoundViolationRational(Rational &maxviol, Rational &sumviol)
gets violation of bounds; returns true on success
Definition: soplex.cpp:3376