BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Polynomial/resultant.h
Go to the documentation of this file.
00001 // Copyright (c) 2008 Max-Planck-Institute Saarbruecken (Germany).
00002 // All rights reserved.
00003 //
00004 // This file is part of CGAL (www.cgal.org); you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public License as
00006 // published by the Free Software Foundation; version 2.1 of the License.
00007 // See the file LICENSE.LGPL distributed with CGAL.
00008 //
00009 // Licensees holding a valid commercial license may use this file in
00010 // accordance with the commercial license agreement provided with the software.
00011 //
00012 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00013 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00014 //
00015 // $URL: svn+ssh://afabri@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $
00016 // $Id: Polynomial.h 46502 2008-10-28 08:36:59Z hemmer $
00017 //
00018 //
00019 // Author(s)     : Michael Hemmer <hemmer@mpi-inf.mpg.de>
00020 
00021 
00022 #ifndef CGAL_POLYNOMIAL_RESULTANT_H
00023 #define CGAL_POLYNOMIAL_RESULTANT_H
00024 
00025 // Modular arithmetic is slower, hence the default is 0
00026 #ifndef CGAL_RESULTANT_USE_MODULAR_ARITHMETIC
00027 #define CGAL_RESULTANT_USE_MODULAR_ARITHMETIC 0
00028 #endif
00029 
00030 #ifndef CGAL_RESULTANT_USE_DECOMPOSE
00031 #define CGAL_RESULTANT_USE_DECOMPOSE 1
00032 #endif 
00033 
00034 
00035 #include <CGAL/basic.h>
00036 #include <CGAL/Polynomial.h>
00037 
00038 #include <CGAL/Polynomial_traits_d.h>
00039 #include <CGAL/Polynomial/Interpolator.h>
00040 #include <CGAL/Polynomial/prs_resultant.h>
00041 #include <CGAL/Polynomial/bezout_matrix.h>
00042 
00043 #include <CGAL/Residue.h>
00044 #include <CGAL/Modular_traits.h>
00045 #include <CGAL/Chinese_remainder_traits.h>
00046 #include <CGAL/primes.h>
00047 #include <CGAL/Polynomial/Cached_extended_euclidean_algorithm.h>
00048 
00049 CGAL_BEGIN_NAMESPACE
00050 
00051 
00052 // The main function provided within this file is CGAL::CGALi::resultant(F,G),
00053 // all other functions are used for dispatching. 
00054 // The implementation uses interpolatation for multivariate polynomials
00055 // Due to the recursive structuture of CGAL::Polynomial<Coeff> it is better 
00056 // to write the function such that the inner most variabel is eliminated. 
00057 // However,  CGAL::CGALi::resultant(F,G) eliminates the outer most variabel.
00058 // This is due to backward compatibility issues with code base on EXACUS. 
00059 // In turn CGAL::CGALi::resultant_(F,G) eliminates the innermost variable. 
00060  
00061 // Dispatching
00062 // CGAL::CGALi::resultant_decompose applies if Coeff is a Fraction
00063 // CGAL::CGALi::resultant_modularize applies if Coeff is Modularizable
00064 // CGAL::CGALi::resultant_interpolate applies for multivairate polynomials
00065 // CGAL::CGALi::resultant_univariate selects the proper algorithm for IC 
00066 
00067 // CGAL_RESULTANT_USE_DECOMPOSE ( default = 1 )
00068 // CGAL_RESULTANT_USE_MODULAR_ARITHMETIC (default = 0 ) 
00069 
00070 namespace CGALi{
00071 
00072 template <class Coeff> 
00073 inline Coeff resultant_interpolate( 
00074     const CGAL::Polynomial<Coeff>&, const CGAL::Polynomial<Coeff>& );
00075 template <class Coeff> 
00076 inline Coeff resultant_modularize( 
00077     const CGAL::Polynomial<Coeff>&, 
00078     const CGAL::Polynomial<Coeff>&, CGAL::Tag_true);
00079 template <class Coeff> 
00080 inline Coeff resultant_modularize( 
00081     const CGAL::Polynomial<Coeff>&, 
00082     const CGAL::Polynomial<Coeff>&, CGAL::Tag_false);
00083 template <class Coeff> 
00084 inline Coeff resultant_decompose( 
00085     const CGAL::Polynomial<Coeff>&, 
00086     const CGAL::Polynomial<Coeff>&, CGAL::Tag_true);
00087 template <class Coeff> 
00088 inline Coeff resultant_decompose( 
00089     const CGAL::Polynomial<Coeff>&, 
00090     const CGAL::Polynomial<Coeff>&, CGAL::Tag_false);
00091 template <class Coeff> 
00092 inline Coeff resultant_( 
00093     const CGAL::Polynomial<Coeff>&, const CGAL::Polynomial<Coeff>&);
00094 
00095 template <class Coeff> 
00096 inline Coeff resultant_univariate( 
00097     const CGAL::Polynomial<Coeff>& A, 
00098     const CGAL::Polynomial<Coeff>& B, 
00099     CGAL::Integral_domain_without_division_tag){ 
00100   return hybrid_bezout_subresultant(A,B,0);
00101 }
00102 template <class Coeff> 
00103 inline Coeff resultant_univariate( 
00104     const CGAL::Polynomial<Coeff>& A, 
00105     const CGAL::Polynomial<Coeff>& B, CGAL::Integral_domain_tag){
00106   // this seems to help for for large polynomials 
00107   return prs_resultant_integral_domain(A,B);
00108 }
00109 template <class Coeff> 
00110 inline Coeff resultant_univariate( 
00111     const CGAL::Polynomial<Coeff>& A, 
00112     const CGAL::Polynomial<Coeff>& B, CGAL::Unique_factorization_domain_tag){
00113   return prs_resultant_ufd(A,B);
00114 }
00115 
00116 template <class Coeff> 
00117 inline Coeff resultant_univariate( 
00118     const CGAL::Polynomial<Coeff>& A, 
00119     const CGAL::Polynomial<Coeff>& B, CGAL::Field_tag){
00120   return prs_resultant_field(A,B);  
00121 }
00122 
00123 } // namespace CGALi
00124 
00125 namespace CGALi{
00126 
00127 
00128 template <class IC> 
00129 inline IC 
00130 resultant_interpolate( 
00131     const CGAL::Polynomial<IC>& F, 
00132     const CGAL::Polynomial<IC>& G){
00133   CGAL_precondition(CGAL::Polynomial_traits_d<CGAL::Polynomial<IC> >::d == 1);
00134     typedef CGAL::Algebraic_structure_traits<IC> AST_IC;
00135     typedef typename AST_IC::Algebraic_category Algebraic_category;
00136     return CGALi::resultant_univariate(F,G,Algebraic_category()); 
00137 }
00138 
00139 template <class Coeff_2> 
00140 inline
00141 CGAL::Polynomial<Coeff_2>  resultant_interpolate(
00142         const CGAL::Polynomial<CGAL::Polynomial<Coeff_2> >& F, 
00143         const CGAL::Polynomial<CGAL::Polynomial<Coeff_2> >& G){
00144     
00145     typedef CGAL::Polynomial<Coeff_2> Coeff_1;
00146     typedef CGAL::Polynomial<Coeff_1> POLY;
00147     typedef CGAL::Polynomial_traits_d<POLY> PT;
00148     typedef typename PT::Innermost_coefficient_type IC; 
00149 
00150     CGAL_precondition(PT::d >= 2);
00151     
00152     typename PT::Degree degree; 
00153     int maxdegree = degree(F,0)*degree(G,PT::d-1) + degree(F,PT::d-1)*degree(G,0); 
00154 
00155     typedef std::pair<IC,Coeff_2> Point; 
00156     std::vector<Point> points; // interpolation points  
00157     
00158    
00159     typename CGAL::Polynomial_traits_d<Coeff_1>::Degree  coeff_degree; 
00160     int i(-maxdegree/2);
00161     int deg_f(0);
00162     int deg_g(0);
00163     
00164    
00165     while((int) points.size() <= maxdegree + 1){
00166         i++;
00167         // timer1.start();
00168         Coeff_1 Fat_i = typename PT::Evaluate()(F,IC(i));
00169         Coeff_1 Gat_i = typename PT::Evaluate()(G,IC(i));
00170         // timer1.stop();
00171         
00172         int deg_f_at_i = coeff_degree(Fat_i,0);
00173         int deg_g_at_i = coeff_degree(Gat_i,0);
00174 
00175         // std::cout << F << std::endl;
00176         // std::cout << Fat_i << std::endl;
00177         // std::cout << deg_f_at_i << " vs. " << deg_f << std::endl;
00178         if(deg_f_at_i >  deg_f ){
00179             points.clear();
00180             deg_f  = deg_f_at_i;
00181             CGAL_postcondition(points.size() == 0);
00182         } 
00183 
00184         if(deg_g_at_i >  deg_g){
00185             points.clear();
00186             deg_g  = deg_g_at_i;
00187             CGAL_postcondition(points.size() == 0);
00188         }
00189         
00190         if(deg_f_at_i ==  deg_f && deg_g_at_i ==  deg_g){
00191             // timer2.start();
00192             Coeff_2 res_at_i = resultant_interpolate(Fat_i, Gat_i);
00193             // timer2.stop();
00194             points.push_back(Point(IC(i),res_at_i));
00195             
00196             // std::cout << typename Polynomial_traits_d<Coeff_2>::Degree()(res_at_i) << std::endl ; 
00197         }      
00198     }
00199    
00200     // timer3.start();
00201     CGAL::CGALi::Interpolator<Coeff_1> interpolator(points.begin(),points.end());
00202     Coeff_1 result = interpolator.get_interpolant();
00203     // timer3.stop();
00204 
00205 #ifndef CGAL_NDEBUG
00206     while((int) points.size() <= maxdegree + 3){
00207         i++;
00208         Coeff_1 Fat_i = typename PT::Evaluate()(F,IC(i));
00209         Coeff_1 Gat_i = typename PT::Evaluate()(G,IC(i));
00210         
00211         assert(coeff_degree(Fat_i,0) <= deg_f);
00212         assert(coeff_degree(Gat_i,0) <= deg_g);
00213         
00214         if(coeff_degree( Fat_i , 0) ==  deg_f && coeff_degree( Gat_i , 0 ) ==  deg_g){
00215             Coeff_2 res_at_i = resultant_interpolate(Fat_i, Gat_i);
00216             points.push_back(Point(IC(i), res_at_i));
00217         }
00218     }
00219     CGAL::CGALi::Interpolator<Coeff_1> 
00220       interpolator_(points.begin(),points.end());
00221     Coeff_1 result_= interpolator_.get_interpolant();
00222     
00223      // the interpolate polynomial has to be stable !
00224     assert(result_ == result); 
00225 #endif 
00226     return result; 
00227 }
00228 
00229 template <class Coeff> 
00230 inline
00231 Coeff resultant_modularize( 
00232         const CGAL::Polynomial<Coeff>& F, 
00233         const CGAL::Polynomial<Coeff>& G, 
00234         CGAL::Tag_false){
00235     return resultant_interpolate(F,G);
00236 };
00237 
00238 template <class Coeff> 
00239 inline
00240 Coeff resultant_modularize( 
00241         const CGAL::Polynomial<Coeff>& F, 
00242         const CGAL::Polynomial<Coeff>& G, 
00243         CGAL::Tag_true){
00244     
00245   // Enforce IEEE double precision and to nearest before using modular arithmetic
00246   CGAL::Protect_FPU_rounding<true> pfr(CGAL_FE_TONEAREST);
00247   
00248 
00249     typedef Polynomial_traits_d<CGAL::Polynomial<Coeff> > PT;
00250     typedef typename PT::Polynomial_d Polynomial;
00251     typedef typename PT::Innermost_coefficient_type IC;
00252     
00253     
00254     typedef Chinese_remainder_traits<Coeff> CRT;
00255     typedef typename CRT::Scalar_type Scalar;
00256 
00257 
00258     typedef typename CGAL::Modular_traits<Polynomial>::Residue_type MPolynomial; 
00259     typedef typename CGAL::Modular_traits<Coeff>::Residue_type      MCoeff; 
00260     typedef typename CGAL::Modular_traits<Scalar>::Residue_type     MScalar;  
00261         
00262     typename CRT::Chinese_remainder chinese_remainder; 
00263     typename CGAL::Modular_traits<Coeff>::Modular_image_representative inv_map;
00264 
00265 
00266     typename PT::Degree_vector                                     degree_vector; 
00267     typename CGAL::Polynomial_traits_d<MPolynomial>::Degree_vector mdegree_vector;
00268 
00269     bool solved = false; 
00270     int prime_index = 0; 
00271     int n = 0;
00272     Scalar p,q,pq,s,t; 
00273     Coeff R, R_old; 
00274     
00275     // CGAL::Timer timer_evaluate, timer_resultant, timer_cr; 
00276     
00277     do{
00278         MPolynomial mF, mG;
00279         MCoeff mR;
00280         //timer_evaluate.start();
00281         do{
00282             // select a prime number
00283             int current_prime = -1;
00284             prime_index++;
00285             if(prime_index >= 2000){
00286                 std::cerr<<"primes in the array exhausted"<<std::endl;
00287                 assert(false);
00288                 current_prime = CGALi::get_next_lower_prime(current_prime);
00289             } else{
00290                 current_prime = CGALi::primes[prime_index];
00291             }
00292             CGAL::Residue::set_current_prime(current_prime);
00293             
00294             mF = CGAL::modular_image(F);
00295             mG = CGAL::modular_image(G);
00296             
00297         }while( degree_vector(F) != mdegree_vector(mF) || 
00298                 degree_vector(G) != mdegree_vector(mG));
00299         //timer_evaluate.stop();
00300         
00301         //timer_resultant.start();
00302         n++;
00303         mR = resultant_interpolate(mF,mG);
00304         //timer_resultant.stop();
00305         //timer_cr.start();
00306         if(n == 1){ 
00307             // init chinese remainder
00308             q =  CGAL::Residue::get_current_prime(); // implicit ! 
00309             R = inv_map(mR);
00310         }else{
00311             // continue chinese remainder
00312             p = CGAL::Residue::get_current_prime(); // implicit!  
00313             R_old  = R ;
00314 //            chinese_remainder(q,Gs ,p,inv_map(mG_),pq,Gs);             
00315 //            cached_extended_euclidean_algorithm(q,p,s,t);
00316             CGALi::Cached_extended_euclidean_algorithm
00317                 <typename CRT::Scalar_type> ceea;
00318             ceea(q,p,s,t);
00319             pq =p*q;
00320             chinese_remainder(q,p,pq,s,t,R_old,inv_map(mR),R);
00321             q=pq;
00322         }
00323         solved = (R==R_old);
00324         //timer_cr.stop();       
00325     } while(!solved);
00326         
00327     //std::cout << "Time Evaluate   : " << timer_evaluate.time() << std::endl; 
00328     //std::cout << "Time Resultant  : " << timer_resultant.time() << std::endl; 
00329     //std::cout << "Time Chinese R  : " << timer_cr.time() << std::endl; 
00330     // CGAL_postcondition(R == resultant_interpolate(F,G));
00331     return R;
00332     // return resultant_interpolate(F,G);
00333 }
00334 
00335 
00336 template <class Coeff> 
00337 inline
00338 Coeff resultant_decompose( 
00339     const CGAL::Polynomial<Coeff>& F,
00340     const CGAL::Polynomial<Coeff>& G, 
00341     CGAL::Tag_false){
00342 #if CGAL_RESULTANT_USE_MODULAR_ARITHMETIC
00343   typedef CGAL::Polynomial<Coeff> Polynomial; 
00344   typedef typename Modular_traits<Polynomial>::Is_modularizable Is_modularizable; 
00345   return resultant_modularize(F,G,Is_modularizable());
00346 #else
00347   return  resultant_modularize(F,G,CGAL::Tag_false());
00348 #endif
00349 }
00350 
00351 template <class Coeff> 
00352 inline
00353 Coeff resultant_decompose( 
00354         const CGAL::Polynomial<Coeff>& F, 
00355         const CGAL::Polynomial<Coeff>& G, 
00356         CGAL::Tag_true){  
00357     
00358     typedef Polynomial<Coeff> POLY;
00359     typedef typename Fraction_traits<POLY>::Numerator_type Numerator;
00360     typedef typename Fraction_traits<POLY>::Denominator_type Denominator;
00361     typename Fraction_traits<POLY>::Decompose decompose;
00362     typedef typename Numerator::NT RES;
00363     
00364     Denominator a, b;
00365     // F.simplify_coefficients(); not const 
00366     // G.simplify_coefficients(); not const 
00367     Numerator F0; decompose(F,F0,a);
00368     Numerator G0; decompose(G,G0,b);
00369     Denominator c = CGAL::ipower(a, G.degree()) * CGAL::ipower(b, F.degree());
00370     typedef Algebraic_structure_traits<RES> AST_RES;
00371     typedef typename AST_RES::Algebraic_category Algebraic_category;
00372     RES res0 =  CGAL::CGALi::resultant_(F0, G0);
00373     typename Fraction_traits<Coeff>::Compose comp_frac;
00374     Coeff res = comp_frac(res0, c);
00375     typename Algebraic_structure_traits<Coeff>::Simplify simplify;
00376     simplify(res);
00377     return res;
00378 }
00379 
00380 
00381 template <class Coeff> 
00382 inline
00383 Coeff resultant_( 
00384         const CGAL::Polynomial<Coeff>& F, 
00385         const CGAL::Polynomial<Coeff>& G){
00386 #if CGAL_RESULTANT_USE_DECOMPOSE
00387     typedef CGAL::Fraction_traits<Polynomial<Coeff > > FT;
00388     typedef typename FT::Is_fraction Is_fraction; 
00389     return resultant_decompose(F,G,Is_fraction());
00390 #else
00391     return resultant_decompose(F,G,CGAL::Tag_false());
00392 #endif
00393 }
00394 
00395 
00396 
00397 template <class Coeff> 
00398 inline
00399 Coeff  resultant( 
00400         const CGAL::Polynomial<Coeff>& F_, 
00401         const CGAL::Polynomial<Coeff>& G_){
00402   // make the variable to be elimnated the innermost one.
00403     typedef CGAL::Polynomial_traits_d<CGAL::Polynomial<Coeff> > PT;
00404     CGAL::Polynomial<Coeff> F = typename PT::Move()(F_, PT::d-1, 0);
00405     CGAL::Polynomial<Coeff> G = typename PT::Move()(G_, PT::d-1, 0);
00406     return CGALi::resultant_(F,G);
00407 }
00408 
00409 } // namespace CGALi    
00410 CGAL_END_NAMESPACE
00411 
00412 
00413 
00414 #endif // CGAL_POLYNOMIAL_RESULTANT_H
00415 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines