source: tol/tol_pkg/MhCnstrLinRegArima/_MhCnstrLinRegArima.tol @ ea1b10f

1941-docker-image-to-testdevel
Last change on this file since ea1b10f was ea1b10f, checked in by Víctor de Buen <vdebuen@…>, 17 years ago

Making standard package

git-svn-id: ​https://www.tol-project.org/svn/tolp/trunk@1655 be4846ae-f051-483a-831f-b64e7d08527f

  • Property mode set to 100644
File size: 15.7 KB
Line 
1/////////////////////////////////////////////////////////////////////////////
2// FILE: _mhCnstrLinRegArima.tol
3/////////////////////////////////////////////////////////////////////////////
4
5
6NameBlock MhCnstrLinRegArima = [[
7Text _.autodoc.description = "Metropolis-Hastings "
8"simulation of a linear regression with ARIMA noise and linear inequality "
9"constraints:\n"
10"\n"
11"\n  Y = X*b + z"
12"\n  A*b <= a"
13"\n  Ar(B)*Dif(B):z = Ma(B):e"
14"\n  e ~ N(0, s^2)"
15"\n\n"
16"The tarjet of this package is just to serve as example and test for "
17"some constrained Metropolis-Hastings simulation methods and related "
18"functions as Gelman diagnosis.\n"
19"For more details see mhCnstrLinRegArima.pdf (Sorry only spanish doc).";
20
21Text _.autodoc.keywords = "MCMC,Markov,Bayesian,Metropolis,Hastings,"
22  "linear,regression,ARIMA,inequality,constraints,polytope";
23
24//////////////////////////////////////////////////////////////////////////////
25Class @Simulator
26//////////////////////////////////////////////////////////////////////////////
27{
28  ////////////////////////////////////////////////////////////////////////////
29  //Definition members
30  ////////////////////////////////////////////////////////////////////////////
31  VMatrix _.Y;       //Output matrix
32  VMatrix _.X;       //Input matrix
33  VMatrix _.A;       //Coefficients of inequation
34  VMatrix _.a;       //Border of inequation
35  Real    _.s2;      //Residuals variance
36  Polyn   _.ar;      //Autoregressive polynomial
37  Polyn   _.ma;      //Moving average polynomial
38  Polyn   _.dif;     //Difference and deterministic structure
39  NameBlock _.armaL; //ARMA filter
40
41  ////////////////////////////////////////////////////////////////////////////
42  //Auxiliar members
43  ////////////////////////////////////////////////////////////////////////////
44  //Data length
45  Real _.m = 0;
46  //Number of variables
47  Real _.n = 0;
48  //Number of inequations
49  Real _.r = 0;
50  //Residuals standard deviation
51  Real _.s = ?;
52  //The expected best ratio of candidates aceptation
53  Real _.acceptRatioTarget=?;
54  //Diagonal matrix with square root of inverse of sum of squares of each row
55  //of _.A used to calculate distances to the polytope _.A*b <= _.a
56  VMatrix _.DAi = Rand(0,0,0,0);
57  //Current number of tried candidates
58  Real _.tryNumber = 0;
59  //Current number of accepted candidates
60  Real _.acceptNumber = 0;
61  //Current ratio of candidates aceptation (_.acceptNumber / _.tryNumber)
62  Real _.acceptRatio = 0;
63  //Last accepted candidate
64  VMatrix _.b = Rand(0,0,0,0);
65  //Current distance from _.b to polytope A*b<=a
66  Real _.distance = ?;
67  //Current ratio of hyperspheric candidate region with center in _.b
68  Real _.ratio = ?;
69  //Candidate density of last accepted candidate
70  Real _.log.Q = -1/0;
71  //Target density of last accepted candidate
72  Real _.log.P = -1/0;
73  //Maximum environment ratio
74  Real _.g = ?;
75
76  ////////////////////////////////////////////////////////////////////////////
77  //Configuration parameters
78  ////////////////////////////////////////////////////////////////////////////
79  //Initial value of maximum environment ratio
80  Real _.gInitial = 0.01;
81  //Tuner factor for _.g that will be divided or multipled for this number
82  //in order to get the target accept ratio
83  Real _.gFactor = 1.1;
84  //Valid interval for accept ratio will be defined as
85  //  _.acceptRatioTarget*_.acceptRangeFactor <=
86  //  _.acceptNumber / _.tryNumber <=
87  //  _.acceptRatioTarget*_.acceptRangeFactor
88  Real _.acceptRangeFactor = 1.10;
89  //Maximum number of tries before accept a candidate
90  Real _.maxIter = 10000;
91
92  ////////////////////////////////////////////////////////////////////////////
93  //Creates an instance of @Simulator
94  Static @Simulator New(
95    VMatrix Y,      //Output matrix
96    VMatrix X,      //Input matrix
97    VMatrix A,      //Coefficients of inequation
98    VMatrix a,      //Border of inequation
99    Real    s2,     //Residuals variance
100    Polyn   ar,     //Autoregressive polynomial
101    Polyn   ma,     //Moving average polynomial
102    Polyn   dif     //Difference and deterministic structure
103  )
104  ////////////////////////////////////////////////////////////////////////////
105  {
106    @Simulator aux =
107    [[
108      VMatrix _.Y = Y;
109      VMatrix _.X = X;
110      VMatrix _.A = A;
111      VMatrix _.a = a;
112      Real    _.s2 = s2;
113      Polyn   _.ar = ar;
114      Polyn   _.ma = ma;
115      Polyn   _.dif = dif;
116      Real    _.m = VRows(_.X);
117      Real    _.n = VColumns(_.X);
118      Real    _.r = VRows(_.A);
119      NameBlock _.armaL = ARMAProcess::FastCholeskiCovFactor(_.ar,_.ma,_.m)
120    ]]
121  };
122
123  ////////////////////////////////////////////////////////////////////////////
124  //Initializes a Markov chain
125  Real initialize(VMatrix b0)
126  ////////////////////////////////////////////////////////////////////////////
127  {
128    Text _MID = "@Simulator::initialize ";
129
130    Real ok = Case(
131    !_.m,
132    { WriteLn(_MID+"Invalid dimensions VRows(_.X)==0","E"); 0 },
133    !_.n,
134    { WriteLn(_MID+"Invalid dimensions VColumns(_.X)==0","E"); 0 },
135    VRows   (_.Y)!=_.m,
136    { WriteLn(_MID+"Invalid dimensions VRows(_.Y)!=VRows(_.X)","E"); 0 },
137    VColumns(_.Y)!=  1,
138    { WriteLn(_MID+"Invalid dimensions VColumns(_.Y)!=1","E"); 0 },
139    _.r & (VColumns(_.A)!=_.n),
140    { WriteLn(_MID+"Invalid dimensions VColumns(_.A)!=VColumns(_.X)","E"); 0 },
141    _.r & (VRows   (_.a)!=_.r),
142    { WriteLn(_MID+"Invalid dimensions VRows(_.a)!=VRows(_.A)","E"); 0 },
143    _.r & (VColumns(_.a)!=  1),
144    { WriteLn(_MID+"Invalid dimensions VColumns(_.a)!=1","E"); 0 },
145    VRows(b0)!= _.n,
146    { WriteLn(_MID+"Invalid dimensions VRows(_.b)!=VColumns(_.X)","E"); 0 },
147    VColumns(b0)!=  1,
148    { WriteLn(_MID+"Invalid dimensions VColumns(_.b)!=1","E"); 0 },
149    1==1,
150    { True });
151    If(!ok, False,
152    {
153      Real _.tryNumber := 0;
154      Real _.acceptNumber := 0;
155      Real _.acceptRatio := 0;
156      Real _.g := _.gInitial;
157      Real _.s := Sqrt(_.s2);
158      Real _.acceptRatioTarget := 0.234  + (0.5-0.234)*Exp(1-_.n);
159      VMatrix If(_.r,
160      _.DAi := Mat2VMat(SetCol(For(1,_.r,Real(Real j)
161      {
162        VMatrix Ai = SubRow(_.A,[[j]]);
163        VMatMoment(Ai,2)^(-0.5)
164      }))));
165      Real setStore(b0);
166      True
167    })
168  };
169
170  ////////////////////////////////////////////////////////////////////////////
171  //Stores an accepted candidate b_ and updates related members
172  Real setStore(VMatrix b_)
173  ////////////////////////////////////////////////////////////////////////////
174  {
175    VMatrix _.b := b_;
176    Real _.distance := If(!_.r, 1/0, eval.distance(_.b));
177    Real _.ratio := If(!_.r, 1/0, Min(_.g, _.distance));
178    Real _.log.Q := If(!_.r, 1, { -3*Log(_.ratio) });
179    Real _.log.P := eval.log.density(_.b);
180    True
181  };
182
183  ////////////////////////////////////////////////////////////////////////////
184  //Calculates distance from a point b_ to the polytope A*b<=a
185  Real eval.distance(VMatrix b_)
186  ////////////////////////////////////////////////////////////////////////////
187  {
188    If(!_.r,1/0,
189      VMatMin(Abs(_.A*b_-_.a) $* _.DAi))
190  };
191
192  ////////////////////////////////////////////////////////////////////////////
193  //Calculates the ratio of the spheric region of candidates for a given
194  //point b_
195  Real eval.ratio(VMatrix b_)
196  ////////////////////////////////////////////////////////////////////////////
197  {
198    If(!_.r,1/0,
199    {
200      Real dist = eval.distance(b_);
201      Min(_.g, dist)
202    })
203  };
204
205  ////////////////////////////////////////////////////////////////////////////
206  //Calculates candidate log of density Q(b0, b1).
207  //If there are no restrictions Q is symmetric, so the value itŽs indiferent
208  //In other case it is a uniform that depends just on position of b0 respect
209  //to the polytope A*b<=a
210  //
211  Real eval.candidate.log.density(VMatrix b0, VMatrix b1)
212  ////////////////////////////////////////////////////////////////////////////
213  {
214    If(!_.r, 1,
215    {
216      -3*Log(eval.ratio(b0))
217    })
218  };
219
220  Real _2pi = 2*Pi;
221
222  ////////////////////////////////////////////////////////////////////////////
223  //Generates a new candidate with
224  VMatrix new.candidate(Real void)
225  ////////////////////////////////////////////////////////////////////////////
226  {
227    Text _MID = "@Simulator::new.candidate ";
228    If(!_.r,
229    {
230      VMatrix u = Gaussian(_.n,1,0,_.s*_.g);
231      _.b + u           
232    },
233    {
234      Real h = _.ratio*(Rand(0,1)^(1/_.n));
235      VMatrix u = Gaussian(_.n,1,0,1);
236      VMatrix v = u/(VMatDat(MtMSqr(u),1,1)^0.5);
237      VMatrix w = v * h;
238      VMatrix c_ = _.b + w;
239      Real trace.all(Real void)
240      {
241        WriteLn("TRACE "+_MID+
242          "\n"<<Matrix VMat2Mat(Tra(_.b|c_|w))<<"\n"<<
243          "\t_.ratio="<< _.ratio<<
244          "\th="<< h<<
245          "\t||v||="<<Real(VMatDat(MtMSqr(v),1,1)^0.5)<<
246          "\t||w||="<<Real(VMatDat(MtMSqr(w),1,1)^0.5));
247        0
248      };
249    //Real trace.all(0);
250      c_
251    })
252  };
253
254  ////////////////////////////////////////////////////////////////////////////
255  //Applies difference polynomial to a matrix
256  VMatrix applyDif(VMatrix z)
257  ////////////////////////////////////////////////////////////////////////////
258  {
259    Real d = Degree(_.dif);
260    SubRow(DifEq(_.dif, z), Range(d+1,_.m, 1))
261  };
262
263  ////////////////////////////////////////////////////////////////////////////
264  //Filters a noise vector to get standarized residuals N(0,I)
265  VMatrix standarize(VMatrix z)
266  ////////////////////////////////////////////////////////////////////////////
267  {
268    _.armaL::filter(applyDif(z/_.s))
269  };
270
271  ////////////////////////////////////////////////////////////////////////////
272  //Evaluates logarithm of target density for a point b
273  Real eval.log.density(VMatrix b)
274  ////////////////////////////////////////////////////////////////////////////
275  {
276    VMatrix e = standarize(_.Y-_.X*b);
277    - 0.5 * VMatDat(MtMSqr(e),1,1)
278
279  };
280
281  ////////////////////////////////////////////////////////////////////////////
282  //Returns true if c matches all inequations A*c<=a
283  Real isFeasible(VMatrix c)
284  ////////////////////////////////////////////////////////////////////////////
285  {
286    If(!_.r, True, VMatMax(_.A*c-_.a)<=0)
287  };
288
289  ////////////////////////////////////////////////////////////////////////////
290  //Tries a new candidate and returns true if it is accepted
291  Real maxLikelihoodStep(Real maxIter)
292  ////////////////////////////////////////////////////////////////////////////
293  {
294    Text _MID = "@Simulator::maxLikelihoodStep ";
295    Real iter = 1;
296    Real advance = False;
297    While(iter<=maxIter,
298    {   
299      VMatrix c = new.candidate(0);
300      Real log.P.c = eval.log.density(c);
301      Real advance := log.P.c > _.log.P;
302      Real trace.all(Real void)
303      {
304        WriteLn("TRACE "+_MID+
305          "\t_.log.P=\t"<<_.log.P<<
306          "\tlog.P.c=\t"<<log.P.c<<
307          "\tadvance=\t"<<advance);
308         0
309      };
310    //Real trace.all(0);
311      If(advance, { setStore(c) });
312      Real iter := iter+1
313    });
314    iter
315  };
316
317  ////////////////////////////////////////////////////////////////////////////
318  //Tries a new candidate and returns true if it is accepted
319  Real try(Real checkFeasible)
320  ////////////////////////////////////////////////////////////////////////////
321  {
322    Text _MID = "@Simulator::try ";
323    Real _.tryNumber := _.tryNumber + 1;
324    VMatrix c = new.candidate(0);
325    Real feasible = If(!checkFeasible, True, isFeasible(c));
326    If(!feasible,
327    {
328      WriteLn(_MID+"Non feasible point","");
329      False
330    },
331    {
332      Real log.Q.c = eval.candidate.log.density(c,_.b);
333      Real log.P.c = eval.log.density(c);
334      Real log.w = Min(1,(log.P.c-_.log.P)+(_.log.Q-log.Q.c));
335      Real w = Exp(log.w);
336      Real r = Rand(0,1);
337      Real accept = r <= w;
338      Real _.acceptRatio := _.acceptNumber / _.tryNumber;
339      Real trace.all(Real void)
340      {
341        WriteLn("TRACE "+_MID+
342          "\n"<<Matrix VMat2Mat(Tra(_.b|c))<<"\n"<<
343          "\taccept=\t"<<accept<<
344          "\tacceptRatio=\t"<<_.acceptRatio<<If(!_.r,"",
345          "\t_.g=\t"<<_.g<<
346          "\t_.distance=\t"<<_.distance<<
347          "\t_.ratio=\t"<<_.ratio<<
348          "\t_.log.Q=\t"<<_.log.Q<<
349          "\tlog.Q.c=\t"<<log.Q.c)<<
350          "\t_.log.P=\t"<<_.log.P<<
351          "\tlog.P.c=\t"<<log.P.c<<
352          "\tw=\t"<<w);
353         0
354      };
355    //Real trace.all(0);
356      If(accept,
357      {
358        Real _.acceptNumber := _.acceptNumber + 1;
359        setStore(Copy(c))
360      });
361      Real mclra::tuner(0);
362      accept
363    })
364  };
365
366  ////////////////////////////////////////////////////////////////////////////
367  //Modifies _.g in order to _.acceptRatio goes closer than
368  //_.acceptRatioTarget
369  Real tuner(Real 0)
370  //////////////////////////////////////////////////////////////////////////
371  {
372    Case(
373    _.acceptRatio<_.acceptRatioTarget/_.acceptRangeFactor,
374    {
375      Real _.g := _.g/_.gFactor
376    },
377    _.acceptRatio>_.acceptRatioTarget*_.acceptRangeFactor,
378    {
379      Real _.g := _.g*_.gFactor
380    },
381    1==1,
382    {
383      _.g
384    });
385    Real trace.all(Real void)
386    {
387      WriteLn("["<<_.tryNumber+"]"+
388              "_.acceptRatio="<<_.acceptRatio+" "+
389              "_.g="<<_.g+" ");
390      0
391    };
392  //Real trace.all(0);
393    If(_.r,
394    {
395      Real _.ratio := Min(_.g, _.distance);
396      Real _.log.Q := -3*Log(_.ratio)
397    });
398    _.g
399  }
400 
401}
402
403/*
404//VBR: UNDER CONSTRUCTION
405////////////////////////////////////////////////////////////////////////////
406Class @Simulator.Std : @Simulator
407////////////////////////////////////////////////////////////////////////////
408{
409  Real _.sz;
410  VMatrix _.Dx;
411  VMatrix _.Dix;
412
413  //////////////////////////////////////////////////////////////////////////
414  Static @Simulator.Std New(@Simulator reg)
415  //////////////////////////////////////////////////////////////////////////
416  {
417    VMatrix Y = reg::applyDif(reg::_.Y);
418    VMatrix X = reg::applyDif(reg::_.X);
419    VMatrix A = reg::_.A;
420    VMatrix a = reg::_.a;
421    Real    s2 = reg::_.s2;
422    Polyn   ar = reg::_.ar;
423    Polyn   ma = reg::_.ma;
424    Polyn   dif = reg::_.dif;
425    Real    m = reg::_.m;
426    Real    n = reg::_.n;
427    Real    r = reg::_.r;
428
429    Real sz = Sqrt(s2);
430    Matrix dx = SetCol(For(1,n,Real(Real j)
431    {
432      VMatrix Xj = SubCol(X,[[j]]);
433      Sqrt(VMatDat(MtMSqr(Xj),1,1))
434    }));
435    Matrix dxi = RPow(dx,-1);
436    VMatrix Dx = Eye(n,n,0,Mat2VMat(dx));
437    VMatrix Dix = Eye(n,n,0,Mat2VMat(dxi));
438
439    @Simulator.Std aux =
440    [[
441      VMatrix _.Y = Y;
442      VMatrix _.X = X;
443      VMatrix _.A = A;
444      VMatrix _.a = a;
445      Real    _.s2 = 1;
446      Polyn   _.ar = ar;
447      Polyn   _.ma = ma;
448      Polyn   _.dif = 1;
449      NameBlock _.armaL = reg::_.armaL;
450      Real    _.m = m;
451      Real    _.n = n;
452      Real    _.r = r;
453      Real    _.sz = sz;
454      VMatrix _.Dx = Dx;
455      VMatrix _.Dix = Dix
456    ]]
457  };
458
459  //////////////////////////////////////////////////////////////////////////
460  VMatrix applyDif(VMatrix z)
461  //////////////////////////////////////////////////////////////////////////
462  {
463    z
464  };
465
466  ////////////////////////////////////////////////////////////////////////////
467  //Filters a noise vector to get standarized residuals N(0,I)
468  VMatrix standarize(VMatrix z)
469  ////////////////////////////////////////////////////////////////////////////
470  {
471    _.armaL::filter(z)
472  }
473
474}
475*/
476
477]];
478
479
480/*
481  ////////////////////////////////////////////////////////////////////////////
482  //Tries a new candidate and returns true if it is accepted
483  Real try.multiple(Real length)
484  ////////////////////////////////////////////////////////////////////////////
485  {
486    Text _MID = "@Simulator::try ";
487    Real _.tryNumber := _.tryNumber + 1;
488    Set c = For(1, length, new.candidate);
489       
490      Real log.Q.c = eval.candidate.log.density(c,_.b);
491      Real log.P.c = eval.log.density(c);
492      Real log.w = Min(1,(log.P.c-_.log.P)+(_.log.Q-log.Q.c));
493      Real w = Exp(log.w);
494      Real r = Rand(0,1);
495      Real accept = r <= w;
496
497      If(accept,
498      {
499        Real _.acceptNumber := _.acceptNumber + 1;
500        setStore(c)
501      });
502      accept
503    })
504  };
505
506/* */
507
Note: See TracBrowser for help on using the repository browser.