aGrUM  0.13.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(valp,
368  new gum::Sequence<
369  gum::Sequence< gum::Instantiation* >* >()); // remember
370  // to
371  // verify
372  // protocole for
373  // param = to 1
374 
375  (*(cptparamval[var]))[valp]->insert(
377 
378  if (this->fromExact(cpt[inst])) {
379  std::stringstream strinst;
380  strinst << var->name();
381  strinst << "_val=" << this->fromExact(cpt[inst]);
382 
383  if (!protable.exists(strinst.str())) {
384  protable.insert(strinst.str(), ++num);
385  strfile << num << "::" << strinst.str() << "\n";
386  }
387  }
388  }
389 
390  (*(cptparamval[var]))[valp]->front()->insert(
391  new gum::Instantiation(inst));
392  }
393  }
394  }
395 
396  std::stringstream str2;
397 
398  while (!cptparamval.empty()) {
400  const DiscreteVariable*,
402  std::string,
404  itvar = cptparamval.begin();
405 
406  while (!(itvar.val())->empty()) {
407  gum::HashTable< std::string,
409  iterator itpvall = (itvar.val())->begin();
410 
411  for (auto pv : *itpvall.val()) {
412  gum::Idx linecount = 0;
413  gum::HashTable< std::string,
414  gum::HashTable< const gum::DiscreteVariable*,
415  std::pair< gum::Set< Idx >*,
416  gum::Set< Idx >* >* >* >
417  orderStruct; // set sizeof Hashtable
418 
419  gum::Set< gum::Idx > elimination;
421 
422  for (auto seqv : *pv) {
423  if (seqv->nbrDim() > 1) {
424  for (Idx iInst = 0; iInst < seqv->nbrDim(); iInst++) {
425  auto instpro = new gum::Instantiation(*seqv, false);
426  const gum::DiscreteVariable* var = &(seqv->variable(iInst));
427  instpro->erase(*var);
428  instpro->reorder(Order);
429 
430  if (!orderStruct.exists(instpro->toString())
431  && !newSeqpre.exists(instpro->toString())) {
432  orderStruct.insert(
433  instpro->toString(),
434  new gum::HashTable<
435  const gum::DiscreteVariable*,
436  std::pair< gum::Set< Idx >*, gum::Set< Idx >* >* >());
437  }
438 
439  if (orderStruct.exists(instpro->toString())
440  && !orderStruct[instpro->toString()]->exists(var)) {
441  orderStruct[instpro->toString()]->insert(
442  var,
443  new std::pair< gum::Set< Idx >*, gum::Set< Idx >* >(
444  new gum::Set< Idx >,
445  new gum::Set< Idx >(
446  seqv->variable(iInst)
447  .domainSize()))); // set sizeof Hashtable
448  }
449 
450  if (orderStruct.exists(instpro->toString())
451  && !newSeqpre.exists(instpro->toString())) {
452  gum::HashTable< const gum::DiscreteVariable*,
453  std::pair< gum::Set< Idx >*,
454  gum::Set< Idx >* >* >* orderStruct2 =
455  orderStruct[instpro->toString()];
456  (*orderStruct2)[var]->first->insert(linecount);
457  (*orderStruct2)[var]->second->insert(seqv->val(iInst));
458 
459  if ((*orderStruct2)[var]->second->size() == var->domainSize()) {
460  newSeqpre.insert(instpro->toString(), instpro);
461 
462  for (auto& elt : *orderStruct2) {
463  elimination = elimination + *(elt.second->first);
464  delete (elt.second->first);
465  delete (elt.second->second);
466  delete (elt.second);
467  }
468 
469  orderStruct2->clear();
470 
471  delete orderStruct2;
472  orderStruct.erase(instpro->toString());
473  } else
474  delete instpro;
475  } else if (newSeqpre.exists(instpro->toString())) {
476  elimination.insert(linecount);
477  delete instpro;
478  }
479  }
480  }
481 
482  linecount += 1;
483  }
484 
485  gum::Sequence< gum::Instantiation* >* newSeq = nullptr;
486 
487  if (!newSeqpre.empty()) {
489 
490  for (auto& elt : newSeqpre)
491  newSeq->insert(elt.second);
492 
493  (itpvall.val())->insert(newSeq);
494 
495  for (Idx itelem = pv->size(); itelem > 0; itelem--) {
496  if (elimination.exists(itelem - 1)) {
497  delete ((*pv)[itelem - 1]);
498  pv->erase((*pv)[itelem - 1]);
499  }
500  }
501  }
502 
503  while (!orderStruct.empty()) {
504  while (!(orderStruct.begin().val())->empty()) {
505  delete orderStruct.begin().val()->begin().val()->first;
506  delete orderStruct.begin().val()->begin().val()->second;
507  (orderStruct.begin().val())
508  ->erase(orderStruct.begin().val()->beginSafe()); // safe
509  // iterator
510  // needed here
511  }
512 
513  delete orderStruct.begin().val();
514  orderStruct.erase(
515  orderStruct.beginSafe()); // safe iterator needed here
516  }
517  }
518 
519  while (!(itpvall.val())->empty()) {
521  itpv = (itpvall.val())->begin();
522 
523  while (!(*itpv)->empty()) {
525  (*itpv)->begin();
526 
527  for (Idx i = 0; i < (*itseqv)->nbrDim(); i++) {
528  std::stringstream str;
529  str << (*itseqv)->variable(i).name() << "_"
530  << (*itseqv)->val((*itseqv)->variable(i));
531  str2 << "-" << vartable[str.str()] << " ";
532  }
533 
534  /*if (itpvall.key().compare("0") != 0 &&
535  itpvall.key().compare("0.0") != 0) { */
536  if (itpvall.key() != "0" && itpvall.key() != "0.0") {
537  std::stringstream strinst;
538  strinst << itvar.key()->name();
539  strinst << "_val=" << itpvall.key();
540  str2 << protable[strinst.str()];
541  }
542 
543  str2 << " 0\n";
544  clause++;
545  delete (*itseqv);
546  (*itpv)->erase((*itpv)->beginSafe()); // safe iterator needed here
547  }
548 
549  delete (*itpv);
550  (itpvall.val())
551  ->erase(itpvall.val()->beginSafe()); // safe iterator needed here
552  }
553 
554  delete (itpvall.val());
555  (itvar.val())
556  ->erase(itvar.val()->beginSafe()); // safe iterator needed here
557  }
558 
559  delete (itvar.val());
560  cptparamval.erase(cptparamval.beginSafe()); // safe iterator needed here
561  }
562 
563  clausstr << str2.str();
564 
565  output << "p cnf " << num << " " << clause << "\neclauses " << numvar << "\n"
566  << clausstr.str() << clausstr2.str() << std::endl;
567  output.flush();
568  outputvar << strfile.str();
569  outputvar.flush();
570 
571  outputvar.close();
572  output.close();
573 
574  if (outputvar.fail()) GUM_ERROR(IOError, "Writting in the ostream failed.");
575 
576  if (output.fail()) GUM_ERROR(IOError, "Writting in the ostream failed.");
577  }
578 
579 } /* namespace gum */
580 
581 #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:653
void erase(const Key &key)
Removes a given element from the hash table.
bool exists(const Key &key) const
Checks whether there exists an element with a given key in the hashtable.
The generic class for storing (ordered) sequences of objects.
Definition: sequence.h:1019
bool exists(const Key &k) const
Indicates whether a given elements belong to the set.
Definition: set_tpl.h:607
ContextualDependenciesCNFWriter()
Default constructor.
void erase(const Key &k)
Erases an element from the set.
Definition: set_tpl.h:656
Base class for discrete random variable.
gum is the global namespace for all aGrUM entities
Definition: agrum.h:25
~ContextualDependenciesCNFWriter() final
Destructor.
const Key & key(const Key &key) const
Returns a reference on a given key.
const Key & back() const
Returns the last element of the sequence.
SequenceIterator< Key > iterator
Types for STL compliance.
Definition: sequence.h:1032
virtual Size domainSize() const =0
Class for assigning/browsing values to tuples of discrete variables.
Definition: instantiation.h:80
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.
unsigned long Idx
Type for indexes.
Definition: types.h:43
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:613
#define GUM_ERROR(type, msg)
Definition: exceptions.h:66
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.