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

Revision 384, 7.1 kB (checked in by mido, 15 years ago)

possibly broken?

  • 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
19namespace bdm
20{
21using std::string;
22
23//!Merging methods
24enum MERGER_METHOD {ARITHMETIC = 1, GEOMETRIC = 2, LOGNORMAL = 3};
25
26/*!
27@brief Base class for general combination of pdfs on discrete support
28
29Mixtures of Gaussian densities are used internally. Switching to other densities should be trivial.
30
31The merged pdfs are expected to be of the form:
32 \f[ f(x_i|y_i),  i=1..n \f]
33where the resulting merger is a density on \f$ \cup [x_i,y_i] \f$ .
34Note that all variables will be joined.
35
36As a result of this feature, each source must be extended to common support
37\f[ f(z_i|y_i,x_i) f(x_i|y_i) f(y_i)  i=1..n \f]
38where \f$ z_i \f$ accumulate variables that were not in the original source.
39These extensions are calculated on-the-fly.
40
41However, 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$.
42For merging of more general cases, use offsprings merger_mix and merger_grid.
43*/
44
45class 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                //!Prior on the log-normal merging model
62                double beta;
63
64                //! Projection to empirical density (could also be piece-wise linear)
65                eEmp eSmp;
66
67                //! debug or not debug
68                bool DBG;
69
70                //! debugging file
71                it_file* dbg_file;
72        public:
73                //! \name Constructors
74                //! @{
75
76                //!Empty constructor
77                merger_base () : compositepdf() {DBG=false;dbg_file=NULL;};
78                //!Constructor from sources
79                merger_base (const Array<mpdf*> &S) {set_sources (S);};
80                //! Function setting the main internal structures
81                void set_sources (const Array<mpdf*> &Sources) {
82                        compositepdf::set_elements (Sources);
83                        //set sizes
84                        dls.set_size (Sources.length());
85                        rvzs.set_size (Sources.length());
86                        zdls.set_size (Sources.length());
87
88                        rv = getrv (/* checkoverlap = */ false);
89                        RV rvc; setrvc (rv, rvc);  // Extend rv by rvc!
90                        // join rv and rvc - see descriprion
91                        rv.add (rvc);
92                        // get dimension
93                        dim = rv._dsize();
94
95                        // create links between sources and common rv
96                        RV xytmp;
97                        for (int i = 0;i < mpdfs.length();i++) {
98                                //Establich connection between mpdfs and merger
99                                dls (i) = new datalink_m2e;
100                                dls (i)->set_connection (mpdfs (i)->_rv(), mpdfs (i)->_rvc(), rv);
101
102                                // find out what is missing in each mpdf
103                                xytmp = mpdfs (i)->_rv();
104                                xytmp.add (mpdfs (i)->_rvc());
105                                // z_i = common_rv-xy
106                                rvzs (i) = rv.subt (xytmp);
107                                //establish connection between extension (z_i|x,y)s and common rv
108                                zdls (i) = new datalink_m2e; zdls (i)->set_connection (rvzs (i), xytmp, rv) ;
109                        };
110                }
111                //! set debug file
112                void set_debug_file (const string fname) { 
113                        if (DBG) delete dbg_file; 
114                        dbg_file = new it_file (fname); 
115                        if (dbg_file) DBG = true;
116                }
117                //! Set internal parameters used in approximation
118                void set_method (MERGER_METHOD MTH, double beta0=0.0) {
119                        METHOD = MTH; 
120                        beta = beta0;
121                }
122                //! Set support points from a pdf by drawing N samples
123                void set_support(const epdf &overall, int N){
124                        it_assert_debug ( rv.equal ( overall._rv() ),"Incompatible parameter overall!" );
125                        eSmp.set_statistics(&overall,N);
126                        Npoints=N;
127                }
128               
129                //! Destructor
130                virtual ~merger_base() {
131                        for (int i = 0; i < Nsources; i++) {
132                                delete dls (i);
133                                delete zdls (i);
134                        }
135                        if (DBG) delete dbg_file;
136                };
137                //!@}
138               
139                //! \name Mathematical operations
140                //!@{
141               
142                //!Merge given sources in given points
143                void merge () {
144                        if (eSmp._w().length() ==0) {it_error("Empty support points use set_support" );}
145                        //check if sources overlap:
146                        bool OK = true;
147                        for (int i = 0;i < mpdfs.length(); i++) {
148                                OK &= (rvzs (i)._dsize() == 0); // z_i is empty
149                                OK &= (mpdfs (i)->_rvc()._dsize() == 0); // y_i is empty
150                        }
151
152                        if (OK) {
153                                mat lW = zeros (mpdfs.length(), eSmp._w().length());
154
155                                vec emptyvec (0);
156                                for (int i = 0; i < mpdfs.length(); i++) {
157                                        for (int j = 0; j < eSmp._w().length(); j++) {
158                                                lW (i, j) = mpdfs (i)->evallogcond (eSmp._samples() (j), emptyvec);
159                                        }
160                                }
161
162                                vec wtmp = exp (merge_points (lW));
163                                //renormalize
164                                eSmp._w() = wtmp / sum (wtmp);
165                        } else {
166                                it_error("Sources are not compatible - use merger_mix");
167                        }
168                        ;
169                };
170
171
172                //! Merge log-likelihood values in points using method specified by parameter METHOD
173                vec merge_points (mat &lW);
174               
175               
176                //! sample from merged density
177//! weight w is a
178                vec mean() const {
179                        const Vec<double> &w = eSmp._w();
180                        const Array<vec> &S = eSmp._samples();
181                        vec tmp = zeros (dim);
182                        for (int i = 0; i < Npoints; i++) {
183                                tmp += w (i) * S (i);
184                        }
185                        return tmp;
186                }
187                mat covariance() const {
188                        const vec &w = eSmp._w();
189                        const Array<vec> &S = eSmp._samples();
190
191                        vec mea = mean();
192
193                        cout << sum (w) << "," << w*w << endl;
194
195                        mat Tmp = zeros (dim, dim);
196                        for (int i = 0; i < Npoints; i++) {
197                                Tmp += w (i) * outer_product (S (i), S (i));
198                        }
199                        return Tmp -outer_product (mea, mea);
200                }
201                vec variance() const {
202                        const vec &w = eSmp._w();
203                        const Array<vec> &S = eSmp._samples();
204
205                        vec tmp = zeros (dim);
206                        for (int i = 0; i < Nsources; i++) {
207                                tmp += w (i) * pow (S (i), 2);
208                        }
209                        return tmp -pow (mean(), 2);
210                }
211                //!@}
212
213                //! \name Access to attributes
214                //! @{
215
216                //! Access function
217                eEmp& _Smp() {return eSmp;}
218               
219                //!@}
220};
221
222class merger_mix : public merger_base
223{
224        protected:
225                //!Internal mixture of EF models
226                MixEF Mix;
227                //!Number of components in a mixture
228                int Ncoms;
229                //! coefficient of resampling
230                double effss_coef;
231
232        public:
233                //!\name Constructors
234                //!@{
235                merger_mix () {};
236                merger_mix (const Array<mpdf*> &S) {set_sources(S);};
237                //! Set sources and prepare all internal structures
238                void set_sources (const Array<mpdf*> &S) {
239                        merger_base::set_sources(S);
240                        Nsources = S.length();
241                }
242                //! Set internal parameters used in approximation
243                void set_parameters (int Ncoms0=10, double effss_coef0 = 0.5) {
244                        Ncoms = Ncoms0;
245                        effss_coef = effss_coef0;
246                }
247                //!@}
248               
249                //! \name Mathematical operations
250                //!@{
251               
252                //!Merge values using mixture approximation
253                void merge ();
254
255                //! sample from the approximating mixture
256                vec sample () const { return Mix.posterior().sample();}
257                //! loglikelihood computed on mixture models
258                double evallog (const vec &dt) const {
259                        vec dtf = ones (dt.length() + 1);
260                        dtf.set_subvector (0, dt);
261                        return Mix.logpred (dtf);
262                }
263                //!@}
264
265                //!\name Access functions
266                //!@{
267//! Access function
268                MixEF& _Mix() {return Mix;}
269                //! Access function
270                emix* proposal() {emix* tmp = Mix.epredictor(); tmp->set_rv (rv); return tmp;}
271        //! @}
272               
273};
274
275}
276
277#endif // MER_H
Note: See TracBrowser for help on using the browser.