aGrUM 2.3.2
a C++ library for (probabilistic) graphical models
BIFXMLBNWriter_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
46
47namespace gum {
48 /*
49 * Default constructor.
50 */
51 template < typename GUM_SCALAR >
53 GUM_CONSTRUCTOR(BIFXMLBNWriter);
54 }
55
56 /*
57 * Destructor.
58 */
59 template < typename GUM_SCALAR >
61 GUM_DESTRUCTOR(BIFXMLBNWriter);
62 }
63
64 /*
65 * Writes a bayes net in the given ouput stream.
66 *
67 * @param output The output stream.
68 * @param bn The bayes net writen in the stream.
69 * @throws IOError Raised if an I/O error occurs.
70 */
71 template < typename GUM_SCALAR >
72 INLINE void BIFXMLBNWriter< GUM_SCALAR >::_doWrite(std::ostream& output,
73 const IBayesNet< GUM_SCALAR >& bn) {
74 if (!output.good()) { GUM_ERROR(IOError, "Input/Output error : stream not writable.") }
75
76 output << _heading_(bn) << std::endl;
77
78 output << "<!-- Variables -->" << std::endl;
79
80 for (auto node: bn.nodes())
81 output << _variableBloc_(bn.variable(node)) << std::endl;
82
83 output << "<!-- Probability distributions -->" << std::endl;
84
85 for (auto node: bn.nodes())
86 output << _variableDefinition_(node, bn);
87
88 output << std::endl;
89
90 output << _documentend_();
91
92 output.flush();
93
94 if (output.fail()) { GUM_ERROR(IOError, "Writing in the ostream failed.") }
95 }
96
97 /*
98 * Writes a bayes net in the file referenced by filePath.
99 * If the file doesn't exists, it is created.
100 * If the file exists, it's content will be erased.
101 *
102 * @param filePath The path to the file used to write the bayes net.
103 * @param bn The bayes net writen in the file.
104 * @throw IOError Raised if an I/O error occurs.
105 */
106 template < typename GUM_SCALAR >
107 INLINE void BIFXMLBNWriter< GUM_SCALAR >::_doWrite(const std::string& filePath,
108 const IBayesNet< GUM_SCALAR >& bn) {
109 std::ofstream output(filePath.c_str(), std::ios_base::trunc);
110
111 _doWrite(output, bn);
112
113 output.close();
114 if (output.fail()) { GUM_ERROR(IOError, "Writing in the ostream failed.") }
115 }
116
117 /*
118 * Returns the header of the BIF file.
119 */
120 template < typename GUM_SCALAR >
122 std::stringstream str;
123
124 // Header for every xml
125 str << "<?xml version=\"1.0\" ?>" << std::endl;
126
127 // Document type definition of BIF 0.3
128 /*str << "<!-- DTD for the XMLBIF 0.3 format -->" << std::endl;
129 str << "<!DOCTYPE BIF [" << std::endl;
130 str << "\t<!ELEMENT BIF ( NETWORK )*>" << std::endl;
131 str << "\t\t<!ATTLIST BIF VERSION CDATA #REQUIRED>" << std::endl;
132 str << "\t<!ELEMENT NETWORK ( NAME, ( PROPERTY | VARIABLE | DEFINITION )*
133 )>" <<
134 std::endl;
135 str << "\t<!ELEMENT NAME (#PCDATA)>" << std::endl;
136 str << "\t<!ELEMENT VARIABLE ( NAME, ( OUTCOME | PROPERTY )* ) >" <<
137 std::endl;
138 str << "\t\t<!ATTLIST VARIABLE TYPE (nature|decision|utility) \"nature\">"
139 <<
140 std::endl;
141 str << "\t<!ELEMENT OUTCOME (#PCDATA)>" << std::endl;
142 str << "\t<!ELEMENT DEFINITION ( FOR | GIVEN | TABLE | PROPERTY )* >" <<
143 std::endl;
144 str << "\t<!ELEMENT FOR (#PCDATA)>" << std::endl;
145 str << "\t<!ELEMENT GIVEN (#PCDATA)>" << std::endl;
146 str << "\t<!ELEMENT TABLE (#PCDATA)>" << std::endl;
147 str << "\t<!ELEMENT PROPERTY (#PCDATA)>" << std::endl;
148 str << "]>" << std::endl;*/
149
150 // BIF version Tag
151 str << std::endl << "<BIF VERSION=\"0.3\">" << std::endl;
152
153 // Network declaration
154 str << "<NETWORK>" << std::endl;
155 str << "<NAME>" << bn.propertyWithDefault("name", "unnamedBN") << "</NAME>" << std::endl;
156 str << "<PROPERTY>software aGrUM</PROPERTY>" << std::endl;
157
158 return str.str();
159 }
160
161 /*
162 * Returns a bloc defining a variable in the BIF format.
163 */
164 template < typename GUM_SCALAR >
166 //<VARIABLE TYPE="nature|decision|utility">
167 //<NAME>name</NAME>
168 //<PROPERTY>description = ...</PROPERTY>
169 //<PROPERTY>fast = A[4,5]</PROPERTY>
170 // <!--OUTCOMES are not used but are kept for compatibility-->
171 //<OUTCOME>outcome1</OUTCOME>
172 //<OUTCOME>outcome2</OUTCOME>
173 //<PROPERTY>property</PROPERTY>
174 //</VARIABLE>
175
176 std::stringstream str;
177
178 // Declaration of variable and his type
179 str << "<VARIABLE TYPE=\"nature\">" << std::endl;
180
181 // Name and description
182 str << "\t<NAME>" << var.name() << "</NAME>" << std::endl;
183 str << "\t<PROPERTY>description = " << var.description() << "</PROPERTY>" << std::endl;
184 str << "\t<PROPERTY>fast = " << var.toFast() << "</PROPERTY>" << std::endl;
185
186 // Outcomes
187 str << "<!--OUTCOME are not used in pyAgrum BIFXML (see fast property) but are kept for "
188 "compatibility-->"
189 << std::endl;
190 for (Idx i = 0; i < var.domainSize(); i++)
191 str << "\t<OUTCOME>" << var.label(i) << "</OUTCOME>" << std::endl;
192
193 // //Closing tag
194 str << "</VARIABLE>" << std::endl;
195
196 return str.str();
197 }
198
199 /*
200 * Returns a bloc defining a variable's CPT in the BIF format.
201 */
202 template < typename GUM_SCALAR >
203 INLINE std::string
205 const IBayesNet< GUM_SCALAR >& bn) {
206 //<DEFINITION>
207 //<FOR>var</FOR>
208 //<GIVEN>conditional var</GIVEN>
209 //<TABLE>conditional probabilities</TABLE>
210 //</DEFINITION>
211 std::stringstream str;
212
213 // Declaration
214 str << "<DEFINITION>" << std::endl;
215
216 // Variable
217 str << "\t<FOR>" << bn.variable(varNodeId).name() << "</FOR>" << std::endl;
218
219 // Table
220 // For historical reason, the code is not the same betwen bIXML for BN and
221 // for ID
222 // ...
223 const Tensor< GUM_SCALAR >& cpt = bn.cpt(varNodeId);
224
225 // Conditional Parents
226 for (Idx i = 1; i < cpt.nbrDim(); i++)
227 str << "\t<GIVEN>" << cpt.variable(i).name() << "</GIVEN>" << std::endl;
228
229 Instantiation inst;
230 inst << cpt.variable(0);
231
232 for (Idx i = cpt.nbrDim() - 1; i > 0; i--)
233 inst << cpt.variable(i);
234
235 str << "\t<TABLE>";
236
237 for (inst.setFirst(); !inst.end(); inst.inc()) {
238 if (inst.val(0) == 0) str << std::endl << "\t\t";
239 else str << " ";
240
241 str << cpt[inst];
242 }
243
244 str << std::endl << "\t</TABLE>" << std::endl;
245
246 // Closing tag
247 str << "</DEFINITION>" << std::endl;
248
249 return str.str();
250 }
251
252 /*
253 * Returns the end of the BIF file.
254 */
255 template < typename GUM_SCALAR >
257 std::stringstream str;
258
259 str << "</NETWORK>" << std::endl;
260 str << "</BIF>" << std::endl;
261
262 return str.str();
263 }
264} /* namespace gum */
265
266#endif // DOXYGEN_SHOULD_SKIP_THIS
Definition file for BIF XML exportation class.
<agrum/BN/io/BIFXML/BIFXMLBNWriter.h>
BIFXMLBNWriter()
Default constructor.
std::string _variableBloc_(const DiscreteVariable &var)
Returns a bloc defining a variable in the BIF format.
std::string _documentend_()
Returns the end of the BIF file.
void _doWrite(std::ostream &output, const IBayesNet< GUM_SCALAR > &bn) final
Writes an bayes net in the given ouput stream.
std::string _variableDefinition_(const NodeId &varNodeId, const IBayesNet< GUM_SCALAR > &bn)
Returns a bloc defining a variable's table (if she has) in the BIF format.
std::string _heading_(const IBayesNet< GUM_SCALAR > &bn)
Returns the header of the BIF file.
~BIFXMLBNWriter() override
Destructor.
Base class for discrete random variable.
Class representing the minimal interface for Bayesian network with no numerical data.
Definition IBayesNet.h:75
Class for assigning/browsing values to tuples of discrete variables.
aGrUM's Tensor is a multi-dimensional array with tensor operators.
Definition tensor.h:85
#define GUM_ERROR(type, msg)
Definition exceptions.h:72
Size Idx
Type for indexes.
Definition types.h:79
Size NodeId
Type for node ids.
gum is the global namespace for all aGrUM entities
Definition agrum.h:46