7 #ifndef JADE_FORCED_GROUPING_HPP__
8 #define JADE_FORCED_GROUPING_HPP__
10 #include "jade.randomizer.hpp"
17 template <
typename TValue>
18 class basic_forced_grouping
46 char const *
const path)
52 assert(path !=
nullptr);
55 std::istringstream in (_strip_comments(path));
57 if (!(in >> _i) || _i == 0)
59 <<
"error parsing number of individuals";
61 if (!(in >> _k) || _k == 0)
63 <<
"error parsing number of components";
67 for (
size_t i = 0; i < _i; i++)
73 <<
"error parsing component assignment "
74 <<
"for individual " << i+1;
79 const auto P = 1 + *std::max_element(_a.begin(), _a.end());
83 for (
size_t p = 0; p < P; p++)
89 catch (
const std::exception & e)
92 <<
"error reading B vector for population index "
93 << p <<
": " << e.
what();
99 catch (
const std::exception & e)
101 throw error() <<
"failed to read forced-grouping file '"
102 << path <<
"': " << e.
what();
111 const std::string & path)
142 return _b[_a[i]].get_value(k + _k);
155 return _b[_a[i]].get_value(k);
165 static const auto epsilon =
value_type(0.000001);
169 for (
size_t k = 0; k < _k; k++)
170 for (
size_t i = 0; i < _i; i++)
173 typedef std::uniform_int_distribution<size_t> k_dist_type;
174 typedef std::uniform_real_distribution<value_type> q_dist_type;
176 k_dist_type k_dist (0, _k - 1);
180 for (
size_t i = 0; i < _i; i++)
185 if (std::fabs(
value_type(1) - row_sum) < epsilon)
188 const auto k = k_dist(engine);
189 const auto q_ik = q(i, k);
193 const auto min_ik =
get_min(i, k);
194 const auto distance = row_sum -
value_type(1);
195 const auto boundary = std::max(min_ik, q_ik - distance);
197 q_dist_type q_dist (boundary, q_ik);
198 q(i, k) = q_dist(engine);
202 const auto max_ik =
get_max(i, k);
203 const auto distance =
value_type(1) - row_sum;
204 const auto boundary = std::min(q_ik + distance, max_ik);
206 q_dist_type q_dist (q_ik, boundary);
207 q(i, k) = q_dist(engine);
225 <<
"inconsistent number of components specified in "
226 <<
"forced-grouping file (" << _k <<
") and "
231 <<
"inconsistent number of individuals specified in "
232 <<
"forced-grouping file (" << _i <<
") and "
235 for (
size_t i = 0; i < _i; i++)
237 for (
size_t k = 0; k < _k; k++)
239 const auto q_ik = q(i, k);
240 const auto min =
get_min(i, k);
241 const auto max =
get_max(i, k);
242 if (q_ik >= min && q_ik <= max)
246 <<
"inconsistent Q matrix cell [" << i+1 <<
"," << k+1
247 <<
"] (" << q_ik <<
") is outside the range specified "
248 <<
"in the forced-grouping file " << min <<
" to "
267 return min + (max - min) * percent;
271 static std::string _strip_comments(
const char *
const path)
273 assert(path !=
nullptr);
275 std::ifstream in (path);
279 std::ostringstream out;
281 for (
auto n = 1;; n++)
284 std::getline(in, line);
286 if (!line.empty() && line[0] !=
'#')
287 out << line << std::endl;
293 throw jade::error() <<
"error reading file at line " << n;
300 void _validate(std::istringstream & in)
const
305 <<
"invalid token encountered at end of file: " << tmp;
309 <<
"invalid number of individuals: " << _i
310 <<
"; expected at least 2";
314 <<
"invalid number of components: " << _k
315 <<
"; expected at least 2";
317 const auto k2 = 2 * _k;
319 for (
size_t k = 0; k < _k; k++)
321 const auto & b_k = _b[k];
323 if (b_k.get_height() != k2 || b_k.get_width() != 1)
325 <<
"invalid B vector for population index " << k
326 <<
": size " << b_k.get_size_str()
327 <<
" does not match expected [" << k2 <<
"x1]";
330 for (
size_t kk = 0; kk < _k; kk++)
334 <<
"invalid B vector for population index " << k
335 <<
": the sum of the first " << _k
336 <<
" values is greater than 1";
339 for (
size_t kk = 0; kk < _k; kk++)
340 max_sum += b_k[_k + kk];
343 <<
"invalid B vector for population index " << k
344 <<
": the sum of the last " << _k
345 <<
" values is less than 1";
347 for (
size_t kk = 0; kk < k2; kk++)
350 <<
"invalid B vector for population index " << k
351 <<
": cell " << kk+1 <<
" (" << b_k[kk]
352 <<
") is not between 0 and 1";
354 for (
size_t kk = 0; kk < _k; kk++)
355 if (!(b_k[kk] <= b_k[_k + kk]))
357 <<
"invalid B vector for population " << k
358 <<
": cell " << kk+1 <<
" (" << b_k[kk]
359 <<
") is greater than cell " << _k+kk+1 <<
" ("
360 << b_k[_k + kk] <<
")";
364 std::vector<size_t> _a;
365 std::vector<matrix_type> _b;
371 #endif // JADE_FORCED_GROUPING_HPP__