aGrUM 3.2.0
a C++ library for (probabilistic) graphical models
XDSLBNReader_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
44#include <agrum/BN/io/XDSL/XDSLBNReader.h> // to ease IDE parser
45#ifndef DOXYGEN_SHOULD_SKIP_THIS
47
49
50namespace gum {
51 /*
52 * Constructor
53 * A reader is created to reading a defined file.
54 * Note that an BN has to be created before and given in parameter.
55 */
56 template < GUM_Numeric GUM_SCALAR >
58 BNReader< GUM_SCALAR >(bn, filePath) {
59 GUM_CONSTRUCTOR(XDSLBNReader);
60 _bn_ = bn;
61 _filePath_ = filePath;
62 }
63
64 /*
65 * Default destructor.
66 */
67 template < GUM_Numeric GUM_SCALAR >
68 XDSLBNReader< GUM_SCALAR >::~XDSLBNReader() {
69 GUM_DESTRUCTOR(XDSLBNReader);
70 }
71
72 /*
73 * Reads the bayes net from the file referenced by filePath given at the
74 * creation
75 * of class
76 * @return Returns the number of error during the parsing (0 if none).
77 */
78 template < GUM_Numeric GUM_SCALAR >
79 Size XDSLBNReader< GUM_SCALAR >::proceed() {
80 try {
81 // Loading file
82 std::string status = "Loading File ...";
83 GUM_EMIT2(onProceed, 0, status);
84
85 XmlDocument xmlDoc(_filePath_);
86 xmlDoc.loadFile();
87
88 if (xmlDoc.noChildren()) {
89 GUM_ERROR(IOError, ": Loading fail, please check the file for any syntax error.")
90 }
91
92 // Finding BIF element
93 status = "File loaded. Now looking for DSL element ...";
94 GUM_EMIT2(onProceed, 4, status);
95
96 XmlElement bifElement = xmlDoc.firstChildElement("smile");
97 std::string netName = "unnamedBN";
98 bifElement.attribute("id", &netName, false);
99 _bn_->setProperty("name", netName);
100
101 // Finding network element
102 status = "smile Element reached. Now searching network ...";
103 GUM_EMIT2(onProceed, 7, status);
104
105 XmlElement nodesElement = bifElement.firstChildElement("nodes");
106
107 // Finding id variables
108 status = "Network found. Now proceeding variables instantiation...";
109 GUM_EMIT2(onProceed, 10, status);
110
111 _parsingCpts_(nodesElement);
112
113 // Filling diagram
114 status = "All variables have been instantiated. Now filling up diagram...";
115 GUM_EMIT2(onProceed, 55, status);
116
117 XmlElement extensionsElement
118 = bifElement.firstChildElement("extensions").firstChildElement("genie");
119
120 // Filling diagram
121 _parsingExtension_(extensionsElement);
122 status = "All variables have been renamed. Now filling up diagram...";
123 GUM_EMIT2(onProceed, 85, status);
124
125
126 status = "Instantiation of network completed";
127 GUM_EMIT2(onProceed, 100, status);
128
129 return 0;
130 } catch (XmlException& xmlException) { GUM_ERROR(IOError, xmlException.what()) }
131 }
132
133 template < GUM_Numeric GUM_SCALAR >
134 Size XDSLBNReader< GUM_SCALAR >::_parsingCpts_(XmlElement cptsNetwork) {
135 // Counting the number of variable for the signal
136 Size nbVar = Size(0);
137 for (const auto& _: cptsNetwork.children("cpt"))
138 nbVar++;
139 nbVar = 3 * nbVar; // 3 loops on vars
140 std::string status = "Network found. Now proceeding variables instantiation...";
141
142 // Iterating on variable element
143 int nbIte = 0;
144
145 // definition of the variables
146 for (const auto& currentVar: cptsNetwork.children("cpt")) {
147 // Getting variable name
148 std::string varName = currentVar.attribute("id");
149 std::string varDescription = varName;
150
151 // Instanciation de la variable
152 auto newVar = new LabelizedVariable(varName, varDescription, 0);
153
154 // Getting variable outcomes
155 for (const auto& state: currentVar.children("state"))
156 newVar->addLabel(state.attribute("id"));
157
158 // Add the variable to the bn and then delete newVar (add makes a copy)
159 _bn_->add(*newVar);
160 delete (newVar);
161
162 // Emitting progress.
163 int progress = (int)((float)nbIte / (float)nbVar * 45) + 10;
164 GUM_EMIT2(onProceed, progress, status);
165 nbIte++;
166 }
167
168 // ADDING ARCS and then CPTS
169 for (const auto& currentVar: cptsNetwork.children("cpt")) {
170 std::string varName = currentVar.attribute("id");
171
172 auto parentsElt = currentVar.firstChildElement("parents", false);
173 if (!parentsElt.isNull()) {
174 // iteration in the list of parents in reverse order
175 const auto& strvec = split(parentsElt.textOrDefault(""), " ");
176 for (auto rit = strvec.begin(); rit != strvec.end(); ++rit)
177 _bn_->addArc(*rit, varName);
178 }
179
180 std::istringstream issTableString(
181 currentVar.firstChildElement("probabilities").textOrDefault(""));
182 std::vector< GUM_SCALAR > tablevector;
183 GUM_SCALAR value;
184
185 while (!issTableString.eof()) {
186 issTableString >> value;
187 tablevector.push_back(value);
188 }
189
190 // Filling tables
191 _bn_->cpt(varName).fillWith(tablevector);
192 }
193
194 //
195 return nbIte;
196 }
197
198 template < GUM_Numeric GUM_SCALAR >
199 void XDSLBNReader< GUM_SCALAR >::_parsingExtension_(XmlElement nodesNetwork) {
200 for (const auto& currentVar: nodesNetwork.children("node")) {
201 std::string varName = currentVar.attribute("id");
202 std::string descName = currentVar.firstChildElement("name").textOrDefault("");
203 if (descName != varName) _bn_->changeVariableName(varName, descName);
204 }
205 }
206} /* namespace gum */
207
208#endif // DOXYGEN_SHOULD_SKIP_THIS
classe for import of bayes net from a XML file written with BIF Format
Pure virtual class for reading a BN from a file.
Definition BNReader.h:78
Class representing a Bayesian network.
Definition BayesNet.h:99
GUM_NODISCARD const char * what() const noexcept override
Exception : input/output problem.
XDSLBNReader(BayesNet< GUM_SCALAR > *bn, std::string_view filePath)
Constructor A reader is created to reading a defined file.
#define GUM_ERROR(type, msg)
Definition exceptions.h:76
std::vector< std::string > split(std::string_view str, std::string_view delim)
Split str using the delimiter.
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
#define GUM_EMIT2(signal, arg1, arg2)
Definition signaler.h:290
Utilities for manipulating strings.