polyfit.hpp
Go to the documentation of this file.
00001 #pragma once
00002 
00003 #ifdef BOOST_UBLAS_TYPE_CHECK
00004 #       undef BOOST_UBLAS_TYPE_CHECK
00005 #endif
00006 #define BOOST_UBLAS_TYPE_CHECK 0
00007 #ifndef _USE_MATH_DEFINES
00008 #       define _USE_MATH_DEFINES
00009 #endif
00010 
00011 #include <boost/numeric/ublas/matrix.hpp>
00012 #include <boost/numeric/ublas/lu.hpp>
00013 #include <vector>
00014 #include <stdexcept>
00015 
00016 /*
00017         Finds the coefficients of a polynomial p(x) of degree n that fits the data, 
00018         p(x(i)) to y(i), in a least squares sense. The result p is a row vector of 
00019         length n+1 containing the polynomial coefficients in incremental powers.
00020 
00021         param:
00022                 oX                              x axis values
00023                 oY                              y axis values
00024                 nDegree                 polynomial degree including the constant
00025 
00026         return:
00027                 coefficients of a polynomial starting at the constant coefficient and
00028                 ending with the coefficient of power to nDegree. C++0x-compatible 
00029                 compilers make returning locally created vectors very efficient.
00030 
00031 */
00032 template<typename T>
00033 std::vector<T> polyfit( const std::vector<T>& oX, const std::vector<T>& oY, int nDegree )
00034 {
00035         using namespace boost::numeric::ublas;
00036 
00037         if ( oX.size() != oY.size() )
00038                 throw std::invalid_argument( "X and Y vector sizes do not match" );
00039 
00040         // more intuative this way
00041         nDegree++;
00042         
00043         size_t nCount =  oX.size();
00044         matrix<T> oXMatrix( nCount, nDegree );
00045         matrix<T> oYMatrix( nCount, 1 );
00046         
00047         // copy y matrix
00048         for ( size_t i = 0; i < nCount; i++ )
00049         {
00050                 oYMatrix(i, 0) = oY[i];
00051         }
00052 
00053         // create the X matrix
00054         for ( size_t nRow = 0; nRow < nCount; nRow++ )
00055         {
00056                 T nVal = 1.0f;
00057                 for ( int nCol = 0; nCol < nDegree; nCol++ )
00058                 {
00059                         oXMatrix(nRow, nCol) = nVal;
00060                         nVal *= oX[nRow];
00061                 }
00062         }
00063 
00064         // transpose X matrix
00065         matrix<T> oXtMatrix( trans(oXMatrix) );
00066         // multiply transposed X matrix with X matrix
00067         matrix<T> oXtXMatrix( prec_prod(oXtMatrix, oXMatrix) );
00068         // multiply transposed X matrix with Y matrix
00069         matrix<T> oXtYMatrix( prec_prod(oXtMatrix, oYMatrix) );
00070 
00071         // lu decomposition
00072         permutation_matrix<int> pert(oXtXMatrix.size1());
00073         const std::size_t singular = lu_factorize(oXtXMatrix, pert);
00074         // must be singular
00075         BOOST_ASSERT( singular == 0 );
00076 
00077         // backsubstitution
00078         lu_substitute(oXtXMatrix, pert, oXtYMatrix);
00079 
00080         // copy the result to coeff
00081         return std::vector<T>( oXtYMatrix.data().begin(), oXtYMatrix.data().end() );
00082 }
00083 
00084 /*
00085         Calculates the value of a polynomial of degree n evaluated at x. The input 
00086         argument pCoeff is a vector of length n+1 whose elements are the coefficients 
00087         in incremental powers of the polynomial to be evaluated.
00088 
00089         param:
00090                 oCoeff                  polynomial coefficients generated by polyfit() function
00091                 oX                              x axis values
00092 
00093         return:
00094                 Fitted Y values. C++0x-compatible compilers make returning locally 
00095                 created vectors very efficient.
00096 */
00097 template<typename T>
00098 std::vector<T> polyval( const std::vector<T>& oCoeff, const std::vector<T>& oX )
00099 {
00100         size_t nCount =  oX.size();
00101         size_t nDegree = oCoeff.size();
00102         std::vector<T>  oY( nCount );
00103 
00104         for ( size_t i = 0; i < nCount; i++ )
00105         {
00106                 T nY = 0;
00107                 T nXT = 1;
00108                 T nX = oX[i];
00109                 for ( size_t j = 0; j < nDegree; j++ )
00110                 {
00111                         // multiply current x by a coefficient
00112                         nY += oCoeff[j] * nXT;
00113                         // power up the X
00114                         nXT *= nX;
00115                 }
00116                 oY[i] = nY;
00117         }
00118 
00119         return oY;
00120 }


dt_local_planner
Author(s): Stephan Hofstaetter
autogenerated on Fri Aug 28 2015 13:41:25