1 /* A sort of clone of the cddlib test program `lcdd'.
2 Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
3 Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)
4
5 This file is part of the Parma Polyhedra Library (PPL).
6
7 The PPL is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11
12 The PPL is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
20
21 For the most up-to-date information see the Parma Polyhedra Library
22 site: http://bugseng.com/products/ppl/ . */
23
24 #if 0
25 #define USE_PIPLIB 1
26 #endif
27
28 #if (!defined(USE_PPL) && !defined(USE_PIPLIB))
29 #define USE_PPL 1
30 #elif (defined(USE_PPL) && defined(USE_PIPLIB))
31 #error "Exactly one among USE_PPL and USE_PIPLIB must be defined"
32 #endif
33
34 #if defined(USE_PPL)
35
36 #include "ppl.hh"
37
38 namespace PPL = Parma_Polyhedra_Library;
39
40 #if PPL_VERSION_MAJOR == 0 && PPL_VERSION_MINOR < 11
41 #error "PPL version 0.11 or following is required"
42 #endif
43
44 typedef PPL::C_Polyhedron POLYHEDRON_TYPE;
45
46 #elif defined(USE_PIPLIB)
47
48 #error "PipLib not supported yet"
49
50 #endif
51
52 #include "timings.hh"
53 #include <gmpxx.h>
54 #include <vector>
55 #include <set>
56 #include <climits>
57 #include <cassert>
58 #include <cstdarg>
59 #include <csignal>
60 #include <cerrno>
61 #include <cstring>
62 #include <cstdio>
63 #include <cstdlib>
64 #include <iostream>
65 #include <fstream>
66 #include <sstream>
67 #include <stdexcept>
68 #include <memory>
69
70 #ifdef PPL_HAVE_GETOPT_H
71 #include <getopt.h>
72
73 // Try to accommodate non-GNU implementations of `getopt()'.
74 #if !defined(no_argument) && defined(NO_ARG)
75 #define no_argument NO_ARG
76 #endif
77
78 #if !defined(required_argument) && defined(REQUIRED_ARG)
79 #define required_argument REQUIRED_ARG
80 #endif
81
82 #if !defined(optional_argument) && defined(OPTIONAL_ARG)
83 #define optional_argument OPTIONAL_ARG
84 #endif
85
86 #endif // defined(PPL_HAVE_GETOPT_H)
87
88 #ifdef PPL_HAVE_UNISTD_H
89 // Include this for `getopt()': especially important if we do not have
90 // <getopt.h>.
91 # include <unistd.h>
92 #endif
93
94 #ifdef PPL_HAVE_SYS_TIME_H
95 # include <sys/time.h>
96 #endif
97
98 #ifdef PPL_HAVE_SYS_RESOURCE_H
99 // This should be included after <time.h> and <sys/time.h> so as to make
100 // sure we have the definitions for, e.g., `ru_utime'.
101 # include <sys/resource.h>
102 #endif
103
104 namespace {
105
106 PPL::PIP_Problem::Control_Parameter_Value cutting_strategy
107 = PPL::PIP_Problem::CUTTING_STRATEGY_FIRST;
108
109 PPL::PIP_Problem::Control_Parameter_Value pivot_row_strategy
110 = PPL::PIP_Problem::PIVOT_ROW_STRATEGY_FIRST;
111
112 long loop_iterations = 1;
113
114 void
pip_display_sol(std::ostream & out,const Parma_Polyhedra_Library::PIP_Tree pip,const Parma_Polyhedra_Library::Variables_Set & parameters,const Parma_Polyhedra_Library::Variables_Set & vars,Parma_Polyhedra_Library::dimension_type space_dimension,int indent=0)115 pip_display_sol(std::ostream& out,
116 const Parma_Polyhedra_Library::PIP_Tree pip,
117 const Parma_Polyhedra_Library::Variables_Set& parameters,
118 const Parma_Polyhedra_Library::Variables_Set& vars,
119 Parma_Polyhedra_Library::dimension_type space_dimension,
120 int indent = 0) {
121 using namespace Parma_Polyhedra_Library::IO_Operators;
122
123 if (!pip) {
124 out << std::setw(indent*2) << "" << "_|_" << std::endl;
125 }
126 else {
127 for (PPL::PIP_Tree_Node::Artificial_Parameter_Sequence::const_iterator
128 i = pip->art_parameter_begin(),
129 i_end = pip->art_parameter_end();
130 i != i_end;
131 ++i) {
132 out << std::setw(indent*2) << "" << "Parameter "
133 << PPL::Linear_Expression(PPL::Variable(space_dimension++))
134 << " = " << *i << std::endl;
135 }
136 const PPL::Constraint_System& constraints = pip->constraints();
137 const bool constraints_empty = constraints.empty();
138 if (!constraints_empty) {
139 out << std::setw(indent*2) << "" << "if ";
140 for (PPL::Constraint_System::const_iterator
141 cs_begin = constraints.begin(),
142 cs_end = constraints.end(),
143 i = cs_begin; i != cs_end; ++i) {
144 out << ((i == cs_begin) ? "" : " and ") << *i;
145 }
146 out << " then" << std::endl;
147 }
148 const PPL::PIP_Decision_Node* const decision_node_p = pip->as_decision();
149 if (decision_node_p) {
150 pip_display_sol(out, decision_node_p->child_node(true),
151 parameters, vars, space_dimension, indent+1);
152 out << std::setw(indent*2) << "" << "else" << std::endl;
153 pip_display_sol(out, decision_node_p->child_node(false),
154 parameters, vars, space_dimension, indent+1);
155 }
156 else {
157 const PPL::PIP_Solution_Node* const solution_node_p = pip->as_solution();
158 out << std::setw(indent*2 + (constraints_empty ? 0 : 2)) << "" << "{";
159 for (PPL::Variables_Set::const_iterator
160 v_begin = vars.begin(),
161 v_end = vars.end(),
162 i = v_begin; i != v_end; ++i) {
163 out << ((i == v_begin) ? "" : " ; ")
164 << solution_node_p->parametric_values(PPL::Variable(*i));
165 }
166 out << "}" << std::endl;
167 if (!constraints_empty) {
168 out << std::setw(indent*2) << "" << "else" << std::endl;
169 out << std::setw(indent*2 + 2) << "" << "_|_" << std::endl;
170 }
171 }
172 }
173 }
174
175 class PIP_Parser {
176 public:
PIP_Parser()177 PIP_Parser() : pip() {
178 pip.set_control_parameter(cutting_strategy);
179 pip.set_control_parameter(pivot_row_strategy);
180 }
181
~PIP_Parser()182 virtual ~PIP_Parser() {
183 }
184
problem() const185 const PPL::PIP_Problem& problem() const {
186 return pip;
187 }
188
189 virtual bool read(std::istream& in) = 0;
190
191 //! Output the solution in "if-then-else" format.
output_solution_tree(std::ostream & out)192 void output_solution_tree(std::ostream& out) {
193 const PPL::Variables_Set& params = pip.parameter_space_dimensions();
194 PPL::Variables_Set vars;
195 for (PPL::dimension_type i = 0; i < pip.space_dimension(); ++i) {
196 if (params.count(i) == 0) {
197 vars.insert(i);
198 }
199 }
200 const PPL::PIP_Tree solution = pip.solution();
201 pip_display_sol(out, solution, params, vars, pip.space_dimension());
202 }
203
204 typedef std::vector<PPL::Coefficient> Coeff_Vector;
205 typedef std::vector<int> Int_Vector;
206
update_pip(PPL::dimension_type num_vars,PPL::dimension_type num_params,PPL::dimension_type num_constraints,PPL::dimension_type num_ctx_rows,const Coeff_Vector & constraints,const Coeff_Vector & context,const Int_Vector & constraint_type,const Int_Vector & ctx_type,PPL::dimension_type bignum_column)207 bool update_pip(PPL::dimension_type num_vars,
208 PPL::dimension_type num_params,
209 PPL::dimension_type num_constraints,
210 PPL::dimension_type num_ctx_rows,
211 const Coeff_Vector& constraints,
212 const Coeff_Vector& context,
213 const Int_Vector& constraint_type,
214 const Int_Vector& ctx_type,
215 PPL::dimension_type bignum_column) {
216 pip.add_space_dimensions_and_embed(num_vars, num_params);
217 for (PPL::dimension_type k = 0, i = 0; i < num_constraints; ++i) {
218 PPL::Linear_Expression expr;
219 for (PPL::dimension_type j = 0; j < num_vars + num_params; ++j) {
220 add_mul_assign(expr, constraints[k++], PPL::Variable(j));
221 }
222 expr += constraints[k++];
223 if (constraint_type[i]) {
224 pip.add_constraint(PPL::Constraint(expr >= 0));
225 }
226 else {
227 pip.add_constraint(PPL::Constraint(expr == 0));
228 }
229 }
230 if (num_params > 0) {
231 for (PPL::dimension_type k = 0, i = 0; i < num_ctx_rows; ++i) {
232 PPL::Linear_Expression expr;
233 for (PPL::dimension_type j = 0; j < num_params; ++j) {
234 add_mul_assign(expr, context[k++], PPL::Variable(num_vars+j));
235 }
236 expr += context[k++];
237 if (ctx_type[i]) {
238 pip.add_constraint(PPL::Constraint(expr >= 0));
239 }
240 else {
241 pip.add_constraint(PPL::Constraint(expr == 0));
242 }
243 }
244 }
245 if (bignum_column != PPL::not_a_dimension()) {
246 pip.set_big_parameter_dimension(bignum_column);
247 }
248 return true;
249 }
250
251 protected:
252 //! The problem object.
253 PPL::PIP_Problem pip;
254 }; // class PIP_Parser
255
256 class PIP_PolyLib_Parser : public PIP_Parser {
257 public:
PIP_PolyLib_Parser()258 PIP_PolyLib_Parser(): PIP_Parser() {
259 }
260
read(std::istream & in)261 bool read(std::istream& in) {
262 std::string line;
263
264 PPL::dimension_type num_ctx_rows;
265 PPL::dimension_type num_params;
266 getline_no_comment(in, line);
267 {
268 std::istringstream iss(line);
269 iss >> num_ctx_rows >> num_params;
270 }
271 PPL_ASSERT(num_params >= 2);
272 num_params -= 2;
273
274 Coeff_Vector context(num_ctx_rows * (1+num_params));
275 Int_Vector ctx_type(num_ctx_rows);
276 for (PPL::dimension_type i = 0; i < num_ctx_rows; ++i) {
277 getline_no_comment(in, line);
278 std::istringstream iss(line);
279 iss >> ctx_type[i];
280 for (PPL::dimension_type j = 0; j <= num_params; ++j) {
281 iss >> context[i*num_ctx_rows + j];
282 }
283 }
284
285 int bignum_column_coding;
286 getline_no_comment(in, line);
287 {
288 std::istringstream iss(line);
289 iss >> bignum_column_coding;
290 }
291 PPL_ASSERT(bignum_column_coding >= -1);
292
293 PPL::dimension_type num_constraints;
294 PPL::dimension_type constraint_width;
295 PPL::dimension_type num_vars;
296 getline_no_comment(in, line);
297 {
298 std::istringstream iss(line);
299 iss >> num_constraints >> constraint_width;
300 }
301 constraint_width -= 1;
302 num_vars = constraint_width - num_params - 1;
303
304 Coeff_Vector constraints(num_constraints * constraint_width);
305 Int_Vector constraint_type(num_constraints);
306 for (PPL::dimension_type i = 0; i < num_constraints; ++i) {
307 getline_no_comment(in, line);
308 std::istringstream iss(line);
309 iss >> constraint_type[i];
310 for (PPL::dimension_type j = 0; j < constraint_width; ++j) {
311 iss >> constraints[i*constraint_width + j];
312 }
313 }
314
315 const PPL::dimension_type bignum_column
316 = (bignum_column_coding == -1)
317 ? PPL::not_a_dimension()
318 : (num_vars + PPL::dimension_type(bignum_column_coding - 1));
319
320 const bool result = update_pip(num_vars, num_params,
321 num_constraints, num_ctx_rows,
322 constraints, context,
323 constraint_type, ctx_type,
324 bignum_column);
325 return result;
326 }
327
328 protected:
getline_no_comment(std::istream & in,std::string & s)329 static void getline_no_comment(std::istream& in, std::string& s) {
330 do {
331 getline(in, s);
332 } while (s.size() == 0 || s[0] == '\r' || s[0] == '#');
333 }
334 }; // class PIP_PolyLib_Parser
335
336 class PIP_PipLib_Parser : public PIP_Parser {
337 public:
PIP_PipLib_Parser()338 PIP_PipLib_Parser()
339 : PIP_Parser(), comment() {
340 }
341
read(std::istream & in)342 bool read(std::istream& in) {
343 if (!expect(in, '(')) {
344 return false;
345 }
346 if (!expect(in, '(')) {
347 return false;
348 }
349 if (!read_comment(in)) {
350 return false;
351 }
352
353 PPL::dimension_type num_vars;
354 PPL::dimension_type num_params;
355 in >> num_vars >> num_params;
356
357 PPL::dimension_type num_constraints;
358 PPL::dimension_type num_ctx_rows;
359 in >> num_constraints >> num_ctx_rows;
360
361 int bignum_column_coding;
362 in >> bignum_column_coding;
363 PPL_ASSERT(bignum_column_coding >= -1);
364 const PPL::dimension_type bignum_column
365 = (bignum_column_coding == -1)
366 ? PPL::not_a_dimension()
367 : PPL::dimension_type(bignum_column_coding - 1);
368
369 int solve_integer;
370 in >> solve_integer;
371 if (solve_integer != 1) {
372 std::cerr << "Can only solve integer problems." << std::endl;
373 return false;
374 }
375
376 if (!expect(in, '(')) {
377 return false;
378 }
379 const PPL::dimension_type constraint_width = num_vars+num_params+1;
380 Coeff_Vector constraints(num_constraints * constraint_width);
381 Int_Vector constraint_type(num_constraints);
382 for (PPL::dimension_type i = 0; i < num_constraints; ++i) {
383 constraint_type[i] = 1;
384 }
385 for (PPL::dimension_type i = 0; i < num_constraints; ++i) {
386 if (!read_vector(in, i, constraint_width, num_vars, constraints)) {
387 return false;
388 }
389 }
390
391 Coeff_Vector context(num_ctx_rows * (1+num_params));
392 Int_Vector ctx_type(num_ctx_rows);
393 for (PPL::dimension_type i = 0; i < num_ctx_rows; ++i) {
394 ctx_type[i] = 1;
395 }
396 for (PPL::dimension_type i = 0; i < num_ctx_rows; ++i) {
397 if (!read_vector(in, i, num_params+1, num_params, context)) {
398 return false;
399 }
400 }
401
402 const bool result = update_pip(num_vars, num_params,
403 num_constraints, num_ctx_rows,
404 constraints, context,
405 constraint_type, ctx_type,
406 bignum_column);
407 return result;
408 }
409
410 protected:
read_comment(std::istream & in)411 bool read_comment(std::istream& in) {
412 comment = "";
413 int count = 1;
414 do {
415 char c;
416 if (!in.get(c)) {
417 return false;
418 }
419 if (c == '(') {
420 ++count;
421 }
422 else if (c == ')') {
423 --count;
424 }
425 if (count > 0) {
426 comment += c;
427 }
428 } while (count > 0);
429 return true;
430 }
431
expect(std::istream & in,char c)432 static bool expect(std::istream& in, char c) {
433 char a;
434 do {
435 in >> a;
436 } while (a != c && in.good());
437 return a == c;
438 }
439
read_vector(std::istream & in,PPL::dimension_type row_index,PPL::dimension_type row_size,PPL::dimension_type cst_col,Coeff_Vector & tab)440 static bool read_vector(std::istream& in,
441 PPL::dimension_type row_index,
442 PPL::dimension_type row_size,
443 PPL::dimension_type cst_col,
444 Coeff_Vector& tab) {
445 if (!expect(in, '#')) {
446 return false;
447 }
448 if (!expect(in, '[')) {
449 return false;
450 }
451 std::string s;
452 getline(in, s, ']');
453 if (in.fail()) {
454 return false;
455 }
456 std::istringstream iss(s);
457 const PPL::dimension_type start_index = row_index * row_size;
458 PPL::dimension_type k = start_index;
459 for (PPL::dimension_type i = 0; i < cst_col; ++i, ++k) {
460 iss >> tab[k];
461 if (iss.fail()) {
462 return false;
463 }
464 }
465 iss >> tab[start_index + row_size - 1];
466 if (iss.fail()) {
467 return false;
468 }
469 for (PPL::dimension_type i = cst_col + 1; i < row_size; ++i, ++k) {
470 iss >> tab[k];
471 if (iss.fail()) {
472 return false;
473 }
474 }
475 return true;
476 }
477
478 // The comment string in the source file
479 std::string comment;
480 }; // class PIP_PipLib_Parser
481
482 #ifdef PPL_HAVE_GETOPT_H
483 struct option long_options[] = {
484 {"max-cpu", required_argument, 0, 'C'},
485 {"max-memory", required_argument, 0, 'R'},
486 {"help", no_argument, 0, 'h'},
487 {"output", required_argument, 0, 'o'},
488 {"polylib", no_argument, 0, 'P'},
489 {"piplib", no_argument, 0, 'p'},
490 {"timings", no_argument, 0, 't'},
491 {"verbose", no_argument, 0, 'v'},
492 {"iterations", required_argument, 0, 'i'},
493 #if defined(USE_PPL)
494 {"version", no_argument, 0, 'V'},
495 {"check", required_argument, 0, 'c'},
496 #endif
497 {"cut-first", no_argument, 0, 'f'},
498 {"cut-deepest", no_argument, 0, 'd'},
499 {"cut-all", no_argument, 0, 'a'},
500 {"row-first", no_argument, 0, 'F'},
501 {"row-max", no_argument, 0, 'M'},
502 {0, 0, 0, 0}
503 };
504 #endif
505
506 static const char* usage_string
507 = "Usage: %s [OPTION]... [FILE]\n"
508 "Reads the definition of a Parametric Integer Programming problem\n"
509 "and displays the lexicographic minimum in terms of the values of the\n"
510 "parameters.\n\n"
511 "Options:\n"
512 " -RMB, --max-memory=MB limits memory usage to MB megabytes\n"
513 " -h, --help prints this help text to stdout\n"
514 " -oPATH, --output=PATH appends output to PATH\n"
515 " -P, --polylib reads problem in PolyLib format (default)\n"
516 " -p, --piplib reads problem in PipLib format\n"
517 " -t, --timings prints timings to stderr\n"
518 " -v, --verbose produces lots of output\n"
519 " -i, --iterations=N executes the resolution N times (default=1)\n"
520 #if defined(USE_PPL)
521 " -V, --version prints version information to stdout\n"
522 " -cPATH, --check=PATH checks if the result is equal to what is in PATH\n"
523 #endif
524 "\nCut generation options:\n"
525 " -f, --cut-first uses the first non-integer row (default)\n"
526 " -d, --cut-deepest tries to generate the deepest cut\n"
527 " -a, --cut-all always generates all possible cuts\n"
528 "\nPivot row strategy options:\n"
529 " -F, --row-first uses the first row with negative parameter (default)\n"
530 " -M, --row-max chooses row generating the lexico-maximal pivot column\n"
531 #ifndef PPL_HAVE_GETOPT_H
532 "\n"
533 "NOTE: this version does not support long options.\n"
534 #endif
535 "\n"
536 "Report bugs to <ppl-devel@cs.unipr.it>.\n";
537
538 #if defined(USE_PPL)
539 #define OPTION_LETTERS "R:ho:Pptvi:Vc:fdaFM"
540 #else
541 #define OPTION_LETTERS "R:ho:Pptvi:fdaFM"
542 #endif
543
544 const char* program_name = 0;
545
546 unsigned long max_bytes_of_virtual_memory = 0;
547 bool print_timings = false;
548 bool verbose = false;
549 const char* check_file_name = 0;
550
551 void
fatal(const char * format,...)552 fatal(const char* format, ...) {
553 va_list ap;
554 va_start(ap, format);
555 fprintf(stderr, "%s: ", program_name);
556 vfprintf(stderr, format, ap);
557 fprintf(stderr, "\n");
558 va_end(ap);
559 exit(1);
560 }
561
562 const char* input_file_name = 0;
563 std::istream* input_stream_p = 0;
564
565 void
set_input(const char * file_name)566 set_input(const char* file_name) {
567 if (input_stream_p && (input_stream_p != &std::cin)) {
568 delete input_stream_p;
569 }
570 if (file_name) {
571 input_stream_p = new std::ifstream(file_name, std::ios_base::in);
572 if (!*input_stream_p) {
573 fatal("cannot open input file `%s'", file_name);
574 }
575 input_file_name = file_name;
576 }
577 else {
578 input_stream_p = &std::cin;
579 input_file_name = "<cin>";
580 }
581 }
582
583 const char* output_file_name = 0;
584 std::ostream* output_stream_p = 0;
585
586 void
set_output(const char * file_name)587 set_output(const char* file_name) {
588 if (output_stream_p && (output_stream_p != &std::cout)) {
589 delete output_stream_p;
590 }
591 if (file_name) {
592 output_stream_p = new std::ofstream(file_name,
593 std::ios_base::out
594 | std::ios_base::app);
595 if (!*output_stream_p) {
596 fatal("cannot open output file `%s'", file_name);
597 }
598 output_file_name = file_name;
599 }
600 else {
601 output_stream_p = &std::cout;
602 output_file_name = "<cout>";
603 }
604 }
605
606 bool piplib_format = false;
607
608 } // namespace
609
610 void
error(const char * format,...)611 error(const char* format, ...) {
612 va_list ap;
613 va_start(ap, format);
614 fprintf(stderr, "%s: in `%s': ", program_name, input_file_name);
615 vfprintf(stderr, format, ap);
616 fprintf(stderr, "\n");
617 va_end(ap);
618 exit(1);
619 }
620
621 void
warning(const char * format,...)622 warning(const char* format, ...) {
623 va_list ap;
624 va_start(ap, format);
625 fprintf(stderr, "%s: Warning: in `%s': ", program_name, input_file_name);
626 vfprintf(stderr, format, ap);
627 fprintf(stderr, "\n");
628 va_end(ap);
629 }
630
631 #if PPL_CXX_SUPPORTS_LIMITING_MEMORY && PPL_HAVE_DECL_RLIMIT_AS
632
633 void
limit_virtual_memory(const unsigned long bytes)634 limit_virtual_memory(const unsigned long bytes) {
635 struct rlimit t;
636
637 if (getrlimit(RLIMIT_AS, &t) != 0) {
638 fatal("getrlimit failed: %s", strerror(errno));
639 }
640 if (bytes < t.rlim_cur) {
641 t.rlim_cur = bytes;
642 if (setrlimit(RLIMIT_AS, &t) != 0) {
643 fatal("setrlimit failed: %s", strerror(errno));
644 }
645 }
646 }
647
648 #else
649
650 void
limit_virtual_memory(unsigned long)651 limit_virtual_memory(unsigned long) {
652 }
653
654 #endif // !PPL_HAVE_DECL_RLIMIT_AS
655
656 void
process_options(int argc,char * argv[])657 process_options(int argc, char* argv[]) {
658 while (true) {
659 #ifdef PPL_HAVE_GETOPT_H
660 int option_index = 0;
661 const int c = getopt_long(argc, argv, OPTION_LETTERS, long_options,
662 &option_index);
663 #else
664 const int c = getopt(argc, argv, OPTION_LETTERS);
665 #endif
666
667 if (c == EOF) {
668 break;
669 }
670 char* endptr;
671 switch (c) {
672 case 0:
673 break;
674
675 case '?':
676 case 'h':
677 fprintf(stdout, usage_string, argv[0]);
678 exit(0);
679 break;
680
681 case 'R':
682 {
683 const unsigned long MEGA = 1024U*1024U;
684 const long l = strtol(optarg, &endptr, 10);
685 if (*endptr || l < 0) {
686 fatal("a non-negative integer must follow `-R'");
687 }
688 else if (static_cast<unsigned long>(l) > ULONG_MAX/MEGA) {
689 max_bytes_of_virtual_memory = ULONG_MAX;
690 }
691 else {
692 max_bytes_of_virtual_memory = static_cast<unsigned long>(l)*MEGA;
693 }
694 }
695 break;
696
697 case 'o':
698 output_file_name = optarg;
699 break;
700
701 case 'P':
702 piplib_format = false;
703 break;
704
705 case 'p':
706 piplib_format = true;
707 break;
708
709 case 't':
710 print_timings = true;
711 break;
712
713 case 'v':
714 verbose = true;
715 break;
716
717 case 'i':
718 loop_iterations = strtol(optarg, &endptr, 10);
719 if (*endptr || loop_iterations < 1) {
720 fatal("a positive integer must follow `-i'");
721 }
722 break;
723
724 #if defined(USE_PPL)
725
726 case 'V':
727 fprintf(stdout, "%s\n", PPL_VERSION);
728 exit(0);
729 break;
730
731 case 'c':
732 check_file_name = optarg;
733 break;
734
735 #endif
736
737 case 'f':
738 cutting_strategy = PPL::PIP_Problem::CUTTING_STRATEGY_FIRST;
739 break;
740
741 case 'd':
742 cutting_strategy = PPL::PIP_Problem::CUTTING_STRATEGY_DEEPEST;
743 break;
744
745 case 'a':
746 cutting_strategy = PPL::PIP_Problem::CUTTING_STRATEGY_ALL;
747 break;
748
749 case 'F':
750 pivot_row_strategy = PPL::PIP_Problem::PIVOT_ROW_STRATEGY_FIRST;
751 break;
752
753 case 'M':
754 pivot_row_strategy = PPL::PIP_Problem::PIVOT_ROW_STRATEGY_MAX_COLUMN;
755 break;
756
757 default:
758 abort();
759 }
760 }
761
762 if (argc - optind > 1) {
763 // We have multiple input files.
764 fatal("at most one input file is accepted");
765 }
766 // We have one input files.
767 if (optind < argc) {
768 input_file_name = argv[optind];
769 }
770 else {
771 // If no input files have been specified: we will read from standard input.
772 assert(input_file_name == 0);
773 }
774 }
775
776 void
maybe_start_clock()777 maybe_start_clock() {
778 if (print_timings) {
779 start_clock();
780 }
781 }
782
783 void
maybe_print_clock()784 maybe_print_clock() {
785 if (print_timings) {
786 std::cerr << input_file_name << " ";
787 print_clock(std::cerr);
788 std::cerr << std::endl;
789 }
790 }
791
792 int
main(int argc,char * argv[])793 main(int argc, char* argv[]) try {
794 program_name = argv[0];
795
796 #if defined(USE_PPL)
797 if (strcmp(PPL_VERSION, PPL::version()) != 0) {
798 fatal("was compiled with PPL version %s, but linked with version %s",
799 PPL_VERSION, PPL::version());
800 }
801 if (verbose) {
802 std::cerr << "Parma Polyhedra Library version:\n" << PPL::version()
803 << "\n\nParma Polyhedra Library banner:\n" << PPL::banner()
804 << std::endl;
805 }
806 #endif
807
808 // Process command line options.
809 process_options(argc, argv);
810
811 if (max_bytes_of_virtual_memory > 0) {
812 limit_virtual_memory(max_bytes_of_virtual_memory);
813 }
814 // Set up the input and output streams.
815 set_input(input_file_name);
816 set_output(output_file_name);
817
818 // POLYHEDRON_TYPE ph;
819 // Representation rep = read_polyhedron(input(), ph);
820 std::auto_ptr<PIP_Parser> parser;
821 if (piplib_format) {
822 parser.reset(new PIP_PipLib_Parser);
823 }
824 else{
825 parser.reset(new PIP_PolyLib_Parser);
826 }
827 if (!parser->read(*input_stream_p)) {
828 return 1;
829 }
830 maybe_start_clock();
831
832 const PPL::PIP_Problem& pip = parser->problem();
833
834 if (loop_iterations == 1) {
835 // Compute the dual simplex on the problem.
836 pip.solve();
837 // Write the solution.
838 parser->output_solution_tree(*output_stream_p);
839 }
840 else {
841 std::auto_ptr<PPL::PIP_Problem> pip_p;
842 // Perform a time benchmark loop executing the resolution several times.
843 for (long i = 0; i < loop_iterations; ++i) {
844 pip_p.reset(new PPL::PIP_Problem(pip));
845 pip_p->solve();
846 }
847 }
848
849 #if defined(USE_PPL) || defined(USE_PIPLIB)
850 maybe_print_clock();
851 #endif
852
853 return 0;
854 }
855 catch (const std::bad_alloc&) {
856 fatal("out of memory");
857 exit(1);
858 }
859 catch (const std::overflow_error& e) {
860 fatal("arithmetic overflow (%s)", e.what());
861 exit(1);
862 }
863 catch (...) {
864 fatal("internal error: please submit a bug report to ppl-devel@cs.unipr.it");
865 exit(1);
866 }
867