aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
multiDimFunctionGraph_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 /**
23  * @file
24  * @brief Template methods of MultiDimFunctionGraph.
25  *
26  * @author Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
27  * @author Pierre-Henri WUILLEMIN(@LIP6) and Jean-Christophe MAGNAN and Christophe
28  * GONZALES(@AMU)
29  */
30 #include <agrum/tools/multidim/implementations/multiDimFunctionGraph.h>
31 
32 namespace gum {
33 
34  // Default constructor.
35  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
36  INLINE MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy >::MultiDimFunctionGraph(
37  bool isReduced) :
39  _name_("MultiDimFunctionGraph"), _tableName_("NO NAME"), _model_(500, true),
40  _manager_(nullptr), _root_(0), _internalNodeMap_(500, true, false),
41  _var2NodeIdMap_(500, true, false), _isReduced_(isReduced) {
43  _manager_ = nullptr;
44  // Pop up a first node so that id 0 is unavailable
45  _model_.addNode();
46  }
47 
48  // Copy constructor.
49  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
53  _name_("MultiDimFunctionGraph"), _tableName_("No NAME"), _model_(500, true),
54  _manager_(nullptr), _root_(0), _internalNodeMap_(500, true, false),
55  _var2NodeIdMap_(500, true, false), _isReduced_(from.isReducedAndOrdered()) {
57  copy(from);
58  }
59 
60  // Copy Operator.
61  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
65  copy(from);
66  return *this;
67  }
68 
69  // Destructor.
70  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
72  // Manager deletion
74  if (_manager_ != nullptr) delete _manager_;
75  this->clear();
76  }
77 
78  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
81  if (_isReduced_)
84  else
86  }
87 
88  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
90  return _name_;
91  }
92 
93  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
94  INLINE void
96  const GUM_SCALAR& value) const {
98  "Function Graph can't be edited so "
99  "easily.\nMultiDimFunctionGraphManager "
100  "provides the framework to edit a "
101  "Function Graph.")
102  }
103 
104  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
105  INLINE void
108  "Function Graph can't be edited so "
109  "easily.\nMultiDimFunctionGraphManager "
110  "provides the framework to edit a "
111  "Function Graph.")
112  }
113 
114  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
116  const std::vector< GUM_SCALAR >& v) const {
118  "Function Graph can't be edited so "
119  "easily.\nMultiDimFunctionGraphManager "
120  "provides the framework to editaa "
121  "Function Graph.")
122  }
123  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
125  std::initializer_list< GUM_SCALAR > l) const {
127  "Function Graph can't be edited so "
128  "easily.\nMultiDimFunctionGraphManager "
129  "provides the framework to edit a "
130  "Function Graph.")
131  }
132 
133  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
134  INLINE void
137 
138  if (!this->_var2NodeIdMap_.exists(&v)) _var2NodeIdMap_.insert(&v, new LinkedList< NodeId >());
139  }
140 
141  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
142  INLINE void
144  if (this->_var2NodeIdMap_.exists(&v)) {
145  while (_var2NodeIdMap_[&v]->list() != nullptr) {
147  }
148  delete _var2NodeIdMap_[&v];
150  }
151 
153  }
154 
155  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
157  return _internalNodeMap_.size(); // + _valueMap_.size();
158  }
159 
160 
161  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
163  const Instantiation& i,
164  const DiscreteVariable* const var,
165  Idx oldval,
166  Idx newval) {}
167 
168  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
170  const Instantiation& i) {}
171 
172  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
174  const Instantiation& i) {}
175 
176  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
178  const Instantiation& i) {}
179 
180  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
182  const Instantiation& i) {}
183 
184  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
186  const Instantiation& i) {}
187 
188  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
190  const Instantiation* i) const {
192  sBuff << (*i) << " = " << this->get(*i);
193  return sBuff.str();
194  }
195 
196  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
198  const MultiDimContainer< GUM_SCALAR >& src,
199  Instantiation* p_i) const {
201  "You cannot copy another type of multiDim "
202  "into a MultiDimFunctionGraph.");
203  }
204 
205  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
207  const MultiDimContainer< GUM_SCALAR >& src) {
209  "You cannot copy another type of multiDim "
210  "into a MultiDimFunctionGraph.");
211  }
212 
213  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
216  if (this->_isReduced_ != src.isReducedAndOrdered())
218  "Cannot copy a Reduced and Ordered "
219  "function graph into Tree function graph "
220  "(or vice-versa).")
221 
222  this->clear();
223 
224  // New variables insertion
228  ++varIter)
229  this->add(**varIter);
230 
231  std::vector< NodeId > lifo;
233 
234  if (src.isTerminalNode(src.root()))
236  else {
237  this->manager()->setRootNode(
238  this->manager()->addInternalNode(src.node(src.root())->nodeVar()));
239  src2dest.insert(src.root(), this->root());
240  lifo.push_back(src.root());
241  }
242 
243  // Depth-first exploration and copy
244  while (!lifo.empty()) {
246  lifo.pop_back();
247 
249 
250  for (Idx index = 0; index < currentSrcNode->nbSons(); ++index) {
255  } else {
258  }
260  }
262  index,
264  }
265  }
266 
267  manager()->clean();
268  }
269 
270  // Copies src diagrams structure into this diagrams.
271  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
274  const Bijection< const DiscreteVariable*, const DiscreteVariable* >& reassign) {
275  if (this->_isReduced_ != src.isReducedAndOrdered())
277  "Cannot copy a Reduced and Ordered "
278  "function graph into Tree function graph "
279  "(or vice-versa).")
280 
281  this->clear();
282 
283  // New variables insertion
287  ++varIter) {
290  "Var " << (*varIter)->name() << " and var " << reassign.second(*varIter)->name()
291  << " have different domain sizes (" << (*varIter)->domainSize()
292  << "!=" << reassign.second(*varIter)->domainSize() << ")")
293  this->add(*(reassign.second(*varIter)));
294  }
295 
296  std::vector< NodeId > lifo;
298 
299  if (src.isTerminalNode(src.root())) {
301  } else {
302  this->manager()->setRootNode(
304  src2dest.insert(src.root(), this->root());
305  lifo.push_back(src.root());
306  }
307 
308  // Depth-first exploration and copy
309  while (!lifo.empty()) {
311  lifo.pop_back();
312 
314 
315  for (Idx index = 0; index < currentSrcNode->nbSons(); ++index) {
320  } else {
324  }
326  }
328  index,
330  }
331  }
332 
333  manager()->clean();
334  }
335 
336  // Copies src diagrams and multiply every value by the given scalar.
337  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
340  GUM_SCALAR gamma) {
341  if (this->_isReduced_ != src.isReducedAndOrdered())
343  "Cannot copy a Reduced and Ordered "
344  "function graph into Tree function graph "
345  "(or vice-versa).")
346 
347  this->clear();
348 
349  // New variables insertion
353  ++varIter)
354  this->add(**varIter);
355 
356  std::vector< NodeId > lifo;
358 
359  if (src.isTerminalNode(src.root()))
360  this->manager()->setRootNode(
362  else {
363  this->manager()->setRootNode(
364  this->manager()->addInternalNode(src.node(src.root())->nodeVar()));
365  src2dest.insert(src.root(), this->root());
366  lifo.push_back(src.root());
367  }
368 
369  // Depth-first exploration an copy
370  while (!lifo.empty()) {
372  lifo.pop_back();
373 
375 
376  for (Idx index = 0; index < currentSrcNode->nbSons(); ++index) {
381  } else {
384  }
386  }
388  index,
390  }
391  }
392 
393  manager()->clean();
394  }
395 
396  // Clears the function graph
397  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
399  _model_.clear();
400  // Always discard the nodeId 0
401  _model_.addNode();
402 
403  this->clearAllTerminalNodes();
404 
405  // Nodes cleaning
408  ++nodeIter) {
409  delete nodeIter.val();
410  }
412 
413  // Cleaning the list of nodes for each variables
417  ++varIter) {
418  delete varIter.val();
419  }
421 
423  = this->variablesSequence().rbeginSafe();
424  varIter != this->variablesSequence().rendSafe();
425  --varIter) {
426  this->erase(**varIter);
427  }
428  }
429 
430 
431  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
432  INLINE std::string
438  // std::stringstream defaultarcstream;
439  output << std::endl << "digraph \" " << _tableName_ << "\" {" << std::endl;
440 
441  terminalStream << "node [shape = box];" << std::endl;
442  nonTerminalStream << "node [shape = ellipse];" << std::endl;
443  std::string tab = " ";
444 
446  ++nodeIter)
447  if (*nodeIter != 0) {
448  if (this->isTerminalNode((NodeId)*nodeIter))
449  terminalStream << tab << *nodeIter << ";" << tab << *nodeIter << " [label=\"" << *nodeIter
450  << " - " << std::setprecision(30) << this->terminalNodeValue(*nodeIter)
451  << "\"]"
452  << ";" << std::endl;
453  else {
455  nonTerminalStream << tab << *nodeIter << ";" << tab << *nodeIter << " [label=\""
456  << *nodeIter << " - " << currentNode->nodeVar()->name() << "\"]"
457  << ";" << std::endl;
458 
459  // if (arcMap_[*nodeIter] != NULL)
461  for (Idx sonIter = 0; sonIter < currentNode->nbSons(); ++sonIter) {
465  }
466 
467  for (auto sonIter = sonMap.beginSafe(); sonIter != sonMap.endSafe(); ++sonIter) {
468  arcstream << tab << *nodeIter << " -> " << sonIter.key() << " [label=\" ";
469  Link< Idx >* modaIter = sonIter.val()->list();
470  while (modaIter) {
471  arcstream << currentNode->nodeVar()->label(modaIter->element()) << ", ";
473  }
474  arcstream << "\",color=\"#0000ff\"]"
475  << ";" << std::endl;
476  delete sonIter.val();
477  }
478 
479  if (withBackArcs) {
481  while (parentIter != nullptr) {
482  arcstream << tab << *nodeIter << " -> " << parentIter->element().parentId
483  << " [label=\"" << parentIter->element().modality << "\",color=\"#ff0000\"]"
484  << ";" << std::endl;
486  }
487  }
488  }
489  }
490 
491  output << terminalStream.str() << std::endl
492  << nonTerminalStream.str() << std::endl
493  << arcstream.str() << std::endl
494  << "}" << std::endl;
495 
496  return output.str();
497  }
498 
499  // Returns a const reference to the manager of this diagram
500  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
501  INLINE const NodeGraphPart&
503  return _model_;
504  }
505 
506  // Returns a const reference to the manager of this diagram
507  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
510  if (_manager_ == nullptr) {
511  if (_isReduced_)
513  else
515  }
516  return _manager_;
517  }
518 
519  // Returns the id of the root node from the diagram
520  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
522  return _root_;
523  }
524 
525  // Indicates if given node is terminal or not
526  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
528  const NodeId& node) const {
529  return this->existsTerminalNodeWithId(node);
530  }
531 
532  // Indicates if given node is terminal or not
533  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
535  const NodeId& node) const {
536  return this->_internalNodeMap_.exists(node);
537  }
538 
539  // Returns value associated to given node.
540  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
541  INLINE const GUM_SCALAR&
543  if (!isTerminalNode(n))
544  GUM_ERROR(InvalidArgument, "Id " << n << " is not bound to any terminal node")
545  return this->terminalNodeValue(n);
546  }
547 
548  // Returns internalNode structure associated to that nodeId
549  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
550  INLINE const InternalNode*
552  if (!isInternalNode(n))
553  GUM_ERROR(InvalidArgument, "Id " << n << " is not bound to any terminal node")
554  return this->_internalNodeMap_[n];
555  }
556 
557  // Returns the list of node associated to given variable
558  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
559  INLINE const LinkedList< NodeId >*
561  const DiscreteVariable* var) const {
562  if (!this->variablesSequence().exists(var))
564  "Var " << var->name() << " has not been inserted in the function graph")
565  return _var2NodeIdMap_[var];
566  }
567 
568  // Returns the name of the table represented by this structure.
569  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
570  INLINE const std::string&
572  return _tableName_;
573  }
574 
575  // Sets the name of the table represented by this structure.
576  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
578  const std::string& name) {
579  _tableName_ = name;
580  }
581 
582  // Returns true if this MultiDimFunctionGraph is reduced and Ordered.
583  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
585  return _isReduced_;
586  }
587 
588  // Returns a reduced and ordered instance.
589  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
593  }
594 
595  // Returns an arborescent instance
596  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
600  }
601 
602  // Not implemented yet
603  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
604  INLINE void
606  const DiscreteVariable* y) {
607  GUM_ERROR(OperationNotAllowed, "Not Implemented Yet")
608  }
609 
610  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
612  const Instantiation& inst) const {
613  GUM_ERROR(OperationNotAllowed, "You can't edit a function by other mean than the manager")
614  }
615 
616  // Return a data, given a Instantiation.
617  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
621  InternalNode* currentNode = nullptr;
622  while (!isTerminalNode(currentNodeId)) {
625  }
626  return this->terminalNodeValue(currentNodeId);
627  }
628 
629 } // namespace gum
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643