"implement" eor
[barvinok.git] / ehrhartpolynom.h
blob5f18c0e60b47f0dec7a97dcc9e67303f667cbc4b
1 //-*-c++-*-
2 /***************************************************************************
3 ehrhartpolynom.h - description
4 -------------------
5 begin : Fri 23 Nov 2001
6 copyright : (C) 2001 by Kristof Beyls
7 email : Kristof.Beyls@elis.rug.ac.be
8 ***************************************************************************/
10 #ifndef EHRHARTPOLYNOM_H
11 #define EHRHARTPOLYNOM_H
13 #include <set>
14 #include <map>
15 #include <string>
16 #include <deque>
18 #define swap omega_swap
19 #define min omega_min
20 #define max omega_max
21 #define gcd omega_gcd
22 #include <omega.h>
23 #undef gcd
24 #undef swap
25 #undef min
26 #undef max
28 #include <gmp.h>
29 #include <assert.h>
31 extern "C" {
32 #include <polylib/polylibgmp.h>
33 #include <polylib/ehrhart.h>
36 using namespace std;
37 /** class PeriodicNumber represents a multidimensional
38 * periodic number. For more definition and more details
39 * about periodic numbers: see "Counting Solutions to Linear
40 * and Nonlinear Constraints through Ehrhart Polynomials:
41 * Applications to Analyze and Transform Scientific Programs",
42 * By Philippe CLAUSS, in tenth ACM International Conference
43 * on Supercomputing, May 1996
45 class PeriodicNumber {
46 friend class EhrhartPolynom;
47 /// parameter_names contains the ordered names of the parameters
48 std::set<string> parameter_names;
49 /// period is the period of the variable
50 map<string,int> period;
51 /** data contains the multi-dimensional matrix containing
52 * the value's in the periodic number. The data
53 * is layed out column-major, with the dimensions
54 * of the matrix ordered with the alphabetical order
55 * of the corresponding parameter names.
57 Value* data;
58 /** stride contains the stride in the data array between
59 * 2 consecutive elements of parameter p.
60 * e.g. if the parameters are "a" and "b", and the strides
61 * are 3 and 4;
62 * stride["a"] = 1 and stride["b"] = 3.
64 map<string,unsigned long> stride;
65 unsigned long datasize;
67 public:
68 /** @param parameter_names contains the names of the
69 * parameters.
70 * @param period contains the periods of the different
71 * parameters.
73 PeriodicNumber(const std::set<string>& _parameter_names,
74 const map<string, int>& _period)
75 : parameter_names(_parameter_names), period(_period)
77 unsigned long datasize = 1;
78 for(map<string,int>::const_iterator i=period.begin();
79 i!=period.end(); i++) {
80 stride[(*i).first] = datasize;
81 datasize*=(*i).second;
83 data = new Value[datasize];
84 for(unsigned i=0;i<datasize;i++) {
85 value_init(data[i]);
86 value_set_si(data[i] , 0);
88 this->datasize = datasize;
90 PeriodicNumber() {
91 parameter_names.insert("");
92 period[""]=1;
93 datasize=1;
94 data = new Value[datasize];
95 value_init(data[0]);
96 value_set_si(data[0],0);
97 stride[""]=1;
99 PeriodicNumber(const Value t) {
100 parameter_names.insert("");
101 period[""]=1;
102 datasize=1;
103 data = new Value[datasize];
104 value_init(data[0]);
105 value_assign(data[0],t);
106 stride[""]=1;
108 PeriodicNumber(const PeriodicNumber& pn)
109 : parameter_names(pn.parameter_names), period(pn.period),
110 stride(pn.stride), datasize(pn.datasize)
112 data = new Value[datasize];
113 for(unsigned i=0;i<datasize; i++) {
114 value_init(data[i]);
115 value_assign(data[i], pn.data[i]);
118 memcpy(data, pn.data, sizeof(Value)*datasize);
121 PeriodicNumber& operator=(const PeriodicNumber& pn) {
122 if (*this==pn)
123 return *this;
124 if (data!=0) {
125 for(unsigned i=0; i<datasize; i++)
126 value_clear(data[i]);
128 delete[] data;
129 parameter_names=pn.parameter_names;
130 period=pn.period;
131 stride=pn.stride;
132 datasize=pn.datasize;
134 data = new Value[datasize];
135 for(unsigned i=0;i<datasize; i++) {
136 value_init(data[i]);
137 value_assign(data[i], pn.data[i]);
139 /* memcpy(data, pn.data, sizeof(Value)*datasize); */
140 return *this;
142 bool is_zero() const {
143 for(unsigned long i=0;i<datasize;i++)
144 if (value_notzero_p(data[i]))
145 return false;
146 return true;
148 bool operator==(const PeriodicNumber& pn) const {
149 bool t1 = (parameter_names==pn.parameter_names &&
150 period==pn.period);
151 if (!t1)
152 return false;
153 assert(stride==pn.stride);
154 assert(datasize==pn.datasize);
155 for(unsigned i=0;i<datasize; i++)
156 if (value_ne( data[i], pn.data[i]))
157 return false;
158 return true;
160 return (0==memcmp(data, pn.data, datasize*sizeof(Value)));
163 inline bool operator!=(const PeriodicNumber& pn) const { return !((*this)==pn); }
164 // PeriodicNumber() : data(0) {}
165 ~PeriodicNumber() {
166 for(unsigned i=0;i<datasize; i++)
167 value_clear(data[i]);
168 delete[] data;
170 int dim() const {
171 assert(period.size()==parameter_names.size());
172 return period.size();
174 /** operator[] returns the Value which correspends to the index
175 * @param index The index in the multidimensional matrix,
176 * representing the multi-periodic number.
178 Value& operator[](const map<string, int>& index);
179 const Value& operator[](const map<string, int>& index) const;
180 /** multiply all the values in the periodic number with v */
181 PeriodicNumber operator*(const Value v) const;
182 /** find the gcd of all the values in the periodic number */
183 void get_gcd(Value& v) const;
184 /** divide all the values in the periodic number by v.
185 * The gcd of all the values should be a multiple of v.*/
186 void divide_by(const Value v);
187 /* Calculate the product of 2 periodic numbers.
188 * e.g. product of [1,2]_p and [5,6]_q
189 * is [ 5 6 ]
190 * [ 10 12]_pq
192 PeriodicNumber operator*(const PeriodicNumber& pn) const;
193 PeriodicNumber operator+(const PeriodicNumber& pn) const;
194 bool smaller_than(const PeriodicNumber& pn) const;
195 string to_string() const;
196 double to_double() const;
197 inline operator string() const { return to_string(); }
198 ::evalue to_evalue(const deque<string>& parameter_names) const;
199 int get_period(const string& name) const {
200 map<string,int>::const_iterator i=period.find(name);
201 assert(i!=period.end());
202 return (*i).second;
204 bool has_param(const string& name) const;
205 std::set<string> get_params() const {
206 std::set<string> result;
207 for(map<string,int>::const_iterator i=period.begin();
208 i!=period.end(); i++)
209 result.insert((*i).first);
210 assert(result == parameter_names);
211 return result;
215 /** class EhrhartPolynom is PolyAst's own representation of
216 * an Ehrhart polynomial. The first reason to create this
217 * representation is to allow an easy algorithm to add up 2
218 * Ehrhart Polynomials, since the eadd-function in polylib4.19
219 * doesn't handle all cases.
221 class EhrhartPolynom {
222 public:
223 struct periodic_rational {
224 PeriodicNumber first;
225 Value second;
226 periodic_rational(const PeriodicNumber& pn, const Value v) {
227 first=pn;
228 value_init(second);
229 value_assign(second, v);
231 periodic_rational() {
232 value_init(second);
234 ~periodic_rational() {
235 value_clear(second);
237 periodic_rational(const periodic_rational& pr) {
238 first = pr.first;
239 value_init(second);
240 value_assign(second, pr.second);
242 periodic_rational& operator=(const periodic_rational& pr) {
243 if (&pr == this)
244 return (*this);
245 first = pr.first;
246 value_assign(second, pr.second);
247 return (*this);
250 /** data represents the Ehrhart polynomial. The first part
251 * of the pair in the map represents the coefficients of the
252 * parameters. The second part represents the coefficient,
253 * which is a periodic number.
254 * e.g.
255 * \f$2x^2y+ 2/3 y^2-z\f$ is represented as
256 * ({(x,2),(y,1)},(2,1)), ({(y,2)},(2,3)), ({(z,1)},(-1,1)).
258 map<map<string, int>, periodic_rational> data;
259 /** simplify removes the terms with coefficient 0
260 * and removes the exponents with power 0.
262 void simplify();
263 public:
264 /** Initialization of EhrhartPolynom from a Polylib representation
265 of the Ehrhart Polynomial. */
266 EhrhartPolynom(const ::evalue* e, const deque<string>& parameter_names);
267 /** Initialization to zero. */
268 EhrhartPolynom() {
269 Value val, one;
270 value_init(val);
271 value_set_si(val, 0);
272 value_init(one);
273 value_set_si(one, 1);
274 map<string,int> exponent;
275 PeriodicNumber pn(val);
276 periodic_rational pr(pn, one);
277 data[exponent] = pr;
278 value_clear(val);
279 value_clear(one);
281 /** Initialization to constant value. */
282 EhrhartPolynom(long cst) {
283 Value val, one;
284 value_init(val);
285 value_set_si(val, cst);
286 value_init(one);
287 value_set_si(one, 1);
288 map<string,int> exponent;
289 PeriodicNumber pn(val);
290 periodic_rational pr(pn, one);
291 data[exponent] = pr;
292 value_clear(val);
293 value_clear(one);
295 /** single-term polynomial. */
296 EhrhartPolynom(const map<string,int>& exponent,
297 const periodic_rational& coef) {
298 data[exponent] = coef;
299 simplify();
301 /** single-term polynomial. */
302 EhrhartPolynom(const map<string,int>& exponent,
303 const pair<PeriodicNumber, Value>& coef) {
304 data[exponent] = periodic_rational(coef.first, coef.second);
305 simplify();
307 bool operator==(const EhrhartPolynom& ep) const;
308 inline bool operator!=(const EhrhartPolynom& ep) const { return !((*this)==ep); }
309 bool smaller_than(const EhrhartPolynom& ep) const;
310 ~EhrhartPolynom();
311 EhrhartPolynom& operator=(const EhrhartPolynom& e1)
313 if (this==&e1)
314 return (*this);
316 for(map<map<string, int>, periodic_rational >::iterator
317 i=data.begin(); i!=data.end(); i++)
318 value_clear((*i).second.second);
320 data.clear();
321 for(map<map<string, int>, periodic_rational>::const_iterator
322 i=e1.data.begin(); i!=e1.data.end(); i++) {
324 Value val;
325 value_init(val);
326 value_assign(val, (*i).second.second);
327 pair<map<string, int>, pair<PeriodicNumber, Value> > new_record=(*i);
328 new_record.second.second = val;
329 data.insert(new_record);
331 data[(*i).first] = (*i).second;
333 return (*this);
335 /** operator+ adds up the this polynomial and polynomial e1. */
336 EhrhartPolynom operator+(const EhrhartPolynom& e1) const;
337 /** operator+= adds up the polynomial e1 to this polynomial. */
338 EhrhartPolynom operator+=(const EhrhartPolynom& e1) {
340 data = ((*this) + e1).data;
342 EhrhartPolynom sum = (*this) + e1;
343 (*this) = sum;
344 return (*this);
346 /** operator* multiplies the this polynomial and polynomial e1. */
347 EhrhartPolynom operator*(const EhrhartPolynom& e1) const;
348 /** operator/ divides by constant. */
349 EhrhartPolynom operator/(const Value v) const;
350 /** operator*= multiplies this polynomial with polynomial e1. */
351 EhrhartPolynom operator*=(const EhrhartPolynom& e1) {
352 EhrhartPolynom prod = (*this) * e1;
353 (*this) = prod;
354 return (*this);
356 ::evalue to_evalue(const deque<string>& parameter_names) const;
357 double to_double() const;
358 string to_string() const;
359 inline operator string() const { return to_string(); }
360 bool contains_parameters() const;
362 /** subst_var substitutes variable @a var in the polynomial
363 with the expression encoded in @a subtitution.
364 @param subtitution is a affine function of variables
365 occuring in the polynomial, minus the substituted variable
366 @a var.
368 EhrhartPolynom subst_var(const string& var,
369 const map<string, int>& substitution,
370 const int divisor=1) const;
371 #if 0
373 * equal_in_domain tries to find out if this polynomial and ep2 are
374 * equal in the domain. e.g. (n-i in domain i=1) and (i-1 in domain
375 * i=n) are equal (they both evaluate to n-1).
376 * @param ep1 the first Ehrhart polynomial.
377 * @param ep2 the second Ehrhart polynomial.
378 * @param domain1 the domain corresponding to ep1.
379 * @param domain2 the domain corresponding to ep2.
380 * @return a null pointer if the polynomials are not equal in the
381 * domain, otherwise a pointer to a simplified EhrhartPolynomial
382 * is returned. In the example above, n-1 would be returned.
384 static EhrhartPolynom* equal_in_domain
385 (const EhrhartPolynom& ep1,
386 const EhrhartPolynom& ep2,
387 const ::Relation& domain1,
388 const ::Relation& domain2);
389 #endif
391 /** struct affine represents an Ehrhart Polynomial as a std::set of
392 * affine functions, if possible. This is only possible if the
393 * polynomial is univariate, with maximum power 1.
395 struct affine {
396 /** period indicates the period of the different parameters in
397 the Ehrhart polynomial. */
398 map<string,int> period;
399 /** @c offset[i] contains the constraints under which @c polynomial[i]
400 and @c denumerator[i] are legal. e.g. when @c offset[i] equals
401 {("a",2),("b",0)} then @c polynomial[i] and @c denumerator[i] are
402 legal iff
404 a \textrm{ mod \tt\ period[}a\textrm{\tt ] } = 2 \wedge
405 b \textrm{ mod \tt\ period[}b\textrm{\tt ] } = 0
408 deque<map<string,int> > offset;
409 /** @c polynomial[i] indicates the polynomial */
410 deque<map<string,int> > polynomial;
411 /** @c denumerator[i] indicates the denumerator, the polynomial should
412 be divided with. */
413 deque<int> denumerator;
414 unsigned size() const {
415 assert(offset.size()==polynomial.size());
416 assert(denumerator.size()==offset.size());
417 return offset.size();
419 string to_string() const;
423 * get_affine_polynomials returns the Ehrhart polynomials as a std::set
424 * of affine functions when possible. If not possible, it returns
425 * the null pointer.
427 struct affine* get_affine_polynomials() const;
430 * get_AST_representation returns an PolyAstNode representation of
431 * the polynom.
433 #if 0
434 /* KB november 2003: only usefull in PolyAST */
435 polyast::Expression* get_AST_representation() const;
436 #endif
437 private:
438 evalue translate_one_term(const deque<string>& parameter_names,
439 const deque<string>& left_over_var_names,
440 const std::set<map<string, int> >& terms) const;
444 #endif