aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
chi2.cpp
Go to the documentation of this file.
1 /**
2  *
3  * Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4  * info_at_agrum_dot_org
5  *
6  * This library is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 
22 /**
23  * @file
24  * @brief The class that represents the chi2 distribution
25  *
26  * The Chi2 class allows to easily compute critical values for the Chi2
27  * distribution.
28  *
29  * @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
30  */
31 
32 #include <agrum/tools/core/math/chi2.h>
33 
34 #ifndef DOXYGEN_SHOULD_SKIP_THIS
35 
36 // constants used by Gary Perlman for his code for computing chi2 critical
37 // values
38 # define GUM_Z_MAX 6.0 // maximum meaningful z value
39 # define GUM_CHI_EPSILON 0.000001 // accuracy of critchi approximation
40 # define GUM_CHI_MAX 99999.0 // maximum chi square value
41 # define GUM_LOG_SQRT_PI 0.5723649429247000870717135 // std::log (std::sqrt (pi))
42 # define GUM_I_SQRT_PI 0.5641895835477562869480795 // 1 / std::sqrt (pi)
43 # define GUM_BIGX 20.0 // max value to represent exp (x)
44 # define _gum_ex(x) (((x) < -GUM_BIGX) ? 0.0 : std::exp(x))
45 
46 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
47 
48 // include the inlined functions if necessary
49 #ifdef GUM_NO_INLINE
50 # include <agrum/tools/core/math/chi2_inl.h>
51 #endif /* GUM_NO_INLINE */
52 
53 namespace gum {
54 
55  // default constructor
58  _confidence_proba_(confidence_proba) { // for debugging purposes
60  }
61 
62  // destructor
63  Chi2::~Chi2() {
64  // for debugging purposes
66  }
67 
68  // computes the probability of normal z value (used by the cache)
69  double Chi2::_probaZValue_(double z) {
70  double y, x, w;
71 
72  if (z == 0.0)
73  x = 0.0;
74  else {
75  y = 0.5 * std::fabs(z);
76 
77  if (y >= (GUM_Z_MAX * 0.5))
78  x = 1.0;
79  else if (y < 1.0) {
80  w = y * y;
81  x = ((((((((0.000124818987 * w - 0.001075204047) * w + 0.005198775019) * w - 0.019198292004)
82  * w
83  + 0.059054035642)
84  * w
85  - 0.151968751364)
86  * w
87  + 0.319152932694)
88  * w
89  - 0.531923007300)
90  * w
91  + 0.797884560593)
92  * y * 2.0;
93  } else {
94  y -= 2.0;
95  x = (((((((((((((-0.000045255659 * y + 0.000152529290) * y - 0.000019538132) * y
96  - 0.000676904986)
97  * y
98  + 0.001390604284)
99  * y
100  - 0.000794620820)
101  * y
102  - 0.002034254874)
103  * y
104  + 0.006549791214)
105  * y
106  - 0.010557625006)
107  * y
108  + 0.011630447319)
109  * y
110  - 0.009279453341)
111  * y
112  + 0.005353579108)
113  * y
114  - 0.002141268741)
115  * y
116  + 0.000535310849)
117  * y
118  + 0.999936657524;
119  }
120  }
121 
122  return (z > 0.0 ? ((x + 1.0) * 0.5) : ((1.0 - x) * 0.5));
123  }
124 
125  // computes the probability of chi2 value (used by the cache)
126  double Chi2::probaChi2(double x, Size df) {
127  double a, y = 0, s;
128  double e, c, z;
129  int even; /* true if df is an even number */
130 
131  if ((x <= 0.0) || (df < 1)) return (1.0);
132 
133  a = 0.5 * x;
134 
135  even = (2 * (df / 2)) == df;
136 
137  if (df > 1) y = _gum_ex(-a);
138 
139  s = (even ? y : (2.0 * _probaZValue_(-std::sqrt(x))));
140 
141  if (df > 2) {
142  x = 0.5 * (df - 1.0);
143  z = (even ? 1.0 : 0.5);
144 
145  if (a > GUM_BIGX) {
146  e = (even ? 0.0 : GUM_LOG_SQRT_PI);
147  c = std::log(a);
148 
149  while (z <= x) {
150  e = std::log(z) + e;
151  s += _gum_ex(c * z - a - e);
152  z += 1.0;
153  }
154 
155  return (s);
156  } else {
157  e = (even ? 1.0 : (GUM_I_SQRT_PI / std::sqrt(a)));
158  c = 0.0;
159 
160  while (z <= x) {
161  e = e * (a / z);
162  c = c + e;
163  z += 1.0;
164  }
165 
166  return (c * y + s);
167  }
168  } else
169  return (s);
170  }
171 
172  // computes the critical value of a given chi2 test (used by the cache)
173  double Chi2::_criticalValue_(double proba, Size df) {
174  double minchisq = 0.0;
175  double maxchisq = GUM_CHI_MAX;
176  double chisqval;
177 
178  if (proba <= 0.0)
179  return (maxchisq);
180  else if (proba >= 1.0)
181  return (0.0);
182 
183  chisqval = df / std::sqrt(proba); /* fair first value */
184 
185  while (maxchisq - minchisq > GUM_CHI_EPSILON) {
186  if (probaChi2(chisqval, df) < proba)
187  maxchisq = chisqval;
188  else
189  minchisq = chisqval;
190 
191  chisqval = (maxchisq + minchisq) * 0.5;
192  }
193 
194  return (chisqval);
195  }
196 
197 } /* namespace gum */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643