ConstrainedOptPack_MatrixHessianSuperBasic.cpp

Go to the documentation of this file.
00001 #if 0
00002 
00003 // @HEADER
00004 // ***********************************************************************
00005 // 
00006 // Moocho: Multi-functional Object-Oriented arCHitecture for Optimization
00007 //                  Copyright (2003) Sandia Corporation
00008 // 
00009 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00010 // license for use of this work by or on behalf of the U.S. Government.
00011 // 
00012 // This library is free software; you can redistribute it and/or modify
00013 // it under the terms of the GNU Lesser General Public License as
00014 // published by the Free Software Foundation; either version 2.1 of the
00015 // License, or (at your option) any later version.
00016 //  
00017 // This library is distributed in the hope that it will be useful, but
00018 // WITHOUT ANY WARRANTY; without even the implied warranty of
00019 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020 // Lesser General Public License for more details.
00021 //  
00022 // You should have received a copy of the GNU Lesser General Public
00023 // License along with this library; if not, write to the Free Software
00024 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00025 // USA
00026 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov) 
00027 // 
00028 // ***********************************************************************
00029 // @HEADER
00030 
00031 #include "ConstrainedOptPack_MatrixHessianSuperBasic.hpp"
00032 #include "ConstrainedOptPack_initialize_Q_R_Q_X.hpp"
00033 #include "AbstractLinAlgPack_GenPermMatrixSliceOp.hpp"
00034 #include "AbstractLinAlgPack/src/AbstractLinAlgPack_SpVectorClass.hpp"
00035 #include "AbstractLinAlgPack_SpVectorOp.hpp"
00036 #include "AbstractLinAlgPack/src/AbstractLinAlgPack_MatrixOpOut.hpp"
00037 #include "DenseLinAlgPack_DVectorClass.hpp"
00038 #include "DenseLinAlgPack_LinAlgOpPack.hpp"
00039 #include "DenseLinAlgPack_AssertOp.hpp"
00040 
00041 namespace LinAlgOpPack {
00042   using AbstractLinAlgPack::Vp_StMtV;
00043 }
00044 
00045 namespace ConstrainedOptPack {
00046 
00047 MatrixHessianSuperBasic::MatrixHessianSuperBasic()
00048   : n_(0)
00049 {}
00050 
00051 void MatrixHessianSuperBasic::initialize(
00052   size_type            n
00053   ,size_type           n_R
00054   ,const size_type     i_x_free[]
00055   ,const size_type     i_x_fixed[]
00056   ,const EBounds       bnd_fixed[]
00057   ,const B_RR_ptr_t&   B_RR_ptr
00058   ,const B_RX_ptr_t&   B_RX_ptr
00059   ,BLAS_Cpp::Transp    B_RX_trans
00060   ,const B_XX_ptr_t&   B_XX_ptr
00061   )
00062 {
00063   using DenseLinAlgPack::Mp_M_assert_sizes;
00064   using BLAS_Cpp::no_trans;
00065 
00066   const size_type
00067     n_X = n - n_R;
00068 
00069     // Validate input arguments
00070 
00071   // i_x_free
00072   if( 0 < n_R && n_R < n && i_x_free == NULL ) {
00073     throw std::invalid_argument(
00074       "MatrixHessianSuperBasic::initialize(...) : Error, "
00075       "i_x_free can not be NULL when 0 < n_R < n" );
00076   }
00077   // i_x_fixed
00078   if( 0 < n_X && n_X < n && i_x_fixed == NULL ) {
00079     throw std::invalid_argument(
00080       "MatrixHessianSuperBasic::initialize(...) : Error, "
00081       "i_x_fixed can not be NULL when 0 < n-n_R < n" );
00082   }
00083   // bnd_fixed
00084   if( 0 < n_X && bnd_fixed == NULL ) {
00085     throw std::invalid_argument(
00086       "MatrixHessianSuperBasic::initialize(...) : Error, "
00087       "bnd_fixed can not be NULL when 0 < n-n_R" );
00088   }
00089   // B_RR
00090   if(n_R > 0 ) {
00091     if( !B_RR_ptr.get() )
00092       throw std::invalid_argument(
00093         "MatrixHessianSuperBasic::initialize(...) : Error, "
00094         "B_RR_ptr.get() can not be NULL when n_R > 0" );
00095     Mp_M_assert_sizes( n_R, n_R, no_trans, B_RR_ptr->rows(), B_RR_ptr->cols(), no_trans );
00096   }
00097   // op(B_RX)
00098   if( n_R < n ) {
00099     if( B_RX_ptr.get() ) {
00100       Mp_M_assert_sizes( n_R, n_X, no_trans, B_RX_ptr->rows(), B_RX_ptr->cols(), B_RX_trans );
00101     }
00102   }
00103   // B_XX
00104   if( n_R < n ) {
00105     if( !B_XX_ptr.get() )
00106       throw std::invalid_argument(
00107         "MatrixHessianSuperBasic::initialize(...) : Error, "
00108         "B_XX_ptr.get() can not be NULL if n_R < n" );
00109     Mp_M_assert_sizes( n_X, n_X, no_trans, B_XX_ptr->rows(), B_XX_ptr->cols(), no_trans );
00110   }
00111 
00112   // Setup Q_R and Q_X and validate i_x_free[] and i_x_fixed[]
00113   const bool Q_R_is_idenity = (n_R == n && i_x_fixed == NULL );
00114   if( Q_R_is_idenity ) {
00115     Q_R_row_i_.resize(0);
00116     Q_R_col_j_.resize(0);
00117   }
00118   else {
00119     Q_R_row_i_.resize(n_R);
00120     Q_R_col_j_.resize(n_R);
00121   }
00122   Q_X_row_i_.resize(n_X);
00123   Q_X_col_j_.resize(n_X);
00124   bool test_setup = true;  // ToDo: Make this an input parameter!
00125   initialize_Q_R_Q_X(
00126     n_R,n_X,i_x_free,i_x_fixed,test_setup
00127     ,!Q_R_is_idenity ? &Q_R_row_i_[0] : NULL
00128     ,!Q_R_is_idenity ? &Q_R_col_j_[0] : NULL
00129     ,&Q_R_
00130     ,n_X ? &Q_X_row_i_[0] : NULL
00131     ,n_X ? &Q_X_col_j_[0] : NULL
00132     ,&Q_X_
00133   );
00134 
00135   // Setup bnd_fixed
00136   bnd_fixed_.resize(n_X);
00137   {for(size_type i = 0; i < n_X; ++i) bnd_fixed_[i] = bnd_fixed[i]; }
00138 
00139   // Set the rest of the arguments
00140   n_           = n;
00141   n_R_         = n_R;
00142   B_RR_ptr_    = B_RR_ptr;
00143   B_RX_ptr_    = B_RX_ptr;
00144   B_RX_trans_  = B_RX_trans;
00145   B_XX_ptr_    = B_XX_ptr;
00146 
00147 }
00148 
00149 // Overridden from Matrix
00150 
00151 size_type MatrixHessianSuperBasic::rows() const
00152 {
00153   return n_;
00154 }
00155 
00156 // Overridden from MatrixOp
00157 
00158 void MatrixHessianSuperBasic::Vp_StMtV(
00159   DVectorSlice* y, value_type a, BLAS_Cpp::Transp B_trans
00160   , const DVectorSlice& x, value_type b
00161   ) const
00162 {
00163   using BLAS_Cpp::no_trans;
00164   using BLAS_Cpp::trans;
00165   using BLAS_Cpp::trans_not;
00166   using AbstractLinAlgPack::V_MtV;
00167   using LinAlgOpPack::V_MtV;
00168   assert_initialized();
00169   DenseLinAlgPack::Vp_MtV_assert_sizes( y->size(), n_, n_, B_trans, x.size() );
00170   if( n_ == n_R_ ) {
00171     //
00172     // B = Q_R*B_RR*Q_R'
00173     //
00174     // y = b*y + a*Q_R*B_RR*Q_R'*x
00175     //
00176     if( Q_R().is_identity() ) {
00177       AbstractLinAlgPack::Vp_StMtV(y,a,*this->B_RR_ptr(),no_trans,x,b);
00178     }
00179     else {
00180       DVector Q_R_x;
00181       V_MtV( &Q_R_x, Q_R(), trans, x );
00182       AbstractLinAlgPack::Vp_StPtMtV(y,a,Q_R(),no_trans,*this->B_RR_ptr(),no_trans,Q_R_x(),b);
00183     }
00184   }
00185   else if( n_R_ == 0 ) {
00186     //
00187     // B = Q_X *B_XX * Q_X'
00188     //
00189     TEST_FOR_EXCEPT(true); // ToDo: Implement this!
00190   }
00191   else {
00192     //
00193     // B = [ Q_R  Q_X  ] * [   B_RR      op(B_RX) ] * [ Q_R' ]
00194     //                     [ op(B_RX')      B_XX  ]   [ Q_X' ]
00195     //
00196     // y = b*y + a*op(B)*x
00197     //
00198     // y = b*y + a * [ Q_R  Q_X ] * [   B_RR      op(B_RX) ] * [ Q_R' ] * x
00199     //                              [ op(B_RX')      B_XX  ]   [ Q_X' ]
00200     //
00201     // y = b*y + a*Q_R*B_RR*x_R      + a*Q_R*op(B_RX)*x_X
00202     //         + a*Q_X*op(B_RX')*x_R + a*Q_X*B_XX*x_X
00203     // where:
00204     //     x_R = Q_R'*x
00205     //     x_X = Q_X'*x
00206     //
00207     SpVector
00208       x_R,
00209       x_X;
00210     // x_R = Q_R'*x
00211     V_MtV( &x_R, Q_R(), trans, x );
00212     // x_X = Q_X'*x
00213     V_MtV( &x_X, Q_X(), trans, x );
00214     // y = b*y + a*Q_R*B_RR*x_R
00215     AbstractLinAlgPack::Vp_StPtMtV(
00216       y, a, Q_R(), no_trans, *B_RR_ptr(), no_trans, x_R(), b );
00217     // y += a*Q_R*op(B_RX)*x_X + a*Q_X*op(B_RX')*x_R
00218     if( B_RX_ptr().get() ) {
00219       AbstractLinAlgPack::Vp_StPtMtV(
00220         y, a, Q_R(), no_trans, *B_RX_ptr(), B_RX_trans(), x_X() );
00221       AbstractLinAlgPack::Vp_StPtMtV(
00222         y, a, Q_X(), no_trans, *B_RX_ptr(), trans_not(B_RX_trans()), x_R() );
00223     }
00224     // y += a*Q_X*B_XX*x_X
00225     AbstractLinAlgPack::Vp_StPtMtV(
00226       y, a, Q_X(), no_trans, *B_XX_ptr(), no_trans, x_X() );
00227   }
00228 }
00229 
00230 void MatrixHessianSuperBasic::Vp_StMtV(
00231   DVectorSlice* y, value_type a, BLAS_Cpp::Transp B_trans
00232   , const SpVectorSlice& x, value_type b
00233   ) const
00234 {
00235   using BLAS_Cpp::no_trans;
00236   using BLAS_Cpp::trans;
00237   using BLAS_Cpp::trans_not;
00238   using AbstractLinAlgPack::V_MtV;
00239   using LinAlgOpPack::V_MtV;
00240   assert_initialized();
00241   DenseLinAlgPack::Vp_MtV_assert_sizes( y->size(), n_, n_, B_trans, x.size() );
00242   if( n_ == n_R_ ) {
00243     //
00244     // B = Q_R*B_RR*Q_R'
00245     //
00246     // y = b*y + a*Q_R*B_RR*Q_R'*x
00247     //
00248     if( Q_R().is_identity() ) {
00249       AbstractLinAlgPack::Vp_StMtV(y,a,*this->B_RR_ptr(),no_trans,x,b);
00250     }
00251     else {
00252       SpVector Q_R_x;
00253       AbstractLinAlgPack::V_MtV( &Q_R_x, Q_R(), trans, x );
00254       AbstractLinAlgPack::Vp_StPtMtV(y,a,Q_R(),no_trans,*this->B_RR_ptr(),no_trans,Q_R_x(),b);
00255     }
00256   }
00257   else if( n_R_ == 0 ) {
00258     //
00259     // B = Q_X *B_XX * Q_X'
00260     //
00261     TEST_FOR_EXCEPT(true); // ToDo: Implement this!
00262   }
00263   else {
00264     //
00265     // B = [ Q_R  Q_X  ] * [   B_RR      op(B_RX) ] * [ Q_R' ]
00266     //                     [ op(B_RX')      B_XX  ]   [ Q_X' ]
00267     //
00268     // y = b*y + a*op(B)*x
00269     //
00270     // y = b*y + a * [ Q_R  Q_X ] * [   B_RR      op(B_RX) ] * [ Q_R' ] * x
00271     //                              [ op(B_RX')      B_XX  ]   [ Q_X' ]
00272     //
00273     // y = b*y + a*Q_R*B_RR*x_R      + a*Q_R*op(B_RX)*x_X
00274     //         + a*Q_X*op(B_RX')*x_R + a*Q_X*B_XX*x_X
00275     // where:
00276     //     x_R = Q_R'*x
00277     //     x_X = Q_X'*x
00278     //
00279     SpVector
00280       x_R,
00281       x_X;
00282     // x_R = Q_R'*x
00283     V_MtV( &x_R, Q_R(), trans, x );
00284     // x_X = Q_X'*x
00285     V_MtV( &x_X, Q_X(), trans, x );
00286     // y = b*y + a*Q_R*B_RR*x_R
00287     AbstractLinAlgPack::Vp_StPtMtV(
00288       y, a, Q_R(), no_trans, *B_RR_ptr(), no_trans, x_R(), b );
00289     // y += a*Q_R*op(B_RX)*x_X + a*Q_X*op(B_RX')*x_R
00290     if( B_RX_ptr().get() ) {
00291       AbstractLinAlgPack::Vp_StPtMtV(
00292         y, a, Q_R(), no_trans, *B_RX_ptr(), B_RX_trans(), x_X() );
00293       AbstractLinAlgPack::Vp_StPtMtV(
00294         y, a, Q_X(), no_trans, *B_RX_ptr(), trans_not(B_RX_trans()), x_R() );
00295     }
00296     // y += a*Q_X*B_XX*x_X
00297     AbstractLinAlgPack::Vp_StPtMtV(
00298       y, a, Q_X(), no_trans, *B_XX_ptr(), no_trans, x_X() );
00299   }
00300 }
00301 
00302 void MatrixHessianSuperBasic::Vp_StPtMtV(
00303   DVectorSlice* y, value_type a
00304   , const GenPermMatrixSlice& P, BLAS_Cpp::Transp P_trans
00305   , BLAS_Cpp::Transp M_trans
00306   , const DVectorSlice& x, value_type b ) const
00307 {
00308   using BLAS_Cpp::no_trans;
00309   using BLAS_Cpp::trans;
00310   using BLAS_Cpp::trans_not;
00311   using AbstractLinAlgPack::V_MtV;
00312   using DenseLinAlgPack::Vt_S;
00313   using LinAlgOpPack::V_MtV;
00314   namespace slap = AbstractLinAlgPack;
00315 
00316   assert_initialized();
00317 
00318   //
00319   // y = b*y + a * op(P) * B * x
00320   //
00321   // =>
00322   //
00323   // y = b*y + a * op(P)*(Q_R*B_RR*Q_R' + Q_R*op(B_RX)*Q_X' + Q_X*op(B_RX')*Q_R + Q_X*B_XX*Q_X')*x
00324   //   
00325   //   = b*y + a*op(P)*Q_R*B_RR*Q_R'*x     + a*op(P)*Q_R*op(B_RX)*Q_X'*x
00326   //         + a*op(P)*Q_X*op(B_RX')*Q_R*x + a*op(P)*Q_X*B_XX*Q_X'*x
00327   //
00328   // In order to implement the above as efficiently as possible we need to minimize the
00329   // computations with the constituent matrices.  First off we will compute
00330   // Q_RT_x = Q_R'*x (O(n_R)) and Q_XT_x = Q_X'*x (O(n_R)) neglect any terms where
00331   // Q_RT_x.nz() == 0 or Q_XT_x.nz() == 0.  We will also determine if op(P)*Q_R == 0 (O(n_R))
00332   // or op(P)*Q_X == 0 (O(n_X)) and neglect these terms if the are zero.
00333   // Hopefully this work will allow us to skip as many computations as possible.
00334   //
00335   LinAlgOpPack::Vp_MtV_assert_sizes(y->size(),P.rows(),P.cols(),P_trans
00336     , BLAS_Cpp::rows( rows(), cols(), M_trans) );
00337   LinAlgOpPack::Vp_MtV_assert_sizes( BLAS_Cpp::cols( P.rows(), P.cols(), P_trans)
00338     ,rows(),cols(),M_trans,x.size());
00339   // Q_R'*x
00340   SpVector Q_RT_x;
00341   if(n_R_) {
00342     slap::V_MtV( &Q_RT_x, Q_R(), trans, x );
00343   }
00344   // Q_X'*x
00345   SpVector Q_XT_x;
00346   if(n_ > n_R_) {
00347     slap::V_MtV( &Q_XT_x, Q_X(), trans, x );
00348   }
00349   // op(P)*Q_R overlap
00350   size_type P_Q_R_nz = 0;
00351   AbstractLinAlgPack::intersection( P, P_trans, Q_R(), no_trans, &P_Q_R_nz );
00352   // op(P)*Q_X overlap
00353   size_type P_Q_X_nz = 0;
00354   AbstractLinAlgPack::intersection( P, P_trans, Q_X(), no_trans, &P_Q_X_nz );
00355   // y = b*y
00356   if(b==0.0)      *y = 0.0;
00357   else if(b!=1.0) Vt_S(y,b);
00358   // 
00359   DVector t; // ToDo: use workspace
00360   // y += a*op(P)*Q_R*B_RR*Q_R'*x
00361   if( P_Q_R_nz && Q_RT_x.nz() ) {
00362     t.resize(n_);
00363     slap::Vp_StPtMtV( &t(), 1.0, Q_R(), no_trans, *B_RR_ptr(), no_trans, Q_RT_x() );
00364     slap::Vp_StMtV( y, a, P, P_trans, t() );
00365   }
00366   // y += a*op(P)*Q_R*op(B_RX)*Q_X'*x
00367   if( P_Q_R_nz && B_RX_ptr().get() && Q_XT_x.nz() ) {
00368     t.resize(n_);
00369     slap::Vp_StPtMtV( &t(), 1.0, Q_R(), no_trans, *B_RX_ptr(), B_RX_trans(), Q_XT_x() );
00370     slap::Vp_StMtV( y, a, P, P_trans, t() );
00371   }
00372   // y += a*op(P)*Q_X*op(B_RX')*Q_R*x
00373   if( P_Q_X_nz && B_RX_ptr().get() && Q_RT_x.nz() ) {
00374     t.resize(n_);
00375     slap::Vp_StPtMtV( &t(), 1.0, Q_X(), no_trans, *B_RX_ptr(), trans_not(B_RX_trans()), Q_RT_x() );
00376     slap::Vp_StMtV( y, a, P, P_trans, t() );
00377   }
00378   // y += a*op(P)*Q_X*B_XX*Q_X'*x
00379   if( P_Q_X_nz && Q_XT_x.nz() ) {
00380     t.resize(n_);
00381     slap::Vp_StPtMtV( &t(), 1.0, Q_X(), no_trans, *B_XX_ptr(), no_trans, Q_XT_x() );
00382     slap::Vp_StMtV( y, a, P, P_trans, t() );
00383   }
00384 }
00385 
00386 value_type MatrixHessianSuperBasic::transVtMtV(
00387   const SpVectorSlice& x1, BLAS_Cpp::Transp B_trans
00388   , const SpVectorSlice& x2 ) const
00389 {
00390   using BLAS_Cpp::no_trans;
00391   using BLAS_Cpp::trans;
00392   assert_initialized();
00393   DenseLinAlgPack::Vp_MtV_assert_sizes( x1.size(), rows(), cols(), B_trans, x1.size() );
00394   if( n_ == n_R_ ) {
00395     //
00396     // B = Q_R*B_RR*Q_R'
00397     //
00398     // a = x1'*Q_R*B_RR*Q_R'*x2
00399     //
00400     if( Q_R().is_identity() ) {
00401       return AbstractLinAlgPack::transVtMtV( x1, *B_RR_ptr(), no_trans, x2 );
00402     }
00403     else {
00404       if( x1.overlap(x2) == DenseLinAlgPack::SAME_MEM ) {
00405         SpVector Q_RT_x2;
00406         AbstractLinAlgPack::V_MtV( &Q_RT_x2, Q_R(), trans, x2 );
00407         SpVectorSlice Q_RT_x2_slc = Q_RT_x2();
00408         return AbstractLinAlgPack::transVtMtV(
00409           Q_RT_x2_slc, *B_RR_ptr(), no_trans, Q_RT_x2_slc );
00410        }
00411       else {
00412         SpVector Q_RT_x2;
00413         AbstractLinAlgPack::V_MtV( &Q_RT_x2, Q_R(), trans, x2 );
00414         SpVector Q_RT_x1;
00415         AbstractLinAlgPack::V_MtV( &Q_RT_x1, Q_R(), trans, x1 );
00416         return AbstractLinAlgPack::transVtMtV(
00417           Q_RT_x1(), *B_RR_ptr(), no_trans, Q_RT_x2() );
00418       }
00419     }
00420   }
00421   else if( n_R_ == 0 ) {
00422     //
00423     // B = Q_X *B_XX * Q_X'
00424     //
00425     TEST_FOR_EXCEPT(true); // ToDo: Implement this!
00426   }
00427   else {
00428     //
00429     // B = [ Q_R  Q_X  ] * [   B_RR      op(B_RX) ] * [ Q_R' ]
00430     //                     [ op(B_RX')      B_XX  ]   [ Q_X' ]
00431     //
00432     //
00433     // a = x1'*B*x2
00434     // =>
00435     // a = x1' * [ Q_R  Q_X  ] * [   B_RR      op(B_RX) ] * [ Q_R' ] * x2
00436     //                           [ op(B_RX')      B_XX  ]   [ Q_X' ]
00437     //
00438     // a = x1'*Q_R*B_RR*Q_R'*x2 + 2*x1'*Q_R*op(B_RX)*Q_X'*x2 + x1'*Q_X*B_XX*Q_X'*x2
00439     //
00440     if( x1.overlap(x2) == DenseLinAlgPack::SAME_MEM ) {
00441       // a = x1'*Q_R*B_RR*Q_R'*x1 + 2*x1'*Q_R*op(B_RX)*Q_X'*x1 + x1'*Q_X*B_XX*Q_X'*x1
00442       SpVector Q_RT_x1;
00443       if( Q_R().nz() )
00444         AbstractLinAlgPack::V_MtV( &Q_RT_x1, Q_R(), trans, x1 );
00445       SpVector Q_XT_x1;
00446       if( Q_X().nz() )
00447         AbstractLinAlgPack::V_MtV( &Q_XT_x1, Q_X(), trans, x1 );
00448       SpVectorSlice Q_RT_x1_slc = Q_RT_x1();
00449       SpVectorSlice Q_XT_x1_slc = Q_XT_x1();
00450       return
00451         ( Q_R().nz()
00452           ? AbstractLinAlgPack::transVtMtV(
00453             Q_RT_x1_slc, *B_RR_ptr(), no_trans, Q_RT_x1_slc )
00454           : 0.0
00455           )
00456         + 2*(  B_RX_ptr().get() && Q_R().nz() && Q_X().nz()
00457              ? AbstractLinAlgPack::transVtMtV(
00458                Q_RT_x1_slc, *B_RX_ptr(), B_RX_trans(), Q_XT_x1_slc )
00459              : 0.0
00460           )
00461         + ( Q_X().nz()
00462           ? AbstractLinAlgPack::transVtMtV(
00463             Q_XT_x1_slc, *B_XX_ptr(), no_trans, Q_XT_x1_slc )
00464           : 0.0
00465           );
00466     }
00467     else {
00468       TEST_FOR_EXCEPT(true); // ToDo: Implement this!
00469     }
00470   }
00471   return 0.0; // Will never be executed!
00472 }
00473 
00474 // Private
00475 
00476 void MatrixHessianSuperBasic::assert_initialized() const
00477 {
00478   if( !n_ )
00479     throw std::logic_error(
00480       "MatrixHessianSuperBasic::assert_initialized() : Error, "
00481       "The matrix is not initialized yet" );
00482 }
00483 
00484 } // end namespace ConstrainedOptPack
00485 
00486 #endif // 0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Generated on Wed Apr 13 10:10:57 2011 for MOOCHO (Single Doxygen Collection) by  doxygen 1.6.3