minor extra merge
[barvinok.git] / ehrhartpolynom.cpp
blobb2990ff7d867c2d6d5491566f389752214d737bd
1 #include "debug.h"
2 #include "ehrhartpolynom.h"
3 #include <iostream>
4 #include <algorithm>
5 #if 0
6 #include "polylib_tools.h"
7 #include "omega_tools.h"
8 #endif
10 // only legal if value==GMP!!
11 #if defined(GNUMP)
12 #define value_to_str(str, str2, val) { str = mpz_get_str(str2,10,(val)); }
13 #define value_gcd(ref, val1, val2) (mpz_gcd((ref),(val1),(val2)))
14 #define value_lcm(ref, val1, val2) (mpz_lcm((ref),(val1),(val2)))
15 #endif
17 static long gcd(long a, long b)
19 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
20 cout<<"gcd("<<a<<", "<<b<<")=";
22 long result;
23 while (a!=0) {
24 result = b%a;
25 b=a;
26 a=result;
28 result = (b<0)?(-b):b;
29 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
30 cout<<result<<endl;
32 return result;
35 static long lcm(long a, long b)
37 long result=(a*b)/gcd(a,b);
38 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
39 cout<<"lcm("<<a<<", "<<b<<")="<<(long)result<<endl;
41 return (long) result;
44 string int2string(int i)
46 char buf[100];
47 buf[99]='\0';
48 char* cur=&buf[99];
49 bool negative=false;
50 if (i==0) return "0";
51 if (i<0) {
52 negative=true;
53 i=-i;
55 while(i!=0) {
56 *--cur = i%10+'0';
57 i /= 10;
59 if (negative) *--cur = '-';
60 return string(cur);
64 char** get_pname(const deque<string>& parameters)
66 char** result = new char*[parameters.size()];
67 for(unsigned i=0;i<parameters.size();i++) {
68 result[i] = new char[parameters[i].size()+1];
69 strcpy(result[i], parameters[i].c_str());
71 return result;
74 void delete_pname(char** pname, const deque<string>& parameters)
76 for(unsigned i=0;i<parameters.size();i++)
77 delete[] pname[i];
78 delete[] pname;
83 string value2string(const Value v) {
84 char* str=0;
85 value_to_str(str, str, v);
86 string result=str;
87 free(str);
88 return result;
92 inline Value& PeriodicNumber::operator[](const map<string, int>& _index) {
93 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=4) {
94 cout<<"in PeriodicNumber::operator[]"<<endl;
95 cout<<"_index=";
96 for(map<string, int>::const_iterator i=_index.begin();
97 i!=_index.end(); i++)
98 cout<<"("<<(*i).first<<", "<<(*i).second<<") ";
99 cout<<endl;
101 unsigned long index=0;
102 for(map<string,int>::const_iterator i=_index.begin();
103 i!=_index.end(); i++) {
104 map<string, unsigned long>::const_iterator j=stride.find((*i).first);
105 assert(j!=stride.end());
106 index += (*j).second * (*i).second;
108 assert(index>=0);
109 assert(index<datasize);
110 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=4) {
111 cout<<"index="<<index<<endl;
112 cout<<"data[index]="<<value2string(data[index])<<endl;
114 return data[index];
117 inline const Value& PeriodicNumber::operator[]
118 (const map<string, int>& _index) const
120 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=4) {
121 cout<<"in PeriodicNumber::operator[] const"<<endl;
122 cout<<"_index=";
123 for(map<string, int>::const_iterator i=_index.begin();
124 i!=_index.end(); i++)
125 cout<<"("<<(*i).first<<", "<<(*i).second<<") ";
126 cout<<endl;
128 unsigned long index=0;
129 for(map<string,int>::const_iterator i=_index.begin();
130 i!=_index.end(); i++) {
131 map<string, unsigned long>::const_iterator j=stride.find((*i).first);
132 assert(j!=stride.end());
133 index += (*j).second * (*i).second;
135 assert(index>=0);
136 assert(index<datasize);
137 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=4) {
138 cout<<"index="<<index<<endl;
139 cout<<"data[index]="<<value2string(data[index])<<endl;
141 return data[index];
144 static long gcd(long a, long b)
146 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
147 cout<<"gcd("<<a<<", "<<b<<")=";
149 long result;
150 while (a!=0) {
151 result = b%a;
152 b=a;
153 a=result;
155 result = (b<0)?(-b):b;
156 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
157 cout<<result<<endl;
159 return result;
163 static long lcm(long a, long b)
165 long result=(a*b)/gcd(a,b);
166 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
167 cout<<"lcm("<<a<<", "<<b<<")="<<(long)result<<endl;
169 return (long) result;
173 /** operator+ adds up two periodic numbers \f$pn_1\f$ and
174 * \f$pn_2\f$. The following algorithm is used: The parameters in the
175 * result equals the union of the parameters in the two periodic
176 * numbers to be counted together. The periods of any parameter
177 * \f$p\f$ is the least common multiple of the period of the
178 * parameter in \f$pn_1\f$ and \f$pn_2\f$. If the parameter doesn't
179 * occur in one of \f$pn_1\f$ and \f$pn_2\f$, its period is taken is
180 * being one in \f$pn_1\f$ or \f$pn_2\f$. After this step, the
181 * values in the matrix are filled in, being the sum of the
182 * corresponding values in \f$pn_1\f$ and \f$pn_2\f$.*/
183 PeriodicNumber PeriodicNumber::operator+(const PeriodicNumber& pn2) const
185 const PeriodicNumber& pn1=(*this);
186 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
187 cout<<"In PeriodicNumber::operator+:"<<endl;
188 cout<<"pn1="<<pn1.to_string()<<endl;
189 cout<<"pn2="<<pn2.to_string()<<endl;
191 set<string> parameters=pn1.parameter_names;
192 map<string, int> period;
193 for(set<string>::const_iterator i=pn2.parameter_names.begin();
194 i!=pn2.parameter_names.end(); i++)
195 parameters.insert(*i);
197 for(set<string>::const_iterator i=parameters.begin();
198 i!=parameters.end(); i++) {
199 bool param_in_pn1 =
200 (pn1.parameter_names.find(*i)!=pn1.parameter_names.end());
201 bool param_in_pn2 =
202 (pn2.parameter_names.find(*i)!=pn2.parameter_names.end());
203 if (param_in_pn1 && param_in_pn2) {
204 map<string, int>::const_iterator j=pn1.period.find(*i);
205 assert(j!=pn1.period.end());
206 map<string, int>::const_iterator k=pn2.period.find(*i);
207 assert(k!=pn2.period.end());
208 period[*i] = lcm((*j).second, (*k).second);
209 } else if (param_in_pn1) {
210 map<string, int>::const_iterator j=pn1.period.find(*i);
211 assert(j!=pn1.period.end());
212 period[*i] = (*j).second;
213 } else if (param_in_pn2) {
214 map<string, int>::const_iterator j=pn2.period.find(*i);
215 assert(j!=pn2.period.end());
216 period[*i] = (*j).second;
217 } else assert(0);
220 PeriodicNumber result(parameters, period);
222 deque<unsigned long> strides2;
223 for(map<string, unsigned long>::const_iterator i=result.stride.begin();
224 i!=result.stride.end(); i++)
225 strides2.push_back((*i).second);
226 strides2.push_back(result.datasize);
227 // now fill in the correct values.
228 Value tmp;
229 value_init(tmp);
230 for(unsigned long i=0;i<result.datasize;i++) {
231 // find out which period-values for which parameters
232 // map to data[i].
233 map<string, int> index;
234 int param_nr=0;
235 for(set<string>::const_iterator j=parameters.begin();
236 j!=parameters.end(); j++, param_nr++) {
237 index[*j] = (i%(strides2[param_nr+1])) / strides2[param_nr];
239 value_set_si(tmp, 0);
240 map<string, int> pn1_index;
241 map<string, int> pn2_index;
242 for(map<string, int>::const_iterator j=index.begin();j!=index.end(); j++) {
243 if (pn1.parameter_names.find((*j).first)==pn1.parameter_names.end())
244 continue;
245 map<string, int>::const_iterator periodd=pn1.period.find((*j).first);
246 assert(periodd!=pn1.period.end());
247 pn1_index[(*j).first] = (*j).second % (*periodd).second;
249 for(map<string, int>::const_iterator j=index.begin();j!=index.end(); j++) {
250 if (pn2.parameter_names.find((*j).first)==pn2.parameter_names.end())
251 continue;
252 map<string, int>::const_iterator periodd=pn2.period.find((*j).first);
253 assert(periodd!=pn2.period.end());
254 pn2_index[(*j).first] = (*j).second % (*periodd).second;
257 value_addto(tmp, tmp, pn1[pn1_index]);
258 value_addto(tmp, tmp, pn2[pn2_index]);
259 value_assign(result[index] , tmp);
261 value_clear(tmp);
263 // if the periodic number has parameters (i.e. not constant coef),
264 // then "" should not occur as parameter!
265 if (result.parameter_names.find("") != result.parameter_names.end()) {
266 assert(result.period[""] == 1);
267 result.parameter_names.erase("");
268 result.period.erase("");
269 result.stride.erase("");
272 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
273 cout<<"In PeriodicNumber::operator+ result of addition is:"<<endl;
274 cout<<result.to_string()<<endl;
277 return result;
280 PeriodicNumber PeriodicNumber::operator*(const ::Value v) const
282 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
283 cout<<"In PeriodicNumber::operator*(value v):"<<endl;
284 cout<<"v="<<value2string(v)<<endl;
285 cout<<"pn="<<to_string()<<endl;
287 PeriodicNumber result(*this);
288 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
289 cout<<"Before multiplication, result="<<result.to_string()<<endl;
291 for(unsigned i=0;i<result.datasize;i++)
292 value_multiply(result.data[i],result.data[i],v);
293 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
294 cout<<"After multiplication with v="<<value2string(v)<<":"<<endl;
295 cout<<"result="<<result.to_string()<<endl;
297 return result;
300 void PeriodicNumber::get_gcd(Value& v) const
302 if (datasize==0) {
303 value_set_si(v, 1);
304 return;
306 value_assign(v,data[0]);
307 for(unsigned i=1;i<datasize;i++)
308 value_gcd(v, v, data[i]);
311 void PeriodicNumber::divide_by(const Value v)
313 #ifndef NDEBUG
314 Value gcd;
315 Value gcd2;
316 value_init(gcd); value_init(gcd2);
317 get_gcd(gcd); get_gcd(gcd2);
318 value_division(gcd, gcd, v);
319 value_multiply(gcd, gcd, v);
320 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
321 cout<<"In PeriodicNumber::divide_by("<<value2string(v)<<")"<<endl;
322 cout<<" periodicnumber = "<<to_string()<<endl;
323 cout<<" gcd = "<<value2string(gcd)<<"; gcd2 = "<<value2string(gcd2)<<endl;
325 assert(value_eq(gcd,gcd2));
326 value_clear(gcd);
327 value_clear(gcd2);
328 #endif
329 for(unsigned i=0; i<datasize; i++)
330 value_division(data[i] , data[i], v);
333 /** operator* multiplies two periodic numbers \f$pn_1\f$ and
334 * \f$pn_2\f$. The following algorithm is used: The parameters in the
335 * result equals the union of the parameters in the two periodic
336 * numbers to be multiplied. The periods of any parameter
337 * \f$p\f$ is the least common multiple of the period of the
338 * parameter in \f$pn_1\f$ and \f$pn_2\f$. If the parameter doesn't
339 * occur in one of \f$pn_1\f$ and \f$pn_2\f$, its period is taken is
340 * being one in \f$pn_1\f$ or \f$pn_2\f$. After this step, the
341 * values in the matrix are filled in, being the product of the
342 * corresponding values in \f$pn_1\f$ and \f$pn_2\f$.*/
343 PeriodicNumber PeriodicNumber::operator*(const PeriodicNumber& pn2) const
345 const PeriodicNumber& pn1=(*this);
346 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
347 cout<<"In PeriodicNumber::operator*:"<<endl;
348 cout<<"pn1="<<pn1.to_string()<<endl;
349 cout<<"pn2="<<pn2.to_string()<<endl;
351 set<string> parameters=pn1.parameter_names;
352 map<string, int> period;
353 for(set<string>::const_iterator i=pn2.parameter_names.begin();
354 i!=pn2.parameter_names.end(); i++)
355 parameters.insert(*i);
357 for(set<string>::const_iterator i=parameters.begin();
358 i!=parameters.end(); i++) {
359 bool param_in_pn1 =
360 (pn1.parameter_names.find(*i)!=pn1.parameter_names.end());
361 bool param_in_pn2 =
362 (pn2.parameter_names.find(*i)!=pn2.parameter_names.end());
363 if (param_in_pn1 && param_in_pn2) {
364 map<string, int>::const_iterator j=pn1.period.find(*i);
365 assert(j!=pn1.period.end());
366 map<string, int>::const_iterator k=pn2.period.find(*i);
367 assert(k!=pn2.period.end());
368 period[*i] = lcm((*j).second, (*k).second);
369 } else if (param_in_pn1) {
370 map<string, int>::const_iterator j=pn1.period.find(*i);
371 assert(j!=pn1.period.end());
372 period[*i] = (*j).second;
373 } else if (param_in_pn2) {
374 map<string, int>::const_iterator j=pn2.period.find(*i);
375 assert(j!=pn2.period.end());
376 period[*i] = (*j).second;
377 } else assert(0);
380 PeriodicNumber result(parameters, period);
381 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
382 cout<<"In PeriodicNumber::operator*:"<<endl;
383 cout<<"result.parameters=";
384 for(set<string>::const_iterator i=parameters.begin();
385 i!=parameters.end(); i++)
386 cout<<(*i)<<" ";
387 cout<<endl;
388 cout<<"result.period=";
389 for(map<string, int>::const_iterator i=period.begin();
390 i!=period.end(); i++)
391 cout<<"("<<(*i).first<<","<<(*i).second<<") ";
392 cout<<endl;
395 deque<unsigned long> strides2;
396 for(map<string, unsigned long>::const_iterator i=result.stride.begin();
397 i!=result.stride.end(); i++)
398 strides2.push_back((*i).second);
399 strides2.push_back(result.datasize);
400 // now fill in the correct values.
401 Value tmp;
402 value_init(tmp);
403 for(unsigned long i=0;i<result.datasize;i++) {
404 // find out which period-values for which parameters
405 // map to data[i].
406 map<string, int> index;
407 int param_nr=0;
408 for(set<string>::const_iterator j=parameters.begin();
409 j!=parameters.end(); j++, param_nr++) {
410 index[*j] = (i%(strides2[param_nr+1])) / strides2[param_nr];
412 value_set_si(tmp, 1);
413 map<string, int> pn1_index;
414 map<string, int> pn2_index;
415 for(map<string, int>::const_iterator j=index.begin();j!=index.end(); j++) {
416 if (pn1.parameter_names.find((*j).first)==pn1.parameter_names.end())
417 continue;
418 map<string, int>::const_iterator periodd=pn1.period.find((*j).first);
419 assert(periodd!=pn1.period.end());
420 pn1_index[(*j).first] = (*j).second % (*periodd).second;
422 for(map<string, int>::const_iterator j=index.begin();j!=index.end(); j++) {
423 if (pn2.parameter_names.find((*j).first)==pn2.parameter_names.end())
424 continue;
425 map<string, int>::const_iterator periodd=pn2.period.find((*j).first);
426 assert(periodd!=pn2.period.end());
427 pn2_index[(*j).first] = (*j).second % (*periodd).second;
430 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=4) {
431 cout<<"In PeriodicNumber::operator*, i="<<i<<", result.datasize="<<datasize<<"\n pn1_index=";
432 for(map<string, int>::const_iterator z=pn1_index.begin(); z!=pn1_index.end(); z++)
433 cout<<"("<<(*z).first<<","<<(*z).second<<") ";
434 cout<<"\npn2_index=";
435 for(map<string, int>::const_iterator z=pn2_index.begin(); z!=pn2_index.end(); z++)
436 cout<<"("<<(*z).first<<","<<(*z).second<<") ";
437 cout<<endl;
438 cout<<"pn1[pn1_index]="<<value2string(pn1[pn1_index])<<endl;
439 cout<<"pn2[pn2_index]="<<value2string(pn2[pn2_index])<<endl;
440 cout<<"tmp="<<value2string(tmp)<<endl;
442 value_multiply(tmp, tmp, pn1[pn1_index]);
443 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=4) { cout<<"tmp="<<value2string(tmp)<<endl; }
444 value_multiply(tmp, tmp, pn2[pn2_index]);
445 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=4) { cout<<"tmp="<<value2string(tmp)<<endl; }
446 value_assign(result[index] , tmp);
448 value_clear(tmp);
450 // if the periodic number has parameters (i.e. not constant coef),
451 // then "" should not occur as parameter!
452 if (result.parameter_names.find("") != result.parameter_names.end()) {
453 assert(result.period[""] == 1);
454 result.parameter_names.erase("");
455 result.period.erase("");
456 result.stride.erase("");
459 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
460 cout<<"In PeriodicNumber::operator* result of multiplication is:"<<endl;
461 cout<<result.to_string()<<endl;
462 cout<<"result.parameter_names=";
463 for(set<string>::const_iterator i=result.parameter_names.begin();
464 i!=result.parameter_names.end(); i++)
465 cout<<(*i)<<" ";
466 cout<<endl;
467 cout<<"result.period=";
468 for(map<string, int>::const_iterator i=result.period.begin();
469 i!=result.period.end(); i++)
470 cout<<"("<<(*i).first<<","<<(*i).second<<") ";
471 cout<<"result.stride =";
472 for(map<string, unsigned long>::const_iterator i=result.stride.begin();
473 i!=result.stride.end(); i++)
474 cout<<"("<<(*i).first<<","<<(*i).second<<") ";
475 cout<<"result.data=";
476 for(unsigned i=0;i<result.datasize;i++) {
477 char* str=0;
478 value_to_str(str,0, result.data[i]);
479 cout<<str<<" ";
480 free(str);
482 cout<<endl;
485 return result;
488 double PeriodicNumber::to_double() const
490 assert(datasize==1);
491 return VALUE_TO_DOUBLE(data[0]);
494 bool PeriodicNumber::smaller_than(const PeriodicNumber& pn) const
496 if (datasize!=1 || pn.datasize!=1)
497 return false;
498 return value_lt(data[0], pn.data[0]);
501 string PeriodicNumber::to_string() const
503 string result;
504 deque<unsigned long> strides2;
505 for(map<string, unsigned long>::const_iterator i=stride.begin();
506 i!=stride.end(); i++)
507 strides2.push_back((*i).second);
508 strides2.push_back(datasize);
509 // now fill in the correct values.
510 for(unsigned long i=0;i<datasize;i++) {
511 // find out which period-values for which parameters
512 // map to data[i].
513 map<string, int> index;
514 int param_nr=0;
515 for(set<string>::const_iterator j=parameter_names.begin();
516 j!=parameter_names.end(); j++, param_nr++) {
517 index[*j] = (i%(strides2[param_nr+1])) / strides2[param_nr];
519 for(map<string, int>::const_iterator j=index.begin();
520 j!=index.end(); j++) {
521 map<string,int>::const_iterator k=period.find((*j).first);
522 assert(k!=period.end());
523 if ((*j).second==0 && (*k).second!=1)
524 result+="[ ";
525 else
526 break;
528 Value val;
529 value_init(val);
530 value_assign(val,((*this)[index]));
531 char* valstr=0;
532 value_to_str(valstr,valstr,val);
533 result += string(valstr)+" ";
534 free(valstr);
535 for(map<string, int>::const_iterator j=index.begin();
536 j!=index.end(); j++) {
537 map<string,int>::const_iterator k=period.find((*j).first);
538 assert(k!=period.end());
539 if ((*j).second==(*k).second-1 && (*k).second!=1) {
540 result+="]";
541 if ((*j).first!=string(""))
542 result+="_";
543 result+=(*j).first+", ";
545 else
546 break;
549 if (result.size()>=2 && result.substr(result.size()-2, result.size())
550 ==", ")
551 result.erase(result.size()-2, result.size());
553 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
554 string debug_str;
555 debug_str+="(\n\tparameter_names=";
556 for(set<string>::const_iterator i=parameter_names.begin();
557 i!=parameter_names.end(); i++)
558 debug_str+=(*i)+" ";
559 debug_str+="\n\tperiod=";
560 for(map<string, int>::const_iterator i=period.begin();
561 i!=period.end(); i++)
562 debug_str+="("+(*i).first+","+int2string((*i).second)+") ";
563 debug_str+="\n\tstride=";
564 for(map<string, unsigned long>::const_iterator i=stride.begin();
565 i!=stride.end(); i++)
566 debug_str+="("+(*i).first+","+int2string((*i).second)+") ";
567 debug_str+="\n\tdata=";
568 for(unsigned i=0;i<datasize;i++) {
569 char* str=0;
570 value_to_str(str,0, data[i]);
571 debug_str+=str+string(" ");
572 free(str);
574 debug_str+=")\n";
575 result += debug_str;
578 return result;
581 static int find_pos_of(const string& name,
582 const deque<string>& names)
584 for(unsigned i=0;i<names.size(); i++)
585 if (name==names[i])
586 return i;
587 return -1;
590 bool PeriodicNumber::has_param(const string& name) const
592 if (DebugBlackboard.debug("AFFINEPOLYNOM")>=6) {
593 cout<<"in PeriodicNumber::has_param("<<name<<") (this="
594 <<to_string()<<"): return "
595 <<(period.find(name)!=period.end())<<endl;
597 return (period.find(name)!=period.end());
600 static void pn_to_evalue(const PeriodicNumber& pn,
601 const map<string,int>& bound_vars,
602 const set<string>& free_vars,
603 const deque<string>& ep_parameter_names,
604 evalue& ev)
606 if (free_vars.size()==0) {
607 value_set_si(ev.d,1);
608 value_assign(ev.x.n , pn[bound_vars]);
609 return;
610 } else {
611 string name;
612 // find an appropriate var_name, i.e., different from ""
613 // if possible
614 for(set<string>::const_iterator i=free_vars.begin();
615 i!=free_vars.end(); i++)
616 if (name=="")
617 name=(*i);
618 if (name=="") {
619 assert(free_vars.size()==1);
620 // assert(bound_vars.size()==0);
621 assert(bound_vars.find("")==bound_vars.end());
622 assert(pn.get_period("")==1);
623 map<string,int> index=bound_vars;
624 index[""]=0;
625 value_set_si(ev.d,1);
626 value_assign(ev.x.n , pn[index]);
627 return;
629 set<string> new_free_vars=free_vars;
630 new_free_vars.erase(new_free_vars.find(name));
631 value_set_si(ev.d,0);
632 value_clear(ev.x.n);
633 ev.x.p = new_enode(periodic, pn.get_period(name),
634 find_pos_of(name, ep_parameter_names)+1);
635 for(int i=0;i<pn.get_period(name);i++) {
636 map<string,int> new_bound_vars=bound_vars;
637 assert(new_bound_vars.find(name)==new_bound_vars.end());
638 new_bound_vars[name]=i;
639 value_init(ev.x.p->arr[i].x.n);
640 pn_to_evalue(pn, new_bound_vars, new_free_vars,
641 ep_parameter_names, ev.x.p->arr[i]);
646 ::evalue PeriodicNumber::to_evalue(const deque<string>& ep_parameter_names)
647 const
649 map<string,int> bound_vars;
650 set<string> free_vars=this->parameter_names;
652 ::evalue result;
653 value_init(result.d);
654 value_init(result.x.n);
655 pn_to_evalue(*this, bound_vars, free_vars, ep_parameter_names, result);
656 return result;
660 static bool check_for_polynomials(::enode* e)
662 assert(e!=0);
663 if (e->type==polynomial)
664 return true;
665 else
666 for(int i=0;i<e->size;i++)
667 if (value_zero_p(e->arr[i].d) &&
668 check_for_polynomials(e->arr[i].x.p))
669 return true;
670 return false;
673 static void find_names(::enode* e,
674 const deque<string>& parameter_names,
675 set<string>& names)
677 assert(e!=0);
678 assert(e->type==periodic);
680 names.insert(parameter_names[e->pos-1]);
681 for(int i=0;i<e->size;i++)
682 if (value_zero_p(e->arr[i].d))
683 find_names(e->arr[i].x.p, parameter_names, names);
686 static void find_periods(::enode* e,
687 const deque<string>& parameter_names,
688 map<string, set<int> >& periods)
690 assert(e!=0);
691 assert(e->type==periodic);
693 periods[parameter_names[e->pos-1]].insert(e->size);
694 for(int i=0;i<e->size;i++)
695 if (value_zero_p(e->arr[i].d))
696 find_periods(e->arr[i].x.p, parameter_names, periods);
699 static void find_denominators(::enode* e,
700 set<Value> &denominators)
702 assert(e!=0);
703 assert(e->type==periodic);
705 for(int i=0;i<e->size;i++) {
706 if (value_zero_p(e->arr[i].d))
707 find_denominators(e->arr[i].x.p, denominators);
708 else
709 denominators.insert(e->arr[i].d);
713 #if 0
715 static void fill_in_values(PeriodicNumber& pn,
716 ::enode* e,
717 const deque<string>& parameter_names,
718 map<string, int>& name2lcm_period,
719 map<string, set<int> >& name2indices,
720 const int lcm_denom)
722 assert(e!=0);
723 assert(e->type==periodic);
724 static int depth=0;
725 depth++;
726 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
727 cout<<"Entering fill_in_values (depth "<<depth<<"):"<<endl;
728 cout<<"e=";
729 char **pname=get_pname(parameter_names);
730 ::print_enode(stdout, e, pname);
731 delete_pname(pname, parameter_names);
732 cout<<endl;
733 cout<<"parameter_names= ";
734 for(deque<string>::const_iterator i=parameter_names.begin();
735 i!=parameter_names.end(); i++)
736 cout<<(*i)<<" ";
737 cout<<endl;
738 cout<<"name2lcm_period= ";
739 for(map<string,int>::const_iterator i=name2lcm_period.begin();
740 i!=name2lcm_period.end(); i++)
741 cout<<"("<<(*i).first<<","<<(*i).second<<")"<<" ";
742 cout<<endl;
743 cout<<"name2indices= ";
744 for(map<string,set<int> >::const_iterator i=name2indices.begin();
745 i!=name2indices.end(); i++) {
746 cout<<"("<<(*i).first<<",{";
747 for(set<int>::const_iterator j=(*i).second.begin();
748 j!=(*i).second.end(); j++) {
749 if (j!=(*i).second.begin())
750 cout<<" ";
751 cout<<(*j);
753 cout<<"}) ";
755 cout<<endl;
756 cout<<"lcm_denom= "<<lcm_denom<<endl;
759 string name=parameter_names[e->pos-1];
760 int period =e->size;
761 int nr_periods = name2lcm_period[name] / e->size;
762 assert(nr_periods*e->size == name2lcm_period[name]);
764 assert(name2indices.find(name) == name2indices.end());
765 for(int i=0;i<e->size;i++) {
766 for(int k=0;k<nr_periods;k++)
767 name2indices[name].insert(i+k*period);
768 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
769 cout<<" i="<<i<<"; period = "<<period
770 <<"; nr_periods = "<<nr_periods<<"name2indices = ";
771 for(map<string,set<int> >::const_iterator i=name2indices.begin();
772 i!=name2indices.end(); i++) {
773 cout<<"("<<(*i).first<<",{";
774 for(set<int>::const_iterator j=(*i).second.begin();
775 j!=(*i).second.end(); j++) {
776 if (j!=(*i).second.begin())
777 cout<<" ";
778 cout<<(*j);
780 cout<<"}) ";
782 cout<<endl;
785 if (e->arr[i].d==0) {
786 fill_in_values(pn, e->arr[i].x.p, parameter_names,
787 name2lcm_period, name2indices, lcm_denom);
788 } else {
789 // e->arr[i].d!=0
790 int multiplier = lcm_denom/e->arr[i].d;
791 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
792 cout<<"multiplier="<<multiplier<<endl;
794 assert(multiplier * e->arr[i].d == lcm_denom);
795 deque<unsigned long> strides;
796 map<string, deque<int> > name2indices2;
797 unsigned long total=1;
798 for(map<string, set<int> >::const_iterator j=name2indices.begin();
799 j!=name2indices.end(); j++) {
800 strides.push_back(total);
801 total *= (*j).second.size();
802 for(set<int>::const_iterator k=(*j).second.begin();
803 k!=(*j).second.end(); k++)
804 name2indices2[(*j).first].push_back(*k);
806 strides.push_back(total);
807 for(unsigned long j=0;j<total; j++) {
808 map<string,int> index;
809 unsigned long t=0;
810 for(map<string, set<int> >::const_iterator k=name2indices.begin();
811 k!=name2indices.end(); k++,t++) {
812 index[(*k).first] =
813 name2indices2[(*k).first][(j%strides[t])/strides[t]];
815 pn[index] = multiplier * e->arr[i].x.n;
818 if (name2indices.find(name) != name2indices.end())
819 name2indices.erase(name2indices.find(name));
821 depth--;
825 /** handle_periodic_enode processes an enode
826 * of type periodic
827 * @return a pair. The first part is the periodic number
828 * The second part is the denominator of the
829 * periodic number.
831 static pair<PeriodicNumber,int> handle_periodic_enode
832 (const deque<string>& parameter_names,
833 ::enode* e)
835 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
836 cout<<"Entering handle_periodic_enode"<<endl;
837 cout<<"e= ";
838 char **pname=get_pname(parameter_names);
839 ::print_enode(stdout, e, pname);
840 delete_pname(pname, parameter_names);
841 cout<<endl;
843 // check some assumptions first:
844 // 1. there are no polynomial enodes further down.
845 assert(false==check_for_polynomials(e));
846 // 2. find the parameter names occuring in the Ehrhart Polynomial
847 set<string> names;
848 find_names(e, parameter_names, names);
849 // 3. find all the periods for all the names that occur.
850 map<string, set<int> > name2periods;
851 find_periods(e, parameter_names, name2periods);
852 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
853 cout<<"In handle_periodic_enode"<<endl;
854 cout<<"name2periods = ";
855 for(map<string, set<int> >::const_iterator i=name2periods.begin();
856 i!=name2periods.end(); i++) {
857 cout<<"("<<(*i).first<<", {";
858 for(set<int>::const_iterator j=(*i).second.begin();
859 j!=(*i).second.end(); j++) {
860 if (j!=(*i).second.begin())
861 cout<<",";
862 cout<<(*j);
864 cout<<"}) ";
866 cout<<endl;
868 // 4. find lcm for all periods of a given name.
869 map<string, int> name2lcm_period;
870 for(set<string>::const_iterator i=names.begin();
871 i!=names.end(); i++) {
872 assert(name2periods.find(*i)!=name2periods.end());
873 int lcmp=1;
874 for(set<int>::const_iterator j=name2periods[*i].begin();
875 j!=name2periods[*i].end(); j++)
876 lcmp = lcm(lcmp, *j);
877 name2lcm_period[*i] = lcmp;
879 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
880 cout<<"In handle_periodic_enode"<<endl;
881 cout<<"name2lcm_period = ";
882 for(map<string,int>::const_iterator i=name2lcm_period.begin();
883 i!=name2lcm_period.end(); i++) {
884 cout<<"("<<(*i).first<<","<<(*i).second<<") ";
886 cout<<endl;
888 // 5. find lcm of all denominators
889 int lcmd=1;
890 set<Value> denominators;
891 find_denominators(e, denominators);
892 for(set<Value>::const_iterator j=denominators.begin();
893 j!=denominators.end(); j++)
894 lcmd = lcm(lcmd, *j);
895 int common_denom=lcmd;
896 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
897 cout<<"common_denom = "<<common_denom<<endl;;
900 // 5. Construct PeriodicNumber, phase 1
901 PeriodicNumber result(names, name2lcm_period);
902 // 6. Fill in the values for the PeriodicNumber
904 // name2indices indicates for which indices of which
905 // parameter names the given value must be filled in.
906 map<string, set<int> > name2indices;
907 fill_in_values(result, e, parameter_names, name2lcm_period, name2indices,
908 common_denom);
910 return pair<PeriodicNumber,int>(result,common_denom);
914 static void process_sub_part_of_evalue
915 (map<map<string, int>, pair<PeriodicNumber, Value> >& data,
916 const deque<string>& parameter_names,
917 const map<string,int>& current_exponents,
918 const PeriodicNumber& current_periodic,
919 Value current_denumerator,
920 ::evalue* e)
922 static int depth=0; //only used for debugging
923 depth++;
925 assert(e!=0);
927 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
928 cout<<"Entering process_sub_part_of_evalue (depth "<<depth<<"):"<<endl;
929 cout<<"parameter_names= ";
930 for(deque<string>::const_iterator i=parameter_names.begin();
931 i!=parameter_names.end(); i++)
932 cout<<(*i)<<" ";
933 cout<<endl;
934 cout<<"current_exponent= ";
935 for(map<string,int>::const_iterator i=current_exponents.begin();
936 i!=current_exponents.end(); i++)
937 cout<<"("<<(*i).first<<","<<(*i).second<<")"<<" ";
938 cout<<endl;
939 cout<<"current_periodic= "<<current_periodic.to_string()<<endl;
940 cout<<"current_denumerator= "<<current_denumerator<<endl;
941 cout<<"e->d="<<e->d<<endl;
944 if (value_notzero_p(e->d)) {
945 // the evalue e represents a rational number
946 assert(data.find(current_exponents)==data.end());
947 value_direct_product(current_denumerator, e->d);
948 PeriodicNumber pn;
949 if (current_periodic.is_zero())
950 pn=PeriodicNumber(e->x.n);
951 else
952 pn = current_periodic * e->x.n;
953 data[current_exponents] =
954 pair<PeriodicNumber, Value>(pn, current_denumerator);
955 } else {
956 ::enode* en=e->x.p;
957 switch(en->type) {
958 case polynomial:
960 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
961 cout<<"The enode is a polynomial enode."<<endl;
963 string param_name;
964 if (en->pos>=1)
965 param_name = parameter_names[en->pos-1];
966 else
967 param_name = "";
968 assert(current_exponents.find(param_name)==
969 current_exponents.end());
970 const int degree=en->size-1;
971 for(int i=0;i<=degree;i++) {
972 map<string,int> exp=current_exponents;
973 exp[param_name] = i;
974 process_sub_part_of_evalue(data, parameter_names,
975 exp, current_periodic,
976 current_denumerator,
977 &(en->arr[i]));
980 break;
981 case periodic:
983 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
984 cout<<"The enode is a periodice enode."<<endl;
986 pair<PeriodicNumber,int> pn=handle_periodic_enode(parameter_names, en);
987 data[current_exponents] =
988 pair<PeriodicNumber, Value>(pn.first, current_denumerator*pn.second);
990 break;
991 case evector:
992 assert(0);
993 break;
996 depth--;
999 #endif
1001 static EhrhartPolynom convert_evalue(const ::evalue e,
1002 const deque<string>& parameter_names)
1004 if (value_notzero_p(e.d)) {
1005 // the evalue e represents a rational number
1006 PeriodicNumber pn(e.x.n);
1007 map<string,int> exponent;
1008 exponent[""]=1;
1009 return EhrhartPolynom(exponent,
1010 EhrhartPolynom::periodic_rational(pn,e.d));
1011 } else {
1012 EhrhartPolynom result;
1013 ::enode* en=e.x.p;
1014 switch(en->type) {
1015 case polynomial:
1017 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
1018 cout<<"The enode is a polynomial enode."<<endl;
1020 string param_name;
1021 if (en->pos>=1)
1022 param_name = parameter_names[en->pos-1];
1023 else
1024 param_name = "";
1025 const int degree=en->size-1;
1026 for(int i=0;i<=degree;i++) {
1027 Value one;
1028 value_init(one);
1029 value_set_si(one, 1);
1030 PeriodicNumber pn(one);
1031 map<string,int> exponent;
1032 exponent[param_name]=i;
1033 EhrhartPolynom ep1(exponent, EhrhartPolynom::periodic_rational(pn,one));
1034 result += ep1 * convert_evalue(en->arr[i],parameter_names);
1035 value_clear(one);
1038 break;
1039 case periodic:
1041 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
1042 cout<<"The enode is a periodice enode."<<endl;
1044 string name=parameter_names[en->pos-1];
1045 assert(name!=string(""));
1046 int period=en->size;
1047 set<string> param_name_set;
1048 param_name_set.insert(name);
1049 map<string,int> period_map;
1050 period_map[name]=period;
1051 map<string,int> exponent;
1052 exponent[""]=1;
1053 for(int i=0;i<period;i++) {
1054 // construct PeriodicNumber with parameter name and
1055 // period period, and 0 everywhere, except in location i.
1056 PeriodicNumber pn(param_name_set, period_map);
1057 map<string,int> index;
1058 index[name]=i;
1059 Value one;
1060 value_init(one);
1061 value_set_si(one, 1);
1062 value_set_si(pn[index], 1);
1063 EhrhartPolynom ep(exponent, EhrhartPolynom::periodic_rational(pn, one));
1064 result += ep * convert_evalue(en->arr[i], parameter_names);
1065 value_clear(one);
1068 break;
1069 case evector:
1070 assert(0);
1071 break;
1073 return result;
1077 EhrhartPolynom::EhrhartPolynom(const ::evalue* e,
1078 const deque<string>& parameter_names)
1080 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
1081 cout<<"In EhrhartPolynom(e): e="<<endl;
1082 char** pname=get_pname(parameter_names);
1083 print_evalue(stdout, const_cast< ::evalue*>(e), pname);
1084 delete_pname(pname, parameter_names);
1085 cout<<endl;
1087 #if 0
1088 map<string,int> current_exponents;
1089 PeriodicNumber t;
1090 process_sub_part_of_evalue(data, parameter_names,
1091 current_exponents, t, 1, e);
1092 #endif
1093 assert(e!=0);
1094 data = convert_evalue(*e, parameter_names).data;
1095 simplify();
1096 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
1097 cout<<"In EhrhartPolynom(e): constructed following EhrhartPolynom:"<<endl;
1098 cout<<to_string()<<endl;
1102 EhrhartPolynom::~EhrhartPolynom() {
1103 data.clear();
1105 for(map<map<string, int>, periodic_rational>::iterator i=
1106 data.begin(); i!=data.end(); i++)
1107 value_clear((*i).second.second);
1111 EhrhartPolynom
1112 EhrhartPolynom::operator+(const EhrhartPolynom& e2) const
1114 const EhrhartPolynom& e1=(*this);
1115 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
1116 cout<<"In EhrhartPolynom()::operator+: adding following polynoms"<<endl;
1117 cout<<e1.to_string()<<endl;
1118 cout<<e2.to_string()<<endl;
1120 EhrhartPolynom result;
1121 for(map<map<string, int>, periodic_rational >::const_iterator i=
1122 e1.data.begin(); i!=e1.data.end(); i++) {
1123 map<map<string, int>, periodic_rational >::const_iterator j =
1124 e2.data.find((*i).first);
1125 if (j==e2.data.end()) {
1126 // the term was not found in e2.
1127 result.data[(*i).first] = (*i).second;
1128 } else {
1129 Value lcm_val;
1130 value_init(lcm_val);
1131 value_lcm(lcm_val, (*i).second.second, (*j).second.second);
1132 //unsigned long lcm_val = lcm( (*i).second.second, (*j).second.second);
1133 Value prod1, prod2;
1134 value_init(prod1); value_init(prod2);
1135 value_division(prod1, lcm_val, (*i).second.second);
1136 value_division(prod2, lcm_val, (*j).second.second);
1137 PeriodicNumber pn1 = (*i).second.first * prod1;
1138 PeriodicNumber pn2 = (*j).second.first * prod2;
1139 value_clear(prod1);
1140 value_clear(prod2);
1141 result.data[(*i).first] = periodic_rational(pn1+pn2, lcm_val);
1142 value_clear(lcm_val);
1145 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
1146 cout<<"In EhrhartPolynom()::operator+: result of addition (after adding terms to term1)"<<endl;
1147 cout<<result.to_string()<<endl;
1149 for(map<map<string, int>, periodic_rational >::const_iterator i=
1150 e2.data.begin(); i!=e2.data.end(); i++) {
1151 map<map<string, int>, periodic_rational >::const_iterator j =
1152 e1.data.find((*i).first);
1153 if (j==e1.data.end()) {
1154 result.data[(*i).first] = (*i).second;
1157 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
1158 cout<<"In EhrhartPolynom()::operator+: result of addition (before simplify)"<<endl;
1159 cout<<result.to_string()<<endl;
1161 result.simplify();
1162 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
1163 cout<<"In EhrhartPolynom()::operator+: result of addition"<<endl;
1164 cout<<result.to_string()<<endl;
1166 return result;
1169 EhrhartPolynom EhrhartPolynom::operator*(const EhrhartPolynom& e2) const
1171 const EhrhartPolynom& e1=(*this);
1172 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
1173 cout<<"In EhrhartPolynom()::operator*: multiplying"
1174 " following polynoms"<<endl;
1175 cout<<e1.to_string()<<endl;
1176 cout<<e2.to_string()<<endl;
1178 EhrhartPolynom result;
1179 Value div1, div2;
1180 value_init(div1); value_init(div2);
1181 Value lcm_val;
1182 value_init(lcm_val);
1183 Value gcd_product_denominator;
1184 value_init(gcd_product_denominator);
1185 Value gcd_of_product;
1186 value_init(gcd_of_product);
1187 for(map<map<string, int>, periodic_rational>::const_iterator i=
1188 e1.data.begin(); i!=e1.data.end(); i++) {
1189 for(map<map<string, int>, periodic_rational>::const_iterator j =
1190 e2.data.begin(); j!=e2.data.end(); j++) {
1191 // add up exponents
1192 map<string,int> exponent=(*i).first;
1193 for(map<string,int>::const_iterator k=(*j).first.begin();
1194 k!=(*j).first.end(); k++)
1195 exponent[(*k).first]+=(*k).second;
1196 // multiply coefficients
1197 value_lcm(lcm_val, (*i).second.second, (*j).second.second);
1198 Value common_denominator;
1199 value_init(common_denominator);
1200 value_multiply(common_denominator, lcm_val, lcm_val);
1202 unsigned long lcm_val = lcm( (*i).second.second, (*j).second.second);
1203 unsigned long common_denominator = lcm_val*lcm_val;
1205 value_division(div1, lcm_val, (*i).second.second);
1206 value_division(div2, lcm_val, (*j).second.second);
1207 PeriodicNumber pn1 = (*i).second.first * div1;
1208 PeriodicNumber pn2 = (*j).second.first * div2;
1209 PeriodicNumber pn1_x_pn2 = pn1*pn2;
1210 pn1_x_pn2.get_gcd(gcd_of_product);
1211 value_gcd(gcd_product_denominator, gcd_of_product, common_denominator);
1212 pn1_x_pn2.divide_by(gcd_product_denominator);
1213 value_division(common_denominator, common_denominator, gcd_product_denominator);
1214 EhrhartPolynom term(exponent,
1215 periodic_rational(pn1_x_pn2, common_denominator));
1216 value_clear(common_denominator);
1217 result+=term;
1220 value_clear(div1); value_clear(div2); value_clear(lcm_val); value_clear(gcd_product_denominator);
1221 value_clear(gcd_of_product);
1223 result.simplify();
1224 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
1225 cout<<"In EhrhartPolynom()::operator*: result of multiplication:"<<endl;
1226 cout<<result.to_string()<<endl;
1228 return result;
1231 EhrhartPolynom EhrhartPolynom::operator/(const Value v) const
1233 EhrhartPolynom result(*this);
1234 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
1235 cout<<"In EhrhartPolynom()::operator/: dividing ";
1236 cout<<this->to_string()<<" by "<<value2string(v)<<endl;
1238 for(map<map<string, int>, periodic_rational>::iterator i=
1239 result.data.begin(); i!= result.data.end(); i++) {
1240 value_multiply ( (*i).second.second, (*i).second.second, v);
1243 result.simplify();
1244 return result;
1248 void EhrhartPolynom::simplify()
1250 Value mult_p1, mult_p2;
1251 value_init(mult_p1);
1252 value_init(mult_p2);
1253 Value lcm_denominator;
1254 value_init(lcm_denominator);
1255 map<map<string, int>, periodic_rational> new_data;
1256 for(map<map<string, int>, periodic_rational>::const_iterator
1257 i=data.begin(); i!=data.end();i++) {
1258 if ((*i).second.first.is_zero())
1259 continue;
1260 // remove exponents with power 0, remove exponents with name ""
1261 map<string,int> exponent;
1262 for(map<string,int>::const_iterator j=(*i).first.begin();
1263 j!=(*i).first.end(); j++) {
1264 if ((*j).second!=0 && (*j).first!=string(""))
1265 exponent[(*j).first]=(*j).second;
1267 if (new_data.find(exponent)!=new_data.end()) {
1268 value_lcm(lcm_denominator, new_data[exponent].second, (*i).second.second);
1269 value_division(mult_p1, lcm_denominator, new_data[exponent].second);
1270 value_division(mult_p2, lcm_denominator, (*i).second.second);
1272 mult_p1=lcm_denominator / new_data[exponent].second;
1273 mult_p2=lcm_denominator / (*i).second.second;
1275 PeriodicNumber pn = (*i).second.first*mult_p2 +
1276 new_data[exponent].first*mult_p1;
1277 new_data[exponent] = periodic_rational(pn, lcm_denominator);
1278 } else {
1279 new_data[exponent] = (*i).second;
1283 data=new_data;
1284 value_clear(mult_p1);
1285 value_clear(mult_p2);
1286 value_clear(lcm_denominator);
1287 if (data.size()==0) {
1288 Value val, one;
1289 value_init(val);
1290 value_set_si(val, 0);
1291 value_init(one);
1292 value_set_si(one, 1);
1293 map<string,int> exponent;
1294 PeriodicNumber pn(val);
1295 periodic_rational pr(pn, one);
1296 data[exponent] = pr;
1297 value_clear(val);
1298 value_clear(one);
1299 return;
1303 double EhrhartPolynom::to_double() const {
1304 // Should only be called on constant EhrhartPolynomials (i.e. no parameters)!
1305 EhrhartPolynom ep1=(*this);
1306 ep1.simplify();
1308 assert(ep1.data.size()==1);
1309 const map<string,int> exponent;
1310 periodic_rational ep1_val = ep1.data[exponent];
1311 return ep1_val.first.to_double() / VALUE_TO_DOUBLE(ep1_val.second);
1314 bool EhrhartPolynom::smaller_than(const EhrhartPolynom& _ep2) const {
1315 EhrhartPolynom ep1=(*this);
1316 EhrhartPolynom ep2=_ep2;
1317 ep1.simplify();
1318 ep2.simplify();
1320 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
1321 cout<<"In EhrhartPolynom::smaller_than, comparing "
1322 <<ep1.to_string()<<" and "<<ep2.to_string()<<endl;
1324 /* only return true if both are comparable, i.e. both
1325 ep1 and ep2 are constant, and ep1 < ep2 */
1326 // Value ep1v, ep2v;
1327 /* check if constant */
1328 bool result;
1329 if (ep1.data.size()==1 && ep2.data.size()==1) {
1330 const map<string,int> exponent;
1331 periodic_rational ep1_val = ep1.data[exponent];
1332 periodic_rational ep2_val = ep2.data[exponent];
1333 PeriodicNumber ep1_scaled=ep1_val.first * ep2_val.second,
1334 ep2_scaled=ep2_val.first * ep1_val.second;
1335 result = ep1_scaled.smaller_than(ep2_scaled);
1336 } else
1337 result = false;
1338 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
1339 cout<<"result of comparison is "<<result<<endl;
1341 return result;
1344 bool EhrhartPolynom::operator==(const EhrhartPolynom& _ep2) const {
1345 EhrhartPolynom ep1=(*this);
1346 EhrhartPolynom ep2=_ep2;
1347 ep1.simplify();
1348 ep2.simplify();
1350 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
1351 cout<<"In EhrhartPolynom::operator==, comparing "
1352 <<ep1.to_string()<<" and "<<ep2.to_string()<<endl;
1355 map<map<string, int>, periodic_rational>::const_iterator i=data.begin();
1356 map<map<string, int>, periodic_rational>::const_iterator j=_ep2.data.begin();
1357 for(; i!=data.end() && j!=_ep2.data.end(); i++, j++) {
1358 if ((*i).first!=(*j).first ||
1359 (*i).second.first != (*j).second.first ||
1360 value_ne((*i).second.second, (*j).second.second))
1362 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
1363 cout<<"result 1 of comparison is false."<<endl;
1365 return false;
1368 if (i!=data.end() || j!=_ep2.data.end()) {
1369 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
1370 cout<<"result 2 of comparison is false."<<endl;
1372 return false;
1374 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
1375 cout<<"result 3 of comparison is true."<<endl;
1377 return true;
1380 static void fill_in_d(evalue& e, const Value d)
1382 if (value_zero_p(e.d)) {
1383 for(int i=0;i<e.x.p->size;i++)
1384 fill_in_d(e.x.p->arr[i], d);
1385 } else {
1386 assert(value_one_p(e.d));
1387 value_gcd(e.d, e.x.n, d);
1388 value_division(e.x.n, e.x.n, e.d);
1389 value_division(e.d, d, e.d);
1393 static evalue create_coef
1394 (const deque<string>& parameter_names,
1395 const EhrhartPolynom::periodic_rational& d)
1397 evalue result=d.first.to_evalue(parameter_names);
1398 fill_in_d(result, d.second);
1399 return result;
1403 static set<map<string,int> > find_terms_with_var
1404 (const set<map<string, int> >& terms,
1405 const string& varname)
1407 set<map<string, int> > result;
1408 for(set<map<string,int> >::const_iterator i=terms.begin();
1409 i!=terms.end(); i++) {
1410 if ((*i).find(varname)!=(*i).end())
1411 result.insert(*i);
1413 return result;
1417 static set<map<string,int> > find_terms_with_var_exp
1418 (const set<map<string,int> >&terms,
1419 const string& varname,
1420 const int exp)
1422 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
1423 cout<<"In find_terms_with_var_exp:"<<endl;
1424 cout<<" terms("<<terms.size()<<") = ";
1425 for(set<map<string,int> >::const_iterator i=terms.begin();
1426 i!=terms.end(); i++) {
1427 for(map<string,int>::const_iterator j=(*i).begin();
1428 j!=(*i).end(); j++)
1429 cout<<"'"<<(*j).first<<"^"<<(*j).second<<"'";
1430 cout<<" ";
1432 cout<<endl;
1433 cout<<"varname = '"<<varname<<"'"<<endl;
1434 cout<<"exp = "<<exp<<endl;
1436 set<map<string, int> > result;
1437 if (exp!=0) {
1438 for(set<map<string,int> >::const_iterator i=terms.begin();
1439 i!=terms.end(); i++) {
1440 if ((*i).find(varname)!=(*i).end() &&
1441 (*( (*i).find(varname) )).second==exp)
1442 result.insert(*i);
1444 } else {
1445 // exp==0
1446 for(set<map<string,int> >::const_iterator i=terms.begin();
1447 i!=terms.end(); i++) {
1448 if ((*i).find(varname)==(*i).end() ||
1449 (*( (*i).find(varname) )).second==exp)
1450 result.insert(*i);
1453 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
1454 cout<<" result("<<result.size()<<") = ";
1455 for(set<map<string,int> >::const_iterator i=result.begin();
1456 i!=result.end(); i++) {
1457 for(map<string,int>::const_iterator j=(*i).begin();
1458 j!=(*i).end(); j++)
1459 cout<<"'"<<(*j).first<<"^"<<(*j).second<<"'";
1460 cout<<" ";
1462 cout<<endl;
1464 return result;
1468 static int find_max_exp(const set<map<string,int> >& terms,
1469 const string& var_name)
1471 int result=0;
1472 for(set<map<string,int> >::const_iterator i=terms.begin();
1473 i!=terms.end(); i++) {
1474 map<string,int>::const_iterator j=(*i).find(var_name);
1475 if (j!=(*i).end())
1476 result = std::max(result, (*j).second);
1478 return result;
1482 evalue
1483 EhrhartPolynom::translate_one_term
1484 (const deque<string>& parameter_names,
1485 const deque<string>& _left_over_var_names,
1486 const set<map<string, int> >& terms) const
1488 static int depth=0;
1489 depth++;
1490 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
1491 cout<<"In EhrhartPolynom::translate_one_term(depth = "
1492 <<depth<<"):"<<endl;
1493 cout<<to_string()<<endl;
1494 cout<<"left_over_var_names = ";
1495 for(unsigned i=0;i<_left_over_var_names.size();i++)
1496 cout<<_left_over_var_names[i]<<" ";
1497 cout<<endl;
1498 cout<<" terms("<<terms.size()<<") = ";
1499 for(set<map<string,int> >::const_iterator i=terms.begin();
1500 i!=terms.end(); i++) {
1501 for(map<string,int>::const_iterator j=(*i).begin();
1502 j!=(*i).end(); j++)
1503 cout<<"'"<<(*j).first<<"^"<<(*j).second<<"'";
1504 cout<<" ";
1506 cout<<endl;
1508 deque<string> left_over_var_names=_left_over_var_names;
1509 if (left_over_var_names.size()==0) {
1510 assert(terms.size()<=1);
1511 if (terms.size()==0) {
1512 evalue zero_val;
1513 value_init(zero_val.d);
1514 value_init(zero_val.x.n);
1515 value_set_si(zero_val.d,1);
1516 value_set_si(zero_val.x.n,0);
1517 depth--;
1518 return zero_val; // no term with the given coeffs.
1520 assert(terms.size()==1);
1521 map<map<string,int>, periodic_rational>::const_iterator t=
1522 data.find(*(terms.begin()));
1523 //assert((*t).first==(*(terms.begin())));
1524 depth--;
1525 return create_coef(parameter_names, (*t).second);
1526 } else {
1527 string var_name = left_over_var_names.front();
1528 left_over_var_names.pop_front();
1529 int exp=find_max_exp(terms, var_name);
1530 assert(exp!=-1);
1531 int pos=find_pos_of(var_name, parameter_names);
1532 assert(pos!=-1);
1533 enode* result = new_enode(polynomial, exp+1, pos+1/*from 1 to m*/);
1534 for(int i=0;i<exp+1;i++) {
1535 set<map<string,int> > new_terms =
1536 find_terms_with_var_exp(terms, var_name, i);
1537 value_clear(result->arr[i].d);
1538 result->arr[i] = translate_one_term(parameter_names,
1539 left_over_var_names,
1540 new_terms);
1542 evalue t_result;
1543 value_init(t_result.d);
1544 value_set_si(t_result.d , 0);
1545 t_result.x.p=result;
1546 depth--;
1547 return t_result;
1551 ::evalue EhrhartPolynom::to_evalue(const deque<string>& parameter_names) const
1553 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
1554 cout<<"In EhrhartPolynom::to_evalue: this="<<endl;
1555 cout<<to_string()<<endl;
1557 ::evalue result;
1558 set<string> var_names;
1559 for(map<map<string, int>, periodic_rational>::const_iterator
1560 i=data.begin(); i!=data.end(); i++) {
1561 for(map<string,int>::const_iterator j=(*i).first.begin();
1562 j!=(*i).first.end(); j++)
1563 var_names.insert((*j).first);
1565 deque<string> var_names_dq;
1566 for(set<string>::const_iterator i=var_names.begin();
1567 i!=var_names.end(); i++)
1568 var_names_dq.push_back(*i);
1570 set<map<string,int> > terms;
1571 for(map<map<string,int>, periodic_rational>::const_iterator i=
1572 data.begin(); i!=data.end(); i++) {
1573 terms.insert((*i).first);
1575 result=translate_one_term(parameter_names, var_names_dq,
1576 terms);
1578 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
1579 cout<<"In EhrhartPolynom::to_evalue: result="<<endl;
1580 char** pname=get_pname(parameter_names);
1581 print_evalue(stdout, &result, pname);
1582 delete_pname(pname, parameter_names);
1583 cout<<endl;
1586 return result;
1589 string EhrhartPolynom::to_string() const
1591 if (data.size()==0)
1592 return "0_size0";
1593 string result;
1594 for(map<map<string, int>, periodic_rational>::const_iterator
1595 i=data.begin();
1596 i!=data.end(); i++) {
1597 if (i!=data.begin())
1598 result+=" + ";
1599 // first print coefficient
1600 if (value_notone_p((*i).second.second)) {
1601 char *str;
1602 value_to_str(str, 0, (*i).second.second);
1603 result+= "(1/"+string(str)+")*";
1604 free(str);
1606 result+=(*i).second.first.to_string()+" ";
1607 for(map<string,int>::const_iterator j=(*i).first.begin();
1608 j!=(*i).first.end(); j++)
1609 if ((*j).second==1)
1610 result+=string("*")+(*j).first.c_str();
1611 else
1612 result+=string("*")+(*j).first+"^"+int2string((*j).second);
1614 // strip of spaces at the end
1615 //result+=" ";
1616 return result.substr(0,result.find_last_not_of(" ")+1);
1619 bool EhrhartPolynom::contains_parameters() const
1621 if (data.size()==0)
1622 return false;
1623 Value zero;
1624 value_init(zero);
1625 value_set_si(zero, 0);
1626 PeriodicNumber pn_zero(zero);
1627 value_clear(zero);
1628 for(map<map<string, int>, periodic_rational>::const_iterator
1629 i=data.begin();
1630 i!=data.end(); i++) {
1631 // first print coefficient
1632 if ((*i).second.first == PeriodicNumber(zero))
1633 continue;
1634 for(map<string,int>::const_iterator j=(*i).first.begin();
1635 j!=(*i).first.end(); j++)
1636 if ((*j).first!="")
1637 return true;
1639 return false;
1643 EhrhartPolynom EhrhartPolynom::subst_var
1644 (const string& var,
1645 const map<string,int>& substitution,
1646 const int divisor) const
1648 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
1649 cout<<"In EhrhartPolynom::subst_var: this="<<(string)(*this)<<endl;
1650 cout<<"var="<<var<<endl;
1651 cout<<"substitution=";
1652 for(map<string,int>::const_iterator i=substitution.begin();
1653 i!=substitution.end(); i++) {
1654 cout<<" "<<(((*i).second>=0)?"+":"")<<(*i).second
1655 <<(*i).first;
1657 cout<<" / "<<divisor;
1658 cout<<endl;
1660 // split the current polynomial into 2 polynomials:
1661 // ep_with_var contains all the terms with variable
1662 // var, ep_without_var contains all the terms without
1663 // the variable var.
1664 EhrhartPolynom ep_with_var;
1665 EhrhartPolynom ep_without_var;
1667 for(map<map<string, int>, periodic_rational>::const_iterator
1668 i=data.begin(); i!=data.end(); i++) {
1669 if ((*i).first.find(var)==(*i).first.end())
1670 ep_without_var += EhrhartPolynom((*i).first, (*i).second);
1671 else
1672 ep_with_var += EhrhartPolynom((*i).first, (*i).second);
1674 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
1675 cout<<"In EhrhartPolynom::subst_var:\n ep_with_var="
1676 <<(string)(ep_with_var)<<endl;
1677 cout<<" ep_without_var="
1678 <<(string)(ep_without_var)<<endl;
1681 if (ep_with_var == EhrhartPolynom(0))
1682 return (*this);
1684 // find the maximum exponent to which var is powered in the Ehrhartpolynom
1685 unsigned maxexp=0;
1686 for(map<map<string, int>, periodic_rational>::const_iterator
1687 i=ep_with_var.data.begin(); i!=ep_with_var.data.end(); i++) {
1688 maxexp = std::max(maxexp, (unsigned) (*((*i).first.find(var))).second);
1690 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
1691 cout<<"In EhrhartPolynom::subst_var:\n maxexp="<<maxexp<<endl;
1693 // create for powers of 1 to n, the powers of substitution.
1694 deque<EhrhartPolynom> subt_powers;
1697 map<string,int> one; one[""]=1;
1698 // subst^0 = r
1699 Value val_one;
1700 value_init(val_one);
1701 value_set_si(val_one, 1);
1702 subt_powers.push_back(EhrhartPolynom(one,
1703 periodic_rational(PeriodicNumber(val_one),val_one)));
1704 // subst^1 = subst
1705 EhrhartPolynom subst;
1706 Value tmp_val, div_val;
1707 value_init(tmp_val);
1708 value_init(div_val);
1709 value_set_si(div_val, divisor);
1710 for(map<string,int>::const_iterator i=substitution.begin();
1711 i!=substitution.end(); i++) {
1712 map<string,int> exponent;
1713 exponent[(*i).first]=1;
1714 value_set_si(tmp_val, (*i).second);
1715 subst += EhrhartPolynom(exponent,
1716 periodic_rational(PeriodicNumber(tmp_val),div_val));
1718 value_clear(div_val);
1719 value_clear(tmp_val);
1720 value_clear(val_one);
1721 subt_powers.push_back(subst);
1722 for(unsigned i=2;i<=maxexp;i++) {
1723 // calculate subt_powers[i]
1724 subt_powers.push_back(subt_powers[i-1]*subt_powers[1]);
1726 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
1727 cout<<"In EhrhartPolynom::subst_var:\n subt_powers:"<<endl;
1728 for(unsigned power=0;power<=maxexp;power++) {
1729 cout<<"subt_powers["<<power<<"]= "
1730 <<subt_powers[power].to_string()<<endl;
1734 EhrhartPolynom result=ep_without_var;
1736 for(map<map<string, int>, periodic_rational>::const_iterator
1737 i=ep_with_var.data.begin(); i!=ep_with_var.data.end(); i++) {
1738 assert((*i).first.find(var)!=(*i).first.end());
1739 map<string,int> new_exp=(*i).first;
1740 unsigned power=new_exp[var];
1741 assert(power<=maxexp);
1742 new_exp.erase(new_exp.find(var));
1743 EhrhartPolynom term(new_exp, (*i).second);
1744 term *= subt_powers[power];
1745 result+=term;
1747 result.simplify();
1749 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
1750 cout<<"In EhrhartPolynom::subst_var:\n result=:"<<endl;
1751 cout<<result.to_string()<<endl;
1753 return result;
1756 static inline bool bit(unsigned long value, int bitnr)
1758 return (value>>bitnr)&1;
1761 #if 0
1762 static bool is_constant(const ::Relation& r,
1763 const int set_var,
1764 const string& char_name,
1765 coef_t& value)
1767 // first project away all other variables
1768 ::Relation t(r);
1769 for(int i=1;i<=r.n_set(); i++) {
1770 if (i<set_var) {
1771 // project away current var 1
1772 t = Project(t, i, Set_Var);
1773 } else if (i>set_var) {
1774 // project away current var 2
1775 t = Project(t, i, Set_Var);
1778 // check to see if there's only one EQ-constraint.
1779 t.simplify();
1781 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
1782 cout<<"in is_constant(,"<<set_var<<","<<char_name<<") after projection, the relation is ";
1783 t.print();
1784 cout<<endl;
1787 // now only the set_var variable remains
1788 // assert(t.n_set()==1);
1790 // there should be only 1 disjunction
1791 DNF_Iterator di(t.query_DNF());
1792 if (di==0)
1793 return false;
1794 di++;
1795 if (di!=0)
1796 return false;
1797 di = t.query_DNF();
1799 // There should be no GEQ constraints
1800 if ((*di)->GEQs() != 0)
1801 return false;
1803 // There should be only on EQ constraint
1804 EQ_Iterator ei=(*di)->EQs();
1805 if (ei==0)
1806 return false;
1807 ei++;
1808 if (ei!=0)
1809 return false;
1810 ei=(*di)->EQs();
1812 coef_t coeff_of_var=0;
1813 // now check to see if var equals a constant
1814 for(Constr_Vars_Iter cvi(*ei); cvi; cvi++) {
1815 if (string((*cvi).var->char_name()) != char_name) {
1816 // there are other variables in the EQ constraint
1817 return false;
1819 coeff_of_var = (*cvi).coef;
1822 if (coeff_of_var==0)
1823 return false;
1825 if (coeff_of_var==1) {
1826 value = -(*ei).get_const();
1827 return true;
1829 if (coeff_of_var==-1) {
1830 value = (*ei).get_const();
1831 return true;
1833 return false;
1837 /** equal_in_domain tries to look if the 2 Ehrhart polynomials @a ep1
1838 * and @a ep2 are equal, taking into account the domain in which the
1839 * Ehrhart polynomials are defined. e.g. @a ep1 \f$=n-i^2-j\f$ in
1840 * domain \f$i=n \wedge j=-1\f$ is equal to @a ep2 \f$=-n^2-i-j\f$ in
1841 * domain \f$i=-n\f$. This is true because, when substituting the
1842 * value for \f$i\f$ with \f$n/-n\f$ in the 2 polynomials, the same
1843 * Ehrhart polynomial is generated, i.e. \f$-n^2+n-j\f$.
1845 * @param ep1 is the first Ehrhart polynomial
1846 * @param ep2 is the second Ehrhart polynomial
1847 * @param domain1 is the domain corresponding to @a ep1. The domain must
1848 * be convex.
1849 * @param domain2 is the domain corresponding to @a ep2. The domain must
1850 * be convex.
1852 * @return If the polynomials are equal inside the domain, a pointer
1853 * to an Ehrhart polynomials is returned which represents a form of
1854 * the Ehrhart polynomial which is equal to @a ep1 and @a ep2. In the
1855 * example above, \f$-n^2+n-j\f$ would be returned. */
1857 EhrhartPolynom* EhrhartPolynom::equal_in_domain
1858 (const EhrhartPolynom& ep1, const EhrhartPolynom& ep2,
1859 const ::Relation& _domain1, const ::Relation& _domain2)
1861 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
1862 cout<<"In EhrhartPolynom::equal_in_domain"<<endl;
1863 cout<<"ep1="<<ep1.to_string()<<endl;
1864 cout<<"ep2="<<ep2.to_string()<<endl;
1865 cout<<"domain1="; ::copy(_domain1).print();
1866 cout<<"domain2="; ::copy(_domain2).print();
1869 if (ep1==ep2) {
1870 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
1871 cout<<"ep1==ep2; returning ep1";
1873 return new EhrhartPolynom(ep1);
1877 // do a very simple check.
1878 // If ep2->ep1 in domain1, return ep2.
1879 // If ep1->ep2 in domain2, return ep1.
1881 // first for domain1, substitute constant values in both ep1 and ep2
1883 // ::Relation tmp(::copy(_domain1));
1884 EhrhartPolynom tmp_ep1(ep1), tmp_ep2(ep2);
1886 // project to a variable.
1887 for(int var_to_check=1; var_to_check<= _domain1.n_set(); var_to_check++) {
1888 ::Relation tmp2(::copy(_domain1));
1889 ::coef_t lowerbound=0, upperbound=0;
1890 tmp2.query_variable_bounds(tmp2.set_var(var_to_check),lowerbound, upperbound);
1891 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
1892 cout <<"Checked variable "<<var_to_check<<" in relation ";
1893 tmp2.print();
1894 cout<<" lowerbound="<<lowerbound<<"; upperbound="<<upperbound<<endl;
1896 if (lowerbound != upperbound) {
1897 coef_t value;
1898 bool cst = is_constant(_domain1, var_to_check, tmp2.set_var(var_to_check)->char_name(),
1899 value);
1900 if (cst)
1901 lowerbound = upperbound = value;
1903 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
1904 cout <<"Checked variable "<<var_to_check<<" in relation ";
1905 tmp2.print();
1906 cout<<" lowerbound2="<<lowerbound<<"; upperbound2="<<upperbound<<endl;
1908 if (lowerbound == upperbound)
1910 // the value is constant for this variable.
1911 // find the variable's name
1912 string var_name = tmp2.set_var(var_to_check)->char_name();
1913 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=2)
1914 cout <<"variable "<<var_name<<"("<<var_to_check<<") has constant value "
1915 <<lowerbound<<endl;
1916 map<string, int> substitution;
1917 substitution[""] = lowerbound;
1918 tmp_ep1=tmp_ep1.subst_var(var_name, substitution);
1919 tmp_ep2=tmp_ep2.subst_var(var_name, substitution);
1922 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
1923 cout<<"In domain1: tmp_ep1="<<tmp_ep1.to_string()<<endl;
1924 cout<<" tmp_ep2="<<tmp_ep2.to_string()<<endl;
1927 if (tmp_ep1 == tmp_ep2) {
1928 // ep1 == ep2 in domain1: return ep2
1929 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
1930 cout<<"In EhrhartPolynom::equal_in_domain"<<endl;
1931 cout<<"Found ep1="<<tmp_ep1.to_string()<<endl;
1932 cout<<" ep2="<<tmp_ep2.to_string()<<endl;
1933 cout<<"In domain:";
1934 ::copy(_domain1).print(); cout<<endl;
1936 return new EhrhartPolynom(ep2);
1940 // next, check for domain2; substitute constant values in both ep1 and ep2
1942 // ::Relation tmp(::copy(_domain2));
1943 EhrhartPolynom tmp_ep1(ep1), tmp_ep2(ep2);
1945 // project to a variable.
1946 for(int var_to_check=1; var_to_check<= _domain2.n_set(); var_to_check++) {
1947 ::Relation tmp2(::copy(_domain2));
1948 ::coef_t lowerbound, upperbound;
1949 tmp2.query_variable_bounds(tmp2.set_var(var_to_check),lowerbound, upperbound);
1950 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
1951 cout <<"Checked variable "<<var_to_check<<" in relation ";
1952 tmp2.print();
1953 cout<<" lowerbound="<<lowerbound<<"; upperbound="<<upperbound<<endl;
1955 if (lowerbound != upperbound) {
1956 coef_t value;
1957 bool cst = is_constant(_domain2, var_to_check, tmp2.set_var(var_to_check)->char_name(),
1958 value);
1959 if (cst)
1960 lowerbound = upperbound = value;
1962 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
1963 cout <<"Checked variable "<<var_to_check<<" in relation ";
1964 tmp2.print();
1965 cout<<" lowerbound2="<<lowerbound<<"; upperbound2="<<upperbound<<endl;
1967 if (lowerbound == upperbound)
1969 // the value is constant for this variable.
1970 // find the variable's name
1971 string var_name = tmp2.set_var(var_to_check)->char_name();
1972 if(DebugBlackboard.debug("EHRHARTPOLYNOM")>=2)
1973 cout <<"variable "<<var_name<<"("<<var_to_check<<") has constant value "
1974 <<lowerbound<<endl;
1975 map<string, int> substitution;
1976 substitution[""] = lowerbound;
1977 tmp_ep1=tmp_ep1.subst_var(var_name, substitution);
1978 tmp_ep2=tmp_ep2.subst_var(var_name, substitution);
1981 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
1982 cout<<"In domain2: tmp_ep1="<<tmp_ep1.to_string()<<endl;
1983 cout<<" tmp_ep2="<<tmp_ep2.to_string()<<endl;
1986 if (tmp_ep1 == tmp_ep2) {
1987 // ep1 == ep2 in domain2: return ep1
1988 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
1989 cout<<"In EhrhartPolynom::equal_in_domain"<<endl;
1990 cout<<"Found ep1="<<tmp_ep1.to_string()<<endl;
1991 cout<<" ep2="<<tmp_ep2.to_string()<<endl;
1992 cout<<"In domain:";
1993 ::copy(_domain2).print(); cout<<endl;
1995 return new EhrhartPolynom(ep1);
2000 ::Relation domain1=::copy(_domain1);
2001 ::Relation domain2=::copy(_domain2);
2003 map<string, map<string,int> > var2subst_in_domain1;
2004 map<string, map<string,int> > var2subst_in_domain2;
2006 set<string> vars_in_domain1;
2007 set<string> vars_in_domain2;
2009 // make sure that that GEQ constraints are translated into
2010 // EQ constraints, where possible.
2011 domain1.simplify(2,2);
2012 domain2.simplify(2,2);
2014 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
2015 cout<<"domain1=";domain1.print(); cout<<endl;
2016 cout<<"domain2=";domain2.print(); cout<<endl;
2019 int counter1=0;
2020 for(DNF_Iterator di(domain1.query_DNF()); di; di++) {
2021 assert(counter1==0); // domain1 must be convex!
2022 counter1++;
2023 for(EQ_Iterator ei=(*di)->EQs(); ei; ei++) {
2024 map<string,int> equalities;
2025 int const_coef;
2026 for(Constr_Vars_Iter cvi(*ei); cvi; cvi++) {
2027 if (string((*cvi).var->char_name()) ==
2028 string(""))
2029 goto next_equality;
2030 equalities[(*cvi).var->char_name()] = (*cvi).coef;
2032 const_coef = (*ei).get_const();
2033 // insert equalities into var2subst_in_domain1
2034 for(map<string,int>::const_iterator i=equalities.begin();
2035 i!=equalities.end(); i++) {
2036 map<string,int> subst_coefs;
2037 // for now, only handle variables with coeffs 1 or -1
2038 // TODO: handle other coeffs
2039 if ((*i).second==1 || (*i).second==-1) {
2040 for(map<string,int>::const_iterator j=equalities.begin();
2041 j!=equalities.end(); j++) {
2042 if (i!=j) {
2043 if ((*i).second<0) subst_coefs[(*j).first]=(*j).second;
2044 else subst_coefs[(*j).first]= -(*j).second;
2047 if ((*i).second<0) subst_coefs[""] = const_coef;
2048 else subst_coefs[""] = -const_coef;
2049 var2subst_in_domain1[(*i).first] = subst_coefs;
2053 next_equality: ;
2057 int counter2=0;
2058 for(DNF_Iterator di(domain2.query_DNF()); di; di++) {
2059 assert(counter2==0); // domain2 must be convex!
2060 counter2++;
2061 for(EQ_Iterator ei=(*di)->EQs(); ei; ei++) {
2062 map<string,int> equalities;
2063 int const_coef;
2064 for(Constr_Vars_Iter cvi(*ei); cvi; cvi++) {
2065 if (string((*cvi).var->char_name()) == string(""))
2066 goto next_equality2;
2067 equalities[(*cvi).var->char_name()] = (*cvi).coef;
2069 const_coef = (*ei).get_const();
2070 // insert equalities into var2subst_in_domain1
2071 for(map<string,int>::const_iterator i=equalities.begin();
2072 i!=equalities.end(); i++) {
2073 map<string,int> subst_coefs;
2074 // for now, only handle variables with coeffs 1 or -1
2075 // TODO: handle other coeffs
2076 if ((*i).second==1 || (*i).second==-1) {
2077 for(map<string,int>::const_iterator j=equalities.begin();
2078 j!=equalities.end(); j++) {
2079 if (i!=j) {
2080 if ((*i).second<0) subst_coefs[(*j).first]=(*j).second;
2081 else subst_coefs[(*j).first]= -(*j).second;
2084 if ((*i).second<0) subst_coefs[""] = const_coef;
2085 else subst_coefs[""] = -const_coef;
2086 var2subst_in_domain2[(*i).first] = subst_coefs;
2089 next_equality2: ;
2093 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
2094 cout<<"var2subst_in_domain1("
2095 <<var2subst_in_domain1.size()<<")"<<endl;
2096 cout<<"var2subst_in_domain2("
2097 <<var2subst_in_domain2.size()<<")"<<endl;
2098 for(map<string, map<string,int> >::const_iterator
2099 i=var2subst_in_domain1.begin();
2100 i!=var2subst_in_domain1.end() ;i++) {
2101 cout<<"var2subst_in_domain1["<<(*i).first<<"]= {";
2102 for(map<string,int>::const_iterator j=(*i).second.begin();
2103 j!=(*i).second.end(); j++)
2104 cout<<"+"<<(*j).second<<(*j).first;
2105 cout<<"}"<<endl;
2107 for(map<string, map<string,int> >::const_iterator
2108 i=var2subst_in_domain2.begin();
2109 i!=var2subst_in_domain2.end() ;i++) {
2110 cout<<"var2subst_in_domain2["<<(*i).first<<"]= {";
2111 for(map<string,int>::const_iterator j=(*i).second.begin();
2112 j!=(*i).second.end(); j++)
2113 cout<<"+"<<(*j).second<<(*j).first;
2114 cout<<"}"<<endl;
2118 // now check for every possible combination of substitutions if
2119 // equality between Ehrhart Polynomials can be reached.
2120 if (var2subst_in_domain2.size()>=30 ||
2121 var2subst_in_domain1.size()>=30) {
2122 // to many combinations, bail out
2123 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=3)
2124 cout<<"too many combinations, bailing out."<<endl;
2125 return 0;
2127 unsigned long nr_combinations_ep1 = 1<<var2subst_in_domain1.size();
2128 unsigned long nr_combinations_ep2 = 1<<var2subst_in_domain2.size();
2129 // generate combinations
2130 deque<EhrhartPolynom> ep1_variations;
2131 deque<EhrhartPolynom> ep2_variations;
2132 for(unsigned long i=0;i<nr_combinations_ep1;i++) {
2133 EhrhartPolynom ep(ep1);
2134 unsigned long counter=0;
2135 for(map<string, map<string,int> >::const_iterator
2136 j=var2subst_in_domain1.begin();
2137 j!=var2subst_in_domain1.end(); j++, counter++) {
2138 if (bit(i,counter))
2139 ep=ep.subst_var((*j).first, (*j).second);
2141 ep1_variations.push_back(ep);
2143 for(unsigned long i=0;i<nr_combinations_ep2;i++) {
2144 EhrhartPolynom ep(ep2);
2145 unsigned long counter=0;
2146 for(map<string, map<string,int> >::const_iterator
2147 j=var2subst_in_domain2.begin();
2148 j!=var2subst_in_domain2.end(); j++, counter++) {
2149 if (bit(i,counter))
2150 ep=ep.subst_var((*j).first, (*j).second);
2152 ep2_variations.push_back(ep);
2155 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
2156 cout<<"ep1_variations("<<ep1_variations.size()<<"):"<<endl;
2157 for(unsigned long i=0;i<ep1_variations.size(); i++)
2158 cout<<ep1_variations[i].to_string()<<endl;
2159 cout<<"ep2_variations("<<ep2_variations.size()<<"):"<<endl;
2160 for(unsigned long i=0;i<ep2_variations.size(); i++)
2161 cout<<ep2_variations[i].to_string()<<endl;
2164 for(unsigned long i=0;i<ep1_variations.size();i++)
2165 for(unsigned long j=0;j<ep2_variations.size();j++) {
2166 if (ep1_variations[i]==ep2_variations[j]) {
2167 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
2168 cout<<"Returning "<<ep1_variations[i].to_string()<<endl;
2170 return new EhrhartPolynom(ep1_variations[i]);
2173 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
2174 cout<<"Returning null"<<endl;
2177 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=2) {
2178 cout<<"not equal."<<endl;
2180 return 0;
2182 #endif
2185 * get_affine_polynomials returns the Ehrhart polynomials as a set
2186 * of affine functions when possible. If not possible, it returns
2187 * the null pointer.
2189 struct EhrhartPolynom::affine*
2190 EhrhartPolynom::get_affine_polynomials() const
2192 if (DebugBlackboard.debug("AFFINEPOLYNOM")>=2) {
2193 cout<<"In EhrhartPolynom::get_affine_polynomials: this="
2194 <<to_string()<<endl;
2197 deque<string> var_names;
2198 // first check if this polynomial is representable as an
2199 // affine polynomial.
2200 for(map<map<string,int>, periodic_rational>::const_iterator
2201 i=data.begin(); i!=data.end(); i++) {
2202 unsigned nr_vars=0;
2203 if ((*i).first.size()==0) {
2204 //constant term
2205 var_names.push_back("");
2206 } else {
2207 for(map<string,int>::const_iterator j=(*i).first.begin();
2208 j!=(*i).first.end(); j++) {
2209 if ((*j).second > 1) // power >1 => not affine
2211 if (DebugBlackboard.debug("AFFINEPOLYNOM")>=2) {
2212 cout<<"Not affine since power of "<<(*j).first<<" is "
2213 <<(*j).second<<" >1."<<endl;
2215 return 0;
2217 if ((*j).first!=string("")) {
2218 nr_vars++;
2219 if (std::find(var_names.begin(), var_names.end(), (*j).first) ==
2220 var_names.end())
2221 var_names.push_back((*j).first);
2224 if (nr_vars > 1) // more than 1 variable in the term => not affine
2226 if (DebugBlackboard.debug("AFFINEPOLYNOM")>=2) {
2227 cout<<"Not affine since nr_vars="<<nr_vars<<" >1."<<endl;
2229 return 0;
2234 if (DebugBlackboard.debug("AFFINEPOLYNOM")>=4) {
2235 cout<<"var_names("<<var_names.size()<<")=";
2236 for(deque<string>::const_iterator i=var_names.begin();
2237 i!=var_names.end(); i++) {
2238 cout<<"'"<<(*i)<<"' ";
2240 cout<<endl;
2243 struct affine* result = new affine;
2244 deque<string> var_names_as_param;
2245 set<string> params_set;
2246 for(map<map<string,int>, periodic_rational>::const_iterator
2247 i=data.begin(); i!=data.end(); i++) {
2248 set<string> p1=(*i).second.first.get_params();
2249 for(set<string>::const_iterator j=p1.begin(); j!=p1.end(); j++)
2250 params_set.insert(*j);
2252 for(set<string>::const_iterator i=params_set.begin();
2253 i!=params_set.end(); i++)
2254 var_names_as_param.push_back(*i);
2256 map<string, set<int> > periods;
2258 for(map<map<string,int>, periodic_rational>::const_iterator
2259 i=data.begin(); i!=data.end(); i++) {
2260 if (DebugBlackboard.debug("AFFINEPOLYNOM")>=6) {
2261 cout<<"Checking params in "<<(*i).second.first.to_string()<<":";
2263 for(unsigned j=0; j!=var_names_as_param.size(); j++) {
2264 if ((*i).second.first.has_param(var_names_as_param[j])) {
2265 if (DebugBlackboard.debug("AFFINEPOLYNOM")>=6) {
2266 cout<<"'"<<var_names_as_param[j]<<"' ";
2268 periods[var_names_as_param[j]].insert
2269 ((*i).second.first.get_period(var_names_as_param[j]));
2272 if (DebugBlackboard.debug("AFFINEPOLYNOM")>=6) {
2273 cout<<endl;
2278 if (DebugBlackboard.debug("AFFINEPOLYNOM")>=4) {
2279 cout<<"var_names_as_param("
2280 <<var_names_as_param.size()<<")=";
2281 for(unsigned i=0;i<var_names_as_param.size(); i++) {
2282 cout<<"'"<<var_names_as_param[i]<<"' ";
2284 cout<<endl;
2285 cout<<"periods=";
2286 for(map<string,set<int> >::const_iterator i=periods.begin();
2287 i!=periods.end(); i++) {
2288 cout<<"('"<<(*i).first<<"',";
2289 for(set<int>::const_iterator j=(*i).second.begin();
2290 j!=(*i).second.end(); j++)
2291 cout<<(*j)<<" ";
2292 cout<<") ";;
2294 cout<<endl;
2297 // for every variable, find the lcm of the periods.
2298 map<string, int> lcm_period;
2299 for(map<string, set<int> >::const_iterator i=periods.begin();
2300 i!=periods.end(); i++) {
2301 int plcm=1;
2302 for(set<int>::const_iterator j=(*i).second.begin();
2303 j!=(*i).second.end(); j++)
2304 plcm=lcm(*j, plcm);
2305 lcm_period[(*i).first] = plcm;
2308 if (DebugBlackboard.debug("AFFINEPOLYNOM")>=3) {
2309 cout<<"lcm_period=";
2310 for(map<string,int>::const_iterator i=lcm_period.begin();
2311 i!=lcm_period.end(); i++)
2312 cout<<"('"<<(*i).first<<"',"<<(*i).second<<") ";
2313 cout<<endl;
2317 result->period = lcm_period;
2319 // start creating the affine structure:
2320 // the number of combinations to be examined are
2321 // all the compination of periods for the different variables.
2322 long nr_comb=1;
2323 for(map<string,int>::const_iterator i=lcm_period.begin();
2324 i!=lcm_period.end(); i++) {
2325 nr_comb *= (*i).second;
2327 if (DebugBlackboard.debug("AFFINEPOLYNOM")>=3) {
2328 cout<<"nr_comb="<<nr_comb<<endl;
2330 deque<long> strides;
2331 for(unsigned j=0;j<var_names_as_param.size();j++) {
2332 if (j==0)
2333 strides.push_back(1);
2334 else
2335 strides.push_back(strides[j-1] * lcm_period[var_names_as_param[j-1]]);
2337 if (var_names_as_param.size()==0) {
2338 assert(nr_comb==1);
2340 else
2341 strides.push_back(strides.back() * lcm_period[var_names_as_param.back()]);
2342 if (DebugBlackboard.debug("AFFINEPOLYNOM")>=3) {
2343 cout<<"strides=";
2344 for(deque<long>::const_iterator i=strides.begin(); i!=strides.end(); i++)
2345 cout<<(*i)<<" ";
2346 cout<<endl;
2349 for(long i=0;i<nr_comb;i++) {
2350 // create index
2351 if (DebugBlackboard.debug("AFFINEPOLYNOM")>=4) {
2352 cout<<"i="<<i<<endl;
2354 map<string,int> index;
2355 for(unsigned j=0;j<var_names_as_param.size();j++) {
2356 // compute value of
2357 // var_names_as_param[i] % lcm_period[var_names_as_param[i]]
2358 assert(strides.size()>j+1);
2359 int remainder = (i%(strides[j+1]) / strides[j]);
2360 index[var_names_as_param[j]] = remainder;
2362 // now find the coefficients for every term and place it
2363 // in the struct affine result.
2364 map<string,int> affine_coef;
2365 Value lcm_denumerator;
2366 value_init(lcm_denumerator);
2367 value_set_si(lcm_denumerator, 1);
2368 for(map<map<string,int>, periodic_rational>::const_iterator
2369 j=data.begin(); j!=data.end(); j++) {
2370 value_lcm(lcm_denumerator ,lcm_denumerator, (*j).second.second);
2373 if (DebugBlackboard.debug("AFFINEPOLYNOM")>=4) {
2374 char* str;
2375 value_to_str(str, 0, lcm_denumerator);
2376 cout<<"lcm_denumerator="<<str<<endl;
2377 free(str);
2379 Value tmp;
2380 value_init(tmp);
2381 for(map<map<string,int>, periodic_rational>::const_iterator
2382 j=data.begin(); j!=data.end(); j++) {
2383 string var="";
2384 for(map<string,int>::const_iterator k=(*j).first.begin();
2385 k!=(*j).first.end(); k++) {
2386 assert(var=="");
2387 assert((*k).second==1);
2388 var=(*k).first;
2390 // filter out the parameters not occuring in the PeriodicNumber
2391 map<string,int> part_index;
2392 const PeriodicNumber& pn=(*j).second.first;
2393 for(map<string,int>::const_iterator k=index.begin();
2394 k!=index.end(); k++) {
2395 if (pn.has_param((*k).first))
2396 part_index[(*k).first] = (*k).second;
2398 if (DebugBlackboard.debug("AFFINEPOLYNOM")>=4) {
2399 cout<<"part_index= ";
2400 for(map<string,int>::const_iterator l=part_index.begin();
2401 l!=part_index.end(); l++)
2402 cout<<"('"<<(*l).first<<"',"<<(*l).second<<") ";
2403 cout<<endl;
2405 value_multiply(tmp, pn[part_index], lcm_denumerator);
2406 value_division(tmp, tmp, (*j).second.second);
2407 affine_coef[var] = VALUE_TO_INT(tmp); //pn[part_index]*lcm_denumerator/(*j).second.second;
2408 if (DebugBlackboard.debug("AFFINEPOLYNOM")>=4) {
2409 cout<<"affine_coef['"<<var<<"']="<<affine_coef[var]<<endl;
2412 value_clear(tmp);
2413 // only push back a polynomial if it is different from 0
2414 bool is_zero=true;
2415 for(map<string,int>::const_iterator j=affine_coef.begin();
2416 j!=affine_coef.end(); j++)
2417 if ((*j).second!=0) {
2418 is_zero=false;
2419 break;
2421 if (!is_zero) {
2422 result->polynomial.push_back(affine_coef);
2423 result->offset.push_back(index);
2424 result->denumerator.push_back(VALUE_TO_INT(lcm_denumerator));
2426 value_clear(lcm_denumerator);
2429 if (DebugBlackboard.debug("AFFINEPOLYNOM")>=3) {
2430 cout<<"In EhrhartPolynom::get_affine_polynomials: returning"<<endl;
2431 cout<<result->to_string()<<endl;
2433 return result;
2436 string EhrhartPolynom::affine::to_string() const {
2437 string result;
2438 result+="period=";
2439 for(map<string,int>::const_iterator i=period.begin();
2440 i!=period.end(); i++)
2441 result+="('"+(*i).first+"',"+int2string((*i).second)+") ";
2442 result+="\n";
2443 result+="nr_polynomials = "+int2string(size())+"\n";
2444 for(unsigned i=0;i<size();i++) {
2445 result+="polynomial["+int2string(i)+"]= (";
2446 for(map<string,int>::const_iterator j=polynomial[i].begin();
2447 j!=polynomial[i].end(); j++) {
2448 result+= (((*j).second>=0)?"+":"")+
2449 int2string((*j).second)+(*j).first;
2451 result+=")/"+int2string(denumerator[i]);
2452 result+=" iff ";
2453 for(map<string, int>::const_iterator k=offset[i].begin();
2454 k!=offset[i].end(); k++) {
2455 assert(period.find((*k).first)!=period.end());
2456 int p=(*(period.find((*k).first))).second;
2457 result+="("+(*k).first+"%"+int2string(p)+"="+int2string((*k).second)+")";
2459 result+="\n";
2462 return result;
2465 #if 0
2466 Expression* EhrhartPolynom::get_AST_representation() const
2468 // Currently, this function is only implemented for Ehrhart
2469 // Polynomials with period 1.
2470 // TODO: handle polynomials with larger period.
2472 if (DebugBlackboard.debug("EHRHARTxTOxAST")>=3) {
2473 cout<<"In EhrhartPolynom::get_AST_representation: about to convert"<<endl;
2474 cout<<this->to_string()<<endl;
2477 for(map<map<string, int>, periodic_rational>::const_iterator i=data.begin();
2478 i!=data.end(); i++) {
2479 if ((*i).second.first.datasize > 1) {
2480 // The period is larger than 1, which cannot handle right now.
2481 // so return a null pointer.
2482 return 0;
2487 Expression* expression = 0;
2488 // create the different terms in the polytope
2489 Value coef;
2490 value_init(coef);
2491 for(map<map<string, int>, periodic_rational>::const_iterator i=data.begin();
2492 i!=data.end(); i++) {
2493 assert((*i).second.first.datasize == 1);
2494 // assert((*i).second.second == 1);
2495 // get the coefficient of the term
2496 value_assign(coef, (*i).second.first.data[0]);
2497 Expression* term = 0;
2498 if (value_notone_p(coef) || (*i).first.size()==0)
2499 term = new Constant((long long)VALUE_TO_LONG(coef));
2500 // build the terms
2501 for(map<string, int>::const_iterator j=(*i).first.begin();
2502 j!=(*i).first.end(); j++) {
2503 for(int p=0;p<(*j).second;p++) {
2504 // (*j).second is the exponent of the variable in the term.
2505 if (term!=0)
2506 term = new BinaryExpression(term,'*', new ScalarRef((*j).first.c_str()));
2507 else
2508 term = new ScalarRef((*j).first.c_str());
2511 // build the overall polynomial
2512 if (expression==0)
2513 expression=term;
2514 else
2515 expression = new BinaryExpression(expression, '+', term);
2516 if (value_notone_p((*i).second.second)) {
2517 expression = new BinaryExpression(expression, '/',
2518 new Constant((long long)VALUE_TO_LONG((*i).second.second)));
2521 value_clear(coef);
2522 if (data.size()==0)
2523 expression = new Constant(0LL);
2525 if (DebugBlackboard.debug("EHRHARTxTOxAST")>=3) {
2526 cout<<"In EhrhartPolynom::get_AST_representation: converted into"<<endl;
2527 cout<<expression->to_string()<<endl;
2530 return expression;
2532 #endif