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