Changeset 477 for library/bdm/stat
- Timestamp:
- 08/05/09 14:40:03 (15 years ago)
- Location:
- library/bdm/stat
- Files:
-
- 5 modified
Legend:
- Unmodified
- Added
- Removed
-
library/bdm/stat/emix.cpp
r464 r477 1 1 #include "emix.h" 2 2 3 namespace bdm {3 namespace bdm { 4 4 5 5 void emix::set_parameters ( const vec &w0, const Array<epdf*> &Coms0, bool copy ) { 6 w = w0 /sum ( w0 );7 dim = Coms0 (0)->dimension();8 bool isnamed = Coms0 (0)->isnamed();6 w = w0 / sum ( w0 ); 7 dim = Coms0 ( 0 )->dimension(); 8 bool isnamed = Coms0 ( 0 )->isnamed(); 9 9 int i; 10 10 RV tmp_rv; 11 if ( isnamed) tmp_rv=Coms0(0)->_rv();12 13 for ( i =0;i<w.length();i++ ) {14 it_assert_debug ( dim == ( Coms0 ( i )->dimension() ),"Component sizes do not match!" );15 it_assert_debug ( !isnamed || tmp_rv.equal ( Coms0 ( i )->_rv() ),"Component RVs do not match!" );11 if ( isnamed ) tmp_rv = Coms0 ( 0 )->_rv(); 12 13 for ( i = 0; i < w.length(); i++ ) { 14 it_assert_debug ( dim == ( Coms0 ( i )->dimension() ), "Component sizes do not match!" ); 15 it_assert_debug ( !isnamed || tmp_rv.equal ( Coms0 ( i )->_rv() ), "Component RVs do not match!" ); 16 16 } 17 17 if ( copy ) { 18 Coms.set_length(Coms0.length()); 19 for ( i=0;i<w.length();i++ ) {it_error("Not imp..."); 20 *Coms ( i ) =*Coms0 ( i );} 21 destroyComs=true; 22 } 23 else { 18 Coms.set_length ( Coms0.length() ); 19 for ( i = 0; i < w.length(); i++ ) { 20 it_error ( "Not imp..." ); 21 *Coms ( i ) = *Coms0 ( i ); 22 } 23 destroyComs = true; 24 } else { 24 25 Coms = Coms0; 25 destroyComs =false;26 } 27 if ( isnamed) epdf::set_rv(tmp_rv); //coms aer already OK, no need for set_rv26 destroyComs = false; 27 } 28 if ( isnamed ) epdf::set_rv ( tmp_rv ); //coms aer already OK, no need for set_rv 28 29 } 29 30 … … 32 33 vec cumDist = cumsum ( w ); 33 34 double u0; 34 35 #pragma omp critical 35 36 u0 = UniRNG.sample(); 36 37 37 int i=0; 38 while ( ( cumDist ( i ) <u0 ) && ( i< ( w.length()-1 ) ) ) {i++;} 38 int i = 0; 39 while ( ( cumDist ( i ) < u0 ) && ( i < ( w.length() - 1 ) ) ) { 40 i++; 41 } 39 42 40 43 return Coms ( i )->sample(); 41 44 } 42 45 43 emix* emix::marginal(const RV &rv) const{ 44 it_assert_debug(isnamed(), "rvs are not assigned"); 45 46 Array<epdf*> Cn(Coms.length()); 47 for(int i=0;i<Coms.length();i++){Cn(i)=Coms(i)->marginal(rv);} 46 emix* emix::marginal ( const RV &rv ) const { 47 it_assert_debug ( isnamed(), "rvs are not assigned" ); 48 49 Array<epdf*> Cn ( Coms.length() ); 50 for ( int i = 0; i < Coms.length(); i++ ) { 51 Cn ( i ) = Coms ( i )->marginal ( rv ); 52 } 48 53 emix* tmp = new emix(); 49 tmp->set_parameters (w,Cn,false);54 tmp->set_parameters ( w, Cn, false ); 50 55 tmp->ownComs(); 51 56 return tmp; 52 57 } 53 58 54 mratio* emix::condition (const RV &rv) const{55 it_assert_debug (isnamed(), "rvs are not assigned");56 return new mratio (this,rv);59 mratio* emix::condition ( const RV &rv ) const { 60 it_assert_debug ( isnamed(), "rvs are not assigned" ); 61 return new mratio ( this, rv ); 57 62 }; 58 63 59 64 void egiwmix::set_parameters ( const vec &w0, const Array<egiw*> &Coms0, bool copy ) { 60 w = w0 /sum ( w0 );61 dim = Coms0 (0)->dimension();65 w = w0 / sum ( w0 ); 66 dim = Coms0 ( 0 )->dimension(); 62 67 int i; 63 for ( i =0;i<w.length();i++ ) {64 it_assert_debug ( dim == ( Coms0 ( i )->dimension() ),"Component sizes do not match!" );68 for ( i = 0; i < w.length(); i++ ) { 69 it_assert_debug ( dim == ( Coms0 ( i )->dimension() ), "Component sizes do not match!" ); 65 70 } 66 71 if ( copy ) { 67 Coms.set_length(Coms0.length()); 68 for ( i=0;i<w.length();i++ ) {it_error("Not imp..."); 69 *Coms ( i ) =*Coms0 ( i );} 70 destroyComs=true; 71 } 72 else { 72 Coms.set_length ( Coms0.length() ); 73 for ( i = 0; i < w.length(); i++ ) { 74 it_error ( "Not imp..." ); 75 *Coms ( i ) = *Coms0 ( i ); 76 } 77 destroyComs = true; 78 } else { 73 79 Coms = Coms0; 74 destroyComs =false;80 destroyComs = false; 75 81 } 76 82 } … … 80 86 vec cumDist = cumsum ( w ); 81 87 double u0; 82 88 #pragma omp critical 83 89 u0 = UniRNG.sample(); 84 90 85 int i=0; 86 while ( ( cumDist ( i ) <u0 ) && ( i< ( w.length()-1 ) ) ) {i++;} 91 int i = 0; 92 while ( ( cumDist ( i ) < u0 ) && ( i < ( w.length() - 1 ) ) ) { 93 i++; 94 } 87 95 88 96 return Coms ( i )->sample(); … … 90 98 91 99 vec egiwmix::mean() const { 92 int i; vec mu = zeros ( dim ); 93 for ( i = 0;i < w.length();i++ ) {mu += w ( i ) * Coms ( i )->mean(); } 100 int i; 101 vec mu = zeros ( dim ); 102 for ( i = 0; i < w.length(); i++ ) { 103 mu += w ( i ) * Coms ( i )->mean(); 104 } 94 105 return mu; 95 106 } … … 98 109 // non-central moment 99 110 vec mom2 = zeros ( dim ); 100 for ( int i = 0; i < w.length();i++ ) {111 for ( int i = 0; i < w.length(); i++ ) { 101 112 // pow is overloaded, we have to use another approach 102 mom2 += w ( i ) * ( Coms(i)->variance() + elem_mult ( Coms(i)->mean(), Coms(i)->mean() ));113 mom2 += w ( i ) * ( Coms ( i )->variance() + elem_mult ( Coms ( i )->mean(), Coms ( i )->mean() ) ); 103 114 } 104 115 // central moment 105 116 // pow is overloaded, we have to use another approach 106 return mom2 - elem_mult( mean(), mean() ); 107 } 108 109 emix* egiwmix::marginal(const RV &rv) const{ 110 it_assert_debug(isnamed(), "rvs are not assigned"); 111 112 Array<epdf*> Cn(Coms.length()); 113 for(int i=0;i<Coms.length();i++){Cn(i)=Coms(i)->marginal(rv);} 117 return mom2 - elem_mult ( mean(), mean() ); 118 } 119 120 emix* egiwmix::marginal ( const RV &rv ) const { 121 it_assert_debug ( isnamed(), "rvs are not assigned" ); 122 123 Array<epdf*> Cn ( Coms.length() ); 124 for ( int i = 0; i < Coms.length(); i++ ) { 125 Cn ( i ) = Coms ( i )->marginal ( rv ); 126 } 114 127 emix* tmp = new emix(); 115 tmp->set_parameters (w,Cn,false);128 tmp->set_parameters ( w, Cn, false ); 116 129 tmp->ownComs(); 117 130 return tmp; … … 124 137 125 138 double sumVecCommon; // common part for many terms in eq. 126 int len = w.length(); // no. of mix components 127 int dimLS = Coms (1)->_V()._D().length() - 1; // dim of LS128 vec vecNu (len); // vector of dfms of components129 vec vecD (len); // vector of LS reminders of comps.130 vec vecCommon (len); // vector of common parts139 int len = w.length(); // no. of mix components 140 int dimLS = Coms ( 1 )->_V()._D().length() - 1; // dim of LS 141 vec vecNu ( len ); // vector of dfms of components 142 vec vecD ( len ); // vector of LS reminders of comps. 143 vec vecCommon ( len ); // vector of common parts 131 144 mat matVecsTheta; // matrix which rows are theta vects. 132 145 133 146 // fill in the vectors vecNu, vecD and matVecsTheta 134 for ( int i =0; i<len; i++ ) {135 vecNu.shift_left ( Coms(i)->_nu() );136 vecD.shift_left ( Coms(i)->_V()._D()(0) );137 matVecsTheta.append_row ( Coms(i)->est_theta());147 for ( int i = 0; i < len; i++ ) { 148 vecNu.shift_left ( Coms ( i )->_nu() ); 149 vecD.shift_left ( Coms ( i )->_V()._D() ( 0 ) ); 150 matVecsTheta.append_row ( Coms ( i )->est_theta() ); 138 151 } 139 152 140 153 // calculate the common parts and their sum 141 vecCommon = elem_mult ( w, elem_div (vecNu, vecD) );142 sumVecCommon = sum (vecCommon);154 vecCommon = elem_mult ( w, elem_div ( vecNu, vecD ) ); 155 sumVecCommon = sum ( vecCommon ); 143 156 144 157 // LS estimator of theta 145 vec aprEstTheta(dimLS); aprEstTheta.zeros(); 146 for ( int i=0; i<len; i++ ) { 147 aprEstTheta += matVecsTheta.get_row( i ) * vecCommon ( i ); 158 vec aprEstTheta ( dimLS ); 159 aprEstTheta.zeros(); 160 for ( int i = 0; i < len; i++ ) { 161 aprEstTheta += matVecsTheta.get_row ( i ) * vecCommon ( i ); 148 162 } 149 163 aprEstTheta /= sumVecCommon; 150 151 164 165 152 166 // LS estimator of dfm 153 167 double aprNu; 154 double A = log ( sumVecCommon ); // Term 'A' in equation155 156 for ( int i =0; i<len; i++ ) {157 A += w (i) * ( log( vecD(i) ) - psi( 0.5 * vecNu(i) ) );158 } 159 160 aprNu = ( 1 + sqrt (1 + 2 * (A - LOG2)/3 ) ) / ( 2 * (A - LOG2) );168 double A = log ( sumVecCommon ); // Term 'A' in equation 169 170 for ( int i = 0; i < len; i++ ) { 171 A += w ( i ) * ( log ( vecD ( i ) ) - psi ( 0.5 * vecNu ( i ) ) ); 172 } 173 174 aprNu = ( 1 + sqrt ( 1 + 2 * ( A - LOG2 ) / 3 ) ) / ( 2 * ( A - LOG2 ) ); 161 175 162 176 … … 167 181 // the following code is very numerically sensitive, thus 168 182 // we have to eliminate decompositions etc. as much as possible 169 mat aprC = zeros (dimLS, dimLS);170 for ( int i =0; i<len; i++ ) {171 aprC += Coms (i)->est_theta_cov().to_mat() * w(i);172 vec tmp = ( matVecsTheta.get_row (i) - aprEstTheta );173 aprC += vecCommon (i) * outer_product( tmp, tmp);183 mat aprC = zeros ( dimLS, dimLS ); 184 for ( int i = 0; i < len; i++ ) { 185 aprC += Coms ( i )->est_theta_cov().to_mat() * w ( i ); 186 vec tmp = ( matVecsTheta.get_row ( i ) - aprEstTheta ); 187 aprC += vecCommon ( i ) * outer_product ( tmp, tmp ); 174 188 } 175 189 176 190 // Construct GiW pdf :: BEGIN 177 ldmat aprCinv ( inv (aprC) );178 vec D = concat ( aprD, aprCinv._D() );179 mat L = eye (dimLS+1);180 L.set_submatrix (1,0, aprCinv._L() * aprEstTheta);181 L.set_submatrix (1,1, aprCinv._L());182 ldmat aprLD ( L, D);183 184 egiw* aprgiw = new egiw (1, aprLD, aprNu);191 ldmat aprCinv ( inv ( aprC ) ); 192 vec D = concat ( aprD, aprCinv._D() ); 193 mat L = eye ( dimLS + 1 ); 194 L.set_submatrix ( 1, 0, aprCinv._L() * aprEstTheta ); 195 L.set_submatrix ( 1, 1, aprCinv._L() ); 196 ldmat aprLD ( L, D ); 197 198 egiw* aprgiw = new egiw ( 1, aprLD, aprNu ); 185 199 return aprgiw; 186 200 }; -
library/bdm/stat/emix.h
r471 r477 14 14 #define EMIX_H 15 15 16 #define LOG2 0.69314718055995 16 #define LOG2 0.69314718055995 17 17 18 18 #include "../shared_ptr.h" … … 48 48 //!Default constructor. By default, the given epdf is not copied! 49 49 //! It is assumed that this function will be used only temporarily. 50 mratio ( const epdf* nom0, const RV &rv, bool copy =false ) :mpdf ( ), dl ( ) {50 mratio ( const epdf* nom0, const RV &rv, bool copy = false ) : mpdf ( ), dl ( ) { 51 51 // adjust rv and rvc 52 52 rvc = nom0->_rv().subt ( rv ); 53 53 dimc = rvc._dsize(); 54 set_ep (shared_ptr<epdf>(new epdf));55 e()->set_parameters (rv._dsize());56 e()->set_rv (rv);57 54 set_ep ( shared_ptr<epdf> ( new epdf ) ); 55 e()->set_parameters ( rv._dsize() ); 56 e()->set_rv ( rv ); 57 58 58 //prepare data structures 59 if ( copy ) {it_error ( "todo" ); destroynom=true; } 60 else { nom = nom0; destroynom = false; } 61 it_assert_debug ( rvc.length() >0,"Makes no sense to use this object!" ); 62 59 if ( copy ) { 60 it_error ( "todo" ); 61 destroynom = true; 62 } else { 63 nom = nom0; 64 destroynom = false; 65 } 66 it_assert_debug ( rvc.length() > 0, "Makes no sense to use this object!" ); 67 63 68 // build denominator 64 69 den = nom->marginal ( rvc ); 65 dl.set_connection (rv,rvc,nom0->_rv());70 dl.set_connection ( rv, rvc, nom0->_rv() ); 66 71 }; 67 72 double evallogcond ( const vec &val, const vec &cond ) { 68 73 double tmp; 69 74 vec nom_val ( e()->dimension() + dimc ); 70 dl.pushup_cond ( nom_val, val,cond );75 dl.pushup_cond ( nom_val, val, cond ); 71 76 tmp = exp ( nom->evallog ( nom_val ) - den->evallog ( cond ) ); 72 it_assert_debug ( std::isfinite ( tmp ), "Infinite value" );77 it_assert_debug ( std::isfinite ( tmp ), "Infinite value" ); 73 78 return tmp; 74 79 } 75 80 //! Object takes ownership of nom and will destroy it 76 void ownnom() {destroynom=true;} 81 void ownnom() { 82 destroynom = true; 83 } 77 84 //! Default destructor 78 ~mratio() {delete den; if ( destroynom ) {delete nom;}} 85 ~mratio() { 86 delete den; 87 if ( destroynom ) { 88 delete nom; 89 } 90 } 79 91 }; 80 92 … … 102 114 //! Set weights \c w and components \c Coms 103 115 //!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. 104 void set_parameters ( const vec &w, const Array<epdf*> &Coms, bool copy =false );116 void set_parameters ( const vec &w, const Array<epdf*> &Coms, bool copy = false ); 105 117 106 118 vec sample() const; 107 119 vec mean() const { 108 int i; vec mu = zeros ( dim ); 109 for ( i = 0;i < w.length();i++ ) {mu += w ( i ) * Coms ( i )->mean(); } 120 int i; 121 vec mu = zeros ( dim ); 122 for ( i = 0; i < w.length(); i++ ) { 123 mu += w ( i ) * Coms ( i )->mean(); 124 } 110 125 return mu; 111 126 } … … 113 128 //non-central moment 114 129 vec mom2 = zeros ( dim ); 115 for ( int i = 0;i < w.length();i++ ) {mom2 += w ( i ) * (Coms(i)->variance() + pow ( Coms ( i )->mean(),2 )); } 130 for ( int i = 0; i < w.length(); i++ ) { 131 mom2 += w ( i ) * ( Coms ( i )->variance() + pow ( Coms ( i )->mean(), 2 ) ); 132 } 116 133 //central moment 117 return mom2 -pow ( mean(),2 );134 return mom2 - pow ( mean(), 2 ); 118 135 } 119 136 double evallog ( const vec &val ) const { 120 137 int i; 121 138 double sum = 0.0; 122 for ( i = 0;i < w.length();i++ ) {sum += w ( i ) * exp ( Coms ( i )->evallog ( val ) );} 123 if ( sum==0.0 ) {sum=std::numeric_limits<double>::epsilon();} 124 double tmp=log ( sum ); 125 it_assert_debug ( std::isfinite ( tmp ),"Infinite" ); 139 for ( i = 0; i < w.length(); i++ ) { 140 sum += w ( i ) * exp ( Coms ( i )->evallog ( val ) ); 141 } 142 if ( sum == 0.0 ) { 143 sum = std::numeric_limits<double>::epsilon(); 144 } 145 double tmp = log ( sum ); 146 it_assert_debug ( std::isfinite ( tmp ), "Infinite" ); 126 147 return tmp; 127 148 }; 128 149 vec evallog_m ( const mat &Val ) const { 129 vec x =zeros ( Val.cols() );150 vec x = zeros ( Val.cols() ); 130 151 for ( int i = 0; i < w.length(); i++ ) { 131 x += w ( i ) *exp ( Coms ( i )->evallog_m ( Val ) );152 x += w ( i ) * exp ( Coms ( i )->evallog_m ( Val ) ); 132 153 } 133 154 return log ( x ); … … 147 168 //Access methods 148 169 //! returns a pointer to the internal mean value. Use with Care! 149 vec& _w() {return w;} 150 virtual ~emix() {if ( destroyComs ) {for ( int i=0;i<Coms.length();i++ ) {delete Coms ( i );}}} 170 vec& _w() { 171 return w; 172 } 173 virtual ~emix() { 174 if ( destroyComs ) { 175 for ( int i = 0; i < Coms.length(); i++ ) { 176 delete Coms ( i ); 177 } 178 } 179 } 151 180 //! Auxiliary function for taking ownership of the Coms() 152 void ownComs() {destroyComs=true;} 181 void ownComs() { 182 destroyComs = true; 183 } 153 184 154 185 //!access function 155 epdf* _Coms ( int i ) {return Coms ( i );} 156 void set_rv(const RV &rv){ 157 epdf::set_rv(rv); 158 for(int i=0;i<Coms.length();i++){Coms(i)->set_rv(rv);} 186 epdf* _Coms ( int i ) { 187 return Coms ( i ); 188 } 189 void set_rv ( const RV &rv ) { 190 epdf::set_rv ( rv ); 191 for ( int i = 0; i < Coms.length(); i++ ) { 192 Coms ( i )->set_rv ( rv ); 193 } 159 194 } 160 195 }; … … 179 214 //! Set weights \c w and components \c Coms 180 215 //!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. 181 void set_parameters ( const vec &w, const Array<egiw*> &Coms, bool copy =false );216 void set_parameters ( const vec &w, const Array<egiw*> &Coms, bool copy = false ); 182 217 183 218 //!return expected value … … 188 223 189 224 //!return the expected variance 190 225 vec variance() const; 191 226 192 227 // TODO!!! Defined to follow ANSI and/or for future development 193 228 void mean_mat ( mat &M, mat&R ) const {}; 194 double evallog_nn ( const vec &val ) const {return 0;}; 195 double lognc () const {return 0;}; 229 double evallog_nn ( const vec &val ) const { 230 return 0; 231 }; 232 double lognc () const { 233 return 0; 234 }; 196 235 emix* marginal ( const RV &rv ) const; 197 236 198 237 //Access methods 199 238 //! returns a pointer to the internal mean value. Use with Care! 200 vec& _w() {return w;} 201 virtual ~egiwmix() {if ( destroyComs ) {for ( int i=0;i<Coms.length();i++ ) {delete Coms ( i );}}} 239 vec& _w() { 240 return w; 241 } 242 virtual ~egiwmix() { 243 if ( destroyComs ) { 244 for ( int i = 0; i < Coms.length(); i++ ) { 245 delete Coms ( i ); 246 } 247 } 248 } 202 249 //! Auxiliary function for taking ownership of the Coms() 203 void ownComs() {destroyComs=true;} 250 void ownComs() { 251 destroyComs = true; 252 } 204 253 205 254 //!access function 206 egiw* _Coms ( int i ) {return Coms ( i );} 207 208 void set_rv(const RV &rv){ 209 egiw::set_rv(rv); 210 for(int i=0;i<Coms.length();i++){Coms(i)->set_rv(rv);} 255 egiw* _Coms ( int i ) { 256 return Coms ( i ); 257 } 258 259 void set_rv ( const RV &rv ) { 260 egiw::set_rv ( rv ); 261 for ( int i = 0; i < Coms.length(); i++ ) { 262 Coms ( i )->set_rv ( rv ); 263 } 211 264 } 212 265 … … 236 289 /*!\brief Constructor from list of mFacs, 237 290 */ 238 mprod() :dummy(new epdf()) { }239 mprod ( Array<mpdf*> mFacs):240 dummy(new epdf()) {241 set_elements(mFacs);242 } 243 244 void set_elements (Array<mpdf*> mFacs , bool own=false) {245 246 compositepdf::set_elements (mFacs,own);247 dls.set_size (mFacs.length());248 epdfs.set_size (mFacs.length());249 250 set_ep (dummy);251 RV rv =getrv ( true );291 mprod() : dummy ( new epdf() ) { } 292 mprod ( Array<mpdf*> mFacs ) : 293 dummy ( new epdf() ) { 294 set_elements ( mFacs ); 295 } 296 297 void set_elements ( Array<mpdf*> mFacs , bool own = false ) { 298 299 compositepdf::set_elements ( mFacs, own ); 300 dls.set_size ( mFacs.length() ); 301 epdfs.set_size ( mFacs.length() ); 302 303 set_ep ( dummy ); 304 RV rv = getrv ( true ); 252 305 set_rv ( rv ); 253 dummy->set_parameters (rv._dsize());254 setrvc (e()->_rv(), rvc);306 dummy->set_parameters ( rv._dsize() ); 307 setrvc ( e()->_rv(), rvc ); 255 308 // rv and rvc established = > we can link them with mpdfs 256 for ( int i = 0; i < mpdfs.length(); i++ ) {309 for ( int i = 0; i < mpdfs.length(); i++ ) { 257 310 dls ( i ) = new datalink_m2m; 258 dls (i)->set_connection( mpdfs ( i )->_rv(), mpdfs ( i )->_rvc(), _rv(), _rvc() );259 } 260 261 for ( int i =0; i<mpdfs.length(); i++ ) {262 epdfs (i) = mpdfs(i)->e();311 dls ( i )->set_connection ( mpdfs ( i )->_rv(), mpdfs ( i )->_rvc(), _rv(), _rvc() ); 312 } 313 314 for ( int i = 0; i < mpdfs.length(); i++ ) { 315 epdfs ( i ) = mpdfs ( i )->e(); 263 316 } 264 317 }; … … 267 320 int i; 268 321 double res = 0.0; 269 for ( i = mpdfs.length() - 1; i >= 0;i-- ) {322 for ( i = mpdfs.length() - 1; i >= 0; i-- ) { 270 323 /* if ( mpdfs(i)->_rvc().count() >0) { 271 324 mpdfs ( i )->condition ( dls ( i )->get_cond ( val,cond ) ); … … 280 333 return res; 281 334 } 282 vec evallogcond_m (const mat &Dt, const vec &cond) {283 vec tmp (Dt.cols());284 for (int i=0;i<Dt.cols(); i++){285 tmp (i) = evallogcond(Dt.get_col(i),cond);286 } 287 return tmp; 288 }; 289 vec evallogcond_m (const Array<vec> &Dt, const vec &cond) {290 vec tmp (Dt.length());291 for (int i=0;i<Dt.length(); i++){292 tmp (i) = evallogcond(Dt(i),cond);293 } 294 return tmp; 335 vec evallogcond_m ( const mat &Dt, const vec &cond ) { 336 vec tmp ( Dt.cols() ); 337 for ( int i = 0; i < Dt.cols(); i++ ) { 338 tmp ( i ) = evallogcond ( Dt.get_col ( i ), cond ); 339 } 340 return tmp; 341 }; 342 vec evallogcond_m ( const Array<vec> &Dt, const vec &cond ) { 343 vec tmp ( Dt.length() ); 344 for ( int i = 0; i < Dt.length(); i++ ) { 345 tmp ( i ) = evallogcond ( Dt ( i ), cond ); 346 } 347 return tmp; 295 348 }; 296 349 … … 298 351 //TODO smarter... 299 352 vec samplecond ( const vec &cond ) { 300 301 vec smp= std::numeric_limits<double>::infinity() * ones ( e()->dimension() );353 //! Ugly hack to help to discover if mpfs are not in proper order. Correct solution = check that explicitely. 354 vec smp = std::numeric_limits<double>::infinity() * ones ( e()->dimension() ); 302 355 vec smpi; 303 356 // Hard assumption here!!! We are going backwards, to assure that samples that are needed from smp are already generated! 304 for ( int i = ( mpdfs.length() - 1 ); i >= 0;i-- ) {357 for ( int i = ( mpdfs.length() - 1 ); i >= 0; i-- ) { 305 358 if ( mpdfs ( i )->dimensionc() ) { 306 mpdfs ( i )->condition ( dls ( i )->get_cond ( smp , cond ) ); // smp is val here!!359 mpdfs ( i )->condition ( dls ( i )->get_cond ( smp , cond ) ); // smp is val here!! 307 360 } 308 361 smpi = epdfs ( i )->sample(); … … 314 367 } 315 368 mat samplecond ( const vec &cond, int N ) { 316 mat Smp ( dimension(),N ); 317 for ( int i=0;i<N;i++ ) {Smp.set_col ( i,samplecond ( cond ) );} 369 mat Smp ( dimension(), N ); 370 for ( int i = 0; i < N; i++ ) { 371 Smp.set_col ( i, samplecond ( cond ) ); 372 } 318 373 return Smp; 319 374 } … … 327 382 //! \endcode 328 383 //!@} 329 void from_setting (const Setting &set){384 void from_setting ( const Setting &set ) { 330 385 Array<mpdf*> Atmp; //temporary Array 331 UI::get (Atmp,set, "mpdfs", UI::compulsory);332 set_elements (Atmp,true);333 } 334 386 UI::get ( Atmp, set, "mpdfs", UI::compulsory ); 387 set_elements ( Atmp, true ); 388 } 389 335 390 }; 336 UIREGISTER (mprod);391 UIREGISTER ( mprod ); 337 392 338 393 //! Product of independent epdfs. For dependent pdfs, use mprod. … … 344 399 Array<datalink*> dls; 345 400 public: 346 eprod () : epdfs ( 0 ), dls ( 0 ) {};347 void set_parameters ( const Array<const epdf*> &epdfs0, bool named =true ) {348 epdfs =epdfs0;//.set_length ( epdfs0.length() );401 eprod () : epdfs ( 0 ), dls ( 0 ) {}; 402 void set_parameters ( const Array<const epdf*> &epdfs0, bool named = true ) { 403 epdfs = epdfs0;//.set_length ( epdfs0.length() ); 349 404 dls.set_length ( epdfs.length() ); 350 405 351 bool independent =true;406 bool independent = true; 352 407 if ( named ) { 353 for ( int i =0;i<epdfs.length();i++ ) {354 independent =rv.add ( epdfs ( i )->_rv() );355 it_assert_debug ( independent ==true, "eprod:: given components are not independent." );408 for ( int i = 0; i < epdfs.length(); i++ ) { 409 independent = rv.add ( epdfs ( i )->_rv() ); 410 it_assert_debug ( independent == true, "eprod:: given components are not independent." ); 356 411 } 357 dim =rv._dsize();358 } 359 else {360 dim =0; for ( int i=0;i<epdfs.length();i++ ) {361 dim +=epdfs ( i )->dimension();412 dim = rv._dsize(); 413 } else { 414 dim = 0; 415 for ( int i = 0; i < epdfs.length(); i++ ) { 416 dim += epdfs ( i )->dimension(); 362 417 } 363 418 } 364 419 // 365 int cumdim =0;366 int dimi =0;420 int cumdim = 0; 421 int dimi = 0; 367 422 int i; 368 for ( i =0;i<epdfs.length();i++ ) {423 for ( i = 0; i < epdfs.length(); i++ ) { 369 424 dls ( i ) = new datalink; 370 if ( named ) {dls ( i )->set_connection ( epdfs ( i )->_rv() , rv );} 371 else { 425 if ( named ) { 426 dls ( i )->set_connection ( epdfs ( i )->_rv() , rv ); 427 } else { 372 428 dimi = epdfs ( i )->dimension(); 373 dls ( i )->set_connection ( dimi, dim, linspace ( cumdim, cumdim+dimi-1 ) );374 cumdim +=dimi;429 dls ( i )->set_connection ( dimi, dim, linspace ( cumdim, cumdim + dimi - 1 ) ); 430 cumdim += dimi; 375 431 } 376 432 } … … 379 435 vec mean() const { 380 436 vec tmp ( dim ); 381 for ( int i =0;i<epdfs.length();i++ ) {437 for ( int i = 0; i < epdfs.length(); i++ ) { 382 438 vec pom = epdfs ( i )->mean(); 383 439 dls ( i )->pushup ( tmp, pom ); … … 387 443 vec variance() const { 388 444 vec tmp ( dim ); //second moment 389 for ( int i =0;i<epdfs.length();i++ ) {445 for ( int i = 0; i < epdfs.length(); i++ ) { 390 446 vec pom = epdfs ( i )->mean(); 391 dls ( i )->pushup ( tmp, pow ( pom, 2 ) );392 } 393 return tmp -pow ( mean(),2 );447 dls ( i )->pushup ( tmp, pow ( pom, 2 ) ); 448 } 449 return tmp - pow ( mean(), 2 ); 394 450 } 395 451 vec sample() const { 396 452 vec tmp ( dim ); 397 for ( int i =0;i<epdfs.length();i++ ) {453 for ( int i = 0; i < epdfs.length(); i++ ) { 398 454 vec pom = epdfs ( i )->sample(); 399 455 dls ( i )->pushup ( tmp, pom ); … … 402 458 } 403 459 double evallog ( const vec &val ) const { 404 double tmp =0;405 for ( int i =0;i<epdfs.length();i++ ) {406 tmp +=epdfs ( i )->evallog ( dls ( i )->pushdown ( val ) );407 } 408 it_assert_debug ( std::isfinite ( tmp ), "Infinite" );460 double tmp = 0; 461 for ( int i = 0; i < epdfs.length(); i++ ) { 462 tmp += epdfs ( i )->evallog ( dls ( i )->pushdown ( val ) ); 463 } 464 it_assert_debug ( std::isfinite ( tmp ), "Infinite" ); 409 465 return tmp; 410 466 } 411 467 //!access function 412 const epdf* operator () ( int i ) const {it_assert_debug ( i<epdfs.length(),"wrong index" );return epdfs ( i );} 468 const epdf* operator () ( int i ) const { 469 it_assert_debug ( i < epdfs.length(), "wrong index" ); 470 return epdfs ( i ); 471 } 413 472 414 473 //!Destructor 415 ~eprod() {for ( int i=0;i<epdfs.length();i++ ) {delete dls ( i );}} 474 ~eprod() { 475 for ( int i = 0; i < epdfs.length(); i++ ) { 476 delete dls ( i ); 477 } 478 } 416 479 }; 417 480 … … 430 493 public: 431 494 //!Default constructor 432 mmix() :iepdf(new emix()) {433 set_ep(iepdf);495 mmix() : iepdf ( new emix() ) { 496 set_ep ( iepdf ); 434 497 } 435 498 … … 438 501 Array<epdf*> Eps ( Coms.length() ); 439 502 440 for ( int i = 0; i < Coms.length();i++ ) {441 Eps (i) = Coms(i)->e();442 } 443 444 iepdf->set_parameters (w, Eps);503 for ( int i = 0; i < Coms.length(); i++ ) { 504 Eps ( i ) = Coms ( i )->e(); 505 } 506 507 iepdf->set_parameters ( w, Eps ); 445 508 } 446 509 447 510 void condition ( const vec &cond ) { 448 for ( int i = 0;i < Coms.length();i++ ) {Coms ( i )->condition ( cond );} 511 for ( int i = 0; i < Coms.length(); i++ ) { 512 Coms ( i )->condition ( cond ); 513 } 449 514 }; 450 515 }; -
library/bdm/stat/exp_family.cpp
r471 r477 4 4 #include "exp_family.h" 5 5 6 namespace bdm {6 namespace bdm { 7 7 8 8 Uniform_RNG UniRNG; … … 12 12 using std::cout; 13 13 14 void BMEF::bayes ( const vec &dt ) {this->bayes ( dt,1.0 );}; 14 void BMEF::bayes ( const vec &dt ) { 15 this->bayes ( dt, 1.0 ); 16 }; 15 17 16 18 vec egiw::sample() const { … … 20 22 21 23 double egiw::evallog_nn ( const vec &val ) const { 22 int vend = val.length() -1;23 24 if ( dimx ==1 ) { //same as the following, just quicker.24 int vend = val.length() - 1; 25 26 if ( dimx == 1 ) { //same as the following, just quicker. 25 27 double r = val ( vend ); //last entry! 26 if ( r<0) return -inf;27 vec Psi ( nPsi +dimx );28 if ( r < 0 ) return -inf; 29 vec Psi ( nPsi + dimx ); 28 30 Psi ( 0 ) = -1.0; 29 Psi.set_subvector ( 1,val ( 0,vend-1 ) ); // fill the rest 30 31 double Vq=V.qform ( Psi ); 32 return -0.5* ( nu*log ( r ) + Vq /r ); 33 } 34 else { 35 mat Th= reshape ( val ( 0,nPsi*dimx-1 ),nPsi,dimx ); 36 fsqmat R ( reshape ( val ( nPsi*dimx,vend ),dimx,dimx ) ); 37 double ldetR=R.logdet(); 38 if (ldetR) return -inf; 39 mat Tmp=concat_vertical ( -eye ( dimx ),Th ); 31 Psi.set_subvector ( 1, val ( 0, vend - 1 ) ); // fill the rest 32 33 double Vq = V.qform ( Psi ); 34 return -0.5* ( nu*log ( r ) + Vq / r ); 35 } else { 36 mat Th = reshape ( val ( 0, nPsi * dimx - 1 ), nPsi, dimx ); 37 fsqmat R ( reshape ( val ( nPsi*dimx, vend ), dimx, dimx ) ); 38 double ldetR = R.logdet(); 39 if ( ldetR ) return -inf; 40 mat Tmp = concat_vertical ( -eye ( dimx ), Th ); 40 41 fsqmat iR ( dimx ); 41 42 R.inv ( iR ); … … 48 49 const vec& D = V._D(); 49 50 50 double m = nu - nPsi - dimx-1;51 double m = nu - nPsi - dimx - 1; 51 52 #define log2 0.693147180559945286226763983 52 53 #define logpi 1.144729885849400163877476189 … … 54 55 #define Inf std::numeric_limits<double>::infinity() 55 56 56 double nkG = 0.5 * dimx* ( -nPsi *log2pi + sum ( log ( D ( dimx,D.length()-1 ) ) ) );57 double nkG = 0.5 * dimx * ( -nPsi * log2pi + sum ( log ( D ( dimx, D.length() - 1 ) ) ) ); 57 58 // temporary for lgamma in Wishart 58 double lg=0; 59 for ( int i =0; i<dimx;i++ ) {lg+=lgamma ( 0.5* ( m-i ) );} 60 61 double nkW = 0.5* ( m*sum ( log ( D ( 0,dimx-1 ) ) ) ) \ 62 - 0.5*dimx* ( m*log2 + 0.5* ( dimx-1 ) *log2pi ) - lg; 63 64 it_assert_debug ( ( ( -nkG-nkW ) >-Inf ) && ( ( -nkG-nkW ) <Inf ), "ARX improper" ); 65 return -nkG-nkW; 59 double lg = 0; 60 for ( int i = 0; i < dimx; i++ ) { 61 lg += lgamma ( 0.5 * ( m - i ) ); 62 } 63 64 double nkW = 0.5 * ( m * sum ( log ( D ( 0, dimx - 1 ) ) ) ) \ 65 - 0.5 * dimx * ( m * log2 + 0.5 * ( dimx - 1 ) * log2pi ) - lg; 66 67 it_assert_debug ( ( ( -nkG - nkW ) > -Inf ) && ( ( -nkG - nkW ) < Inf ), "ARX improper" ); 68 return -nkG - nkW; 66 69 } 67 70 68 71 vec egiw::est_theta() const { 69 if ( dimx ==1 ) {72 if ( dimx == 1 ) { 70 73 const mat &L = V._L(); 71 74 int end = L.rows() - 1; 72 75 73 mat iLsub = ltuinv ( L ( dimx,end,dimx,end ) ); 74 75 vec L0 = L.get_col(0); 76 77 return iLsub * L0(1,end); 78 } 79 else { 80 it_error("ERROR: est_theta() not implemented for dimx>1"); 76 mat iLsub = ltuinv ( L ( dimx, end, dimx, end ) ); 77 78 vec L0 = L.get_col ( 0 ); 79 80 return iLsub * L0 ( 1, end ); 81 } else { 82 it_error ( "ERROR: est_theta() not implemented for dimx>1" ); 81 83 return 0; 82 84 } … … 89 91 int end = D.length() - 1; 90 92 91 mat Lsub = L ( 1, end, 1, end); 92 mat Dsub = diag(D(1, end)); 93 94 return inv( transpose(Lsub) * Dsub * Lsub ); 95 96 } 97 else { 98 it_error("ERROR: est_theta_cov() not implemented for dimx>1"); 93 mat Lsub = L ( 1, end, 1, end ); 94 mat Dsub = diag ( D ( 1, end ) ); 95 96 return inv ( transpose ( Lsub ) * Dsub * Lsub ); 97 98 } else { 99 it_error ( "ERROR: est_theta_cov() not implemented for dimx>1" ); 99 100 return 0; 100 101 } … … 104 105 vec egiw::mean() const { 105 106 106 if ( dimx ==1 ) {107 const vec &D = V._D();108 int end = D.length() -1;107 if ( dimx == 1 ) { 108 const vec &D = V._D(); 109 int end = D.length() - 1; 109 110 110 111 vec m ( dim ); 111 112 m.set_subvector ( 0, est_theta() ); 112 m ( end ) = D ( 0 ) / ( nu - nPsi -2*dimx -2 );113 m ( end ) = D ( 0 ) / ( nu - nPsi - 2 * dimx - 2 ); 113 114 return m; 114 } 115 else { 115 } else { 116 116 mat M; 117 117 mat R; 118 mean_mat ( M, R );119 return cvectorize ( concat_vertical ( M, R ) );118 mean_mat ( M, R ); 119 return cvectorize ( concat_vertical ( M, R ) ); 120 120 } 121 121 … … 124 124 vec egiw::variance() const { 125 125 126 if ( dimx ==1 ) {127 int l =V.rows();128 const ldmat tmp (V,linspace(1,l-1));129 ldmat itmp (l);130 tmp.inv (itmp);131 double cove = V._D() ( 0 ) / ( nu - nPsi -2*dimx -2 );132 133 vec var (l);134 var.set_subvector (0,diag(itmp.to_mat())*cove);135 var (l-1)=cove*cove/( nu -nPsi -2*dimx -2 );126 if ( dimx == 1 ) { 127 int l = V.rows(); 128 const ldmat tmp ( V, linspace ( 1, l - 1 ) ); 129 ldmat itmp ( l ); 130 tmp.inv ( itmp ); 131 double cove = V._D() ( 0 ) / ( nu - nPsi - 2 * dimx - 2 ); 132 133 vec var ( l ); 134 var.set_subvector ( 0, diag ( itmp.to_mat() ) *cove ); 135 var ( l - 1 ) = cove * cove / ( nu - nPsi - 2 * dimx - 2 ); 136 136 return var; 137 } 138 else {it_error("not implemented"); return vec(0);} 137 } else { 138 it_error ( "not implemented" ); 139 return vec ( 0 ); 140 } 139 141 } 140 142 141 143 void egiw::mean_mat ( mat &M, mat&R ) const { 142 const mat &L = V._L();143 const vec &D = V._D();144 int end = L.rows() -1;145 146 ldmat ldR ( L ( 0, dimx-1,0,dimx-1 ), D ( 0,dimx-1 ) / ( nu -nPsi -2*dimx -2 ) ); //exp val of R147 mat iLsub =ltuinv ( L ( dimx,end,dimx,end ) );144 const mat &L = V._L(); 145 const vec &D = V._D(); 146 int end = L.rows() - 1; 147 148 ldmat ldR ( L ( 0, dimx - 1, 0, dimx - 1 ), D ( 0, dimx - 1 ) / ( nu - nPsi - 2*dimx - 2 ) ); //exp val of R 149 mat iLsub = ltuinv ( L ( dimx, end, dimx, end ) ); 148 150 149 151 // set mean value 150 mat Lpsi = L ( dimx, end,0,dimx-1 );151 M = iLsub*Lpsi;152 R = ldR.to_mat() ;152 mat Lpsi = L ( dimx, end, 0, dimx - 1 ); 153 M = iLsub * Lpsi; 154 R = ldR.to_mat() ; 153 155 } 154 156 155 157 vec egamma::sample() const { 156 vec smp ( dim );158 vec smp ( dim ); 157 159 int i; 158 160 159 for ( i=0; i<dim; i++ ) { 160 if ( beta ( i ) >std::numeric_limits<double>::epsilon() ) { 161 GamRNG.setup ( alpha ( i ),beta ( i ) ); 162 } 163 else { 164 GamRNG.setup ( alpha ( i ),std::numeric_limits<double>::epsilon() ); 161 for ( i = 0; i < dim; i++ ) { 162 if ( beta ( i ) > std::numeric_limits<double>::epsilon() ) { 163 GamRNG.setup ( alpha ( i ), beta ( i ) ); 164 } else { 165 GamRNG.setup ( alpha ( i ), std::numeric_limits<double>::epsilon() ); 165 166 } 166 167 #pragma omp critical … … 190 191 int i; 191 192 192 if ( any(val<=0.)) return -inf;193 if ( any(beta<=0.)) return -inf;194 for ( i =0; i<dim; i++ ) {195 res += ( alpha ( i ) - 1 ) * std::log ( val ( i ) ) - beta ( i ) *val ( i );196 } 197 double tmp =res-lognc();;198 it_assert_debug ( std::isfinite ( tmp ), "Infinite value" );193 if ( any ( val <= 0. ) ) return -inf; 194 if ( any ( beta <= 0. ) ) return -inf; 195 for ( i = 0; i < dim; i++ ) { 196 res += ( alpha ( i ) - 1 ) * std::log ( val ( i ) ) - beta ( i ) * val ( i ); 197 } 198 double tmp = res - lognc();; 199 it_assert_debug ( std::isfinite ( tmp ), "Infinite value" ); 199 200 return tmp; 200 201 } … … 204 205 int i; 205 206 206 for ( i =0; i<dim; i++ ) {207 res += lgamma ( alpha ( i ) ) - alpha ( i ) * std::log ( beta ( i ) ) ;207 for ( i = 0; i < dim; i++ ) { 208 res += lgamma ( alpha ( i ) ) - alpha ( i ) * std::log ( beta ( i ) ) ; 208 209 } 209 210 … … 211 212 } 212 213 213 void mgamma::set_parameters (double k0, const vec &beta0) {214 void mgamma::set_parameters ( double k0, const vec &beta0 ) { 214 215 k = k0; 215 iepdf->set_parameters (k * ones(beta0.length()), beta0);216 iepdf->set_parameters ( k * ones ( beta0.length() ), beta0 ); 216 217 dimc = e()->dimension(); 217 218 } 218 219 219 ivec eEmp::resample ( RESAMPLING_METHOD method) {220 ivec ind =zeros_i ( n );220 ivec eEmp::resample ( RESAMPLING_METHOD method ) { 221 ivec ind = zeros_i ( n ); 221 222 ivec N_babies = zeros_i ( n ); 222 223 vec cumDist = cumsum ( w ); 223 224 vec u ( n ); 224 int i, j,parent;225 int i, j, parent; 225 226 double u0; 226 227 227 228 switch ( method ) { 228 229 230 231 for ( i = n - 2;i >= 0;i-- ) {232 233 234 235 236 237 238 239 for ( i = 0;i < n;i++ ) {240 241 242 243 244 245 246 247 248 for ( i = 0;i < n;i++ ) {249 250 251 252 253 254 255 229 case MULTINOMIAL: 230 u ( n - 1 ) = pow ( UniRNG.sample(), 1.0 / n ); 231 232 for ( i = n - 2; i >= 0; i-- ) { 233 u ( i ) = u ( i + 1 ) * pow ( UniRNG.sample(), 1.0 / ( i + 1 ) ); 234 } 235 236 break; 237 238 case STRATIFIED: 239 240 for ( i = 0; i < n; i++ ) { 241 u ( i ) = ( i + UniRNG.sample() ) / n; 242 } 243 244 break; 245 246 case SYSTEMATIC: 247 u0 = UniRNG.sample(); 248 249 for ( i = 0; i < n; i++ ) { 250 u ( i ) = ( i + u0 ) / n; 251 } 252 253 break; 254 255 default: 256 it_error ( "PF::resample(): Unknown resampling method" ); 256 257 } 257 258 … … 259 260 j = 0; 260 261 261 for ( i = 0; i < n;i++ ) {262 for ( i = 0; i < n; i++ ) { 262 263 while ( u ( i ) > cumDist ( j ) ) j++; 263 264 … … 270 271 271 272 // find the first parent; 272 parent=0; while ( N_babies ( parent ) ==0 ) parent++; 273 parent = 0; 274 while ( N_babies ( parent ) == 0 ) parent++; 273 275 274 276 // Build index 275 for ( i = 0; i < n;i++ ) {277 for ( i = 0; i < n; i++ ) { 276 278 if ( N_babies ( i ) > 0 ) { 277 279 ind ( i ) = i; 278 280 N_babies ( i ) --; //this index was now replicated; 279 } 280 else { 281 } else { 281 282 // test if the parent has been fully replicated 282 283 // if yes, find the next one 283 while ( ( N_babies ( parent ) == 0 ) || ( N_babies ( parent ) ==1 && parent>i ) ) parent++;284 while ( ( N_babies ( parent ) == 0 ) || ( N_babies ( parent ) == 1 && parent > i ) ) parent++; 284 285 285 286 // Replicate parent … … 292 293 293 294 // copy the internals according to ind 294 for ( i =0;i<n;i++ ) {295 if ( ind ( i ) != i ) {296 samples ( i ) = samples ( ind ( i ) );297 } 298 w ( i ) = 1.0 /n;295 for ( i = 0; i < n; i++ ) { 296 if ( ind ( i ) != i ) { 297 samples ( i ) = samples ( ind ( i ) ); 298 } 299 w ( i ) = 1.0 / n; 299 300 } 300 301 … … 305 306 //it_assert_debug(rv==epdf0->rv(),"Wrong epdf0"); 306 307 dim = epdf0->dimension(); 307 w =w0;308 w /=sum ( w0 );//renormalize309 n =w.length();308 w = w0; 309 w /= sum ( w0 );//renormalize 310 n = w.length(); 310 311 samples.set_size ( n ); 311 312 dim = epdf0->dimension(); 312 313 313 for ( int i=0;i<n;i++ ) {samples ( i ) =epdf0->sample();} 314 for ( int i = 0; i < n; i++ ) { 315 samples ( i ) = epdf0->sample(); 316 } 314 317 } 315 318 316 319 void eEmp::set_samples ( const epdf* epdf0 ) { 317 320 //it_assert_debug(rv==epdf0->rv(),"Wrong epdf0"); 318 w=1; 319 w/=sum ( w );//renormalize 320 321 for ( int i=0;i<n;i++ ) {samples ( i ) =epdf0->sample();} 322 } 323 324 void migamma_ref::from_setting( const Setting &set ) 325 { 321 w = 1; 322 w /= sum ( w );//renormalize 323 324 for ( int i = 0; i < n; i++ ) { 325 samples ( i ) = epdf0->sample(); 326 } 327 } 328 329 void migamma_ref::from_setting ( const Setting &set ) { 326 330 vec ref; 327 UI::get( ref, set, "ref" , UI::compulsory); 328 set_parameters(set["k"],ref,set["l"]); 329 } 330 331 void mlognorm::from_setting( const Setting &set ) 332 { 333 vec mu0; 334 UI::get( mu0, set, "mu0", UI::compulsory); 335 set_parameters(mu0.length(),set["k"]); 336 condition(mu0); 331 UI::get ( ref, set, "ref" , UI::compulsory ); 332 set_parameters ( set["k"], ref, set["l"] ); 333 } 334 335 void mlognorm::from_setting ( const Setting &set ) { 336 vec mu0; 337 UI::get ( mu0, set, "mu0", UI::compulsory ); 338 set_parameters ( mu0.length(), set["k"] ); 339 condition ( mu0 ); 337 340 } 338 341 -
library/bdm/stat/merger.cpp
r461 r477 3 3 #include "../estim/arx.h" 4 4 5 namespace bdm 6 { 7 8 merger_base::merger_base(const Array<mpdf*> &S, bool own) { 9 DBG = false; 10 dbg_file = NULL; 11 set_sources(S, own); 12 } 13 14 vec merger_base::merge_points ( mat &lW ) { 15 int nu=lW.rows(); 16 vec result; 17 ivec indW; 18 bool infexist; 19 switch ( METHOD ) { 20 case ARITHMETIC: 21 result= log ( sum ( exp ( lW ) ) ); //ugly! 22 break; 23 case GEOMETRIC: 24 result= sum ( lW ) /nu; 25 break; 26 case LOGNORMAL: 27 vec sumlW=sum ( lW ) ; 28 indW=find((sumlW<inf) & (sumlW>-inf)); 29 infexist=(indW.size()<lW.cols()); 30 vec mu; 31 vec lam; 32 if (infexist){ 33 mu = sumlW(indW) /nu; //mean of logs 34 // 35 mat validlW=lW.get_cols(indW); 36 lam = sum ( pow ( validlW-outer_product ( ones ( validlW.rows() ),mu ),2 ) ); 37 } 38 else { 39 mu = sum ( lW ) /nu; //mean of logs 40 lam = sum ( pow ( lW-outer_product ( ones ( lW.rows() ),mu ),2 ) ); 41 } 42 // 43 double coef=0.0; 44 vec sq2bl=sqrt ( 2*beta*lam ); //this term is everywhere 45 switch ( nu ) { 46 case 2: 47 coef= ( 1-0.5*sqrt ( ( 4.0*beta-3.0 ) /beta ) ); 48 result =coef*sq2bl + mu ; 49 break; 50 // case 4: == can be done similar to case 2 - is it worth it??? 51 default: // see accompanying document merge_lognorm_derivation.lyx 52 coef = sqrt(1-(nu+1)/(2*beta*nu)); 53 result =log(besselk((nu-3)/2, sq2bl*coef))-log(besselk((nu-3)/2, sq2bl)) + mu; 54 break; 55 } 56 break; 57 } 58 if (infexist){ 59 vec tmp =-inf*ones(lW.cols()); 60 set_subvector(tmp, indW, result); 61 return tmp; 62 } 63 else {return result;} 64 } 65 66 void merger_mix::merge ( ) 67 { 68 Array<vec> &Smp = eSmp._samples(); //aux 69 vec &w = eSmp._w(); //aux 70 71 mat Smp_ex =ones ( dim +1,Npoints ); // Extended samples for the ARX model - the last row is ones 72 for ( int i=0;i<Npoints;i++ ) { set_col_part ( Smp_ex,i,Smp ( i ) );} 73 74 if ( DBG ) *dbg_file << Name ( "Smp_0" ) << Smp_ex; 75 76 // Stuff for merging 77 vec lw_src ( Npoints ); // weights of the ith source 78 vec lw_mix ( Npoints ); // weights of the approximating mixture 79 vec lw ( Npoints ); // tmp 80 mat lW=zeros ( Nsources,Npoints ); // array of weights of all sources 81 vec vec0 ( 0 ); 82 83 //initialize importance weights 84 lw_mix = 1.0; // assuming uniform grid density -- otherwise 85 86 // Initial component in the mixture model 87 mat V0=1e-8*eye ( dim +1 ); 88 ARX A0; A0.set_statistics ( dim, V0 ); //initial guess of Mix: 89 90 Mix.init ( &A0, Smp_ex, Ncoms ); 91 //Preserve initial mixture for repetitive estimation via flattening 92 MixEF Mix_init ( Mix ); 93 94 // ============= MAIN LOOP ================== 95 bool converged=false; 96 int niter = 0; 97 char dbg_str[100]; 98 99 emix* Mpred=Mix.epredictor ( ); 100 vec Mix_pdf ( Npoints ); 101 while ( !converged ) 102 { 103 //Re-estimate Mix 104 //Re-Initialize Mixture model 105 Mix.flatten ( &Mix_init ); 106 Mix.bayesB ( Smp_ex, w*Npoints ); 107 delete Mpred; 108 Mpred = Mix.epredictor ( ); // Allocation => must be deleted at the end!! 109 Mpred->set_rv ( rv ); //the predictor predicts rv of this merger 110 111 // This will be active only later in iterations!!! 112 if ( 1./sum_sqr ( w ) <effss_coef*Npoints ) 113 { 114 // Generate new samples 115 eSmp.set_samples ( Mpred ); 116 for ( int i=0;i<Npoints;i++ ) 117 { 118 //////////// !!!!!!!!!!!!! 119 //if ( Smp ( i ) ( 2 ) <0 ) {Smp ( i ) ( 2 ) = 0.01; } 120 set_col_part ( Smp_ex,i,Smp ( i ) ); 121 //Importance of the mixture 122 //lw_mix ( i ) =Mix.logpred (Smp_ex.get_col(i) ); 123 lw_mix ( i ) = Mpred->evallog ( Smp ( i ) ); 124 } 125 if ( DBG ) 126 { 127 cout<<"Resampling =" << 1./sum_sqr ( w ) << endl; 128 cout << Mix._e()->mean() <<endl; 129 cout << sum ( Smp_ex,2 ) /Npoints <<endl; 130 cout << Smp_ex*Smp_ex.T() /Npoints << endl; 131 } 132 } 133 if ( DBG ) 134 { 135 sprintf ( dbg_str,"Mpred_mean%d",niter ); 136 *dbg_file << Name ( dbg_str ) << Mpred->mean(); 137 sprintf ( dbg_str,"Mpred_var%d",niter ); 138 *dbg_file << Name ( dbg_str ) << Mpred->variance(); 139 140 141 sprintf ( dbg_str,"Mpdf%d",niter ); 142 for ( int i=0;i<Npoints;i++ ) {Mix_pdf ( i ) = Mix.logpred ( Smp_ex.get_col ( i ) );} 143 *dbg_file << Name ( dbg_str ) << Mix_pdf; 144 145 sprintf ( dbg_str,"Smp%d",niter ); 146 *dbg_file << Name ( dbg_str ) << Smp_ex; 147 148 } 149 //Importace weighting 150 for ( int i=0;i<mpdfs.length();i++ ) 151 { 152 lw_src=0.0; 153 //======== Same RVs =========== 154 //Split according to dependency in rvs 155 if ( mpdfs ( i )->dimension() ==dim ) 156 { 157 // no need for conditioning or marginalization 158 lw_src = mpdfs ( i )->e()->evallog_m ( Smp ); 159 } 160 else 161 { 162 // compute likelihood of marginal on the conditional variable 163 if ( mpdfs ( i )->dimensionc() >0 ) 164 { 165 // Make marginal on rvc_i 166 epdf* tmp_marg = Mpred->marginal ( mpdfs ( i )->_rvc() ); 167 //compute vector of lw_src 168 for ( int k=0;k<Npoints;k++ ) 169 { 170 // Here val of tmp_marg = cond of mpdfs(i) ==> calling dls->get_cond 171 lw_src ( k ) += tmp_marg->evallog ( dls ( i )->get_cond ( Smp ( k ) ) ); 172 } 173 delete tmp_marg; 5 namespace bdm { 6 7 merger_base::merger_base ( const Array<mpdf*> &S, bool own ) { 8 DBG = false; 9 dbg_file = NULL; 10 set_sources ( S, own ); 11 } 12 13 vec merger_base::merge_points ( mat &lW ) { 14 int nu = lW.rows(); 15 vec result; 16 ivec indW; 17 bool infexist; 18 switch ( METHOD ) { 19 case ARITHMETIC: 20 result = log ( sum ( exp ( lW ) ) ); //ugly! 21 break; 22 case GEOMETRIC: 23 result = sum ( lW ) / nu; 24 break; 25 case LOGNORMAL: 26 vec sumlW = sum ( lW ) ; 27 indW = find ( ( sumlW < inf ) & ( sumlW > -inf ) ); 28 infexist = ( indW.size() < lW.cols() ); 29 vec mu; 30 vec lam; 31 if ( infexist ) { 32 mu = sumlW ( indW ) / nu; //mean of logs 33 // 34 mat validlW = lW.get_cols ( indW ); 35 lam = sum ( pow ( validlW - outer_product ( ones ( validlW.rows() ), mu ), 2 ) ); 36 } else { 37 mu = sum ( lW ) / nu; //mean of logs 38 lam = sum ( pow ( lW - outer_product ( ones ( lW.rows() ), mu ), 2 ) ); 39 } 40 // 41 double coef = 0.0; 42 vec sq2bl = sqrt ( 2 * beta * lam ); //this term is everywhere 43 switch ( nu ) { 44 case 2: 45 coef = ( 1 - 0.5 * sqrt ( ( 4.0 * beta - 3.0 ) / beta ) ); 46 result = coef * sq2bl + mu ; 47 break; 48 // case 4: == can be done similar to case 2 - is it worth it??? 49 default: // see accompanying document merge_lognorm_derivation.lyx 50 coef = sqrt ( 1 - ( nu + 1 ) / ( 2 * beta * nu ) ); 51 result = log ( besselk ( ( nu - 3 ) / 2, sq2bl * coef ) ) - log ( besselk ( ( nu - 3 ) / 2, sq2bl ) ) + mu; 52 break; 53 } 54 break; 55 } 56 if ( infexist ) { 57 vec tmp = -inf * ones ( lW.cols() ); 58 set_subvector ( tmp, indW, result ); 59 return tmp; 60 } else { 61 return result; 62 } 63 } 64 65 void merger_mix::merge ( ) { 66 Array<vec> &Smp = eSmp._samples(); //aux 67 vec &w = eSmp._w(); //aux 68 69 mat Smp_ex = ones ( dim + 1, Npoints ); // Extended samples for the ARX model - the last row is ones 70 for ( int i = 0; i < Npoints; i++ ) { 71 set_col_part ( Smp_ex, i, Smp ( i ) ); 72 } 73 74 if ( DBG ) *dbg_file << Name ( "Smp_0" ) << Smp_ex; 75 76 // Stuff for merging 77 vec lw_src ( Npoints ); // weights of the ith source 78 vec lw_mix ( Npoints ); // weights of the approximating mixture 79 vec lw ( Npoints ); // tmp 80 mat lW = zeros ( Nsources, Npoints ); // array of weights of all sources 81 vec vec0 ( 0 ); 82 83 //initialize importance weights 84 lw_mix = 1.0; // assuming uniform grid density -- otherwise 85 86 // Initial component in the mixture model 87 mat V0 = 1e-8 * eye ( dim + 1 ); 88 ARX A0; 89 A0.set_statistics ( dim, V0 ); //initial guess of Mix: 90 91 Mix.init ( &A0, Smp_ex, Ncoms ); 92 //Preserve initial mixture for repetitive estimation via flattening 93 MixEF Mix_init ( Mix ); 94 95 // ============= MAIN LOOP ================== 96 bool converged = false; 97 int niter = 0; 98 char dbg_str[100]; 99 100 emix* Mpred = Mix.epredictor ( ); 101 vec Mix_pdf ( Npoints ); 102 while ( !converged ) { 103 //Re-estimate Mix 104 //Re-Initialize Mixture model 105 Mix.flatten ( &Mix_init ); 106 Mix.bayesB ( Smp_ex, w*Npoints ); 107 delete Mpred; 108 Mpred = Mix.epredictor ( ); // Allocation => must be deleted at the end!! 109 Mpred->set_rv ( rv ); //the predictor predicts rv of this merger 110 111 // This will be active only later in iterations!!! 112 if ( 1. / sum_sqr ( w ) < effss_coef*Npoints ) { 113 // Generate new samples 114 eSmp.set_samples ( Mpred ); 115 for ( int i = 0; i < Npoints; i++ ) { 116 //////////// !!!!!!!!!!!!! 117 //if ( Smp ( i ) ( 2 ) <0 ) {Smp ( i ) ( 2 ) = 0.01; } 118 set_col_part ( Smp_ex, i, Smp ( i ) ); 119 //Importance of the mixture 120 //lw_mix ( i ) =Mix.logpred (Smp_ex.get_col(i) ); 121 lw_mix ( i ) = Mpred->evallog ( Smp ( i ) ); 122 } 123 if ( DBG ) { 124 cout << "Resampling =" << 1. / sum_sqr ( w ) << endl; 125 cout << Mix._e()->mean() << endl; 126 cout << sum ( Smp_ex, 2 ) / Npoints << endl; 127 cout << Smp_ex*Smp_ex.T() / Npoints << endl; 128 } 129 } 130 if ( DBG ) { 131 sprintf ( dbg_str, "Mpred_mean%d", niter ); 132 *dbg_file << Name ( dbg_str ) << Mpred->mean(); 133 sprintf ( dbg_str, "Mpred_var%d", niter ); 134 *dbg_file << Name ( dbg_str ) << Mpred->variance(); 135 136 137 sprintf ( dbg_str, "Mpdf%d", niter ); 138 for ( int i = 0; i < Npoints; i++ ) { 139 Mix_pdf ( i ) = Mix.logpred ( Smp_ex.get_col ( i ) ); 140 } 141 *dbg_file << Name ( dbg_str ) << Mix_pdf; 142 143 sprintf ( dbg_str, "Smp%d", niter ); 144 *dbg_file << Name ( dbg_str ) << Smp_ex; 145 146 } 147 //Importace weighting 148 for ( int i = 0; i < mpdfs.length(); i++ ) { 149 lw_src = 0.0; 150 //======== Same RVs =========== 151 //Split according to dependency in rvs 152 if ( mpdfs ( i )->dimension() == dim ) { 153 // no need for conditioning or marginalization 154 lw_src = mpdfs ( i )->e()->evallog_m ( Smp ); 155 } else { 156 // compute likelihood of marginal on the conditional variable 157 if ( mpdfs ( i )->dimensionc() > 0 ) { 158 // Make marginal on rvc_i 159 epdf* tmp_marg = Mpred->marginal ( mpdfs ( i )->_rvc() ); 160 //compute vector of lw_src 161 for ( int k = 0; k < Npoints; k++ ) { 162 // Here val of tmp_marg = cond of mpdfs(i) ==> calling dls->get_cond 163 lw_src ( k ) += tmp_marg->evallog ( dls ( i )->get_cond ( Smp ( k ) ) ); 164 } 165 delete tmp_marg; 174 166 175 167 // sprintf ( str,"marg%d",niter ); 176 168 // *dbg << Name ( str ) << lw_src; 177 169 170 } 171 // Compute likelihood of the missing variable 172 if ( dim > ( mpdfs ( i )->dimension() + mpdfs ( i )->dimensionc() ) ) { 173 /////////////// 174 // There are variales unknown to mpdfs(i) : rvzs 175 mpdf* tmp_cond = Mpred->condition ( rvzs ( i ) ); 176 // Compute likelihood 177 vec lw_dbg = lw_src; 178 for ( int k = 0; k < Npoints; k++ ) { 179 lw_src ( k ) += log ( 180 tmp_cond->evallogcond ( 181 zdls ( i )->pushdown ( Smp ( k ) ), 182 zdls ( i )->get_cond ( Smp ( k ) ) ) ); 183 if ( !std::isfinite ( lw_src ( k ) ) ) { 184 lw_src ( k ) = -1e16; 185 cout << "!"; 186 } 178 187 } 179 // Compute likelihood of the missing variable 180 if ( dim > ( mpdfs ( i )->dimension() + mpdfs ( i )->dimensionc() ) ) 181 { 182 /////////////// 183 // There are variales unknown to mpdfs(i) : rvzs 184 mpdf* tmp_cond = Mpred->condition ( rvzs ( i ) ); 185 // Compute likelihood 186 vec lw_dbg=lw_src; 187 for ( int k= 0; k<Npoints; k++ ) 188 { 189 lw_src ( k ) += log ( 190 tmp_cond->evallogcond ( 191 zdls ( i )->pushdown ( Smp ( k ) ), 192 zdls ( i )->get_cond ( Smp ( k ) ) ) ); 193 if ( !std::isfinite ( lw_src ( k ) ) ) 194 { 195 lw_src ( k ) = -1e16; cout << "!"; 196 } 197 } 198 delete tmp_cond; 199 } 200 // Compute likelihood of the partial source 201 for ( int k= 0; k<Npoints; k++ ) 202 { 203 mpdfs ( i )->condition ( dls ( i )->get_cond ( Smp ( k ) ) ); 204 lw_src ( k ) += mpdfs ( i )->e()->evallog ( dls ( i )->pushdown ( Smp ( k ) ) ); 205 } 206 188 delete tmp_cond; 207 189 } 208 // it_assert_debug(std::isfinite(sum(lw_src)),"bad"); 209 lW.set_row ( i, lw_src ); // do not divide by mix 210 } 211 lw = merger_base::merge_points ( lW ); //merge 212 213 //Importance weighting 214 lw -= lw_mix; // hoping that it is not numerically sensitive... 215 w = exp ( lw-max ( lw ) ); 216 217 //renormalize 218 double sumw =sum ( w ); 219 if ( std::isfinite ( sumw ) ) 220 { 221 w = w/sumw; 222 } 223 else 224 { 225 it_file itf ( "merg_err.it" ); 226 itf << Name ( "w" ) << w; 227 } 228 229 if ( DBG ) 230 { 231 sprintf ( dbg_str,"lW%d",niter ); 232 *dbg_file << Name ( dbg_str ) << lW; 233 sprintf ( dbg_str,"w%d",niter ); 234 *dbg_file << Name ( dbg_str ) << w; 235 sprintf ( dbg_str,"lw_m%d",niter ); 236 *dbg_file << Name ( dbg_str ) << lw_mix; 237 } 238 // ==== stopping rule === 239 niter++; 240 converged = ( niter>stop_niter ); 241 } 242 delete Mpred; 190 // Compute likelihood of the partial source 191 for ( int k = 0; k < Npoints; k++ ) { 192 mpdfs ( i )->condition ( dls ( i )->get_cond ( Smp ( k ) ) ); 193 lw_src ( k ) += mpdfs ( i )->e()->evallog ( dls ( i )->pushdown ( Smp ( k ) ) ); 194 } 195 196 } 197 // it_assert_debug(std::isfinite(sum(lw_src)),"bad"); 198 lW.set_row ( i, lw_src ); // do not divide by mix 199 } 200 lw = merger_base::merge_points ( lW ); //merge 201 202 //Importance weighting 203 lw -= lw_mix; // hoping that it is not numerically sensitive... 204 w = exp ( lw - max ( lw ) ); 205 206 //renormalize 207 double sumw = sum ( w ); 208 if ( std::isfinite ( sumw ) ) { 209 w = w / sumw; 210 } else { 211 it_file itf ( "merg_err.it" ); 212 itf << Name ( "w" ) << w; 213 } 214 215 if ( DBG ) { 216 sprintf ( dbg_str, "lW%d", niter ); 217 *dbg_file << Name ( dbg_str ) << lW; 218 sprintf ( dbg_str, "w%d", niter ); 219 *dbg_file << Name ( dbg_str ) << w; 220 sprintf ( dbg_str, "lw_m%d", niter ); 221 *dbg_file << Name ( dbg_str ) << lw_mix; 222 } 223 // ==== stopping rule === 224 niter++; 225 converged = ( niter > stop_niter ); 226 } 227 delete Mpred; 243 228 // cout << endl; 244 229 245 246 247 // DEFAULTS FOR MERGER_BASE 248 const MERGER_METHOD merger_base::DFLT_METHOD=LOGNORMAL;249 const double merger_base::DFLT_beta=1.2;250 251 const int merger_mix::DFLT_Ncoms=10;252 const double merger_mix::DFLT_effss_coef=0.5;253 254 } 230 } 231 232 // DEFAULTS FOR MERGER_BASE 233 const MERGER_METHOD merger_base::DFLT_METHOD = LOGNORMAL; 234 const double merger_base::DFLT_beta = 1.2; 235 // DEFAULTS FOR MERGER_MIX 236 const int merger_mix::DFLT_Ncoms = 10; 237 const double merger_mix::DFLT_effss_coef = 0.5; 238 239 } -
library/bdm/stat/merger.h
r471 r477 17 17 #include "../estim/mixtures.h" 18 18 19 namespace bdm 20 { 19 namespace bdm { 21 20 using std::string; 22 21 … … 43 42 */ 44 43 45 class merger_base : public compositepdf, public epdf 46 { 47 protected: 48 //! Data link for each mpdf in mpdfs 49 Array<datalink_m2e*> dls; 50 //! Array of rvs that are not modelled by mpdfs at all, \f$ z_i \f$ 51 Array<RV> rvzs; 52 //! Data Links for extension \f$ f(z_i|x_i,y_i) \f$ 53 Array<datalink_m2e*> zdls; 54 //! number of support points 55 int Npoints; 56 //! number of sources 57 int Nsources; 58 59 //! switch of the methoh used for merging 60 MERGER_METHOD METHOD; 61 //! Default for METHOD 62 static const MERGER_METHOD DFLT_METHOD; 63 64 //!Prior on the log-normal merging model 65 double beta; 66 //! default for beta 67 static const double DFLT_beta; 68 69 //! Projection to empirical density (could also be piece-wise linear) 70 eEmp eSmp; 71 72 //! debug or not debug 73 bool DBG; 74 75 //! debugging file 76 it_file* dbg_file; 77 public: 78 //! \name Constructors 79 //! @{ 80 81 //!Empty constructor 82 merger_base () : compositepdf() {DBG = false;dbg_file = NULL;} 83 84 //!Constructor from sources 85 merger_base (const Array<mpdf*> &S, bool own=false); 86 87 //! Function setting the main internal structures 88 void set_sources (const Array<mpdf*> &Sources, bool own) { 89 compositepdf::set_elements (Sources,own); 90 Nsources=mpdfs.length(); 91 //set sizes 92 dls.set_size (Sources.length()); 93 rvzs.set_size (Sources.length()); 94 zdls.set_size (Sources.length()); 95 96 rv = getrv (/* checkoverlap = */ false); 97 RV rvc; setrvc (rv, rvc); // Extend rv by rvc! 98 // join rv and rvc - see descriprion 99 rv.add (rvc); 100 // get dimension 101 dim = rv._dsize(); 102 103 // create links between sources and common rv 104 RV xytmp; 105 for (int i = 0;i < mpdfs.length();i++) { 106 //Establich connection between mpdfs and merger 107 dls (i) = new datalink_m2e; 108 dls (i)->set_connection (mpdfs (i)->_rv(), mpdfs (i)->_rvc(), rv); 109 110 // find out what is missing in each mpdf 111 xytmp = mpdfs (i)->_rv(); 112 xytmp.add (mpdfs (i)->_rvc()); 113 // z_i = common_rv-xy 114 rvzs (i) = rv.subt (xytmp); 115 //establish connection between extension (z_i|x,y)s and common rv 116 zdls (i) = new datalink_m2e; zdls (i)->set_connection (rvzs (i), xytmp, rv) ; 117 }; 118 } 119 //! Rectangular support each vector of XYZ specifies (begining-end) interval for each dimension. Same number of points, \c dimsize, in each dimension. 120 void set_support (const Array<vec> &XYZ, const int dimsize) { 121 set_support(XYZ,dimsize*ones_i(XYZ.length())); 122 } 123 //! Rectangular support each vector of XYZ specifies (begining-end) interval for each dimension. \c gridsize specifies number of points is each dimension. 124 void set_support (const Array<vec> &XYZ, const ivec &gridsize) { 125 int dim = XYZ.length(); //check with internal dim!! 126 Npoints = prod (gridsize); 127 eSmp.set_parameters (Npoints, false); 128 Array<vec> &samples = eSmp._samples(); 129 eSmp._w() = ones (Npoints) / Npoints; //unifrom size of bins 130 //set samples 131 ivec ind = zeros_i (dim); //indeces of dimensions in for cycle; 132 vec smpi (dim); // ith sample 133 vec steps =zeros(dim); // ith sample 134 // first corner 135 for (int j = 0; j < dim; j++) { 136 smpi (j) = XYZ (j) (0); /* beginning of the interval*/ 137 it_assert(gridsize(j)!=0.0,"Zeros in gridsize!"); 138 steps (j) = ( XYZ(j)(1)-smpi(j) )/gridsize(j); 139 } 140 // fill samples 141 for (int i = 0; i < Npoints; i++) { 142 // copy 143 samples(i) = smpi; 144 // go through all dimensions 145 for (int j = 0;j < dim;j++) { 146 if (ind (j) == gridsize (j) - 1) { //j-th index is full 147 ind (j) = 0; //shift back 148 smpi(j) = XYZ(j)(0); 149 150 if (i<Npoints-1) { 151 ind (j + 1) ++; //increase the next dimension; 152 smpi(j+1) += steps(j+1); 153 break; 154 } 155 156 } else { 157 ind (j) ++; 158 smpi(j) +=steps(j); 44 class merger_base : public compositepdf, public epdf { 45 protected: 46 //! Data link for each mpdf in mpdfs 47 Array<datalink_m2e*> dls; 48 //! Array of rvs that are not modelled by mpdfs at all, \f$ z_i \f$ 49 Array<RV> rvzs; 50 //! Data Links for extension \f$ f(z_i|x_i,y_i) \f$ 51 Array<datalink_m2e*> zdls; 52 //! number of support points 53 int Npoints; 54 //! number of sources 55 int Nsources; 56 57 //! switch of the methoh used for merging 58 MERGER_METHOD METHOD; 59 //! Default for METHOD 60 static const MERGER_METHOD DFLT_METHOD; 61 62 //!Prior on the log-normal merging model 63 double beta; 64 //! default for beta 65 static const double DFLT_beta; 66 67 //! Projection to empirical density (could also be piece-wise linear) 68 eEmp eSmp; 69 70 //! debug or not debug 71 bool DBG; 72 73 //! debugging file 74 it_file* dbg_file; 75 public: 76 //! \name Constructors 77 //! @{ 78 79 //!Empty constructor 80 merger_base () : compositepdf() { 81 DBG = false; 82 dbg_file = NULL; 83 } 84 85 //!Constructor from sources 86 merger_base ( const Array<mpdf*> &S, bool own = false ); 87 88 //! Function setting the main internal structures 89 void set_sources ( const Array<mpdf*> &Sources, bool own ) { 90 compositepdf::set_elements ( Sources, own ); 91 Nsources = mpdfs.length(); 92 //set sizes 93 dls.set_size ( Sources.length() ); 94 rvzs.set_size ( Sources.length() ); 95 zdls.set_size ( Sources.length() ); 96 97 rv = getrv ( /* checkoverlap = */ false ); 98 RV rvc; 99 setrvc ( rv, rvc ); // Extend rv by rvc! 100 // join rv and rvc - see descriprion 101 rv.add ( rvc ); 102 // get dimension 103 dim = rv._dsize(); 104 105 // create links between sources and common rv 106 RV xytmp; 107 for ( int i = 0; i < mpdfs.length(); i++ ) { 108 //Establich connection between mpdfs and merger 109 dls ( i ) = new datalink_m2e; 110 dls ( i )->set_connection ( mpdfs ( i )->_rv(), mpdfs ( i )->_rvc(), rv ); 111 112 // find out what is missing in each mpdf 113 xytmp = mpdfs ( i )->_rv(); 114 xytmp.add ( mpdfs ( i )->_rvc() ); 115 // z_i = common_rv-xy 116 rvzs ( i ) = rv.subt ( xytmp ); 117 //establish connection between extension (z_i|x,y)s and common rv 118 zdls ( i ) = new datalink_m2e; 119 zdls ( i )->set_connection ( rvzs ( i ), xytmp, rv ) ; 120 }; 121 } 122 //! Rectangular support each vector of XYZ specifies (begining-end) interval for each dimension. Same number of points, \c dimsize, in each dimension. 123 void set_support ( const Array<vec> &XYZ, const int dimsize ) { 124 set_support ( XYZ, dimsize*ones_i ( XYZ.length() ) ); 125 } 126 //! Rectangular support each vector of XYZ specifies (begining-end) interval for each dimension. \c gridsize specifies number of points is each dimension. 127 void set_support ( const Array<vec> &XYZ, const ivec &gridsize ) { 128 int dim = XYZ.length(); //check with internal dim!! 129 Npoints = prod ( gridsize ); 130 eSmp.set_parameters ( Npoints, false ); 131 Array<vec> &samples = eSmp._samples(); 132 eSmp._w() = ones ( Npoints ) / Npoints; //unifrom size of bins 133 //set samples 134 ivec ind = zeros_i ( dim ); //indeces of dimensions in for cycle; 135 vec smpi ( dim ); // ith sample 136 vec steps = zeros ( dim ); // ith sample 137 // first corner 138 for ( int j = 0; j < dim; j++ ) { 139 smpi ( j ) = XYZ ( j ) ( 0 ); /* beginning of the interval*/ 140 it_assert ( gridsize ( j ) != 0.0, "Zeros in gridsize!" ); 141 steps ( j ) = ( XYZ ( j ) ( 1 ) - smpi ( j ) ) / gridsize ( j ); 142 } 143 // fill samples 144 for ( int i = 0; i < Npoints; i++ ) { 145 // copy 146 samples ( i ) = smpi; 147 // go through all dimensions 148 for ( int j = 0; j < dim; j++ ) { 149 if ( ind ( j ) == gridsize ( j ) - 1 ) { //j-th index is full 150 ind ( j ) = 0; //shift back 151 smpi ( j ) = XYZ ( j ) ( 0 ); 152 153 if ( i < Npoints - 1 ) { 154 ind ( j + 1 ) ++; //increase the next dimension; 155 smpi ( j + 1 ) += steps ( j + 1 ); 159 156 break; 160 157 } 158 159 } else { 160 ind ( j ) ++; 161 smpi ( j ) += steps ( j ); 162 break; 161 163 } 162 164 } 163 165 } 164 //! set debug file 165 void set_debug_file (const string fname) { 166 if (DBG) delete dbg_file; 167 dbg_file = new it_file (fname); 168 if (dbg_file) DBG = true; 169 } 170 //! Set internal parameters used in approximation 171 void set_method (MERGER_METHOD MTH=DFLT_METHOD, double beta0 = DFLT_beta) { 172 METHOD = MTH; 173 beta = beta0; 174 } 175 //! Set support points from a pdf by drawing N samples 176 void set_support (const epdf &overall, int N) { 177 eSmp.set_statistics (&overall, N); 178 Npoints = N; 179 } 180 181 //! Destructor 182 virtual ~merger_base() { 183 for (int i = 0; i < Nsources; i++) { 184 delete dls (i); 185 delete zdls (i); 186 } 187 if (DBG) delete dbg_file; 188 }; 189 //!@} 190 191 //! \name Mathematical operations 192 //!@{ 193 194 //!Merge given sources in given points 195 virtual void merge () { 196 validate(); 197 198 //check if sources overlap: 199 bool OK = true; 200 for (int i = 0;i < mpdfs.length(); i++) { 201 OK &= (rvzs (i)._dsize() == 0); // z_i is empty 202 OK &= (mpdfs (i)->_rvc()._dsize() == 0); // y_i is empty 203 } 204 205 if (OK) { 206 mat lW = zeros (mpdfs.length(), eSmp._w().length()); 207 208 vec emptyvec (0); 209 for (int i = 0; i < mpdfs.length(); i++) { 210 for (int j = 0; j < eSmp._w().length(); j++) { 211 lW (i, j) = mpdfs (i)->evallogcond (eSmp._samples() (j), emptyvec); 212 } 213 } 214 215 vec w_nn=merge_points (lW); 216 vec wtmp = exp (w_nn-max(w_nn)); 217 //renormalize 218 eSmp._w() = wtmp / sum (wtmp); 219 } else { 220 it_error ("Sources are not compatible - use merger_mix"); 221 } 222 }; 223 224 225 //! Merge log-likelihood values in points using method specified by parameter METHOD 226 vec merge_points (mat &lW); 227 228 229 //! sample from merged density 230 //! weight w is a 231 vec mean() const { 232 const Vec<double> &w = eSmp._w(); 233 const Array<vec> &S = eSmp._samples(); 234 vec tmp = zeros (dim); 235 for (int i = 0; i < Npoints; i++) { 236 tmp += w (i) * S (i); 237 } 238 return tmp; 239 } 240 mat covariance() const { 241 const vec &w = eSmp._w(); 242 const Array<vec> &S = eSmp._samples(); 243 244 vec mea = mean(); 245 246 // cout << sum (w) << "," << w*w << endl; 247 248 mat Tmp = zeros (dim, dim); 249 for (int i = 0; i < Npoints; i++) { 250 Tmp += w (i) * outer_product (S (i), S (i)); 251 } 252 return Tmp -outer_product (mea, mea); 253 } 254 vec variance() const { 255 const vec &w = eSmp._w(); 256 const Array<vec> &S = eSmp._samples(); 257 258 vec tmp = zeros (dim); 259 for (int i = 0; i < Nsources; i++) { 260 tmp += w (i) * pow (S (i), 2); 261 } 262 return tmp -pow (mean(), 2); 263 } 264 //!@} 265 266 //! \name Access to attributes 267 //! @{ 268 269 //! Access function 270 eEmp& _Smp() {return eSmp;} 271 272 //! load from setting 273 void from_setting (const Setting& set) { 274 // get support 275 // find which method to use 276 string meth_str; 277 UI::get<string> (meth_str, set, "method", UI::compulsory); 278 if (!strcmp (meth_str.c_str(), "arithmetic")) 279 set_method (ARITHMETIC); 280 else { 281 if (!strcmp (meth_str.c_str(), "geometric")) 282 set_method (GEOMETRIC); 283 else if (!strcmp (meth_str.c_str(), "lognormal")) { 284 set_method (LOGNORMAL); 285 set.lookupValue( "beta",beta); 166 } 167 //! set debug file 168 void set_debug_file ( const string fname ) { 169 if ( DBG ) delete dbg_file; 170 dbg_file = new it_file ( fname ); 171 if ( dbg_file ) DBG = true; 172 } 173 //! Set internal parameters used in approximation 174 void set_method ( MERGER_METHOD MTH = DFLT_METHOD, double beta0 = DFLT_beta ) { 175 METHOD = MTH; 176 beta = beta0; 177 } 178 //! Set support points from a pdf by drawing N samples 179 void set_support ( const epdf &overall, int N ) { 180 eSmp.set_statistics ( &overall, N ); 181 Npoints = N; 182 } 183 184 //! Destructor 185 virtual ~merger_base() { 186 for ( int i = 0; i < Nsources; i++ ) { 187 delete dls ( i ); 188 delete zdls ( i ); 189 } 190 if ( DBG ) delete dbg_file; 191 }; 192 //!@} 193 194 //! \name Mathematical operations 195 //!@{ 196 197 //!Merge given sources in given points 198 virtual void merge () { 199 validate(); 200 201 //check if sources overlap: 202 bool OK = true; 203 for ( int i = 0; i < mpdfs.length(); i++ ) { 204 OK &= ( rvzs ( i )._dsize() == 0 ); // z_i is empty 205 OK &= ( mpdfs ( i )->_rvc()._dsize() == 0 ); // y_i is empty 206 } 207 208 if ( OK ) { 209 mat lW = zeros ( mpdfs.length(), eSmp._w().length() ); 210 211 vec emptyvec ( 0 ); 212 for ( int i = 0; i < mpdfs.length(); i++ ) { 213 for ( int j = 0; j < eSmp._w().length(); j++ ) { 214 lW ( i, j ) = mpdfs ( i )->evallogcond ( eSmp._samples() ( j ), emptyvec ); 286 215 } 287 216 } 288 string dbg_file; 289 if (UI::get(dbg_file, set, "dbg_file")) 290 set_debug_file(dbg_file); 291 //validate() - not used 292 } 293 294 void validate() { 295 it_assert (eSmp._w().length() > 0, "Empty support, use set_support()."); 296 it_assert (dim == eSmp._samples() (0).length(), "Support points and rv are not compatible!"); 297 it_assert (isnamed(),"mergers must be named"); 298 } 299 //!@} 217 218 vec w_nn = merge_points ( lW ); 219 vec wtmp = exp ( w_nn - max ( w_nn ) ); 220 //renormalize 221 eSmp._w() = wtmp / sum ( wtmp ); 222 } else { 223 it_error ( "Sources are not compatible - use merger_mix" ); 224 } 225 }; 226 227 228 //! Merge log-likelihood values in points using method specified by parameter METHOD 229 vec merge_points ( mat &lW ); 230 231 232 //! sample from merged density 233 //! weight w is a 234 vec mean() const { 235 const Vec<double> &w = eSmp._w(); 236 const Array<vec> &S = eSmp._samples(); 237 vec tmp = zeros ( dim ); 238 for ( int i = 0; i < Npoints; i++ ) { 239 tmp += w ( i ) * S ( i ); 240 } 241 return tmp; 242 } 243 mat covariance() const { 244 const vec &w = eSmp._w(); 245 const Array<vec> &S = eSmp._samples(); 246 247 vec mea = mean(); 248 249 // cout << sum (w) << "," << w*w << endl; 250 251 mat Tmp = zeros ( dim, dim ); 252 for ( int i = 0; i < Npoints; i++ ) { 253 Tmp += w ( i ) * outer_product ( S ( i ), S ( i ) ); 254 } 255 return Tmp - outer_product ( mea, mea ); 256 } 257 vec variance() const { 258 const vec &w = eSmp._w(); 259 const Array<vec> &S = eSmp._samples(); 260 261 vec tmp = zeros ( dim ); 262 for ( int i = 0; i < Nsources; i++ ) { 263 tmp += w ( i ) * pow ( S ( i ), 2 ); 264 } 265 return tmp - pow ( mean(), 2 ); 266 } 267 //!@} 268 269 //! \name Access to attributes 270 //! @{ 271 272 //! Access function 273 eEmp& _Smp() { 274 return eSmp; 275 } 276 277 //! load from setting 278 void from_setting ( const Setting& set ) { 279 // get support 280 // find which method to use 281 string meth_str; 282 UI::get<string> ( meth_str, set, "method", UI::compulsory ); 283 if ( !strcmp ( meth_str.c_str(), "arithmetic" ) ) 284 set_method ( ARITHMETIC ); 285 else { 286 if ( !strcmp ( meth_str.c_str(), "geometric" ) ) 287 set_method ( GEOMETRIC ); 288 else if ( !strcmp ( meth_str.c_str(), "lognormal" ) ) { 289 set_method ( LOGNORMAL ); 290 set.lookupValue ( "beta", beta ); 291 } 292 } 293 string dbg_file; 294 if ( UI::get ( dbg_file, set, "dbg_file" ) ) 295 set_debug_file ( dbg_file ); 296 //validate() - not used 297 } 298 299 void validate() { 300 it_assert ( eSmp._w().length() > 0, "Empty support, use set_support()." ); 301 it_assert ( dim == eSmp._samples() ( 0 ).length(), "Support points and rv are not compatible!" ); 302 it_assert ( isnamed(), "mergers must be named" ); 303 } 304 //!@} 300 305 }; 301 UIREGISTER(merger_base); 302 303 class merger_mix : public merger_base 304 { 305 protected: 306 //!Internal mixture of EF models 307 MixEF Mix; 308 //!Number of components in a mixture 309 int Ncoms; 310 //! coefficient of resampling [0,1] 311 double effss_coef; 312 //! stop after niter iterations 313 int stop_niter; 314 315 //! default value for Ncoms 316 static const int DFLT_Ncoms; 317 //! default value for efss_coef; 318 static const double DFLT_effss_coef; 319 320 public: 321 //!\name Constructors 322 //!@{ 323 merger_mix () {}; 324 merger_mix (const Array<mpdf*> &S,bool own=false) {set_sources (S,own);}; 325 //! Set sources and prepare all internal structures 326 void set_sources (const Array<mpdf*> &S, bool own) { 327 merger_base::set_sources (S,own); 328 Nsources = S.length(); 329 } 330 //! Set internal parameters used in approximation 331 void set_parameters (int Ncoms0 = DFLT_Ncoms, double effss_coef0 = DFLT_effss_coef) { 332 Ncoms = Ncoms0; 333 effss_coef = effss_coef0; 334 } 335 //!@} 336 337 //! \name Mathematical operations 338 //!@{ 339 340 //!Merge values using mixture approximation 341 void merge (); 342 343 //! sample from the approximating mixture 344 vec sample () const { return Mix.posterior().sample();} 345 //! loglikelihood computed on mixture models 346 double evallog (const vec &dt) const { 347 vec dtf = ones (dt.length() + 1); 348 dtf.set_subvector (0, dt); 349 return Mix.logpred (dtf); 350 } 351 //!@} 352 353 //!\name Access functions 354 //!@{ 306 UIREGISTER ( merger_base ); 307 308 class merger_mix : public merger_base { 309 protected: 310 //!Internal mixture of EF models 311 MixEF Mix; 312 //!Number of components in a mixture 313 int Ncoms; 314 //! coefficient of resampling [0,1] 315 double effss_coef; 316 //! stop after niter iterations 317 int stop_niter; 318 319 //! default value for Ncoms 320 static const int DFLT_Ncoms; 321 //! default value for efss_coef; 322 static const double DFLT_effss_coef; 323 324 public: 325 //!\name Constructors 326 //!@{ 327 merger_mix () {}; 328 merger_mix ( const Array<mpdf*> &S, bool own = false ) { 329 set_sources ( S, own ); 330 }; 331 //! Set sources and prepare all internal structures 332 void set_sources ( const Array<mpdf*> &S, bool own ) { 333 merger_base::set_sources ( S, own ); 334 Nsources = S.length(); 335 } 336 //! Set internal parameters used in approximation 337 void set_parameters ( int Ncoms0 = DFLT_Ncoms, double effss_coef0 = DFLT_effss_coef ) { 338 Ncoms = Ncoms0; 339 effss_coef = effss_coef0; 340 } 341 //!@} 342 343 //! \name Mathematical operations 344 //!@{ 345 346 //!Merge values using mixture approximation 347 void merge (); 348 349 //! sample from the approximating mixture 350 vec sample () const { 351 return Mix.posterior().sample(); 352 } 353 //! loglikelihood computed on mixture models 354 double evallog ( const vec &dt ) const { 355 vec dtf = ones ( dt.length() + 1 ); 356 dtf.set_subvector ( 0, dt ); 357 return Mix.logpred ( dtf ); 358 } 359 //!@} 360 361 //!\name Access functions 362 //!@{ 355 363 //! Access function 356 MixEF& _Mix() {return Mix;} 357 //! Access function 358 emix* proposal() {emix* tmp = Mix.epredictor(); tmp->set_rv (rv); return tmp;} 359 //! from_settings 360 void from_setting(const Setting& set){ 361 merger_base::from_setting(set); 362 set.lookupValue("ncoms",Ncoms); 363 set.lookupValue("effss_coef",effss_coef); 364 set.lookupValue("stop_niter",stop_niter); 365 } 366 367 //! @} 364 MixEF& _Mix() { 365 return Mix; 366 } 367 //! Access function 368 emix* proposal() { 369 emix* tmp = Mix.epredictor(); 370 tmp->set_rv ( rv ); 371 return tmp; 372 } 373 //! from_settings 374 void from_setting ( const Setting& set ) { 375 merger_base::from_setting ( set ); 376 set.lookupValue ( "ncoms", Ncoms ); 377 set.lookupValue ( "effss_coef", effss_coef ); 378 set.lookupValue ( "stop_niter", stop_niter ); 379 } 380 381 //! @} 368 382 369 383 }; 370 UIREGISTER (merger_mix);384 UIREGISTER ( merger_mix ); 371 385 372 386 }