00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00025
00026
00027
00028
00029 #include "config.hpp"
00030
00031 #if !defined(ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE) || \
00032 defined(ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE_INTCOUNT_BARVINOK)
00033
00034
00035 #include <string>
00036 #include <list>
00037 #include <iostream>
00038 #include <fstream>
00039
00040 #ifdef ARAGELI_INTERNAL_BARVINOK_DEBUG_OUTPUT
00041 #include <ctime>
00042 #endif
00043
00044 #include "big_int.hpp"
00045 #include "vector.hpp"
00046 #include "matrix.hpp"
00047 #include "gauss.hpp"
00048 #include "lll.hpp"
00049 #include "skeleton.hpp"
00050 #include "rational.hpp"
00051
00052 #include "intcount_barvinok.hpp"
00053
00054
00055 namespace Arageli
00056 {
00057
00058
00059 namespace _Internal
00060 {
00061
00062
00063
00064
00065 template <typename T1, typename T2>
00066 T1 C_n_k(const T1 n,const T2 k);
00067
00068 template <typename T, typename R, typename MT, typename VT, typename VR>
00069 class UniCone
00070 {
00071 public:
00072 UniCone(const MT& a,VR& v, int s);
00073 void Dual();
00074 bool check_lyambda(const VT& lyambda);
00075 void GetLatticePoint();
00076 T t_to_s(const VT& lyambda);
00077 R GetValue(const T& min_num);
00078 void GetRationalFuncInDVariables(std::ofstream& out);
00079 void GetRationalFuncInOneVariable(std::ofstream& out);
00080 friend std::ostream& operator<< (std::ostream&,UniCone);
00081 private:
00082 MT generators;
00083 VR vertex;
00084 VT lattice_point;
00085 int sign;
00086 VT koeff_degree_s_num;
00087 VT koeff_degree_s_den;
00088 };
00089
00090 template <typename T, typename R, typename MT, typename VT, typename VR>
00091 class SimplicialCone
00092 {
00093 public:
00094 SimplicialCone(const MT& a, VR& v, int s,T i);
00095 bool Decompose(std::list<UniCone<T, R, MT, VT, VR>*>& UniCones);
00096 void Dual();
00097 T GetIndex();
00098 friend std::ostream& operator<< (std::ostream&, SimplicialCone);
00099 private:
00100 MT generators;
00101 T Index;
00102 int sign;
00103 VR vertex;
00104 };
00105
00106
00107 template <typename T, typename R, typename MT, typename VT, typename VR>
00108 class Cone
00109 {
00110 public:
00111 Cone(const MT& a, VR& v);
00112 void Dual();
00113 void Delone(std::list<SimplicialCone<T, R, MT, VT, VR>*>& Simplicial);
00114 friend std::ostream& operator<< (std::ostream&,Cone);
00115 private:
00116 MT generators;
00117 VR vertex;
00118 };
00119
00120
00121 template <typename T, typename R, typename MT, typename VT, typename VR>
00122 class Polytope
00123 {
00124 public:
00125 Polytope(const MT& a);
00126 R barvinok_algorithm(bool points = false);
00127 int GetSupportCones(std::list<Cone<T, R, MT, VT, VR>*>& SupportCones);
00128 friend std::ostream& operator<< (std::ostream&,Polytope);
00129 private:
00130 MT a;
00131 };
00132
00133
00134
00135
00136
00137 template <typename VT, typename T>
00138 bool add_one(VT& koeff, T max)
00139 {
00140 bool flag = false;
00141 for(size_t i = (koeff.size()-1); i >= 0; i--)
00142 if (koeff(i) == max && i == koeff.size()-1)
00143 {
00144 koeff(i) = (-1)*max;
00145 koeff(i-1)++;
00146 flag = true;
00147 if (koeff(i-1) <= max)
00148 break;
00149 }
00150 else if ((koeff(i) < max)&&(i == koeff.size()-1))
00151 {
00152 koeff(i)++;
00153 if (koeff(i) == max)
00154 flag = true;
00155 break;
00156 }
00157 else if ((koeff(i) > max)&&(i!=0))
00158 {
00159 koeff(i) = (-1)*max;
00160 koeff(i-1)++;
00161 flag = true;
00162 if (koeff(i-1) <= max)
00163 break;
00164 }
00165 else if ((koeff(i) > max)&&(i == 0))
00166 return false;
00167
00168 if (!flag)
00169 {
00170
00171 size_t count_neudovl = 0;
00172 for(size_t i = 0; i < koeff.size(); i++)
00173 if (abs(koeff(i)) == max)
00174 break;
00175 else count_neudovl++;
00176
00177 if (count_neudovl == koeff.size())
00178 add_one(koeff,max);
00179 }
00180 return true;
00181 }
00182
00183
00184 template <typename T, typename R, typename VT, typename VR, typename MR>
00185 bool enumeration_step(VR &lyambda,const MR& a)
00186 {
00187 size_t d = a.ncols();
00188 VT koeff_row(d);
00189 double norm_lyambda = pow(double(std::abs(det(a))),double(1.0/d));
00190 size_t max = 1;
00191 for(;;)
00192 {
00193
00194 if (!add_one(koeff_row,max))
00195 {
00196 max++;
00197
00198 for(size_t i = 0; i < d-1; i++)
00199 koeff_row(i)= T(0)-max;
00200 }
00201
00202 for(size_t i = 0; i < lyambda.size(); i++)
00203 lyambda(i) = R(0);
00204 size_t count_udovl = 0;
00205 for(size_t i = 0; i < d; i++)
00206 {
00207 for(size_t j = 0; j < d; j++)
00208 lyambda(i)+= koeff_row(j)*a(j,i);
00209
00210 if (double(std::abs(lyambda(i))) > norm_lyambda)
00211 break;
00212 else
00213 count_udovl++;
00214 }
00215
00216 if (count_udovl == a.ncols())
00217 return true;
00218 }
00219 return false;
00220 }
00221
00222 template <typename T1, typename T2>
00223 T1 C_n_k(const T1 n,const T2 k)
00224 {
00225 if ((n==0)&&(k==0))
00226 return 1;
00227 else if (k > n)
00228 return 0;
00229 else
00230 {
00231 T1 den(1),num(1);
00232 for(T1 i = 1; i < k+1; i++)
00233 den*=i;
00234 for(T1 i = n; i > n-k; i--)
00235 num*=i;
00236 ARAGELI_ASSERT_1(is_divisible(num, den));
00237 return num/den;
00238
00239
00240
00241
00242
00243 }
00244 }
00245
00246 template <typename T, typename R, typename MT, typename VT, typename VR>
00247 UniCone<T, R, MT, VT, VR>::UniCone(const MT& a,VR& v, int s): generators(a),vertex(v)
00248 {
00249 sign = s;
00250 }
00251
00252 template <typename T, typename R, typename MT, typename VT, typename VR>
00253 void UniCone<T, R, MT, VT, VR>::Dual()
00254 {
00255 MT f,q,e;
00256 skeleton(generators,f,q,e);
00257 generators = f;
00258 }
00259
00260 template <typename T, typename R, typename MT, typename VT, typename VR>
00261 std::ostream& operator<< (std::ostream& out, UniCone<T, R, MT, VT, VR> c)
00262 {
00263 out << "unimodular cone: " << std::endl
00264 << "vertex = " << c.vertex << std::endl
00265 << "sign = ";
00266 if (c.sign == 1)
00267 out << "+ \n";
00268 else
00269 out << "- \n";
00270 output_aligned(out,c.generators);
00271 out << std::endl;
00272
00273 return out;
00274 }
00275
00276 template <typename T, typename R, typename MT, typename VT, typename VR>
00277 void UniCone<T, R, MT, VT, VR>::GetRationalFuncInOneVariable(std::ofstream& out)
00278 {
00279
00280 out << "(" << koeff_degree_s_num(0);
00281 for(size_t i = 1; i < koeff_degree_s_num.size(); i++)
00282 {
00283 if (koeff_degree_s_num(i) == 1)
00284 out << "+s^" << i;
00285 else if (koeff_degree_s_num(i) == -1)
00286 out << "-s^" << i;
00287 else if ((koeff_degree_s_num(i) > 0)&&(koeff_degree_s_num(i)!=1))
00288 out << "+" << koeff_degree_s_num(i) << "*s^" << i;
00289 else if ((koeff_degree_s_num(i) < 0)&&(koeff_degree_s_num(i)!=-1))
00290 out << koeff_degree_s_num(i) << "*s^" << i;
00291 }
00292
00293 out << ")/(" << std::endl;
00294
00295 if (koeff_degree_s_den(0)!=0)
00296 out << koeff_degree_s_den(0);
00297 for(size_t i = 1; i < koeff_degree_s_den.size(); i++)
00298 {
00299 if (koeff_degree_s_den(i) == 1)
00300 out << " + s^" << i;
00301 else if (koeff_degree_s_den(i)!= 0)
00302 out << " + " << koeff_degree_s_den(i) << "*s^" << i;
00303 }
00304 out << ")" << std::endl;
00305 }
00306
00307 template <typename T, typename R, typename MT, typename VT, typename VR>
00308 void UniCone<T, R, MT, VT, VR>::GetRationalFuncInDVariables(std::ofstream& out)
00309 {
00310 size_t d = generators.ncols();
00311 if (sign == 1)
00312 out << "+";
00313 else
00314 out << "-";
00315
00316 int count_null = 0;
00317 for(size_t i = 0; i < d; i++)
00318 {
00319 if (lattice_point(i) == T(0))
00320 count_null++;
00321 else if (lattice_point(i) == T(1))
00322 out << "x" << i;
00323 else
00324 out << "x" << i << "^(" << lattice_point(i) << ")";
00325
00326 if (count_null == d)
00327 out << "1";
00328 }
00329 out << "/(";
00330
00331 for(size_t i = 0; i < d; i++)
00332 {
00333 out << "(1 - ";
00334 for(size_t j = 0; j < d; j++)
00335 {
00336 if (generators(i,j) == T(0))
00337 ;
00338 else if (generators(i,j) == T(1))
00339 out << "x" << j;
00340 else
00341 out << "x" << j << "^(" << generators(i,j) << ")";
00342 }
00343 out << ")";
00344 }
00345 out << ")";
00346 }
00347
00348 template <typename T, typename R, typename MT, typename VT, typename VR>
00349 bool UniCone<T, R, MT, VT, VR>::check_lyambda(const VT& lyambda)
00350 {
00351
00352 for(size_t i = 0; i < generators.nrows(); i++)
00353 {
00354 big_int sum = 0;
00355 for(size_t j = 0; j < generators.ncols(); j++)
00356 sum+= lyambda(j)*generators(i,j);
00357 if (sum == 0)
00358 return false;
00359 }
00360 return true;
00361 }
00362
00363 template <typename T, typename R, typename MT, typename VT, typename VR>
00364 void UniCone<T, R, MT, VT, VR>::GetLatticePoint()
00365 {
00366 typedef typename MT::template other_element_type<R>::type MR;
00367
00368 size_t d = generators.ncols();
00369
00370 lattice_point.resize(d);
00371
00372 bool flag = true;
00373 for(size_t i = 0; i < vertex.size(); i++)
00374 if (!vertex(i).is_integer())
00375 {
00376 flag = false;
00377 break;
00378 }
00379 else
00380 lattice_point(i) = iceil(vertex(i));
00381
00382 if (!flag)
00383 {
00384 VR koeff_vertex(vertex.size());
00385 generators.transpose();
00386 koeff_vertex = inverse(MR(generators))*vertex;
00387 VR res_koeff(vertex.size());
00388 for(size_t i = 0; i < koeff_vertex.size(); i++)
00389 koeff_vertex(i) = iceil(koeff_vertex(i));
00390 res_koeff = generators*koeff_vertex;
00391 for(size_t i = 0; i < res_koeff.size(); i++)
00392 lattice_point(i) = iceil(res_koeff(i));
00393 generators.transpose();
00394 }
00395
00396 }
00397
00398 template <typename T, typename R, typename MT, typename VT, typename VR>
00399 T UniCone<T, R, MT, VT, VR>::t_to_s(const VT& lyambda)
00400 {
00401
00402 size_t d = generators.ncols();
00403
00404 koeff_degree_s_num.resize(d+1);
00405
00406 for(size_t i = 0; i < d; i++)
00407 koeff_degree_s_num(0)+= lattice_point(i)*lyambda(i);
00408
00409
00410 koeff_degree_s_den.resize(d+1);
00411 for(size_t i = 0; i < generators.nrows(); i++)
00412 {
00413
00414 T degree_t(0);
00415 for(size_t j = 0; j < d; j++)
00416 degree_t+= lyambda(j)*generators(i,j);
00417
00418 if (degree_t < 0)
00419 {
00420 degree_t *= -1;
00421 koeff_degree_s_num(0) += degree_t;
00422 }
00423 else
00424 sign *= -1;
00425
00426 if (i==0)
00427 for(size_t j = 0; j < d+1; j++)
00428 koeff_degree_s_den(j) = C_n_k(degree_t,j+1);
00429 else
00430 {
00431
00432 VT current_koeff(d+1);
00433 for(size_t j = 0; j < d+1; j++)
00434 current_koeff(j) = C_n_k(degree_t,j+1);
00435
00436 VT new_koeff(d+1,T(0));
00437 for(size_t j = 0; j < d+1; j++)
00438 for (size_t k = 0; k < j+1; k++)
00439 for(size_t l = 0; l < j+1; l++)
00440 if ((k+l) == j)
00441 new_koeff(j)+=koeff_degree_s_den(k)*current_koeff(l);
00442
00443 koeff_degree_s_den = new_koeff;
00444 }
00445 }
00446
00447 return koeff_degree_s_num(0);
00448 }
00449
00450
00451
00452 template <typename T, typename R, typename MT, typename VT, typename VR>
00453 R UniCone<T, R, MT, VT, VR>::GetValue(const T& min_num)
00454 {
00455
00456 koeff_degree_s_num(0)-=min_num;
00457 T degree_t;
00458 degree_t = koeff_degree_s_num(0);
00459 size_t d = generators.ncols();
00460 koeff_degree_s_num.resize(d+1);
00461
00462 for(size_t i = 0; i < d+1; i++)
00463 koeff_degree_s_num(i) = sign*C_n_k(degree_t,i);
00464 VR c(d+1);
00465 c(0) = R(koeff_degree_s_num(0),koeff_degree_s_den(0));
00466 for(size_t k = 1; k < d+1; k++)
00467 {
00468 c(k) = koeff_degree_s_num(k);
00469 for(size_t j = 1; j < k+1; j++)
00470 for(size_t l = 0; l < k; l++)
00471 if ((j+l) == k)
00472 c(k)-=koeff_degree_s_den(j)*c(l);
00473 c(k)/= koeff_degree_s_den(0);
00474 }
00475 return c.at(d);
00476 }
00477
00478 template <typename T, typename R, typename MT, typename VT, typename VR>
00479 SimplicialCone<T, R, MT, VT, VR>::SimplicialCone(const MT& a, VR &v, int s, T i): generators(a),vertex(v)
00480 {
00481 sign = s;
00482 Index = i;
00483 }
00484
00485 template <typename T, typename R, typename MT, typename VT, typename VR>
00486 void SimplicialCone<T, R, MT, VT, VR>::Dual()
00487 {
00488 MT f,q,e;
00489 skeleton(generators,f,q,e);
00490 generators = f;
00491 Index = det_int(generators);
00492 }
00493
00494 template <typename T, typename R, typename MT, typename VT, typename VR>
00495 std::ostream& operator<< (std::ostream& out, SimplicialCone<T, R, MT, VT, VR> c)
00496 {
00497 out << "simplicial cone: " << std::endl
00498 << "vertex = " << c.vertex << std::endl
00499 << "sign = ";
00500 if (c.sign == 1)
00501 out << "+ \n";
00502 else
00503 out << "- \n";
00504 output_aligned(out,c.generators);
00505 out << std::endl;
00506
00507 return out;
00508 }
00509
00510 template <typename T, typename R, typename MT, typename VT, typename VR>
00511 bool SimplicialCone<T, R, MT, VT, VR>::Decompose(std::list<UniCone<T, R, MT, VT, VR>*>& UniCones)
00512 {
00513 std::list<SimplicialCone<T, R, MT, VT, VR>*> NonUni;
00514 typedef typename MT::template other_element_type<R>::type MR;
00515 size_t m = generators.nrows();
00516 size_t d = generators.ncols();
00517 if (m!=d)
00518 {
00519 std::cerr << "there is not simplicial cone " << std::endl;
00520 return false;
00521 }
00522
00523 if (std::abs(Index)==T(1))
00524 UniCones.push_back(new UniCone<T, R, MT, VT, VR>(generators,vertex,1));
00525 else
00526 if (Index==T(0))
00527 {
00528 std::cerr << "matrix of cones is singular" << std::endl;
00529 return false;
00530 }
00531 else
00532 NonUni.push_back(new SimplicialCone<T, R, MT, VT, VR>(generators,vertex,sign,Index));
00533
00534 while(!NonUni.empty())
00535 {
00536 SimplicialCone* K(NonUni.back());
00537 NonUni.pop_back();
00538 MR Q(K->generators);
00539
00540 Q.transpose();
00541 Q = inverse(Q);
00542 MR H;
00543
00544
00545 lll_reduction(Q,H);
00546 Q.transpose();
00547
00548 VR max_el(d, R(0));
00549 for(size_t i = 0; i < d; i++)
00550 for(size_t j = 0; j < d; j++)
00551 if (std::abs(Q(i,j)) > max_el(i))
00552 max_el(i) = std::abs(Q(i,j));
00553
00554 size_t min_index = 0;
00555 for(size_t i = 1; i < d; i++)
00556 if (max_el(i) < max_el(min_index))
00557 min_index = i;
00558
00559 (K->generators).transpose();
00560
00561 VT z(d);
00562 R current_entries;
00563 for(size_t k = 0; k < d; k++)
00564 {
00565 current_entries = 0;
00566 for(size_t j = 0; j < d; j++)
00567 current_entries+= K->generators(k,j)*Q(min_index,j);
00568 z(k) = iceil(current_entries);
00569 }
00570 size_t count_otr = 0;
00571 for(size_t j = 0; j < d; j++)
00572 if (Q(min_index,j) <= T(0))
00573 count_otr++;
00574 if (count_otr == d)
00575 z*= -1;
00576 (K->generators).transpose();
00577
00578 vector< MT > MatrixForCone(d,K->generators);
00579 VT DetOfCone(d);
00580 bool flag = true;
00581 for(size_t j = 0; j < d; j++)
00582 {
00583 MatrixForCone(j).insert_row(j,z);
00584
00585 MatrixForCone(j).erase_row(j+1);
00586
00587 if (rank_int(MatrixForCone(j)) == d)
00588 {
00589 DetOfCone(j) = det_int(MatrixForCone(j));
00590 if (std::abs(DetOfCone(j)) >= std::abs(K->Index))
00591 {
00592 flag = false;
00593 break;
00594 }
00595 }
00596 else
00597 DetOfCone(j) = T(0);
00598 }
00599
00600 if (!flag)
00601 {
00602 vector< R > lyambda(d);
00604 enumeration_step<T, R, VT>(lyambda,Q);
00605 (K->generators).transpose();
00606
00607 VT z(d);
00608 R current_entries;
00609 for(size_t k = 0; k < d; k++)
00610 {
00611 current_entries = 0;
00612 for(size_t j = 0; j < d; j++)
00613 current_entries+= K->generators(k,j)*lyambda(j);
00614 z(k) = iceil(current_entries);
00615 }
00616
00617 size_t count_otr = 0;
00618 for(size_t j = 0; j < d; j++)
00619 if (lyambda(j) < T(0))
00620 count_otr++;
00621 if (count_otr == d)
00622 z*= -1;
00623 (K->generators).transpose();
00624 flag = true;
00625 for(size_t j = 0; j < d; j++)
00626 {
00627
00628 MatrixForCone(j).insert_row(j,z);
00629
00630 MatrixForCone(j).erase_row(j+1);
00631 if (rank_int(MatrixForCone(j))==d)
00632 {
00633 DetOfCone(j) = det_int(MatrixForCone(j));
00634 if (std::abs(DetOfCone(j)) >= std::abs(K->Index))
00635 flag = false;
00636 std::cerr << "not smaller index! \n";
00637 return false;
00638 }
00639 else
00640 DetOfCone(j) = T(0);
00641 }
00642
00643 }
00644 for(size_t j = 0; j < d; j++)
00645 {
00646 if (std::abs(DetOfCone(j)) == T(1))
00647 {
00648 if (DetOfCone(j)*K->Index>0)
00649 UniCones.push_back(new UniCone<T, R, MT, VT, VR>(MatrixForCone(j),vertex,K->sign));
00650 else
00651 UniCones.push_back(new UniCone<T, R, MT, VT, VR>(MatrixForCone(j),vertex,-K->sign));
00652 }
00653 else
00654 {
00655 if (DetOfCone(j) == T(0))
00656 ;
00657 else
00658 {
00659 if (DetOfCone(j)*K->Index>0)
00660 NonUni.push_back(new SimplicialCone<T, R, MT, VT, VR>(MatrixForCone(j),vertex,K->sign,DetOfCone(j)));
00661 else
00662 NonUni.push_back(new SimplicialCone<T, R, MT, VT, VR>(MatrixForCone(j),vertex,-K->sign,DetOfCone(j)));
00663 }
00664 }
00665 }
00666 delete K;
00667 }
00668
00669 return true;
00670 }
00671
00672
00673 template <typename T, typename R, typename MT, typename VT, typename VR>
00674 Cone<T, R, MT, VT, VR>::Cone(const MT& a, VR& v): generators(a),vertex(v) {}
00675
00676 template <typename T, typename R, typename MT, typename VT, typename VR>
00677 void Cone<T, R, MT, VT, VR>::Dual()
00678 {
00679 MT f,q,e;
00680 skeleton(generators,f,q,e);
00681 generators = f;
00682 }
00683
00684 template <typename T, typename R, typename MT, typename VT, typename VR>
00685 std::ostream& operator<< (std::ostream& out, Cone<T, R, MT, VT, VR> c)
00686 {
00687 out << std::endl;
00688 out << "cone: " << std::endl
00689 << "vertex: " << c.vertex << std::endl;
00690 output_aligned(out, c.generators);
00691
00692 return out;
00693 }
00694
00695 template <typename T, typename R, typename MT, typename VT, typename VR>
00696 void Cone<T, R, MT, VT, VR>::Delone(std::list<SimplicialCone<T, R, MT, VT, VR>*>& Simplicial)
00697 {
00698 size_t ncols = generators.ncols();
00699 size_t nrows = generators.nrows();
00700 if (ncols == nrows)
00701 Simplicial.push_back(new SimplicialCone<T, R, MT, VT, VR>(generators,vertex,1,det_int(generators)));
00702 else
00703 {
00704 generators.insert_col(ncols, T(0));
00705
00706 for(size_t i = 0; i < nrows; i++)
00707 for(size_t j = 0; j < ncols; j++)
00708 generators(i,ncols) += generators(i,j)*generators(i,j);
00709 MT f,q,e;
00710 skeleton(generators,f,q,e);
00711 generators.erase_col(ncols);
00712
00713 for (size_t i = 0; i < f.nrows(); i++)
00714 {
00715 if (f(i, f.ncols()-1) < 0)
00716 {
00717 MT b(0,ncols);
00718 for(size_t j = 0; j < q.ncols(); j++)
00719 if (q(i,j) == T(0))
00720 b.insert_row(b.nrows(),generators.copy_row(j));
00721 Simplicial.push_back(new SimplicialCone<T, R, MT, VT, VR>(b,vertex,1,det_int(b)));
00722 }
00723 }
00724 }
00725 }
00726
00727
00728 template <typename T, typename R, typename MT, typename VT, typename VR>
00729 void barvinok_lyambda(VT& lyambda,std::list<UniCone<T, R, MT, VT, VR>*>& Uni)
00730 {
00731
00732
00733
00734
00735 size_t d = lyambda.size();
00736 size_t I = Uni.size();
00737 size_t m = d*(d-1)*I+1;
00738 for(size_t i = 0; i < m; i++)
00739 {
00740 lyambda.at(0) = 1;
00741 lyambda.at(1) = i;
00742 for(size_t j = 2; j < d; j++)
00743 lyambda.at(j) = i*lyambda.at(j-1);
00744 size_t count_udovl = 0;
00745 for(typename std::list<UniCone<T, R, MT, VT, VR>*>::iterator j = Uni.begin(); j!=Uni.end(); ++j)
00746 if (!(*j)->check_lyambda(lyambda))
00747 break;
00748 else
00749 count_udovl++;
00750 if (count_udovl == I)
00751 break;
00752 }
00753 }
00754
00755 template <typename T, typename R, typename MT, typename VT, typename VR>
00756 void random_lyambda(VT& lyambda,std::list<UniCone<T, R, MT, VT, VR>*>& Uni)
00757 {
00758
00759 for(size_t i = 0; i < lyambda.size(); i++)
00760 lyambda.at(i) = big_int::random_in_range(T(18))-9;
00761 for(;;)
00762 {
00763 size_t count_udovl = 0;
00764 for(typename std::list<UniCone<T, R, MT, VT, VR>*>::iterator i = Uni.begin(); i!= Uni.end(); ++i)
00765 if (!(*i)->check_lyambda(lyambda))
00766 break;
00767 else
00768 count_udovl++;
00769 if (count_udovl == Uni.size())
00770 break;
00771 else
00772 {
00773 size_t add = big_int::random_in_range(lyambda.size()-1);
00774 lyambda.at(add)++;
00775 }
00776 }
00777 }
00778
00779 template <typename T, typename R, typename MT, typename VT, typename VR>
00780 Polytope<T, R, MT, VT, VR>::Polytope(const MT& a): a(a)
00781 {
00782 }
00783
00784 template <typename T, typename R, typename MT, typename VT, typename VR>
00785 std::ostream& operator<< (std::ostream& out, Polytope<T, R, MT, VT, VR> p)
00786 {
00787 out << "polytope: (Ax <= b) as (b|-A)" << std::endl;
00788 output_aligned(out, p.a);
00789 out << std::endl;
00790
00791 return out;
00792 }
00793
00794
00795
00796
00797
00798
00799
00800 template <typename T, typename R, typename MT, typename VT, typename VR>
00801 int Polytope<T, R, MT, VT, VR>::GetSupportCones(std::list<Cone<T, R, MT, VT, VR>*>& SupportCones)
00802 {
00803
00804
00805 MT f,q,e;
00806 skeleton(a,f,q,e);
00807
00808 if (f.nrows() == 0)
00809 {
00810
00811 return 3;
00812 }
00813 else if (f.nrows() == 1)
00814 {
00815
00816 return 4;
00817 }
00818 else if (e.nrows() != 0)
00819 {
00820
00821 return 5;
00822 }
00823 else
00824 {
00825 for(size_t i = 0; i < f.nrows();i++)
00826 if (f(i,0) == 0)
00827 {
00828 std::cerr << "Unbounded politop!" << std::endl;
00829 return 2;
00830 }
00831
00832
00833
00834
00835 for (size_t i = 0; i < f.nrows(); i++)
00836 {
00837 MT b(0,a.ncols()-1);
00838 for(size_t j = 0; j < q.ncols(); j++)
00839 {
00840 if (q(i,j) == T(0))
00841 {
00842 VT one_row(a.copy_row(j));
00843 one_row.erase(0);
00844
00845 b.insert_row(b.nrows(),one_row);
00846 }
00847 }
00848
00849
00850 VR vertex(f.ncols()-1);
00851 for(size_t j = 1; j < f.ncols(); j++)
00852 vertex(j-1) = R(f(i,j),f(i,0));
00853 SupportCones.push_back(new Cone<T, R, MT, VT, VR>(b, vertex));
00854 }
00855
00856
00857 }
00858 return 1;
00859 }
00860
00861
00862 template <typename T, typename R, typename MT, typename VT, typename VR>
00863 R Polytope<T, R, MT, VT, VR>::barvinok_algorithm(bool points)
00864 {
00865 #ifdef ARAGELI_INTERNAL_BARVINOK_DEBUG_OUTPUT
00866
00867 std::time_t time_begin = std::clock();
00868 std::ofstream out("intcount_barvinok.debug.output.txt");
00869 out << "Arageli Debug Output File for Barvinok algorithm.\nIf you don't want this file is being generated, comment definition of macro ARAGELI_INTERNAL_BARVINOK_DEBUG_OUTPUT\n\n";
00870
00871 #else
00872
00873 std::ofstream out;
00874
00875 #endif
00876
00877 std::list<Cone<T, R, MT, VT, VR>*> SupportCones;
00878 std::list<SimplicialCone<T, R, MT, VT, VR>*> SimplicialCones;
00879 std::list<UniCone<T, R, MT, VT, VR>*> UniCones;
00880
00881
00882 switch(GetSupportCones(SupportCones))
00883 {
00884 case 2:
00885 out << "unbounded polytope!\n";
00886 return -1;
00887 break;
00888 case 3:
00889 out << "empty polytope!\n";
00890 return -1;
00891 break;
00892 case 4:
00893 out << "#points: \n" << "1\n"
00894 << "one-pointed polytope\n";
00895 return R(1);
00896 break;
00897 case 5:
00898 out << "not bodily polytope!\n";
00899 return -1;
00900 break;
00901 }
00902
00903 out << "triangulation Delone...";
00904 for(typename std::list<Cone<T, R, MT, VT, VR>*>::iterator i = SupportCones.begin(); i != SupportCones.end(); ++i)
00905 (*i)->Delone(SimplicialCones);
00906 out << "done.\n";
00907
00908 out << "decompose simplicial cones on unimodular cones...";
00909 for(typename std::list<SimplicialCone<T, R, MT, VT, VR>*>::iterator i = SimplicialCones.begin(); i != SimplicialCones.end(); ++i)
00910 if (!(*i)->Decompose(UniCones))
00911 {
00912 out << "not smaller index! not decomposition!" << std::endl;
00913 return -1;
00914 }
00915 out << "done.\n";
00916
00917 out << "dualizing unimodular cones...";
00918 for(typename std::list<UniCone<T, R, MT, VT, VR>*>::iterator i = UniCones.begin(); i != UniCones.end(); ++i)
00919 (*i)->Dual();
00920 out << "done.\n";
00921
00922 VT lyambda(a.ncols()-1);
00923 random_lyambda(lyambda,UniCones);
00924
00925 out << "get lattice point for every unimodular cones...";
00926 for(typename std::list<UniCone<T, R, MT, VT, VR>*>::iterator i = UniCones.begin(); i != UniCones.end(); ++i)
00927 (*i)->GetLatticePoint();
00928 out << "done.\n";
00929
00930 #ifdef ARAGELI_INTERNAL_BARVINOK_DEBUG_OUTPUT
00931
00932
00933 if (points == true)
00934 {
00935 std::ofstream out_points("intcount_barvinok.points.debug.output.txt");
00936 for(typename std::list<UniCone<T, R, MT, VT, VR>*>::iterator i = UniCones.begin(); i != UniCones.end(); ++i)
00937 (*i)->GetRationalFuncInDVariables(out_points);
00938 out_points.close();
00939 }
00940
00941 #endif
00942
00943 out << "transformation of variables: t to s ...";
00944
00945 typename std::list<UniCone<T, R, MT, VT, VR>*>::iterator i = UniCones.begin();
00946 T min_num_degree = (*i)->t_to_s(lyambda);
00947 ++i;
00948 while(i != UniCones.end())
00949 {
00950 T current_degree = (*i)->t_to_s(lyambda);
00951 if (current_degree < min_num_degree)
00952 min_num_degree = current_degree;
00953 ++i;
00954 }
00955 out << "done.\n";
00956
00957 out << "get value for rational function's for every unimodular cones...";
00958 R value = 0;
00959 for(typename std::list<UniCone<T, R, MT, VT, VR>*>::iterator i = UniCones.begin(); i != UniCones.end(); ++i)
00960 value += (*i)->GetValue(min_num_degree);
00961 out << "done.\n";
00962
00963 #ifdef ARAGELI_INTERNAL_BARVINOK_DEBUG_OUTPUT
00964
00965 std::time_t time_end = std::clock();
00966
00967 out << "#points: \n" << value << std::endl
00968 << "#cones: \n" << SupportCones.size() << std::endl
00969 << "#simplicial_cones: \n" << SimplicialCones.size() << std::endl
00970 << "#uni_cones: \n" << UniCones.size() << std::endl
00971 << "lyambda = " << lyambda << std::endl
00972 << "#time: (sec)\n" << (double(time_end) - time_begin)/CLOCKS_PER_SEC << std::endl;
00973
00974 #endif
00975
00976
00977 for(typename std::list<UniCone<T, R, MT, VT, VR>*>::iterator i = UniCones.begin(); i != UniCones.end(); ++i)
00978 delete (*i);
00979 for(typename std::list<SimplicialCone<T, R, MT, VT, VR>*>::iterator i = SimplicialCones.begin(); i != SimplicialCones.end(); ++i)
00980 delete (*i);
00981 for(typename std::list<Cone<T, R, MT, VT, VR>*>::iterator i = SupportCones.begin(); i != SupportCones.end(); ++i)
00982 delete (*i);
00983
00984 return value;
00985 }
00986
00987
00988 }
00989
00990
00991 template <typename A, typename T, typename Ctrler>
00992 void intcount_barvinok (const A& a, T& res, Ctrler ctrler)
00993 {
00994 _Internal::Polytope<T, rational<T>, matrix<T>, vector<T>, vector<rational<T> > > polytope(a);
00995 res = polytope.barvinok_algorithm(true);
00996 }
00997
00998
00999
01000 }
01001
01002
01003 #endif