aGrUM  0.14.2
ContextualDependenciesCNFWriter_tpl.h
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005 by Pierre-Henri WUILLEMIN et Christophe GONZALES *
3  * {prenom.nom}_at_lip6.fr *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19  ***************************************************************************/
20 
21 #ifndef DOXYGEN_SHOULD_SKIP_THIS
22 
23 // to ease parsing in IDE
25 
26 namespace gum {
27  /* =========================================================================*/
28  /* === GUM_BN_WRITER === */
29  /* =========================================================================*/
30  // Default constructor.
31  template < typename GUM_SCALAR, template < class > class IApproximationPolicy >
34  GUM_CONSTRUCTOR(ContextualDependenciesCNFWriter);
35  }
36 
37  // Default destructor.
38  template < typename GUM_SCALAR, template < class > class IApproximationPolicy >
41  GUM_DESTRUCTOR(ContextualDependenciesCNFWriter);
42  }
43 
44  //
45  // Writes a Bayesian Network in the output stream using the BN format.
46  //
47  // @param ouput The output stream.
48  // @param bn The Bayesian Network writen in output.
49  // @throws Raised if an I/O error occurs.
50  template < typename GUM_SCALAR, template < class > class IApproximationPolicy >
51  INLINE void
53  std::ostream& output, const IBayesNet< GUM_SCALAR >& bn) {
54  Instantiation Order;
55 
56  for (auto node : bn.topologicalOrder())
57  Order.add(bn.variable(node));
58 
59  if (!output.good())
60  GUM_ERROR(IOError, "Stream states flags are not all unset.");
61 
62  std::stringstream strfile, strfile2;
63 
64  Idx num = 0;
65  Idx numvar = 0;
66  Idx clause = 0;
67  std::stringstream clausstr, clausstr2;
71  const gum::DiscreteVariable*,
72  gum::HashTable< std::string,
74  cptparamval;
75 
76  for (auto node : bn.nodes()) {
77  std::stringstream str0;
78  const DiscreteVariable* var = &bn.variable(node);
79 
80  for (Idx i = 0; i < var->domainSize(); i++) {
81  std::stringstream stri;
82  stri << var->name() << "_" << var->label(i);
83  vartable.insert(stri.str(), ++num);
84  strfile << num << "::" << stri.str() << "\n";
85  str0 << vartable[stri.str()] << " ";
86  }
87 
88  str0 << "0\n";
89  clause++;
90  numvar++;
91  clausstr2 << str0.str();
92  const Potential< GUM_SCALAR >& cpt = bn.cpt(node);
93  Instantiation inst(cpt);
94  inst.forgetMaster();
95  inst.reorder(Order);
96  cptparamval.insert(
97  var,
98  new gum::HashTable<
99  std::string,
101 
102  for (inst.setFirst(); !inst.end(); ++inst) {
103  if (this->fromExact(cpt[inst]) != 1) {
104  std::stringstream strk;
105  strk << this->fromExact(cpt[inst]);
106  std::string valp = strk.str();
107 
108  if (!(cptparamval[var])->exists(valp)) {
109  (cptparamval[var])
110  ->insert(
111  valp,
113 
114  (*(cptparamval[var]))[valp]->insert(
116 
117  if (this->fromExact(cpt[inst])) {
118  std::stringstream strinst;
119  strinst << var->name();
120  strinst << "_val=" << this->fromExact(cpt[inst]);
121 
122  if (!protable.exists(strinst.str())) {
123  protable.insert(strinst.str(), ++num);
124  strfile << num << "::" << strinst.str() << "\n";
125  }
126  }
127  }
128 
129  (*(cptparamval[var]))[valp]->front()->insert(
130  new gum::Instantiation(inst));
131  }
132  }
133  }
134 
135  std::stringstream str2;
136 
137  while (!cptparamval.empty()) {
139  const DiscreteVariable*,
141  std::string,
143  itvar = cptparamval.begin();
144 
145  while (!(itvar.val())->empty()) {
146  gum::HashTable< std::string,
148  iterator itpvall = (itvar.val())->begin(); // needed here
149 
150  for (auto pv : *itpvall.val()) {
151  gum::Idx linecount = 0;
152  gum::HashTable< std::string,
153  gum::HashTable< const gum::DiscreteVariable*,
154  std::pair< gum::Set< Idx >*,
155  gum::Set< Idx >* >* >* >
156  orderStruct; // set sizeof Hashtable
157 
158  for (auto seqv : *pv) {
159  if (seqv->nbrDim() > 1) {
160  for (Idx iInst = 0; iInst < seqv->nbrDim(); iInst++) {
161  gum::Instantiation instpro(*seqv, false);
162  instpro.reorder(Order);
163  const gum::DiscreteVariable* var = &(seqv->variable(iInst));
164  instpro.erase(*var); // reorder instance to optimize make sure
165  // key unicity.
166 
167  if (!orderStruct.exists(instpro.toString())) {
168  orderStruct.insert(
169  instpro.toString(),
170  new gum::HashTable<
171  const gum::DiscreteVariable*,
172  std::pair< gum::Set< Idx >*, gum::Set< Idx >* >* >());
173  }
174 
175  if (!orderStruct[instpro.toString()]->exists(var)) {
176  orderStruct[instpro.toString()]->insert(
177  var,
178  new std::pair< gum::Set< Idx >*, gum::Set< Idx >* >(
179  new gum::Set< Idx >,
180  new gum::Set< Idx >(
181  seqv->variable(iInst)
182  .domainSize()))); // set sizeof Hashtable
183  }
184 
185  gum::HashTable< const gum::DiscreteVariable*,
186  std::pair< gum::Set< Idx >*, gum::Set< Idx >* >* >*
187  orderStruct2 = orderStruct[instpro.toString()];
188  (*orderStruct2)[var]->first->insert(linecount);
189  (*orderStruct2)[var]->second->insert(seqv->val(iInst));
190  }
191  }
192 
193  linecount += 1;
194  }
195 
196  gum::Set< gum::Idx > elimination;
197  gum::Sequence< gum::Instantiation* >* newSeq = nullptr;
198 
199  for (auto& elt : orderStruct) {
200  bool added = false;
201 
202  for (auto& elt2 : *elt.second) {
203  if (elt2.second->second->size() == elt2.first->domainSize()) {
204  if (!newSeq) newSeq = new gum::Sequence< gum::Instantiation* >();
205 
206  if (!added) {
207  added = true;
208  newSeq->insert(new gum::Instantiation(
209  *((*pv)[(*(elt2.second->first->begin()))]), false));
210  newSeq->back()->erase(*elt2.first);
211  }
212 
213  elimination = elimination + *(elt2.second->first);
214  }
215  }
216  }
217 
218  if (newSeq) {
219  (itpvall.val())->insert(newSeq);
220 
221  for (Idx itelem = pv->size(); itelem > 0; itelem--) {
222  if (elimination.exists(itelem - 1)) {
223  delete ((*pv)[itelem - 1]);
224  pv->erase((*pv)[itelem - 1]);
225  }
226  }
227  }
228 
229  while (!orderStruct.empty()) {
230  while (!(orderStruct.begin().val())->empty()) {
231  delete orderStruct.begin().val()->begin().val()->first;
232  delete orderStruct.begin().val()->begin().val()->second;
233  (orderStruct.begin().val())
234  ->erase((orderStruct.begin().val())
235  ->beginSafe()); // safe iterator needed here
236  }
237 
238  delete orderStruct.begin().val();
239  orderStruct.erase(
240  orderStruct.beginSafe()); // safe iterator needed here
241  }
242  }
243 
244  while (!(itpvall.val())->empty()) {
246  (itpvall.val())->begin();
247 
248  while (!(*itpv)->empty()) {
250  (*itpv)->begin();
251 
252  for (Idx i = 0; i < (*itseqv)->nbrDim(); i++) {
253  std::stringstream str;
254  str << (*itseqv)->variable(i).name() << "_"
255  << (*itseqv)->val((*itseqv)->variable(i));
256  str2 << "-" << vartable[str.str()] << " ";
257  }
258 
259  // if (itpvall.key().compare("0") != 0 &&
260  // itpvall.key().compare("0.0") != 0) {
261  if (itpvall.key() != "0" && itpvall.key() != "0.0") {
262  std::stringstream strinst;
263  strinst << itvar.key()->name();
264  strinst << "_val=" << itpvall.key();
265  str2 << protable[strinst.str()];
266  }
267 
268  str2 << " 0\n";
269  clause++;
270  delete (*itseqv);
271  (*itpv)->erase(itseqv);
272  }
273 
274  delete (*itpv);
275  (itpvall.val())->erase(itpv);
276  }
277 
278  delete (itpvall.val());
279  (itvar.val())
280  ->erase(itvar.val()->beginSafe()); // safe iterator needed here
281  }
282 
283  delete (itvar.val());
284  cptparamval.erase(cptparamval.beginSafe()); // safe iterator needed here
285  }
286 
287  clausstr << str2.str();
288 
289  output << "p cnf " << num << " " << clause << "\neclauses " << numvar << "\n"
290  << clausstr.str() << clausstr2.str() << std::endl;
291  output.flush();
292  }
293 
294  // Writes a Bayesian Network in the referenced file using the BN format.
295  // If the file doesn't exists, it is created.
296  // If the file exists, it's content will be erased.
297  //
298  // @param filePath The path to the file used to write the Bayesian Network.
299  // @param bn The Bayesian Network writed in the file.
300  // @throws Raised if an I/O error occurs.
301  template < typename GUM_SCALAR, template < class > class IApproximationPolicy >
302  INLINE void
304  const std::string& filePath, const IBayesNet< GUM_SCALAR >& bn) {
305  std::ofstream output(filePath.c_str(), std::ios_base::trunc);
306  std::ofstream outputvar((filePath + ".var").c_str(), std::ios_base::trunc);
307 
308  if (!output.good())
309  GUM_ERROR(IOError, "Stream states flags are not all unset.");
310 
311  std::stringstream strfile, strfile2;
312 
313  if (!outputvar.good())
314  GUM_ERROR(IOError, "Stream states flags are not all unset.");
315 
316  Idx num = 0;
317  Idx numvar = 0;
318  Idx clause = 0;
319  std::stringstream clausstr, clausstr2;
323  const gum::DiscreteVariable*,
324  gum::HashTable< std::string,
326  cptparamval;
327 
328  Instantiation Order;
329 
330  for (auto node : bn.topologicalOrder())
331  Order.add(bn.variable(node));
332 
333  for (auto node : bn.nodes()) {
334  std::stringstream str0;
335  const DiscreteVariable* var = &bn.variable(node);
336 
337  for (Idx i = 0; i < bn.variable(node).domainSize(); i++) {
338  std::stringstream stri;
339  stri << var->name() << "_" << var->label(i);
340  vartable.insert(stri.str(), ++num);
341  strfile << num << "::" << stri.str() << "\n";
342  str0 << vartable[stri.str()] << " ";
343  }
344 
345  str0 << "0\n";
346  clause++;
347  numvar++;
348  clausstr2 << str0.str();
349  const Potential< GUM_SCALAR >& cpt = bn.cpt(node);
350  Instantiation inst(cpt);
351  inst.forgetMaster();
352  inst.reorder(Order);
353  cptparamval.insert(
354  var,
355  new gum::HashTable<
356  std::string,
358 
359  for (inst.setFirst(); !inst.end(); ++inst) {
360  if (this->fromExact(cpt[inst]) != 1) {
361  std::stringstream strk;
362  strk << this->fromExact(cpt[inst]);
363  std::string valp = strk.str();
364 
365  if (!(cptparamval[var])->exists(valp)) {
366  (cptparamval[var])
367  ->insert(
368  valp,
369  new gum::Sequence<
370  gum::Sequence< gum::Instantiation* >* >()); // remember
371  // to
372  // verify
373  // protocole for
374  // param = to 1
375 
376  (*(cptparamval[var]))[valp]->insert(
378 
379  if (this->fromExact(cpt[inst])) {
380  std::stringstream strinst;
381  strinst << var->name();
382  strinst << "_val=" << this->fromExact(cpt[inst]);
383 
384  if (!protable.exists(strinst.str())) {
385  protable.insert(strinst.str(), ++num);
386  strfile << num << "::" << strinst.str() << "\n";
387  }
388  }
389  }
390 
391  (*(cptparamval[var]))[valp]->front()->insert(
392  new gum::Instantiation(inst));
393  }
394  }
395  }
396 
397  std::stringstream str2;
398 
399  while (!cptparamval.empty()) {
401  const DiscreteVariable*,
403  std::string,
405  itvar = cptparamval.begin();
406 
407  while (!(itvar.val())->empty()) {
408  gum::HashTable< std::string,
410  iterator itpvall = (itvar.val())->begin();
411 
412  for (auto pv : *itpvall.val()) {
413  gum::Idx linecount = 0;
414  gum::HashTable< std::string,
415  gum::HashTable< const gum::DiscreteVariable*,
416  std::pair< gum::Set< Idx >*,
417  gum::Set< Idx >* >* >* >
418  orderStruct; // set sizeof Hashtable
419 
420  gum::Set< gum::Idx > elimination;
422 
423  for (auto seqv : *pv) {
424  if (seqv->nbrDim() > 1) {
425  for (Idx iInst = 0; iInst < seqv->nbrDim(); iInst++) {
426  auto instpro = new gum::Instantiation(*seqv, false);
427  const gum::DiscreteVariable* var = &(seqv->variable(iInst));
428  instpro->erase(*var);
429  instpro->reorder(Order);
430 
431  if (!orderStruct.exists(instpro->toString())
432  && !newSeqpre.exists(instpro->toString())) {
433  orderStruct.insert(
434  instpro->toString(),
435  new gum::HashTable<
436  const gum::DiscreteVariable*,
437  std::pair< gum::Set< Idx >*, gum::Set< Idx >* >* >());
438  }
439 
440  if (orderStruct.exists(instpro->toString())
441  && !orderStruct[instpro->toString()]->exists(var)) {
442  orderStruct[instpro->toString()]->insert(
443  var,
444  new std::pair< gum::Set< Idx >*, gum::Set< Idx >* >(
445  new gum::Set< Idx >,
446  new gum::Set< Idx >(
447  seqv->variable(iInst)
448  .domainSize()))); // set sizeof Hashtable
449  }
450 
451  if (orderStruct.exists(instpro->toString())
452  && !newSeqpre.exists(instpro->toString())) {
453  gum::HashTable< const gum::DiscreteVariable*,
454  std::pair< gum::Set< Idx >*,
455  gum::Set< Idx >* >* >* orderStruct2 =
456  orderStruct[instpro->toString()];
457  (*orderStruct2)[var]->first->insert(linecount);
458  (*orderStruct2)[var]->second->insert(seqv->val(iInst));
459 
460  if ((*orderStruct2)[var]->second->size() == var->domainSize()) {
461  newSeqpre.insert(instpro->toString(), instpro);
462 
463  for (auto& elt : *orderStruct2) {
464  elimination = elimination + *(elt.second->first);
465  delete (elt.second->first);
466  delete (elt.second->second);
467  delete (elt.second);
468  }
469 
470  orderStruct2->clear();
471 
472  delete orderStruct2;
473  orderStruct.erase(instpro->toString());
474  } else
475  delete instpro;
476  } else if (newSeqpre.exists(instpro->toString())) {
477  elimination.insert(linecount);
478  delete instpro;
479  }
480  }
481  }
482 
483  linecount += 1;
484  }
485 
486  gum::Sequence< gum::Instantiation* >* newSeq = nullptr;
487 
488  if (!newSeqpre.empty()) {
490 
491  for (auto& elt : newSeqpre)
492  newSeq->insert(elt.second);
493 
494  (itpvall.val())->insert(newSeq);
495 
496  for (Idx itelem = pv->size(); itelem > 0; itelem--) {
497  if (elimination.exists(itelem - 1)) {
498  delete ((*pv)[itelem - 1]);
499  pv->erase((*pv)[itelem - 1]);
500  }
501  }
502  }
503 
504  while (!orderStruct.empty()) {
505  while (!(orderStruct.begin().val())->empty()) {
506  delete orderStruct.begin().val()->begin().val()->first;
507  delete orderStruct.begin().val()->begin().val()->second;
508  (orderStruct.begin().val())
509  ->erase(orderStruct.begin().val()->beginSafe()); // safe
510  // iterator
511  // needed here
512  }
513 
514  delete orderStruct.begin().val();
515  orderStruct.erase(
516  orderStruct.beginSafe()); // safe iterator needed here
517  }
518  }
519 
520  while (!(itpvall.val())->empty()) {
522  itpv = (itpvall.val())->begin();
523 
524  while (!(*itpv)->empty()) {
526  (*itpv)->begin();
527 
528  for (Idx i = 0; i < (*itseqv)->nbrDim(); i++) {
529  std::stringstream str;
530  str << (*itseqv)->variable(i).name() << "_"
531  << (*itseqv)->val((*itseqv)->variable(i));
532  str2 << "-" << vartable[str.str()] << " ";
533  }
534 
535  /*if (itpvall.key().compare("0") != 0 &&
536  itpvall.key().compare("0.0") != 0) { */
537  if (itpvall.key() != "0" && itpvall.key() != "0.0") {
538  std::stringstream strinst;
539  strinst << itvar.key()->name();
540  strinst << "_val=" << itpvall.key();
541  str2 << protable[strinst.str()];
542  }
543 
544  str2 << " 0\n";
545  clause++;
546  delete (*itseqv);
547  (*itpv)->erase((*itpv)->beginSafe()); // safe iterator needed here
548  }
549 
550  delete (*itpv);
551  (itpvall.val())
552  ->erase(itpvall.val()->beginSafe()); // safe iterator needed here
553  }
554 
555  delete (itpvall.val());
556  (itvar.val())
557  ->erase(itvar.val()->beginSafe()); // safe iterator needed here
558  }
559 
560  delete (itvar.val());
561  cptparamval.erase(cptparamval.beginSafe()); // safe iterator needed here
562  }
563 
564  clausstr << str2.str();
565 
566  output << "p cnf " << num << " " << clause << "\neclauses " << numvar << "\n"
567  << clausstr.str() << clausstr2.str() << std::endl;
568  output.flush();
569  outputvar << strfile.str();
570  outputvar.flush();
571 
572  outputvar.close();
573  output.close();
574 
575  if (outputvar.fail()) GUM_ERROR(IOError, "Writting in the ostream failed.");
576 
577  if (output.fail()) GUM_ERROR(IOError, "Writting in the ostream failed.");
578  }
579 
580 } /* namespace gum */
581 
582 #endif // DOXYGEN_SHOULD_SKIP_THIS
Safe iterators for Sequence.
Definition: sequence.h:1203
iterator begin() const
Returns an unsafe begin iterator.
Definition: sequence_tpl.h:654
The generic class for storing (ordered) sequences of objects.
Definition: sequence.h:1019
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:653
Base class for discrete random variable.
gum is the global namespace for all aGrUM entities
Definition: agrum.h:25
~ContextualDependenciesCNFWriter() final
Destructor.
Representation of a setA Set is a structure that contains arbitrary elements.
Definition: set.h:162
SequenceIterator< Key > iterator
Types for STL compliance.
Definition: sequence.h:1032
virtual Size domainSize() const =0
bool exists(const Key &k) const
Indicates whether a given elements belong to the set.
Definition: set_tpl.h:604
Class for assigning/browsing values to tuples of discrete variables.
Definition: instantiation.h:80
Size Idx
Type for indexes.
Definition: types.h:50
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:372
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.
Definition of classe for BN file output manipulation.
void insert(const Key &k)
Inserts a new element into the set.
Definition: set_tpl.h:610
const Key & back() const
Returns the last element of the sequence.
Definition: sequence_tpl.h:565
#define GUM_ERROR(type, msg)
Definition: exceptions.h:52
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:405