aGrUM 3.1.1
a C++ library for (probabilistic) graphical models
UAIBNReader_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/UAI/UAIBNReader.h> // to ease IDE parser
45#ifndef DOXYGEN_SHOULD_SKIP_THIS
46
47namespace gum {
48
49 template < GUM_Numeric GUM_SCALAR >
51 BNReader< GUM_SCALAR >(bn, filename) {
52 GUM_CONSTRUCTOR(UAIBNReader);
53 _bn_ = bn;
54 _streamName_ = filename;
55 _parseDone_ = false;
56
57 _ioerror_ = false;
58
59 try {
60 _scanner_ = new UAIBN::Scanner(_streamName_.c_str());
61 _parser_ = new UAIBN::Parser(_scanner_);
62 } catch (IOError const&) { _ioerror_ = true; }
63 }
64
65 template < GUM_Numeric GUM_SCALAR >
66 UAIBNReader< GUM_SCALAR >::~UAIBNReader() {
67 GUM_DESTRUCTOR(UAIBNReader);
68
69 if (!_ioerror_) {
70 // this could lead to memory leak !!
71 if (_parser_) delete (_parser_);
72
73 if (_scanner_) delete (_scanner_);
74 }
75 }
76
77 template < GUM_Numeric GUM_SCALAR >
78 UAIBN::Scanner& UAIBNReader< GUM_SCALAR >::scanner() {
79 if (_ioerror_) { GUM_ERROR(gum::IOError, "No such file " + streamName()) }
80
81 return *_scanner_;
82 }
83
84 template < GUM_Numeric GUM_SCALAR >
85 const std::string& UAIBNReader< GUM_SCALAR >::streamName() const {
86 return _streamName_;
87 }
88
89 template < GUM_Numeric GUM_SCALAR >
90 bool UAIBNReader< GUM_SCALAR >::trace() const {
91 return _traceScanning_;
92 }
93
94 template < GUM_Numeric GUM_SCALAR >
95 void UAIBNReader< GUM_SCALAR >::trace(bool b) {
96 _traceScanning_ = b;
97 scanner().setTrace(b);
98 }
99
100 template < GUM_Numeric GUM_SCALAR >
101 Size UAIBNReader< GUM_SCALAR >::proceed() {
102 if (_ioerror_) { GUM_ERROR(gum::IOError, "No such file " + streamName()) }
103
104 if (!_parseDone_) {
105 try {
106 _parser_->Parse();
107 _parseDone_ = true;
108 buildFromQuartets(_parser_->getQuartets());
109 } catch (gum::Exception& e) {
110 GUM_SHOWERROR(e);
111 return 1 + _parser_->errors().error_count;
112 }
113 }
114
115 return (_parser_->errors().error_count);
116 }
117
118 template < GUM_Numeric GUM_SCALAR >
119 void UAIBNReader< GUM_SCALAR >::buildFromQuartets(
120 std::vector< std::tuple< float, int, int, int > > quartets) {
121 Idx current;
122 Size max = quartets.size();
123 if (max == 0) {
124 _addWarning_(1, 1, "Empty BayesNet");
125 return;
126 }
127
128 auto isInt = [&]() -> bool { return (std::get< 0 >(quartets[current]) == -1); };
129 auto lig = [&]() -> int { return std::get< 2 >(quartets[current]); };
130 auto col = [&]() -> int { return std::get< 3 >(quartets[current]); };
131
132 auto getInt = [&]() -> int {
133 if (!isInt()) this->_addFatalError_(lig(), col(), "int expected");
134 return std::get< 1 >(quartets[current]);
135 };
136 auto getVal = [&]() -> GUM_SCALAR {
137 return (isInt()) ? (std::get< 1 >(quartets[current])) : (std::get< 0 >(quartets[current]));
138 };
139 auto incCurrent = [&]() {
140 current += 1;
141 if (current >= max) this->_addFatalError_(lig(), col(), "Not enough data in UAI file");
142 };
143
144 current = 0;
145 Size nbrNode = (Size)getInt();
146
147 for (NodeId i = 0; i < nbrNode; i++) {
148 incCurrent();
149 int mod = getInt();
150 if (mod < 2) _addError_(lig(), col(), "Number of modalities should be greater than 2.");
151 _bn_->add(gum::LabelizedVariable(std::to_string(i), "", mod));
152 }
153
154 incCurrent();
155 Size nbrPot = (Size)getInt();
156 if (nbrPot != nbrNode)
157 _addWarning_(lig(), col(), "Number of CPTs should be the same as number of nodes");
158
159 Set< NodeId > s;
160 for (NodeId i = 0; i < nbrPot; i++) {
161 incCurrent();
162 Size nbrPar = (Size)getInt();
163 if (nbrPar == 0) _addError_(lig(), col(), "0 is not possible here");
164
165 std::vector< NodeId > papas;
166 for (NodeId j = 1; j < nbrPar; j++) {
167 incCurrent();
168 NodeId papa = (NodeId)getInt();
169 if (papa >= nbrNode) _addError_(lig(), col(), "Not enough variables in the BayesNet");
170 papas.push_back(papa);
171 }
172
173 incCurrent();
174 NodeId nodePot = (Size)getInt();
175 if (nodePot >= nbrNode) _addError_(lig(), col(), "Not enough variables in the BayesNet");
176 if (s.contains(nodePot)) _addError_(lig(), col(), "Parents already defined");
177 s.insert(nodePot);
178
179 for (const auto papa: papas) {
180 _bn_->addArc(papa, nodePot);
181 }
182 }
183
184 std::vector< GUM_SCALAR > v;
185 for (NodeId i = 0; i < nbrPot; i++) {
186 incCurrent();
187 Size nbrParam = (Size)getInt();
188 if (nbrParam != _bn_->cpt(i).domainSize())
189 _addFatalError_(lig(), col(), "Size does not fit between parents and parameters");
190 for (Idx j = 0; j < nbrParam; j++) {
191 incCurrent();
192 v.push_back(getVal());
193 }
194 _bn_->cpt(i).fillWith(v);
195 v.clear();
196 }
197
198 if (current != max - 1) _addError_(lig(), col(), "Too many data in this file");
199 }
200
201 // @{
202 // publishing Errors API
203 template < GUM_Numeric GUM_SCALAR >
204 Idx UAIBNReader< GUM_SCALAR >::errLine(Idx i) {
205 if (_parseDone_) return _parser_->errors().error(i).line;
206 else { GUM_ERROR(OperationNotAllowed, "UAI file not parsed yet") }
207 }
208
209 template < GUM_Numeric GUM_SCALAR >
210 Idx UAIBNReader< GUM_SCALAR >::errCol(Idx i) {
211 if (_parseDone_) return _parser_->errors().error(i).column;
212 else { GUM_ERROR(OperationNotAllowed, "UAI file not parsed yet") }
213 }
214
215 template < GUM_Numeric GUM_SCALAR >
216 bool UAIBNReader< GUM_SCALAR >::errIsError(Idx i) {
217 if (_parseDone_) return _parser_->errors().error(i).is_error;
218 else { GUM_ERROR(OperationNotAllowed, "UAI file not parsed yet") }
219 }
220
221 template < GUM_Numeric GUM_SCALAR >
222 std::string UAIBNReader< GUM_SCALAR >::errMsg(Idx i) {
223 if (_parseDone_) return _parser_->errors().error(i).msg;
224 else { GUM_ERROR(OperationNotAllowed, "UAI file not parsed yet") }
225 }
226
227 template < GUM_Numeric GUM_SCALAR >
228 void UAIBNReader< GUM_SCALAR >::showElegantErrors(std::ostream& o) {
229 if (_parseDone_) _parser_->errors().elegantErrors(o);
230 else { GUM_ERROR(OperationNotAllowed, "UAI file not parsed yet") }
231 }
232
233 template < GUM_Numeric GUM_SCALAR >
234 void UAIBNReader< GUM_SCALAR >::showElegantErrorsAndWarnings(std::ostream& o) {
235 if (_parseDone_) _parser_->errors().elegantErrorsAndWarnings(o);
236 else { GUM_ERROR(OperationNotAllowed, "UAI file not parsed yet") }
237 }
238
239 template < GUM_Numeric GUM_SCALAR >
240 void UAIBNReader< GUM_SCALAR >::showErrorsAndWarnings(std::ostream& o) {
241 if (_parseDone_) _parser_->errors().simpleErrorsAndWarnings(o);
242 else { GUM_ERROR(OperationNotAllowed, "UAI file not parsed yet") }
243 }
244
245 template < GUM_Numeric GUM_SCALAR >
246 void UAIBNReader< GUM_SCALAR >::showErrorCounts(std::ostream& o) {
247 if (_parseDone_) _parser_->errors().syntheticResults(o);
248 else { GUM_ERROR(OperationNotAllowed, "UAI file not parsed yet") }
249 }
250
251 template < GUM_Numeric GUM_SCALAR >
252 Size UAIBNReader< GUM_SCALAR >::errors() {
253 return (!_parseDone_) ? (Size)0 : _parser_->errors().error_count;
254 }
255
256 template < GUM_Numeric GUM_SCALAR >
257 Size UAIBNReader< GUM_SCALAR >::warnings() {
258 return (!_parseDone_) ? (Size)0 : _parser_->errors().warning_count;
259 }
260
261 template < GUM_Numeric GUM_SCALAR >
262 void UAIBNReader< GUM_SCALAR >::_addFatalError_(Idx lig, Idx col, std::string_view s) {
263 _parser_->errors().addError(s, _streamName_, lig, col);
264 GUM_ERROR(gum::OperationNotAllowed, "")
265 }
266
267 template < GUM_Numeric GUM_SCALAR >
268 void UAIBNReader< GUM_SCALAR >::_addError_(Idx lig, Idx col, std::string_view s) {
269 _parser_->errors().addError(s, _streamName_, lig, col);
270 }
271
272 template < GUM_Numeric GUM_SCALAR >
273 void UAIBNReader< GUM_SCALAR >::_addWarning_(Idx lig, Idx col, std::string_view s) {
274 _parser_->errors().addWarning(s, _streamName_, lig, col);
275 }
276
277 // @}
278} // namespace gum
279
280#endif // DOXYGEN_SHOULD_SKIP_THIS
Definition file for UAI exportation class.
Pure virtual class for reading a BN from a file.
Definition BNReader.h:78
Class representing a Bayesian network.
Definition BayesNet.h:99
Base class for all aGrUM's exceptions.
Definition exceptions.h:122
Exception : input/output problem.
class LabelizedVariable
Exception : operation not allowed.
UAIBNReader(BayesNet< GUM_SCALAR > *bn, std::string_view filename)
Constructor A reader is defined for reading a defined file.
#define GUM_ERROR(type, msg)
Definition exceptions.h:76
#define GUM_SHOWERROR(e)
Definition exceptions.h:89
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
STL namespace.