29 #ifndef DOXYGEN_SHOULD_SKIP_THIS 31 # include <agrum/tools/core/math/variableLog2ParamComplexity.h> 32 # include <agrum/tools/core/math/gammaLog2.h> 41 template <
template <
typename >
class ALLOC >
42 INLINE
typename VariableLog2ParamComplexity< ALLOC >::allocator_type
43 VariableLog2ParamComplexity< ALLOC >::getAllocator()
const {
49 template <
template <
typename >
class ALLOC >
50 INLINE VariableLog2ParamComplexity< ALLOC >::VariableLog2ParamComplexity(
51 const allocator_type& alloc) :
52 VariableLog2ParamComplexity< ALLOC >::allocator_type(alloc),
54 GUM_CONSTRUCTOR(VariableLog2ParamComplexity);
59 template <
template <
typename >
class ALLOC >
60 INLINE VariableLog2ParamComplexity< ALLOC >::VariableLog2ParamComplexity(
61 const VariableLog2ParamComplexity< ALLOC >& from,
62 const typename VariableLog2ParamComplexity< ALLOC >::allocator_type& alloc) :
63 VariableLog2ParamComplexity< ALLOC >::allocator_type(alloc),
64 _use_cache_(from._use_cache_), _cache_(from._cache_) {
65 GUM_CONS_CPY(VariableLog2ParamComplexity);
70 template <
template <
typename >
class ALLOC >
71 INLINE VariableLog2ParamComplexity< ALLOC >::VariableLog2ParamComplexity(
72 const VariableLog2ParamComplexity< ALLOC >& from) :
73 VariableLog2ParamComplexity(from,
this->getAllocator()) {}
77 template <
template <
typename >
class ALLOC >
78 INLINE VariableLog2ParamComplexity< ALLOC >::VariableLog2ParamComplexity(
79 VariableLog2ParamComplexity< ALLOC >&& from,
80 const typename VariableLog2ParamComplexity< ALLOC >::allocator_type& alloc) :
81 VariableLog2ParamComplexity< ALLOC >::allocator_type(alloc),
82 _use_cache_(from._use_cache_), _cache_(std::move(from._cache_)) {
83 GUM_CONS_MOV(VariableLog2ParamComplexity);
88 template <
template <
typename >
class ALLOC >
89 INLINE VariableLog2ParamComplexity< ALLOC >::VariableLog2ParamComplexity(
90 VariableLog2ParamComplexity< ALLOC >&& from) :
91 VariableLog2ParamComplexity(std::move(from),
this->getAllocator()) {}
95 template <
template <
typename >
class ALLOC >
96 VariableLog2ParamComplexity< ALLOC >* VariableLog2ParamComplexity< ALLOC >::clone(
97 const typename VariableLog2ParamComplexity< ALLOC >::allocator_type& alloc)
const {
98 ALLOC< VariableLog2ParamComplexity< ALLOC > > allocator(alloc);
99 VariableLog2ParamComplexity< ALLOC >* table = allocator.allocate(1);
101 allocator.construct(table, *
this);
103 allocator.deallocate(table, 1);
111 template <
template <
typename >
class ALLOC >
112 VariableLog2ParamComplexity< ALLOC >* VariableLog2ParamComplexity< ALLOC >::clone()
const {
113 return clone(
this->getAllocator());
118 template <
template <
typename >
class ALLOC >
119 INLINE VariableLog2ParamComplexity< ALLOC >::~VariableLog2ParamComplexity() {
120 GUM_DESTRUCTOR(VariableLog2ParamComplexity);
125 template <
template <
typename >
class ALLOC >
126 INLINE VariableLog2ParamComplexity< ALLOC >& VariableLog2ParamComplexity< ALLOC >::operator=(
127 const VariableLog2ParamComplexity< ALLOC >& from) {
133 template <
template <
typename >
class ALLOC >
134 INLINE VariableLog2ParamComplexity< ALLOC >&
135 VariableLog2ParamComplexity< ALLOC >::operator=(VariableLog2ParamComplexity< ALLOC >&& from) {
141 template <
template <
typename >
class ALLOC >
142 INLINE
void VariableLog2ParamComplexity< ALLOC >::useCache(
const bool on_off) {
143 _use_cache_ = on_off;
148 template <
template <
typename >
class ALLOC >
149 INLINE
void VariableLog2ParamComplexity< ALLOC >::clearCache() {
155 template <
template <
typename >
class ALLOC >
156 double VariableLog2ParamComplexity< ALLOC >::log2Cnr(
const std::size_t r,
const double n) {
160 if (r == std::size_t(1))
return 0.0;
161 if (n == 0.0)
return 0.0;
162 if (n == 1.0)
return std::log2((
double)r);
165 GUM_ERROR(OutOfBounds,
166 "In the penalty of the fNML score, n must be greater " 167 <<
"than or equal to 0. But, here, n = " << n);
170 if (n < VariableLog2ParamComplexityCTableNSize) {
173 std::size_t xn = (std::size_t)n;
174 if (r - 2 < VariableLog2ParamComplexityCTableRSize) {
175 return VariableLog2ParamComplexityCTable[r - 2][xn];
180 return _cache_[std::pair< std::size_t,
double >{r, n}];
181 }
catch (NotFound&) {}
200 double log2Cnr1 = VariableLog2ParamComplexityCTable[3][xn];
201 double log2Cnr2 = VariableLog2ParamComplexityCTable[2][xn];
202 double log2Cnr = 0.0;
203 double k_r = std::exp((log2Cnr2 - log2Cnr1) * M_LN2);
204 double q_r = 1.0 + k_r * n / (6.0 - 2.0);
205 for (std::size_t i = std::size_t(6); i <= r; ++i) {
206 log2Cnr = log2Cnr1 + std::log2(q_r);
209 q_r = 1.0 + k_r * (n / (i - 1.0));
213 if (_use_cache_) { _cache_.insert(std::pair< std::size_t,
double >{r, n}, log2Cnr); }
221 return _cache_[std::pair< std::size_t,
double >{r, n}];
222 }
catch (NotFound&) {}
227 double log2Cnr1 = 0.5 * std::log2(n) + _cst1_ + _cst2_ / std::sqrt(n) + _cst3_ / n;
228 if (r == std::size_t(2))
return log2Cnr1;
231 double log2Cnr2 = 0.0;
235 double k_r = std::exp((log2Cnr2 - log2Cnr1) * M_LN2);
236 double q_r = 1.0 + k_r * n / (3.0 - 2.0);
237 double log2Cnr = 0.0;
238 for (std::size_t i = std::size_t(3); i <= r; ++i) {
239 log2Cnr = log2Cnr1 + std::log2(q_r);
242 q_r = 1.0 + k_r * (n / (i - 1.0));
246 if (_use_cache_) { _cache_.insert(std::pair< std::size_t,
double >{r, n}, log2Cnr); }
254 template <
template <
typename >
class ALLOC >
255 void VariableLog2ParamComplexity< ALLOC >::CnrToFile(
const std::string& filename) {
257 std::vector<
long double > cn2_table(VariableLog2ParamComplexityCTableNSize);
263 GammaLog2 gamma_log2;
264 for (
double n = 2; n < VariableLog2ParamComplexityCTableNSize; ++n) {
272 for (
double h = 1; h < n; ++h) {
273 long double elt = (gamma_log2(n + 1) - gamma_log2(h + 1) - gamma_log2((n - h) + 1)) * M_LN2
274 + h * std::log(h / n) + (n - h) * std::log((n - h) / n);
275 cn2 += std::exp(elt);
283 std::ofstream outfile(filename);
284 if (!outfile.is_open()) { GUM_ERROR(IOError,
"It is impossible to open file " << filename) }
285 outfile.precision(20);
286 outfile <<
"namespace gum {\n\n";
295 outfile <<
" // the CTable cache for log2(Cnr), n < " << VariableLog2ParamComplexityCTableNSize
296 <<
" and r in {2,3,4,5}\n";
297 outfile <<
" const double VariableLog2ParamComplexityCTable[4][" 298 << VariableLog2ParamComplexityCTableNSize <<
"] = {\n";
303 for (
const auto cn2: cn2_table) {
308 const double logCn2 = (
double)std::log2(cn2);
315 for (std::size_t i = std::size_t(0); i < VariableLog2ParamComplexityCTableNSize; ++i) {
316 if (i > std::size_t(0)) outfile <<
",\n ";
317 const double logCn3 = (
double)std::log2(cn2_table[i] + i);
324 for (std::size_t i = std::size_t(0); i < VariableLog2ParamComplexityCTableNSize; ++i) {
325 if (i > std::size_t(0)) outfile <<
",\n ";
326 const double logCn4 = (
double)std::log2(cn2_table[i] * (1.0 + i / 2.0) + i);
333 for (std::size_t i = std::size_t(0); i < VariableLog2ParamComplexityCTableNSize; ++i) {
334 if (i > std::size_t(0)) outfile <<
",\n ";
336 = (
double)std::log2(cn2_table[i] * (1.0 + 5.0 * i / 6.0) + i + i * i / 3.0);
342 outfile <<
" };\n\n";
343 outfile <<
"} /* namespace gum */\n";