aGrUM  0.16.0
lrslib.h
Go to the documentation of this file.
1 #ifndef DOXYGEN_SHOULD_SKIP_THIS
2 
3 /* lrslib.hpp (vertex enumeration using lexicographic reverse search) */
4 #define TITLE "lrslib "
5 #define VERSION "v.6.2 2016.3.28"
6 #define AUTHOR "*Copyright (C) 1995,2016, David Avis avis@cs.mcgill.ca "
7 
8 /* This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
21  */
22 /*Ver 6.1 major change is new lrsnash driver and library coded by Terje
23  * Lensberg */
24 /*Ver 6.0 major change is mplrs wrapper for multithreading coded by Skip
25  * Jordan */
26 /*Ver 5.0 major change is plrs wrapper for multithreading coded by Gary
27  * Roumanis */
28 /*Ver 4.2* library version */
29 /******************************************************************************/
30 /* See http://cgm.cs.mcgill.ca/~avis/C/lrs.html for usage instructions */
31 /******************************************************************************/
32 
33 
34 #ifdef PLRS
35 #include <algorithm>
36 #include <fstream>
37 #include <iostream>
38 #include <sstream>
39 #include <string>
40 #endif
41 
42 
43 #ifdef LRSLONG
44 #define ARITH "lrslong.h" /* lrs long integer arithmetic package */
45 #else
46 #ifdef GMP
47 #define ARITH "lrsgmp.h" /* lrs wrapper for gmp multiple precsion arithmetic */
48 #else
49 #define ARITH "lrsmp.h" /* lrs multiple precsion arithmetic */
50 #define MP
51 #endif
52 #endif
53 
54 #include ARITH
55 
56 // 64 bits for windows (long is 32 bits)
57 #ifdef _MSC_VER
58 typedef __int64 int64_t;
59 typedef unsigned __int64 uint64_t;
60 #else
61 #include <stdint.h>
62 #endif
63 
64 #ifdef SIGNALS
65 #include <signal.h>
66 #include <unistd.h>
67 #define errcheck(s, e) \
68  if ((int64_t)(e) == -1L) { \
69  perror(s); \
70  exit(1); \
71  }
72 #endif
73 
74 #define CALLOC(n, s) xcalloc(n, s, __LINE__, __FILE__)
75 
76 /*********************/
77 /*global constants */
78 /*********************/
79 #define MAX_LRS_GLOBALS 10000L /* number of allocated dictionaries */
80 #define MAXIMIZE 1L /* maximize the lp */
81 #define MINIMIZE 0L /* maximize the lp */
82 #define GE 1L /* constraint is >= */
83 #define EQ 0L /* constraint is linearity */
84 
85 
86 /*************/
87 /* typedefs */
88 /*************/
89 
90 /******************************************************************************/
91 /* Indexing after initialization */
92 /* Basis Cobasis */
93 /* --------------------------------------- ----------------------------- */
94 /* | i |0|1| .... |lastdv|lastdv+1|...|m| | j | 0 | 1 | ... |d-1| d | */
95 /* |-----|+|+|++++++|++++++|--------|---|-| |----|---|---|-----|---|+++++| */
96 /* |B[i] |0|1| .... |lastdv|lastdv+1|...|m| |C[j]|m+1|m+2| ... |m+d|m+d+1| */
97 /* -----|+|+|++++++|++++++|????????|???|?| ----|???|???|-----|???|+++++| */
98 /* */
99 /* Row[i] is row location for B[i] Col[j] is column location for C[j] */
100 /* ----------------------------- ----------------------------- */
101 /* | i |0|1| ..........|m-1|m| | j | 0 | 1 | ... |d-1| d | */
102 /* |-------|+|-|-----------|---|-| |------|---|---|--- |---|++++| */
103 /* |Row[i] |0|1|...........|m-1|m| |Col[j]| 1 | 2 | ... | d | 0 | */
104 /* --------|+|*|***********|***|*| ------|***|***|*****|***|++++| */
105 /* */
106 /* + = remains invariant * = indices may be permuted ? = swapped by pivot */
107 /* */
108 /* m = number of input rows n= number of input columns */
109 /* input dimension inputd = n-1 (H-rep) or n (V-rep) */
110 /* lastdv = inputd-nredundcol (each redundant column removes a dec. var) */
111 /* working dimension d=lastdv-nlinearity (an input linearity removes a slack)
112  */
113 /* obj function in row 0, index 0=B[0] col 0 has index m+d+1=C[d] */
114 /* H-rep: b-vector in col 0, A matrix in columns 1..n-1 */
115 /* V-rep: col 0 all zero, b-vector in col 1, A matrix in columns 1..n */
116 /******************************************************************************/
117 
118 typedef struct lrs_dic_struct /* dynamic dictionary data */
119 {
120  lrs_mp_matrix A;
121  int64_t m; /* A has m+1 rows, row 0 is cost row */
122  int64_t m_A; /* =m or m-d if nonnegative flag set */
123  int64_t d; /* A has d+1 columns, col 0 is b-vector */
124  int64_t d_orig; /* value of d as A was allocated (E.G.) */
125  int64_t lexflag; /* true if lexmin basis for this vertex */
126  int64_t depth; /* depth of basis/vertex in reverse search tree */
127  int64_t i, j; /* last pivot row and column pivot indices */
128  lrs_mp det; /* current determinant of basis */
129  lrs_mp objnum; /* objective numerator value */
130  lrs_mp objden; /* objective denominator value */
131  int64_t * B, *Row; /* basis, row location indices */
132  int64_t * C, *Col; /* cobasis, column location indices */
133  struct lrs_dic_struct *prev, *next;
134 } lrs_dic;
135 
136 typedef struct lrs_dat /* global problem data */
137 {
138  lrs_mp_vector Gcd; /* Gcd of each row of numerators */
139  lrs_mp_vector Lcm; /* Lcm for each row of input denominators */
140 
141  lrs_mp sumdet; /* sum of determinants */
142  lrs_mp Nvolume; /* volume numerator */
143  lrs_mp Dvolume; /* volume denominator */
144  lrs_mp boundn; /* objective bound numerator */
145  lrs_mp boundd; /* objective bound denominator */
146  int64_t unbounded; /* lp unbounded */
147  char fname[100]; /* input file name from line 1 of input */
148 
149  int64_t* inequality; /* indices of inequalities corr. to cobasic ind */
150  /* initially holds order used to find starting */
151  /* basis, default: m,m-1,...,2,1 */
152  int64_t* facet; /* cobasic indices for restart in needed */
153  int64_t* redundcol; /* holds columns which are redundant */
154  int64_t* linearity; /* holds cobasic indices of input linearities */
155  int64_t* minratio; /* used for lexicographic ratio test */
156  int64_t* temparray; /* for sorting indices, dimensioned to d */
157  int64_t *isave, *jsave; /* arrays for estimator, malloc'ed at start */
158  int64_t inputd; /* input dimension: n-1 for H-rep, n for V-rep */
159 
160  int64_t m; /* number of rows in input file */
161  int64_t n; /* number of columns in input file */
162  int64_t lastdv; /* index of last dec. variable after preproc */
163  /* given by inputd-nredundcol */
164  int64_t count[10]; /* count[0]=rays [1]=verts. [2]=base [3]=pivots */
165  /* count[4]=integer vertices */
166 
167  int64_t startcount[5];
168 
169  int64_t deepest; /* max depth ever reached in search */
170  int64_t nredundcol; /* number of redundant columns */
171  int64_t nlinearity; /* number of input linearities */
172  int64_t totalnodes; /* count total number of tree nodes evaluated */
173  int64_t runs; /* probes for estimate function */
174  int64_t seed; /* seed for random number generator */
175  double cest[10]; /* ests: 0=rays,1=vert,2=bases,3=vol,4=int vert */
176  /**** flags ********** */
177  int64_t allbases; /* TRUE if all bases should be printed */
178  int64_t bound; /* TRUE if upper/lower bound on objective given */
179  int64_t countonly; /* TRUE if only count totals should be output */
180  int64_t debug;
181  int64_t dualdeg; /* TRUE if start dictionary is dual degenerate */
182  int64_t etrace; /* turn off debug at basis # strace */
183  int64_t frequency; /* frequency to print cobasis indices */
184  int64_t geometric; /* TRUE if incident vertex prints after each ray */
185  int64_t getvolume; /* do volume calculation */
186  int64_t givenstart; /* TRUE if a starting cobasis is given */
187  int64_t homogeneous; /* TRUE if all entries in column one are zero */
188  int64_t hull; /* do convex hull computation if TRUE */
189  int64_t incidence; /* print all tight inequalities (vertices/rays) */
190  int64_t lponly; /* true if only lp solution wanted */
191  int64_t maxdepth; /* max depth to search to in treee */
192  int64_t maximize; /* flag for LP maximization */
193  int64_t maxoutput; /* if positive, maximum number of output lines */
194  int64_t maxcobases; /* if positive, after maxcobasis unexplored subtrees reported
195  */
196  int64_t minimize; /* flag for LP minimization */
197  int64_t mindepth; /* do not backtrack above mindepth */
198  int64_t nash; /* TRUE for computing nash equilibria */
199  int64_t nonnegative; /* TRUE if last d constraints are nonnegativity */
200  int64_t polytope; /* TRUE for facet computation of a polytope */
201  int64_t printcobasis; /* TRUE if all cobasis should be printed */
202  int64_t printslack; /* TRUE if indices of slack inequal. printed */
203  int64_t truncate; /* TRUE: truncate tree when moving from opt vert*/
204  int64_t verbose; /* FALSE for minimalist output */
205  int64_t restart; /* TRUE if restarting from some cobasis */
206  int64_t strace; /* turn on debug at basis # strace */
207  int64_t voronoi; /* compute voronoi vertices by transformation */
208  int64_t subtreesize; /* in estimate mode, iterates if cob_est >= subtreesize */
209 
210  /* Variables for saving/restoring cobasis, db */
211 
212  int64_t id; /* numbered sequentially */
213  char* name; /* passed by user */
214 
215  int64_t saved_count[3]; /* How often to print out current cobasis */
216  int64_t* saved_C;
217  lrs_mp saved_det;
218  int64_t saved_depth;
219  int64_t saved_d;
220 
221  int64_t saved_flag; /* There is something in the saved cobasis */
222 
223  /* Variables for cacheing dictionaries, db */
224  lrs_dic *Qhead, *Qtail;
225 
226 } lrs_dat, lrs_dat_p;
227 
228 
229 #ifdef PLRS
230 /****************/
231 /* PLRS */
232 /****************/
233 
234 void post_output(const char*, const char*);
235 void plrs_read_dat(lrs_dat* Q, std::ifstream& ff);
236 void plrs_read_dic(lrs_dic* P, lrs_dat* Q, std::ifstream& ff);
237 void plrs_readfacets(lrs_dat* Q, int64_t facet[], string facets);
238 void plrs_readlinearity(lrs_dat* Q, string line);
239 #endif
240 
241 
242 /*******************************/
243 /* functions for external use */
244 /*******************************/
245 extern FILE* lrs_cfp; /* output file for checkpoint information */
246 int64_t
247 lrs_main(int argc,
248  char* argv[]); /* lrs driver, argv[1]=input file, [argc-1]=output file */
249 int64_t
250 redund_main(int argc,
251  char* argv[]); /* redund driver, argv[1]=input file, [2]=output file */
252 lrs_dat*
253 lrs_alloc_dat(const char* name); /* allocate for lrs_dat structure "name" */
254 lrs_dic* lrs_alloc_dic(lrs_dat* Q); /* allocate for lrs_dic structure corr. to Q */
255 int64_t lrs_estimate(lrs_dic* P,
256  lrs_dat* Q); /* get estimates only and returns est number of
257  cobases in subtree */
258 int64_t lrs_read_dat(lrs_dat* Q,
259  int argc,
260  char* argv[]); /* read header and set up lrs_dat */
261 int64_t lrs_read_dic(lrs_dic* P,
262  lrs_dat* Q); /* read input and set up problem and lrs_dic */
263 int64_t lrs_checkbound(
264  lrs_dic* P,
265  lrs_dat* Q); /* TRUE if current objective value exceeds specified bound */
266 int64_t lrs_getfirstbasis(
267  lrs_dic** P_p,
268  lrs_dat* Q,
269  lrs_mp_matrix* Lin,
270  int64_t no_output); /* gets first basis, FALSE if none,P may get changed if
271  lin. space Lin found no_output is TRUE supresses
272  output headers P may get changed if lin. space Lin
273  found */
274 void lrs_getinput(lrs_dic* P,
275  lrs_dat* Q,
276  int64_t* num,
277  int64_t* den,
278  int64_t m,
279  int64_t d); /* reads input matrix b A in lrs/cdd format */
280 int64_t lrs_getnextbasis(lrs_dic** dict_p,
281  lrs_dat* Q,
282  int64_t prune); /* gets next lrs tree basis,
283  FALSE if none backtrack if
284  prune is TRUE */
285 int64_t lrs_getsolution(lrs_dic* P, lrs_dat* Q, lrs_mp_vector output, int64_t col);
286 int64_t lrs_getray(
287  lrs_dic* P, lrs_dat* Q, int64_t col, int64_t comment, lrs_mp_vector output);
288 int64_t lrs_getvertex(lrs_dic* P, lrs_dat* Q, lrs_mp_vector output);
289 void lrs_close(char* name); /* close lrs lib program "name" */
290 int64_t lrs_init(
291  char* name); /* initialize lrslib and arithmetic package for prog "name" */
292 void lrs_lpoutput(lrs_dic* P,
293  lrs_dat* Q,
294  lrs_mp_vector output); /* print LP primal and dual solutions */
295 void lrs_printcobasis(
296  lrs_dic* P,
297  lrs_dat* Q,
298  int64_t col); /* print cobasis for column col(verted or ray) */
299 void lrs_printoutput(lrs_dat* Q, lrs_mp_vector output); /* print output array */
300 void lrs_printrow(char name[],
301  lrs_dat* Q,
302  lrs_mp_vector output,
303  int64_t rowd); /*print row of A matrix in output[0..rowd] */
304 void lrs_printsol(lrs_dic* P,
305  lrs_dat* Q,
306  int64_t col,
307  int64_t comment); /* print out solution from col, comment=
308  0=normal,-1=geometric
309  ray,1..inputd=linearity */
310 void lrs_printtotals(lrs_dic* P, lrs_dat* Q); /* print final totals for lrs */
311 int64_t lrs_set_digits(
312  int64_t dec_digits); /* set lrsmp digits to equiv. of decimal dec_digits */
313 int64_t
314 lrs_solvelp(lrs_dic* P,
315  lrs_dat* Q,
316  int64_t maximize); /* solve primal feas LP:TRUE bounded else FALSE */
317 
318 
319 /*******************************/
320 /* functions for internal use */
321 /*******************************/
322 
323 
324 /*******************************/
325 /* basic dictionary functions */
326 /*******************************/
327 int64_t getabasis(lrs_dic* P,
328  lrs_dat* Q,
329  int64_t order[]); /* Try to find a starting basis */
330 void getnextoutput(lrs_dic* P,
331  lrs_dat* Q,
332  int64_t i,
333  int64_t col,
334  lrs_mp out); /* get A[B[i][col] and copy to out */
335 int64_t ismin(lrs_dic* P,
336  lrs_dat* Q,
337  int64_t r,
338  int64_t s); /* test if A[r][s] is a min ratio for col s */
339 int64_t lexmin(lrs_dic* P,
340  lrs_dat* Q,
341  int64_t col); /* test A to see if current basis is lexmin */
342 void pivot(lrs_dic* P,
343  lrs_dat* Q,
344  int64_t bas,
345  int64_t cob); /* Qpivot routine for array A */
346 int64_t primalfeasible(lrs_dic* P,
347  lrs_dat* Q); /* Do dual pivots to get primal feasibility */
348 int64_t lrs_ratio(lrs_dic* P, lrs_dat* Q, int64_t col); /* find lex min. ratio */
349 int64_t removecobasicindex(lrs_dic* P,
350  lrs_dat* Q,
351  int64_t k); /* remove C[k] from problem */
352 int64_t restartpivots(lrs_dic* P,
353  lrs_dat* Q); /* restart problem from given cobasis */
354 int64_t reverse(lrs_dic* P,
355  lrs_dat* Q,
356  int64_t* r,
357  int64_t s); /* TRUE if B[*r] C[s] is a reverse lex-pos pivot */
358 int64_t
359 selectpivot(lrs_dic* P,
360  lrs_dat* Q,
361  int64_t* r,
362  int64_t* s); /* select pivot indices using lexicographic rule */
363 int64_t
364 dan_selectpivot(lrs_dic* P,
365  lrs_dat* Q,
366  int64_t* r,
367  int64_t* s); /* select pivot indices using dantzig-lex rule */
368 void update(lrs_dic* P,
369  lrs_dat* Q,
370  int64_t* i,
371  int64_t* j); /* update the B,C, LOC arrays after a pivot */
372 void updatevolume(lrs_dic* P,
373  lrs_dat* Q); /* rescale determinant and update the volume */
374 
375 
376 /*******************************/
377 /* other functions using P,Q */
378 /*******************************/
379 int64_t
380 lrs_degenerate(lrs_dic* P,
381  lrs_dat* Q); /* TRUE if the dictionary is primal degenerate */
382 void print_basis(FILE* fp, lrs_dat* Q);
383 void printA(lrs_dic* P,
384  lrs_dat* Q); /* raw print of dictionary, bases for debugging */
385 void pimat(lrs_dic* P,
386  int64_t r,
387  int64_t s,
388  lrs_mp Nt,
389  char name[]); /* print the row r col s of A */
390 int64_t readfacets(lrs_dat* Q, int64_t facet[]); /* read and check facet list */
391 int64_t readlinearity(lrs_dat* Q); /* read and check linearity list */
392 void rescaledet(lrs_dic* P,
393  lrs_dat* Q,
394  lrs_mp Vnum,
395  lrs_mp Vden); /* rescale determinant to get its volume */
396 void rescalevolume(lrs_dic* P,
397  lrs_dat* Q,
398  lrs_mp Vnum,
399  lrs_mp Vden); /* adjust volume for dimension */
400 int64_t lrs_leaf(lrs_dic* P, lrs_dat* Q); /* true if current dictionary is leaf
401  of reverse search tree */
402 
403 
404 /***************************************************/
405 /* Routines for redundancy checking */
406 /***************************************************/
407 int64_t checkredund(lrs_dic* P, lrs_dat* Q); /* solve primal lp to check redund
408  of obj fun. returns TRUE if
409  redundant, else FALSE */
410 int64_t checkcobasic(lrs_dic* P,
411  lrs_dat* Q,
412  int64_t index); /* TRUE if index is cobasic and
413  nondegenerate FALSE if basic, or
414  degen. cobasic, where it will get
415  pivoted out */
416 int64_t checkindex(
417  lrs_dic* P,
418  lrs_dat* Q,
419  int64_t index); /* index=0 non-red.,1 red., 2 input linearity NOTE: row is
420  returned all zero if redundant!! */
421 
422 
423 /***************************************************/
424 /* Routines for caching and restoring dictionaries */
425 /***************************************************/
426 void lrs_free_dic(lrs_dic* P, lrs_dat* Q);
427 void lrs_free_dic2(lrs_dic* P, lrs_dat* Q); /* same as lrs_free_dic but no cache*/
428 void lrs_free_dat(lrs_dat* Q);
429 void copy_dict(lrs_dat* global, lrs_dic* dest, lrs_dic* src);
430 lrs_dic* alloc_memory(lrs_dat* Q);
431 lrs_dic* lrs_getdic(lrs_dat* Q);
432 lrs_dic* resize(lrs_dic* P, lrs_dat* Q);
433 
434 /*******************************/
435 /* utilities */
436 /*******************************/
437 void lprat(const char* name,
438  int64_t Num,
439  int64_t Den); /* Print Num/Den without reducing */
440 int64_t
441 lreadrat(int64_t* Num,
442  int64_t* Den); /* read a rational string and convert to long integers */
443 void reorder(int64_t a[],
444  int64_t range); /* reorder array in increasing order with one
445  misplaced element */
446 void reorder1(int64_t a[],
447  int64_t b[],
448  int64_t newone,
449  int64_t range); /* reorder array a in increasing order with
450  misplaced element newone elements of b go along
451  for the ride */
452 
453 /***************************/
454 /* lp_solve like functions */
455 /***************************/
456 int64_t lrs_solve_lp(lrs_dic* P,
457  lrs_dat* Q); /* solve lp only for given dictionary */
458 void lrs_set_row(
459  lrs_dic* P,
460  lrs_dat* Q,
461  int64_t row,
462  int64_t num[],
463  int64_t den[],
464  int64_t ineq); /* load row i of dictionary from num[]/den[] ineq=GE */
465 void lrs_set_row_mp(
466  lrs_dic* P,
467  lrs_dat* Q,
468  int64_t row,
469  lrs_mp_vector num,
470  lrs_mp_vector den,
471  int64_t ineq); /* same as lrs_set_row except num/den is lrs_mp type */
472 void lrs_set_obj(lrs_dic* P,
473  lrs_dat* Q,
474  int64_t num[],
475  int64_t den[],
476  int64_t max); /* set up objective function with coeffs
477  num[]/den[] max=MAXIMIZE or MINIMIZE */
478 void lrs_set_obj_mp(
479  lrs_dic* P,
480  lrs_dat* Q,
481  lrs_mp_vector num,
482  lrs_mp_vector den,
483  int64_t max); /* same as lrs_set_obj but num/den has lrs_mp type */
484 
485 #endif // DOXYGEN_SHOULD_SKIP_THIS