aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
chi2.cpp
Go to the documentation of this file.
1 /**
2  *
3  * Copyright 2005-2020 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
42  0.5723649429247000870717135 // std::log (std::sqrt (pi))
43 # define GUM_I_SQRT_PI 0.5641895835477562869480795 // 1 / std::sqrt (pi)
44 # define GUM_BIGX 20.0 // max value to represent exp (x)
45 # define gum__ex(x) (((x) < -GUM_BIGX) ? 0.0 : std::exp(x))
46 
47 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
48 
49 // include the inlined functions if necessary
50 #ifdef GUM_NO_INLINE
51 # include <agrum/tools/core/math/chi2_inl.h>
52 #endif /* GUM_NO_INLINE */
53 
54 namespace gum {
55 
56  // default constructor
58  double confidence_proba) :
61  // for debugging purposes
63  }
64 
65  // destructor
66  Chi2::~Chi2() {
67  // for debugging purposes
69  }
70 
71  // computes the probability of normal z value (used by the cache)
72  double Chi2::probaZValue__(double z) {
73  double y, x, w;
74 
75  if (z == 0.0)
76  x = 0.0;
77  else {
78  y = 0.5 * std::fabs(z);
79 
80  if (y >= (GUM_Z_MAX * 0.5))
81  x = 1.0;
82  else if (y < 1.0) {
83  w = y * y;
84  x = ((((((((0.000124818987 * w - 0.001075204047) * w + 0.005198775019) * w
85  - 0.019198292004)
86  * w
87  + 0.059054035642)
88  * w
89  - 0.151968751364)
90  * w
91  + 0.319152932694)
92  * w
93  - 0.531923007300)
94  * w
95  + 0.797884560593)
96  * y * 2.0;
97  } else {
98  y -= 2.0;
99  x = (((((((((((((-0.000045255659 * y + 0.000152529290) * y
100  - 0.000019538132)
101  * y
102  - 0.000676904986)
103  * y
104  + 0.001390604284)
105  * y
106  - 0.000794620820)
107  * y
108  - 0.002034254874)
109  * y
110  + 0.006549791214)
111  * y
112  - 0.010557625006)
113  * y
114  + 0.011630447319)
115  * y
116  - 0.009279453341)
117  * y
118  + 0.005353579108)
119  * y
120  - 0.002141268741)
121  * y
122  + 0.000535310849)
123  * y
124  + 0.999936657524;
125  }
126  }
127 
128  return (z > 0.0 ? ((x + 1.0) * 0.5) : ((1.0 - x) * 0.5));
129  }
130 
131  // computes the probability of chi2 value (used by the cache)
132  double Chi2::probaChi2(double x, Size df) {
133  double a, y = 0, s;
134  double e, c, z;
135  int even; /* true if df is an even number */
136 
137  if ((x <= 0.0) || (df < 1)) return (1.0);
138 
139  a = 0.5 * x;
140 
141  even = (2 * (df / 2)) == df;
142 
143  if (df > 1) y = gum__ex(-a);
144 
145  s = (even ? y : (2.0 * probaZValue__(-std::sqrt(x))));
146 
147  if (df > 2) {
148  x = 0.5 * (df - 1.0);
149  z = (even ? 1.0 : 0.5);
150 
151  if (a > GUM_BIGX) {
152  e = (even ? 0.0 : GUM_LOG_SQRT_PI);
153  c = std::log(a);
154 
155  while (z <= x) {
156  e = std::log(z) + e;
157  s += gum__ex(c * z - a - e);
158  z += 1.0;
159  }
160 
161  return (s);
162  } else {
163  e = (even ? 1.0 : (GUM_I_SQRT_PI / std::sqrt(a)));
164  c = 0.0;
165 
166  while (z <= x) {
167  e = e * (a / z);
168  c = c + e;
169  z += 1.0;
170  }
171 
172  return (c * y + s);
173  }
174  } else
175  return (s);
176  }
177 
178  // computes the critical value of a given chi2 test (used by the cache)
179  double Chi2::criticalValue__(double proba, Size df) {
180  double minchisq = 0.0;
181  double maxchisq = GUM_CHI_MAX;
182  double chisqval;
183 
184  if (proba <= 0.0)
185  return (maxchisq);
186  else if (proba >= 1.0)
187  return (0.0);
188 
189  chisqval = df / std::sqrt(proba); /* fair first value */
190 
191  while (maxchisq - minchisq > GUM_CHI_EPSILON) {
192  if (probaChi2(chisqval, df) < proba)
193  maxchisq = chisqval;
194  else
195  minchisq = chisqval;
196 
197  chisqval = (maxchisq + minchisq) * 0.5;
198  }
199 
200  return (chisqval);
201  }
202 
203 } /* namespace gum */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669