indii/ml/aux/PNorm.hpp

00001 #ifndef INDII_ML_AUX_PNORM_HPP
00002 #define INDII_ML_AUX_PNORM_HPP
00003 
00004 #include "Norm.hpp"
00005 
00006 namespace indii {
00007   namespace ml {
00008     namespace aux {
00009 /**
00010  * Vector p-norm, \f$\|\cdot\|_p\f$.
00011  *
00012  * @author Lawrence Murray <lawrence@indii.org>
00013  * @version $Rev: 420 $
00014  * @date $Date: 2008-04-03 20:56:55 +0100 (Thu, 03 Apr 2008) $
00015  *
00016  * @param P Degree of the p-norm.
00017  */
00018 template <unsigned int P>
00019 class PNorm : public Norm {
00020 public:
00021   /**
00022    * Destructor.
00023    */
00024   virtual ~PNorm();
00025 
00026   virtual double operator()(const vector& x) const;
00027 
00028   virtual vector sample(const unsigned int N) const;
00029 
00030 private:
00031   /**
00032    * Serialize.
00033    */
00034   template<class Archive>
00035   void serialize(Archive& ar, const unsigned int version);
00036 
00037   /*
00038    * Boost.Serialization requirements.
00039    */
00040   friend class boost::serialization::access;
00041     
00042 };
00043 
00044 template<>
00045 vector PNorm<2>::sample(const unsigned int N) const;
00046 
00047     }
00048   }
00049 }
00050 
00051 #include "Random.hpp"
00052 #include "vector.hpp"
00053 
00054 #include <set>
00055 
00056 using namespace indii::ml::aux;
00057 
00058 template<unsigned int P>
00059 indii::ml::aux::PNorm<P>::~PNorm() {
00060   //
00061 }
00062 
00063 template<unsigned int P>
00064 inline double indii::ml::aux::PNorm<P>::operator()(const vector& x)
00065     const {
00066   return norm<P,vector>(x);
00067 }
00068 
00069 template<>
00070 indii::ml::aux::vector indii::ml::aux::PNorm<2>::sample(
00071     const unsigned int N) const {   
00072   return Random::unitVector(N);
00073 }
00074 
00075 template<unsigned int P>
00076 indii::ml::aux::vector indii::ml::aux::PNorm<P>::sample(
00077     const unsigned int N) const {   
00078   unsigned int i;
00079   std::multiset<double> u;
00080   std::multiset<double>::iterator iter, end;
00081   vector x(N);
00082   
00083   /* sample independent uniform variates on [0,1] and sort */
00084   for (i = 0; i < N - 1; i++) {
00085     u.insert(Random::uniform(0.0, 1.0));
00086   }
00087   
00088   /* calculate increments */
00089   if (!u.empty()) {
00090     iter = u.begin();
00091     end = u.end();
00092     x(0) = *iter;
00093     iter++;
00094     for (i = 1; iter != end; iter++, i++) {
00095       x(i) = *iter - x(i - 1);
00096     }
00097     x(N - 1) = 1.0 - x(N - 2);
00098   } else {
00099     x(0) = 1.0;
00100   }
00101   //assert (sum(x) == 1.0);
00102   
00103   /* normalise to unit vector in given norm */
00104   for (i = 0; i < N; i++) {
00105     x(i) = pow(x(i), 1.0 / P);
00106     if (Random::bernoulli() == 0) {
00107       x(i) *= -1.0;
00108     }
00109   }
00110   
00111   return x;
00112   
00113   /* alternative angular coordinates approach (for 2-norm only)? See
00114    * Wikipedia article on "n-sphere" */
00115   //unsigned int i;
00116   //double y;
00117   //vector x(N), phi(N - 1);
00118   
00119   /* sample angular coordinates (radians), last has range of 2*PI,
00120    * others PI */
00121   //if (N >= 2) {
00122   //  for (i = 0; i < N - 2; i++) {
00123   //    phi(i) = Random::uniform(0.0, M_PI);
00124   //  }
00125   //  phi(N - 2) = Random::uniform(0.0, 2.0*M_PI);
00126   //}
00127   
00128   /* calculate cartesian coordinates */
00129   //y = 1.0;
00130   //for (i = 0; i < N - 1; i++) {
00131   //  x(i) = y * cos(phi(i));
00132   //  y *= sin(phi(i));
00133   //}
00134   //x(N - 1) = y;
00135 }
00136 
00137 template<unsigned int P>
00138 template<class Archive>
00139 void indii::ml::aux::PNorm<P>::serialize(Archive& ar,
00140     const unsigned int version) {  
00141   ar & boost::serialization::base_object<Norm>(*this);
00142 }
00143 
00144 #endif
00145 

Generated on Wed Dec 17 15:11:57 2008 for dysii Dynamical Systems Library by  doxygen 1.5.3