1 \section{Internal Representation of the
\protect\ai[\tt]{barvinok
} library
}
3 Our
\barvinok/ library is built on top of
\PolyLib/
4 \shortcite{Wilde1993,Loechner1999
}.
5 In particular, it reuses the implementations
7 \shortciteN{Loechner97parameterized
}
8 for computing parametric vertices
10 \shortciteN{Clauss1998parametric
}
11 for computing chamber decompositions.
12 Initially, our library was meant to be a replacement
13 for the algorithm of
\shortciteN{Clauss1998parametric
},
14 also implemented in
\PolyLib/, for computing quasi-polynomials.
15 To ease the transition of application programs we
16 tried to reuse the existing data structures as much as possible.
18 \subsection{Existing Data Structures
}
21 Inside
\PolyLib/ integer values are represented by the
22 \ai[\tt]{Value
} data type.
23 Depending on a configure option, the data type may
24 either by a
32-bit integer, a
64-bit integer
25 or an arbitrary precision integer using
\ai[\tt]{GMP
}.
26 The
\barvinok/ library requires that
\PolyLib/ is compiled
27 with support for arbitrary precision integers.
29 The basic structure for representing (unions of) polyhedra is a
32 typedef struct polyhedron
{
33 unsigned Dimension, NbConstraints, NbRays, NbEq, NbBid;
38 struct polyhedron *next;
41 The attribute
\ai[\tt]{Dimension
} is the dimension
42 of the ambient space, i.e., the number of variables.
43 The attributes
\ai[\tt]{Constraint
}
44 and
\ai[\tt]{Ray
} point to two-dimensional arrays
45 of constraints and generators, respectively.
46 The number of rows is stored in
47 \ai[\tt]{NbConstraints
} and
48 \ai[\tt]{NbRays
}, respectively.
49 The number of columns in both arrays is equal
50 to
\verb!
1+Dimension+
1!.
51 The first column of
\ai[\tt]{Constraint
} is either
52 $
0$ or $
1$ depending on whether the constraint
53 is an equality ($
0$) or an inequality ($
1$).
54 The number of equalities is stored in
\ai[\tt]{NbEq
}.
55 If the constraint is $
\sp a x + c
\ge 0$, then
56 the next columns contain the coefficients $a_i$
57 and the final column contains the constant $c$.
58 The first column of
\ai[\tt]{Ray
} is either
59 $
0$ or $
1$ depending on whether the generator
60 is a line ($
0$) or a vertex or ray ($
1$).
61 The number of lines is stored in
\ai[\tt]{NbBid
}.
62 Let $d$ be the
\ac{lcm
} of the denominators of the coordinates
63 of a vertex $
\vec v$, then the next columns contain
64 $d v_i$ and the final column contains $d$.
65 For a ray, the final column contains $
0$.
66 The field
\ai[\tt]{next
} points to the next polyhedron in
67 the union of polyhedra.
68 It is
\verb+
0+ if this is the last (or only) polyhedron in the union.
69 For more information on this structure, we refer to
\shortciteN{Wilde1993
}.
71 Quasi-polynomials are represented using the
72 \ai[\tt]{evalue
} and
\ai[\tt]{enode
} structures.
74 typedef enum
{ polynomial, periodic, evector
} enode_type;
76 typedef struct _evalue
{
77 Value d; /* denominator */
79 Value n; /* numerator (if denominator !=
0) */
80 struct _enode *p; /* pointer (if denominator ==
0) */
84 typedef struct _enode
{
85 enode_type type; /* polynomial or periodic or evector */
86 int size; /* number of attached pointers */
87 int pos; /* parameter position */
88 evalue arr
[1]; /* array of rational/pointer */
91 If the field
\ai[\tt]{d
} of an
\ai[\tt]{evalue
} is zero, then
92 the
\ai[\tt]{evalue
} is a placeholder for a pointer to
93 an
\ai[\tt]{enode
}, stored in
\ai[\tt]{x.p
}.
94 Otherwise, the
\ai[\tt]{evalue
} is a rational number with
95 numerator
\ai[\tt]{x.n
} and denominator
\ai[\tt]{d
}.
96 An
\ai[\tt]{enode
} is either a
\ai[\tt]{polynomial
}
97 or a
\ai[\tt]{periodic
}, depending on the value
99 The length of the array
\ai[\tt]{arr
} is stored in
\ai[\tt]{size
}.
100 For a
\ai[\tt]{polynomial
},
\ai[\tt]{arr
} contains the coefficients.
101 For a
\ai[\tt]{periodic
}, it contains the values for the different
102 residue classes modulo the parameter indicated by
\ai[\tt]{pos
}.
103 For a polynomial,
\ai[\tt]{pos
} refers to the variable
105 The value of
\ai[\tt]{pos
} is
\verb+
1+ for the first parameter.
106 That is, if the value of
\ai[\tt]{pos
} is
\verb+
1+ and the first
107 parameter is $p$, and if the length of the array is $l$,
108 then in case it is a polynomial, the
109 \ai[\tt]{enode
} represents
111 \verb+arr
[0]+ +
\verb+arr
[1]+ p +
\verb+arr
[2]+ p^
2 +
\cdots +
112 \verb+arr
[l-
1]+ p^
{l-
1}
115 If it is a periodic, then it represents
118 \verb+arr
[0]+,
\verb+arr
[1]+,
\verb+arr
[2]+,
\ldots,
123 Note that the elements of a
\ai[\tt]{periodic
} may themselves
124 be other
\ai[\tt]{periodic
}s or even
\ai[\tt]{polynomial
}s.
125 In our library, we only allow the elements of a
\ai[\tt]{periodic
}
126 to be other
\ai[\tt]{periodic
}s or rational numbers.
127 The chambers and their corresponding quasi-polynomial are
128 stored in
\ai[\tt]{Enumeration
} structures.
130 typedef struct _enumeration
{
131 Polyhedron *ValidityDomain; /* constraints on the parameters */
132 evalue EP; /* dimension = combined space */
133 struct _enumeration *next; /* Ehrhart Polynomial,
134 corresponding to parameter
135 values inside the domain
136 ValidityDomain above */
139 For more information on these structures, we refer to
\shortciteN{Loechner1999
}.
142 Figure~
\ref{f:Loechner
} is a skillful reconstruction
143 of Figure~
2 from
\shortciteN{Loechner1999
}.
144 It shows the contents of the
\ai[\tt]{enode
} structures
145 representing the quasi-polynomial
147 [1,
2]_p p^
2 +
3 p +
\frac 5 2
154 \begin{tabular
}{|c|c|c|
}
156 \multicolumn{2}{|c|
}{type
} & polynomial \\
158 \multicolumn{2}{|c|
}{size
} &
3 \\
160 \multicolumn{2}{|c|
}{pos
} &
1 \\
162 \smash{\lower 6.25pt
\hbox{arr
[0]}} & d &
2 \\
166 \smash{\lower 6.25pt
\hbox{arr
[1]}} & d &
1 \\
170 \smash{\lower 6.25pt
\hbox{arr
[2]}} & d &
0 \\
177 +DR*!DR
\hbox{\strut\hskip 1.5\tabcolsep\phantom{\tt polynomial
}\hskip 1.5\tabcolsep}+C="a"
178 \POS(
60,-
15)*!UL
{\hbox{
180 \begin{tabular
}{|c|c|c|
}
182 \multicolumn{2}{|c|
}{type
} & periodic \\
184 \multicolumn{2}{|c|
}{size
} &
2 \\
186 \multicolumn{2}{|c|
}{pos
} &
1 \\
188 \smash{\lower 6.25pt
\hbox{arr
[0]}} & d &
1 \\
192 \smash{\lower 6.25pt
\hbox{arr
[1]}} & d &
1 \\
199 +UL+<
0.5\tabcolsep,
0pt>*!UL
\hbox{\strut}+CL="b"
201 \POS"box1"+UC*++!D
\hbox{\tt enode
}
202 \POS"box2"+UC*++!D
\hbox{\tt enode
}
204 \caption{The quasi-polynomial $
[1,
2]_p p^
2 +
3 p +
\frac 5 2$.
}
212 The
\ai[\tt]{barvinok
\_options} structure contains various
213 options that influence the behavior of the library.
216 struct barvinok_options
{
217 struct barvinok_stats *stats;
219 /* PolyLib options */
223 /* LLL reduction parameter delta=LLL_a/LLL_b */
227 /* barvinok options */
228 #define BV_SPECIALIZATION_BF
2
229 #define BV_SPECIALIZATION_DF
1
230 #define BV_SPECIALIZATION_RANDOM
0
231 #define BV_SPECIALIZATION_TODD
3
232 int incremental_specialization;
234 unsigned long max_index;
237 int count_sample_infinite;
239 int try_Delaunay_triangulation;
241 #define BV_APPROX_SIGN_NONE
0
242 #define BV_APPROX_SIGN_APPROX
1
243 #define BV_APPROX_SIGN_LOWER
2
244 #define BV_APPROX_SIGN_UPPER
3
245 int polynomial_approximation;
246 #define BV_APPROX_NONE
0
247 #define BV_APPROX_DROP
1
248 #define BV_APPROX_SCALE
2
249 #define BV_APPROX_VOLUME
3
250 #define BV_APPROX_BERNOULLI
4
251 int approximation_method;
252 #define BV_APPROX_SCALE_FAST (
1 <<
0)
253 #define BV_APPROX_SCALE_NARROW (
1 <<
1)
254 #define BV_APPROX_SCALE_NARROW2 (
1 <<
2)
255 #define BV_APPROX_SCALE_CHAMBER (
1 <<
3)
257 #define BV_VOL_LIFT
0
258 #define BV_VOL_VERTEX
1
259 #define BV_VOL_BARYCENTER
2
260 int volume_triangulate;
262 /* basis reduction options */
263 #define BV_GBR_NONE
0
264 #define BV_GBR_GLPK
1
268 /* bernstein options */
269 #define BV_BERNSTEIN_NONE
0
270 #define BV_BERNSTEIN_MAX
1
271 #define BV_BERNSTEIN_MIN -
1
272 int bernstein_optimize;
274 #define BV_BERNSTEIN_FACTORS
1
275 #define BV_BERNSTEIN_INTERVALS
2
276 int bernstein_recurse;
278 #define BV_LP_POLYLIB
0
285 #define BV_HULL_GBR
0
286 #define BV_HULL_HILBERT
1
290 struct barvinok_options *barvinok_options_new_with_defaults();
293 The function
\ai[\tt]{barvinok
\_options\_new\_with\_defaults}
294 can be used to create a
\ai[\tt]{barvinok
\_options} structure
298 \item \PolyLib/ options
302 \item \ai[\tt]{MaxRays
}
304 The value of
\ai[\tt]{MaxRays
} is passed to various
\PolyLib/
305 functions and defines the
306 maximum size of a table used in the
\ai{double description
} computation
307 in the
\PolyLib/ function
\ai[\tt]{Chernikova
}.
308 In earlier versions of
\PolyLib/,
309 this parameter had to be conservatively set
310 to a high number to ensure successful operation,
311 resulting in significant memory overhead.
312 Our change to allow this table to grow
313 dynamically is available in recent versions of
\PolyLib/.
314 In these versions, the value no longer indicates the maximal
315 table size, but rather the size of the initial allocation.
316 This value may be set to
\verb+
0+ or left as set
317 by
\ai[\tt]{barvinok
\_options\_new\_with\_defaults}.
321 \item \ai[\tt]{NTL
} options
325 \item \ai[\tt]{LLL
\_a}
326 \item \ai[\tt]{LLL
\_b}
328 The values used for the
\ai{reduction parameter
}
329 in the call to
\ai[\tt]{NTL
}'s implementation of
\indac{LLL
}.
333 \item \ai[\tt]{barvinok
} specific options
337 \item \ai[\tt]{incremental
\_specialization}
339 Selects the
\ai{specialization
} algorithm to be used.
340 If set to
{\tt 0} then a direct specialization is performed
341 using a random vector.
342 Value
{\tt 1} selects a depth first incremental specialization,
343 while value
{\tt 2} selects a breadth first incremental specialization.
344 The default is selected by the
\ai[\tt]{--enable-incremental
}
345 \ai[\tt]{configure
} option.
346 For more information we refer to~
\citeN[Section~
4.4.3]{Verdoolaege2005PhD
}.
352 \subsection{Data Structures for Quasi-polynomials
}
355 Internally, we do not represent our
\ai{quasi-polynomial
}s
356 as step-polynomials, but, similarly to
\shortciteN{Loechner1999
},
357 as polynomials with periodic numbers for coefficients.
358 However, we also allow our periodic numbers to be represented by
359 fractional parts of degree-$
1$ polynomials rather than
360 an explicit enumeration using the
\ai[\tt]{periodic
} type.
361 By default, the current version of
\barvinok/ uses
362 \ai[\tt]{periodic
}s, but this can be changed through
363 the
\ai[\tt]{--enable-fractional
} configure option.
364 In the latter case, the quasi-polynomial using fractional
365 parts can also be converted to an actual step-polynomial
366 using
\ai[\tt]{evalue
\_frac2floor}, but this is not fully
369 For reasons of compatibility,
%
370 \footnote{Also known as laziness.
}
371 we shoehorned our representations for piecewise quasi-polynomials
372 into the existing data structures.
373 To this effect, we introduced four new types,
374 \ai[\tt]{fractional
},
\ai[\tt]{relation
},
375 \ai[\tt]{partition
} and
\ai[\tt]{flooring
}.
377 typedef enum
{ polynomial, periodic, evector, fractional,
378 relation, partition, flooring
} enode_type;
380 The field
\ai[\tt]{pos
} is not used in most of these
381 additional types and is therefore set to
\verb+-
1+.
383 The types
\ai[\tt]{fractional
} and
\ai[\tt]{flooring
}
384 represent polynomial expressions in a fractional part or a floor respectively.
385 The generator is stored in
\verb+arr
[0]+, while the
386 coefficients are stored in the remaining array elements.
387 That is, an
\ai[\tt]{enode
} of type
\ai[\tt]{fractional
}
390 \verb+arr
[1]+ +
\verb+arr
[2]+ \
{\verb+arr
[0]+\
} +
391 \verb+arr
[3]+ \
{\verb+arr
[0]+\
}^
2 +
\cdots +
392 \verb+arr
[l-
1]+ \
{\verb+arr
[0]+\
}^
{l-
2}
395 An
\ai[\tt]{enode
} of type
\ai[\tt]{flooring
}
398 \verb+arr
[1]+ +
\verb+arr
[2]+
\lfloor\verb+arr
[0]+
\rfloor +
399 \verb+arr
[3]+
\lfloor\verb+arr
[0]+
\rfloor^
2 +
\cdots +
400 \verb+arr
[l-
1]+
\lfloor\verb+arr
[0]+
\rfloor^
{l-
2}
405 The internal representation of the quasi-polynomial
406 $$
\left(
1+
2 \left\
{\frac p
2\right\
}\right) p^
2 +
3 p +
\frac 5 2$$
407 is shown in Figure~
\ref{f:fractional
}.
413 \begin{tabular
}{|c|c|c|
}
415 \multicolumn{2}{|c|
}{type
} & polynomial \\
417 \multicolumn{2}{|c|
}{size
} &
3 \\
419 \multicolumn{2}{|c|
}{pos
} &
1 \\
421 \smash{\lower 6.25pt
\hbox{arr
[0]}} & d &
2 \\
425 \smash{\lower 6.25pt
\hbox{arr
[1]}} & d &
1 \\
429 \smash{\lower 6.25pt
\hbox{arr
[2]}} & d &
0 \\
436 +DR*!DR
\hbox{\strut\hskip 1.5\tabcolsep\phantom{\tt polynomial
}\hskip 1.5\tabcolsep}+C="a"
437 \POS(
60,
0)*!UL
{\hbox{
439 \begin{tabular
}{|c|c|c|
}
441 \multicolumn{2}{|c|
}{type
} & fractional \\
443 \multicolumn{2}{|c|
}{size
} &
3 \\
445 \multicolumn{2}{|c|
}{pos
} & -
1 \\
447 \smash{\lower 6.25pt
\hbox{arr
[0]}} & d &
0 \\
451 \smash{\lower 6.25pt
\hbox{arr
[1]}} & d &
1 \\
455 \smash{\lower 6.25pt
\hbox{arr
[2]}} & d &
1 \\
462 +UL+<
0.5\tabcolsep,
0pt>*!UL
\hbox{\strut}+CL="b"
464 \POS"box2"+UR*!UR
{\hbox{
478 }+CD*!U
{\strut}+C="c"
479 \POS(
60,-
50)*!UL
{\hbox{
481 \begin{tabular
}{|c|c|c|
}
483 \multicolumn{2}{|c|
}{type
} & polynomial \\
485 \multicolumn{2}{|c|
}{size
} &
2 \\
487 \multicolumn{2}{|c|
}{pos
} &
1 \\
489 \smash{\lower 6.25pt
\hbox{arr
[0]}} & d &
1 \\
493 \smash{\lower 6.25pt
\hbox{arr
[1]}} & d &
2 \\
500 +UR-<
0.8\tabcolsep,
0pt>*!UR
\hbox{\strut}+CR="d"
502 \POS"box1"+UC*++!D
\hbox{\tt enode
}
503 \POS"box2"+UC*++!D
\hbox{\tt enode
}
504 \POS"box3"+UC*++!D
\hbox{\tt enode
}
506 \caption{The quasi-polynomial
507 $
\left(
1+
2 \left\
{\frac p
2\right\
}\right) p^
2 +
3 p +
\frac 5 2$.
}
513 The
\ai[\tt]{relation
} type is used to represent
\ai{stride
}s.
514 In particular, if the value of
\ai[\tt]{size
} is
2, then
515 the value of a
\ai[\tt]{relation
} is (in pseudo-code):
517 (value(arr
[0]) ==
0) ? value(arr
[1]) :
0
519 If the size is
3, then the value is:
521 (value(arr
[0]) ==
0) ? value(arr
[1]) : value(arr
[2])
523 The type of
\verb+arr
[0]+ is typically
\ai[\tt]{fractional
}.
525 Finally, the
\ai[\tt]{partition
} type is used to
526 represent piecewise quasi-polynomials.
527 We prefer to encode this information inside
\ai[\tt]{evalue
}s
529 rather than using
\ai[\tt]{Enumeration
}s since we want
530 to perform the same kinds of operations on both quasi-polynomials
531 and piecewise quasi-polynomials.
532 An
\ai[\tt]{enode
} of type
\ai[\tt]{partition
} may not be nested
533 inside another
\ai[\tt]{enode
}.
534 The size of the array is twice the number of ``chambers''.
535 Pointers to chambers are stored in the even slots,
536 whereas pointer to the associated quasi-polynomials
537 are stored in the odd slots.
538 To be able to store pointers to chambers, the
539 definition of
\ai[\tt]{evalue
} was changed as follows.
541 typedef struct _evalue
{
542 Value d; /* denominator */
544 Value n; /* numerator (if denominator >
0) */
545 struct _enode *p; /* pointer (if denominator ==
0) */
546 Polyhedron *D; /* domain (if denominator == -
1) */
550 Note that we allow a ``chamber'' to be a union of polyhedra
551 as discussed in
\citeN[Section~
4.5.1]{Verdoolaege2005PhD
}.
552 Chambers with extra variables, i.e., those of
553 \citeN[Section~
4.6.5]{Verdoolaege2005PhD
},
554 are only partially supported.
555 The field
\ai[\tt]{pos
} is set to the actual dimension,
556 i.e., the number of parameters.
558 \subsection{Operations on Quasi-polynomials
}
561 In this section we discuss some of the more important
562 operations on
\ai[\tt]{evalue
}s provided by the
564 Some of these operations are extensions
565 of the functions from
\PolyLib/ with the same name.
568 void eadd(const evalue *e1,evalue *res);
569 void emul(const evalue *e1, evalue *res);
571 The functions
\ai[\tt]{eadd
} and
\ai[\tt]{emul
} takes
572 two (pointers to)
\ai[\tt]{evalue
}s
\verb+e1+ and
\verb+res+
573 and computes their sum and product respectively.
574 The result is stored in
\verb+res+, overwriting (and deallocating)
575 the original value of
\verb+res+.
576 It is an error if exactly one of
577 the arguments of
\ai[\tt]{eadd
} is of type
\ai[\tt]{partition
}
578 (unless the other argument is
\verb+
0+).
579 The addition and multiplication operations are described
580 in
\citeN[Section~
4.5.1]{Verdoolaege2005PhD
}
581 and~
\citeN[Section~
4.5.2]{Verdoolaege2005PhD
}
584 The function
\ai[\tt]{eadd
} is an extension of the function
585 \ai[\tt]{new
\_eadd} from
\shortciteN{Seghir2002
}.
586 Apart from supporting the additional types from Section~
\ref{a:data
},
587 the new version also additionally imposes an order on the nesting of
588 different
\ai[\tt]{enode
}s.
589 Without such an ordering,
\ai[\tt]{evalue
}s could be constructed
590 representing for example
592 (
0 y^
0 + (
0 x^
0 +
1 x^
1 ) y^
1 ) x^
0 + (
0 y^
0 -
1 y^
1) x^
1
595 which is just a funny way of saying $
0$.
598 void eor(evalue *e1, evalue *res);
600 The function
\ai[\tt]{eor
} implements the
\ai{union
}
601 operation from
\citeN[Section~
4.5.3]{Verdoolaege2005PhD
}. Both arguments
602 are assumed to correspond to indicator functions.
605 evalue *esum(evalue *E, int nvar);
606 evalue *evalue_sum(evalue *E, int nvar, unsigned MaxRays);
608 The function
\ai[\tt]{esum
} has been superseded by
609 \ai[\tt]{evalue
\_sum}.
610 The function
\ai[\tt]{evalue
\_sum} performs the summation
611 operation from
\citeN[Section~
4.5.4]{Verdoolaege2005PhD
}.
612 The piecewise step-polynomial represented by
\verb+E+ is summated
613 over its first
\verb+nvar+ variables.
614 Note that
\verb+E+ must be zero or of type
\ai[\tt]{partition
}.
615 The function returns the result in a newly allocated
617 Note also that
\verb+E+ needs to have been converted
618 from
\ai[\tt]{fractional
}s to
\ai[\tt]{flooring
}s using
619 the function
\ai[\tt]{evalue
\_frac2floor}.
621 void evalue_frac2floor(evalue *e);
623 This function also ensures that the arguments of the
624 \ai[\tt]{flooring
}s are positive in the relevant chambers.
625 It currently assumes that the argument of each
626 \ai[\tt]{fractional
} in the original
\ai[\tt]{evalue
}
627 has a minimum in the corresponding chamber.
630 double compute_evalue(const evalue *e, Value *list_args);
631 Value *compute_poly(Enumeration *en,Value *list_args);
632 evalue *evalue_eval(const evalue *e, Value *values);
634 The functions
\ai[\tt]{compute
\_evalue},
635 \ai[\tt]{compute
\_poly} and
636 \ai[\tt]{evalue
\_eval}
637 evaluate a (piecewise) quasi-polynomial
638 at a certain point. The argument
\verb+list_args+
639 points to an array of
\ai[\tt]{Value
}s that is assumed
641 The
\verb+double+ return value of
\ai[\tt]{compute
\_evalue}
642 is inherited from
\PolyLib/.
645 void print_evalue(FILE *DST, const evalue *e, char **pname);
647 The function
\ai[\tt]{print
\_evalue} dumps a human-readable
648 representation to the stream pointed to by
\verb+DST+.
649 The argument
\verb+pname+ points
650 to an array of character strings representing the parameter names.
651 The array is assumed to be long enough.
654 int eequal(const evalue *e1, const evalue *e2);
656 The function
\ai[\tt]{eequal
} return true (
\verb+
1+) if its
657 two arguments are structurally identical.
658 I.e., it does
{\em not\/
} check whether the two
659 (piecewise) quasi-polynomial represent the same function.
662 void reduce_evalue (evalue *e);
664 The function
\ai[\tt]{reduce
\_evalue} performs some
665 simplifications on
\ai[\tt]{evalue
}s.
666 Here, we only describe the simplifications that are directly
667 related to the internal representation.
668 Some other simplifications are explained in
669 \citeN[Section~
4.7.2]{Verdoolaege2005PhD
}.
670 If the highest order coefficients of a
\ai[\tt]{polynomial
},
671 \ai[\tt]{fractional
} or
\ai[\tt]{flooring
} are zero (possibly
672 after some other simplifications), then the size of the array
673 is reduced. If only the constant term remains, i.e.,
674 the size is reduced to $
1$ for
\ai[\tt]{polynomial
} or to $
2$
675 for the other types, then the whole node is replaced by
677 Additionally, if the argument of a
\ai[\tt]{fractional
}
678 has been reduced to a constant, then the whole node
679 is replaced by its partial evaluation.
680 A
\ai[\tt]{relation
} is similarly reduced if its second
681 branch or both its branches are zero.
682 Chambers with zero associated quasi-polynomials are
683 discarded from a
\ai[\tt]{partition
}.
685 \subsection{Generating Functions
}
687 The representation of
\rgf/s uses
688 some basic types from the
\ai[\tt]{NTL
} library
\shortcite{NTL
}
689 for representing arbitrary precision integers
691 as well as vectors (
\ai[\tt]{vec
\_ZZ}) and matrices (
\ai[\tt]{mat
\_ZZ})
693 We further introduces a type
\ai[\tt]{QQ
} for representing a rational
694 number and use vectors (
\ai[\tt]{vec
\_QQ}) of such numbers.
701 NTL_vector_decl(QQ,vec_QQ);
704 Each term in a
\rgf/ is represented by a
\ai[\tt]{short
\_rat}
709 /* rows: terms in numerator */
714 /* rows: factors in denominator */
719 The fields
\ai[\tt]{n
} and
\ai[\tt]{d
} represent the
720 numerator and the denominator respectively.
721 Note that in our implementation we combine terms
722 with the same denominator.
723 In the numerator, each element of
\ai[\tt]{coeff
} and each row of
\ai[\tt]{power
}
724 represents a single such term.
725 The vector
\ai[\tt]{coeff
} contains the rational coefficients
726 $
\alpha_i$ of each term.
727 The columns of
\ai[\tt]{power
} correspond to the powers
729 In the denominator, each row of
\ai[\tt]{power
}
730 corresponds to the power $
\vec b_
{ij
}$ of a
731 factor in the denominator.
735 shows the internal representation of
737 \frac{\frac 3 2 \, x_0^
2 x_1^
3 +
2 \, x_0^
5 x_1^
{-
7}}
738 { (
1 - x_0 x_1^
{-
3}) (
1 - x_1^
2)
}
744 \begin{minipage
}{0cm
}
748 \begin{tabular
}{|c|c|c|
}
763 }+UC*++!D
\hbox{\tt short
\_rat}
767 \caption{Representation of
769 \left(
\frac 3 2 \, x_0^
2 x_1^
3 +
2 \, x_0^
5 x_1^
{-
7}\right)
770 /
\left( (
1 - x_0 x_1^
{-
3}) (
1 - x_1^
2)
\right)
777 The whole
\rgf/ is represented by a
\ai[\tt]{gen
\_fun}
780 typedef std::set<short_rat *,
781 short_rat_lex_smaller_denominator > short_rat_list;
787 void add(const QQ& c, const vec_ZZ& num, const mat_ZZ& den);
788 void add(short_rat *r);
789 void add(const QQ& c, const gen_fun *gf,
790 barvinok_options *options);
791 void substitute(Matrix *CP);
792 gen_fun *Hadamard_product(const gen_fun *gf,
793 barvinok_options *options);
794 void print(std::ostream& os,
795 unsigned int nparam, char **param_name) const;
796 operator evalue *() const;
797 ZZ coefficient(Value* params, barvinok_options *options) const;
798 void coefficient(Value* params, Value* c) const;
800 gen_fun(Polyhedron *C);
802 gen_fun(const gen_fun *gf);
806 A new
\ai[\tt]{gen
\_fun} can be constructed either as empty
\rgf/ (possibly
807 with a given context
\verb+C+), as a copy of an existing
\rgf/
\verb+gf+, or as
808 constant
\rgf/ with value for the constant term specified by
\verb+c+.
810 The first
\ai[\tt]{gen
\_fun::add
} method adds a new term to the
\rgf/,
811 described by the coefficient
\verb+c+, the numerator
\verb+num+ and the
812 denominator
\verb+den+.
813 It makes all powers in the denominator lexico-positive,
814 orders them in lexicographical order and inserts the new
815 term in
\ai[\tt]{term
} according to the lexicographical
816 order of the combined powers in the denominator.
817 The second
\ai[\tt]{gen
\_fun::add
} method adds
\verb+c+ times
\verb+gf+
820 The method
\ai[\tt]{gen
\_fun::operator evalue *
} performs
821 the conversion from
\rgf/ to
\psp/ explained in
822 \citeN[Section~
4.5.5]{Verdoolaege2005PhD
}.
823 The
\ai[\tt]{Polyhedron
} \ai[\tt]{context
} is the superset
824 of all points where the enumerator is non-zero used during this conversion,
825 i.e., it is the set $Q$ from
\citeN[Equation~
4.31]{Verdoolaege2005PhD
}.
826 If
\ai[\tt]{context
} is
\verb+NULL+ the maximal
827 allowed context is assumed, i.e., the maximal
828 region with lexico-positive rays.
830 The method
\ai[\tt]{gen
\_fun::coefficient
} computes the coefficient
831 of the term with power given by
\verb+params+ and stores the result
833 This method performs essentially the same computations as
834 \ai[\tt]{gen
\_fun::operator evalue *
}, except that it adds extra
835 equality constraints based on the specified values for the power.
837 The method
\ai[\tt]{gen
\_fun::substitute
} performs the
838 \ai{monomial substitution
} specified by the homogeneous matrix
\verb+CP+
839 that maps a set of ``
\ai{compressed parameter
}s''
\shortcite{Meister2004PhD
}
840 to the original set of parameters.
841 That is, if we are given a
\rgf/ $G(
\vec z)$ that encodes the
842 explicit function $g(
\vec i')$, where $
\vec i'$ are the coordinates of
843 the transformed space, and
\verb+CP+ represents the map
844 $
\vec i = A
\vec i' +
\vec a$ back to the original space with coordinates $
\vec i$,
845 then this method transforms the
\rgf/ to $F(
\vec x)$ encoding the
846 same explicit function $f(
\vec i)$, i.e.,
847 $$f(
\vec i) = f(A
\vec i' +
\vec a) = g(
\vec i ').$$
848 This means that the coefficient of the term
849 $
\vec x^
{\vec i
} =
\vec x^
{A
\vec i' +
\vec a
}$ in $F(
\vec x)$ should be equal to the
850 coefficient of the term $
\vec z^
{\vec i'
}$ in $G(
\vec z)$.
854 \sum_i \epsilon_i \frac{\vec z^
{\vec v_i
}}{\prod_j (
1-
\vec z^
{\vec b_
{ij
}})
}
859 \sum_i \epsilon_i \frac{\vec x^
{A
\vec v_i +
\vec a
}}
860 {\prod_j (
1-
\vec x^
{A
\vec b_
{ij
}})
}
864 The method
\ai[\tt]{gen
\_fun::Hadamard
\_product} computes the
865 \ai{Hadamard product
} of the current
\rgf/ with the
\rgf/
\verb+gf+,
866 as explained in
\citeN[Section~
4.5.2]{Verdoolaege2005PhD
}.
868 \subsection{Counting Functions
}
869 \label{a:counting:functions
}
871 Our library provides essentially three different counting functions:
872 one for non-parametric polytopes, one for parametric polytopes
873 and one for parametric sets with existential variables.
874 The old versions of these functions have a ``
\ai[\tt]{MaxRays
}''
875 argument, while the new versions have a more general
876 \ai[\tt]{barvinok
\_options} argument.
877 For more information on
\ai[\tt]{barvinok
\_options}, see Section~
\ref{a:options
}.
880 void barvinok_count(Polyhedron *P, Value* result,
882 void barvinok_count_with_options(Polyhedron *P, Value* result,
883 struct barvinok_options *options);
885 The function
\ai[\tt]{barvinok
\_count} or
886 \ai[\tt]{barvinok
\_count\_with\_options} enumerates the non-parametric
887 polytope
\verb+P+ and returns the result in the
\ai[\tt]{Value
}
888 pointed to by
\verb+result+, which needs to have been allocated
890 If
\verb+P+ is a union, then only the first set in the union will
891 be taken into account.
892 For the meaning of the argument
\verb+NbMaxCons+, see
893 the discussion on
\ai[\tt]{MaxRays
} in Section~
\ref{a:options
}.
895 The function
\ai[\tt]{barvinok
\_enumerate} for enumerating
896 parametric polytopes was meant to be
897 a drop-in replacement of
\PolyLib/'s
\ai[\tt]{Polyhedron
\_Enumerate}
899 Unfortunately, the latter has been changed to
900 accept an extra argument in recent versions of
\PolyLib/ as shown below.
902 Enumeration* barvinok_enumerate(Polyhedron *P, Polyhedron* C,
904 extern Enumeration *Polyhedron_Enumerate(Polyhedron *P,
905 Polyhedron *C, unsigned MAXRAYS, char **pname);
907 The argument
\verb+MaxRays+ has the same meaning as the argument
908 \verb+NbMaxCons+ above.
909 The argument
\verb+P+ refers to the $(d+n)$-dimensional
910 polyhedron defining the parametric polytope.
911 The argument
\verb+C+ is an $n$-dimensional polyhedron containing
912 extra constraints on the parameter space.
913 Its primary use is to indicate how many of the dimensions
914 in
\verb+P+ refer to parameters as any constraint in
\verb+C+
915 could equally well have been added to
\verb+P+ itself.
916 Note that the dimensions referring to the parameters should
918 If either
\verb+P+ or
\verb+C+ is a union,
919 then only the first set in the union will be taken into account.
920 The result is a newly allocated
\ai[\tt]{Enumeration
}.
921 As an alternative we also provide a function
922 (
\ai[\tt]{barvinok
\_enumerate\_ev} or
923 \ai[\tt]{barvinok
\_enumerate\_with\_options}) that returns
926 evalue* barvinok_enumerate_ev(Polyhedron *P, Polyhedron* C,
928 evalue* barvinok_enumerate_with_options(Polyhedron *P,
929 Polyhedron* C, struct barvinok_options *options);
932 For enumerating parametric sets with existentially quantified variables,
933 we provide two functions:
934 \ai[\tt]{barvinok
\_enumerate\_e}
936 \ai[\tt]{barvinok
\_enumerate\_pip}.
938 evalue* barvinok_enumerate_e(Polyhedron *P,
939 unsigned exist, unsigned nparam, unsigned MaxRays);
940 evalue* barvinok_enumerate_e_with_options(Polyhedron *P,
941 unsigned exist, unsigned nparam,
942 struct barvinok_options *options);
943 evalue *barvinok_enumerate_pip(Polyhedron *P,
944 unsigned exist, unsigned nparam, unsigned MaxRays);
945 evalue* barvinok_enumerate_pip_with_options(Polyhedron *P,
946 unsigned exist, unsigned nparam,
947 struct barvinok_options *options);
948 evalue *barvinok_enumerate_scarf(Polyhedron *P,
949 unsigned exist, unsigned nparam,
950 struct barvinok_options *options);
952 The first function tries the simplification rules from
953 \citeN[Section~
4.6.2]{Verdoolaege2005PhD
} before resorting to the method
954 based on
\indac{PIP
} from
\citeN[Section~
4.6.3]{Verdoolaege2005PhD
}.
955 The second function immediately applies the technique from
956 \citeN[Section~
4.6.3]{Verdoolaege2005PhD
}.
957 The argument
\verb+exist+ refers to the number of existential variables,
959 the argument
\verb+nparam+ refers to the number of parameters.
960 The order of the dimensions in
\verb+P+ is:
961 counted variables first, then existential variables and finally
963 The function
\ai[\tt]{barvinok
\_enumerate\_scarf} performs the same
964 computation as the function
\ai[\tt]{barvinok
\_enumerate\_scarf\_series}
965 below, but produces an explicit representation instead of a generating function.
968 gen_fun * barvinok_series(Polyhedron *P, Polyhedron* C,
970 gen_fun * barvinok_series_with_options(Polyhedron *P,
971 Polyhedron* C, barvinok_options *options);
972 gen_fun *barvinok_enumerate_e_series(Polyhedron *P,
973 unsigned exist, unsigned nparam,
974 barvinok_options *options);
975 gen_fun *barvinok_enumerate_scarf_series(Polyhedron *P,
976 unsigned exist, unsigned nparam,
977 barvinok_options *options);
980 \ai[\tt]{barvinok
\_series} or
981 \ai[\tt]{barvinok
\_series\_with\_options} enumerates parametric polytopes
982 in the form of a
\rgf/.
983 The polyhedron
\verb+P+ is assumed to have only
984 revlex-positive rays.
986 The function
\ai[\tt]{barvinok
\_enumerate\_e\_series} computes a
987 generating function for the number of point in the parametric set
988 defined by
\verb+P+ with
\verb+exist+ existentially quantified
989 variables using the
\ai{projection theorem
}, as explained
990 in
\autoref{s:projection
}.
991 The function
\ai[\tt]{barvinok
\_enumerate\_scarf\_series} computes a
992 generating function for the number of point in the parametric set
993 defined by
\verb+P+ with
\verb+exist+ existentially quantified
994 variables, which is assumed to be
2.
995 This function implements the technique of
996 \shortciteN{Scarf2006Neighborhood
} using the
\ai{neighborhood complex
}
997 description of
\shortciteN{Scarf1981indivisibilities:II
}.
998 It is currently restricted to problems with
3 or
4 constraints involving
999 the existentially quantified variables.
1001 \subsection{Auxiliary Functions
}
1003 In this section we briefly mention some auxiliary functions
1004 available in the
\barvinok/ library.
1007 void Polyhedron_Polarize(Polyhedron *P);
1009 The function
\ai[\tt]{Polyhedron
\_Polarize}
1010 polarizes its argument and is explained
1011 in
\citeN[Section~
4.4.2]{Verdoolaege2005PhD
}.
1014 int unimodular_complete(Matrix *M, int row);
1016 The function
\ai[\tt]{unimodular
\_complete} extends
1017 the first
\verb+row+ rows of
1018 \verb+M+ with an integral basis of the orthogonal complement
1019 as explained in Section~
\ref{s:completion
}.
1021 if the resulting matrix is unimodular
\index{unimodular matrix
}.
1024 int DomainIncludes(Polyhedron *D1, Polyhedron *D2);
1026 The function
\ai[\tt]{DomainIncludes
} extends
1027 the function
\ai[\tt]{PolyhedronIncludes
}
1028 provided by
\PolyLib/
1029 to unions of polyhedra.
1030 It checks whether every polyhedron in the union
{\tt D2
}
1031 is included in some polyhedron of
{\tt D1
}.
1034 Polyhedron *DomainConstraintSimplify(Polyhedron *P,
1037 The value returned by
1038 \ai[\tt]{DomainConstraintSimplify
} is a pointer to
1039 a newly allocated
\ai[\tt]{Polyhedron
} that contains the
1040 same integer points as its first argument but possibly
1041 has simpler constraints.
1042 Each constraint $ g
\sp a x
\ge c $
1043 is replaced by $
\sp a x
\ge \ceil{ \frac c g
} $,
1044 where $g$ is the
\ac{gcd
} of the coefficients in the original
1046 The
\ai[\tt]{Polyhedron
} pointed to by
\verb+P+ is destroyed.
1049 Polyhedron* Polyhedron_Project(Polyhedron *P, int dim);
1051 The function
\ai[\tt]{Polyhedron
\_Project} projects
1052 \verb+P+ onto its last
\verb+dim+ dimensions.
1055 Matrix *left_inverse(Matrix *M, Matrix **Eq);
1057 The
\ai[\tt]{left
\_inverse} function computes the left inverse
1058 of
\verb+M+ as explained in Section~
\ref{s:inverse
}.
1060 \sindex{reduced
}{basis
}
1061 \sindex{generalized
}{reduced basis
}
1063 Matrix *Polyhedron_Reduced_Basis(Polyhedron *P,
1064 struct barvinok_options *options);
1066 \ai[\tt]{Polyhedron
\_Reduced\_Basis} computes
1067 a
\ai{generalized reduced basis
} of
{\tt P
}, which
1068 is assumed to be a polytope, using the algorithm
1069 of~
\shortciteN{Cook1993implementation
}.
1070 See
\autoref{s:feasibility
} for more information.
1071 The basis vectors are stored in the rows of the matrix returned.
1074 Vector *Polyhedron_Sample(Polyhedron *P,
1075 struct barvinok_options *options);
1077 \ai[\tt]{Polyhedron
\_Sample} returns an
\ai{integer point
} of
{\tt P
}
1078 or
{\tt NULL
} if
{\tt P
} contains no integer points.
1079 The integer point is found using the algorithm
1080 of~
\shortciteN{Cook1993implementation
} and uses
1081 \ai[\tt]{Polyhedron
\_Reduced\_Basis} to compute the reduced bases.
1082 See
\autoref{s:feasibility
} for more information.
1084 \subsection{\protect\ai[\tt]{bernstein
} Data Structures and Functions
}
1086 The
\bernstein/ library used
\ai[\tt]{GiNaC
} data structures to
1087 represent the data it manipulates.
1088 In particular, a polynomial is stored in a
\ai[\tt]{GiNaC::ex
},
1089 a list of variable or parameter names is stored in a
\ai[\tt]{GiNaC::exvector
},
1090 while the parametric vertices or generators are stored in a
\ai[\tt]{GiNaC::matrix
},
1091 where the rows refer to the generators and the columns to the coordinates
1095 namespace bernstein
{
1096 GiNaC::exvector constructParameterVector(
1097 const char * const *param_names, unsigned nbParams);
1098 GiNaC::exvector constructVariableVector(unsigned nbVariables,
1099 const char *prefix);
1102 The functions
\ai[\tt]{constructParameterVector
}
1103 and
\ai[\tt]{constructVariableVector
} construct a list of variable
1104 names either from a list of
{\tt char *
}s or
1105 by suffixing
{\tt prefix
} with a number starting from
0.
1106 Such lists are needed for the functions
1107 \ai[\tt]{domainVertices
},
\ai[\tt]{bernsteinExpansion
}
1108 and
\ai[\tt]{evalue
\_bernstein\_coefficients}.
1111 namespace bernstein
{
1112 GiNaC::matrix domainVertices(Param_Polyhedron *PP, Param_Domain *Q,
1113 const GiNaC::exvector& params);
1116 The function
\ai[\tt]{domainVertices
} constructs a matrix representing the
1117 generators (in this case vertices) of the
\ai[\tt]{Param
\_Polyhedron} {\tt PP
}
1118 for the
\ai[\tt]{Param
\_Domain} {\tt Q
}, to be used
1119 in a call to
\ai[\tt]{bernsteinExpansion
}.
1120 The elements of
{\tt params
} are used in the resulting matrix
1121 to refer to the parameters.
1124 namespace bernstein
{
1125 GiNaC::lst bernsteinExpansion(const GiNaC::matrix& vert,
1126 const GiNaC::ex& poly,
1127 const GiNaC::exvector& vars,
1128 const GiNaC::exvector& params);
1131 The function
\ai[\tt]{bernsteinExpansion
} computes the
1132 \ai{Bernstein coefficient
}s of the polynomial
\verb+poly+
1133 over the
\ai{parametric polytope
} that is the
\ai{convex hull
}
1134 of the rows in
\verb+vert+. The vectors
\verb+vars+
1135 and
\verb+params+ identify the variables (i.e., the coordinates
1136 of the space in which the parametric polytope lives) and
1137 the parameters, respectively.
1140 namespace bernstein
{
1142 typedef std::pair< Polyhedron *, GiNaC::lst > guarded_lst;
1144 struct piecewise_lst
{
1145 const GiNaC::exvector vars;
1146 std::vector<guarded_lst> list;
1147 /*
0: just collect terms
1148 *
1: remove obviously smaller terms (maximize)
1149 * -
1: remove obviously bigger terms (minimize)
1153 piecewise_lst(const GiNaC::exvector& vars);
1154 piecewise_lst& combine(const piecewise_lst& other);
1156 void simplify_domains(Polyhedron *ctx, unsigned MaxRays);
1157 GiNaC::numeric evaluate(const GiNaC::exvector& values);
1158 void add(const GiNaC::ex& poly);
1163 A
\ai[\tt]{piecewise
\_list} structure represents a list of (disjoint)
1164 polyhedral domains, each with an associated
\ai[\tt]{GiNaC::lst
}
1166 The
\ai[\tt]{vars
} member contains the variable names of the
1167 dimensions of the polyhedral domains.
1169 \ai[\tt]{piecewise
\_lst::combine
} computes the
\ai{common refinement
}
1170 of the polyhedral domains in
\verb+this+ and
\verb+other+ and associates
1171 to each of the resulting subdomains the union of the sets of polynomials
1172 associated to the domains from
\verb+this+ and
\verb+other+ that contain
1174 If the
\verb+sign+s of the
\ai[\tt]{piecewise
\_list}s are not zero,
1175 then the (obviously) redundant elements of these sets are removed
1177 The result is stored in
\verb+this+.
1179 \ai[\tt]{piecewise
\_lst::maximize
} removes polynomials from domains that evaluate
1180 to a value that is smaller than or equal to the value of some
1181 other polynomial associated to the same domain for each point in the domain.
1183 \ai[\tt]{piecewise
\_lst::evaluate
} ``evaluates'' the
\ai[\tt]{piecewise
\_list}
1184 by looking for the domain (if any) that contains the point given by
1185 \verb+values+ and computing the maximal value attained by any of the
1186 associated polynomials evaluated at that point.
1188 \ai[\tt]{piecewise
\_lst::add
} adds the polynomial
\verb+poly+
1189 to each of the polynomial associated to each of the domains.
1191 \ai[\tt]{piecewise
\_lst::simplify
\_domains} ``simplifies'' the domains
1192 by removing the constraints that are implied by the constraints
1193 in
\verb+ctx+, basically by calling
\PolyLib/'s
1194 \ai[\tt]{DomainSimplify
}. Note that you should only do this
1195 at the end of your computation. In particular, you do not
1196 want to call this method before calling
1197 \ai[\tt]{piecewise
\_lst::maximize
}, since this method will then
1198 have less information on the domains to exploit.
1202 namespace barvinok
{
1203 bernstein::piecewise_lst *evalue_bernstein_coefficients(
1204 bernstein::piecewise_lst *pl_all, evalue *e,
1205 Polyhedron *ctx, const GiNaC::exvector& params);
1206 bernstein::piecewise_lst *evalue_bernstein_coefficients(
1207 bernstein::piecewise_lst *pl_all, evalue *e,
1208 Polyhedron *ctx, const GiNaC::exvector& params,
1209 barvinok_options *options);
1212 The
\ai[\tt]{evalue
\_bernstein\_coefficients} function will compute the
1213 \ai{Bernstein coefficient
}s of the piecewise parametric polynomial stored in the
1214 \ai[\tt]{evalue
} \verb+e+.
1215 The
\verb+params+ vector specifies the names to be used for the parameters,
1216 while the context
\ai[\tt]{Polyhedron
} \verb+ctx+ specifies extra constraints
1218 The dimension of
\verb+ctx+ needs to be the same as the length of
\verb+params+.
1219 The
\ai[\tt]{evalue
} \verb+e+ is assumed to be of type
\ai[\tt]{partition
}
1220 and each of the domains in this
\ai[\tt]{partition
} is interpreted
1221 as a parametric polytope in the given parameters. The procedure
1222 will compute the
\ai{Bernstein coefficient
}s of the associated polynomial
1223 over each such parametric polytope.
1224 The resulting
\ai[\tt]{bernstein::piecewise
\_lst} collects the
1225 Bernstein coefficients over all parametric polytopes in
\verb+e+.
1226 If
\verb+pl_all+ is not
\verb+NULL+ then this list will be combined
1227 with the list computed by calling
\ai[\tt]{piecewise
\_lst::combine
}.
1228 If
\ai[\tt]{bernstein
\_optimize} is set to
\ai[\tt]{BV
\_BERNSTEIN\_MAX}
1229 in
\verb+options+, then this combination will remove obviously
1230 redundant Bernstein coefficients with respect to upper bound computation
1231 and similarly for
\ai[\tt]{BV
\_BERNSTEIN\_MIN}.
1232 The default (
\ai[\tt]{BV
\_BERNSTEIN\_NONE}) is to only remove duplicate
1233 Bernstein coefficients.