aGrUM 3.1.1
a C++ library for (probabilistic) graphical models
BNLearner_tpl.h
Go to the documentation of this file.
1/****************************************************************************
2 * This file is part of the aGrUM/pyAgrum library. *
3 * *
4 * Copyright (c) 2005-2026 by *
5 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
6 * - Christophe GONZALES(_at_AMU) *
7 * *
8 * The aGrUM/pyAgrum library is free software; you can redistribute it *
9 * and/or modify it under the terms of either : *
10 * *
11 * - the GNU Lesser General Public License as published by *
12 * the Free Software Foundation, either version 3 of the License, *
13 * or (at your option) any later version, *
14 * - the MIT license (MIT), *
15 * - or both in dual license, as here. *
16 * *
17 * (see https://agrum.gitlab.io/articles/dual-licenses-lgplv3mit.html) *
18 * *
19 * This aGrUM/pyAgrum library is distributed in the hope that it will be *
20 * useful, but WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
21 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES MERCHANTABILITY or FITNESS *
22 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
26 * OTHER DEALINGS IN THE SOFTWARE. *
27 * *
28 * See LICENCES for more details. *
29 * *
30 * SPDX-FileCopyrightText: Copyright 2005-2026 *
31 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
32 * - Christophe GONZALES(_at_AMU) *
33 * SPDX-License-Identifier: LGPL-3.0-or-later OR MIT *
34 * *
35 * Contact : info_at_agrum_dot_org *
36 * homepage : http://agrum.gitlab.io *
37 * gitlab : https://gitlab.com/agrumery/agrum *
38 * *
39 ****************************************************************************/
40
41#pragma once
42
43
52#include <fstream>
53
54#include <agrum/BN/learning/BNLearner.h> // to ease IDE parser
55
56#ifndef DOXYGEN_SHOULD_SKIP_THIS
57
58// to help IDE parser
61
62namespace gum {
63
64 namespace learning {
65 template < GUM_Numeric GUM_SCALAR >
66 BNLearner< GUM_SCALAR >::BNLearner(std::string_view filename,
67 const std::vector< std::string >& missingSymbols,
68 const bool induceTypes) :
69 IBNLearner(filename, missingSymbols, induceTypes) {
70 GUM_CONSTRUCTOR(BNLearner);
71 }
72
73 template < GUM_Numeric GUM_SCALAR >
74 BNLearner< GUM_SCALAR >::BNLearner(const DatabaseTable& db) : IBNLearner(db) {
75 GUM_CONSTRUCTOR(BNLearner);
76 }
77
78 template < GUM_Numeric GUM_SCALAR >
79 BNLearner< GUM_SCALAR >::BNLearner(std::string_view filename,
81 const std::vector< std::string >& missing_symbols) :
82 IBNLearner(filename, bn, missing_symbols) {
83 GUM_CONSTRUCTOR(BNLearner);
84 }
85
87 template < GUM_Numeric GUM_SCALAR >
88 BNLearner< GUM_SCALAR >::BNLearner(const BNLearner< GUM_SCALAR >& src) : IBNLearner(src) {
89 GUM_CONSTRUCTOR(BNLearner);
90 }
91
93 template < GUM_Numeric GUM_SCALAR >
94 BNLearner< GUM_SCALAR >::BNLearner(BNLearner< GUM_SCALAR >&& src) : IBNLearner(src) {
95 GUM_CONSTRUCTOR(BNLearner);
96 }
97
99 template < GUM_Numeric GUM_SCALAR >
100 BNLearner< GUM_SCALAR >::~BNLearner() {
101 GUM_DESTRUCTOR(BNLearner);
102 }
103
105
106 // ##########################################################################
108 // ##########################################################################
110
112 template < GUM_Numeric GUM_SCALAR >
113 BNLearner< GUM_SCALAR >&
114 BNLearner< GUM_SCALAR >::operator=(const BNLearner< GUM_SCALAR >& src) {
115 IBNLearner::operator=(src);
116 return *this;
117 }
118
120 template < GUM_Numeric GUM_SCALAR >
121 BNLearner< GUM_SCALAR >&
122 BNLearner< GUM_SCALAR >::operator=(BNLearner< GUM_SCALAR >&& src) noexcept {
123 IBNLearner::operator=(std::move(src));
124 return *this;
125 }
126
128 template < GUM_Numeric GUM_SCALAR >
129 BayesNet< GUM_SCALAR > BNLearner< GUM_SCALAR >::learnBN() {
130 // create the score, the prior and the estimator
131 auto notification = checkScorePriorCompatibility();
132 if (notification != "") { std::cout << "[aGrUM notification] " << notification << std::endl; }
133 createPrior_();
134 createScore_();
135
136 std::unique_ptr< ParamEstimator > param_estimator(
137 createParamEstimator_(scoreDatabase_.parser(), true));
138
139 return dag2BN_.createBN< GUM_SCALAR >(*(param_estimator.get()), learnDag_());
140 }
141
142 // check that the database contains the nodes of the dag, else raise an exception
143 template < GUM_Numeric GUM_SCALAR >
144 void BNLearner< GUM_SCALAR >::_checkDAGCompatibility_(const DAG& dag) {
145 // if the dag contains no node, this is compatible with the database
146 if (dag.size() == 0) return;
147
148 // check that the dag corresponds to the database
149 std::vector< NodeId > ids;
150 ids.reserve(dag.sizeNodes());
151 for (const auto node: dag)
152 ids.push_back(node);
153 std::sort(ids.begin(), ids.end());
154
155 if (ids.back() >= scoreDatabase_.names().size()) {
156 std::string str = "Learning parameters corresponding to the dag is impossible "
157 "because the database does not contain the following nodeID";
158 std::vector< NodeId > bad_ids;
159 for (const auto node: ids) {
160 if (node >= scoreDatabase_.names().size()) bad_ids.push_back(node);
161 }
162 if (bad_ids.size() > 1) str += 's';
163 str += ": ";
164 bool deja = false;
165 for (const auto node: bad_ids) {
166 if (deja) str += ", ";
167 else deja = true;
168 str += std::to_string(node);
169 }
171 }
172 }
173
174 // learns a BN (its parameters) using a basic learning when its structure is known
175 template < GUM_Numeric GUM_SCALAR >
176 BayesNet< GUM_SCALAR > BNLearner< GUM_SCALAR >::_learnParameters_(const DAG& dag,
177 bool takeIntoAccountScore) {
178 // if the dag contains no node, return an empty BN
179 if (dag.size() == 0) return BayesNet< GUM_SCALAR >();
180
181 // be sure that the database contains dag's node ids
182 _checkDAGCompatibility_(dag);
183
184 // create the prior
185 createPrior_();
186
187 // check that the database does not contain any missing value
188 if (scoreDatabase_.databaseTable().hasMissingValues()
189 || ((priorDatabase_ != nullptr)
190 && (priorType_ == BNLearnerPriorType::DIRICHLET_FROM_DATABASE)
191 && priorDatabase_->databaseTable().hasMissingValues())) {
193 "In general, the BNLearner is unable to cope with "
194 << "missing values in databases. To learn parameters in "
195 << "such situations, you should first use method " << "useEM()");
196 }
197
198 // create the usual estimator
199 DBRowGeneratorParser parser(scoreDatabase_.databaseTable().handler(), DBRowGeneratorSet());
200 std::unique_ptr< ParamEstimator > param_estimator(
201 createParamEstimator_(parser, takeIntoAccountScore));
202
203 return dag2BN_.createBN< GUM_SCALAR >(*(param_estimator.get()), dag);
204 }
205
206 // initialize the parameter learning by EM
207 // GCC 16 false positive: VRP inlines shared_ptr<ParamEstimator> control block and
208 // incorrectly reports -Warray-bounds on the mutex; #pragma GCC diagnostic cannot
209 // suppress warnings whose primary location is in system headers (stl_construct.h),
210 // so we disable VRP for this function via optimize pragma instead
211# if defined(__GNUC__) && !defined(__clang__)
212# pragma GCC push_options
213# pragma GCC optimize("no-tree-vrp")
214# endif
215
216 template < GUM_Numeric GUM_SCALAR >
217 std::pair< std::shared_ptr< ParamEstimator >, std::shared_ptr< ParamEstimator > >
218 BNLearner< GUM_SCALAR >::_initializeEMParameterLearning_(const DAG& dag,
219 bool takeIntoAccountScore) {
220 // be sure that the database contains dag's node ids
221 _checkDAGCompatibility_(dag);
222
223 // create the prior
224 createPrior_();
225
226 // propagate the messages of dag2BN_ to the BNLearner so that the objects that listen
227 // to the BNLearner can be informed of the progress of the EM's execution by dag2BN_
228 // BNLearnerListener listener(this, dag2BN_);
229
230 // get the column types
231 const auto& database = scoreDatabase_.databaseTable();
232 const std::size_t nb_vars = database.nbVariables();
233 const std::vector< gum::learning::DBTranslatedValueType > col_types(
234 nb_vars,
236
237 // create the bootstrap estimator
238 DBRowGenerator4CompleteRows generator_bootstrap(col_types);
239 DBRowGeneratorSet genset_bootstrap;
240 genset_bootstrap.insertGenerator(generator_bootstrap);
241 DBRowGeneratorParser parser_bootstrap(database.handler(), genset_bootstrap);
242 std::shared_ptr< ParamEstimator > param_estimator_bootstrap(
243 createParamEstimator_(parser_bootstrap, takeIntoAccountScore));
244
245 // create the EM estimator
246 BayesNet< GUM_SCALAR > dummy_bn;
247 DBRowGeneratorEM< GUM_SCALAR > generator_EM(col_types, dummy_bn);
248 DBRowGenerator& gen_EM = generator_EM; // fix for g++-4.8
249 DBRowGeneratorSet genset_EM;
250 genset_EM.insertGenerator(gen_EM);
251 DBRowGeneratorParser parser_EM(database.handler(), genset_EM);
252 std::shared_ptr< ParamEstimator > param_estimator_EM(
253 createParamEstimator_(parser_EM, takeIntoAccountScore));
254
255 return {param_estimator_bootstrap, param_estimator_EM};
256 }
257
258# if defined(__GNUC__) && !defined(__clang__)
259# pragma GCC pop_options
260# endif
261
262 // learns a BN (its parameters) with EM when its structure is known
263 template < GUM_Numeric GUM_SCALAR >
264 BayesNet< GUM_SCALAR >
265 BNLearner< GUM_SCALAR >::_learnParametersWithEM_(const DAG& dag,
266 bool takeIntoAccountScore) {
267 // if the dag contains no node, return an empty BN
268 if (dag.size() == 0) return BayesNet< GUM_SCALAR >();
269
270 // get a pair containing the bootstrap and the EM estimators
271 auto estimators = _initializeEMParameterLearning_(dag, takeIntoAccountScore);
272
273 // perform the EM algorithm
274 return dag2BN_.createBNwithEM< GUM_SCALAR >(*(estimators.first.get()),
275 *(estimators.second.get()),
276 dag);
277 }
278
280 template < GUM_Numeric GUM_SCALAR >
281 BayesNet< GUM_SCALAR >
282 BNLearner< GUM_SCALAR >::_learnParametersWithEM_(const BayesNet< GUM_SCALAR >& bn,
283 bool takeIntoAccountScore) {
284 // if the dag contains no node, return an empty BN
285 if (bn.internalDag().size() == 0) return BayesNet< GUM_SCALAR >();
286
287 // get a pair containing the bootstrap and the EM estimators
288 auto estimators = _initializeEMParameterLearning_(bn.internalDag(), takeIntoAccountScore);
289
290 return dag2BN_.createBNwithEM< GUM_SCALAR >(*(estimators.first.get()),
291 *(estimators.second.get()),
292 bn);
293 }
294
296 template < GUM_Numeric GUM_SCALAR >
297 BayesNet< GUM_SCALAR > BNLearner< GUM_SCALAR >::learnParameters(const DAG& dag,
298 bool takeIntoAccountScore) {
299 if (!scoreDatabase_.databaseTable().hasMissingValues() || !useEM_) {
300 // here, we learn without EM
301 return _learnParameters_(dag, takeIntoAccountScore);
302 } else {
303 // here we learn with EM
304 return _learnParametersWithEM_(dag, takeIntoAccountScore);
305 }
306 }
307
309 template < GUM_Numeric GUM_SCALAR >
310 BayesNet< GUM_SCALAR >
311 BNLearner< GUM_SCALAR >::learnParameters(const BayesNet< GUM_SCALAR >& bn,
312 bool takeIntoAccountScore) {
313 if (!scoreDatabase_.databaseTable().hasMissingValues() || !useEM_) {
314 DAG dag;
315 const auto& db = scoreDatabase_.databaseTable();
316 for (const auto n: bn.nodes()) {
317 dag.addNodeWithId(db.columnFromVariableName(bn.variable(n).name()));
318 }
319 for (const auto& arc: bn.arcs()) {
320 dag.addArc(db.columnFromVariableName(bn.variable(arc.tail()).name()),
321 db.columnFromVariableName(bn.variable(arc.head()).name()));
322 }
323
324 // create le DAG en fonction des
325 return _learnParameters_(dag, takeIntoAccountScore);
326 } else {
327 return _learnParametersWithEM_(bn, takeIntoAccountScore);
328 }
329 }
330
332 template < GUM_Numeric GUM_SCALAR >
333 BayesNet< GUM_SCALAR > BNLearner< GUM_SCALAR >::learnParameters(bool take_into_account_score) {
334 return learnParameters(initialDag_, take_into_account_score);
335 }
336
337 template < GUM_Numeric GUM_SCALAR >
338 NodeProperty< Sequence< std::string > >
339 BNLearner< GUM_SCALAR >::_labelsFromBN_(std::string_view filename,
340 const BayesNet< GUM_SCALAR >& src) {
341 std::ifstream in(std::string(filename), std::ifstream::in);
342
343 if ((in.rdstate() & std::ifstream::failbit) != 0) {
344 GUM_ERROR(gum::IOError, "File " << filename << " not found")
345 }
346
347 CSVParser parser(in, std::string(filename));
348 parser.next();
349 auto names = parser.current();
350
351 NodeProperty< Sequence< std::string > > modals;
352
353 for (gum::Idx col = 0; col < names.size(); col++) {
354 if (src.exists(names[col])) {
355 gum::NodeId graphId = src.idFromName(names[col]);
356 modals.insert(col, gum::Sequence< std::string >());
357
358 for (gum::Size i = 0; i < src.variable(graphId).domainSize(); ++i)
359 modals[col].insert(src.variable(graphId).label(i));
360 }
361 // else: no problem, a column not in the BN...
362 }
363
364 return modals;
365 }
366
367 template < GUM_Numeric GUM_SCALAR >
368 std::string BNLearner< GUM_SCALAR >::toString() const {
369 const auto st = state();
370
371 Size maxkey = 0;
372 for (const auto& tuple: st)
373 if (std::get< 0 >(tuple).length() > maxkey) maxkey = std::get< 0 >(tuple).length();
374
375 std::string s;
376 for (const auto& tuple: st) {
377 s += std::format("{:<{}} : {}", std::get< 0 >(tuple), maxkey, std::get< 1 >(tuple));
378 if (std::get< 2 >(tuple) != "") s += std::format(" ({})", std::get< 2 >(tuple));
379 s += '\n';
380 }
381 return s;
382 }
383
384 template < GUM_Numeric GUM_SCALAR >
385 std::vector< std::tuple< std::string, std::string, std::string > >
386 BNLearner< GUM_SCALAR >::state() const {
387 std::vector< std::tuple< std::string, std::string, std::string > > vals;
388
389 std::string key;
390 std::string comment;
391 const auto& db = database();
392
393 vals.emplace_back("Filename", filename_, "");
394 vals.emplace_back("Size",
395 "(" + std::to_string(nbRows()) + "," + std::to_string(nbCols()) + ")",
396 "");
397
398 std::string vars = "";
399 for (NodeId i = 0; i < db.nbVariables(); i++) {
400 if (i > 0) vars += ", ";
401 vars += nameFromId(i) + "[" + std::to_string(db.domainSize(i)) + "]";
402 }
403 vals.emplace_back("Variables", vars, "");
404 vals.emplace_back("Induced types", inducedTypes_ ? "True" : "False", "");
405 vals.emplace_back("Missing values", hasMissingValues() ? "True" : "False", "");
406
407 key = "Algorithm";
408 switch (selectedAlgo_) {
409 case AlgoType::GREEDY_HILL_CLIMBING :
410 vals.emplace_back(key, "Greedy Hill Climbing", "");
411 break;
412 case AlgoType::EXTENDED_GREEDY_HILL_CLIMBING :
413 vals.emplace_back(key, "Extended Greedy Hill Climbing", "");
414 break;
415 case AlgoType::K2 : {
416 vals.emplace_back(key, "K2", "");
417 const auto& k2order = algoK2_.order();
418 vars = "";
419 for (NodeId i = 0; i < k2order.size(); i++) {
420 if (i > 0) vars += ", ";
421 vars += nameFromId(k2order.atPos(i));
422 }
423 vals.emplace_back("K2 order", vars, "");
424 } break;
425 case AlgoType::LOCAL_SEARCH_WITH_TABU_LIST :
426 vals.emplace_back(key, "Local Search with Tabu List", "");
427 vals.emplace_back("Tabu list size", std::to_string(nbDecreasingChanges_), "");
428 break;
429 case AlgoType::MIIC : vals.emplace_back(key, "MIIC", ""); break;
430 case AlgoType::PC : vals.emplace_back(key, "PC", ""); break;
431 case AlgoType::FCI : vals.emplace_back(key, "FCI", ""); break;
432 case AlgoType::GREEDY_THICK_THINNING :
433 vals.emplace_back(key, "Greedy Thick Thinning", "");
434 break;
435 default : vals.emplace_back(key, "(unknown)", "?"); break;
436 }
437
438 key = "Score";
439
440 if (isScoreBased()) {
441 switch (scoreType_) {
442 case ScoreType::AIC : vals.emplace_back(key, "AIC", ""); break;
443 case ScoreType::BIC : vals.emplace_back(key, "BIC", ""); break;
444 case ScoreType::BD : vals.emplace_back(key, "BD", ""); break;
445 case ScoreType::BDeu : vals.emplace_back(key, "BDeu", ""); break;
446 case ScoreType::fNML : vals.emplace_back(key, "fNML", ""); break;
447 case ScoreType::K2 : vals.emplace_back(key, "K2", ""); break;
448 case ScoreType::LOG2LIKELIHOOD : vals.emplace_back(key, "Log2Likelihood", ""); break;
449 case ScoreType::MDL : vals.emplace_back(key, "MDL", ""); break;
450 default : vals.emplace_back(key, "(unknown)", "?"); break;
451 }
452 }
453
454 if (isConstraintBased()) {
455 key = "Correction";
456 switch (kmodeMiic_) {
457 case CorrectedMutualInformation::KModeTypes::MDL :
458 vals.emplace_back(key, "MDL", "");
459 break;
460 case CorrectedMutualInformation::KModeTypes::NML :
461 vals.emplace_back(key, "NML", "");
462 break;
463 case CorrectedMutualInformation::KModeTypes::NoCorr :
464 vals.emplace_back(key, "No correction", "");
465 break;
466 default : vals.emplace_back(key, "(unknown)", "?"); break;
467 }
468 }
469
470 key = "Prior";
471 comment = checkScorePriorCompatibility();
472 switch (priorType_) {
473 case BNLearnerPriorType::NO_prior : vals.emplace_back(key, "-", comment); break;
474 case BNLearnerPriorType::DIRICHLET_FROM_DATABASE :
475 vals.emplace_back(key, "Dirichlet", comment);
476 vals.emplace_back("Dirichlet from database", priorDbname_, "");
477 break;
478 case BNLearnerPriorType::DIRICHLET_FROM_BAYESNET :
479 vals.emplace_back(key, "Dirichlet", comment);
480 vals.emplace_back("Dirichlet from Bayesian network : ", _prior_bn_.toString(), "");
481 break;
482 case BNLearnerPriorType::BDEU : vals.emplace_back(key, "BDEU", comment); break;
483 case BNLearnerPriorType::SMOOTHING : vals.emplace_back(key, "Smoothing", comment); break;
484 default : vals.emplace_back(key, "(unknown)", "?"); break;
485 }
486
487 if (priorType_ != BNLearnerPriorType::NO_prior)
488 vals.emplace_back("Prior weight", std::to_string(priorWeight_), "");
489
490 if (databaseWeight() != double(nbRows())) {
491 vals.emplace_back("Database weight", std::to_string(databaseWeight()), "");
492 }
493
494 if (useEM_) {
495 comment = "";
496 if (!hasMissingValues()) comment = "But no missing values in this database";
497 vals.emplace_back("use EM", "True", "");
498 std::string s = "[";
499 bool first = true;
500 if (dag2BN_.isEnabledMinEpsilonRate()) {
501 s += std::format("MinRate: {}", dag2BN_.minEpsilonRate());
502 first = false;
503 }
504 if (dag2BN_.isEnabledEpsilon()) {
505 if (!first) s += ", ";
506 first = false;
507 s += std::format("MinDiff: {}", dag2BN_.epsilon());
508 }
509 if (dag2BN_.isEnabledMaxIter()) {
510 if (!first) s += ", ";
511 first = false;
512 s += std::format("MaxIter: {}", dag2BN_.maxIter());
513 }
514 if (dag2BN_.isEnabledMaxTime()) {
515 if (!first) s += ", ";
516 first = false;
517 s += std::format("MaxTime: {}", dag2BN_.maxTime());
518 }
519 s += "]";
520 vals.emplace_back("EM stopping criteria", s, comment);
521 }
522
523 std::string res;
524 bool nofirst;
525 if (constraintIndegree_.maxIndegree() < std::numeric_limits< Size >::max()) {
526 vals.emplace_back("Constraint Max InDegree",
527 std::to_string(constraintIndegree_.maxIndegree()),
528 "");
529 }
530 if (!constraintForbiddenArcs_.arcs().empty()) {
531 res = "{";
532 nofirst = false;
533 for (const auto& arc: constraintForbiddenArcs_.arcs()) {
534 if (nofirst) res += ", ";
535 else nofirst = true;
536 res += nameFromId(arc.tail()) + "->" + nameFromId(arc.head());
537 }
538 res += "}";
539 vals.emplace_back("Constraint Forbidden Arcs", res, "");
540 }
541 if (!constraintMandatoryArcs_.arcs().empty()) {
542 res = "{";
543 nofirst = false;
544 for (const auto& arc: constraintMandatoryArcs_.arcs()) {
545 if (nofirst) res += ", ";
546 else nofirst = true;
547 res += nameFromId(arc.tail()) + "->" + nameFromId(arc.head());
548 }
549 res += "}";
550 vals.emplace_back("Constraint Mandatory Arcs", res, "");
551 }
552 if (!constraintPossibleEdges_.edges().empty()) {
553 res = "{";
554 nofirst = false;
555 for (const auto& edge: constraintPossibleEdges_.edges()) {
556 if (nofirst) res += ", ";
557 else nofirst = true;
558 res += nameFromId(edge.first()) + "--" + nameFromId(edge.second());
559 }
560 res += "}";
561 vals.emplace_back("Constraint Possible Edges", res, "");
562 }
563 if (!constraintSliceOrder_.sliceOrder().empty()) {
564 res = "{";
565 nofirst = false;
566 const auto& order = constraintSliceOrder_.sliceOrder();
567 for (const auto& p: order) {
568 if (nofirst) res += ", ";
569 else nofirst = true;
570 res += nameFromId(p.first) + ":" + std::to_string(p.second);
571 }
572 res += "}";
573 vals.emplace_back("Constraint Slice Order", res, "");
574 }
575 if (!constraintNoParentNodes_.nodes().empty()) {
576 res = "{";
577 nofirst = false;
578 for (const auto& node: constraintNoParentNodes_.nodes()) {
579 if (nofirst) res += ", ";
580 else nofirst = true;
581 res += nameFromId(node);
582 }
583 res += "}";
584 vals.emplace_back("Constraint No Parent Nodes", res, "");
585 }
586 if (!constraintNoChildrenNodes_.nodes().empty()) {
587 res = "{";
588 nofirst = false;
589 for (const auto& node: constraintNoChildrenNodes_.nodes()) {
590 if (nofirst) res += ", ";
591 else nofirst = true;
592 res += nameFromId(node);
593 }
594 res += "}";
595 vals.emplace_back("Constraint No Children Nodes", res, "");
596 }
597 if (initialDag_.size() != 0) {
598 vals.emplace_back("Initial DAG", "True", initialDag_.toDot());
599 }
600
601 return vals;
602 }
603
604 template < GUM_Numeric GUM_SCALAR >
605 void BNLearner< GUM_SCALAR >::copyState(const BNLearner< GUM_SCALAR >& learner) {
606 switch (learner.selectedAlgo_) {
607 case AlgoType::EXTENDED_GREEDY_HILL_CLIMBING : useExtendedGreedyHillClimbing(); break;
608 case AlgoType::GREEDY_HILL_CLIMBING : useGreedyHillClimbing(); break;
609 case AlgoType::GREEDY_THICK_THINNING :
610 useGreedyThickThinning();
611 setGreedyThickThinningReversals(learner.greedyThickThinningReversals());
612 break;
613 case AlgoType::K2 : useK2(learner.algoK2_.order()); break;
614 case AlgoType::LOCAL_SEARCH_WITH_TABU_LIST :
615 useLocalSearchWithTabuList(learner.nbDecreasingChanges_);
616 break;
617 case AlgoType::MIIC : useMIIC(); break;
618 case AlgoType::PC : usePC(); break;
619 case AlgoType::FCI : useFCI(); break;
620 }
621
622 switch (learner.scoreType_) {
623 case ScoreType::K2 : useScoreK2(); break;
624 case ScoreType::AIC : useScoreAIC(); break;
625 case ScoreType::BIC : useScoreBIC(); break;
626 case ScoreType::BD : useScoreBD(); break;
627 case ScoreType::BDeu : useScoreBDeu(); break;
628 case ScoreType::fNML : useScorefNML(); break;
629 case ScoreType::MDL : useScoreMDL(); break;
630 case ScoreType::LOG2LIKELIHOOD : useScoreLog2Likelihood(); break;
631 }
632
633 switch (learner.kmodeMiic_) {
634 case CorrectedMutualInformation::KModeTypes::MDL : useMDLCorrection(); break;
635 case CorrectedMutualInformation::KModeTypes::NML : useNMLCorrection(); break;
636 case CorrectedMutualInformation::KModeTypes::NoCorr : useNoCorrection(); break;
637 }
638
639 switch (learner.priorType_) {
640 case BNLearnerPriorType::NO_prior : useNoPrior(); break;
641 case BNLearnerPriorType::DIRICHLET_FROM_DATABASE :
642 useDirichletPrior(learner.priorDbname_, learner.priorWeight_);
643 break;
644 case BNLearnerPriorType::DIRICHLET_FROM_BAYESNET :
645 useDirichletPrior(learner._prior_bn_);
646 break;
647 case BNLearnerPriorType::BDEU : useBDeuPrior(learner.priorWeight_); break;
648 case BNLearnerPriorType::SMOOTHING : useSmoothingPrior(learner.priorWeight_); break;
649 }
650
651 useEM_ = learner.useEM_;
652 noiseEM_ = learner.noiseEM_;
653 dag2BN_ = learner.dag2BN_;
654
655 setMaxIndegree(learner.constraintIndegree_.maxIndegree());
656 for (const auto src: learner.constraintNoParentNodes_.nodes()) {
657 try {
658 const auto dst = idFromName(learner.nameFromId(src));
659 addNoParentNode(dst);
660 } catch (const MissingVariableInDatabase&) {
661 // nothing to do
662 }
663 }
664 for (const auto src: learner.constraintNoChildrenNodes_.nodes()) {
665 try {
666 const auto dst = idFromName(learner.nameFromId(src));
667 addNoChildrenNode(dst);
668 } catch (const MissingVariableInDatabase&) {
669 // nothing to do
670 }
671 }
672 for (const auto& arc: learner.constraintForbiddenArcs_.arcs()) {
673 try {
674 const auto src = idFromName(learner.nameFromId(arc.tail()));
675 const auto dst = idFromName(learner.nameFromId(arc.head()));
676 addForbiddenArc(src, dst);
677 } catch (const MissingVariableInDatabase&) {
678 // nothing to do
679 }
680 }
681 for (const auto& arc: learner.constraintMandatoryArcs_.arcs()) {
682 try {
683 const auto src = idFromName(learner.nameFromId(arc.tail()));
684 const auto dst = idFromName(learner.nameFromId(arc.head()));
685 addMandatoryArc(src, dst);
686 } catch (const MissingVariableInDatabase&) {
687 // nothing to do
688 }
689 }
690 for (const auto& edge: learner.constraintPossibleEdges_.edges()) {
691 try {
692 const auto src = idFromName(learner.nameFromId(edge.first()));
693 const auto dst = idFromName(learner.nameFromId(edge.second()));
694 addPossibleEdge(src, dst);
695 } catch (const MissingVariableInDatabase&) {
696 // nothing to do
697 }
698 }
699 if (!learner.constraintSliceOrder_.sliceOrder().empty()) {
700 NodeProperty< NodeId > slice_order;
701 for (const auto& p: learner.constraintSliceOrder_.sliceOrder()) {
702 try {
703 slice_order.insert(idFromName(learner.nameFromId(p.first)), p.second);
704 } catch (const MissingVariableInDatabase&) {
705 // nothing to do
706 }
707 }
708 setSliceOrder(slice_order);
709 }
710 if (!learner.constraintTotalOrder_.totalOrder().empty()) {
711 setTotalOrder(learner.constraintTotalOrder_.totalOrder());
712 }
713 }
714
715 template < GUM_Numeric GUM_SCALAR >
716 void BNLearner< GUM_SCALAR >::createPrior_() {
717 // first, save the old prior, to be delete if everything is ok
718 Prior* old_prior = prior_;
719
720 // create the new prior
721 switch (priorType_) {
722 case BNLearnerPriorType::NO_prior :
723 prior_ = new NoPrior(scoreDatabase_.databaseTable(), scoreDatabase_.nodeId2Columns());
724 break;
725
726 case BNLearnerPriorType::SMOOTHING :
727 prior_
728 = new SmoothingPrior(scoreDatabase_.databaseTable(), scoreDatabase_.nodeId2Columns());
729 break;
730
731 case BNLearnerPriorType::DIRICHLET_FROM_DATABASE :
732 if (priorDatabase_ != nullptr) {
733 delete priorDatabase_;
734 priorDatabase_ = nullptr;
735 }
736
737 priorDatabase_
738 = new Database(priorDbname_, scoreDatabase_, scoreDatabase_.missingSymbols());
739
740 prior_ = new DirichletPriorFromDatabase(scoreDatabase_.databaseTable(),
741 priorDatabase_->parser(),
742 priorDatabase_->nodeId2Columns());
743 break;
744
745 case BNLearnerPriorType::DIRICHLET_FROM_BAYESNET :
746 prior_
747 = new DirichletPriorFromBN< GUM_SCALAR >(scoreDatabase_.databaseTable(), &_prior_bn_);
748 break;
749
750 case BNLearnerPriorType::BDEU :
751 prior_ = new BDeuPrior(scoreDatabase_.databaseTable(), scoreDatabase_.nodeId2Columns());
752 break;
753
754 default : GUM_ERROR(OperationNotAllowed, "The BNLearner does not support yet this prior")
755 }
756
757 // do not forget to assign a weight to the prior
758 prior_->setWeight(priorWeight_);
759
760 // remove the old prior, if any
761 if (old_prior != nullptr) delete old_prior;
762 }
763
764 template < GUM_Numeric GUM_SCALAR >
765 std::ostream& operator<<(std::ostream& output, const BNLearner< GUM_SCALAR >& learner) {
766 output << learner.toString();
767 return output;
768 }
769
770 // =========================================================================
771 // Delegation methods — each calls IBNLearner and returns *this
772 // =========================================================================
773
774 template < GUM_Numeric GUM_SCALAR >
775 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::setInitialDAG(const DAG& dag) {
776 IBNLearner::setInitialDAG(dag);
777 return *this;
778 }
779
780 template < GUM_Numeric GUM_SCALAR >
781 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useEM(const double epsilon,
782 const double noise) {
783 IBNLearner::useEM(epsilon, noise);
784 return *this;
785 }
786
787 template < GUM_Numeric GUM_SCALAR >
788 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useEMWithRateCriterion(const double epsilon,
789 const double noise) {
790 IBNLearner::useEMWithRateCriterion(epsilon, noise);
791 return *this;
792 }
793
794 template < GUM_Numeric GUM_SCALAR >
795 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useEMWithDiffCriterion(const double epsilon,
796 const double noise) {
797 IBNLearner::useEMWithDiffCriterion(epsilon, noise);
798 return *this;
799 }
800
801 template < GUM_Numeric GUM_SCALAR >
802 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::forbidEM() {
803 IBNLearner::forbidEM();
804 return *this;
805 }
806
807 template < GUM_Numeric GUM_SCALAR >
808 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::EMsetEpsilon(const double eps) {
809 IBNLearner::EMsetEpsilon(eps);
810 return *this;
811 }
812
813 template < GUM_Numeric GUM_SCALAR >
814 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::EMdisableEpsilon() {
815 IBNLearner::EMdisableEpsilon();
816 return *this;
817 }
818
819 template < GUM_Numeric GUM_SCALAR >
820 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::EMenableEpsilon() {
821 IBNLearner::EMenableEpsilon();
822 return *this;
823 }
824
825 template < GUM_Numeric GUM_SCALAR >
826 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::EMsetMinEpsilonRate(const double rate) {
827 IBNLearner::EMsetMinEpsilonRate(rate);
828 return *this;
829 }
830
831 template < GUM_Numeric GUM_SCALAR >
832 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::EMdisableMinEpsilonRate() {
833 IBNLearner::EMdisableMinEpsilonRate();
834 return *this;
835 }
836
837 template < GUM_Numeric GUM_SCALAR >
838 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::EMenableMinEpsilonRate() {
839 IBNLearner::EMenableMinEpsilonRate();
840 return *this;
841 }
842
843 template < GUM_Numeric GUM_SCALAR >
844 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::EMsetMaxIter(const Size max) {
845 IBNLearner::EMsetMaxIter(max);
846 return *this;
847 }
848
849 template < GUM_Numeric GUM_SCALAR >
850 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::EMdisableMaxIter() {
851 IBNLearner::EMdisableMaxIter();
852 return *this;
853 }
854
855 template < GUM_Numeric GUM_SCALAR >
856 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::EMenableMaxIter() {
857 IBNLearner::EMenableMaxIter();
858 return *this;
859 }
860
861 template < GUM_Numeric GUM_SCALAR >
862 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::EMsetMaxTime(const double timeout) {
863 IBNLearner::EMsetMaxTime(timeout);
864 return *this;
865 }
866
867 template < GUM_Numeric GUM_SCALAR >
868 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::EMdisableMaxTime() {
869 IBNLearner::EMdisableMaxTime();
870 return *this;
871 }
872
873 template < GUM_Numeric GUM_SCALAR >
874 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::EMenableMaxTime() {
875 IBNLearner::EMenableMaxTime();
876 return *this;
877 }
878
879 template < GUM_Numeric GUM_SCALAR >
880 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::EMsetPeriodSize(const Size p) {
881 IBNLearner::EMsetPeriodSize(p);
882 return *this;
883 }
884
885 template < GUM_Numeric GUM_SCALAR >
886 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::EMsetVerbosity(const bool v) {
887 IBNLearner::EMsetVerbosity(v);
888 return *this;
889 }
890
891 template < GUM_Numeric GUM_SCALAR >
892 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useScoreAIC() {
893 IBNLearner::useScoreAIC();
894 return *this;
895 }
896
897 template < GUM_Numeric GUM_SCALAR >
898 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useScoreBD() {
899 IBNLearner::useScoreBD();
900 return *this;
901 }
902
903 template < GUM_Numeric GUM_SCALAR >
904 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useScoreBDeu() {
905 IBNLearner::useScoreBDeu();
906 return *this;
907 }
908
909 template < GUM_Numeric GUM_SCALAR >
910 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useScoreBIC() {
911 IBNLearner::useScoreBIC();
912 return *this;
913 }
914
915 template < GUM_Numeric GUM_SCALAR >
916 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useScoreK2() {
917 IBNLearner::useScoreK2();
918 return *this;
919 }
920
921 template < GUM_Numeric GUM_SCALAR >
922 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useScoreLog2Likelihood() {
923 IBNLearner::useScoreLog2Likelihood();
924 return *this;
925 }
926
927 template < GUM_Numeric GUM_SCALAR >
928 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useNoPrior() {
929 IBNLearner::useNoPrior();
930 return *this;
931 }
932
933 template < GUM_Numeric GUM_SCALAR >
934 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useBDeuPrior(double weight) {
935 IBNLearner::useBDeuPrior(weight);
936 return *this;
937 }
938
939 template < GUM_Numeric GUM_SCALAR >
940 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useSmoothingPrior(double weight) {
941 IBNLearner::useSmoothingPrior(weight);
942 return *this;
943 }
944
945 template < GUM_Numeric GUM_SCALAR >
946 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useDirichletPrior(std::string_view filename,
947 double weight) {
948 IBNLearner::useDirichletPrior(filename, weight);
949 return *this;
950 }
951
952 template < GUM_Numeric GUM_SCALAR >
953 BNLearner< GUM_SCALAR >&
954 BNLearner< GUM_SCALAR >::useDirichletPrior(const gum::BayesNet< GUM_SCALAR >& bn,
955 double weight) {
956 _prior_bn_ = bn;
957 priorType_ = BNLearnerPriorType::DIRICHLET_FROM_BAYESNET;
958 _setPriorWeight_(weight);
959 return *this;
960 }
961
962 template < GUM_Numeric GUM_SCALAR >
963 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useGreedyHillClimbing() {
964 IBNLearner::useGreedyHillClimbing();
965 return *this;
966 }
967
968 template < GUM_Numeric GUM_SCALAR >
969 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useExtendedGreedyHillClimbing() {
970 IBNLearner::useExtendedGreedyHillClimbing();
971 return *this;
972 }
973
974 template < GUM_Numeric GUM_SCALAR >
975 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useGreedyThickThinning() {
976 IBNLearner::useGreedyThickThinning();
977 return *this;
978 }
979
980 template < GUM_Numeric GUM_SCALAR >
981 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::setGreedyThickThinningReversals(bool allow) {
982 IBNLearner::setGreedyThickThinningReversals(allow);
983 return *this;
984 }
985
986 template < GUM_Numeric GUM_SCALAR >
987 bool BNLearner< GUM_SCALAR >::greedyThickThinningReversals() const {
988 return IBNLearner::greedyThickThinningReversals();
989 }
990
991 template < GUM_Numeric GUM_SCALAR >
992 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useLocalSearchWithTabuList(Size tabu_size,
993 Size nb_decrease) {
994 IBNLearner::useLocalSearchWithTabuList(tabu_size, nb_decrease);
995 return *this;
996 }
997
998 template < GUM_Numeric GUM_SCALAR >
999 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useK2(const Sequence< NodeId >& order) {
1000 IBNLearner::useK2(order);
1001 return *this;
1002 }
1003
1004 template < GUM_Numeric GUM_SCALAR >
1005 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useK2(const std::vector< NodeId >& order) {
1006 IBNLearner::useK2(order);
1007 return *this;
1008 }
1009
1010 template < GUM_Numeric GUM_SCALAR >
1011 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useMIIC() {
1012 IBNLearner::useMIIC();
1013 return *this;
1014 }
1015
1016 template < GUM_Numeric GUM_SCALAR >
1017 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::usePC() {
1018 IBNLearner::usePC();
1019 return *this;
1020 }
1021
1022 template < GUM_Numeric GUM_SCALAR >
1023 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useFCI() {
1024 IBNLearner::useFCI();
1025 return *this;
1026 }
1027
1028 template < GUM_Numeric GUM_SCALAR >
1029 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useFCIChi2Test() {
1030 IBNLearner::useFCIChi2Test();
1031 return *this;
1032 }
1033
1034 template < GUM_Numeric GUM_SCALAR >
1035 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useFCIG2Test() {
1036 IBNLearner::useFCIG2Test();
1037 return *this;
1038 }
1039
1040 template < GUM_Numeric GUM_SCALAR >
1041 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::setFCIAlpha(double alpha) {
1042 IBNLearner::setFCIAlpha(alpha);
1043 return *this;
1044 }
1045
1046 template < GUM_Numeric GUM_SCALAR >
1047 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::setFCIMaxPathLength(Size max_len) {
1048 IBNLearner::setFCIMaxPathLength(max_len);
1049 return *this;
1050 }
1051
1052 template < GUM_Numeric GUM_SCALAR >
1053 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::setFCIExhaustiveSepSet(bool exhaustive) {
1054 IBNLearner::setFCIExhaustiveSepSet(exhaustive);
1055 return *this;
1056 }
1057
1058 template < GUM_Numeric GUM_SCALAR >
1059 bool BNLearner< GUM_SCALAR >::fciExhaustiveSepSet() const {
1060 return IBNLearner::fciExhaustiveSepSet();
1061 }
1062
1063 template < GUM_Numeric GUM_SCALAR >
1064 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useChi2Test() {
1065 IBNLearner::useChi2Test();
1066 return *this;
1067 }
1068
1069 template < GUM_Numeric GUM_SCALAR >
1070 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useG2Test() {
1071 IBNLearner::useG2Test();
1072 return *this;
1073 }
1074
1075 template < GUM_Numeric GUM_SCALAR >
1076 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::setPCAlpha(double alpha) {
1077 IBNLearner::setPCAlpha(alpha);
1078 return *this;
1079 }
1080
1081 template < GUM_Numeric GUM_SCALAR >
1082 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::setPCStable(bool stable) {
1083 IBNLearner::setPCStable(stable);
1084 return *this;
1085 }
1086
1087 template < GUM_Numeric GUM_SCALAR >
1088 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::setPCMaxCondSetSize(Size max_k) {
1089 IBNLearner::setPCMaxCondSetSize(max_k);
1090 return *this;
1091 }
1092
1093 template < GUM_Numeric GUM_SCALAR >
1094 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::setPCUnshieldedColliderSorted(bool sorted) {
1095 IBNLearner::setPCUnshieldedColliderSorted(sorted);
1096 return *this;
1097 }
1098
1099 template < GUM_Numeric GUM_SCALAR >
1100 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useNMLCorrection() {
1101 IBNLearner::useNMLCorrection();
1102 return *this;
1103 }
1104
1105 template < GUM_Numeric GUM_SCALAR >
1106 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useMDLCorrection() {
1107 IBNLearner::useMDLCorrection();
1108 return *this;
1109 }
1110
1111 template < GUM_Numeric GUM_SCALAR >
1112 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::useNoCorrection() {
1113 IBNLearner::useNoCorrection();
1114 return *this;
1115 }
1116
1117 template < GUM_Numeric GUM_SCALAR >
1118 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::setMaxIndegree(Size max_indegree) {
1119 IBNLearner::setMaxIndegree(max_indegree);
1120 return *this;
1121 }
1122
1123 template < GUM_Numeric GUM_SCALAR >
1124 BNLearner< GUM_SCALAR >&
1125 BNLearner< GUM_SCALAR >::setSliceOrder(const NodeProperty< NodeId >& slice_order) {
1126 IBNLearner::setSliceOrder(slice_order);
1127 return *this;
1128 }
1129
1130 template < GUM_Numeric GUM_SCALAR >
1131 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::setSliceOrder(
1132 const std::vector< std::vector< std::string > >& slices) {
1133 IBNLearner::setSliceOrder(slices);
1134 return *this;
1135 }
1136
1137 template < GUM_Numeric GUM_SCALAR >
1138 BNLearner< GUM_SCALAR >&
1139 BNLearner< GUM_SCALAR >::setTotalOrder(const std::vector< std::string >& order) {
1140 IBNLearner::setTotalOrder(order);
1141 return *this;
1142 }
1143
1144 template < GUM_Numeric GUM_SCALAR >
1145 BNLearner< GUM_SCALAR >&
1146 BNLearner< GUM_SCALAR >::setTotalOrder(const Sequence< NodeId >& order) {
1147 IBNLearner::setTotalOrder(order);
1148 return *this;
1149 }
1150
1151 template < GUM_Numeric GUM_SCALAR >
1152 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::setForbiddenArcs(const ArcSet& set) {
1153 IBNLearner::setForbiddenArcs(set);
1154 return *this;
1155 }
1156
1157 template < GUM_Numeric GUM_SCALAR >
1158 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::addForbiddenArc(const Arc& arc) {
1159 IBNLearner::addForbiddenArc(arc);
1160 return *this;
1161 }
1162
1163 template < GUM_Numeric GUM_SCALAR >
1164 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::addForbiddenArc(NodeId tail, NodeId head) {
1165 IBNLearner::addForbiddenArc(tail, head);
1166 return *this;
1167 }
1168
1169 template < GUM_Numeric GUM_SCALAR >
1170 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::addForbiddenArc(std::string_view tail,
1171 std::string_view head) {
1172 IBNLearner::addForbiddenArc(tail, head);
1173 return *this;
1174 }
1175
1176 template < GUM_Numeric GUM_SCALAR >
1177 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::eraseForbiddenArc(const Arc& arc) {
1178 IBNLearner::eraseForbiddenArc(arc);
1179 return *this;
1180 }
1181
1182 template < GUM_Numeric GUM_SCALAR >
1183 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::eraseForbiddenArc(NodeId tail, NodeId head) {
1184 IBNLearner::eraseForbiddenArc(tail, head);
1185 return *this;
1186 }
1187
1188 template < GUM_Numeric GUM_SCALAR >
1189 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::eraseForbiddenArc(std::string_view tail,
1190 std::string_view head) {
1191 IBNLearner::eraseForbiddenArc(tail, head);
1192 return *this;
1193 }
1194
1195 template < GUM_Numeric GUM_SCALAR >
1196 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::addMandatoryArc(const Arc& arc) {
1197 IBNLearner::addMandatoryArc(arc);
1198 return *this;
1199 }
1200
1201 template < GUM_Numeric GUM_SCALAR >
1202 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::addMandatoryArc(NodeId tail, NodeId head) {
1203 IBNLearner::addMandatoryArc(tail, head);
1204 return *this;
1205 }
1206
1207 template < GUM_Numeric GUM_SCALAR >
1208 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::addMandatoryArc(std::string_view tail,
1209 std::string_view head) {
1210 IBNLearner::addMandatoryArc(tail, head);
1211 return *this;
1212 }
1213
1214 template < GUM_Numeric GUM_SCALAR >
1215 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::eraseMandatoryArc(const Arc& arc) {
1216 IBNLearner::eraseMandatoryArc(arc);
1217 return *this;
1218 }
1219
1220 template < GUM_Numeric GUM_SCALAR >
1221 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::eraseMandatoryArc(NodeId tail, NodeId head) {
1222 IBNLearner::eraseMandatoryArc(tail, head);
1223 return *this;
1224 }
1225
1226 template < GUM_Numeric GUM_SCALAR >
1227 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::eraseMandatoryArc(std::string_view tail,
1228 std::string_view head) {
1229 IBNLearner::eraseMandatoryArc(tail, head);
1230 return *this;
1231 }
1232
1233 template < GUM_Numeric GUM_SCALAR >
1234 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::addPossibleEdge(const Edge& edge) {
1235 IBNLearner::addPossibleEdge(edge);
1236 return *this;
1237 }
1238
1239 template < GUM_Numeric GUM_SCALAR >
1240 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::addPossibleEdge(NodeId tail, NodeId head) {
1241 IBNLearner::addPossibleEdge(tail, head);
1242 return *this;
1243 }
1244
1245 template < GUM_Numeric GUM_SCALAR >
1246 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::addPossibleEdge(std::string_view tail,
1247 std::string_view head) {
1248 IBNLearner::addPossibleEdge(tail, head);
1249 return *this;
1250 }
1251
1252 template < GUM_Numeric GUM_SCALAR >
1253 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::erasePossibleEdge(const Edge& edge) {
1254 IBNLearner::erasePossibleEdge(edge);
1255 return *this;
1256 }
1257
1258 template < GUM_Numeric GUM_SCALAR >
1259 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::erasePossibleEdge(NodeId tail, NodeId head) {
1260 IBNLearner::erasePossibleEdge(tail, head);
1261 return *this;
1262 }
1263
1264 template < GUM_Numeric GUM_SCALAR >
1265 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::erasePossibleEdge(std::string_view tail,
1266 std::string_view head) {
1267 IBNLearner::erasePossibleEdge(tail, head);
1268 return *this;
1269 }
1270
1271 template < GUM_Numeric GUM_SCALAR >
1272 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::setMandatoryArcs(const ArcSet& set) {
1273 IBNLearner::setMandatoryArcs(set);
1274 return *this;
1275 }
1276
1277 template < GUM_Numeric GUM_SCALAR >
1278 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::setPossibleEdges(const EdgeSet& set) {
1279 IBNLearner::setPossibleEdges(set);
1280 return *this;
1281 }
1282
1283 template < GUM_Numeric GUM_SCALAR >
1284 BNLearner< GUM_SCALAR >&
1285 BNLearner< GUM_SCALAR >::setPossibleSkeleton(const UndiGraph& skeleton) {
1286 IBNLearner::setPossibleSkeleton(skeleton);
1287 return *this;
1288 }
1289
1290 template < GUM_Numeric GUM_SCALAR >
1291 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::addNoParentNode(NodeId node) {
1292 IBNLearner::addNoParentNode(node);
1293 return *this;
1294 }
1295
1296 template < GUM_Numeric GUM_SCALAR >
1297 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::addNoParentNode(std::string_view name) {
1298 IBNLearner::addNoParentNode(name);
1299 return *this;
1300 }
1301
1302 template < GUM_Numeric GUM_SCALAR >
1303 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::eraseNoParentNode(NodeId node) {
1304 IBNLearner::eraseNoParentNode(node);
1305 return *this;
1306 }
1307
1308 template < GUM_Numeric GUM_SCALAR >
1309 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::eraseNoParentNode(std::string_view name) {
1310 IBNLearner::eraseNoParentNode(name);
1311 return *this;
1312 }
1313
1314 template < GUM_Numeric GUM_SCALAR >
1315 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::addNoChildrenNode(NodeId node) {
1316 IBNLearner::addNoChildrenNode(node);
1317 return *this;
1318 }
1319
1320 template < GUM_Numeric GUM_SCALAR >
1321 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::addNoChildrenNode(std::string_view name) {
1322 IBNLearner::addNoChildrenNode(name);
1323 return *this;
1324 }
1325
1326 template < GUM_Numeric GUM_SCALAR >
1327 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::eraseNoChildrenNode(NodeId node) {
1328 IBNLearner::eraseNoChildrenNode(node);
1329 return *this;
1330 }
1331
1332 template < GUM_Numeric GUM_SCALAR >
1333 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::eraseNoChildrenNode(std::string_view name) {
1334 IBNLearner::eraseNoChildrenNode(name);
1335 return *this;
1336 }
1337
1338 template < GUM_Numeric GUM_SCALAR >
1339 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::allowArcAdditions(bool allow) {
1340 IBNLearner::allowArcAdditions(allow);
1341 return *this;
1342 }
1343
1344 template < GUM_Numeric GUM_SCALAR >
1345 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::allowArcDeletions(bool allow) {
1346 IBNLearner::allowArcDeletions(allow);
1347 return *this;
1348 }
1349
1350 template < GUM_Numeric GUM_SCALAR >
1351 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::allowArcReversals(bool allow) {
1352 IBNLearner::allowArcReversals(allow);
1353 return *this;
1354 }
1355
1356 template < GUM_Numeric GUM_SCALAR >
1357 BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::allowArcTriangleDeletions(bool allow) {
1358 IBNLearner::allowArcTriangleDeletions(allow);
1359 return *this;
1360 }
1361
1362 template < GUM_Numeric GUM_SCALAR >
1363 bool BNLearner< GUM_SCALAR >::isConstraintBased() const {
1364 return IBNLearner::isConstraintBased();
1365 }
1366
1367 template < GUM_Numeric GUM_SCALAR >
1368 bool BNLearner< GUM_SCALAR >::isScoreBased() const {
1369 return IBNLearner::isScoreBased();
1370 }
1371
1372 } /* namespace learning */
1373
1374} /* namespace gum */
1375
1376#endif /* DOXYGEN_SHOULD_SKIP_THIS */
A listener that allows BNLearner to be used as a proxy for its inner algorithms.
A basic pack of learning algorithms that can easily be used.
Class representing a Bayesian network.
Definition BayesNet.h:99
Error: The database contains some missing values.
Error: A name of variable is not found in the database.
Exception : operation not allowed.
BNLearner(std::string_view filename, const std::vector< std::string > &missingSymbols={"?"}, const bool induceTypes=true)
default constructor
A pack of learning algorithms that can easily be used.
Definition IBNLearner.h:104
#define GUM_ERROR(type, msg)
Definition exceptions.h:76
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition types.h:74
Size Idx
Type for indexes.
Definition types.h:79
Size NodeId
Type for node ids.
include the inlined functions if necessary
Definition CSVParser.h:55
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
std::ostream & operator<<(std::ostream &out, const TiXmlNode &base)
Definition tinyxml.cpp:1516