gambit is hosted by Hepforge, IPPP Durham
GAMBIT  v1.5.0-2191-ga4742ac
a Global And Modular Bsm Inference Tool
doublelogflatjoin.cpp
Go to the documentation of this file.
1 // GAMBIT: Global and Modular BSM Inference Tool
2 // *********************************************
22 
24 
25 #include <cmath>
26 
27 namespace Gambit
28 {
29  namespace Priors
30  {
31 
33  DoubleLogFlatJoin::DoubleLogFlatJoin(const std::vector<std::string>& param, const Options& options)
34  : BasePrior(param, 1)
35  , myparameter(param_names[0])
36  , lower(0.0)
37  , flat_start(0.0)
38  , flat_end(0.0)
39  , upper(0.0)
40  , C(0.0)
41  , P01(0.0)
42  , P12(0.0)
43  , P23(0.0)
44  , no_lower_log(false)
45  , no_upper_log(false)
46  {
47  // Only valid for 1D parameter transformation
48  if (param.size()!=1)
49  {
50  scan_err << "Invalid input to DoubleLogFlatJoin prior (in constructor): " << endl
51  << "Input parameters must be a vector of size 1! (has size=" << param.size() << ")" << scan_end;
52  }
53 
54  // Read the entries we need from the options
55  if ( options.hasKey("ranges") )
56  {
57  // Shortcut option assignment method
58  std::vector<double> ranges = options.getValue<std::vector<double>>("ranges");
59  if(ranges.size()!=4)
60  {
61  scan_err << "Invalid input to DoubleLogFlatJoin prior (in constructor): value " << endl
62  << "of 'ranges' key must be a vector of length 4 (length was "<<ranges.size()<<"), " << endl
63  << "where the entries specify 'lower', 'flat_start', 'flat_end', and 'upper'." << scan_end;
64  }
65  lower = ranges[0];
66  flat_start = ranges[1];
67  flat_end = ranges[2];
68  upper = ranges[3];
69  }
70  else if ( options.hasKey("range") )
71  {
72  // Semi-shortcut option assignment method
73  std::vector<double> range = options.getValue<std::vector<double>>("range");
74  if(range.size()!=2)
75  {
76  scan_err << "Invalid input to DoubleLogFlatJoin prior (in constructor): value " << endl
77  << "of 'range' key must be a vector of length 2 (length was "<<range.size()<<"), " << endl
78  << "where the entries specify 'lower', and 'upper'." << scan_end;
79  }
80  lower = range[0];
81  upper = range[1];
82  flat_start = get_option("flat_start", options);
83  flat_end = get_option("flat_end", options);
84  }
85  else
86  {
87  lower = get_option("lower", options);
88  flat_start = get_option("flat_start", options);
89  flat_end = get_option("flat_end", options);
90  upper = get_option("upper", options);
91  }
92 
93  // Make sure ordering of constraints makes sense
94  if( (lower < flat_start)
95  and (flat_start < 0)
96  and (0 < flat_end)
97  and (flat_end < upper) )
98  {
99  // No problem
100  }
101  else if( (lower==flat_start)
102  and (flat_start <= flat_end)
103  and (0 < flat_end)
104  and (flat_end < upper) )
105  {
106  // Lower log portion is collapsed; flat portion may now be fully above zero, and is allowed to collapse.
107  no_lower_log = true;
108  }
109  else if( (lower < flat_start)
110  and (flat_start < 0)
111  and (flat_start <= flat_end)
112  and (flat_end==upper) )
113  {
114  // Upper log portion is collapsed; flat portion may now be fully below zero, and is allowed to collapse.
115  no_upper_log = true;
116  }
117  else if( (lower==flat_start)
118  and (flat_start < flat_end)
119  and (flat_end==upper) )
120  {
121  // Both log portions collapsed; flat portion may now be anywhere, but is not allowed to collapse.
122  no_upper_log = true;
123  }
124  else
125  {
126  scan_err << "Inconsistent values of options for DoubleLogFlatJoin prior detected! " << endl
127  << "The required ordering is: lower <= flat_start < 0 < flat_end <= upper."<< endl
128  << "Values received were: ["<<lower<<", "<<flat_start<<", "<<flat_end<<", "<<upper<<"]." << endl
129  << "(if either log portion is collapsed then the flat portion is permitted to move from covering zero as appropriate)" << scan_end;
130  }
131 
132  // Useful quantities:
133  double x0 = lower;
134  double x1 = flat_start;
135  double x2 = flat_end;
136  double x3 = upper;
137  double Nlower = 0;
138  double Nupper = 0;
139  double Nflat = x2-x1;
140  if(not no_lower_log) Nlower = x1*log(fabs(x1/x0));
141  if(not no_upper_log) Nupper = x2*log(fabs(x3/x2));
142  C = 1. / ( Nflat + Nlower + Nupper ); // Normalization factor
143  P01 = C * Nlower; // Prob. of x in (x0,x1)
144  P12 = C * Nflat; // Prob. of x in (x1,x2)
145  P23 = C * Nupper; // Prob. of x in (x2,x3)
146 
147  }
148 
149 
151  double DoubleLogFlatJoin::get_option(const str& name, const Options& options)
152  {
153  if (options.hasKey(name))
154  {
155  return options.getValue<double>(name);
156  }
157  else
158  {
159  scan_err << "Missing option " << name <<" (or 'ranges') for DoubleLogFlatJoin prior. Must specify " << endl
160  << "'lower', 'flat_start', 'flat_end', and 'upper', or else all of these at once in a vector labelled 'ranges'." << scan_end;
161  }
162  return 0;
163  }
164 
165 
167  void DoubleLogFlatJoin::transform(const std::vector <double> &unitpars, std::unordered_map <std::string, double> &output) const
168  {
169  // Only valid for 1D parameter transformation
170  if (unitpars.size()!=1)
171  {
172  scan_err << "Invalid input to DoubleLogFlatJoin prior (in 'transform'): Input parameters must be a vector of size 1! (has size=" << unitpars.size() << ")" << scan_end;
173  }
174 
175  double x = 0; // output (result)
176  double r = unitpars[0]; // input unit cube parameter
177  double x0 = lower;
178  double x1 = flat_start;
179  double x2 = flat_end;
180  //double x3 = upper; // apparantly don't need this
181 
182  // Based on Anders' python implementation.
183 
184  // Transformation:
185  if( r <= P01 )
186  {
187  x = x0 * exp(r/(x1*C));
188  }
189  else if( (r > P01) and (r < (P01+P12)) )
190  {
191  x = x1 + (r-P01)/C;
192  }
193  else if( (r > (P01+P12)) and (r <= (P01+P12+P23)) )
194  {
195  x = x2*exp( (r-(P01+P12))/(x2*C) );
196  }
197  else
198  {
199  scan_err << "Problem transforming r-value for DoubleLogFlatJoin (received "<<r<<")!" << scan_end;
200  }
201 
202  output[myparameter] = x;
203  }
204 
205  std::vector<double> DoubleLogFlatJoin::inverse_transform(const std::unordered_map<std::string, double> &physical) const
206  {
207  const double p = physical.at(myparameter);
208 
209  if (p >= lower && p < flat_start)
210  {
211  // log prior from lower to flat_start
212  double u01 = std::log(p / lower) / std::log(flat_start / lower);
213  return {u01 * P01};
214  }
215  else if (p >= flat_start && p < flat_end)
216  {
217  // flat prior from flat_start to flat_end
218  double u01 = (p - flat_start) / (flat_end - flat_start);
219  return {P01 + u01 * P12};
220  }
221  else if (p>= flat_end && p < upper)
222  {
223  // log prior from flat_end to upper
224  double u01 = std::log(p / flat_end) / std::log(upper / flat_end);
225  return {P01 + P12 + u01 * P23};
226  }
227  else
228  {
229  scan_err << "no inverse transformation for double_log_flat_join - outside range"
230  << scan_end;
231  return {}; // silence compiler warning (reaches end non-void function)
232  }
233  }
234 
235  double DoubleLogFlatJoin::operator()(const std::vector<double> &vec) const
236  {
237  double r = 0;
238  double x = vec[0];
239  double x0 = lower;
240  double x1 = flat_start;
241  double x2 = flat_end;
242  double x3 = upper;
243  if( x <= x0 )
244  {
245  r = 0.;
246  }
247  else if( (x > x0) and (x <= x1) )
248  {
249  r = 1./x * x1 * C;
250  }
251  else if( (x > x1) and (x <= x2) )
252  {
253  r = C;
254  }
255  else if( (x > x2) and (x <= x3) )
256  {
257  r = 1./x * x2 * C;
258  }
259  else if (x > x3)
260  {
261  r = 0;
262  }
263  else
264  {
265  scan_err << "Problem computing prior density for DoubleLogFlatJoin (received x="<<x<<")!" << scan_end;
266  }
267 
268  return r;
269  }
270 
271  }
272 }
double lower
Variables controlling the prior range etc.
std::vector< double > inverse_transform(const std::unordered_map< std::string, double > &) const override
Transform from parameter back to unit hypercube.
Abstract base class for priors.
Definition: base_prior.hpp:40
double get_option(const str &, const Options &)
Try to get options for double log-flat joined prior.
const std::string & myparameter
Name of the parameter that this prior is supposed to transform.
bool hasKey(const args &... keys) const
Getters for key/value pairs (which is all the options node should contain)
TYPE getValue(const args &... keys) const
bool no_lower_log
Flags to register if special cases are active.
START_MODEL x2
Definition: demo.hpp:42
#define scan_err
Defined to macros to output errors in the form: scan_err << "error" << scan_end; scan_warn << "warnin...
DoubleLogFlatJoin(const std::vector< std::string > &param, const Options &)
Constructor defined in doublelogflatjoin.cpp.
std::string str
Shorthand for a standard string.
Definition: Analysis.hpp:35
START_MODEL dNur_CMB r
START_MODEL x3
Definition: demo.hpp:42
double operator()(const std::vector< double > &vec) const
Probability density function.
#define scan_end
std::vector< T > vec(std::vector< T > vector)
Definition: daFunk.hpp:142
TODO: see if we can use this one:
Definition: Analysis.hpp:33
A small wrapper object for &#39;options&#39; nodes.
Prior function made up of two log priors (positive and negative branch) joined across zero by a flat ...
void transform(const std::vector< double > &unitpars, std::unordered_map< std::string, double > &output) const
Transformation from unit interval to the double log + flat join (inverse prior transform) ...