2 #include "ehrhartpolynom.h"
6 #include "polylib_tools.h"
7 #include "omega_tools.h"
10 // only legal if value==GMP!!
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)))
17 static long gcd(long a
, long b
)
19 if (DebugBlackboard
.debug("EHRHARTPOLYNOM")>=3) {
20 cout
<<"gcd("<<a
<<", "<<b
<<")=";
28 result
= (b
<0)?(-b
):b
;
29 if (DebugBlackboard
.debug("EHRHARTPOLYNOM")>=3) {
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
;
44 string
int2string(int i
)
59 if (negative
) *--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());
74 void delete_pname(char** pname
, const deque
<string
>& parameters
)
76 for(unsigned i
=0;i
<parameters
.size();i
++)
83 string
value2string(const Value v
) {
85 value_to_str(str
, str
, v
);
92 inline Value
& PeriodicNumber::operator[](const map
<string
, int>& _index
) {
93 if (DebugBlackboard
.debug("EHRHARTPOLYNOM")>=4) {
94 cout
<<"in PeriodicNumber::operator[]"<<endl
;
96 for(map
<string
, int>::const_iterator i
=_index
.begin();
98 cout
<<"("<<(*i
).first
<<", "<<(*i
).second
<<") ";
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
;
109 assert(index
<datasize
);
110 if (DebugBlackboard
.debug("EHRHARTPOLYNOM")>=4) {
111 cout
<<"index="<<index
<<endl
;
112 cout
<<"data[index]="<<value2string(data
[index
])<<endl
;
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
;
123 for(map
<string
, int>::const_iterator i
=_index
.begin();
124 i
!=_index
.end(); i
++)
125 cout
<<"("<<(*i
).first
<<", "<<(*i
).second
<<") ";
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
;
136 assert(index
<datasize
);
137 if (DebugBlackboard
.debug("EHRHARTPOLYNOM")>=4) {
138 cout
<<"index="<<index
<<endl
;
139 cout
<<"data[index]="<<value2string(data
[index
])<<endl
;
144 static long gcd(long a, long b)
146 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
147 cout<<"gcd("<<a<<", "<<b<<")=";
155 result = (b<0)?(-b):b;
156 if (DebugBlackboard.debug("EHRHARTPOLYNOM")>=3) {
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
++) {
200 (pn1
.parameter_names
.find(*i
)!=pn1
.parameter_names
.end());
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
;
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.
230 for(unsigned long i
=0;i
<result
.datasize
;i
++) {
231 // find out which period-values for which parameters
233 map
<string
, int> index
;
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())
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())
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
);
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
;
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
;
300 void PeriodicNumber::get_gcd(Value
& v
) const
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
)
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
));
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
++) {
360 (pn1
.parameter_names
.find(*i
)!=pn1
.parameter_names
.end());
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
;
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
++)
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
<<") ";
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.
403 for(unsigned long i
=0;i
<result
.datasize
;i
++) {
404 // find out which period-values for which parameters
406 map
<string
, int> index
;
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())
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())
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
<<") ";
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
);
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
++)
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
++) {
478 value_to_str(str
,0, result
.data
[i
]);
488 double PeriodicNumber::to_double() const
491 return VALUE_TO_DOUBLE(data
[0]);
494 bool PeriodicNumber::smaller_than(const PeriodicNumber
& pn
) const
496 if (datasize
!=1 || pn
.datasize
!=1)
498 return value_lt(data
[0], pn
.data
[0]);
501 string
PeriodicNumber::to_string() const
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
513 map
<string
, int> index
;
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)
530 value_assign(val
,((*this)[index
]));
532 value_to_str(valstr
,valstr
,val
);
533 result
+= string(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) {
541 if ((*j
).first
!=string(""))
543 result
+=(*j
).first
+", ";
549 if (result
.size()>=2 && result
.substr(result
.size()-2, result
.size())
551 result
.erase(result
.size()-2, result
.size());
553 if (DebugBlackboard
.debug("EHRHARTPOLYNOM")>=3) {
555 debug_str
+="(\n\tparameter_names=";
556 for(set
<string
>::const_iterator i
=parameter_names
.begin();
557 i
!=parameter_names
.end(); 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
++) {
570 value_to_str(str
,0, data
[i
]);
571 debug_str
+=str
+string(" ");
581 static int find_pos_of(const string
& name
,
582 const deque
<string
>& names
)
584 for(unsigned i
=0;i
<names
.size(); i
++)
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
,
606 if (free_vars
.size()==0) {
607 value_set_si(ev
.d
,1);
608 value_assign(ev
.x
.n
, pn
[bound_vars
]);
612 // find an appropriate var_name, i.e., different from ""
614 for(set
<string
>::const_iterator i
=free_vars
.begin();
615 i
!=free_vars
.end(); i
++)
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
;
625 value_set_si(ev
.d
,1);
626 value_assign(ev
.x
.n
, pn
[index
]);
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);
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
)
649 map
<string
,int> bound_vars
;
650 set
<string
> free_vars
=this->parameter_names
;
653 value_init(result
.d
);
654 value_init(result
.x
.n
);
655 pn_to_evalue(*this, bound_vars
, free_vars
, ep_parameter_names
, result
);
660 static bool check_for_polynomials(::enode
* e
)
663 if (e
->type
==polynomial
)
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
))
673 static void find_names(::enode
* e
,
674 const deque
<string
>& parameter_names
,
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
)
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
)
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
);
709 denominators
.insert(e
->arr
[i
].d
);
715 static void fill_in_values(PeriodicNumber
& pn
,
717 const deque
<string
>& parameter_names
,
718 map
<string
, int>& name2lcm_period
,
719 map
<string
, set
<int> >& name2indices
,
723 assert(e
->type
==periodic
);
726 if(DebugBlackboard
.debug("EHRHARTPOLYNOM")>=3) {
727 cout
<<"Entering fill_in_values (depth "<<depth
<<"):"<<endl
;
729 char **pname
=get_pname(parameter_names
);
730 ::print_enode(stdout
, e
, pname
);
731 delete_pname(pname
, parameter_names
);
733 cout
<<"parameter_names= ";
734 for(deque
<string
>::const_iterator i
=parameter_names
.begin();
735 i
!=parameter_names
.end(); i
++)
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
<<")"<<" ";
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())
756 cout
<<"lcm_denom= "<<lcm_denom
<<endl
;
759 string name
=parameter_names
[e
->pos
-1];
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())
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
);
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
;
810 for(map
<string
, set
<int> >::const_iterator k
=name2indices
.begin();
811 k
!=name2indices
.end(); k
++,t
++) {
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
));
825 /** handle_periodic_enode processes an enode
827 * @return a pair. The first part is the periodic number
828 * The second part is the denominator of the
831 static pair
<PeriodicNumber
,int> handle_periodic_enode
832 (const deque
<string
>& parameter_names
,
835 if(DebugBlackboard
.debug("EHRHARTPOLYNOM")>=3) {
836 cout
<<"Entering handle_periodic_enode"<<endl
;
838 char **pname
=get_pname(parameter_names
);
839 ::print_enode(stdout
, e
, pname
);
840 delete_pname(pname
, parameter_names
);
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
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())
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());
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
<<") ";
888 // 5. find lcm of all denominators
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
,
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
,
922 static int depth
=0; //only used for debugging
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
++)
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
<<")"<<" ";
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
);
949 if (current_periodic
.is_zero())
950 pn
=PeriodicNumber(e
->x
.n
);
952 pn
= current_periodic
* e
->x
.n
;
953 data
[current_exponents
] =
954 pair
<PeriodicNumber
, Value
>(pn
, current_denumerator
);
960 if(DebugBlackboard
.debug("EHRHARTPOLYNOM")>=3) {
961 cout
<<"The enode is a polynomial enode."<<endl
;
965 param_name
= parameter_names
[en
->pos
-1];
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
;
974 process_sub_part_of_evalue(data
, parameter_names
,
975 exp
, current_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
);
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
;
1009 return EhrhartPolynom(exponent
,
1010 EhrhartPolynom::periodic_rational(pn
,e
.d
));
1012 EhrhartPolynom result
;
1017 if(DebugBlackboard
.debug("EHRHARTPOLYNOM")>=3) {
1018 cout
<<"The enode is a polynomial enode."<<endl
;
1022 param_name
= parameter_names
[en
->pos
-1];
1025 const int degree
=en
->size
-1;
1026 for(int i
=0;i
<=degree
;i
++) {
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
);
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
;
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
;
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
);
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
);
1088 map
<string
,int> current_exponents
;
1090 process_sub_part_of_evalue(data
, parameter_names
,
1091 current_exponents
, t
, 1, e
);
1094 data
= convert_evalue(*e
, parameter_names
).data
;
1096 if(DebugBlackboard
.debug("EHRHARTPOLYNOM")>=2) {
1097 cout
<<"In EhrhartPolynom(e): constructed following EhrhartPolynom:"<<endl
;
1098 cout
<<to_string()<<endl
;
1102 EhrhartPolynom::~EhrhartPolynom() {
1105 for(map<map<string, int>, periodic_rational>::iterator i=
1106 data.begin(); i!=data.end(); i++)
1107 value_clear((*i).second.second);
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
;
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);
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
;
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
;
1162 if(DebugBlackboard
.debug("EHRHARTPOLYNOM")>=2) {
1163 cout
<<"In EhrhartPolynom()::operator+: result of addition"<<endl
;
1164 cout
<<result
.to_string()<<endl
;
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
;
1180 value_init(div1
); value_init(div2
);
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
++) {
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
);
1220 value_clear(div1
); value_clear(div2
); value_clear(lcm_val
); value_clear(gcd_product_denominator
);
1221 value_clear(gcd_of_product
);
1224 if(DebugBlackboard
.debug("EHRHARTPOLYNOM")>=2) {
1225 cout
<<"In EhrhartPolynom()::operator*: result of multiplication:"<<endl
;
1226 cout
<<result
.to_string()<<endl
;
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
);
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())
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
);
1279 new_data
[exponent
] = (*i
).second
;
1284 value_clear(mult_p1
);
1285 value_clear(mult_p2
);
1286 value_clear(lcm_denominator
);
1287 if (data
.size()==0) {
1290 value_set_si(val
, 0);
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
;
1303 double EhrhartPolynom::to_double() const {
1304 // Should only be called on constant EhrhartPolynomials (i.e. no parameters)!
1305 EhrhartPolynom ep1
=(*this);
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
;
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 */
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
);
1338 if(DebugBlackboard
.debug("EHRHARTPOLYNOM")>=3) {
1339 cout
<<"result of comparison is "<<result
<<endl
;
1344 bool EhrhartPolynom::operator==(const EhrhartPolynom
& _ep2
) const {
1345 EhrhartPolynom ep1
=(*this);
1346 EhrhartPolynom ep2
=_ep2
;
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
;
1368 if (i
!=data
.end() || j
!=_ep2
.data
.end()) {
1369 if(DebugBlackboard
.debug("EHRHARTPOLYNOM")>=3) {
1370 cout
<<"result 2 of comparison is false."<<endl
;
1374 if(DebugBlackboard
.debug("EHRHARTPOLYNOM")>=3) {
1375 cout
<<"result 3 of comparison is true."<<endl
;
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
);
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
);
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())
1417 static set
<map
<string
,int> > find_terms_with_var_exp
1418 (const set
<map
<string
,int> >&terms
,
1419 const string
& varname
,
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();
1429 cout
<<"'"<<(*j
).first
<<"^"<<(*j
).second
<<"'";
1433 cout
<<"varname = '"<<varname
<<"'"<<endl
;
1434 cout
<<"exp = "<<exp
<<endl
;
1436 set
<map
<string
, int> > result
;
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
)
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
)
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();
1459 cout
<<"'"<<(*j
).first
<<"^"<<(*j
).second
<<"'";
1468 static int find_max_exp(const set
<map
<string
,int> >& terms
,
1469 const string
& var_name
)
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
);
1476 result
= std::max(result
, (*j
).second
);
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
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
]<<" ";
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();
1503 cout
<<"'"<<(*j
).first
<<"^"<<(*j
).second
<<"'";
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) {
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);
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())));
1525 return create_coef(parameter_names
, (*t
).second
);
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
);
1531 int pos
=find_pos_of(var_name
, parameter_names
);
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
,
1543 value_init(t_result
.d
);
1544 value_set_si(t_result
.d
, 0);
1545 t_result
.x
.p
=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
;
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
,
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
);
1589 string
EhrhartPolynom::to_string() const
1594 for(map
<map
<string
, int>, periodic_rational
>::const_iterator
1596 i
!=data
.end(); i
++) {
1597 if (i
!=data
.begin())
1599 // first print coefficient
1600 if (value_notone_p((*i
).second
.second
)) {
1602 value_to_str(str
, 0, (*i
).second
.second
);
1603 result
+= "(1/"+string(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
++)
1610 result
+=string("*")+(*j
).first
.c_str();
1612 result
+=string("*")+(*j
).first
+"^"+int2string((*j
).second
);
1614 // strip of spaces at the end
1616 return result
.substr(0,result
.find_last_not_of(" ")+1);
1619 bool EhrhartPolynom::contains_parameters() const
1625 value_set_si(zero
, 0);
1626 PeriodicNumber
pn_zero(zero
);
1628 for(map
<map
<string
, int>, periodic_rational
>::const_iterator
1630 i
!=data
.end(); i
++) {
1631 // first print coefficient
1632 if ((*i
).second
.first
== PeriodicNumber(zero
))
1634 for(map
<string
,int>::const_iterator j
=(*i
).first
.begin();
1635 j
!=(*i
).first
.end(); j
++)
1643 EhrhartPolynom
EhrhartPolynom::subst_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
1657 cout
<<" / "<<divisor
;
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
);
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))
1684 // find the maximum exponent to which var is powered in the Ehrhartpolynom
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;
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
)));
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
];
1749 if(DebugBlackboard
.debug("EHRHARTPOLYNOM")>=3) {
1750 cout
<<"In EhrhartPolynom::subst_var:\n result=:"<<endl
;
1751 cout
<<result
.to_string()<<endl
;
1756 static inline bool bit(unsigned long value
, int bitnr
)
1758 return (value
>>bitnr
)&1;
1762 static bool is_constant(const ::Relation
& r
,
1764 const string
& char_name
,
1767 // first project away all other variables
1769 for(int i
=1;i
<=r
.n_set(); i
++) {
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.
1781 if (DebugBlackboard
.debug("EHRHARTPOLYNOM")>=2) {
1782 cout
<<"in is_constant(,"<<set_var
<<","<<char_name
<<") after projection, the relation is ";
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());
1799 // There should be no GEQ constraints
1800 if ((*di
)->GEQs() != 0)
1803 // There should be only on EQ constraint
1804 EQ_Iterator 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
1819 coeff_of_var
= (*cvi
).coef
;
1822 if (coeff_of_var
==0)
1825 if (coeff_of_var
==1) {
1826 value
= -(*ei
).get_const();
1829 if (coeff_of_var
==-1) {
1830 value
= (*ei
).get_const();
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
1849 * @param domain2 is the domain corresponding to @a ep2. The domain must
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();
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 ";
1894 cout
<<" lowerbound="<<lowerbound
<<"; upperbound="<<upperbound
<<endl
;
1896 if (lowerbound
!= upperbound
) {
1898 bool cst
= is_constant(_domain1
, var_to_check
, tmp2
.set_var(var_to_check
)->char_name(),
1901 lowerbound
= upperbound
= value
;
1903 if(DebugBlackboard
.debug("EHRHARTPOLYNOM")>=2) {
1904 cout
<<"Checked variable "<<var_to_check
<<" in relation ";
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 "
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
;
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 ";
1953 cout
<<" lowerbound="<<lowerbound
<<"; upperbound="<<upperbound
<<endl
;
1955 if (lowerbound
!= upperbound
) {
1957 bool cst
= is_constant(_domain2
, var_to_check
, tmp2
.set_var(var_to_check
)->char_name(),
1960 lowerbound
= upperbound
= value
;
1962 if(DebugBlackboard
.debug("EHRHARTPOLYNOM")>=2) {
1963 cout
<<"Checked variable "<<var_to_check
<<" in relation ";
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 "
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
;
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;
2020 for(DNF_Iterator di(domain1.query_DNF()); di; di++) {
2021 assert(counter1==0); // domain1 must be convex!
2023 for(EQ_Iterator ei=(*di)->EQs(); ei; ei++) {
2024 map<string,int> equalities;
2026 for(Constr_Vars_Iter cvi(*ei); cvi; cvi++) {
2027 if (string((*cvi).var->char_name()) ==
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++) {
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;
2058 for(DNF_Iterator di(domain2.query_DNF()); di; di++) {
2059 assert(counter2==0); // domain2 must be convex!
2061 for(EQ_Iterator ei=(*di)->EQs(); ei; ei++) {
2062 map<string,int> equalities;
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++) {
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;
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;
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;
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;
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++) {
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++) {
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
;
2185 * get_affine_polynomials returns the Ehrhart polynomials as a set
2186 * of affine functions when possible. If not possible, it returns
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
++) {
2203 if ((*i
).first
.size()==0) {
2205 var_names
.push_back("");
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
;
2217 if ((*j
).first
!=string("")) {
2219 if (std::find(var_names
.begin(), var_names
.end(), (*j
).first
) ==
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
;
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
)<<"' ";
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) {
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
]<<"' ";
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
++)
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
++) {
2302 for(set
<int>::const_iterator j
=(*i
).second
.begin();
2303 j
!=(*i
).second
.end(); j
++)
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
<<") ";
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.
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
++) {
2333 strides
.push_back(1);
2335 strides
.push_back(strides
[j
-1] * lcm_period
[var_names_as_param
[j
-1]]);
2337 if (var_names_as_param
.size()==0) {
2341 strides
.push_back(strides
.back() * lcm_period
[var_names_as_param
.back()]);
2342 if (DebugBlackboard
.debug("AFFINEPOLYNOM")>=3) {
2344 for(deque
<long>::const_iterator i
=strides
.begin(); i
!=strides
.end(); i
++)
2349 for(long i
=0;i
<nr_comb
;i
++) {
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
++) {
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) {
2375 value_to_str(str
, 0, lcm_denumerator
);
2376 cout
<<"lcm_denumerator="<<str
<<endl
;
2381 for(map
<map
<string
,int>, periodic_rational
>::const_iterator
2382 j
=data
.begin(); j
!=data
.end(); j
++) {
2384 for(map
<string
,int>::const_iterator k
=(*j
).first
.begin();
2385 k
!=(*j
).first
.end(); k
++) {
2387 assert((*k
).second
==1);
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
<<") ";
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
;
2413 // only push back a polynomial if it is different from 0
2415 for(map
<string
,int>::const_iterator j
=affine_coef
.begin();
2416 j
!=affine_coef
.end(); j
++)
2417 if ((*j
).second
!=0) {
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
;
2436 string
EhrhartPolynom::affine::to_string() const {
2439 for(map
<string
,int>::const_iterator i
=period
.begin();
2440 i
!=period
.end(); i
++)
2441 result
+="('"+(*i
).first
+"',"+int2string((*i
).second
)+") ";
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
]);
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
)+")";
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.
2487 Expression
* expression
= 0;
2488 // create the different terms in the polytope
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
));
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.
2506 term
= new BinaryExpression(term
,'*', new ScalarRef((*j
).first
.c_str()));
2508 term
= new ScalarRef((*j
).first
.c_str());
2511 // build the overall polynomial
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
)));
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
;