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