mult_series_expansion_aux.h

Go to the documentation of this file.
00001 /* MLPACK 0.2
00002  *
00003  * Copyright (c) 2008, 2009 Alexander Gray,
00004  *                          Garry Boyer,
00005  *                          Ryan Riegel,
00006  *                          Nikolaos Vasiloglou,
00007  *                          Dongryeol Lee,
00008  *                          Chip Mappus, 
00009  *                          Nishant Mehta,
00010  *                          Hua Ouyang,
00011  *                          Parikshit Ram,
00012  *                          Long Tran,
00013  *                          Wee Chin Wong
00014  *
00015  * Copyright (c) 2008, 2009 Georgia Institute of Technology
00016  *
00017  * This program is free software; you can redistribute it and/or
00018  * modify it under the terms of the GNU General Public License as
00019  * published by the Free Software Foundation; either version 2 of the
00020  * License, or (at your option) any later version.
00021  *
00022  * This program is distributed in the hope that it will be useful, but
00023  * WITHOUT ANY WARRANTY; without even the implied warranty of
00024  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00025  * General Public License for more details.
00026  *
00027  * You should have received a copy of the GNU General Public License
00028  * along with this program; if not, write to the Free Software
00029  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00030  * 02110-1301, USA.
00031  */
00035 #ifndef MULT_SERIES_EXPANSION_AUX_H
00036 #define MULT_SERIES_EXPANSION_AUX_H
00037 
00038 #include "fastlib/fastlib.h"
00039 
00044 class MultSeriesExpansionAux {
00045 
00046  public:
00047 
00048   int dim_;
00049 
00050   int max_order_;
00051 
00052   Vector factorials_;
00053 
00054   ArrayList<int> list_total_num_coeffs_;
00055 
00056   Vector inv_multiindex_factorials_;
00057 
00058   Vector neg_inv_multiindex_factorials_;
00059 
00060   Matrix multiindex_combination_;
00061 
00062   ArrayList< ArrayList<int> > multiindex_mapping_;
00063 
00069   ArrayList< ArrayList<int> > lower_mapping_index_;
00070 
00076   ArrayList< ArrayList<int> > upper_mapping_index_;
00077 
00079   Matrix n_choose_k_;
00080 
00085   ArrayList< ArrayList<int> > traversal_mapping_;
00086 
00087   OT_DEF_BASIC(MultSeriesExpansionAux) {
00088     OT_MY_OBJECT(dim_);
00089     OT_MY_OBJECT(max_order_);
00090     OT_MY_OBJECT(factorials_);
00091     OT_MY_OBJECT(list_total_num_coeffs_);
00092     OT_MY_OBJECT(inv_multiindex_factorials_);
00093     OT_MY_OBJECT(neg_inv_multiindex_factorials_);
00094     OT_MY_OBJECT(multiindex_combination_);
00095     OT_MY_OBJECT(multiindex_mapping_);
00096     OT_MY_OBJECT(lower_mapping_index_);
00097     OT_MY_OBJECT(upper_mapping_index_);
00098     OT_MY_OBJECT(n_choose_k_);
00099     OT_MY_OBJECT(traversal_mapping_);
00100   }
00101 
00102  public:
00103 
00104   void ComputeFactorials() {
00105     factorials_.Init(2 * max_order_ + 1);
00106 
00107     factorials_[0] = 1;
00108     for(index_t t = 1; t < factorials_.length(); t++) {
00109       factorials_[t] = t * factorials_[t - 1];
00110     }
00111   }
00112 
00113   void ComputeTraversalMapping() {
00114 
00115     // initialize the index
00116     int limit = 2 * max_order_;
00117     traversal_mapping_.Init(limit + 1);
00118 
00119     for(index_t i = 0; i <= max_order_; i++) {
00120 
00121       traversal_mapping_[i].Init();
00122 
00123       for(index_t j = 0; j < list_total_num_coeffs_[limit]; j++) {
00124         
00125         const ArrayList<int> &mapping = multiindex_mapping_[j];
00126         int flag = 0;
00127 
00128         for(index_t d = 0; d < dim_; d++) {
00129           if(mapping[d] > i) {
00130             flag = 1;
00131             break;
00132           }
00133         }
00134 
00135         if(flag == 0) {
00136           (traversal_mapping_[i]).PushBackCopy(j);
00137         }
00138       } // end of j-loop
00139     } // end of i-loop
00140   }
00141 
00142   void ComputeLowerMappingIndex() {
00143 
00144     ArrayList<int> diff;
00145     diff.Init(dim_);
00146 
00147     // initialize the index
00148     int limit = 2 * max_order_;
00149     lower_mapping_index_.Init(list_total_num_coeffs_[limit]);
00150 
00151     for(index_t i = 0; i < list_total_num_coeffs_[limit]; i++) {
00152       const ArrayList<int> &outer_mapping = multiindex_mapping_[i];
00153       lower_mapping_index_[i].Init();
00154 
00155       for(index_t j = 0; j < list_total_num_coeffs_[limit]; j++) {
00156         const ArrayList<int> &inner_mapping = multiindex_mapping_[j];
00157         int flag = 0;
00158 
00159         for(index_t d = 0; d < dim_; d++) {
00160           diff[d] = outer_mapping[d] - inner_mapping[d];
00161 
00162           if(diff[d] < 0) {
00163             flag = 1;
00164             break;
00165           }
00166         }
00167 
00168         if(flag == 0) {
00169           (lower_mapping_index_[i]).PushBackCopy(j);
00170         }
00171       } // end of j-loop
00172     } // end of i-loop
00173   }
00174 
00175   void ComputeMultiindexCombination() {
00176 
00177     int limit = 2 * max_order_;
00178     multiindex_combination_.Init(list_total_num_coeffs_[limit],
00179                                  list_total_num_coeffs_[limit]);
00180 
00181     for(index_t j = 0; j < list_total_num_coeffs_[limit]; j++) {
00182 
00183       // beta mapping
00184       const ArrayList<int> &beta_mapping = multiindex_mapping_[j];
00185 
00186       for(index_t k = 0; k < list_total_num_coeffs_[limit]; k++) {
00187 
00188         // alpha mapping
00189         const ArrayList<int> &alpha_mapping = multiindex_mapping_[k];
00190 
00191         // initialize the factor to 1
00192         multiindex_combination_.set(j, k, 1);
00193 
00194         for(index_t i = 0; i < dim_; i++) {
00195           multiindex_combination_.set
00196             (j, k, multiindex_combination_.get(j, k) *
00197              n_choose_k_.get(beta_mapping[i], alpha_mapping[i]));
00198 
00199           if(multiindex_combination_.get(j, k) == 0)
00200             break;
00201         }
00202       }
00203     }
00204   }
00205 
00206   void ComputeUpperMappingIndex() {
00207 
00208     ArrayList<int> diff;
00209     diff.Init(dim_);
00210 
00211     // initialize the index
00212     int limit = 2 * max_order_;
00213     upper_mapping_index_.Init(list_total_num_coeffs_[limit]);
00214 
00215     for(index_t i = 0; i < list_total_num_coeffs_[limit]; i++) {
00216       const ArrayList<int> &outer_mapping = multiindex_mapping_[i];
00217       upper_mapping_index_[i].Init();
00218 
00219       for(index_t j = 0; j < list_total_num_coeffs_[limit]; j++) {
00220         const ArrayList<int> &inner_mapping = multiindex_mapping_[j];
00221         int flag = 0;
00222 
00223         for(index_t d = 0; d < dim_; d++) {
00224           diff[d] = inner_mapping[d] - outer_mapping[d];
00225 
00226           if(diff[d] < 0) {
00227             flag = 1;
00228             break;
00229           }
00230         }
00231 
00232         if(flag == 0) {
00233           (upper_mapping_index_[i]).PushBackCopy(j);
00234         }
00235       } // end of j-loop
00236     } // end of i-loop
00237   }
00238 
00239   // getters and setters
00240   double factorial(int k) const { return factorials_[k]; }
00241 
00242   int get_dimension() const { return dim_; }
00243 
00244   int get_total_num_coeffs(int order) const { 
00245     return list_total_num_coeffs_[order]; 
00246   }
00247 
00248   int get_max_total_num_coeffs() const { 
00249     return list_total_num_coeffs_[max_order_]; 
00250   }
00251 
00252   const Vector& get_inv_multiindex_factorials() const {
00253     return inv_multiindex_factorials_;
00254   }
00255 
00256   const ArrayList< int > * get_lower_mapping_index() const {
00257     return lower_mapping_index_.begin();
00258   }
00259 
00260   int get_max_order() const {
00261     return max_order_;
00262   }
00263 
00264   const ArrayList< int > & get_multiindex(int pos) const {
00265     return multiindex_mapping_[pos];
00266   }
00267 
00268   const ArrayList< int > * get_multiindex_mapping() const {
00269     return multiindex_mapping_.begin();
00270   }
00271 
00272   const Vector& get_neg_inv_multiindex_factorials() const {
00273     return neg_inv_multiindex_factorials_;
00274   }
00275 
00276   double get_n_choose_k(int n, int k) const {
00277     return n_choose_k_.get(n, (int) math::ClampNonNegative(k));
00278   }
00279 
00280   double get_n_multichoose_k_by_pos(int n, int k) const {
00281     return multiindex_combination_.get(n, k);
00282   }
00283 
00284   const ArrayList< int > * get_upper_mapping_index() const {
00285     return upper_mapping_index_.begin();
00286   }
00287 
00288   // interesting functions
00289 
00293   int ComputeMultiindexPosition(const ArrayList<int> &multiindex) const {
00294     int index = 0;
00295     
00296     // using Horner's rule
00297     for(index_t i = 0; i < dim_; i++) {
00298       index *= (2 * max_order_ + 1);
00299       index += multiindex[i];
00300     }
00301     return index;
00302   }
00303 
00307   double FarFieldEvaluationCost(int order) const {
00308     return pow(order + 1, dim_);
00309   }
00310 
00314   double FarFieldToLocalTranslationCost(int order) const {
00315     return pow(order + 1, 2 * dim_);
00316   }
00317 
00321   double DirectLocalAccumulationCost(int order) const {
00322     return pow(order + 1, dim_);
00323   }
00324 
00329   void Init(int max_order, int dim) {
00330 
00331     // initialize max order and dimension
00332     dim_ = dim;
00333     max_order_ = max_order;
00334   
00335     // compute the list of total number of coefficients for p-th order 
00336     // expansion
00337     int limit = 2 * max_order_;
00338     list_total_num_coeffs_.Init(limit + 1);
00339     list_total_num_coeffs_[0] = 1;
00340     for(index_t p = 1; p <= limit; p++) {
00341       list_total_num_coeffs_[p] = (int) pow(p + 1, dim);
00342     }
00343 
00344     // compute factorials
00345     ComputeFactorials();
00346 
00347     // allocate space for inverse factorial and 
00348     // negative inverse factorials and multiindex mapping and n_choose_k 
00349     // and multiindex_combination precomputed factors
00350     inv_multiindex_factorials_.Init(list_total_num_coeffs_[limit]);  
00351     neg_inv_multiindex_factorials_.Init(list_total_num_coeffs_[limit]);
00352     multiindex_mapping_.Init(list_total_num_coeffs_[limit]);
00353     (multiindex_mapping_[0]).Init(dim_);
00354     for(index_t j = 0; j < dim; j++) {
00355       (multiindex_mapping_[0])[j] = 0;
00356     }
00357     n_choose_k_.Init(dim * (limit + 1), dim * (limit + 1));
00358     n_choose_k_.SetZero();
00359 
00360     // compute inverse factorial and negative inverse factorials and
00361     // multiindex mappings...
00362     inv_multiindex_factorials_[0] = 1.0;
00363     neg_inv_multiindex_factorials_[0] = 1.0;
00364     if(max_order > 0) {
00365       index_t boundary, i, k, step;
00366 
00367       for(boundary = list_total_num_coeffs_[limit], k = 0, 
00368             step = list_total_num_coeffs_[limit] / (limit + 1);
00369           step >= 1; step /= (limit + 1), 
00370             boundary /= (limit + 1), k++) {
00371 
00372         for(i = 0; i < list_total_num_coeffs_[limit]; ) {
00373           int inner_limit = i + boundary;
00374           int div = 1;
00375           
00376           i += step;
00377           
00378           for( ; i < inner_limit; i += step) {
00379             
00380             inv_multiindex_factorials_[i] = 
00381               inv_multiindex_factorials_[i - step] / div;
00382             neg_inv_multiindex_factorials_[i] =
00383               -neg_inv_multiindex_factorials_[i - step] / div;
00384             div++;
00385 
00386             // copy multiindex from old to the new position
00387             multiindex_mapping_[i].InitCopy(multiindex_mapping_[i - step]);
00388             (multiindex_mapping_[i])[k] = (multiindex_mapping_[i])[k] + 1;
00389           }
00390         }
00391       }
00392     }
00393 
00394     // compute n choose k's
00395     for(index_t j = 0; j < n_choose_k_.n_rows(); j++) {
00396       for(index_t k = 0; k < n_choose_k_.n_cols(); k++) {
00397         n_choose_k_.set(j, k, math::BinomialCoefficient(j, k));
00398       }
00399     }
00400 
00401     // initialize multiindex_combination matrix beta choose alpha
00402     ComputeMultiindexCombination();
00403 
00404     // compute the lower_mapping_index_ and the upper_mapping_index_
00405     // (see series_expansion_aux.h for explanation)
00406     ComputeLowerMappingIndex();
00407     ComputeUpperMappingIndex();
00408 
00409     // compute traversal mapping
00410     ComputeTraversalMapping();
00411   }
00412 
00416   void PrintDebug(const char *name="", FILE *stream=stderr) const {
00417     fprintf(stream, "----- SERIESEXPANSIONAUX %s ------\n", name);
00418     fprintf(stream, "Max order: %d, dimension: %d\n", max_order_, dim_);
00419 
00420     fprintf(stream, "Multiindex mapping: ");
00421     for (index_t i = 0; i < multiindex_mapping_.size(); i++) {
00422 
00423       DEBUG_ASSERT_MSG(ComputeMultiindexPosition(multiindex_mapping_[i]) == i,
00424                        "REIMPLEMENT ComputeMultiindexPosition function!");
00425       fprintf(stream, "( ");
00426       for(index_t j = 0; j < dim_; j++) {
00427         fprintf(stream, "%d ", multiindex_mapping_[i][j]);
00428       }
00429       fprintf(stream, "): %g %g ", inv_multiindex_factorials_[i],
00430               neg_inv_multiindex_factorials_[i]);
00431     }
00432     fprintf(stream, "\n");
00433   }
00434 
00435 };
00436 
00437 #endif
Generated on Mon Jan 24 12:04:38 2011 for FASTlib by  doxygen 1.6.3