intcount_barvinok.cpp

Go to the documentation of this file.
00001 /*****************************************************************************
00002     
00003     intcount_barvinok.cpp -- The algorithm that counts all integer points
00004         in polytope.
00005 
00006     This file is a part of the Arageli library.
00007 
00008     An implementation of all algorithms in this file
00009     have been done by Ekaterina Schukina.
00010     
00011     An integration of the implemented algorithms
00012     into Arageli by Sergey Lyalin.
00013 
00014     Copyright (C) Ekaterina Shchukina, 2006
00015     Copyright (C) Sergey S. Lyalin, 2006
00016 
00017 *****************************************************************************/
00018 
00025 //TODO: This file needs to rewrite with new approaches.
00026 
00027 //#define ARAGELI_INTERNAL_BARVINOK_DEBUG_OUTPUT
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 // +++++++ Original declaration part ++++++++
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); //true - разложили, false - индекс не уменьшился   
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 // +++++++ Original implementation part ++++++++
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             //R res = num/den;
00239             //if (res.is_integer())
00240             //  return res;
00241             //else 
00242             //  return 0;
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     //write x^(lattice_point) (numerator function)  
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         //point (0,0,...,0)
00326         if (count_null == d)
00327             out << "1";
00328     }
00329     out << "/(";
00330     //write all d generators
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             //z = (K->generators)*lyambda
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     //g(tau)=(1,tau,tau^2,...,tau^d-1)
00732     //(g(tau),bij)!=0 
00733     //l принадлежит {g(0),g(1),...,g(m)}, m=d(d-1)|I|+1
00734     //|I|-count of unimodular cones
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 //return:
00795 //5 - not bodily polytope
00796 //4 - all inequalities crosses in one point
00797 //3 - empty polytope
00798 //2 - unbounded polytope
00799 //1 - all good
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     //use algorithm Motzkin - Burger
00804     //for double description of polytope
00805     MT f,q,e;
00806     skeleton(a,f,q,e);
00807     
00808     if (f.nrows() == 0)
00809     {
00810         //std::cout << "Empty polytope!" << std::endl;
00811         return 3;
00812     }
00813     else if (f.nrows() == 1)
00814     {
00815         //std::cout << "One pointed polytope!" << std::endl;
00816         return 4;
00817     }
00818     else if (e.nrows() != 0)
00819     {
00820         //std::cout << "Not bodily polytope!" << std::endl;
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         //if q(i,j) == 0, that 
00833         //rows number i in matrix a (inequalities) corresponding
00834         //rows number j in matrix f (generators)
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                     //insert corresponding generators 
00845                     b.insert_row(b.nrows(),one_row); 
00846                 }
00847             }
00848             //getting support cones for vertex i
00849             //get vertex: rows of f without first entries / (first entries)
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         //A**=A, 
00857     }
00858     return 1;
00859 }
00860 
00861 //return count lattice points in bodily polyhedron
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;  // just a black hole
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     //get support cones for polytope (with skeleton)
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     //output rational functions if options [-points] in command line
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     //and find min degree of s in numerator
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     //delete all cones
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 } // namesapce Arageli
01001 
01002 
01003 #endif

Generated on Thu Aug 31 17:38:06 2006 for Arageli by  doxygen 1.4.7