aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
DBRowGeneratorSet_tpl.h
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 /** @file
23  * @brief Template implementation of DBRowGeneratorSet
24  *
25  * @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
26  */
27 
28 #ifndef DOXYGEN_SHOULD_SKIP_THIS
29 
30 namespace gum {
31 
32  namespace learning {
33 
34 
35  /// default constructor
36  template < template < typename > class ALLOC >
37  INLINE DBRowGeneratorSet< ALLOC >::DBRowGeneratorSet(
38  const typename DBRowGeneratorSet< ALLOC >::allocator_type& alloc) :
42  }
43 
44 
45  /// copy constructor with a given allocator
46  template < template < typename > class ALLOC >
48  const DBRowGeneratorSet< ALLOC >& from,
49  const typename DBRowGeneratorSet< ALLOC >::allocator_type& alloc) :
53  // create the generators
54  for (std::size_t i = std::size_t(0); i < _nb_generators_; ++i)
56 
58  }
59 
60 
61  /// copy constructor
62  template < template < typename > class ALLOC >
65 
66 
67  /// move constructor with a given allocator
68  template < template < typename > class ALLOC >
71  const typename DBRowGeneratorSet< ALLOC >::allocator_type& alloc) :
76  }
77 
78 
79  /// move constructor
80  template < template < typename > class ALLOC >
83 
84  /// virtual copy constructor with a given allocator
85  template < template < typename > class ALLOC >
87  const typename DBRowGeneratorSet< ALLOC >::allocator_type& alloc) const {
90  try {
92  } catch (...) {
94  throw;
95  }
96  return generators;
97  }
98 
99 
100  /// virtual copy constructor
101  template < template < typename > class ALLOC >
103  return clone(this->getAllocator());
104  }
105 
106 
107  /// removes all the generators
108  template < template < typename > class ALLOC >
109  void DBRowGeneratorSet< ALLOC >::clear() {
110  // delete all the generators
112  for (auto gen: _generators_) {
115  }
116 
117  // clear all the internal fields
119  _nb_generators_ = std::size_t(0);
120  _output_row_ = nullptr;
122  }
123 
124 
125  /// destructor
126  template < template < typename > class ALLOC >
129  clear();
130  }
131 
132 
133  /// copy operator
134  template < template < typename > class ALLOC >
137  if (this != &from) {
138  // produce the new generators
142  nullptr,
143  allocator);
144  for (std::size_t i = std::size_t(0); i < from._nb_generators_; ++i) {
145  try {
147  } catch (...) {
148  for (std::size_t j = std::size_t(0); j < i; ++j) {
151  }
152  throw;
153  }
154  }
155 
156  // create the setInputDBrow_performed vector
158  0,
159  getAllocator());
160 
161  // remove the old generators and copy the new ones
162  clear();
165  _output_row_ = nullptr;
167  }
168 
169  return *this;
170  }
171 
172 
173  /// move operator
174  template < template < typename > class ALLOC >
177  if (this != &from) {
178  // remove the old generators and move the new ones
179  clear();
184  }
185  return *this;
186  }
187 
188 
189  /// returns the ith generator
190  template < template < typename > class ALLOC >
192  return *(_generators_[i]);
193  }
194 
195 
196  /// returns the ith generator
197  template < template < typename > class ALLOC >
198  INLINE const DBRowGenerator< ALLOC >&
199  DBRowGeneratorSet< ALLOC >::operator[](const std::size_t i) const {
200  return *(_generators_[i]);
201  }
202 
203 
204  /// inserts a new generator at the end of the set
205  template < template < typename > class ALLOC >
206  template < template < template < typename > class > class Generator >
208  // check that no output row generation is still active
209  if (_output_row_ != nullptr)
211  "you cannot insert a new generator while a generation is "
212  "still being processed");
213 
216 
217  try {
219  } catch (...) {
222  throw;
223  }
224 
225  ++_nb_generators_;
226  _output_row_ = nullptr;
227  }
228 
229 
230  /// inserts a new generator at the end of the set
231  template < template < typename > class ALLOC >
232  template < template < template < typename > class > class Generator >
234  const std::size_t i) {
235  // check that no output row generation is still active
236  if (_output_row_ != nullptr)
238  "you cannot insert a new generator while a generation is "
239  "still being processed");
240 
243 
244  try {
246  } catch (...) {
249  throw;
250  }
251 
252  ++_nb_generators_;
253  _output_row_ = nullptr;
254  }
255 
256 
257  /// returns the number of generators
258  template < template < typename > class ALLOC >
259  INLINE std::size_t DBRowGeneratorSet< ALLOC >::nbGenerators() const noexcept {
260  return _nb_generators_;
261  }
262 
263 
264  /// assign a new Bayes net to all the generators that depend on a BN
265  template < template < typename > class ALLOC >
266  template < typename GUM_SCALAR >
269  old_bns;
270 
271  for (auto xgen: _generators_) {
272  // check if the generator relies on a Bayes net
273  DBRowGeneratorWithBN< GUM_SCALAR, ALLOC >* gen = nullptr;
274  try {
275  gen = dynamic_cast< DBRowGeneratorWithBN< GUM_SCALAR, ALLOC >* >(xgen);
276  } catch (std::bad_cast&) {}
277 
278  if (gen != nullptr) {
279  // try to assign the new BN to the generator
280  try {
281  const BayesNet< GUM_SCALAR >* bn = &(gen->getBayesNet());
282  old_bns.insert(gen, bn);
284  } catch (...) {
285  // if we could not assign the new BN to the generator, then
286  // make all the generators that were successfully assigned this
287  // BN revert to the old BN they had
288  for (auto& generator: old_bns) {
290  }
291  throw;
292  }
293  }
294  }
295  }
296 
297 
298  /// returns the number of generators (alias for nbGenerators)
299  template < template < typename > class ALLOC >
300  INLINE std::size_t DBRowGeneratorSet< ALLOC >::size() const noexcept {
301  return _nb_generators_;
302  }
303 
304 
305  /// returns true if there are still rows that can be output by the RowFilter
306  template < template < typename > class ALLOC >
308  return _output_row_ != nullptr;
309  }
310 
311 
312  // try to produce a new row
313  template < template < typename > class ALLOC >
316  std::size_t i) {
317  // the generation of output rows can be viewed as the traversal of a
318  // tree: each node of the tree correspond to the input row received by
319  // a generator. So the root node is the row passed in argument to
320  // the setInputDBrow() Method. From these input rows, generators produce
321  // through their generate() method new output rows, which correspond to
322  // the input rows of the next level of the tree. If we traverse this tree
323  // in terms of generators rather than in terms of input rows, we should
324  // call once Method setInputDBrow() in order to update the generators
325  // data structures, and then, to call method generate() to create new
326  // output rows. When some generators are unable to produce output rows,
327  // we just need to backtrack in the tree
328 
329  // for the ith generator, we set the new input DBRow passed in
330  // argument of setInputDBRow. We ask it to generate a new output row.
331  // If this can be done, the new output row is passed as a new input DBRow
332  // for the next generator, and so on. If a generator cannot produce any
333  // output row, we ask its predecessors to generate new rows (backtrack),
334  // until all the generators have been able to generate at least one output
335  // row (or no output row can be produced from input_row).
337  while (i != _nb_generators_) {
338  auto generator = _generators_[i];
339 
340  // if we did not pass any row yet to the ith generator, do it
341  // else use method generate() to generate a new output row
342  if (_setInputRow_performed_[i] == 0) {
343  // pass the current row
344  const bool has_rows = generator->setInputRow(*row);
345 
346  // if the generator could not create output rows, try to backtrack
347  if (!has_rows) {
348  if (i > std::size_t(0)) {
349  --i;
350  continue;
351  } else {
352  // here we were unable to generate output rows
353  _output_row_ = nullptr;
354  return false;
355  }
356  } else {
357  // here, the generator is able to generate output rows
358  // so, generate the first one
359  row = &(generator->generate());
361 
362  // pass to the next generator
363  ++i;
364  }
365  } else {
366  // here, the generator has already performed its setInputDBRow call
367  // so we should ask it to generate a new row. If it cannot produce
368  // any more row, try to backtrack
369  if (generator->hasRows()) {
370  // get the new row
371  row = &(generator->generate());
372 
373  // pass to the next generator
374  ++i;
375  } else {
376  // indicate that the next time we use this generator, we will have
377  // to use method setInputDBRow and backtrack
379  if (i > std::size_t(0)) {
380  --i;
381  continue;
382  } else {
383  // here we were unable to generate output rows
384  _output_row_ = nullptr;
385  return false;
386  }
387  }
388  }
389  }
390 
391  // here row contains a row generated on a leaf of the row generation tree
392  // we should keep it when the user will ask for the next row to generate
393  _output_row_ = row;
394  return true;
395  }
396 
397 
398  /// sets the input row from which the generator will create new rows
399  template < template < typename > class ALLOC >
400  INLINE bool
402  // reset all the generators: ask them to use method setInputDBRow
403  if (hasRows())
405  performed = 0;
406 
407  // now, parse the row generation tree
408  return _produceNextRow_(&input_row, std::size_t(0));
409  }
410 
411 
412  /// generate new rows from the input row
413  template < template < typename > class ALLOC >
415  // get the row that we should return
416  const auto row = _output_row_;
417 
418  // we should ask the last generator to produce the next output row
420 
421  return *row;
422  }
423 
424 
425  /// resets the filter
426  template < template < typename > class ALLOC >
427  INLINE void DBRowGeneratorSet< ALLOC >::reset() {
428  for (auto gen: _generators_)
429  gen->reset();
431  performed = 0;
432  _output_row_ = nullptr;
433  }
434 
435 
436  /// sets the columns of interest: the output DBRow needs only
437  /// contain values fot these columns
438  template < template < typename > class ALLOC >
440  const std::vector< std::size_t, ALLOC< std::size_t > >& cols_of_interest) {
441  // check that no output row generation is still active
442  if (_output_row_ != nullptr)
444  "you cannot change the columns of interest while a "
445  "generation is still being processed");
446  for (auto gen: _generators_)
448  }
449 
450 
451  /// sets the columns of interest: the output DBRow needs only
452  /// contain values fot these columns
453  template < template < typename > class ALLOC >
456  if (_output_row_ != nullptr)
458  "you cannot change the columns of interest while a "
459  "generation is still being processed");
460  for (auto gen: _generators_)
462  }
463 
464 
465  /// returns the current set of columns of interest
466  template < template < typename > class ALLOC >
467  INLINE const std::vector< std::size_t, ALLOC< std::size_t > >&
469  if (_nb_generators_ == std::size_t(0)) {
471  "there are no generators yet in the generator set, so "
472  "there are no columns of interest");
473  }
474  return _generators_[0]->columnsOfInterest();
475  }
476 
477 
478  /// returns the allocator used
479  template < template < typename > class ALLOC >
481  DBRowGeneratorSet< ALLOC >::getAllocator() const {
483  }
484 
485 
486  } /* namespace learning */
487 
488 } /* namespace gum */
489 
490 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643
Database(const std::string &filename, const BayesNet< GUM_SCALAR > &bn, const std::vector< std::string > &missing_symbols)