BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Polynomial/determinant.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 // TODO: The comments are all original EXACUS comments and aren't adapted. So
00022 //         they may be wrong now.
00023 
00024 #ifndef CGAL_POLYNOMIAL_DETERMINANT_H
00025 #define CGAL_POLYNOMIAL_DETERMINANT_H
00026 
00027 CGAL_BEGIN_NAMESPACE ;
00028 
00029 #include <CGAL/basic.h>
00030 
00031 namespace CGALi {
00032     
00033     // TODO: Own simple matrix and vector to avoid importing the whole matrix stuff 
00034     // from EXACUS.
00035     
00036     // This is to be replaced by a corresponding CGAL Matrix and Vector.
00037     template< class Coeff >
00038     struct Simple_matrix
00039         : public std::vector< std::vector< Coeff > > {
00040         
00041         typedef Coeff NT;    
00042 
00043         Simple_matrix() {
00044         }
00045                 
00046         Simple_matrix( int m ) {
00047             initialize( m, m, Coeff(0) );
00048         }
00049                         
00050         Simple_matrix( int m, int n, Coeff x = Coeff(0) ) {
00051             initialize( m, n, x );
00052         }
00053         
00054         void swap_rows(int i, int j) {
00055             std::vector< Coeff > swap = this->operator[](i);
00056             this->operator[](i) = this->operator[](j);
00057             this->operator[](j) = swap;
00058         }
00059 
00060         void swap_columns(int i, int j) {
00061             for(int k = 0; k < m; k++) {
00062                 Coeff swap = this->operator[](k).operator[](i);
00063                 this->operator[](k).operator[](i)
00064                     = this->operator[](k).operator[](j);
00065                 this->operator[](k).operator[](j) = swap;
00066             }
00067         }
00068 
00069         int row_dimension() const { return m; }
00070         int column_dimension() const { return n; } 
00071         
00072         private:
00073         
00074         void initialize( int m, int n, Coeff x ) {
00075             this->reserve( m );
00076             this->m = m;
00077             this->n = n;
00078             for( int i = 0; i < m; ++i ) {
00079                 this->push_back( std::vector< Coeff >() );
00080                 this->operator[](i).reserve(n);
00081                 for( int j = 0; j < n; ++j ) {
00082                     this->operator[](i).push_back( x );
00083                 }
00084             }            
00085         }
00086         
00087         int m,n;
00088     };
00089     
00090     template< class Coeff >
00091     struct Simple_vector
00092         : public std::vector< Coeff > {
00093         Simple_vector( int m ) {
00094                 this->reserve( m );
00095             for( int i = 0; i < m; ++i )
00096                 this->push_back( Coeff(0) );
00097         }
00098         
00099         Coeff operator*( const Simple_vector<Coeff>& v2 ) const {
00100             CGAL_precondition( v2.size() == this->size() );
00101             Coeff result(0);
00102                         
00103             for( unsigned i = 0; i < this->size(); ++i )
00104                 result += ( this->operator[](i) * v2[i] );
00105                 
00106             return result;
00107         }
00108     };
00109     
00110     // call for auto-selection of best routine (exact NT)
00111     template <class M> inline
00112     typename M::NT determinant (const M& matrix,
00113                                 int n,
00114                                 Integral_domain_without_division_tag,
00115                                 ::CGAL::Boolean_tag<true> )
00116     {
00117         return det_berkowitz(matrix, n);
00118     }
00119     
00120     // call for auto-selection of best routine (inexact NT)
00121     template <class M> inline
00122     typename M::NT determinant (const M& matrix,
00123                                 int n,
00124                                 Integral_domain_without_division_tag,
00125                                 ::CGAL::Boolean_tag<false> )
00126     {
00127         typedef typename M::NT NT;
00128         NT type = NT(0);
00129         
00130         return inexact_determinant_select(matrix, n, type);
00131     }
00132 
00133     // (other datatypes)
00134     template <class M, class other> inline
00135     typename M::NT inexact_determinant_select (const M& matrix,
00136                                                int n,
00137                                                other type)
00138     {
00139         return det_berkowitz(matrix, n);
00140     }
00141 
00147     template <class NT > inline 
00148     NT determinant(const CGALi::Simple_matrix<NT>& A)
00149     {
00150         CGAL_assertion(A.row_dimension()==A.column_dimension());
00151         return determinant(A,A.column_dimension());
00152     }
00153     
00159     template <class M> inline
00160     typename M::NT determinant(const M& matrix,
00161                                int n)
00162     {
00163         typedef typename M::NT NT;
00164         typedef typename Algebraic_structure_traits<NT>::Algebraic_category Algebraic_category;
00165         typedef typename Algebraic_structure_traits<NT>::Is_exact Is_exact;
00166     
00167         return CGALi::determinant (matrix, n, Algebraic_category(), Is_exact());
00168     }
00169 
00170 
00171     // Part of det_berkowitz
00172     // Computes sum of all clows of length k
00173     template <class M> 
00174     inline
00175     std::vector<typename M::NT> 
00176     clow_lengths (const M& A,int k,int n)
00177     {
00178         typedef typename M::NT NT;
00179     
00180         int i, j, l;
00181     
00182         typename CGALi::Simple_vector<NT> r(k-1);
00183         typename CGALi::Simple_vector<NT> s(k-1);
00184         typename CGALi::Simple_vector<NT> t(k-1);
00185         std::vector<NT> rMks(k);
00186     
00187         typename CGALi::Simple_matrix<NT> MM(k-1);
00188     
00189         for (i=n-k+2;i<=n;++i)
00190             for (j=n-k+2;j<=n;++j)
00191                 MM[i-n+k-2][j-n+k-2] = A[i-1][j-1];
00192     
00193         i = n-k+1;
00194         l = 1;
00195     
00196         for (j=n-k+2;j<=n;++j,++l)
00197         {
00198             r[l-1] = A[i-1][j-1];
00199             s[l-1] = A[j-1][i-1];
00200         }
00201     
00202         rMks[0] = A[i-1][i-1];
00203         rMks[1] = r*s;
00204     
00205         for (i=2;i<k;++i)
00206         {
00207             // r = r * M;
00208             for (j=0;j<k-1;++j)
00209                 for (l=0;l<k-1;++l)
00210                     t[j] += r[l] * MM[l][j];
00211             for (j=0;j<k-1;++j)
00212             {
00213                 r[j] = t[j];
00214                 t[j] = NT(0);
00215             }
00216             rMks[i] = r*s; 
00217         }
00218     
00219         return rMks;
00220     }
00221 
00229     template <class NT > inline 
00230     NT det_berkowitz(const CGALi::Simple_matrix<NT>& A)
00231     {
00232         CGAL_assertion(A.row_dimension()==A.column_dimension());
00233         return det_berkowitz(A,A.column_dimension());
00234     }
00235 
00236     template <class M, class OutputIterator> inline 
00237     OutputIterator minors_berkowitz (const M& A,OutputIterator minors,int n,int m=0)
00238     {
00239         CGAL_precondition(n>0);
00240         CGAL_precondition(m<=n);
00241         
00242        
00243         typedef typename M::NT NT;
00244         
00245         // If default value is set, reset it to the second parameter
00246         if(m==0) {
00247           m=n;
00248         }
00249     
00250         int i, j, k, offset;
00251         std::vector<NT> rMks;
00252         NT a;
00253     
00254         typename CGALi::Simple_matrix<NT> B(n+1);  // not square in original
00255     
00256         typename CGALi::Simple_vector<NT> p(n+1);
00257         typename CGALi::Simple_vector<NT> q(n+1);
00258     
00259         for (k=1;k<=n;++k)
00260         {
00261             // compute vector q = B*p;
00262             if (k == 1)
00263         {
00264                 p[0] = NT(-1);
00265                 q[0] = p[0];
00266                 p[1] = A[n-1][n-1];
00267                 q[1] = p[1];
00268         }
00269             else if (k == 2)
00270             {
00271                 p[0] = NT(1);
00272                 q[0] = p[0];
00273                 p[1] = -A[n-2][n-2] - A[n-1][n-1];
00274                 q[1] = p[1];
00275                 p[2] = -A[n-2][n-1] * A[n-1][n-2] + A[n-2][n-2] * A[n-1][n-1];
00276                 q[2] = p[2];
00277         }
00278             else if (k == n)
00279         {
00280                 rMks = CGALi::clow_lengths<M>(A,k,n);
00281                 // Setup for last row of matrix B
00282                 i = n+1;
00283                 B[i-1][n-1] = NT(-1);
00284     
00285                 for (j=1;j<=n;++j)
00286                     B[i-1][i-j-1] = rMks[j-1];
00287     
00288                 p[i-1] = NT(0);
00289     
00290                 for (j=1;j<=n;++j)
00291                     p[i-1] = p[i-1] + B[i-1][j-1] * q[j-1];
00292         }
00293             else
00294             {
00295                 rMks = CGALi::clow_lengths<M>(A,k,n);
00296     
00297                 // Setup for matrix B (diagonal after diagonal)
00298     
00299                 for (i=1;i<=k;++i)
00300                     B[i-1][i-1] = NT(-1);
00301     
00302                 for (offset=1;offset<=k;++offset)
00303                 {
00304                     a = rMks[offset-1]; 
00305     
00306                     for (i=1;i<=k-offset+1;++i)
00307                         B[offset+i-1][i-1] = a;
00308                 }
00309     
00310                 // Multiply s.t. p=B*q
00311     
00312                 for (i=1;i<=k;++i)
00313                 {
00314                     p[i-1] = NT(0);
00315     
00316                     for (j=1;j<=i;++j)
00317                         p[i-1] = p[i-1] + B[i-1][j-1] * q[j-1];
00318                 }
00319     
00320                 p[i-1] = NT(0);
00321     
00322                 for (j=1;j<=k;++j)
00323                     p[i-1] = p[i-1] + B[i-1][j-1] * q[j-1];
00324     
00325                 for (i=1;i<=k+1;++i)
00326                     q[i-1] = p[i-1];
00327             }
00328            
00329         if(k > n-m) { 
00330           (*minors)=p[k];
00331           ++minors;
00332         }
00333         }
00334         return minors;
00335     }
00336     
00343     template <class M> inline 
00344     typename M::NT det_berkowitz (const M& A,
00345                                   int n)
00346     {
00347       typedef typename M::NT NT;
00348       if(n==0) {
00349         return NT(1);
00350       }
00351       NT det[1];
00352       minors_berkowitz(A,det,n,1);
00353       return det[0];
00354     }
00355 
00356     
00357 
00358 } // namespace CGALi
00359 
00360 
00361 
00362 CGAL_END_NAMESPACE
00363 
00364 #endif // CGAL_POLYNOMIAL_DETERMINANT_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines