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-2019 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 
110  if(s2 != 0)
111  {
112  delete [] s2;
113  s2 = 0;
114  }
115 
116  if(s3 != 0)
117  {
118  delete [] s3;
119  s3 = 0;
120  }
121 
122  if(s4 != 0)
123  {
124  delete [] s4;
125  s4 = 0;
126  }
127 
128  if(s5 != 0)
129  {
130  delete [] s5;
131  s5 = 0;
132  }
133 }
134 
135 /// performs external feasibility check with real type
136 ///@todo implement external check; currently we use the internal methods for convenience
137 static
139 {
140  if(soplex.hasPrimal())
141  {
142  Real boundviol;
143  Real rowviol;
144  Real sumviol;
145 
146  if(soplex.getBoundViolationReal(boundviol, sumviol) && soplex.getRowViolationReal(rowviol, sumviol))
147  {
148  MSG_INFO1(soplex.spxout,
149  Real maxviol = boundviol > rowviol ? boundviol : rowviol;
150  bool feasible = (maxviol <= soplex.realParam(SoPlex::FEASTOL));
151  soplex.spxout << "Primal solution " << (feasible ? "feasible" : "infeasible")
152  << " in original problem (max. violation = " << std::scientific << maxviol
153  << std::setprecision(8) << std::fixed << ").\n"
154  );
155  }
156  else
157  {
158  MSG_INFO1(soplex.spxout, soplex.spxout << "Could not check primal solution.\n");
159  }
160  }
161  else
162  {
163  MSG_INFO1(soplex.spxout, soplex.spxout << "No primal solution available.\n");
164  }
165 
166  if(soplex.hasDual())
167  {
168  Real redcostviol;
169  Real dualviol;
170  Real sumviol;
171 
172  if(soplex.getRedCostViolationReal(redcostviol, sumviol)
173  && soplex.getDualViolationReal(dualviol, sumviol))
174  {
175  MSG_INFO1(soplex.spxout,
176  Real maxviol = redcostviol > dualviol ? redcostviol : dualviol;
177  bool feasible = (maxviol <= soplex.realParam(SoPlex::OPTTOL));
178  soplex.spxout << "Dual solution " << (feasible ? "feasible" : "infeasible")
179  << " in original problem (max. violation = " << std::scientific << maxviol
180  << std::setprecision(8) << std::fixed << ").\n"
181  );
182  }
183  else
184  {
185  MSG_INFO1(soplex.spxout, soplex.spxout << "Could not check dual solution.\n");
186  }
187  }
188  else
189  {
190  MSG_INFO1(soplex.spxout, soplex.spxout << "No dual solution available.\n");
191  }
192 }
193 
194 /// performs external feasibility check with rational type
195 ///@todo implement external check; currently we use the internal methods for convenience
196 static
198 {
199  if(soplex.hasPrimal())
200  {
201  Rational boundviol;
202  Rational rowviol;
203  Rational sumviol;
204 
205  if(soplex.getBoundViolationRational(boundviol, sumviol)
206  && soplex.getRowViolationRational(rowviol, sumviol))
207  {
208  MSG_INFO1(soplex.spxout,
209  Rational maxviol = boundviol > rowviol ? boundviol : rowviol;
210  bool feasible = (maxviol <= soplex.realParam(SoPlex::FEASTOL));
211  soplex.spxout << "Primal solution " << (feasible ? "feasible" : "infeasible") <<
212  " in original problem (max. violation = " << rationalToString(maxviol) << ").\n"
213  );
214  }
215  else
216  {
217  MSG_INFO1(soplex.spxout, soplex.spxout << "Could not check primal solution.\n");
218  }
219  }
220  else
221  {
222  MSG_INFO1(soplex.spxout, soplex.spxout << "No primal solution available.\n");
223  }
224 
225  if(soplex.hasDual())
226  {
227  Rational redcostviol;
228  Rational dualviol;
229  Rational sumviol;
230 
231  if(soplex.getRedCostViolationRational(redcostviol, sumviol)
232  && soplex.getDualViolationRational(dualviol, sumviol))
233  {
234  MSG_INFO1(soplex.spxout,
235  Rational maxviol = redcostviol > dualviol ? redcostviol : dualviol;
236  bool feasible = (maxviol <= soplex.realParam(SoPlex::OPTTOL));
237  soplex.spxout << "Dual solution " << (feasible ? "feasible" : "infeasible") <<
238  " in original problem (max. violation = " << rationalToString(maxviol) << ").\n"
239  );
240  }
241  else
242  {
243  MSG_INFO1(soplex.spxout, soplex.spxout << "Could not check dual solution.\n");
244  }
245  }
246  else
247  {
248  MSG_INFO1(soplex.spxout, soplex.spxout << "No dual solution available.\n");
249  }
250 }
251 
252 /// performs external feasibility check according to check mode
253 static
255 {
259  {
260  checkSolutionRational(soplex);
261  }
262  else
263  {
264  checkSolutionReal(soplex);
265  }
266 
267  MSG_INFO1(soplex.spxout, soplex.spxout << "\n");
268 }
269 
270 static
271 void printPrimalSolution(SoPlex& soplex, NameSet& colnames, NameSet& rownames, bool real = true,
272  bool rational = false)
273 {
274  int printprec;
275  int printwidth;
276  printprec = (int) - log10(double(Param::epsilon()));
277  printwidth = printprec + 10;
278 
279  if(real)
280  {
281  DVector primal(soplex.numColsReal());
282 
283  if(soplex.getPrimalRayReal(primal))
284  {
285  MSG_INFO1(soplex.spxout, soplex.spxout << "\nPrimal ray (name, value):\n";)
286 
287  for(int i = 0; i < soplex.numColsReal(); ++i)
288  {
289  if(isNotZero(primal[i]))
290  {
291  MSG_INFO1(soplex.spxout, soplex.spxout << colnames[i] << "\t"
292  << std::setw(printwidth) << std::setprecision(printprec)
293  << primal[i] << std::endl;)
294  }
295  }
296 
297  MSG_INFO1(soplex.spxout, soplex.spxout << "All other entries are zero (within "
298  << std::setprecision(1) << std::scientific << Param::epsilon()
299  << std::setprecision(8) << std::fixed
300  << ")." << std::endl;)
301  }
302  else if(soplex.isPrimalFeasible() && soplex.getPrimalReal(primal))
303  {
304  int nNonzeros = 0;
305  MSG_INFO1(soplex.spxout, soplex.spxout << "\nPrimal solution (name, value):\n";)
306 
307  for(int i = 0; i < soplex.numColsReal(); ++i)
308  {
309  if(isNotZero(primal[i]))
310  {
311  MSG_INFO1(soplex.spxout, soplex.spxout << colnames[i] << "\t"
312  << std::setw(printwidth) << std::setprecision(printprec)
313  << primal[i] << std::endl;)
314  ++nNonzeros;
315  }
316  }
317 
318  MSG_INFO1(soplex.spxout, soplex.spxout << "All other variables are zero (within "
319  << std::setprecision(1) << std::scientific << Param::epsilon()
320  << std::setprecision(8) << std::fixed
321  << "). Solution has " << nNonzeros << " nonzero entries." << std::endl;)
322  }
323  else
324  MSG_INFO1(soplex.spxout, soplex.spxout << "No primal information available.\n")
325  }
326 
327  if(rational)
328  {
329  DVectorRational primal(soplex.numColsReal());
330 
331  if(soplex.getPrimalRayRational(primal))
332  {
333  MSG_INFO1(soplex.spxout, soplex.spxout << "\nPrimal ray (name, value):\n";)
334 
335  for(int i = 0; i < soplex.numColsReal(); ++i)
336  {
337  if(primal[i] != (Rational) 0)
338  {
339  MSG_INFO1(soplex.spxout, soplex.spxout << colnames[i] << "\t"
340  << std::setw(printwidth) << std::setprecision(printprec)
341  << primal[i] << std::endl;)
342  }
343  }
344 
345  MSG_INFO1(soplex.spxout, soplex.spxout << "All other entries are zero." << std::endl;)
346  }
347 
348  if(soplex.isPrimalFeasible() && soplex.getPrimalRational(primal))
349  {
350  int nNonzeros = 0;
351  MSG_INFO1(soplex.spxout, soplex.spxout << "\nPrimal solution (name, value):\n";)
352 
353  for(int i = 0; i < soplex.numColsRational(); ++i)
354  {
355  if(primal[i] != (Rational) 0)
356  {
357  MSG_INFO1(soplex.spxout, soplex.spxout << colnames[i] << "\t" << primal[i] << std::endl;)
358  ++nNonzeros;
359  }
360  }
361 
362  MSG_INFO1(soplex.spxout, soplex.spxout << "All other variables are zero. Solution has "
363  << nNonzeros << " nonzero entries." << std::endl;)
364  }
365  else
366  MSG_INFO1(soplex.spxout, soplex.spxout << "No primal (rational) solution available.\n")
367 
368  }
369 }
370 
371 static
372 void printDualSolution(SoPlex& soplex, NameSet& colnames, NameSet& rownames, bool real = true,
373  bool rational = false)
374 {
375  int printprec;
376  int printwidth;
377  printprec = (int) - log10(double(Param::epsilon()));
378  printwidth = printprec + 10;
379 
380  if(real)
381  {
382  DVector dual(soplex.numRowsReal());
383 
384  if(soplex.getDualFarkasReal(dual))
385  {
386  MSG_INFO1(soplex.spxout, soplex.spxout << "\nDual ray (name, value):\n";)
387 
388  for(int i = 0; i < soplex.numRowsReal(); ++i)
389  {
390  if(isNotZero(dual[i]))
391  {
392  MSG_INFO1(soplex.spxout, soplex.spxout << rownames[i] << "\t"
393  << std::setw(printwidth) << std::setprecision(printprec)
394  << dual[i] << std::endl;)
395  }
396  }
397 
398  MSG_INFO1(soplex.spxout, soplex.spxout << "All other entries are zero (within "
399  << std::setprecision(1) << std::scientific << Param::epsilon()
400  << std::setprecision(8) << std::fixed << ")." << std::endl;)
401  }
402  else if(soplex.isDualFeasible() && soplex.getDualReal(dual))
403  {
404  MSG_INFO1(soplex.spxout, soplex.spxout << "\nDual solution (name, value):\n";)
405 
406  for(int i = 0; i < soplex.numRowsReal(); ++i)
407  {
408  if(isNotZero(dual[i]))
409  {
410  MSG_INFO1(soplex.spxout, soplex.spxout << rownames[i] << "\t"
411  << std::setw(printwidth) << std::setprecision(printprec)
412  << dual[i] << std::endl;)
413  }
414  }
415 
416  MSG_INFO1(soplex.spxout, soplex.spxout << "All other dual values are zero (within "
417  << std::setprecision(1) << std::scientific << Param::epsilon()
418  << std::setprecision(8) << std::fixed << ")." << std::endl;)
419 
420  DVector redcost(soplex.numColsReal());
421 
422  if(soplex.getRedCostReal(redcost))
423  {
424  MSG_INFO1(soplex.spxout, soplex.spxout << "\nReduced costs (name, value):\n";)
425 
426  for(int i = 0; i < soplex.numColsReal(); ++i)
427  {
428  if(isNotZero(redcost[i]))
429  {
430  MSG_INFO1(soplex.spxout, soplex.spxout << colnames[i] << "\t"
431  << std::setw(printwidth) << std::setprecision(printprec)
432  << redcost[i] << std::endl;)
433  }
434  }
435 
436  MSG_INFO1(soplex.spxout, soplex.spxout << "All other reduced costs are zero (within "
437  << std::setprecision(1) << std::scientific << Param::epsilon()
438  << std::setprecision(8) << std::fixed << ")." << std::endl;)
439  }
440  }
441  else
442  MSG_INFO1(soplex.spxout, soplex.spxout << "No dual information available.\n")
443  }
444 
445  if(rational)
446  {
447  DVectorRational dual(soplex.numRowsReal());
448 
449  if(soplex.getDualFarkasRational(dual))
450  {
451  MSG_INFO1(soplex.spxout, soplex.spxout << "\nDual ray (name, value):\n";)
452 
453  for(int i = 0; i < soplex.numRowsReal(); ++i)
454  {
455  if(dual[i] != (Rational) 0)
456  {
457  MSG_INFO1(soplex.spxout, soplex.spxout << rownames[i] << "\t"
458  << std::setw(printwidth)
459  << std::setprecision(printprec)
460  << dual[i] << std::endl;)
461  }
462  }
463 
464  MSG_INFO1(soplex.spxout, soplex.spxout << "All other entries are zero." << std::endl;)
465  }
466 
467  if(soplex.isDualFeasible() && soplex.getDualRational(dual))
468  {
469  MSG_INFO1(soplex.spxout, soplex.spxout << "\nDual solution (name, value):\n";)
470 
471  for(int i = 0; i < soplex.numRowsRational(); ++i)
472  {
473  if(dual[i] != (Rational) 0)
474  MSG_INFO1(soplex.spxout, soplex.spxout << rownames[i] << "\t" << dual[i] << std::endl;)
475  }
476 
477  MSG_INFO1(soplex.spxout, soplex.spxout << "All other dual values are zero." << std::endl;)
478 
479  DVectorRational redcost(soplex.numColsReal());
480 
481  if(soplex.getRedCostRational(redcost))
482  {
483  MSG_INFO1(soplex.spxout, soplex.spxout << "\nReduced costs (name, value):\n";)
484 
485  for(int i = 0; i < soplex.numColsReal(); ++i)
486  {
487  if(redcost[i] != (Rational) 0)
488  MSG_INFO1(soplex.spxout, soplex.spxout << colnames[i] << "\t" << redcost[i] << std::endl;)
489  }
490 
491  MSG_INFO1(soplex.spxout, soplex.spxout << "All other reduced costs are zero." << std::endl;)
492  }
493  }
494  else
495  MSG_INFO1(soplex.spxout, soplex.spxout << "No dual (rational) solution available.\n")
496  }
497 }
498 
499 
500 
501 /// runs SoPlex command line
502 int main(int argc, char* argv[])
503 {
504  ///@todo the EGlib version info should be printed after the SoPlex version info
505  // initialize EGlib's GMP memory management before any rational numbers are created
506  EGlpNumStart();
507 
508  SoPlex* soplex = 0;
509 
510  Timer* readingTime = 0;
511  Validation* validation = 0;
512  int optidx;
513 
514  const char* lpfilename = 0;
515  char* readbasname = 0;
516  char* writebasname = 0;
517  char* writefilename = 0;
518  char* writedualfilename = 0;
519  char* loadsetname = 0;
520  char* savesetname = 0;
521  char* diffsetname = 0;
522  bool printPrimal = false;
523  bool printPrimalRational = false;
524  bool printDual = false;
525  bool printDualRational = false;
526  bool displayStatistics = false;
527  bool checkSol = false;
528 
529  int returnValue = 0;
530 
531  try
532  {
533  NameSet rownames;
534  NameSet colnames;
535 
536  // create default timer (CPU time)
538  soplex = 0;
539  spx_alloc(soplex);
540  new(soplex) SoPlex();
541 
542  soplex->printVersion();
543  MSG_INFO1(soplex->spxout, soplex->spxout << SOPLEX_COPYRIGHT << std::endl << std::endl);
544 
545  validation = 0;
546  spx_alloc(validation);
547  new(validation) Validation();
548 
549  // no options were given
550  if(argc <= 1)
551  {
552  printUsage(argv, 0);
553  returnValue = 1;
554  goto TERMINATE;
555  }
556 
557  // read arguments from command line
558  for(optidx = 1; optidx < argc; optidx++)
559  {
560  char* option = argv[optidx];
561 
562  // we reached <lpfile>
563  if(option[0] != '-')
564  {
565  lpfilename = argv[optidx];
566  continue;
567  }
568 
569  // option string must start with '-', must contain at least two characters, and exactly two characters if and
570  // only if it is -x, -y, -q, or -c
571  if(option[0] != '-' || option[1] == '\0'
572  || ((option[2] == '\0') != (option[1] == 'x' || option[1] == 'X' || option[1] == 'y'
573  || option[1] == 'Y' || option[1] == 'q' || option[1] == 'c')))
574  {
575  printUsage(argv, optidx);
576  returnValue = 1;
577  goto TERMINATE_FREESTRINGS;
578  }
579 
580  switch(option[1])
581  {
582  case '-' :
583  {
584  option = &option[2];
585 
586  // --readbas=<basfile> : read starting basis from file
587  if(strncmp(option, "readbas=", 8) == 0)
588  {
589  if(readbasname == 0)
590  {
591  char* filename = &option[8];
592  readbasname = new char[strlen(filename) + 1];
593  spxSnprintf(readbasname, strlen(filename) + 1, "%s", filename);
594  }
595  }
596  // --writebas=<basfile> : write terminal basis to file
597  else if(strncmp(option, "writebas=", 9) == 0)
598  {
599  if(writebasname == 0)
600  {
601  char* filename = &option[9];
602  writebasname = new char[strlen(filename) + 1];
603  spxSnprintf(writebasname, strlen(filename) + 1, "%s", filename);
604  }
605  }
606  // --writefile=<lpfile> : write LP to file
607  else if(strncmp(option, "writefile=", 10) == 0)
608  {
609  if(writefilename == 0)
610  {
611  char* filename = &option[10];
612  writefilename = new char[strlen(filename) + 1];
613  spxSnprintf(writefilename, strlen(filename) + 1, "%s", filename);
614  }
615  }
616  // --writedual=<lpfile> : write dual LP to a file
617  else if(strncmp(option, "writedual=", 10) == 0)
618  {
619  if(writedualfilename == 0)
620  {
621  char* dualfilename = &option[10];
622  writedualfilename = new char[strlen(dualfilename) + 1];
623  spxSnprintf(writedualfilename, strlen(dualfilename) + 1, "%s", dualfilename);
624  }
625  }
626  // --loadset=<setfile> : load parameters from settings file
627  else if(strncmp(option, "loadset=", 8) == 0)
628  {
629  if(loadsetname == 0)
630  {
631  char* filename = &option[8];
632  loadsetname = new char[strlen(filename) + 1];
633  spxSnprintf(loadsetname, strlen(filename) + 1, "%s", filename);
634 
635  if(!soplex->loadSettingsFile(loadsetname))
636  {
637  printUsage(argv, optidx);
638  returnValue = 1;
639  goto TERMINATE_FREESTRINGS;
640  }
641  else
642  {
643  // we need to start parsing again because some command line parameters might have been overwritten
644  optidx = 0;
645  }
646  }
647  }
648  // --saveset=<setfile> : save parameters to settings file
649  else if(strncmp(option, "saveset=", 8) == 0)
650  {
651  if(savesetname == 0)
652  {
653  char* filename = &option[8];
654  savesetname = new char[strlen(filename) + 1];
655  spxSnprintf(savesetname, strlen(filename) + 1, "%s", filename);
656  }
657  }
658  // --diffset=<setfile> : save modified parameters to settings file
659  else if(strncmp(option, "diffset=", 8) == 0)
660  {
661  if(diffsetname == 0)
662  {
663  char* filename = &option[8];
664  diffsetname = new char[strlen(filename) + 1];
665  spxSnprintf(diffsetname, strlen(filename) + 1, "%s", filename);
666  }
667  }
668  // --readmode=<value> : choose reading mode for <lpfile> (0* - floating-point, 1 - rational)
669  else if(strncmp(option, "readmode=", 9) == 0)
670  {
671  if(!soplex->setIntParam(SoPlex::READMODE, option[9] - '0'))
672  {
673  printUsage(argv, optidx);
674  returnValue = 1;
675  goto TERMINATE_FREESTRINGS;
676  }
677  }
678  // --solvemode=<value> : choose solving mode (0* - floating-point solve, 1 - auto, 2 - force iterative refinement)
679  else if(strncmp(option, "solvemode=", 10) == 0)
680  {
681  if(!soplex->setIntParam(SoPlex::SOLVEMODE, option[10] - '0'))
682  {
683  printUsage(argv, optidx);
684  returnValue = 1;
685  goto TERMINATE_FREESTRINGS;
686  }
687  // if the LP is parsed rationally and might be solved rationally, we choose automatic syncmode such that
688  // the rational LP is kept after reading
691  {
693  }
694  }
695  // --extsol=<value> : external solution for soplex to use for validation
696  else if(strncmp(option, "extsol=", 7) == 0)
697  {
698  char* input = &option[7];
699 
700  if(!validation->updateExternalSolution(input))
701  {
702  printUsage(argv, optidx);
703  returnValue = 1;
704  goto TERMINATE_FREESTRINGS;
705  }
706  }
707  // --<type>:<name>=<val> : change parameter value using syntax of settings file entries
708  else if(!soplex->parseSettingsString(option))
709  {
710  printUsage(argv, optidx);
711  returnValue = 1;
712  goto TERMINATE_FREESTRINGS;
713  }
714 
715  break;
716  }
717 
718  case 't' :
719 
720  // -t<s> : set time limit to <s> seconds
721  if(!soplex->setRealParam(SoPlex::TIMELIMIT, atoi(&option[2])))
722  {
723  printUsage(argv, optidx);
724  returnValue = 1;
725  goto TERMINATE_FREESTRINGS;
726  }
727 
728  break;
729 
730  case 'i' :
731 
732  // -i<n> : set iteration limit to <n>
733  if(!soplex->setIntParam(SoPlex::ITERLIMIT, atoi(&option[2])))
734  {
735  printUsage(argv, optidx);
736  returnValue = 1;
737  goto TERMINATE_FREESTRINGS;
738  }
739 
740  break;
741 
742  case 'f' :
743 
744  // -f<eps> : set primal feasibility tolerance to <eps>
745  if(!soplex->setRealParam(SoPlex::FEASTOL, atof(&option[2])))
746  {
747  printUsage(argv, optidx);
748  returnValue = 1;
749  goto TERMINATE_FREESTRINGS;
750  }
751 
752  break;
753 
754  case 'o' :
755 
756  // -o<eps> : set dual feasibility (optimality) tolerance to <eps>
757  if(!soplex->setRealParam(SoPlex::OPTTOL, atof(&option[2])))
758  {
759  printUsage(argv, optidx);
760  returnValue = 1;
761  goto TERMINATE_FREESTRINGS;
762  }
763 
764  break;
765 
766  case 'l' :
767 
768  // l<eps> : set validation tolerance to <eps>
769  if(!validation->updateValidationTolerance(&option[2]))
770  {
771  printUsage(argv, optidx);
772  returnValue = 1;
773  goto TERMINATE_FREESTRINGS;
774  }
775 
776  break;
777 
778  case 's' :
779 
780  // -s<value> : choose simplifier/presolver (0 - off, 1* - auto)
781  if(!soplex->setIntParam(SoPlex::SIMPLIFIER, option[2] - '0'))
782  {
783  printUsage(argv, optidx);
784  returnValue = 1;
785  goto TERMINATE_FREESTRINGS;
786  }
787 
788  break;
789 
790  case 'g' :
791 
792  // -g<value> : choose scaling (0 - off, 1 - uni-equilibrium, 2* - bi-equilibrium, 3 - geometric, 4 - iterated geometric, 5 - least squares, 6 - geometric-equilibrium)
793  if(!soplex->setIntParam(SoPlex::SCALER, option[2] - '0'))
794  {
795  printUsage(argv, optidx);
796  returnValue = 1;
797  goto TERMINATE_FREESTRINGS;
798  }
799 
800  break;
801 
802  case 'p' :
803 
804  // -p<value> : choose pricing (0* - auto, 1 - dantzig, 2 - parmult, 3 - devex, 4 - quicksteep, 5 - steep)
805  if(!soplex->setIntParam(SoPlex::PRICER, option[2] - '0'))
806  {
807  printUsage(argv, optidx);
808  returnValue = 1;
809  goto TERMINATE_FREESTRINGS;
810  }
811 
812  break;
813 
814  case 'r' :
815 
816  // -r<value> : choose ratio tester (0 - textbook, 1 - harris, 2* - fast, 3 - boundflipping)
817  if(!soplex->setIntParam(SoPlex::RATIOTESTER, option[2] - '0'))
818  {
819  printUsage(argv, optidx);
820  returnValue = 1;
821  goto TERMINATE_FREESTRINGS;
822  }
823 
824  break;
825 
826  case 'v' :
827 
828  // -v<level> : set verbosity to <level> (0 - error, 3 - normal, 5 - high)
829  if(!soplex->setIntParam(SoPlex::VERBOSITY, option[2] - '0'))
830  {
831  printUsage(argv, optidx);
832  returnValue = 1;
833  goto TERMINATE_FREESTRINGS;
834  }
835 
836  break;
837 
838  case 'x' :
839  // -x : print primal solution
840  printPrimal = true;
841  break;
842 
843  case 'X' :
844  // -X : print primal solution with rationals
845  printPrimalRational = true;
846  break;
847 
848  case 'y' :
849  // -y : print dual multipliers
850  printDual = true;
851  break;
852 
853  case 'Y' :
854  // -Y : print dual multipliers with rationals
855  printDualRational = true;
856  break;
857 
858  case 'q' :
859  // -q : display detailed statistics
860  displayStatistics = true;
861  break;
862 
863  case 'c' :
864  // -c : perform final check of optimal solution in original problem
865  checkSol = true;
866  break;
867 
868  case 'h' :
869 
870  // -h : display all parameters
871  if(!soplex->saveSettingsFile(0, false))
872  {
873  MSG_ERROR(std::cerr << "Error printing parameters\n");
874  }
875 
876  break;
877 
878  //lint -fallthrough
879  default :
880  {
881  printUsage(argv, optidx);
882  returnValue = 1;
883  goto TERMINATE_FREESTRINGS;
884  }
885  }
886  }
887 
888  MSG_INFO1(soplex->spxout, soplex->printUserSettings();)
889 
890  // no LP file was given and no settings files are written
891  if(lpfilename == 0 && savesetname == 0 && diffsetname == 0)
892  {
893  printUsage(argv, 0);
894  returnValue = 1;
895  goto TERMINATE_FREESTRINGS;
896  }
897 
898  // ensure that syncmode is not manual
900  {
901  MSG_ERROR(std::cerr <<
902  "Error: manual synchronization is invalid on command line. Change parameter int:syncmode.\n");
903  returnValue = 1;
904  goto TERMINATE_FREESTRINGS;
905  }
906 
907  // save settings files
908  if(savesetname != 0)
909  {
910  MSG_INFO1(soplex->spxout, soplex->spxout << "Saving parameters to settings file <" << savesetname <<
911  "> . . .\n");
912 
913  if(!soplex->saveSettingsFile(savesetname, false))
914  {
915  MSG_ERROR(std::cerr << "Error writing parameters to file <" << savesetname << ">\n");
916  }
917  }
918 
919  if(diffsetname != 0)
920  {
921  MSG_INFO1(soplex->spxout, soplex->spxout << "Saving modified parameters to settings file <" <<
922  diffsetname << "> . . .\n");
923 
924  if(!soplex->saveSettingsFile(diffsetname, true))
925  {
926  MSG_ERROR(std::cerr << "Error writing modified parameters to file <" << diffsetname << ">\n");
927  }
928  }
929 
930  // no LP file given: exit after saving settings
931  if(lpfilename == 0)
932  {
933  if(loadsetname != 0 || savesetname != 0 || diffsetname != 0)
934  {
935  MSG_INFO1(soplex->spxout, soplex->spxout << "\n");
936  }
937 
938  goto TERMINATE_FREESTRINGS;
939  }
940 
941  // measure time for reading LP file and basis file
942  readingTime->start();
943 
944  // if the LP is parsed rationally and might be solved rationally, we choose automatic syncmode such that
945  // the rational LP is kept after reading
948  {
950  }
951 
952  // read LP from input file
953  MSG_INFO1(soplex->spxout, soplex->spxout << "Reading "
954  << (soplex->intParam(SoPlex::READMODE) == SoPlex::READMODE_REAL ? "(real)" : "(rational)")
955  << " LP file <" << lpfilename << "> . . .\n");
956 
957  if(!soplex->readFile(lpfilename, &rownames, &colnames))
958  {
959  MSG_ERROR(std::cerr << "Error while reading file <" << lpfilename << ">.\n");
960  returnValue = 1;
961  goto TERMINATE_FREESTRINGS;
962  }
963 
964  // write LP if specified
965  if(writefilename != 0)
966  {
967  if(!soplex->writeFileReal(writefilename, &rownames, &colnames))
968  {
969  MSG_ERROR(std::cerr << "Error while writing file <" << writefilename << ">.\n\n");
970  returnValue = 1;
971  goto TERMINATE_FREESTRINGS;
972  }
973  else
974  {
975  MSG_INFO1(soplex->spxout, soplex->spxout << "Written LP to file <" << writefilename << ">.\n\n");
976  }
977  }
978 
979  // write dual LP if specified
980  if(writedualfilename != 0)
981  {
982  if(!soplex->writeDualFileReal(writedualfilename, &rownames, &colnames))
983  {
984  MSG_ERROR(std::cerr << "Error while writing dual file <" << writedualfilename << ">.\n\n");
985  returnValue = 1;
986  goto TERMINATE_FREESTRINGS;
987  }
988  else
989  {
990  MSG_INFO1(soplex->spxout, soplex->spxout << "Written dual LP to file <" << writedualfilename <<
991  ">.\n\n");
992  }
993  }
994 
995  // read basis file if specified
996  if(readbasname != 0)
997  {
998  MSG_INFO1(soplex->spxout, soplex->spxout << "Reading basis file <" << readbasname << "> . . . ");
999 
1000  if(!soplex->readBasisFile(readbasname, &rownames, &colnames))
1001  {
1002  MSG_ERROR(std::cerr << "Error while reading file <" << readbasname << ">.\n");
1003  returnValue = 1;
1004  goto TERMINATE_FREESTRINGS;
1005  }
1006  }
1007 
1008  readingTime->stop();
1009 
1010  MSG_INFO1(soplex->spxout,
1011  std::streamsize prec = soplex->spxout.precision();
1012  soplex->spxout << "Reading took "
1013  << std::fixed << std::setprecision(2) << readingTime->time()
1014  << std::scientific << std::setprecision(int(prec))
1015  << " seconds.\n\n");
1016 
1017  MSG_INFO1(soplex->spxout, soplex->spxout << "LP has " << soplex->numRowsReal() << " rows "
1018  << soplex->numColsReal() << " columns and " << soplex->numNonzerosReal() << " nonzeros.\n\n");
1019 
1020  // solve the LP
1021  soplex->optimize();
1022 
1023  // print solution, check solution, and display statistics
1024  printPrimalSolution(*soplex, colnames, rownames, printPrimal, printPrimalRational);
1025  printDualSolution(*soplex, colnames, rownames, printDual, printDualRational);
1026 
1027  if(checkSol)
1028  checkSolution(*soplex);
1029 
1030  if(displayStatistics)
1031  {
1032  MSG_INFO1(soplex->spxout, soplex->spxout << "Statistics\n==========\n\n");
1033  soplex->printStatistics(soplex->spxout.getStream(SPxOut::INFO1));
1034  }
1035 
1036  if(validation->validate)
1037  validation->validateSolveReal(*soplex);
1038 
1039  // write basis file if specified
1040  if(writebasname != 0)
1041  {
1042  if(!soplex->hasBasis())
1043  {
1044  MSG_WARNING(soplex->spxout, soplex->spxout <<
1045  "No basis information available. Could not write file <" << writebasname << ">\n\n");
1046  }
1047  else if(!soplex->writeBasisFile(writebasname, &rownames, &colnames))
1048  {
1049  MSG_ERROR(std::cerr << "Error while writing file <" << writebasname << ">.\n\n");
1050  returnValue = 1;
1051  goto TERMINATE_FREESTRINGS;
1052  }
1053  else
1054  {
1055  MSG_INFO1(soplex->spxout, soplex->spxout << "Written basis information to file <" << writebasname <<
1056  ">.\n\n");
1057  }
1058  }
1059  }
1060  catch(const SPxException& x)
1061  {
1062  MSG_ERROR(std::cerr << "Exception caught: " << x.what() << "\n");
1063  returnValue = 1;
1064  goto TERMINATE_FREESTRINGS;
1065  }
1066 
1067 TERMINATE_FREESTRINGS:
1068  freeStrings(readbasname, writebasname, loadsetname, savesetname, diffsetname);
1069 
1070 TERMINATE:
1071 
1072  // because EGlpNumClear() calls mpq_clear() for all mpq_t variables, we need to destroy all objects of class Rational
1073  // beforehand; hence all Rational objects and all data that uses Rational objects must be allocated dynamically via
1074  // spx_alloc() and freed here; disabling the list memory is crucial
1075  if(0 != soplex)
1076  {
1077  soplex->~SoPlex();
1078  spx_free(soplex);
1079  }
1080 
1081  if(0 != validation)
1082  {
1083  validation->~Validation();
1084  spx_free(validation);
1085  }
1086 
1088  EGlpNumClear();
1089 
1090  if(0 != readingTime)
1091  {
1092  readingTime->~Timer();
1093  spx_free(readingTime);
1094  }
1095 
1096  return returnValue;
1097 }
bool isNotZero(Real a, Real eps=Param::epsilon())
returns true iff |a| > eps
Definition: spxdefines.h:418
standard floating-point parsing
Definition: soplex.h:1227
void printVersion() const
prints version and compilation options
Definition: soplex.cpp:7309
bool getDualViolationRational(Rational &maxviol, Rational &sumviol)
gets violation of dual multipliers; returns true on success
Definition: soplex.cpp:3709
#define EGlpNumStart()
Definition: soplexmain.cpp:36
int numRowsReal() const
returns number of rows
Definition: soplex.cpp:850
type of ratio test
Definition: soplex.h:1008
verbosity level
Definition: soplex.h:993
automatic sync of real and rational LP
Definition: soplex.h:1217
bool getPrimalReal(VectorReal &vector)
gets the primal solution vector if available; returns true on success
Definition: soplex.cpp:3078
int numRowsRational() const
returns number of rows
Definition: soplex.cpp:1142
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:5399
bool getDualRational(VectorRational &vector)
gets the dual solution vector if available; returns true on success
Definition: soplex.cpp:3453
time limit in seconds (INFTY if unlimited)
Definition: soplex.h:1323
mode for iterative refinement strategy
Definition: soplex.h:1017
virtual ~SoPlex()
destructor
Definition: soplex.cpp:808
bool getRedCostRational(VectorRational &vector)
gets the vector of reduced cost values if available; returns true on success
Definition: soplex.cpp:3468
primal feasibility tolerance
Definition: soplex.h:1302
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:5615
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:5415
mode for reading LP files
Definition: soplex.h:1014
mode for synchronizing real and rational LP
Definition: soplex.h:1011
bool getDualFarkasReal(VectorReal &vector)
gets the Farkas proof if available; returns true on success
Definition: soplex.cpp:3153
iteration limit (-1 if unlimited)
Definition: soplex.h:981
bool getRowViolationReal(Real &maxviol, Real &sumviol)
gets violation of constraints; returns true on success
Definition: soplex.cpp:3211
decide according to READMODE
Definition: soplex.h:1253
bool getRowViolationRational(Rational &maxviol, Rational &sumviol)
gets violation of constraints; returns true on success
Definition: soplex.cpp:3555
bool updateExternalSolution(char *solution)
updates the external solution used for validation
Definition: validation.cpp:26
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:5333
int intParam(const IntParam param) const
returns integer parameter value
Definition: soplex.cpp:5775
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:3260
void printStatistics(std::ostream &os)
prints complete statistics
Definition: soplex.cpp:7198
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:1220
virtual const std::string what() const
returns exception message
Definition: exceptions.h:57
bool isDualFeasible() const
is stored dual solution feasible?
Definition: soplex.cpp:3031
SPxSolver::Status optimize()
optimize the given LP
Definition: soplex.cpp:2902
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:3006
type of scaler
Definition: soplex.h:999
double Real
Definition: spxdefines.h:218
int main(int argc, char *argv[])
runs SoPlex command line
Definition: soplexmain.cpp:502
bool getPrimalRayReal(VectorReal &vector)
gets the primal ray if available; returns true on success
Definition: soplex.cpp:3108
bool hasPrimal() const
is a primal feasible solution available?
Definition: soplex.cpp:3015
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:70
bool hasBasis() const
is an advanced starting basis available?
Definition: soplex.cpp:4025
#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:3317
int spxSnprintf(char *t, size_t len, const char *s,...)
safe version of snprintf
Definition: spxdefines.h:460
type of simplifier
Definition: soplex.h:996
void printUserSettings()
print non-default parameter values
Definition: soplex.cpp:6559
static void checkSolutionRational(SoPlex &soplex)
performs external feasibility check with rational type
Definition: soplexmain.cpp:197
static void printPrimalSolution(SoPlex &soplex, NameSet &colnames, NameSet &rownames, bool real=true, bool rational=false)
Definition: soplexmain.cpp:271
int numColsRational() const
returns number of columns
Definition: soplex.cpp:1151
bool getPrimalRational(VectorRational &vector)
gets the primal solution vector if available; returns true on success
Definition: soplex.cpp:3408
bool getRedCostReal(VectorReal &vector)
gets the vector of reduced cost values if available; returns true on success
Definition: soplex.cpp:3138
Real realParam(const RealParam param) const
returns real parameter value
Definition: soplex.cpp:5785
virtual Real time() const =0
bool hasDual() const
is a dual feasible solution available?
Definition: soplex.cpp:3040
bool parseSettingsString(char *line)
parses one setting string and returns true on success; note that string is modified ...
Definition: soplex.cpp:6776
SPxOut spxout
Definition: soplex.h:1476
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:372
Preconfigured SoPlex LP solver.
apply standard floating-point algorithm
Definition: soplex.h:1237
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:33
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:6312
bool loadSettingsFile(const char *filename)
reads settings file; returns true on success
Definition: soplex.cpp:6724
int numNonzerosReal() const
returns number of nonzeros
Definition: soplex.cpp:868
bool getRedCostViolationRational(Rational &maxviol, Rational &sumviol)
gets violation of reduced costs; returns true on success
Definition: soplex.cpp:3614
type of pricer
Definition: soplex.h:1005
bool getDualReal(VectorReal &vector)
gets the dual solution vector if available; returns true on success
Definition: soplex.cpp:3123
static void checkSolution(SoPlex &soplex)
performs external feasibility check according to check mode
Definition: soplexmain.cpp:254
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:3168
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:5352
mode for a posteriori feasibility checks
Definition: soplex.h:1020
~Validation()
default destructor
Definition: validation.h:50
bool getDualFarkasRational(VectorRational &vector)
gets the Farkas proof if LP is infeasible; returns true on success
Definition: soplex.cpp:3483
#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:3257
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:3438
dual feasibility tolerance
Definition: soplex.h:1305
bool setIntParam(const IntParam param, const int value, const bool init=true)
sets integer parameter value; returns true on success
Definition: soplex.cpp:5887
bool saveSettingsFile(const char *filename, const bool onlyChanged=false) const
writes settings file; returns true on success
Definition: soplex.cpp:6624
static void checkSolutionReal(SoPlex &soplex)
performs external feasibility check with real type
Definition: soplexmain.cpp:138
std::string rationalToString(const Rational &r, const int precision)
convert rational number to string
Definition: rational.cpp:3645
bool updateValidationTolerance(char *tolerance)
updates the tolerance used for validation
Definition: validation.cpp:53
int numColsReal() const
returns number of columns
Definition: soplex.cpp:859
Wrapper for the system time query methods.
Definition: timer.h:76
void spx_free(T &p)
Release memory.
Definition: spxalloc.h:110
bool getBoundViolationRational(Rational &maxviol, Rational &sumviol)
gets violation of bounds; returns true on success
Definition: soplex.cpp:3498