52#ifndef DOXYGEN_SHOULD_SKIP_THIS
59 template < GUM_Numeric GUM_SCALAR >
61 const std::vector< DBTranslatedValueType >& column_types,
62 const BayesNet< GUM_SCALAR >& bn,
63 const Bijection< NodeId, std::size_t >& nodeId2columns) :
68 _filled_row1_(bn.size(), 1.0), _filled_row2_(bn.size(), 1.0) {
71 GUM_CONSTRUCTOR(DBRowGeneratorEM);
75 template < GUM_Numeric GUM_SCALAR >
76 DBRowGeneratorEM< GUM_SCALAR >::DBRowGeneratorEM(
const DBRowGeneratorEM< GUM_SCALAR >& from) :
77 DBRowGeneratorWithBN< GUM_SCALAR >(from), _input_row_(from._input_row_),
78 _missing_cols_(from._missing_cols_), _nb_miss_(from._nb_miss_),
79 _joint_proba_(from._joint_proba_), _filled_row1_(from._filled_row1_),
80 _filled_row2_(from._filled_row2_), _use_filled_row1_(from._use_filled_row1_),
81 _original_weight_(from._original_weight_) {
82 if (from._joint_inst_ !=
nullptr) {
83 _joint_inst_ = new Instantiation(_joint_proba_);
84 const auto& var_seq = _joint_inst_->variablesSequence();
85 const std::size_t size = var_seq.size();
86 for (std::size_t i = std::size_t(0); i < size; ++i) {
87 _joint_inst_->chgVal(Idx(i), from._joint_inst_->val(i));
91 GUM_CONS_CPY(DBRowGeneratorEM);
95 template < GUM_Numeric GUM_SCALAR >
96 DBRowGeneratorEM< GUM_SCALAR >::DBRowGeneratorEM(DBRowGeneratorEM< GUM_SCALAR >&& from) noexcept
98 DBRowGeneratorWithBN< GUM_SCALAR >(std::move(from)), _input_row_(from._input_row_),
99 _missing_cols_(std::move(from._missing_cols_)), _nb_miss_(from._nb_miss_),
100 _joint_proba_(std::move(from._joint_proba_)), _filled_row1_(std::move(from._filled_row1_)),
101 _filled_row2_(std::move(from._filled_row2_)), _use_filled_row1_(from._use_filled_row1_),
102 _original_weight_(from._original_weight_) {
103 if (from._joint_inst_ !=
nullptr) {
104 _joint_inst_ =
new Instantiation(_joint_proba_);
105 const auto& var_seq = _joint_inst_->variablesSequence();
106 const std::size_t size = var_seq.size();
107 for (std::size_t i = std::size_t(0); i < size; ++i) {
108 _joint_inst_->chgVal(Idx(i), from._joint_inst_->val(i));
112 GUM_CONS_MOV(DBRowGeneratorEM);
116 template < GUM_Numeric GUM_SCALAR >
117 DBRowGeneratorEM< GUM_SCALAR >* DBRowGeneratorEM< GUM_SCALAR >::clone()
const {
118 return new DBRowGeneratorEM< GUM_SCALAR >(*
this);
122 template < GUM_Numeric GUM_SCALAR >
123 DBRowGeneratorEM< GUM_SCALAR >::~DBRowGeneratorEM() {
124 if (_joint_inst_ !=
nullptr)
delete _joint_inst_;
125 GUM_DESTRUCTOR(DBRowGeneratorEM);
129 template < GUM_Numeric GUM_SCALAR >
130 DBRowGeneratorEM< GUM_SCALAR >&
131 DBRowGeneratorEM< GUM_SCALAR >::operator=(
const DBRowGeneratorEM< GUM_SCALAR >& from) {
133 DBRowGeneratorWithBN< GUM_SCALAR >::operator=(from);
134 _input_row_ = from._input_row_;
135 _missing_cols_ = from._missing_cols_;
136 _nb_miss_ = from._nb_miss_;
137 _joint_proba_ = from._joint_proba_;
138 _filled_row1_ = from._filled_row1_;
139 _filled_row2_ = from._filled_row2_;
140 _use_filled_row1_ = from._use_filled_row1_;
141 _original_weight_ = from._original_weight_;
143 if (_joint_inst_ !=
nullptr) {
145 _joint_inst_ =
nullptr;
148 if (from._joint_inst_ !=
nullptr) {
149 _joint_inst_ =
new Instantiation(_joint_proba_);
150 const auto& var_seq = _joint_inst_->variablesSequence();
151 const std::size_t size = var_seq.size();
152 for (std::size_t i = std::size_t(0); i < size; ++i) {
153 _joint_inst_->chgVal(Idx(i), from._joint_inst_->val(i));
162 template < GUM_Numeric GUM_SCALAR >
163 DBRowGeneratorEM< GUM_SCALAR >&
164 DBRowGeneratorEM< GUM_SCALAR >::operator=(DBRowGeneratorEM< GUM_SCALAR >&& from) {
166 DBRowGeneratorWithBN< GUM_SCALAR >::operator=(std::move(from));
167 _input_row_ = from._input_row_;
168 _missing_cols_ = std::move(from._missing_cols_);
169 _nb_miss_ = from._nb_miss_;
170 _joint_proba_ = std::move(from._joint_proba_);
171 _filled_row1_ = std::move(from._filled_row1_);
172 _filled_row2_ = std::move(from._filled_row2_);
173 _use_filled_row1_ = from._use_filled_row1_;
174 _original_weight_ = from._original_weight_;
176 if (_joint_inst_ !=
nullptr) {
178 _joint_inst_ =
nullptr;
181 if (from._joint_inst_ !=
nullptr) {
182 _joint_inst_ =
new Instantiation(_joint_proba_);
183 const auto& var_seq = _joint_inst_->variablesSequence();
184 const std::size_t size = var_seq.size();
185 for (std::size_t i = std::size_t(0); i < size; ++i) {
186 _joint_inst_->chgVal(Idx(i), from._joint_inst_->val(i));
195 template < GUM_Numeric GUM_SCALAR >
196 const DBRow< DBTranslatedValue >& DBRowGeneratorEM< GUM_SCALAR >::generate() {
197 this->decreaseRemainingRows();
200 if (_input_row_ !=
nullptr)
return *_input_row_;
202 if (_use_filled_row1_) {
204 _filled_row1_.setWeight(_joint_proba_.get(*_joint_inst_) * _original_weight_);
207 for (std::size_t i = std::size_t(0); i < _nb_miss_; ++i)
208 _filled_row1_[_missing_cols_[i]].discr_val = _joint_inst_->val(i);
211 _use_filled_row1_ =
false;
213 return _filled_row1_;
216 _filled_row2_.setWeight(_joint_proba_.get(*_joint_inst_) * _original_weight_);
219 for (std::size_t i = std::size_t(0); i < _nb_miss_; ++i)
220 _filled_row2_[_missing_cols_[i]].discr_val = _joint_inst_->val(i);
223 _use_filled_row1_ =
true;
225 return _filled_row2_;
230 template < GUM_Numeric GUM_SCALAR >
232 DBRowGeneratorEM< GUM_SCALAR >::computeRows_(
const DBRow< DBTranslatedValue >& row) {
235 bool found_unobserved =
false;
236 const auto& xrow = row.row();
237 for (
const auto col: this->columns_of_interest_) {
238 switch (this->column_types_[col]) {
239 case DBTranslatedValueType::DISCRETE :
240 if (xrow[col].discr_val == std::numeric_limits< std::size_t >::max()) {
241 if (!found_unobserved) {
242 _missing_cols_.clear();
243 found_unobserved =
true;
245 _missing_cols_.push_back(col);
249 case DBTranslatedValueType::CONTINUOUS :
251 "The BDRowGeneratorEM does not handle yet continuous "
252 <<
"variables. But the variable in column" << col <<
" is continuous.");
257 "DBTranslatedValueType " <<
int(this->column_types_[col])
258 <<
" is not supported yet");
263 if (!found_unobserved) {
265 return std::size_t(1);
268 _input_row_ =
nullptr;
269 _nb_miss_ = _missing_cols_.size();
270 _original_weight_ = row.weight();
274 VariableElimination< GUM_SCALAR > ve(this->bn_);
278 if (this->nodeId2columns_.empty()) {
279 std::size_t i = std::size_t(0);
280 bool end_miss =
false;
281 for (
const auto col: this->columns_of_interest_) {
282 if (!end_miss && (col == _missing_cols_[i])) {
283 target_set.insert(NodeId(col));
285 if (i == _nb_miss_) end_miss =
true;
287 _filled_row1_[col].discr_val = xrow[col].discr_val;
288 _filled_row2_[col].discr_val = xrow[col].discr_val;
292 std::size_t i = std::size_t(0);
293 bool end_miss =
false;
294 for (
const auto col: this->columns_of_interest_) {
295 if (!end_miss && (col == _missing_cols_[i])) {
296 target_set.insert(this->nodeId2columns_.first(col));
298 if (i == _nb_miss_) end_miss =
true;
300 _filled_row1_[col].discr_val = xrow[col].discr_val;
301 _filled_row2_[col].discr_val = xrow[col].discr_val;
306 ve.addJointTarget(target_set);
309 const std::size_t row_size = xrow.size();
310 if (this->nodeId2columns_.empty()) {
311 for (std::size_t col = std::size_t(0); col < row_size; ++col) {
312 switch (this->column_types_[col]) {
313 case DBTranslatedValueType::DISCRETE :
315 if (xrow[col].discr_val != std::numeric_limits< std::size_t >::max()) {
316 ve.addEvidence(NodeId(col), xrow[col].discr_val);
320 case DBTranslatedValueType::CONTINUOUS :
322 "The BDRowGeneratorEM does not handle yet continuous "
323 <<
"variables. But the variable in column" << col <<
" is continuous.");
328 "DBTranslatedValueType " <<
int(this->column_types_[col])
329 <<
" is not supported yet");
333 for (std::size_t col = std::size_t(0); col < row_size; ++col) {
334 switch (this->column_types_[col]) {
335 case DBTranslatedValueType::DISCRETE :
337 if (xrow[col].discr_val != std::numeric_limits< std::size_t >::max()) {
338 ve.addEvidence(this->nodeId2columns_.first(col), xrow[col].discr_val);
342 case DBTranslatedValueType::CONTINUOUS :
344 "The BDRowGeneratorEM does not handle yet continuous "
345 <<
"variables. But the variable in column" << col <<
" is continuous.");
350 "DBTranslatedValueType " <<
int(this->column_types_[col])
351 <<
" is not supported yet");
357 Tensor< GUM_SCALAR >& pot
358 =
const_cast< Tensor< GUM_SCALAR >&
>(ve.jointPosterior(target_set));
359 _joint_proba_ = std::move(pot);
360 if (_joint_inst_ !=
nullptr)
delete _joint_inst_;
361 _joint_inst_ =
new Instantiation(_joint_proba_);
365 const auto& var_sequence = _joint_proba_.variablesSequence();
366 if (this->nodeId2columns_.empty()) {
367 for (std::size_t i = std::size_t(0); i < _nb_miss_; ++i) {
368 _missing_cols_[i] = std::size_t(this->bn_->nodeId(*(var_sequence[i])));
371 for (std::size_t i = std::size_t(0); i < _nb_miss_; ++i) {
372 _missing_cols_[i] = this->nodeId2columns_.second(this->bn_->nodeId(*(var_sequence[i])));
376 return std::size_t(_joint_proba_.domainSize());
380 template < GUM_Numeric GUM_SCALAR >
381 void DBRowGeneratorEM< GUM_SCALAR >::setBayesNet(
const BayesNet< GUM_SCALAR >& new_bn) {
384 if (!this->nodeId2columns_.empty()) {
385 const DAG& dag = new_bn.internalDag();
386 for (
auto iter = this->nodeId2columns_.begin(); iter != this->nodeId2columns_.end();
388 if (!dag.existsNode(iter.first())) {
390 "Column " << iter.second() <<
" of the database is associated to Node ID "
392 <<
", which does not belong to the Bayesian network");
397 DBRowGeneratorWithBN< GUM_SCALAR >::setBayesNet(new_bn);
400 std::size_t size = std::size_t(0);
401 if (this->nodeId2columns_.empty()) {
405 for (
auto node: new_bn.internalDag())
406 if (std::size_t(node) > size) size = std::size_t(node);
408 for (
auto iter = this->nodeId2columns_.begin(); iter != this->nodeId2columns_.end();
410 if (iter.second() > size) size = iter.second();
413 _filled_row1_.resize(size + 1);
414 _filled_row2_.resize(size + 1);
A DBRowGenerator class that returns incomplete rows as EM would do.
A DBRowGenerator class that returns exactly the rows it gets in input.
Exception : node does not exist.
Exception : there is something wrong with an implementation.
DBRowGeneratorEM(const std::vector< DBTranslatedValueType > &column_types, const BayesNet< GUM_SCALAR > &bn, const Bijection< NodeId, std::size_t > &nodeId2columns=Bijection< NodeId, std::size_t >())
default constructor
Base class for DBRowGenerator classes that use a BN for computing their outputs.
#define GUM_ERROR(type, msg)
Set< NodeId > NodeSet
Some typdefs and define for shortcuts ...
DBRowGeneratorGoal
the type of things that a DBRowGenerator is designed for
@ ONLY_REMOVE_MISSING_VALUES
include the inlined functions if necessary
gum is the global namespace for all aGrUM entities