source: tol/tol_pkg/MhCnstrLinRegArima/_MhCnstrLinRegArima.tol @ 7faafd4e

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

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

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