BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Polynomial/bezout_matrix.h
Go to the documentation of this file.
00001 // Copyright (c) 2008 Max-Planck-Institute Saarbruecken (Germany)
00002 //
00003 // This file is part of CGAL (www.cgal.org); you can redistribute it and/or
00004 // modify it under the terms of the GNU Lesser General Public License as
00005 // published by the Free Software Foundation; version 2.1 of the License.
00006 // See the file LICENSE.LGPL distributed with CGAL.
00007 //
00008 // Licensees holding a valid commercial license may use this file in
00009 // accordance with the commercial license agreement provided with the software.
00010 //
00011 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 //
00014 // $URL: svn+ssh://afabri@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial/polynomial_functions.h $
00015 // $Id: polynomial_functions.h 46402 2008-10-21 16:20:05Z eric $
00016 //
00017 //
00018 // Author(s)     : Michael Hemmer
00019 //
00020 // ============================================================================
00021 
00022 // TODO: The comments are all original EXACUS comments and aren't adapted. So
00023 //         they may be wrong now.
00024 
00025 #ifndef CGAL_POLYNOMIAL_BEZOUT_MATRIX_H
00026 #define CGAL_POLYNOMIAL_BEZOUT_MATRIX_H
00027 
00028 #include <algorithm>
00029 
00030 #include <CGAL/basic.h>
00031 #include <CGAL/Polynomial_traits_d.h>
00032 #include <CGAL/Polynomial/determinant.h>
00033 
00034 #include <vector>
00035 //#include <CGAL/Linear_algebraHd.h>
00036 
00037 
00038 //#include <CGAL/Linear_algebra.h>
00039 //#include <CGAL/number_type_utils.h>
00040 
00041 CGAL_BEGIN_NAMESPACE
00042 
00043 namespace CGALi {
00044 
00074 template <typename Polynomial_traits_d>
00075 typename CGALi::Simple_matrix< typename Polynomial_traits_d::Coefficient_type >
00076 hybrid_bezout_matrix(typename Polynomial_traits_d::Polynomial_d f, 
00077                      typename Polynomial_traits_d::Polynomial_d g, 
00078                      int sub = 0)
00079 {
00080 
00081     typedef typename Polynomial_traits_d::Polynomial_d Polynomial;
00082     typedef typename Polynomial_traits_d::Coefficient_type NT;
00083     typename Polynomial_traits_d::Degree degree;
00084     typename CGAL::Algebraic_structure_traits<Polynomial>::Is_zero is_zero;
00085     typename Polynomial_traits_d::Get_coefficient coeff;
00086 
00087     typedef typename CGALi::Simple_matrix<NT> Matrix;
00088 
00089     int n = degree(f);
00090     int m = degree(g);
00091     CGAL_precondition((n >= 0) && !is_zero(f));
00092     CGAL_precondition((m >= 0) && !is_zero(g));
00093     CGAL_precondition(n > sub || sub == 0);
00094     CGAL_precondition(m > sub || sub == 0);
00095 
00096     int i, j, k, l;
00097     NT  s;
00098 
00099     if (m > n) {
00100         std::swap(f, g);
00101         std::swap(m, n);
00102     }
00103 
00104     Matrix B(n-sub);
00105 
00106     for (i = 1+sub; i <= m; i++) {
00107         for (j = 1; j <= n-sub; j++) {
00108             s = NT(0);
00109             for (k = 0; k <= i-1; k++) {
00110                 l = n+i-j-k;
00111                 if ((l <= n) and (l >= n-(m-i))) {
00112                     s += coeff(f,l) * coeff(g,k);
00113                 }
00114             }
00115             for (k = 0; k <= n-(m-i+1); k++) {
00116                 l = n+i-j-k;
00117                 if ((l <= m) and (l >= i)) {
00118                     s -= coeff(f,k) * coeff(g,l);
00119                 }
00120             }
00121             B[i-sub-1][j-1] = s;
00122         }
00123     }
00124     for (i = std::max(m+1, 1+sub); i <= n; i++) {
00125         for (j = i-m; j <= std::min(i, n-sub); j++) {
00126             B[i-sub-1][j-1] = coeff(g,i-j);
00127         }
00128     }
00129 
00130     return B; // g++ 3.1+ has NRVO, so this should not be too expensive
00131 }
00132 
00144 template <typename Polynomial_traits_d>
00145 typename CGALi::Simple_matrix<typename Polynomial_traits_d::Coefficient_type>
00146 symmetric_bezout_matrix
00147     (typename Polynomial_traits_d::Polynomial_d f, 
00148      typename Polynomial_traits_d::Polynomial_d g, 
00149      int sub = 0)
00150 {
00151 
00152     
00153 
00154   // Note: The algorithm is taken from:
00155   // Chionh, Zhang, Goldman: Fast Computation of the Bezout and Dixon Resultant
00156   // Matrices. J.Symbolic Computation 33, 13-29 (2002)
00157     
00158     typedef typename Polynomial_traits_d::Polynomial_d Polynomial;
00159     typedef typename Polynomial_traits_d::Coefficient_type NT;
00160     typename Polynomial_traits_d::Degree degree;
00161     typename CGAL::Algebraic_structure_traits<Polynomial>::Is_zero is_zero;
00162     typename Polynomial_traits_d::Get_coefficient coeff;
00163 
00164     typedef typename CGALi::Simple_matrix<NT> Matrix;
00165 
00166     int n = degree(f);
00167     int m = degree(g);
00168     CGAL_precondition((n >= 0) && !is_zero(f));
00169     CGAL_precondition((m >= 0) && !is_zero(g));
00170 
00171     int i,j,stop;
00172 
00173     NT sum1,sum2;
00174 
00175     if (m > n) {
00176         std::swap(f, g);
00177         std::swap(m, n);
00178     }
00179 
00180     CGAL_precondition((sub>=0) && sub < n);
00181 
00182     int d = n - sub;
00183 
00184     Matrix B(d);
00185 
00186     // 1st step: Initialisation
00187     for(i=0;i<d;i++) {
00188       for(j=i;j<d;j++) {
00189         sum1 = ((j+sub)+1>m) ? NT(0) : -coeff(f,i+sub)*coeff(g,(j+sub)+1);
00190         sum2 =  ((i+sub)>m)  ? NT(0) :  coeff(g,i+sub)*coeff(f,(j+sub)+1);
00191         B[i][j]=sum1+sum2;
00192       }
00193     }
00194 
00195     // 2nd Step: Recursion adding
00196     
00197     // First, set up the first line correctly
00198     for(i=0;i<d-1;i++) {
00199       stop = (sub<d-1-i) ? sub : d-i-1;
00200       for(j=1;j<=stop;j++) {
00201           sum1 = ((i+sub+j)+1>m) ? NT(0) 
00202                                  : -coeff(f,sub-j)*coeff(g,(i+sub+j)+1);
00203           sum2 =  ((sub-j)>m)    ? NT(0) 
00204                                  : coeff(g,sub-j)*coeff(f,(i+sub+j)+1);
00205         
00206         B[0][i]+=sum1+sum2;
00207       }
00208     }
00209     // Now, compute the rest
00210     for(i=1;i<d-1;i++) {
00211       for(j=i;j<d-1;j++) {
00212         B[i][j]+=B[i-1][j+1];
00213       }
00214     }
00215 
00216     
00217    //3rd Step: Exploit symmetry
00218     for(i=1;i<d;i++) {
00219       for(j=0;j<i;j++) {
00220         B[i][j]=B[j][i];
00221       }
00222     }
00223     
00224     return B;
00225 }
00226     
00227 
00228 
00244 template <class Polynomial_traits_d>
00245 typename Polynomial_traits_d::Coefficient_type hybrid_bezout_subresultant(
00246         typename Polynomial_traits_d::Polynomial_d f, 
00247         typename Polynomial_traits_d::Polynomial_d g, 
00248         int sub = 0
00249 ) { 
00250 
00251     typedef typename Polynomial_traits_d::Polynomial_d Polynomial;
00252     typedef typename Polynomial_traits_d::Coefficient_type NT;
00253     typename Polynomial_traits_d::Degree degree;
00254     typename CGAL::Algebraic_structure_traits<Polynomial>::Is_zero is_zero;
00255     
00256     typedef CGALi::Simple_matrix<NT> Matrix;
00257 
00258     CGAL_precondition((degree(f) >= 0));
00259     CGAL_precondition((degree(g) >= 0));
00260     
00261     if (is_zero(f) || is_zero(g)) return NT(0);
00262     
00263     Matrix S = hybrid_bezout_matrix<Polynomial_traits_d>(f, g, sub);
00264     CGAL_assertion(S.row_dimension() == S.column_dimension());
00265     if (S.row_dimension() == 0) {
00266         return NT(1);
00267     } else {
00268         return CGALi::determinant(S);
00269     }
00270 }
00271 
00272 // Transforms the minors of the symmetric bezout matrix into the subresultant.
00273 // Needs the appropriate power of the leading coedfficient of f and the
00274 // degrees of f and g
00275 template<class InputIterator,class OutputIterator,class NT>
00276 void symmetric_minors_to_subresultants(InputIterator in,
00277                                        OutputIterator out,
00278                                        NT divisor,
00279                                        int n,
00280                                        int m,
00281                                        bool swapped) {
00282   
00283     typename CGAL::Algebraic_structure_traits<NT>::Integral_division idiv;
00284     
00285     for(int i=0;i<m;i++) {
00286       bool negate = ((n-m+i+1) & 2)>>1; // (n-m+i+1)==2 or 3 mod 4
00287       negate=negate ^ (swapped & ((n-m+i+1)*(i+1)));  
00288       //...XOR (swapped AND (n-m+i+1)* (i+1) is odd) 
00289       
00290       *out = idiv(*in,  negate ? -divisor : divisor);
00291       in++;
00292       out++;
00293     }
00294 }
00295 
00296 
00308 template<class Polynomial_traits_d,class OutputIterator>
00309 OutputIterator symmetric_bezout_subresultants(
00310            typename Polynomial_traits_d::Polynomial_d f, 
00311            typename Polynomial_traits_d::Polynomial_d g,
00312            OutputIterator sres)
00313 {
00314 
00315     typedef typename Polynomial_traits_d::Polynomial_d Polynomial;
00316     typedef typename Polynomial_traits_d::Coefficient_type NT;
00317     typename Polynomial_traits_d::Degree degree;
00318     typename CGAL::Algebraic_structure_traits<Polynomial>::Is_zero is_zero;
00319     typename Polynomial_traits_d::Leading_coefficient lcoeff;
00320 
00321     typedef typename CGALi::Simple_matrix<NT> Matrix;
00322     
00323     int n = degree(f);
00324     int m = degree(g);
00325     
00326     bool swapped=false;
00327 
00328     if(n < m) {
00329       std::swap(f,g);
00330       std::swap(n,m);
00331       swapped=true;
00332       
00333     }
00334 
00335     Matrix B = symmetric_bezout_matrix<Polynomial_traits_d>(f,g);
00336     
00337     // Compute a_0^{n-m}
00338 
00339     NT divisor=ipower(lcoeff(f),n-m);
00340     
00341     std::vector<NT> minors;
00342     minors_berkowitz(B,std::back_inserter(minors),n,m);
00343     CGAL::CGALi::symmetric_minors_to_subresultants(minors.begin(),sres,
00344                                                    divisor,n,m,swapped);
00345     
00346     return sres; 
00347   }
00348 
00349 /* 
00350  * Return a modified version of the hybrid bezout matrix such that the minors
00351  * from the last k rows and columns give the subresultants
00352  */
00353 template<class Polynomial_traits_d>
00354 typename CGALi::Simple_matrix<typename Polynomial_traits_d::Coefficient_type>
00355 modified_hybrid_bezout_matrix
00356     (typename Polynomial_traits_d::Polynomial_d f,
00357      typename Polynomial_traits_d::Polynomial_d g) {
00358 
00359     typedef typename Polynomial_traits_d::Coefficient_type NT;
00360 
00361     typedef typename CGALi::Simple_matrix<NT> Matrix;
00362     
00363     typename Polynomial_traits_d::Degree degree;
00364 
00365     int n = degree(f);
00366     int m = degree(g);
00367     
00368     int i,j;
00369 
00370     bool negate, swapped=false;
00371 
00372     if(n < m) {
00373       std::swap(f,g); //(*)
00374       std::swap(n,m);
00375       swapped=true;
00376     }
00377     
00378     Matrix B = CGAL::CGALi::hybrid_bezout_matrix<Polynomial_traits_d>(f,g);
00379 
00380 
00381     // swap columns
00382     i=0;
00383     while(i<n-i-1) {
00384       B.swap_columns(i,n-i-1); // (**)
00385       i++;
00386     }
00387     for(i=0;i<n;i++) { 
00388       negate=(n-i-1) & 1; // Negate every second column because of (**)
00389       negate=negate ^ (swapped & (n-m+1)); // XOR negate everything because of(*)
00390       if(negate) {
00391         for(j=0;j<n;j++) {
00392           B[j][i] *= -1;
00393         }
00394       }
00395     }
00396     return B;
00397 }
00398 
00410 template<class Polynomial_traits_d,class OutputIterator>
00411 OutputIterator hybrid_bezout_subresultants(
00412            typename Polynomial_traits_d::Polynomial_d f, 
00413            typename Polynomial_traits_d::Polynomial_d g,
00414            OutputIterator sres) 
00415   {
00416 
00417     typedef typename Polynomial_traits_d::Coefficient_type NT;
00418     typename Polynomial_traits_d::Degree degree;
00419 
00420     typedef typename CGALi::Simple_matrix<NT> Matrix;
00421     
00422     int n = degree(f);
00423     int m = degree(g);
00424 
00425     Matrix B = CGAL::CGALi::modified_hybrid_bezout_matrix<Polynomial_traits_d>
00426         (f,g);
00427 
00428     if(n<m) {
00429       std::swap(n,m);
00430     }
00431 
00432     return minors_berkowitz(B,sres,n,m);
00433   }
00434 
00435 
00436   // Swap entry A_ij with A_(n-i)(n-j) for square matrix A of dimension n
00437   template<class NT>
00438     void swap_entries(typename CGALi::Simple_matrix<NT> & A) {
00439     CGAL_precondition(A.row_dimension()==A.column_dimension());
00440     int n = A.row_dimension();
00441     int i=0;
00442     while(i<n-i-1) {
00443         A.swap_rows(i,n-i-1); 
00444         A.swap_columns(i,n-i-1); 
00445         i++;
00446     }
00447   }
00448   
00449   // Produce S-matrix with the given matrix and integers.
00450   template<class NT,class InputIterator>
00451     typename CGALi::Simple_matrix<NT> s_matrix(
00452               const typename CGALi::Simple_matrix<NT>& B,
00453               InputIterator num,int size)
00454     {
00455       typename CGALi::Simple_matrix<NT> S(size);
00456       CGAL_precondition_code(int n = B.row_dimension();)
00457       CGAL_precondition(n==(int)B.column_dimension());
00458       int curr_num;
00459       bool negate;
00460       
00461       for(int i=0;i<size;i++) {
00462         curr_num=(*num);
00463         num++;
00464         negate = curr_num<0;
00465         if(curr_num<0) {
00466           curr_num=-curr_num;
00467         }
00468         for(int j=0;j<size;j++) {
00469           
00470           S[j][i]=negate ? -B[j][curr_num-1] : B[j][curr_num-1];
00471           
00472         }
00473       }
00474       return S;
00475     }
00476   
00477   // Produces the integer sequence for the S-matrix, where c is the first entry
00478   // of the sequence, s the number of desired diagonals and n the dimension 
00479   // of the base matrix
00480   template<class OutputIterator>
00481     OutputIterator s_matrix_integer_sequence(OutputIterator it,
00482                                               int c,int s,int n) {
00483     CGAL_precondition(0<s);
00484     CGAL_precondition(s<=n);
00485     // c is interpreted modulo s wrt to the representants {1,..,s}
00486     c=c%s;
00487     if(c==0) {
00488       c=s;
00489     }
00490     
00491     int i, p=0, q=c;
00492     while(q<=n) {
00493       *it = q;
00494       it++;
00495       for(i=p+1;i<q;i++) {
00496         *it = -i;
00497         it++;
00498       }
00499       p = q;
00500       q = q+s;
00501     }
00502     return it;
00503   }
00504 
00521 template<typename Polynomial_traits_d>
00522 typename CGALi::Simple_matrix<typename Polynomial_traits_d::Coefficient_type> 
00523 polynomial_subresultant_matrix(typename Polynomial_traits_d::Polynomial_d f,
00524                                typename Polynomial_traits_d::Polynomial_d g,
00525                                int d=0) {
00526 
00527     typedef typename Polynomial_traits_d::Coefficient_type NT;
00528     typename Polynomial_traits_d::Degree degree;
00529     typename Polynomial_traits_d::Leading_coefficient lcoeff;
00530 
00531     int n = degree(f);
00532     int m = degree(g);
00533 
00534     CGAL_precondition(n>=0);
00535     CGAL_precondition(m>=0);
00536     CGAL_precondition(d>=0);
00537 
00538     typedef CGALi::Simple_matrix<NT> Matrix;
00539    
00540     bool swapped=false;
00541 
00542     if(n < m) {
00543       std::swap(f,g);
00544       std::swap(n,m);
00545       swapped=true;
00546     }
00547 
00548     if(d==0) {
00549       d=m;
00550     };
00551 
00552 
00553     Matrix B = CGAL::CGALi::symmetric_bezout_matrix<Polynomial_traits_d>(f,g);
00554 
00555     // For easier notation, we swap all entries:
00556     CGALi::swap_entries<NT>(B);
00557     
00558     // Compute the S-matrices and collect the minors
00559     std::vector<Matrix> s_mat(m);
00560     std::vector<std::vector<NT> > coeffs(d);
00561     for(int i = 1; i<=d;i++) {
00562       std::vector<int> intseq;
00563       CGALi::s_matrix_integer_sequence(std::back_inserter(intseq),i,d,n);
00564 
00565       Matrix S = CGALi::s_matrix<NT>(B,intseq.begin(),(int)intseq.size());
00566       CGALi::swap_entries<NT>(S);
00567       //std::cout << S << std::endl;
00568       int Sdim = S.row_dimension();
00569       int number_of_minors=(Sdim < m) ? Sdim : Sdim; 
00570       
00571       CGALi::minors_berkowitz(S,std::back_inserter(coeffs[i-1]),
00572                             Sdim,number_of_minors);
00573 
00574     }
00575 
00576     // Now, rearrange the minors in the matrix
00577 
00578     Matrix Ret(m,m,NT(0));
00579 
00580     for(int i = 0; i < d; i++) {
00581       for(int j = 0;j < m-i ; j++) {
00582         int s_index=(n-m+j+i+1)%d;
00583         if(s_index==0) {
00584           s_index=d;
00585         }
00586         s_index--;
00587         Ret[j][j+i]=coeffs[s_index][n-m+j];
00588         
00589       }
00590     }
00591 
00592     typename CGAL::Algebraic_structure_traits<NT>::Integral_division idiv;
00593 
00594     NT divisor = ipower(lcoeff(f),n-m); 
00595 
00596     // Divide through the divisor and set the correct sign
00597     for(int i=0;i<m;i++) {
00598       for(int j = i;j<m;j++) {
00599         bool negate = ((n-m+i+1) & 2)>>1; // (n-m+i+1)==2 or 3 mod 4
00600         negate=negate ^ (swapped & ((n-m+i+1)*(i+1)));  
00601         //...XOR (swapped AND (n-m+i+1)* (i+1) is odd) 
00602         Ret[i][j] = idiv(Ret[i][j],  negate ? -divisor : divisor);
00603       }
00604     }
00605 
00606     return Ret;
00607 }
00608 
00609 }
00610 
00611 CGAL_END_NAMESPACE
00612 
00613 
00614 
00615 #endif // CGAL_POLYNOMIAL_BEZOUT_MATRIX_H
00616 // EOF
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines