aGrUM  0.16.0
ContextualDependenciesCNFWriter_tpl.h
Go to the documentation of this file.
1 
23 #ifndef DOXYGEN_SHOULD_SKIP_THIS
24 
25 // to ease parsing in IDE
27 
28 namespace gum {
29  /* =========================================================================*/
30  /* === GUM_BN_WRITER === */
31  /* =========================================================================*/
32  // Default constructor.
33  template < typename GUM_SCALAR, template < class > class IApproximationPolicy >
36  GUM_CONSTRUCTOR(ContextualDependenciesCNFWriter);
37  }
38 
39  // Default destructor.
40  template < typename GUM_SCALAR, template < class > class IApproximationPolicy >
43  GUM_DESTRUCTOR(ContextualDependenciesCNFWriter);
44  }
45 
46  //
47  // Writes a Bayesian Network in the output stream using the BN format.
48  //
49  // @param ouput The output stream.
50  // @param bn The Bayesian Network writen in output.
51  // @throws Raised if an I/O error occurs.
52  template < typename GUM_SCALAR, template < class > class IApproximationPolicy >
53  INLINE void
55  std::ostream& output, const IBayesNet< GUM_SCALAR >& bn) {
56  Instantiation Order;
57 
58  for (auto node : bn.topologicalOrder())
59  Order.add(bn.variable(node));
60 
61  if (!output.good())
62  GUM_ERROR(IOError, "Stream states flags are not all unset.");
63 
64  std::stringstream strfile, strfile2;
65 
66  Idx num = 0;
67  Idx numvar = 0;
68  Idx clause = 0;
69  std::stringstream clausstr, clausstr2;
73  const gum::DiscreteVariable*,
74  gum::HashTable< std::string,
76  cptparamval;
77 
78  for (auto node : bn.nodes()) {
79  std::stringstream str0;
80  const DiscreteVariable* var = &bn.variable(node);
81 
82  for (Idx i = 0; i < var->domainSize(); i++) {
83  std::stringstream stri;
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);
95  Instantiation inst(cpt);
96  inst.forgetMaster();
97  inst.reorder(Order);
98  cptparamval.insert(
99  var,
100  new gum::HashTable<
101  std::string,
103 
104  for (inst.setFirst(); !inst.end(); ++inst) {
105  if (this->fromExact(cpt[inst]) != 1) {
106  std::stringstream strk;
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,
115 
116  (*(cptparamval[var]))[valp]->insert(
118 
119  if (this->fromExact(cpt[inst])) {
120  std::stringstream strinst;
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 
137  std::stringstream str2;
138 
139  while (!cptparamval.empty()) {
141  const DiscreteVariable*,
143  std::string,
145  itvar = cptparamval.begin();
146 
147  while (!(itvar.val())->empty()) {
148  gum::HashTable< std::string,
150  iterator itpvall = (itvar.val())->begin(); // needed here
151 
152  for (auto pv : *itpvall.val()) {
153  gum::Idx linecount = 0;
154  gum::HashTable< std::string,
155  gum::HashTable< const gum::DiscreteVariable*,
156  std::pair< gum::Set< Idx >*,
157  gum::Set< Idx >* >* >* >
158  orderStruct; // set sizeof Hashtable
159 
160  for (auto seqv : *pv) {
161  if (seqv->nbrDim() > 1) {
162  for (Idx iInst = 0; iInst < seqv->nbrDim(); iInst++) {
163  gum::Instantiation instpro(*seqv, false);
164  instpro.reorder(Order);
165  const gum::DiscreteVariable* var = &(seqv->variable(iInst));
166  instpro.erase(*var); // reorder instance to optimize make sure
167  // key unicity.
168 
169  if (!orderStruct.exists(instpro.toString())) {
170  orderStruct.insert(
171  instpro.toString(),
172  new gum::HashTable<
173  const gum::DiscreteVariable*,
174  std::pair< gum::Set< Idx >*, gum::Set< Idx >* >* >());
175  }
176 
177  if (!orderStruct[instpro.toString()]->exists(var)) {
178  orderStruct[instpro.toString()]->insert(
179  var,
180  new std::pair< gum::Set< Idx >*, gum::Set< Idx >* >(
181  new gum::Set< Idx >,
182  new gum::Set< Idx >(
183  seqv->variable(iInst)
184  .domainSize()))); // set sizeof Hashtable
185  }
186 
187  gum::HashTable< const gum::DiscreteVariable*,
188  std::pair< gum::Set< Idx >*, gum::Set< Idx >* >* >*
189  orderStruct2 = orderStruct[instpro.toString()];
190  (*orderStruct2)[var]->first->insert(linecount);
191  (*orderStruct2)[var]->second->insert(seqv->val(iInst));
192  }
193  }
194 
195  linecount += 1;
196  }
197 
198  gum::Set< gum::Idx > elimination;
199  gum::Sequence< gum::Instantiation* >* newSeq = nullptr;
200 
201  for (auto& elt : orderStruct) {
202  bool added = false;
203 
204  for (auto& elt2 : *elt.second) {
205  if (elt2.second->second->size() == elt2.first->domainSize()) {
206  if (!newSeq) newSeq = new gum::Sequence< gum::Instantiation* >();
207 
208  if (!added) {
209  added = true;
210  newSeq->insert(new gum::Instantiation(
211  *((*pv)[(*(elt2.second->first->begin()))]), false));
212  newSeq->back()->erase(*elt2.first);
213  }
214 
215  elimination = elimination + *(elt2.second->first);
216  }
217  }
218  }
219 
220  if (newSeq) {
221  (itpvall.val())->insert(newSeq);
222 
223  for (Idx itelem = pv->size(); itelem > 0; itelem--) {
224  if (elimination.exists(itelem - 1)) {
225  delete ((*pv)[itelem - 1]);
226  pv->erase((*pv)[itelem - 1]);
227  }
228  }
229  }
230 
231  while (!orderStruct.empty()) {
232  while (!(orderStruct.begin().val())->empty()) {
233  delete orderStruct.begin().val()->begin().val()->first;
234  delete orderStruct.begin().val()->begin().val()->second;
235  (orderStruct.begin().val())
236  ->erase((orderStruct.begin().val())
237  ->beginSafe()); // safe iterator needed here
238  }
239 
240  delete orderStruct.begin().val();
241  orderStruct.erase(
242  orderStruct.beginSafe()); // safe iterator needed here
243  }
244  }
245 
246  while (!(itpvall.val())->empty()) {
248  (itpvall.val())->begin();
249 
250  while (!(*itpv)->empty()) {
252  (*itpv)->begin();
253 
254  for (Idx i = 0; i < (*itseqv)->nbrDim(); i++) {
255  std::stringstream str;
256  str << (*itseqv)->variable(i).name() << "_"
257  << (*itseqv)->val((*itseqv)->variable(i));
258  str2 << "-" << vartable[str.str()] << " ";
259  }
260 
261  // if (itpvall.key().compare("0") != 0 &&
262  // itpvall.key().compare("0.0") != 0) {
263  if (itpvall.key() != "0" && itpvall.key() != "0.0") {
264  std::stringstream strinst;
265  strinst << itvar.key()->name();
266  strinst << "_val=" << itpvall.key();
267  str2 << protable[strinst.str()];
268  }
269 
270  str2 << " 0\n";
271  clause++;
272  delete (*itseqv);
273  (*itpv)->erase(itseqv);
274  }
275 
276  delete (*itpv);
277  (itpvall.val())->erase(itpv);
278  }
279 
280  delete (itpvall.val());
281  (itvar.val())
282  ->erase(itvar.val()->beginSafe()); // safe iterator needed here
283  }
284 
285  delete (itvar.val());
286  cptparamval.erase(cptparamval.beginSafe()); // safe iterator needed here
287  }
288 
289  clausstr << str2.str();
290 
291  output << "p cnf " << num << " " << clause << "\neclauses " << numvar << "\n"
292  << clausstr.str() << clausstr2.str() << std::endl;
293  output.flush();
294  }
295 
296  // Writes a Bayesian Network in the referenced file using the BN format.
297  // If the file doesn't exists, it is created.
298  // If the file exists, it's content will be erased.
299  //
300  // @param filePath The path to the file used to write the Bayesian Network.
301  // @param bn The Bayesian Network writed in the file.
302  // @throws Raised if an I/O error occurs.
303  template < typename GUM_SCALAR, template < class > class IApproximationPolicy >
304  INLINE void
306  const std::string& filePath, const IBayesNet< GUM_SCALAR >& bn) {
307  std::ofstream output(filePath.c_str(), std::ios_base::trunc);
308  std::ofstream outputvar((filePath + ".var").c_str(), std::ios_base::trunc);
309 
310  if (!output.good())
311  GUM_ERROR(IOError, "Stream states flags are not all unset.");
312 
313  std::stringstream strfile, strfile2;
314 
315  if (!outputvar.good())
316  GUM_ERROR(IOError, "Stream states flags are not all unset.");
317 
318  Idx num = 0;
319  Idx numvar = 0;
320  Idx clause = 0;
321  std::stringstream clausstr, clausstr2;
325  const gum::DiscreteVariable*,
326  gum::HashTable< std::string,
328  cptparamval;
329 
330  Instantiation Order;
331 
332  for (auto node : bn.topologicalOrder())
333  Order.add(bn.variable(node));
334 
335  for (auto node : bn.nodes()) {
336  std::stringstream str0;
337  const DiscreteVariable* var = &bn.variable(node);
338 
339  for (Idx i = 0; i < bn.variable(node).domainSize(); i++) {
340  std::stringstream stri;
341  stri << var->name() << "_" << var->label(i);
342  vartable.insert(stri.str(), ++num);
343  strfile << num << "::" << stri.str() << "\n";
344  str0 << vartable[stri.str()] << " ";
345  }
346 
347  str0 << "0\n";
348  clause++;
349  numvar++;
350  clausstr2 << str0.str();
351  const Potential< GUM_SCALAR >& cpt = bn.cpt(node);
352  Instantiation inst(cpt);
353  inst.forgetMaster();
354  inst.reorder(Order);
355  cptparamval.insert(
356  var,
357  new gum::HashTable<
358  std::string,
360 
361  for (inst.setFirst(); !inst.end(); ++inst) {
362  if (this->fromExact(cpt[inst]) != 1) {
363  std::stringstream strk;
364  strk << this->fromExact(cpt[inst]);
365  std::string valp = strk.str();
366 
367  if (!(cptparamval[var])->exists(valp)) {
368  (cptparamval[var])
369  ->insert(
370  valp,
371  new gum::Sequence<
372  gum::Sequence< gum::Instantiation* >* >()); // remember
373  // to
374  // verify
375  // protocole for
376  // param = to 1
377 
378  (*(cptparamval[var]))[valp]->insert(
380 
381  if (this->fromExact(cpt[inst])) {
382  std::stringstream strinst;
383  strinst << var->name();
384  strinst << "_val=" << this->fromExact(cpt[inst]);
385 
386  if (!protable.exists(strinst.str())) {
387  protable.insert(strinst.str(), ++num);
388  strfile << num << "::" << strinst.str() << "\n";
389  }
390  }
391  }
392 
393  (*(cptparamval[var]))[valp]->front()->insert(
394  new gum::Instantiation(inst));
395  }
396  }
397  }
398 
399  std::stringstream str2;
400 
401  while (!cptparamval.empty()) {
403  const DiscreteVariable*,
405  std::string,
407  itvar = cptparamval.begin();
408 
409  while (!(itvar.val())->empty()) {
410  gum::HashTable< std::string,
412  iterator itpvall = (itvar.val())->begin();
413 
414  for (auto pv : *itpvall.val()) {
415  gum::Idx linecount = 0;
416  gum::HashTable< std::string,
417  gum::HashTable< const gum::DiscreteVariable*,
418  std::pair< gum::Set< Idx >*,
419  gum::Set< Idx >* >* >* >
420  orderStruct; // set sizeof Hashtable
421 
422  gum::Set< gum::Idx > elimination;
424 
425  for (auto seqv : *pv) {
426  if (seqv->nbrDim() > 1) {
427  for (Idx iInst = 0; iInst < seqv->nbrDim(); iInst++) {
428  auto instpro = new gum::Instantiation(*seqv, false);
429  const gum::DiscreteVariable* var = &(seqv->variable(iInst));
430  instpro->erase(*var);
431  instpro->reorder(Order);
432 
433  if (!orderStruct.exists(instpro->toString())
434  && !newSeqpre.exists(instpro->toString())) {
435  orderStruct.insert(
436  instpro->toString(),
437  new gum::HashTable<
438  const gum::DiscreteVariable*,
439  std::pair< gum::Set< Idx >*, gum::Set< Idx >* >* >());
440  }
441 
442  if (orderStruct.exists(instpro->toString())
443  && !orderStruct[instpro->toString()]->exists(var)) {
444  orderStruct[instpro->toString()]->insert(
445  var,
446  new std::pair< gum::Set< Idx >*, gum::Set< Idx >* >(
447  new gum::Set< Idx >,
448  new gum::Set< Idx >(
449  seqv->variable(iInst)
450  .domainSize()))); // set sizeof Hashtable
451  }
452 
453  if (orderStruct.exists(instpro->toString())
454  && !newSeqpre.exists(instpro->toString())) {
455  gum::HashTable< const gum::DiscreteVariable*,
456  std::pair< gum::Set< Idx >*,
457  gum::Set< Idx >* >* >* orderStruct2 =
458  orderStruct[instpro->toString()];
459  (*orderStruct2)[var]->first->insert(linecount);
460  (*orderStruct2)[var]->second->insert(seqv->val(iInst));
461 
462  if ((*orderStruct2)[var]->second->size() == var->domainSize()) {
463  newSeqpre.insert(instpro->toString(), instpro);
464 
465  for (auto& elt : *orderStruct2) {
466  elimination = elimination + *(elt.second->first);
467  delete (elt.second->first);
468  delete (elt.second->second);
469  delete (elt.second);
470  }
471 
472  orderStruct2->clear();
473 
474  delete orderStruct2;
475  orderStruct.erase(instpro->toString());
476  } else
477  delete instpro;
478  } else if (newSeqpre.exists(instpro->toString())) {
479  elimination.insert(linecount);
480  delete instpro;
481  }
482  }
483  }
484 
485  linecount += 1;
486  }
487 
488  gum::Sequence< gum::Instantiation* >* newSeq = nullptr;
489 
490  if (!newSeqpre.empty()) {
492 
493  for (auto& elt : newSeqpre)
494  newSeq->insert(elt.second);
495 
496  (itpvall.val())->insert(newSeq);
497 
498  for (Idx itelem = pv->size(); itelem > 0; itelem--) {
499  if (elimination.exists(itelem - 1)) {
500  delete ((*pv)[itelem - 1]);
501  pv->erase((*pv)[itelem - 1]);
502  }
503  }
504  }
505 
506  while (!orderStruct.empty()) {
507  while (!(orderStruct.begin().val())->empty()) {
508  delete orderStruct.begin().val()->begin().val()->first;
509  delete orderStruct.begin().val()->begin().val()->second;
510  (orderStruct.begin().val())
511  ->erase(orderStruct.begin().val()->beginSafe()); // safe
512  // iterator
513  // needed here
514  }
515 
516  delete orderStruct.begin().val();
517  orderStruct.erase(
518  orderStruct.beginSafe()); // safe iterator needed here
519  }
520  }
521 
522  while (!(itpvall.val())->empty()) {
524  itpv = (itpvall.val())->begin();
525 
526  while (!(*itpv)->empty()) {
528  (*itpv)->begin();
529 
530  for (Idx i = 0; i < (*itseqv)->nbrDim(); i++) {
531  std::stringstream str;
532  str << (*itseqv)->variable(i).name() << "_"
533  << (*itseqv)->val((*itseqv)->variable(i));
534  str2 << "-" << vartable[str.str()] << " ";
535  }
536 
537  /*if (itpvall.key().compare("0") != 0 &&
538  itpvall.key().compare("0.0") != 0) { */
539  if (itpvall.key() != "0" && itpvall.key() != "0.0") {
540  std::stringstream strinst;
541  strinst << itvar.key()->name();
542  strinst << "_val=" << itpvall.key();
543  str2 << protable[strinst.str()];
544  }
545 
546  str2 << " 0\n";
547  clause++;
548  delete (*itseqv);
549  (*itpv)->erase((*itpv)->beginSafe()); // safe iterator needed here
550  }
551 
552  delete (*itpv);
553  (itpvall.val())
554  ->erase(itpvall.val()->beginSafe()); // safe iterator needed here
555  }
556 
557  delete (itpvall.val());
558  (itvar.val())
559  ->erase(itvar.val()->beginSafe()); // safe iterator needed here
560  }
561 
562  delete (itvar.val());
563  cptparamval.erase(cptparamval.beginSafe()); // safe iterator needed here
564  }
565 
566  clausstr << str2.str();
567 
568  output << "p cnf " << num << " " << clause << "\neclauses " << numvar << "\n"
569  << clausstr.str() << clausstr2.str() << std::endl;
570  output.flush();
571  outputvar << strfile.str();
572  outputvar.flush();
573 
574  outputvar.close();
575  output.close();
576 
577  if (outputvar.fail()) GUM_ERROR(IOError, "Writting in the ostream failed.");
578 
579  if (output.fail()) GUM_ERROR(IOError, "Writting in the ostream failed.");
580  }
581 
582 } /* namespace gum */
583 
584 #endif // DOXYGEN_SHOULD_SKIP_THIS
Safe iterators for Sequence.
Definition: sequence.h:1206
iterator begin() const
Returns an unsafe begin iterator.
Definition: sequence_tpl.h:657
The generic class for storing (ordered) sequences of objects.
Definition: sequence.h:1022
bool exists(const Key &key) const
Checks whether there exists an element with a given key in the hashtable.
ContextualDependenciesCNFWriter()
Default constructor.
const Key & key(const Key &key) const
Returns a reference on a given key.
void erase(const Key &k)
Erases an element from the set.
Definition: set_tpl.h:656
Base class for discrete random variable.
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
Definition: agrum.h:25
~ContextualDependenciesCNFWriter() final
Destructor.
Representation of a setA Set is a structure that contains arbitrary elements.
Definition: set.h:165
SequenceIterator< Key > iterator
Types for STL compliance.
Definition: sequence.h:1035
virtual Size domainSize() const =0
bool exists(const Key &k) const
Indicates whether a given elements belong to the set.
Definition: set_tpl.h:607
Class for assigning/browsing values to tuples of discrete variables.
Definition: instantiation.h:83
Size Idx
Type for indexes.
Definition: types.h:53
void erase(const DiscreteVariable &v) final
Removes a variable from the Instantiation.
void clear()
Removes all the elements, if any, from the set.
Definition: set_tpl.h:375
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
const std::string & name() const
returns the name of the variable
bool empty() const noexcept
Indicates whether the hash table is empty.
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
void insert(const Key &k)
Inserts a new element into the set.
Definition: set_tpl.h:613
const Key & back() const
Returns the last element of the sequence.
Definition: sequence_tpl.h:568
#define GUM_ERROR(type, msg)
Definition: exceptions.h:55
void write(std::ostream &output, const IBayesNet< GUM_SCALAR > &bn) final
Writes a Bayesian Network in the output stream using the BN format.
void insert(const Key &k)
Insert an element at the end of the sequence.
Definition: sequence_tpl.h:408