root/library/bdm/stat/exp_family.cpp @ 477

Revision 477, 7.5 kB (checked in by mido, 15 years ago)

panove, vite, jak jsem peclivej na upravu kodu.. snad se vam bude libit:) konfigurace je v souboru /system/astylerc

  • Property svn:eol-style set to native
Line 
1#include <math.h>
2
3#include <itpp/base/bessel.h>
4#include "exp_family.h"
5
6namespace bdm {
7
8Uniform_RNG UniRNG;
9Normal_RNG NorRNG;
10Gamma_RNG GamRNG;
11
12using std::cout;
13
14void BMEF::bayes ( const vec &dt ) {
15        this->bayes ( dt, 1.0 );
16};
17
18vec egiw::sample() const {
19        it_warning ( "Function not implemented" );
20        return vec_1 ( 0.0 );
21}
22
23double egiw::evallog_nn ( const vec &val ) const {
24        int vend = val.length() - 1;
25
26        if ( dimx == 1 ) { //same as the following, just quicker.
27                double r = val ( vend ); //last entry!
28                if ( r < 0 ) return -inf;
29                vec Psi ( nPsi + dimx );
30                Psi ( 0 ) = -1.0;
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 );
41                fsqmat iR ( dimx );
42                R.inv ( iR );
43
44                return -0.5* ( nu*ldetR + trace ( iR.to_mat() *Tmp.T() *V.to_mat() *Tmp ) );
45        }
46}
47
48double egiw::lognc() const {
49        const vec& D = V._D();
50
51        double m = nu - nPsi - dimx - 1;
52#define log2  0.693147180559945286226763983
53#define logpi 1.144729885849400163877476189
54#define log2pi 1.83787706640935
55#define Inf std::numeric_limits<double>::infinity()
56
57        double nkG = 0.5 * dimx * ( -nPsi * log2pi + sum ( log ( D ( dimx, D.length() - 1 ) ) ) );
58        // temporary for lgamma in Wishart
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;
69}
70
71vec egiw::est_theta() const {
72        if ( dimx == 1 ) {
73                const mat &L = V._L();
74                int end = L.rows() - 1;
75
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" );
83                return 0;
84        }
85}
86
87ldmat egiw::est_theta_cov() const {
88        if ( dimx == 1 ) {
89                const mat &L = V._L();
90                const vec &D = V._D();
91                int end = D.length() - 1;
92
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" );
100                return 0;
101        }
102
103}
104
105vec egiw::mean() const {
106
107        if ( dimx == 1 ) {
108                const vec &D = V._D();
109                int end = D.length() - 1;
110
111                vec m ( dim );
112                m.set_subvector ( 0, est_theta() );
113                m ( end ) = D ( 0 ) / ( nu - nPsi - 2 * dimx - 2 );
114                return m;
115        } else {
116                mat M;
117                mat R;
118                mean_mat ( M, R );
119                return cvectorize ( concat_vertical ( M, R ) );
120        }
121
122}
123
124vec egiw::variance() const {
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 );
136                return var;
137        } else {
138                it_error ( "not implemented" );
139                return vec ( 0 );
140        }
141}
142
143void egiw::mean_mat ( mat &M, mat&R ) const {
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 ) );
150
151        // set mean value
152        mat Lpsi = L ( dimx, end, 0, dimx - 1 );
153        M = iLsub * Lpsi;
154        R = ldR.to_mat()  ;
155}
156
157vec egamma::sample() const {
158        vec smp ( dim );
159        int i;
160
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() );
166                }
167#pragma omp critical
168                smp ( i ) = GamRNG();
169        }
170
171        return smp;
172}
173
174// mat egamma::sample ( int N ) const {
175//      mat Smp ( rv.count(),N );
176//      int i,j;
177//
178//      for ( i=0; i<rv.count(); i++ ) {
179//              GamRNG.setup ( alpha ( i ),beta ( i ) );
180//
181//              for ( j=0; j<N; j++ ) {
182//                      Smp ( i,j ) = GamRNG();
183//              }
184//      }
185//
186//      return Smp;
187// }
188
189double egamma::evallog ( const vec &val ) const {
190        double res = 0.0; //the rest will be added
191        int i;
192
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" );
200        return tmp;
201}
202
203double egamma::lognc() const {
204        double res = 0.0; //will be added
205        int i;
206
207        for ( i = 0; i < dim; i++ ) {
208                res += lgamma ( alpha ( i ) ) - alpha ( i ) * std::log ( beta ( i ) ) ;
209        }
210
211        return res;
212}
213
214void mgamma::set_parameters ( double k0, const vec &beta0 ) {
215        k = k0;
216        iepdf->set_parameters ( k * ones ( beta0.length() ), beta0 );
217        dimc = e()->dimension();
218}
219
220ivec eEmp::resample ( RESAMPLING_METHOD method ) {
221        ivec ind = zeros_i ( n );
222        ivec N_babies = zeros_i ( n );
223        vec cumDist = cumsum ( w );
224        vec u ( n );
225        int i, j, parent;
226        double u0;
227
228        switch ( method ) {
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" );
257        }
258
259        // U is now full
260        j = 0;
261
262        for ( i = 0; i < n; i++ ) {
263                while ( u ( i ) > cumDist ( j ) ) j++;
264
265                N_babies ( j ) ++;
266        }
267        // We have assigned new babies for each Particle
268        // Now, we fill the resulting index such that:
269        // * particles with at least one baby should not move *
270        // This assures that reassignment can be done inplace;
271
272        // find the first parent;
273        parent = 0;
274        while ( N_babies ( parent ) == 0 ) parent++;
275
276        // Build index
277        for ( i = 0; i < n; i++ ) {
278                if ( N_babies ( i ) > 0 ) {
279                        ind ( i ) = i;
280                        N_babies ( i ) --; //this index was now replicated;
281                } else {
282                        // test if the parent has been fully replicated
283                        // if yes, find the next one
284                        while ( ( N_babies ( parent ) == 0 ) || ( N_babies ( parent ) == 1 && parent > i ) ) parent++;
285
286                        // Replicate parent
287                        ind ( i ) = parent;
288
289                        N_babies ( parent ) --; //this index was now replicated;
290                }
291
292        }
293
294        // copy the internals according to ind
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;
300        }
301
302        return ind;
303}
304
305void eEmp::set_statistics ( const vec &w0, const epdf* epdf0 ) {
306        //it_assert_debug(rv==epdf0->rv(),"Wrong epdf0");
307        dim = epdf0->dimension();
308        w = w0;
309        w /= sum ( w0 );//renormalize
310        n = w.length();
311        samples.set_size ( n );
312        dim = epdf0->dimension();
313
314        for ( int i = 0; i < n; i++ ) {
315                samples ( i ) = epdf0->sample();
316        }
317}
318
319void eEmp::set_samples ( const epdf* epdf0 ) {
320        //it_assert_debug(rv==epdf0->rv(),"Wrong epdf0");
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
329void migamma_ref::from_setting ( const Setting &set ) {
330        vec ref;
331        UI::get ( ref, set, "ref" , UI::compulsory );
332        set_parameters ( set["k"], ref, set["l"] );
333}
334
335void 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 );
340}
341
342};
Note: See TracBrowser for help on using the browser.