GLAMERDOC++
Gravitational Lensing Code Library
Loading...
Searching...
No Matches
slicer.h
1//
2// slicer.h
3// GLAMER
4//
5// Created by Robert Benton Metcalf on 15/05/2020.
6//
7
8#ifndef slicer_h
9#define slicer_h
10
11#include <cmath>
20template <typename V,typename L,typename R>
21class Slicer{
22public:
23 Slicer(int Dim
24 ,const V &scale
25 ,int kmax = 10
26 ):
27 w(scale),Kmax(kmax),dim(Dim),n_evals(0){
28 assert(scale.size()>=Dim);
29 }
30
32 void run(L &lnprob
33 ,std::vector<V> &chain
34 ,V xo
35 ,R &ran
36 ,int step_type
37 ,bool verbose=false
38 ){
39 if(lnprob(xo) <= -1.0e20){
40 std::cerr << "Slicer: Initial point has 0 probability" << std::endl;
41 throw std::runtime_error("bad point");
42 }
43 n_evals=0;
44 int n = chain.size();
45 int k = 0;
46 chain[0] = xo;
47 if(verbose) std::cout << std::endl;
48 for(int i=1;i<n;++i){
49 chain[i] = chain[i-1];
50 if(step_type) step_double(chain[i],lnprob,k,ran);
51 else step_out(chain[i],lnprob,k,ran);
52 k = (k+1)%dim;
53 if(verbose) std::cout << i << " " << n_evals << " " << chain[i] << std::endl;
54 }
55 }
56
58 size_t number_evaluations(){ return n_evals;}
59
60private:
61 V xl,xr,ll,rr,lshrink,rshrink,x_new;
62 const V w;
63 const int Kmax;
64 const int dim;
65
66 size_t n_evals;
67
68 void step_double(V &x,L &lnprob,int i,R &ran){
69 //double y = prob(x) * ran();
70 double y = lnprob(x) + log(ran()); ++n_evals;
71
72 assert(!std::isnan(y));
73 // find range
74 int k = Kmax;
75
76 xl = x; xl[i] = x[i] - w[i] * ran();;
77 xr = x; xr[i] = xl[i] + w[i];
78
79 double lprob = lnprob(xl); ++n_evals;
80 double rprob = lnprob(xr); ++n_evals;
81
82 while( k > 0 && ( y < lprob || y < rprob )){
83 double u = ran();
84 if(u<0.5){
85 xl[i] = 2*xl[i] - xr[i];
86 lprob = lnprob(xl); ++n_evals;
87 }else{
88 xr[i] = 2*xr[i] - xl[i];
89 rprob = lnprob(xr); ++n_evals;
90 }
91 --k;
92 }
93
94 // shrink the range
95 lshrink = xl;
96 rshrink = xr;
97 x_new = x;
98
99 for(;;){
100 x_new[i] = lshrink[i] + ran()*( rshrink[i] - lshrink[i] );
101 ++n_evals;
102 if( y < lnprob(x_new) && accept(y,x,x_new,i,lnprob)) break;
103 if(x_new[i] < x[i]){
104 lshrink[i] = x_new[i];
105 }else{
106 rshrink[i] = x_new[i];
107 }
108 }
109
110 swap(x,x_new);
111 }
112
113 void step_out(V &x,L &lnprob,int i,R &ran){
114 //double y = prob(x) * ran();
115
116 double y = lnprob(x) + log(ran()); ++n_evals;
117
118 // find range
119 xl = xr = x;
120
121 xl[i] = x[i] - w[i] * ran();;
122 xr[i] = xl[i] + w[i];
123 int j = floor(Kmax*ran());
124 int k = Kmax - 1 - j;
125
126 while( j > 0 && y < lnprob(xl)){
127 ++n_evals;
128 xl[i] = xl[i] - w[i];
129 --j;
130 }
131 while( k > 0 && y < lnprob(xr)){
132 ++n_evals;
133 xr[i] = xr[i] + w[i];
134 --k;
135 }
136
137 // shrink the range
138 lshrink = xl;
139 rshrink = xr;
140 x_new = x;
141
142 for(;;){
143 x_new[i] = lshrink[i] + ran()*( rshrink[i] - lshrink[i] );
144 ++n_evals;
145 if( y < lnprob(x_new) ) break;
146 if(x_new[i] < x[i]){
147 lshrink[i] = x_new[i];
148 }else{
149 rshrink[i] = x_new[i];
150 }
151 }
152
153 swap(x,x_new);
154 }
155
156 bool accept(const double y,V &xo,V &x1,int i,L &lnprob){
157 ll = xl;
158 rr = xr;
159 bool D = false;
160
161 double lprob = lnprob(ll); ++n_evals;
162 double rprob = lnprob(rr); ++n_evals;
163
164 while( (rr[i] - ll[i]) > 1.1 * w[i]){
165 double m = (ll[i]+rr[i])/2;
166 if( (xo[i] < m)*(x1[i] >= m) ||
167 (xo[i] >= m)*(x1[i] < m) ) D = true;
168
169 if(x_new[i] < m ){
170 rr[i] = m;
171 rprob = lnprob(rr); ++n_evals;
172 }else{
173 ll[i] = m;
174 lprob = lnprob(ll); ++n_evals;
175 }
176 if(D && y >= lprob && y >= rprob ) return false;
177 }
178 return true;
179 }
180};
181
182template <typename V,typename L,typename R>
183class SimpleMH_MCMC{
184private:
185
186 const V w;
187 int dim;
188
189 size_t n_evals;
190 std::vector<int> active;
191
192public:
193 SimpleMH_MCMC(int Dim
194 ,const V &scale
195 ,std::vector<int> active_parameters = {}
196 ):
197 w(scale),dim(Dim),n_evals(0),active(active_parameters)
198 {
199
200 if(active.size() == 0){
201 for(int i ; i<dim ; ++i) active.push_back(i);
202 }else{
203 if(dim > active.size()) dim = active.size();
204 }
205
206 assert(scale.size() >= dim);
207 assert(active.size() >= dim);
208 }
209
211 void run(L &lnprob
212 ,std::vector<V> &chain
213 ,V xo
214 ,R &ran
215 ,bool cyclic = true
216 ,bool verbose=false
217 ){
218
219 double lnp = lnprob(xo);
220 n_evals=0;
221 int n = chain.size();
222 chain[0] = xo;
223 if(verbose) std::cout << std::endl;
224
225 int k=0;
226 for(int i=1;i<n;++i){
227 chain[i] = chain[i-1];
228
229 if(cyclic){
230 int j = active[k];
231 chain[i][j] += w[j]*ran.gauss();
232 k = (k+1) % dim;
233 }else{
234 for(int j=0;j<dim;++j){
235 k = active[k];
236 chain[i][j] += w[j]*ran.gauss();
237 }
238 }
239 double lnp2 = lnprob(chain[i]);
240
241 if( lnp2 <= lnp && exp(lnp2 - lnp) < ran() ){
242 chain[i] = chain[i-1];
243 }else{
244 lnp = lnp2;
245 ++n_evals;
246 }
247 if(verbose) std::cout << i << " " << n_evals << " " << chain[i] << std::endl;
248 }
249 }
250
253 void runAux(L &lnprob
254 ,std::vector<V> &chain
255 ,V xo
256 ,R &ran
257 ,bool cyclic = true
258 ,bool verbose=false
259 ){
260
261 double lnp = lnprob(xo);
262 n_evals=0;
263 int n = chain.size();
264 chain[0] = xo;
265 lnprob.aux_update(ran,lnp);
266
267 if(verbose) std::cout << std::endl;
268
269 int k=0;
270 for(int i=1;i<n;++i){
271 chain[i] = chain[i-1];
272
273 if(i%dim == 0){
274 lnprob.aux_update(ran,lnp);
275 }else{
276 if(cyclic){
277 chain[i][k] += w[k]*ran.gauss();
278 k = (k+1) % dim;
279 }else{
280 for(int j=0;j<dim;++j){
281 chain[i][j] += w[j]*ran.gauss();
282 }
283 }
284 double lnp2 = lnprob(chain[i]);
285
286 if( lnp2 <= lnp && exp(lnp2 - lnp) < ran() ){
287 chain[i] = chain[i-1];
288 }else{
289 lnp = lnp2;
290 ++n_evals;
291 }
292 }
293 if(verbose) std::cout << i << " " << n_evals << " " << chain[i] << std::endl;
294 }
295 }
296
298 size_t number_evaluations(){ return n_evals;}
299
300};
301#endif /* slicer_h */
Definition slicer.h:21
void run(L &lnprob, std::vector< V > &chain, V xo, R &ran, int step_type, bool verbose=false)
run the MC chain
Definition slicer.h:32
Slicer(int Dim, const V &scale, int kmax=10)
Definition slicer.h:23
size_t number_evaluations()
returns the number of evaluations of the posterior during the last run
Definition slicer.h:58