aGrUM 3.1.1
a C++ library for (probabilistic) graphical models
BIFXMLIDWriter_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#include <fstream>
44#include <sstream>
45
46#include <agrum/ID/io/BIFXML/BIFXMLIDWriter.h> // to ease IDE parser
47#ifndef DOXYGEN_SHOULD_SKIP_THIS
48
50
51namespace gum {
52 /*
53 * Default constructor.
54 */
55 template < GUM_Numeric GUM_SCALAR >
57 GUM_CONSTRUCTOR(BIFXMLIDWriter);
58 }
59
60 /*
61 * Destructor.
62 */
63 template < GUM_Numeric GUM_SCALAR >
65 GUM_DESTRUCTOR(BIFXMLIDWriter);
66 }
67
68 /*
69 * Writes an influence diagram in the given ouput stream.
70 *
71 * @param output The output stream.
72 * @param infdiag The influence diagram writen in the stream.
73 * @throws IOError Raised if an I/O error occurs.
74 */
75 template < GUM_Numeric GUM_SCALAR >
76 void BIFXMLIDWriter< GUM_SCALAR >::write(std::ostream& output,
77 const InfluenceDiagram< GUM_SCALAR >& infdiag) {
78 if (!output.good()) { GUM_ERROR(IOError, "Input/Output error : stream not writable.") }
79
80 output << _heading_() << std::endl;
81 output << "<!-- Variables -->" << std::endl;
82
83 for (const auto node: infdiag.nodes()) {
84 int nodeType = 1;
85
86 if (infdiag.isChanceNode(node)) nodeType = 2;
87 else if (infdiag.isUtilityNode(node)) nodeType = 3;
88
89 output << _variableBloc_(infdiag.variable(node), nodeType) << std::endl;
90 }
91
92 output << "<!-- Probability distributions -->" << std::endl;
93
94 for (const auto node: infdiag.nodes())
95 output << _variableDefinition_(node, infdiag);
96
97 output << std::endl;
98 output << _documentend_();
99 output.flush();
100
101 if (output.fail()) { GUM_ERROR(IOError, "Writing in the ostream failed.") }
102 }
103
104 /*
105 * Writes an Influence Diagram in the file referenced by filePath.
106 * If the file doesn't exists, it is created.
107 * If the file exists, it's content will be erased.
108 *
109 * @param filePath The path to the file used to write the Influence Diagram.
110 * @param infdiag The Influence Diagram writen in the file.
111 * @throw IOError Raised if an I/O error occurs.
112 */
113 template < GUM_Numeric GUM_SCALAR >
114 void BIFXMLIDWriter< GUM_SCALAR >::write(std::string_view filePath,
115 const InfluenceDiagram< GUM_SCALAR >& infdiag) {
116 std::ofstream output(std::filesystem::path{filePath}, std::ios_base::trunc);
117
118 write(output, infdiag);
119
120 output.close();
121
122 if (output.fail()) { GUM_ERROR(IOError, "Writing in the ostream failed.") }
123 }
124
125 /*
126 * Returns the header of the BIF file.
127 */
128 template < GUM_Numeric GUM_SCALAR >
130 std::stringstream str;
131
132 // Header for every xml
133 str << "<?xml version=\"1.0\" ?>" << std::endl;
134
135 // Document type definition of BIF 0.3
136 /* https://www.cs.cmu.edu/afs/cs/user/fgcozman/www/Research/InterchangeFormat/ */
137
138 // BIF version Tag
139 str << std::endl << "<BIF VERSION=\"0.3\">" << std::endl;
140
141 // Network declaration
142 str << "<NETWORK>" << std::endl;
143
144 return str.str();
145 }
146
147 /*
148 * Returns a bloc defining a variable in the BIF format.
149 */
150 template < GUM_Numeric GUM_SCALAR >
152 int varType) {
153 //<VARIABLE TYPE="nature|decision|utility">
154 //<NAME>name</NAME>
155 //<PROPERTY>description = ...</PROPERTY>
156 //<PROPERTY>fast = A[4,5]</PROPERTY>PROPERTY>
157 // <!- OUTCOMES are not used but are kept for compatibility->
158 //<OUTCOME>outcome1</OUTCOME>
159 //<OUTCOME>outcome2</OUTCOME>
160 //<PROPERTY>property</PROPERTY>
161 //</VARIABLE>
162
163 std::stringstream str;
164
165 // Declaration of variable and his type
166 str << "<VARIABLE TYPE=\"";
167
168 switch (varType) {
169 case 1 : str << "decision"; break;
170
171 case 2 : str << "nature"; break;
172
173 case 3 : str << "utility"; break;
174
175 default : break;
176 }
177
178 str << "\">" << std::endl;
179
180 // Name and description
181 str << std::format("\t<NAME>{}</NAME>\n", var.name());
182 str << std::format("\t<PROPERTY>description = {}</PROPERTY>\n", var.description());
183 str << std::format("\t<PROPERTY>fast = {}</PROPERTY>\n", var.toFast());
184
185 // Outcomes
186 str << "<!-- OUTCOME are not used in pyAgrum BIFXML (see fast property) but are kept for "
187 "compatibility-->"
188 << std::endl;
189 for (Idx i = 0; i < var.domainSize(); i++)
190 str << std::format("\t<OUTCOME>{}</OUTCOME>\n", var.label(i));
191
192 // //Closing tag
193 str << "</VARIABLE>" << std::endl;
194
195 return str.str();
196 }
197
198 /*
199 * Returns a bloc defining a variable's CPT in the BIF format.
200 */
201 template < GUM_Numeric GUM_SCALAR >
203 const NodeId& varNodeId,
204 const InfluenceDiagram< GUM_SCALAR >& infdiag) {
205 //<DEFINITION>
206 //<FOR>var</FOR>
207 //<GIVEN>conditional var</GIVEN>
208 //<TABLE>conditional probabilities</TABLE>
209 //</DEFINITION>
210 std::stringstream str;
211
212 if (!((infdiag.isDecisionNode(varNodeId)) && (infdiag.parents(varNodeId).empty()))) {
213 // Declaration
214 str << "<DEFINITION>" << std::endl;
215
216 // Variable
217 str << std::format("\t<FOR>{}</FOR>", infdiag.variable(varNodeId).name());
218
219 str << std::format("<!--{} | ", infdiag.variable(varNodeId).name());
220 for (const auto n: infdiag.parents(varNodeId))
221 str << infdiag.variable(n).name() << ",";
222 str << "-->\n";
223
224 // Conditional Parents for decision node
225 if (infdiag.isDecisionNode(varNodeId)) {
226 // finding the parents in the graph
227 List< std::string > parentList;
228
229 for (const auto par: infdiag.parents(varNodeId))
230 parentList.pushBack(infdiag.variable(par).name());
231
232 for (auto parentListIte = parentList.rbegin(); parentListIte != parentList.rend();
233 --parentListIte)
234 str << std::format("\t<GIVEN>{}</GIVEN>\n", *parentListIte);
235 } else if (infdiag.isChanceNode(varNodeId)) // finding the parents in the cpt
236 for (Idx i = infdiag.cpt(varNodeId).nbrDim(); i > 1;
237 i--) // the first dimension is not a parent
238 str << std::format("\t<GIVEN>{}</GIVEN>\n",
239 infdiag.cpt(varNodeId).variable(i - 1).name());
240 else if (infdiag.isUtilityNode(varNodeId)) // finding the parents in the utility
241 for (Idx i = infdiag.utility(varNodeId).nbrDim(); i > 1;
242 i--) // the first dimension is not a parent
243 str << std::format("\t<GIVEN>{}</GIVEN>\n",
244 infdiag.utility(varNodeId).variable(i - 1).name());
245
246
247 if (infdiag.isChanceNode(varNodeId)) {
248 Instantiation inst(infdiag.cpt(varNodeId));
249 str << "\t<TABLE>";
250
251 for (inst.setFirst(); !inst.end(); inst.inc())
252 str << infdiag.cpt(varNodeId)[inst] << " ";
253
254 str << "</TABLE>" << std::endl;
255 } else if (infdiag.isUtilityNode(varNodeId)) {
256 // Values
257 Instantiation inst(infdiag.utility(varNodeId));
258 str << "\t<TABLE>";
259
260 for (inst.setFirst(); !inst.end(); inst.inc())
261 str << infdiag.utility(varNodeId)[inst] << " ";
262
263 str << "</TABLE>" << std::endl;
264 }
265
266 // Closing tag
267 str << "</DEFINITION>" << std::endl;
268 }
269
270 return str.str();
271 }
272
273 /*
274 * Returns the end of the BIF file.
275 */
276 template < GUM_Numeric GUM_SCALAR >
278 std::stringstream str;
279
280 str << "</NETWORK>" << std::endl;
281 str << "</BIF>" << std::endl;
282
283 return str.str();
284 }
285} /* namespace gum */
286
287#endif // DOXYGEN_SHOULD_SKIP_THIS
Definition file for BIF XML exportation class.
Writes an influence diagram in a XML files with BIF format.
virtual ~BIFXMLIDWriter()
Destructor.
std::string _heading_()
Returns the header of the BIF file.
std::string _variableBloc_(const DiscreteVariable &var, int nodeType)
Returns a bloc defining a variable in the BIF format.
BIFXMLIDWriter()
Default constructor.
std::string _variableDefinition_(const NodeId &varNodeId, const InfluenceDiagram< GUM_SCALAR > &infdiag)
Returns a bloc defining a variable's table (if she has) in the BIF format.
std::string _documentend_()
Returns the end of the BIF file.
virtual void write(std::ostream &output, const InfluenceDiagram< GUM_SCALAR > &infdiag)
Writes an influence diagram in the given output stream.
Base class for discrete random variable.
Class representing an Influence Diagram.
Class for assigning/browsing values to tuples of discrete variables.
Val & pushBack(const Val &val)
Inserts a new element (a copy) at the end of the chained list.
Definition list_tpl.h:1481
#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