root/library/bdm/stat/merger.h @ 1187

Revision 1114, 10.4 kB (checked in by smidl, 14 years ago)

compilation fixes

  • Property svn:eol-style set to native
Line 
1/*!
2  \file
3  \brief Mergers for combination of pdfs
4  \author Vaclav Smidl.
5
6  -----------------------------------
7  BDM++ - C++ library for Bayesian Decision Making under Uncertainty
8
9  Using IT++ for numerical operations
10  -----------------------------------
11*/
12
13#ifndef MERGER_H
14#define MERGER_H
15
16
17#include "../estim/mixtures.h"
18#include "discrete.h"
19
20namespace bdm {
21using std::string;
22
23//!Merging methods
24enum MERGER_METHOD {ARITHMETIC = 1, GEOMETRIC = 2, LOGNORMAL = 3};
25
26/*!  \brief Abstract common class for mergers
27
28Merging is defined as a combination of information from \c source pdfs into a single pdf called the \c merger.
29
30\f[
31f_{merged}(x) \leftarrow {f_1(x),f_2(x),f_3(x)}
32\f]
33
34In the basic form, the random variables of all source pdfs must be identical, e.g. \f$ x \f$ from the example above.
35
36Extension of the merger to a more demanding scenarios with fragmental sources is available in offspring bdm::merger_mix.
37
38This abstract class defines only the interface to using merger: operation merge(), and operation merger() which returns the result.
39*/
40class MergerBase: public root{
41        public:         
42                //! weights of the sources -- no restrictions
43                vec w;
44                //! source pdfs -- conditioning allowed
45                Array<shared_ptr<epdf> > sources;
46                //! merge
47                virtual void merge() NOT_IMPLEMENTED_VOID;
48                //!
49                //! check if all epdfs are on the same support
50                virtual void set_sources(const Array<shared_ptr<pdf> > &A) {
51                        int n=A.length();
52                       
53                        bdm_assert(n>0,"merger has no sources to merge");
54                        // check if weights are ok
55                        if (w.length()!=n) {
56                                w = ones(n)/n;
57                        }
58                       
59                        // check compatibility of sources -- no types are needed
60                        int dim0 = A(0)->dimension();
61                        for (int i=0; i<n; i++){
62                                const epdf *si=dynamic_cast<const epdf*>(A(i).get());
63                                if (si){
64                                        sources(i) = shared_ptr<epdf>(const_cast<epdf*>(si));
65                                }
66                                bdm_assert(sources(i)->dimension()==dim0, "Merger: Incompatible dimensions of sources");
67                                if (sources(i)->isnamed()){
68                                        //check if rv match
69                                }
70                        }
71                }
72                //! return the result of merging
73                virtual const epdf& merger()=0;
74};
75
76//! \brief Merger into normal density, max entropy approximator for 2 moments (mean+variance)
77template<class sq_T>
78class ENormMerger: public MergerBase{
79        protected:
80                //!internal epdf
81                enorm<sq_T> iepdf;
82        public:
83                ENormMerger():method(GEOMETRIC){};
84                MERGER_METHOD method;
85                void merge(){
86                        int n = sources.length();
87                        int dim = sources(0)->dimension();
88                        sq_T Var(zeros(dim));
89                        vec mea=zeros(dim);
90                        // go through all sources
91                        epdf * si;
92                        for (int i=0; i<n; i++){
93                                si = dynamic_cast<epdf*>(sources(i).get());  // transform pdf into epdf
94
95                                if (!si) {bdm_error("Can't merger this type of pdf: " + sources(i)->to_string());}
96                               
97                                sq_T Ci = si->covariance();
98                                sq_T wCi = Ci; wCi*=w(i);
99                                vec mi = si->mean();
100                                switch (method) {
101                                        case ARITHMETIC:{
102                                                Var += wCi;
103                                                Var.opupdt(mi,w(i)); // + mean * mean'
104                                                mea += w(i)*mi;
105                                                break;
106                                        }
107                                        case GEOMETRIC:{
108                                                Var += wCi;
109                                                sq_T iCi;
110                                                Ci.inv(iCi);
111                                                mea += iCi.to_mat()*w(i)*mi;
112                                                break;
113                                        }
114                                        default:
115                                                bdm_error("Method not implemneted");
116                                }
117                        }
118                        // post pocessing
119                        switch (method) {
120                                case ARITHMETIC:
121                                        iepdf._R()=Var;
122                                        iepdf._R().opupdt(mea,-1.0); // Var - mean * mean'
123                                        iepdf._mu()=mea;
124                                        break;
125                                case GEOMETRIC:
126                                        iepdf._R()=Var;
127                                        iepdf._mu() = Var.to_mat()*mea; // mean=sqrt(Var)*mea
128                                        break;
129                                default:
130                                        bdm_error("Method not implemneted");
131                        }
132                }
133                //! access function
134                const epdf& merger(){return iepdf;}
135};
136
137/*!
138@brief Base class (interface) for for general combination of pdfs on discrete support
139
140Mixtures of Gaussian densities are used internally. Switching to other densities should be trivial.
141
142The merged pdfs are expected to be of the form:
143 \f[ f(x_i|y_i),  i=1..n \f]
144where the resulting merger is a density on \f$ \cup [x_i,y_i] \f$ .
145Note that all variables will be joined.
146
147As a result of this feature, each source must be extended to common support
148\f[ f(z_i|y_i,x_i) f(x_i|y_i) f(y_i)  i=1..n \f]
149where \f$ z_i \f$ accumulate variables that were not in the original source.
150These extensions are calculated on-the-fly.
151
152However, these operations can not be performed in general. Hence, this class merges only sources on common support, \f$ y_i={}, z_i={}, \forall i \f$.
153For merging of more general cases, use offsprings merger_mix and merger_grid.
154
155\TODO use sources for extensions
156*/
157class MergerDiscrete : public MergerBase {
158protected:
159        //! partial sources
160        Array<shared_ptr< pdf > > part_sources;
161       
162    //! Data link for each pdf in pdfs
163    Array<datalink_m2e*> dls;
164
165    //! Array of rvs that are not modelled by pdfs at all, \f$ z_i \f$
166    Array<RV> rvzs;
167
168    //! Data Links for extension \f$ f(z_i|x_i,y_i) \f$
169    Array<datalink_m2e*> zdls;
170
171    //! number of support points
172    int Npoints;
173
174    //! number of sources
175    int Nsources;
176
177    //! switch of the methoh used for merging
178    MERGER_METHOD METHOD;
179    //! Default for METHOD
180    static const MERGER_METHOD DFLT_METHOD;
181
182    //!Prior on the log-normal merging model
183    double beta;
184    //! default for beta
185    static const double DFLT_beta;
186
187    //! Projection to empirical density (could also be piece-wise linear)
188    eEmp eSmp;
189
190    //! debug or not debug
191    bool DBG;
192
193    //! debugging file
194    it_file* dbg_file;
195public:
196    //! \name Constructors
197    //! @{
198
199    //! Default constructor
200    MergerDiscrete () : Npoints ( 0 ), Nsources ( 0 ), DBG ( false ), dbg_file ( 0 ) {
201    }
202
203    //!Constructor from sources
204    MergerDiscrete ( const Array<shared_ptr<pdf> > &S );
205
206    //! Function setting the main internal structures
207    void set_sources ( const Array<shared_ptr<pdf> > &PartSources );
208
209    //! Set support points from rectangular grid
210    void set_support ( rectangular_support &Sup );
211
212    //! Set support points from dicrete grid
213    void set_support ( discrete_support &Sup ) {
214        Npoints = Sup.points();
215        eSmp.set_parameters ( Sup._Spoints() );
216        eSmp.validate();
217    }
218
219
220    //! set debug file
221    void set_debug_file ( const string fname ) {
222        if ( DBG ) delete dbg_file;
223        dbg_file = new it_file ( fname );
224        DBG = ( dbg_file != 0 );
225    }
226
227    //! Set internal parameters used in approximation
228    void set_method ( MERGER_METHOD MTH = GEOMETRIC, double beta0 = 1.2 ) {
229        METHOD = MTH;
230        beta = beta0;
231    }
232    //! Set support points from a pdf by drawing N samples
233    void set_support ( const epdf &overall, int N ) {
234        eSmp.set_statistics ( overall, N );
235        Npoints = N;
236    }
237
238    //! Destructor
239    virtual ~MergerDiscrete() {
240        for ( int i = 0; i < Nsources; i++ ) {
241            delete dls ( i );
242            delete zdls ( i );
243        }
244        if ( DBG ) delete dbg_file;
245    };
246    //!@}
247
248    //! \name Mathematical operations
249    //!@{
250
251    //!Merge given sources in given points
252    void merge ();
253
254    //! Merge log-likelihood values in points using method specified by parameter METHOD
255    vec merge_points ( mat &lW );
256
257  //!@}
258
259    //! \name Access to attributes
260    //! @{
261
262    //! Access function
263    eEmp& _Smp() {
264        return eSmp;
265    }
266
267        eEmp & merger() {return eSmp;}
268
269    /*! Create object from the following structure
270
271    \code
272    class = 'MergerDiscrete';
273    method = 'arithmetic' or 'geometric' or 'lognormal';   % name of the model used for merging
274    --- compulsory only for lognormal merging model ---
275    beta = x;                                              % scalar prior on the log-normal merging model
276    --- optional fields ---
277    dbg_file = '...';                                      % name of the file to store debug informations
278    --- inherited fields ---
279    bdm::MergerBase::from_setting
280    \endcode
281    */
282    void from_setting ( const Setting& set );
283
284    void to_setting  (Setting  &set) const ;
285
286    void validate() ;
287    //!@}
288};
289UIREGISTER ( MergerDiscrete );
290SHAREDPTR ( MergerDiscrete );
291
292//! \brief Merger using importance sampling with mixture proposal density
293class merger_mix : public MergerDiscrete {
294protected:
295    //!Internal mixture of EF models
296    MixEF Mix;
297    //!Number of components in a mixture
298    int Ncoms;
299    //! coefficient of resampling [0,1]
300    double effss_coef;
301    //! stop after niter iterations
302    int stop_niter;
303
304    //! default value for Ncoms
305    static const int DFLT_Ncoms;
306    //! default value for efss_coef;
307    static const double DFLT_effss_coef;
308
309public:
310    //!\name Constructors
311    //!@{
312    merger_mix () : Ncoms ( 0 ), effss_coef ( 0 ), stop_niter ( 0 ) { }
313
314    merger_mix ( const Array<shared_ptr<pdf> > &S ) :
315        Ncoms ( 0 ), effss_coef ( 0 ), stop_niter ( 0 ) {
316        set_sources ( S );
317    }
318
319    //! Set sources and prepare all internal structures
320    void set_sources ( const Array<shared_ptr<pdf> > &S ) {
321        MergerDiscrete::set_sources ( S );
322        //Nsources = S.length();
323    }
324
325    //! Set internal parameters used in approximation
326    void set_parameters ( int Ncoms0 = DFLT_Ncoms, double effss_coef0 = DFLT_effss_coef ) {
327        Ncoms = Ncoms0;
328        effss_coef = effss_coef0;
329    }
330    //!@}
331
332    //! \name Mathematical operations
333    //!@{
334
335    //!Merge values using mixture approximation
336    void merge ();
337
338    //! sample from the approximating mixture
339    vec sample () const {
340        return Mix.posterior().sample();
341    }
342    //! loglikelihood computed on mixture models
343    double evallog ( const vec &yt ) const {
344        vec dtf = ones ( yt.length() + 1 );
345        dtf.set_subvector ( 0, yt );
346        return Mix.logpred ( dtf, vec(0) );
347    }
348    //!@}
349
350    //!\name Access functions
351    //!@{
352//! Access function
353    MixEF& _Mix() {
354        return Mix;
355    }
356    //! Access function
357    emix* proposal() {
358        emix* tmp = Mix.epredictor();
359        tmp->set_rv ( merger()._rv() );
360        return tmp;
361    }
362    /*! Create object from the following structure
363
364    \code
365    class = 'merger_mix';
366    --- optional fields ---
367    ncoms = [];        % number of components in a mixture
368    effss_coef = [];   % coefficient of resampling from interval [0,1]
369    stop_niter = [];   % number of interations
370    --- inherited fields ---
371    bdm::merger_base::from_setting
372    \endcode   
373    If the optional fields are not given, they will be filled as follows:
374    \code
375    ncoms = 10;       
376    effss_coef = 0.9; 
377    stop_niter = 10; 
378    \endcode
379
380    */
381    void from_setting ( const Setting& set );
382
383    void to_setting  (Setting  &set) const;
384    void validate();
385
386//      const emix &merger(){return *Mpred;}
387    //! @}
388};
389UIREGISTER ( merger_mix );
390SHAREDPTR ( merger_mix );
391
392}
393
394#endif // MER_H
Note: See TracBrowser for help on using the browser.