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