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