aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
ContextualDependenciesCNFWriter_tpl.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4  * info_at_agrum_dot_org
5  *
6  * This library is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 
22 #ifndef DOXYGEN_SHOULD_SKIP_THIS
23 
24 // to ease parsing in IDE
25 # include <agrum/BN/io/cnf/ContextualDependenciesCNFWriter.h>
26 
27 namespace gum {
28  /* =========================================================================*/
29  /* === GUM_BN_WRITER === */
30  /* =========================================================================*/
31  // Default constructor.
32  template < typename GUM_SCALAR, template < class > class IApproximationPolicy >
33  INLINE
34  ContextualDependenciesCNFWriter< GUM_SCALAR,
37  }
38 
39  // Default destructor.
40  template < typename GUM_SCALAR, template < class > class IApproximationPolicy >
41  INLINE
45  }
46 
47  //
48  // Writes a Bayesian network in the output stream using the BN format.
49  //
50  // @param ouput The output stream.
51  // @param bn The Bayesian network writen in output.
52  // @throws Raised if an I/O error occurs.
53  template < typename GUM_SCALAR, template < class > class IApproximationPolicy >
55  std::ostream& output,
56  const IBayesNet< GUM_SCALAR >& bn) {
58 
59  for (auto node: bn.topologicalOrder())
61 
62  if (!output.good()) GUM_ERROR(IOError, "Stream states flags are not all unset.")
63 
65 
66  Idx num = 0;
67  Idx numvar = 0;
68  Idx clause = 0;
72  gum::HashTable<
73  const gum::DiscreteVariable*,
76 
77  for (auto node: bn.nodes()) {
79  const DiscreteVariable* var = &bn.variable(node);
80 
81  for (Idx i = 0; i < var->domainSize(); i++) {
83  stri << var->name() << "_" << var->label(i);
84  vartable.insert(stri.str(), ++num);
85  strfile << num << "::" << stri.str() << "\n";
86  str0 << vartable[stri.str()] << " ";
87  }
88 
89  str0 << "0\n";
90  clause++;
91  numvar++;
92  clausstr2 << str0.str();
93  const Potential< GUM_SCALAR >& cpt = bn.cpt(node);
98  var,
99  new gum::HashTable< std::string,
100  gum::Sequence< gum::Sequence< gum::Instantiation* >* >* >());
101 
102  for (inst.setFirst(); !inst.end(); ++inst) {
103  if (this->fromExact(cpt[inst]) != 1) {
105  strk << this->fromExact(cpt[inst]);
106  std::string valp = strk.str();
107 
108  if (!(cptparamval[var])->exists(valp)) {
109  (cptparamval[var])
110  ->insert(valp, new gum::Sequence< gum::Sequence< gum::Instantiation* >* >());
111 
112  (*(cptparamval[var]))[valp]->insert(new gum::Sequence< gum::Instantiation* >);
113 
114  if (this->fromExact(cpt[inst])) {
116  strinst << var->name();
117  strinst << "_val=" << this->fromExact(cpt[inst]);
118 
119  if (!protable.exists(strinst.str())) {
120  protable.insert(strinst.str(), ++num);
121  strfile << num << "::" << strinst.str() << "\n";
122  }
123  }
124  }
125 
126  (*(cptparamval[var]))[valp]->front()->insert(new gum::Instantiation(inst));
127  }
128  }
129  }
130 
132 
133  while (!cptparamval.empty()) {
134  gum::HashTable<
135  const DiscreteVariable*,
138  = cptparamval.begin();
139 
140  while (!(itvar.val())->empty()) {
141  gum::HashTable< std::string,
143  = (itvar.val())->begin(); // needed here
144 
145  for (auto pv: *itpvall.val()) {
146  gum::Idx linecount = 0;
147  gum::HashTable< std::string,
148  gum::HashTable< const gum::DiscreteVariable*,
149  std::pair< gum::Set< Idx >*,
150  gum::Set< Idx >* >* >* >
151  orderStruct; // set sizeof Hashtable
152 
153  for (auto seqv: *pv) {
154  if (seqv->nbrDim() > 1) {
155  for (Idx iInst = 0; iInst < seqv->nbrDim(); iInst++) {
156  gum::Instantiation instpro(*seqv, false);
158  const gum::DiscreteVariable* var = &(seqv->variable(iInst));
159  instpro.erase(*var); // reorder instance to optimize make sure
160  // key unicity.
161 
164  instpro.toString(),
165  new gum::HashTable< const gum::DiscreteVariable*,
166  std::pair< gum::Set< Idx >*, gum::Set< Idx >* >* >());
167  }
168 
169  if (!orderStruct[instpro.toString()]->exists(var)) {
171  var,
172  new std::pair< gum::Set< Idx >*, gum::Set< Idx >* >(
173  new gum::Set< Idx >,
174  new gum::Set< Idx >(
175  seqv->variable(iInst).domainSize()))); // set sizeof Hashtable
176  }
177 
178  gum::HashTable< const gum::DiscreteVariable*,
179  std::pair< gum::Set< Idx >*, gum::Set< Idx >* >* >* orderStruct2
183  }
184  }
185 
186  linecount += 1;
187  }
188 
189  gum::Set< gum::Idx > elimination;
190  gum::Sequence< gum::Instantiation* >* newSeq = nullptr;
191 
192  for (auto& elt: orderStruct) {
193  bool added = false;
194 
195  for (auto& elt2: *elt.second) {
196  if (elt2.second->second->size() == elt2.first->domainSize()) {
197  if (!newSeq) newSeq = new gum::Sequence< gum::Instantiation* >();
198 
199  if (!added) {
200  added = true;
201  newSeq->insert(
202  new gum::Instantiation(*((*pv)[(*(elt2.second->first->begin()))]), false));
203  newSeq->back()->erase(*elt2.first);
204  }
205 
207  }
208  }
209  }
210 
211  if (newSeq) {
212  (itpvall.val())->insert(newSeq);
213 
214  for (Idx itelem = pv->size(); itelem > 0; itelem--) {
215  if (elimination.exists(itelem - 1)) {
216  delete ((*pv)[itelem - 1]);
217  pv->erase((*pv)[itelem - 1]);
218  }
219  }
220  }
221 
222  while (!orderStruct.empty()) {
223  while (!(orderStruct.begin().val())->empty()) {
224  delete orderStruct.begin().val()->begin().val()->first;
225  delete orderStruct.begin().val()->begin().val()->second;
226  (orderStruct.begin().val())
227  ->erase((orderStruct.begin().val())->beginSafe()); // safe iterator needed here
228  }
229 
230  delete orderStruct.begin().val();
231  orderStruct.erase(orderStruct.beginSafe()); // safe iterator needed here
232  }
233  }
234 
235  while (!(itpvall.val())->empty()) {
237  = (itpvall.val())->begin();
238 
239  while (!(*itpv)->empty()) {
241 
242  for (Idx i = 0; i < (*itseqv)->nbrDim(); i++) {
244  str << (*itseqv)->variable(i).name() << "_" << (*itseqv)->val((*itseqv)->variable(i));
245  str2 << "-" << vartable[str.str()] << " ";
246  }
247 
248  // if (itpvall.key().compare("0") != 0 &&
249  // itpvall.key().compare("0.0") != 0) {
250  if (itpvall.key() != "0" && itpvall.key() != "0.0") {
252  strinst << itvar.key()->name();
253  strinst << "_val=" << itpvall.key();
254  str2 << protable[strinst.str()];
255  }
256 
257  str2 << " 0\n";
258  clause++;
259  delete (*itseqv);
260  (*itpv)->erase(itseqv);
261  }
262 
263  delete (*itpv);
264  (itpvall.val())->erase(itpv);
265  }
266 
267  delete (itpvall.val());
268  (itvar.val())->erase(itvar.val()->beginSafe()); // safe iterator needed here
269  }
270 
271  delete (itvar.val());
272  cptparamval.erase(cptparamval.beginSafe()); // safe iterator needed here
273  }
274 
275  clausstr << str2.str();
276 
277  output << "p cnf " << num << " " << clause << "\neclauses " << numvar << "\n"
278  << clausstr.str() << clausstr2.str() << std::endl;
279  output.flush();
280  }
281 
282  // Writes a Bayesian network in the referenced file using the BN format.
283  // If the file doesn't exists, it is created.
284  // If the file exists, it's content will be erased.
285  //
286  // @param filePath The path to the file used to write the Bayesian network.
287  // @param bn The Bayesian network writed in the file.
288  // @throws Raised if an I/O error occurs.
289  template < typename GUM_SCALAR, template < class > class IApproximationPolicy >
291  const std::string& filePath,
292  const IBayesNet< GUM_SCALAR >& bn) {
294  std::ofstream outputvar((filePath + ".var").c_str(), std::ios_base::trunc);
295 
296  if (!output.good()) GUM_ERROR(IOError, "Stream states flags are not all unset.")
297 
299 
300  if (!outputvar.good()) GUM_ERROR(IOError, "Stream states flags are not all unset.")
301 
302  Idx num = 0;
303  Idx numvar = 0;
304  Idx clause = 0;
308  gum::HashTable<
309  const gum::DiscreteVariable*,
311  cptparamval;
312 
314 
315  for (auto node: bn.topologicalOrder())
317 
318  for (auto node: bn.nodes()) {
320  const DiscreteVariable* var = &bn.variable(node);
321 
322  for (Idx i = 0; i < bn.variable(node).domainSize(); i++) {
324  stri << var->name() << "_" << var->label(i);
325  vartable.insert(stri.str(), ++num);
326  strfile << num << "::" << stri.str() << "\n";
327  str0 << vartable[stri.str()] << " ";
328  }
329 
330  str0 << "0\n";
331  clause++;
332  numvar++;
333  clausstr2 << str0.str();
334  const Potential< GUM_SCALAR >& cpt = bn.cpt(node);
336  inst.forgetMaster();
337  inst.reorder(Order);
339  var,
340  new gum::HashTable< std::string,
341  gum::Sequence< gum::Sequence< gum::Instantiation* >* >* >());
342 
343  for (inst.setFirst(); !inst.end(); ++inst) {
344  if (this->fromExact(cpt[inst]) != 1) {
346  strk << this->fromExact(cpt[inst]);
347  std::string valp = strk.str();
348 
349  if (!(cptparamval[var])->exists(valp)) {
350  (cptparamval[var])
351  ->insert(valp,
352  new gum::Sequence< gum::Sequence< gum::Instantiation* >* >()); // remember
353  // to
354  // verify
355  // protocole for
356  // param = to 1
357 
358  (*(cptparamval[var]))[valp]->insert(new gum::Sequence< gum::Instantiation* >);
359 
360  if (this->fromExact(cpt[inst])) {
362  strinst << var->name();
363  strinst << "_val=" << this->fromExact(cpt[inst]);
364 
365  if (!protable.exists(strinst.str())) {
366  protable.insert(strinst.str(), ++num);
367  strfile << num << "::" << strinst.str() << "\n";
368  }
369  }
370  }
371 
372  (*(cptparamval[var]))[valp]->front()->insert(new gum::Instantiation(inst));
373  }
374  }
375  }
376 
378 
379  while (!cptparamval.empty()) {
380  gum::HashTable<
381  const DiscreteVariable*,
384  = cptparamval.begin();
385 
386  while (!(itvar.val())->empty()) {
387  gum::HashTable< std::string,
389  = (itvar.val())->begin();
390 
391  for (auto pv: *itpvall.val()) {
392  gum::Idx linecount = 0;
393  gum::HashTable< std::string,
394  gum::HashTable< const gum::DiscreteVariable*,
395  std::pair< gum::Set< Idx >*,
396  gum::Set< Idx >* >* >* >
397  orderStruct; // set sizeof Hashtable
398 
399  gum::Set< gum::Idx > elimination;
401 
402  for (auto seqv: *pv) {
403  if (seqv->nbrDim() > 1) {
404  for (Idx iInst = 0; iInst < seqv->nbrDim(); iInst++) {
405  auto instpro = new gum::Instantiation(*seqv, false);
406  const gum::DiscreteVariable* var = &(seqv->variable(iInst));
407  instpro->erase(*var);
409 
411  && !newSeqpre.exists(instpro->toString())) {
413  instpro->toString(),
414  new gum::HashTable< const gum::DiscreteVariable*,
415  std::pair< gum::Set< Idx >*, gum::Set< Idx >* >* >());
416  }
417 
419  && !orderStruct[instpro->toString()]->exists(var)) {
421  var,
422  new std::pair< gum::Set< Idx >*, gum::Set< Idx >* >(
423  new gum::Set< Idx >,
424  new gum::Set< Idx >(
425  seqv->variable(iInst).domainSize()))); // set sizeof Hashtable
426  }
427 
429  && !newSeqpre.exists(instpro->toString())) {
430  gum::HashTable< const gum::DiscreteVariable*,
431  std::pair< gum::Set< Idx >*, gum::Set< Idx >* >* >* orderStruct2
435 
436  if ((*orderStruct2)[var]->second->size() == var->domainSize()) {
438 
439  for (auto& elt: *orderStruct2) {
441  delete (elt.second->first);
442  delete (elt.second->second);
443  delete (elt.second);
444  }
445 
446  orderStruct2->clear();
447 
448  delete orderStruct2;
450  } else
451  delete instpro;
452  } else if (newSeqpre.exists(instpro->toString())) {
454  delete instpro;
455  }
456  }
457  }
458 
459  linecount += 1;
460  }
461 
462  gum::Sequence< gum::Instantiation* >* newSeq = nullptr;
463 
464  if (!newSeqpre.empty()) {
465  newSeq = new gum::Sequence< gum::Instantiation* >();
466 
467  for (auto& elt: newSeqpre)
469 
470  (itpvall.val())->insert(newSeq);
471 
472  for (Idx itelem = pv->size(); itelem > 0; itelem--) {
473  if (elimination.exists(itelem - 1)) {
474  delete ((*pv)[itelem - 1]);
475  pv->erase((*pv)[itelem - 1]);
476  }
477  }
478  }
479 
480  while (!orderStruct.empty()) {
481  while (!(orderStruct.begin().val())->empty()) {
482  delete orderStruct.begin().val()->begin().val()->first;
483  delete orderStruct.begin().val()->begin().val()->second;
484  (orderStruct.begin().val())->erase(orderStruct.begin().val()->beginSafe()); // safe
485  // iterator
486  // needed here
487  }
488 
489  delete orderStruct.begin().val();
490  orderStruct.erase(orderStruct.beginSafe()); // safe iterator needed here
491  }
492  }
493 
494  while (!(itpvall.val())->empty()) {
496  = (itpvall.val())->begin();
497 
498  while (!(*itpv)->empty()) {
500 
501  for (Idx i = 0; i < (*itseqv)->nbrDim(); i++) {
503  str << (*itseqv)->variable(i).name() << "_" << (*itseqv)->val((*itseqv)->variable(i));
504  str2 << "-" << vartable[str.str()] << " ";
505  }
506 
507  /*if (itpvall.key().compare("0") != 0 &&
508  itpvall.key().compare("0.0") != 0) { */
509  if (itpvall.key() != "0" && itpvall.key() != "0.0") {
511  strinst << itvar.key()->name();
512  strinst << "_val=" << itpvall.key();
513  str2 << protable[strinst.str()];
514  }
515 
516  str2 << " 0\n";
517  clause++;
518  delete (*itseqv);
519  (*itpv)->erase((*itpv)->beginSafe()); // safe iterator needed here
520  }
521 
522  delete (*itpv);
523  (itpvall.val())->erase(itpvall.val()->beginSafe()); // safe iterator needed here
524  }
525 
526  delete (itpvall.val());
527  (itvar.val())->erase(itvar.val()->beginSafe()); // safe iterator needed here
528  }
529 
530  delete (itvar.val());
531  cptparamval.erase(cptparamval.beginSafe()); // safe iterator needed here
532  }
533 
534  clausstr << str2.str();
535 
536  output << "p cnf " << num << " " << clause << "\neclauses " << numvar << "\n"
537  << clausstr.str() << clausstr2.str() << std::endl;
538  output.flush();
539  outputvar << strfile.str();
540  outputvar.flush();
541 
542  outputvar.close();
543  output.close();
544 
545  if (outputvar.fail()) GUM_ERROR(IOError, "Writting in the ostream failed.")
546 
547  if (output.fail()) GUM_ERROR(IOError, "Writting in the ostream failed.")
548  }
549 
550 } /* namespace gum */
551 
552 #endif // DOXYGEN_SHOULD_SKIP_THIS
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643