#include "emix.h" namespace bdm { void emix_base::validate () { epdf::validate(); bdm_assert ( no_coms() > 0, "There has to be at least one component." ); bdm_assert ( no_coms() == w.length(), "It is obligatory to define weights of all the components." ); double sum_w = sum ( w ); bdm_assert ( sum_w != 0, "There has to be a component with non-zero weight." ); w = w / sum_w; dim = component ( 0 )->dimension(); RV rv_tmp = component ( 0 )->_rv() ; bool isnamed = component( 0 )->isnamed(); for ( int i = 1; i < no_coms(); i++ ) { bdm_assert ( dim == ( component ( i )->dimension() ), "Component sizes do not match!" ); isnamed &= component(i)->isnamed() & component(i)->_rv().equal(rv_tmp); } if (isnamed) epdf::set_rv ( rv_tmp); } vec emix_base::sample() const { //Sample which component vec cumDist = cumsum ( w ); double u0; #pragma omp critical u0 = UniRNG.sample(); int i = 0; while ( ( cumDist ( i ) < u0 ) && ( i < ( w.length() - 1 ) ) ) { i++; } return component ( i )->sample(); } vec emix_base::mean() const { int i; vec mu = zeros ( dim ); for ( i = 0; i < w.length(); i++ ) { mu += w ( i ) * component ( i )->mean(); } return mu; } vec emix_base::variance() const { //non-central moment vec mom2 = zeros ( dim ); vec mom1 = zeros ( dim ); for ( int i = 0; i < w.length(); i++ ) { vec vi=component( i )->variance(); vec mi=component ( i )->mean(); mom2 += w ( i ) * ( vi + pow ( mi, 2 ) ); mom1 += w(i) * mi; } //central moment return mom2 - pow ( mom1, 2 ); } double emix_base::evallog ( const vec &val ) const { int i; double sum = 0.0; for ( i = 0; i < w.length(); i++ ) { sum += w ( i ) * exp ( component ( i )->evallog ( val ) ); } if ( sum == 0.0 ) { sum = std::numeric_limits::epsilon(); } double tmp = log ( sum ); bdm_assert_debug ( std::isfinite ( tmp ), "Infinite" ); return tmp; } vec emix_base::evallog_mat ( const mat &Val ) const { vec x = zeros ( Val.cols() ); for ( int i = 0; i < w.length(); i++ ) { x += w ( i ) * exp ( component( i )->evallog_mat ( Val ) ); } return log ( x ); }; mat emix_base::evallog_coms ( const mat &Val ) const { mat X ( w.length(), Val.cols() ); for ( int i = 0; i < w.length(); i++ ) { X.set_row ( i, w ( i ) *exp ( component( i )->evallog_mat ( Val ) ) ); } return X; } shared_ptr emix_base::marginal ( const RV &rv ) const { emix *tmp = new emix(); shared_ptr narrow ( tmp ); marginal ( rv, *tmp ); return narrow; } void emix_base::marginal ( const RV &rv, emix &target ) const { bdm_assert ( isnamed(), "rvs are not assigned" ); Array > Cn ( no_coms() ); for ( int i = 0; i < no_coms(); i++ ) { Cn ( i ) = component ( i )->marginal ( rv ); } target._w() = w; target._Coms() = Cn; target.validate(); } shared_ptr emix_base::condition ( const RV &rv ) const { bdm_assert ( isnamed(), "rvs are not assigned" ); mratio *tmp = new mratio ( this, rv ); return shared_ptr ( tmp ); } void emix::from_setting ( const Setting &set ) { emix_base::from_setting(set); UI::get ( Coms, set, "pdfs", UI::compulsory ); UI::get ( w, set, "weights", UI::compulsory ); } void emix::to_setting (Setting &set) const { emix_base::to_setting(set); UI::save(Coms, set, "pdfs"); UI::save( w, set, "weights"); } void emix::validate () { emix_base::validate(); dim = Coms ( 0 )->dimension(); } double mprod::evallogcond ( const vec &val, const vec &cond ) { int i; double res = 0.0; for ( i = pdfs.length() - 1; i >= 0; i-- ) { /* if ( pdfs(i)->_rvc().count() >0) { pdfs ( i )->condition ( dls ( i )->get_cond ( val,cond ) ); } // add logarithms res += epdfs ( i )->evallog ( dls ( i )->pushdown ( val ) );*/ res += pdfs ( i )->evallogcond ( dls ( i )->pushdown ( val ), dls ( i )->get_cond ( val, cond ) ); } return res; } vec mprod::evallogcond_mat ( const mat &Dt, const vec &cond ) { vec tmp ( Dt.cols() ); for ( int i = 0; i < Dt.cols(); i++ ) { tmp ( i ) = evallogcond ( Dt.get_col ( i ), cond ); } return tmp; } vec mprod::evallogcond_mat ( const Array &Dt, const vec &cond ) { vec tmp ( Dt.length() ); for ( int i = 0; i < Dt.length(); i++ ) { tmp ( i ) = evallogcond ( Dt ( i ), cond ); } return tmp; } void mprod::set_elements ( const Array > &mFacs ) { pdfs = mFacs; dls.set_size ( mFacs.length() ); rv = get_composite_rv ( pdfs, true ); dim = rv._dsize(); for ( int i = 0; i < pdfs.length(); i++ ) { RV rvx = pdfs ( i )->_rvc().subt ( rv ); rvc.add ( rvx ); // add rv to common rvc } dimc = rvc._dsize(); // rv and rvc established = > we can link them with pdfs for ( int i = 0; i < pdfs.length(); i++ ) { dls ( i ) = new datalink_m2m; dls ( i )->set_connection ( pdfs ( i )->_rv(), pdfs ( i )->_rvc(), _rv(), _rvc() ); } } void mprod::from_setting ( const Setting &set ) { pdf::from_setting(set); Array > temp_array; UI::get ( temp_array, set, "pdfs", UI::compulsory ); set_elements ( temp_array ); } void mprod::to_setting (Setting &set) const { pdf::to_setting(set); UI::save( pdfs, set, "pdfs"); } void mmix::validate() { pdf::validate(); bdm_assert ( Coms.length() > 0, "There has to be at least one component." ); bdm_assert ( Coms.length() == w.length(), "It is obligatory to define weights of all the components." ); double sum_w = sum ( w ); bdm_assert ( sum_w != 0, "There has to be a component with non-zero weight." ); w = w / sum_w; dim = Coms ( 0 )->dimension(); dimc = Coms ( 0 )->dimensionc(); RV rv_tmp = Coms ( 0 )->_rv(); RV rvc_tmp = Coms ( 0 )->_rvc(); bool isnamed = Coms ( 0 )->isnamed(); for ( int i = 1; i < Coms.length(); i++ ) { bdm_assert ( dim == ( Coms ( i )->dimension() ), "Component sizes do not match!" ); bdm_assert ( dimc >= ( Coms ( i )->dimensionc() ), "Component sizes do not match!" ); isnamed &= Coms(i)->isnamed() & Coms(i)->_rv().equal(rv_tmp) & Coms(i)->_rvc().equal(rvc_tmp); } if (isnamed) { pdf::set_rv ( rv_tmp ); pdf::set_rvc ( rvc_tmp ); } } void mmix::from_setting ( const Setting &set ) { pdf::from_setting(set); UI::get ( Coms, set, "pdfs", UI::compulsory ); if ( !UI::get ( w, set, "weights", UI::optional ) ) { int len = Coms.length(); w.set_length ( len ); w = 1.0 / len; } } void mmix::to_setting (Setting &set) const { pdf::to_setting(set); UI::save( Coms, set, "pdfs"); UI::save( w, set, "weights"); } vec mmix::samplecond ( const vec &cond ) { //Sample which component vec cumDist = cumsum ( w ); double u0; #pragma omp critical u0 = UniRNG.sample(); int i = 0; while ( ( cumDist ( i ) < u0 ) && ( i < ( w.length() - 1 ) ) ) { i++; } return Coms ( i )->samplecond ( cond ); } vec eprod_base::mean() const { vec tmp ( dim ); for ( int i = 0; i < no_factors(); i++ ) { vec pom = factor( i )->mean(); dls ( i )->pushup ( tmp, pom ); } return tmp; } vec eprod_base::variance() const { vec tmp ( dim ); //second moment for ( int i = 0; i < no_factors(); i++ ) { vec pom = factor ( i )->variance(); dls ( i )->pushup ( tmp, pom ); // } return tmp; } vec eprod_base::sample() const { vec tmp ( dim ); for ( int i = 0; i < no_factors(); i++ ) { vec pom = factor ( i )->sample(); dls ( i )->pushup ( tmp, pom ); } return tmp; } double eprod_base::evallog ( const vec &val ) const { double tmp = 0; for ( int i = 0; i < no_factors(); i++ ) { tmp += factor ( i )->evallog ( dls ( i )->pushdown ( val ) ); } //bdm_assert_debug ( std::isfinite ( tmp ), "Infinite" ); return tmp; } }