aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
ContextualDependenciesCNFWriter_tpl.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright 2005-2020 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 ContextualDependenciesCNFWriter< GUM_SCALAR, IApproximationPolicy >::
36  }
37 
38  // Default destructor.
39  template < typename GUM_SCALAR, template < class > class IApproximationPolicy >
43  }
44 
45  //
46  // Writes a Bayesian network in the output stream using the BN format.
47  //
48  // @param ouput The output stream.
49  // @param bn The Bayesian network writen in output.
50  // @throws Raised if an I/O error occurs.
51  template < typename GUM_SCALAR, template < class > class IApproximationPolicy >
52  INLINE void
54  std::ostream& output,
55  const IBayesNet< GUM_SCALAR >& bn) {
57 
58  for (auto node: bn.topologicalOrder())
60 
61  if (!output.good())
62  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*,
75  gum::Sequence< gum::Sequence< gum::Instantiation* >* >* >* >
77 
78  for (auto node: bn.nodes()) {
80  const DiscreteVariable* var = &bn.variable(node);
81 
82  for (Idx i = 0; i < var->domainSize(); i++) {
84  stri << var->name() << "_" << var->label(i);
85  vartable.insert(stri.str(), ++num);
86  strfile << num << "::" << stri.str() << "\n";
87  str0 << vartable[stri.str()] << " ";
88  }
89 
90  str0 << "0\n";
91  clause++;
92  numvar++;
93  clausstr2 << str0.str();
94  const Potential< GUM_SCALAR >& cpt = bn.cpt(node);
99  var,
100  new gum::HashTable<
101  std::string,
102  gum::Sequence< gum::Sequence< gum::Instantiation* >* >* >());
103 
104  for (inst.setFirst(); !inst.end(); ++inst) {
105  if (this->fromExact(cpt[inst]) != 1) {
107  strk << this->fromExact(cpt[inst]);
108  std::string valp = strk.str();
109 
110  if (!(cptparamval[var])->exists(valp)) {
111  (cptparamval[var])
112  ->insert(
113  valp,
114  new gum::Sequence< gum::Sequence< gum::Instantiation* >* >());
115 
116  (*(cptparamval[var]))[valp]->insert(
117  new gum::Sequence< gum::Instantiation* >);
118 
119  if (this->fromExact(cpt[inst])) {
121  strinst << var->name();
122  strinst << "_val=" << this->fromExact(cpt[inst]);
123 
124  if (!protable.exists(strinst.str())) {
125  protable.insert(strinst.str(), ++num);
126  strfile << num << "::" << strinst.str() << "\n";
127  }
128  }
129  }
130 
131  (*(cptparamval[var]))[valp]->front()->insert(
132  new gum::Instantiation(inst));
133  }
134  }
135  }
136 
138 
139  while (!cptparamval.empty()) {
140  gum::HashTable<
141  const DiscreteVariable*,
142  gum::HashTable<
143  std::string,
144  gum::Sequence< gum::Sequence< gum::Instantiation* >* >* >* >::iterator
145  itvar
146  = cptparamval.begin();
147 
148  while (!(itvar.val())->empty()) {
149  gum::HashTable< std::string,
150  gum::Sequence< gum::Sequence< gum::Instantiation* >* >* >::
152  = (itvar.val())->begin(); // needed here
153 
154  for (auto pv: *itpvall.val()) {
155  gum::Idx linecount = 0;
156  gum::HashTable< std::string,
157  gum::HashTable< const gum::DiscreteVariable*,
158  std::pair< gum::Set< Idx >*,
159  gum::Set< Idx >* >* >* >
160  orderStruct; // set sizeof Hashtable
161 
162  for (auto seqv: *pv) {
163  if (seqv->nbrDim() > 1) {
164  for (Idx iInst = 0; iInst < seqv->nbrDim(); iInst++) {
165  gum::Instantiation instpro(*seqv, false);
167  const gum::DiscreteVariable* var = &(seqv->variable(iInst));
168  instpro.erase(*var); // reorder instance to optimize make sure
169  // key unicity.
170 
173  instpro.toString(),
174  new gum::HashTable<
175  const gum::DiscreteVariable*,
176  std::pair< gum::Set< Idx >*, gum::Set< Idx >* >* >());
177  }
178 
179  if (!orderStruct[instpro.toString()]->exists(var)) {
181  var,
182  new std::pair< gum::Set< Idx >*, gum::Set< Idx >* >(
183  new gum::Set< Idx >,
184  new gum::Set< Idx >(
186  .domainSize()))); // set sizeof Hashtable
187  }
188 
189  gum::HashTable< const gum::DiscreteVariable*,
190  std::pair< gum::Set< Idx >*, gum::Set< Idx >* >* >*
195  }
196  }
197 
198  linecount += 1;
199  }
200 
201  gum::Set< gum::Idx > elimination;
202  gum::Sequence< gum::Instantiation* >* newSeq = nullptr;
203 
204  for (auto& elt: orderStruct) {
205  bool added = false;
206 
207  for (auto& elt2: *elt.second) {
208  if (elt2.second->second->size() == elt2.first->domainSize()) {
209  if (!newSeq) newSeq = new gum::Sequence< gum::Instantiation* >();
210 
211  if (!added) {
212  added = true;
214  *((*pv)[(*(elt2.second->first->begin()))]),
215  false));
216  newSeq->back()->erase(*elt2.first);
217  }
218 
220  }
221  }
222  }
223 
224  if (newSeq) {
225  (itpvall.val())->insert(newSeq);
226 
227  for (Idx itelem = pv->size(); itelem > 0; itelem--) {
228  if (elimination.exists(itelem - 1)) {
229  delete ((*pv)[itelem - 1]);
230  pv->erase((*pv)[itelem - 1]);
231  }
232  }
233  }
234 
235  while (!orderStruct.empty()) {
236  while (!(orderStruct.begin().val())->empty()) {
237  delete orderStruct.begin().val()->begin().val()->first;
238  delete orderStruct.begin().val()->begin().val()->second;
239  (orderStruct.begin().val())
240  ->erase((orderStruct.begin().val())
241  ->beginSafe()); // safe iterator needed here
242  }
243 
244  delete orderStruct.begin().val();
246  orderStruct.beginSafe()); // safe iterator needed here
247  }
248  }
249 
250  while (!(itpvall.val())->empty()) {
252  = (itpvall.val())->begin();
253 
254  while (!(*itpv)->empty()) {
256  = (*itpv)->begin();
257 
258  for (Idx i = 0; i < (*itseqv)->nbrDim(); i++) {
260  str << (*itseqv)->variable(i).name() << "_"
261  << (*itseqv)->val((*itseqv)->variable(i));
262  str2 << "-" << vartable[str.str()] << " ";
263  }
264 
265  // if (itpvall.key().compare("0") != 0 &&
266  // itpvall.key().compare("0.0") != 0) {
267  if (itpvall.key() != "0" && itpvall.key() != "0.0") {
269  strinst << itvar.key()->name();
270  strinst << "_val=" << itpvall.key();
271  str2 << protable[strinst.str()];
272  }
273 
274  str2 << " 0\n";
275  clause++;
276  delete (*itseqv);
277  (*itpv)->erase(itseqv);
278  }
279 
280  delete (*itpv);
281  (itpvall.val())->erase(itpv);
282  }
283 
284  delete (itpvall.val());
285  (itvar.val())
286  ->erase(itvar.val()->beginSafe()); // safe iterator needed here
287  }
288 
289  delete (itvar.val());
290  cptparamval.erase(cptparamval.beginSafe()); // safe iterator needed here
291  }
292 
293  clausstr << str2.str();
294 
295  output << "p cnf " << num << " " << clause << "\neclauses " << numvar << "\n"
296  << clausstr.str() << clausstr2.str() << std::endl;
297  output.flush();
298  }
299 
300  // Writes a Bayesian network in the referenced file using the BN format.
301  // If the file doesn't exists, it is created.
302  // If the file exists, it's content will be erased.
303  //
304  // @param filePath The path to the file used to write the Bayesian network.
305  // @param bn The Bayesian network writed in the file.
306  // @throws Raised if an I/O error occurs.
307  template < typename GUM_SCALAR, template < class > class IApproximationPolicy >
308  INLINE void
310  const std::string& filePath,
311  const IBayesNet< GUM_SCALAR >& bn) {
313  std::ofstream outputvar((filePath + ".var").c_str(), std::ios_base::trunc);
314 
315  if (!output.good())
316  GUM_ERROR(IOError, "Stream states flags are not all unset.");
317 
319 
320  if (!outputvar.good())
321  GUM_ERROR(IOError, "Stream states flags are not all unset.");
322 
323  Idx num = 0;
324  Idx numvar = 0;
325  Idx clause = 0;
329  gum::HashTable<
330  const gum::DiscreteVariable*,
331  gum::HashTable< std::string,
332  gum::Sequence< gum::Sequence< gum::Instantiation* >* >* >* >
333  cptparamval;
334 
336 
337  for (auto node: bn.topologicalOrder())
339 
340  for (auto node: bn.nodes()) {
342  const DiscreteVariable* var = &bn.variable(node);
343 
344  for (Idx i = 0; i < bn.variable(node).domainSize(); i++) {
346  stri << var->name() << "_" << var->label(i);
347  vartable.insert(stri.str(), ++num);
348  strfile << num << "::" << stri.str() << "\n";
349  str0 << vartable[stri.str()] << " ";
350  }
351 
352  str0 << "0\n";
353  clause++;
354  numvar++;
355  clausstr2 << str0.str();
356  const Potential< GUM_SCALAR >& cpt = bn.cpt(node);
358  inst.forgetMaster();
359  inst.reorder(Order);
361  var,
362  new gum::HashTable<
363  std::string,
364  gum::Sequence< gum::Sequence< gum::Instantiation* >* >* >());
365 
366  for (inst.setFirst(); !inst.end(); ++inst) {
367  if (this->fromExact(cpt[inst]) != 1) {
369  strk << this->fromExact(cpt[inst]);
370  std::string valp = strk.str();
371 
372  if (!(cptparamval[var])->exists(valp)) {
373  (cptparamval[var])
374  ->insert(
375  valp,
376  new gum::Sequence<
377  gum::Sequence< gum::Instantiation* >* >()); // remember
378  // to
379  // verify
380  // protocole for
381  // param = to 1
382 
383  (*(cptparamval[var]))[valp]->insert(
384  new gum::Sequence< gum::Instantiation* >);
385 
386  if (this->fromExact(cpt[inst])) {
388  strinst << var->name();
389  strinst << "_val=" << this->fromExact(cpt[inst]);
390 
391  if (!protable.exists(strinst.str())) {
392  protable.insert(strinst.str(), ++num);
393  strfile << num << "::" << strinst.str() << "\n";
394  }
395  }
396  }
397 
398  (*(cptparamval[var]))[valp]->front()->insert(
399  new gum::Instantiation(inst));
400  }
401  }
402  }
403 
405 
406  while (!cptparamval.empty()) {
407  gum::HashTable<
408  const DiscreteVariable*,
409  gum::HashTable<
410  std::string,
411  gum::Sequence< gum::Sequence< gum::Instantiation* >* >* >* >::iterator
412  itvar
413  = cptparamval.begin();
414 
415  while (!(itvar.val())->empty()) {
416  gum::HashTable< std::string,
417  gum::Sequence< gum::Sequence< gum::Instantiation* >* >* >::
419  = (itvar.val())->begin();
420 
421  for (auto pv: *itpvall.val()) {
422  gum::Idx linecount = 0;
423  gum::HashTable< std::string,
424  gum::HashTable< const gum::DiscreteVariable*,
425  std::pair< gum::Set< Idx >*,
426  gum::Set< Idx >* >* >* >
427  orderStruct; // set sizeof Hashtable
428 
429  gum::Set< gum::Idx > elimination;
431 
432  for (auto seqv: *pv) {
433  if (seqv->nbrDim() > 1) {
434  for (Idx iInst = 0; iInst < seqv->nbrDim(); iInst++) {
435  auto instpro = new gum::Instantiation(*seqv, false);
436  const gum::DiscreteVariable* var = &(seqv->variable(iInst));
437  instpro->erase(*var);
439 
441  && !newSeqpre.exists(instpro->toString())) {
443  instpro->toString(),
444  new gum::HashTable<
445  const gum::DiscreteVariable*,
446  std::pair< gum::Set< Idx >*, gum::Set< Idx >* >* >());
447  }
448 
450  && !orderStruct[instpro->toString()]->exists(var)) {
452  var,
453  new std::pair< gum::Set< Idx >*, gum::Set< Idx >* >(
454  new gum::Set< Idx >,
455  new gum::Set< Idx >(
457  .domainSize()))); // set sizeof Hashtable
458  }
459 
461  && !newSeqpre.exists(instpro->toString())) {
462  gum::HashTable< const gum::DiscreteVariable*,
463  std::pair< gum::Set< Idx >*,
464  gum::Set< Idx >* >* >* orderStruct2
468 
469  if ((*orderStruct2)[var]->second->size() == var->domainSize()) {
471 
472  for (auto& elt: *orderStruct2) {
474  delete (elt.second->first);
475  delete (elt.second->second);
476  delete (elt.second);
477  }
478 
479  orderStruct2->clear();
480 
481  delete orderStruct2;
483  } else
484  delete instpro;
485  } else if (newSeqpre.exists(instpro->toString())) {
487  delete instpro;
488  }
489  }
490  }
491 
492  linecount += 1;
493  }
494 
495  gum::Sequence< gum::Instantiation* >* newSeq = nullptr;
496 
497  if (!newSeqpre.empty()) {
498  newSeq = new gum::Sequence< gum::Instantiation* >();
499 
500  for (auto& elt: newSeqpre)
502 
503  (itpvall.val())->insert(newSeq);
504 
505  for (Idx itelem = pv->size(); itelem > 0; itelem--) {
506  if (elimination.exists(itelem - 1)) {
507  delete ((*pv)[itelem - 1]);
508  pv->erase((*pv)[itelem - 1]);
509  }
510  }
511  }
512 
513  while (!orderStruct.empty()) {
514  while (!(orderStruct.begin().val())->empty()) {
515  delete orderStruct.begin().val()->begin().val()->first;
516  delete orderStruct.begin().val()->begin().val()->second;
517  (orderStruct.begin().val())
518  ->erase(orderStruct.begin().val()->beginSafe()); // safe
519  // iterator
520  // needed here
521  }
522 
523  delete orderStruct.begin().val();
525  orderStruct.beginSafe()); // safe iterator needed here
526  }
527  }
528 
529  while (!(itpvall.val())->empty()) {
531  itpv
532  = (itpvall.val())->begin();
533 
534  while (!(*itpv)->empty()) {
536  = (*itpv)->begin();
537 
538  for (Idx i = 0; i < (*itseqv)->nbrDim(); i++) {
540  str << (*itseqv)->variable(i).name() << "_"
541  << (*itseqv)->val((*itseqv)->variable(i));
542  str2 << "-" << vartable[str.str()] << " ";
543  }
544 
545  /*if (itpvall.key().compare("0") != 0 &&
546  itpvall.key().compare("0.0") != 0) { */
547  if (itpvall.key() != "0" && itpvall.key() != "0.0") {
549  strinst << itvar.key()->name();
550  strinst << "_val=" << itpvall.key();
551  str2 << protable[strinst.str()];
552  }
553 
554  str2 << " 0\n";
555  clause++;
556  delete (*itseqv);
557  (*itpv)->erase((*itpv)->beginSafe()); // safe iterator needed here
558  }
559 
560  delete (*itpv);
561  (itpvall.val())
562  ->erase(itpvall.val()->beginSafe()); // safe iterator needed here
563  }
564 
565  delete (itpvall.val());
566  (itvar.val())
567  ->erase(itvar.val()->beginSafe()); // safe iterator needed here
568  }
569 
570  delete (itvar.val());
571  cptparamval.erase(cptparamval.beginSafe()); // safe iterator needed here
572  }
573 
574  clausstr << str2.str();
575 
576  output << "p cnf " << num << " " << clause << "\neclauses " << numvar << "\n"
577  << clausstr.str() << clausstr2.str() << std::endl;
578  output.flush();
579  outputvar << strfile.str();
580  outputvar.flush();
581 
582  outputvar.close();
583  output.close();
584 
585  if (outputvar.fail()) GUM_ERROR(IOError, "Writting in the ostream failed.");
586 
587  if (output.fail()) GUM_ERROR(IOError, "Writting in the ostream failed.");
588  }
589 
590 } /* namespace gum */
591 
592 #endif // DOXYGEN_SHOULD_SKIP_THIS
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669