Changeset 886 for library/bdm/stat

Show
Ignore:
Timestamp:
03/29/10 23:01:49 (14 years ago)
Author:
smidl
Message:

epdf and emix now have _base classes

Location:
library/bdm/stat
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • library/bdm/stat/emix.cpp

    r878 r886  
    33namespace bdm { 
    44 
    5 void emix::validate (){ 
    6         bdm_assert ( Coms.length() > 0, "There has to be at least one component." ); 
    7  
    8         bdm_assert ( Coms.length() == w.length(), "It is obligatory to define weights of all the components." ); 
     5void emix_base::validate (){ 
     6        bdm_assert ( no_coms() > 0, "There has to be at least one component." ); 
     7 
     8        bdm_assert ( no_coms() == w.length(), "It is obligatory to define weights of all the components." ); 
    99 
    1010        double sum_w = sum ( w ); 
     
    1212        w = w / sum_w; 
    1313 
    14         dim = Coms ( 0 )->dimension(); 
    15         RV rv_tmp = Coms ( 0 )->_rv() ; 
    16         bool isnamed = Coms ( 0 )->isnamed(); 
    17         for ( int i = 1; i < Coms.length(); i++ ) { 
    18                 bdm_assert ( dim == ( Coms ( i )->dimension() ), "Component sizes do not match!" ); 
    19                 isnamed &= Coms(i)->isnamed() & Coms(i)->_rv().equal(rv_tmp); 
     14        dim = component ( 0 )->dimension(); 
     15        RV rv_tmp = component ( 0 )->_rv() ; 
     16        bool isnamed = component( 0 )->isnamed(); 
     17        for ( int i = 1; i < no_coms(); i++ ) { 
     18                bdm_assert ( dim == ( component ( i )->dimension() ), "Component sizes do not match!" ); 
     19                isnamed &= component(i)->isnamed() & component(i)->_rv().equal(rv_tmp); 
    2020        } 
    2121        if (isnamed) 
     
    2323} 
    2424 
    25 void emix::from_setting ( const Setting &set ) { 
    26         UI::get ( Coms, set, "pdfs", UI::compulsory ); 
    27  
    28         if ( !UI::get ( w, set, "weights", UI::optional ) ) { 
    29                 int len = Coms.length(); 
    30                 w.set_length ( len ); 
    31                 w = 1.0 / len; 
    32         } 
    33 } 
    34  
    35  
    36 vec emix::sample() const { 
     25 
     26 
     27vec emix_base::sample() const { 
    3728        //Sample which component 
    3829        vec cumDist = cumsum ( w ); 
     
    4637        } 
    4738 
    48         return Coms ( i )->sample(); 
    49 } 
    50  
    51 vec emix::mean() const { 
     39        return component ( i )->sample(); 
     40} 
     41 
     42vec emix_base::mean() const { 
    5243        int i; 
    5344        vec mu = zeros ( dim ); 
    5445        for ( i = 0; i < w.length(); i++ ) { 
    55                 mu += w ( i ) * Coms ( i )->mean(); 
     46                mu += w ( i ) * component ( i )->mean(); 
    5647        } 
    5748        return mu; 
    5849} 
    5950 
    60 vec emix::variance() const { 
     51vec emix_base::variance() const { 
    6152        //non-central moment 
    6253        vec mom2 = zeros ( dim ); 
    6354        for ( int i = 0; i < w.length(); i++ ) { 
    64                 mom2 += w ( i ) * ( Coms ( i )->variance() + pow ( Coms ( i )->mean(), 2 ) ); 
     55                mom2 += w ( i ) * ( component( i )->variance() + pow ( component ( i )->mean(), 2 ) ); 
    6556        } 
    6657        //central moment 
     
    6859} 
    6960 
    70 double emix::evallog ( const vec &val ) const { 
     61double emix_base::evallog ( const vec &val ) const { 
    7162        int i; 
    7263        double sum = 0.0; 
    7364        for ( i = 0; i < w.length(); i++ ) { 
    74                 sum += w ( i ) * exp ( Coms ( i )->evallog ( val ) ); 
     65                sum += w ( i ) * exp ( component ( i )->evallog ( val ) ); 
    7566        } 
    7667        if ( sum == 0.0 ) { 
     
    8273} 
    8374 
    84 vec emix::evallog_mat ( const mat &Val ) const { 
     75vec emix_base::evallog_mat ( const mat &Val ) const { 
    8576        vec x = zeros ( Val.cols() ); 
    8677        for ( int i = 0; i < w.length(); i++ ) { 
    87                 x += w ( i ) * exp ( Coms ( i )->evallog_mat ( Val ) ); 
     78                x += w ( i ) * exp ( component( i )->evallog_mat ( Val ) ); 
    8879        } 
    8980        return log ( x ); 
    9081}; 
    9182 
    92 mat emix::evallog_coms ( const mat &Val ) const { 
     83mat emix_base::evallog_coms ( const mat &Val ) const { 
    9384        mat X ( w.length(), Val.cols() ); 
    9485        for ( int i = 0; i < w.length(); i++ ) { 
    95                 X.set_row ( i, w ( i ) *exp ( Coms ( i )->evallog_mat ( Val ) ) ); 
     86                X.set_row ( i, w ( i ) *exp ( component( i )->evallog_mat ( Val ) ) ); 
    9687        } 
    9788        return X; 
    9889} 
    9990 
    100 shared_ptr<epdf> emix::marginal ( const RV &rv ) const { 
     91shared_ptr<epdf> emix_base::marginal ( const RV &rv ) const { 
    10192        emix *tmp = new emix(); 
    10293        shared_ptr<epdf> narrow ( tmp ); 
     
    10596} 
    10697 
    107 void emix::marginal ( const RV &rv, emix &target ) const { 
     98void emix_base::marginal ( const RV &rv, emix &target ) const { 
    10899        bdm_assert ( isnamed(), "rvs are not assigned" ); 
    109100 
    110         Array<shared_ptr<epdf> > Cn ( Coms.length() ); 
    111         for ( int i = 0; i < Coms.length(); i++ ) { 
    112                 Cn ( i ) = Coms ( i )->marginal ( rv ); 
     101        Array<shared_ptr<epdf> > Cn ( no_coms() ); 
     102        for ( int i = 0; i < no_coms(); i++ ) { 
     103                Cn ( i ) = component ( i )->marginal ( rv ); 
    113104        } 
    114105 
     
    118109} 
    119110 
    120 shared_ptr<pdf> emix::condition ( const RV &rv ) const { 
     111shared_ptr<pdf> emix_base::condition ( const RV &rv ) const { 
    121112        bdm_assert ( isnamed(), "rvs are not assigned" ); 
    122113        mratio *tmp = new mratio ( this, rv ); 
     
    124115} 
    125116 
    126 void egiwmix::set_parameters ( const vec &w0, const Array<egiw*> &Coms0, bool copy ) { 
    127         w = w0 / sum ( w0 ); 
    128         int i; 
    129         for ( i = 0; i < w.length(); i++ ) { 
    130                 bdm_assert_debug ( dim == ( Coms0 ( i )->dimension() ), "Component sizes do not match!" ); 
    131         } 
    132         if ( copy ) { 
    133                 Coms.set_length ( Coms0.length() ); 
    134                 for ( i = 0; i < w.length(); i++ ) { 
    135                         bdm_error ( "Not implemented" ); 
    136                         // *Coms ( i ) = *Coms0 ( i ); 
    137                 } 
    138                 destroyComs = true; 
    139         } else { 
    140                 Coms = Coms0; 
    141                 destroyComs = false; 
    142         } 
    143 } 
    144  
    145 void    egiwmix::validate (){ 
    146    dim = Coms ( 0 )->dimension(); 
    147 } 
    148  
    149 vec egiwmix::sample() const { 
    150         //Sample which component 
    151         vec cumDist = cumsum ( w ); 
    152         double u0; 
    153 #pragma omp critical 
    154         u0 = UniRNG.sample(); 
    155  
    156         int i = 0; 
    157         while ( ( cumDist ( i ) < u0 ) && ( i < ( w.length() - 1 ) ) ) { 
    158                 i++; 
    159         } 
    160  
    161         return Coms ( i )->sample(); 
    162 } 
    163  
    164 vec egiwmix::mean() const { 
    165         int i; 
    166         vec mu = zeros ( dim ); 
    167         for ( i = 0; i < w.length(); i++ ) { 
    168                 mu += w ( i ) * Coms ( i )->mean(); 
    169         } 
    170         return mu; 
    171 } 
    172  
    173 vec egiwmix::variance() const { 
    174         // non-central moment 
    175         vec mom2 = zeros ( dim ); 
    176         for ( int i = 0; i < w.length(); i++ ) { 
    177                 // pow is overloaded, we have to use another approach 
    178                 mom2 += w ( i ) * ( Coms ( i )->variance() + elem_mult ( Coms ( i )->mean(), Coms ( i )->mean() ) ); 
    179         } 
    180         // central moment 
    181         // pow is overloaded, we have to use another approach 
    182         return mom2 - elem_mult ( mean(), mean() ); 
    183 } 
    184  
    185 shared_ptr<epdf> egiwmix::marginal ( const RV &rv ) const { 
    186         emix *tmp = new emix(); 
    187         shared_ptr<epdf> narrow ( tmp ); 
    188         marginal ( rv, *tmp ); 
    189         return narrow; 
    190 } 
    191  
    192 void egiwmix::marginal ( const RV &rv, emix &target ) const { 
    193         bdm_assert_debug ( isnamed(), "rvs are not assigned" ); 
    194  
    195         Array<shared_ptr<epdf> > Cn ( Coms.length() ); 
    196         for ( int i = 0; i < Coms.length(); i++ ) { 
    197                 Cn ( i ) = Coms ( i )->marginal ( rv ); 
    198         } 
    199  
    200         target._w() = w; 
    201         target._Coms() = Cn; 
    202         target.validate(); 
    203 } 
    204  
    205 egiw*   egiwmix::approx() { 
    206         // NB: dimx == 1 !!! 
    207         // The following code might look a bit spaghetti-like, 
    208         // consult Dedecius, K. et al.: Partial forgetting in AR models. 
    209  
    210         double sumVecCommon;                            // common part for many terms in eq. 
    211         int len = w.length();                           // no. of mix components 
    212         int dimLS = Coms ( 1 )->_V()._D().length() - 1;         // dim of LS 
    213         vec vecNu ( len );                                      // vector of dfms of components 
    214         vec vecD ( len );                                       // vector of LS reminders of comps. 
    215         vec vecCommon ( len );                          // vector of common parts 
    216         mat matVecsTheta;                               // matrix which rows are theta vects. 
    217  
    218         // fill in the vectors vecNu, vecD and matVecsTheta 
    219         for ( int i = 0; i < len; i++ ) { 
    220                 vecNu.shift_left ( Coms ( i )->_nu() ); 
    221                 vecD.shift_left ( Coms ( i )->_V()._D() ( 0 ) ); 
    222                 matVecsTheta.append_row ( Coms ( i )->est_theta() ); 
    223         } 
    224  
    225         // calculate the common parts and their sum 
    226         vecCommon = elem_mult ( w, elem_div ( vecNu, vecD ) ); 
    227         sumVecCommon = sum ( vecCommon ); 
    228  
    229         // LS estimator of theta 
    230         vec aprEstTheta ( dimLS ); 
    231         aprEstTheta.zeros(); 
    232         for ( int i = 0; i < len; i++ ) { 
    233                 aprEstTheta +=  matVecsTheta.get_row ( i ) * vecCommon ( i ); 
    234         } 
    235         aprEstTheta /= sumVecCommon; 
    236  
    237  
    238         // LS estimator of dfm 
    239         double aprNu; 
    240         double A = log ( sumVecCommon );                // Term 'A' in equation 
    241  
    242         for ( int i = 0; i < len; i++ ) { 
    243                 A += w ( i ) * ( log ( vecD ( i ) ) - psi ( 0.5 * vecNu ( i ) ) ); 
    244         } 
    245  
    246         aprNu = ( 1 + sqrt ( 1 + 2 * ( A - LOG2 ) / 3 ) ) / ( 2 * ( A - LOG2 ) ); 
    247  
    248  
    249         // LS reminder (term D(0,0) in C-syntax) 
    250         double aprD = aprNu / sumVecCommon; 
    251  
    252         // Aproximation of cov 
    253         // the following code is very numerically sensitive, thus 
    254         // we have to eliminate decompositions etc. as much as possible 
    255         mat aprC = zeros ( dimLS, dimLS ); 
    256         for ( int i = 0; i < len; i++ ) { 
    257                 aprC += Coms ( i )->est_theta_cov().to_mat() * w ( i ); 
    258                 vec tmp = ( matVecsTheta.get_row ( i ) - aprEstTheta ); 
    259                 aprC += vecCommon ( i ) * outer_product ( tmp, tmp ); 
    260         } 
    261  
    262         // Construct GiW pdf :: BEGIN 
    263         ldmat aprCinv ( inv ( aprC ) ); 
    264         vec D = concat ( aprD, aprCinv._D() ); 
    265         mat L = eye ( dimLS + 1 ); 
    266         L.set_submatrix ( 1, 0, aprCinv._L() * aprEstTheta ); 
    267         L.set_submatrix ( 1, 1, aprCinv._L() ); 
    268         ldmat aprLD ( L, D ); 
    269  
    270         egiw* aprgiw = new egiw ( 1, aprLD, aprNu ); 
    271         return aprgiw; 
    272 }; 
     117void emix::from_setting ( const Setting &set ) { 
     118        UI::get ( Coms, set, "pdfs", UI::compulsory ); 
     119        UI::get ( w, set, "weights", UI::compulsory ); 
     120} 
     121 
     122void    emix::validate (){ 
     123        emix_base::validate(); 
     124        dim = Coms ( 0 )->dimension(); 
     125} 
     126 
    273127 
    274128double mprod::evallogcond ( const vec &val, const vec &cond ) { 
     
    378232} 
    379233 
    380 vec eprod::mean() const { 
     234vec eprod_base::mean() const { 
    381235        vec tmp ( dim ); 
    382         for ( int i = 0; i < epdfs.length(); i++ ) { 
    383                 vec pom = epdfs ( i )->mean(); 
     236        for ( int i = 0; i < no_factors(); i++ ) { 
     237                vec pom = factor( i )->mean(); 
    384238                dls ( i )->pushup ( tmp, pom ); 
    385239        } 
     
    387241} 
    388242 
    389 vec eprod::variance() const { 
     243vec eprod_base::variance() const { 
    390244        vec tmp ( dim ); //second moment 
    391         for ( int i = 0; i < epdfs.length(); i++ ) { 
    392                 vec pom = epdfs ( i )->mean(); 
     245        for ( int i = 0; i < no_factors(); i++ ) { 
     246                vec pom = factor ( i )->mean(); 
    393247                dls ( i )->pushup ( tmp, pow ( pom, 2 ) ); 
    394248        } 
    395249        return tmp - pow ( mean(), 2 ); 
    396250} 
    397 vec eprod::sample() const { 
     251vec eprod_base::sample() const { 
    398252        vec tmp ( dim ); 
    399         for ( int i = 0; i < epdfs.length(); i++ ) { 
    400                 vec pom = epdfs ( i )->sample(); 
     253        for ( int i = 0; i < no_factors(); i++ ) { 
     254                vec pom = factor ( i )->sample(); 
    401255                dls ( i )->pushup ( tmp, pom ); 
    402256        } 
    403257        return tmp; 
    404258} 
    405 double eprod::evallog ( const vec &val ) const { 
     259double eprod_base::evallog ( const vec &val ) const { 
    406260        double tmp = 0; 
    407         for ( int i = 0; i < epdfs.length(); i++ ) { 
    408                 tmp += epdfs ( i )->evallog ( dls ( i )->pushdown ( val ) ); 
    409         } 
    410         bdm_assert_debug ( std::isfinite ( tmp ), "Infinite" ); 
    411         return tmp; 
    412 } 
    413  
    414 } 
    415 // mprod::mprod ( Array<pdf*> mFacs, bool overlap) : pdf ( RV(), RV() ), n ( mFacs.length() ), epdfs ( n ), pdfs ( mFacs ), rvinds ( n ), rvcinrv ( n ), irvcs_rvc ( n ) { 
    416 //              int i; 
    417 //              bool rvaddok; 
    418 //              // Create rv 
    419 //              for ( i = 0;i < n;i++ ) { 
    420 //                      rvaddok=rv.add ( pdfs ( i )->_rv() ); //add rv to common rvs. 
    421 //                      // If rvaddok==false, pdfs overlap => assert error. 
    422 //                      epdfs ( i ) = & ( pdfs ( i )->posterior() ); // add pointer to epdf 
    423 //              }; 
    424 //              // Create rvc 
    425 //              for ( i = 0;i < n;i++ ) { 
    426 //                      rvc.add ( pdfs ( i )->_rvc().subt ( rv ) ); //add rv to common rvs. 
    427 //              }; 
    428 // 
    429 // //           independent = true; 
    430 //              //test rvc of pdfs and fill rvinds 
    431 //              for ( i = 0;i < n;i++ ) { 
    432 //                      // find ith rv in common rv 
    433 //                      rvsinrv ( i ) = pdfs ( i )->_rv().dataind ( rv ); 
    434 //                      // find ith rvc in common rv 
    435 //                      rvcinrv ( i ) = pdfs ( i )->_rvc().dataind ( rv ); 
    436 //                      // find ith rvc in common rv 
    437 //                      irvcs_rvc ( i ) = pdfs ( i )->_rvc().dataind ( rvc ); 
    438 //                      // 
    439 // /*                   if ( rvcinrv ( i ).length() >0 ) {independent = false;} 
    440 //                      if ( irvcs_rvc ( i ).length() >0 ) {independent = false;}*/ 
    441 //              } 
    442 //      }; 
    443  
     261        for ( int i = 0; i < no_factors(); i++ ) { 
     262                tmp += factor ( i )->evallog ( dls ( i )->pushdown ( val ) ); 
     263        } 
     264        //bdm_assert_debug ( std::isfinite ( tmp ), "Infinite" ); 
     265        return tmp; 
     266} 
     267 
     268} 
     269 
  • library/bdm/stat/emix.h

    r878 r886  
    9797 
    9898 
    99  
    100  
    10199private: 
    102100        // not implemented 
    103101        mratio ( const mratio & ); 
    104102        mratio &operator= ( const mratio & ); 
     103}; 
     104 
     105class emix; //forward 
     106 
     107/*! Base class (Interface) for mixtures  
     108*/ 
     109class emix_base : public epdf { 
     110        protected: 
     111        //! reference to vector of weights 
     112        vec &w; 
     113        //! function returning ith component 
     114        virtual const epdf * component(const int &i) const=0; 
     115         
     116        virtual int no_coms() const=0; 
     117         
     118        public: 
     119                 
     120                emix_base(vec &w0): w(w0){} 
     121                 
     122                void validate (); 
     123                 
     124                vec sample() const; 
     125                 
     126                vec mean() const; 
     127                 
     128                vec variance() const; 
     129                 
     130                double evallog ( const vec &val ) const; 
     131                 
     132                vec evallog_mat ( const mat &Val ) const; 
     133                 
     134                //! Auxiliary function that returns pdflog for each component 
     135                mat evallog_coms ( const mat &Val ) const; 
     136                 
     137                shared_ptr<epdf> marginal ( const RV &rv ) const; 
     138                //! Update already existing marginal density  \c target 
     139                void marginal ( const RV &rv, emix &target ) const; 
     140                shared_ptr<pdf> condition ( const RV &rv ) const; 
     141                 
     142                //Access methods         
     143                //! returns a reference to the internal weights. Use with Care! 
     144                vec& _w() { 
     145                        return w; 
     146                } 
     147                 
     148                const vec& _w() const { 
     149                        return w; 
     150                } 
     151                //!access 
     152                const epdf* _com(int i) const {return component(i);} 
     153                 
    105154}; 
    106155 
     
    115164 
    116165*/ 
    117 class emix : public epdf { 
     166class emix : public emix_base { 
    118167protected: 
    119168        //! weights of the components 
    120         vec w; 
     169        vec weights; 
    121170 
    122171        //! Component (epdfs) 
     
    125174public: 
    126175        //! Default constructor 
    127         emix ( ) : epdf ( ) { } 
    128  
    129         virtual void validate (); 
    130  
    131         vec sample() const; 
    132  
    133         vec mean() const; 
    134  
    135         vec variance() const; 
    136  
    137         double evallog ( const vec &val ) const; 
    138  
    139         vec evallog_mat ( const mat &Val ) const; 
    140  
    141         //! Auxiliary function that returns pdflog for each component 
    142         mat evallog_coms ( const mat &Val ) const; 
    143  
    144         shared_ptr<epdf> marginal ( const RV &rv ) const; 
    145         //! Update already existing marginal density  \c target 
    146         void marginal ( const RV &rv, emix &target ) const; 
    147         shared_ptr<pdf> condition ( const RV &rv ) const; 
    148  
    149         //Access methods         
    150         //! returns a reference to the internal weights. Use with Care! 
    151         vec& _w() { 
    152                 return w; 
    153         } 
    154  
    155         /*! 
    156           \brief returns a reference to the internal array of components. Use with Care! Set components \c Coms 
    157  
    158           Shared pointers in Coms are kept inside this instance and 
    159           shouldn't be modified after being passed to this method. 
    160         */ 
    161         Array<shared_ptr<epdf> >& _Coms ( ) { 
    162                 return Coms; 
    163         } 
    164  
    165         //! returns a reference to the internal components specified by index i. Use with Care! 
    166         shared_ptr<epdf> _Coms ( int i ) { 
    167                 return Coms ( i ); 
    168         } 
    169  
    170         void set_rv ( const RV &rv ) { 
    171                 epdf::set_rv ( rv ); 
    172                 for ( int i = 0; i < Coms.length(); i++ ) { 
    173                         Coms ( i )->set_rv ( rv ); 
    174                 } 
    175         } 
     176        emix ( ) : emix_base ( weights) { } 
     177         
     178        const epdf* component(const int &i) const {return Coms(i).get();} 
     179        void validate(); 
     180         
     181 
     182        int no_coms() const {return Coms.length(); } 
    176183 
    177184        //! Load from structure with elements: 
     
    184191        //!@} 
    185192        void from_setting ( const Setting &set ); 
     193 
     194        void set_rv ( const RV &rv ) { 
     195                epdf::set_rv ( rv ); 
     196                for ( int i = 0; i < no_coms(); i++ ) { 
     197                        Coms( i )->set_rv ( rv ); 
     198                } 
     199        } 
     200         
     201        Array<shared_ptr<epdf> >& _Coms ( ) { 
     202                        return Coms; 
     203                } 
    186204}; 
    187205SHAREDPTR ( emix ); 
    188206UIREGISTER ( emix ); 
    189207 
    190 /*! 
    191 * \brief Mixture of egiws 
    192  
    193 */ 
    194 class egiwmix : public egiw { 
    195 protected: 
    196         //! weights of the components 
    197         vec w; 
    198         //! Component (epdfs) 
    199         Array<egiw*> Coms; 
    200         //!Flag if owning Coms 
    201         bool destroyComs; 
    202 public: 
    203         //!Default constructor 
    204         egiwmix ( ) : egiw ( ) {}; 
    205  
    206         //! Set weights \c w and components \c Coms 
    207         //!By default Coms are copied inside. Parameter \c copy can be set to false if Coms live externally. Use method ownComs() if Coms should be destroyed by the destructor. 
    208         void set_parameters ( const vec &w, const Array<egiw*> &Coms, bool copy = false ); 
    209          
    210         //!return expected value 
    211         void validate(); 
    212          
    213         vec mean() const; 
    214  
    215         //!return a sample from the density 
    216         vec sample() const; 
    217  
    218         //!return the expected variance 
    219         vec variance() const; 
    220  
    221         // TODO!!! Defined to follow ANSI and/or for future development 
    222         void mean_mat ( mat &M, mat&R ) const {}; 
    223         double evallog_nn ( const vec &val ) const { 
    224                 return 0; 
    225         }; 
    226         double lognc () const { 
    227                 return 0; 
    228         } 
    229  
    230         shared_ptr<epdf> marginal ( const RV &rv ) const; 
    231         //! marginal density update 
    232         void marginal ( const RV &rv, emix &target ) const; 
    233  
    234 //Access methods 
    235         //! returns a pointer to the internal mean value. Use with Care! 
    236         vec& _w() { 
    237                 return w; 
    238         } 
    239         virtual ~egiwmix() { 
    240                 if ( destroyComs ) { 
    241                         for ( int i = 0; i < Coms.length(); i++ ) { 
    242                                 delete Coms ( i ); 
    243                         } 
    244                 } 
    245         } 
    246         //! Auxiliary function for taking ownership of the Coms() 
    247         void ownComs() { 
    248                 destroyComs = true; 
    249         } 
    250  
    251         //!access function 
    252         egiw* _Coms ( int i ) { 
    253                 return Coms ( i ); 
    254         } 
    255  
    256         void set_rv ( const RV &rv ) { 
    257                 egiw::set_rv ( rv ); 
    258                 for ( int i = 0; i < Coms.length(); i++ ) { 
    259                         Coms ( i )->set_rv ( rv ); 
    260                 } 
    261         } 
    262  
    263         //! Approximation of a GiW mix by a single GiW pdf 
    264         egiw* approx(); 
    265 }; 
    266208 
    267209/*! \brief Chain rule decomposition of epdf 
     
    329271SHAREDPTR ( mprod ); 
    330272 
     273 
    331274//! Product of independent epdfs. For dependent pdfs, use mprod. 
    332 class eprod: public epdf { 
     275class eprod_base: public epdf { 
    333276protected: 
    334         //! Components (epdfs) 
    335         Array<const epdf*> epdfs; 
    336277        //! Array of indeces 
    337278        Array<datalink*> dls; 
     279        //! interface for a factor 
     280        virtual const epdf* factor(int i) const NOT_IMPLEMENTED(NULL);  
     281        //!number of factors 
     282        virtual const int no_factors() const =0; 
    338283public: 
    339284        //! Default constructor 
    340         eprod () : epdfs ( 0 ), dls ( 0 ) {}; 
     285        eprod_base () :  dls (0) {}; 
    341286        //! Set internal 
    342         void set_parameters ( const Array<const epdf*> &epdfs0, bool named = true ) { 
    343                 epdfs = epdfs0;//.set_length ( epdfs0.length() ); 
    344                 dls.set_length ( epdfs.length() ); 
     287        vec mean() const; 
     288 
     289        vec variance() const; 
     290 
     291        vec sample() const; 
     292 
     293        double evallog ( const vec &val ) const; 
     294 
     295        //!Destructor 
     296        ~eprod_base() { 
     297                for ( int i = 0; i < dls.length(); i++ ) { 
     298                        delete dls ( i ); 
     299                } 
     300        } 
     301        void validate() { 
     302                dls.set_length ( no_factors() ); 
     303                 
    345304                bool independent = true; 
    346                 if ( named ) { 
    347                         for ( int i = 0; i < epdfs.length(); i++ ) { 
    348                                 independent = rv.add ( epdfs ( i )->_rv() ); 
    349                                 bdm_assert_debug ( independent, "eprod:: given components are not independent." ); 
    350                         } 
    351                         dim = rv._dsize(); 
    352                          
    353                 } else { 
    354                         dim = 0; 
    355                         for ( int i = 0; i < epdfs.length(); i++ ) { 
    356                                 dim += epdfs ( i )->dimension(); 
    357                         } 
    358                 } 
     305                dim = 0; 
     306                for ( int i = 0; i < no_factors(); i++ ) { 
     307                        independent = rv.add ( factor ( i )->_rv() ); 
     308                        dim += factor ( i )->dimension(); 
     309                        bdm_assert_debug ( independent, "eprod:: given components are not independent." ); 
     310                }; 
     311                 
    359312                // 
    360313                int cumdim = 0; 
    361314                int dimi = 0; 
    362315                int i; 
    363                 for ( i = 0; i < epdfs.length(); i++ ) { 
     316                for ( i = 0; i < no_factors(); i++ ) { 
    364317                        dls ( i ) = new datalink; 
    365                         if ( named ) { 
    366                                 dls ( i )->set_connection ( epdfs ( i )->_rv() , rv ); 
    367                         } else { 
    368                                 dimi = epdfs ( i )->dimension(); 
     318                        if ( isnamed() ) { // rvs are complete 
     319                                dls ( i )->set_connection ( factor ( i )->_rv() , rv ); 
     320                        } else { //rvs are not reliable 
     321                                dimi = factor ( i )->dimension(); 
    369322                                dls ( i )->set_connection ( dimi, dim, linspace ( cumdim, cumdim + dimi - 1 ) ); 
    370323                                cumdim += dimi; 
     
    373326         
    374327        } 
    375  
    376          
    377         vec mean() const; 
    378  
    379         vec variance() const; 
    380  
    381         vec sample() const; 
    382  
    383         double evallog ( const vec &val ) const; 
    384  
    385         //!access function 
    386         const epdf* operator () ( int i ) const { 
    387                 bdm_assert_debug ( i < epdfs.length(), "wrong index" ); 
    388                 return epdfs ( i ); 
    389         } 
    390  
    391         //!Destructor 
    392         ~eprod() { 
    393                 for ( int i = 0; i < epdfs.length(); i++ ) { 
    394                         delete dls ( i ); 
    395                 } 
    396         } 
    397 }; 
    398  
     328}; 
     329 
     330class eprod: public eprod_base{ 
     331        protected: 
     332                Array<shared_ptr<epdf> > factors; 
     333        public: 
     334                const epdf* factor(int i) const {return factors(i).get();} 
     335                const int no_factors() const {return factors.length();} 
     336        void set_parameters ( const Array<shared_ptr<epdf> > &epdfs0) { 
     337                factors = epdfs0; 
     338        } 
     339}; 
     340 
     341//! similar to eprod but used only internally -- factors are external pointers 
     342class eprod_internal: public eprod_base{ 
     343        protected: 
     344                Array<epdf* > factors; 
     345                const epdf* factor(int i) const {return factors(i);} 
     346                const int no_factors() const {return factors.length();} 
     347        public: 
     348                void set_parameters ( const Array<epdf *> &epdfs0) { 
     349                        factors = epdfs0; 
     350                } 
     351}; 
    399352 
    400353/*! \brief Mixture of pdfs with constant weights, all pdfs are of equal RV and RVC