aGrUM  0.21.0
a C++ library for (probabilistic) graphical models
influenceDiagram.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 Class representing Influence Diagrams
25  *
26  * @author Pierre-Henri WUILLEMIN(@LIP6) and Jean-Christophe MAGNAN and Christophe
27  * GONZALES(@AMU)
28  *
29  */
30 
31 #ifndef GUM_INF_DIAG_H
32 #define GUM_INF_DIAG_H
33 
34 #include <string>
35 #include <utility>
36 
37 #include <agrum/agrum.h>
38 
39 #include <agrum/tools/core/hashTable.h>
40 #include <agrum/tools/graphicalModels/DAGmodel.h>
41 #include <agrum/tools/multidim/potential.h>
42 
43 namespace gum {
44 
45  /**
46  * @class InfluenceDiagram
47  * @headerfile influenceDiagram.h <agrum/ID/influenceDiagram.h>
48  * @brief Class representing an Influence Diagram
49  * @ingroup InfluenceDiagram_group
50  *
51  */
52  template < typename GUM_SCALAR >
53  class InfluenceDiagram: public DAGmodel {
54  // friend class InfluenceDiagramFactory<GUM_SCALAR>;
55  public:
56  /**
57  * Create an Influence Diagram with a dot-like syntax which specifies:
58  * - the structure "a->*b->$c;b->d<-*e;".
59  * - the prefix of a variable can be :
60  * - nothing : chance node (a,d)
61  * - * : decision node (*b)
62  * - $ : utility node ($c) *
63  * - the type of the chance or decision variables with different syntax:
64  * + by default, a variable is a gum::RangeVariable using the default
65  * domainSize (second argument)
66  * + with "a[10]", the variable is a gum::RangeVariable using 10 as
67  * domainSize (from 0 to 9)
68  * + with "a[3,7]", the variable is a gum::RangeVariable using a domainSize
69  * from 3 to 7
70  * + with "a[1,3.14,5,6.2]", the variable is a gum::DiscretizedVariable
71  * using the given ticks (at least 3 values)
72  * + with "a{top|middle|bottom}", the variable is a gum::LabelizedVariable
73  * using the given labels.
74  *
75  * Note that if the dot-like string contains such a specification more than
76  * once for a variable, the first specification will be used.
77  *
78  * @param dotlike the string containing the specification
79  * @param domainSize the default domain size for chance and decision variables
80  * @return the resulting influence diagram
81  */
82  static InfluenceDiagram< GUM_SCALAR > fastPrototype(const std::string& dotlike,
83  Size domainSize = 2);
84 
85  // ===========================================================================
86  /// @name Constructors / Destructors
87  // ===========================================================================
88  /// @{
89 
90  /**
91  * Default constructor.
92  */
94 
95  /**
96  * Destructor.
97  */
99 
100  /**
101  * Copy Constructor
102  */
103  InfluenceDiagram(const InfluenceDiagram< GUM_SCALAR >& source);
104 
105  /**
106  * Copy Operator
107  */
108  InfluenceDiagram< GUM_SCALAR >& operator=(const InfluenceDiagram< GUM_SCALAR >& source);
109 
110  /// @}
111 
112  /// @return Returns a dot representation of this Influence Diagram.
113  std::string toDot() const;
114 
115  /// @return Returns a string representation of this Influence Diagram.
116  std::string toString() const;
117 
118  void clear();
119 
120  // ===========================================================================
121  /// @name Variable manipulation methods.
122  // ===========================================================================
123  /// @{
124 
125  /**
126  * Returns the CPT of a potential variable.
127  * @throw NotFound If no variable's id matches varId.
128  */
129  virtual const Potential< GUM_SCALAR >& cpt(NodeId varId) const;
130  virtual const Potential< GUM_SCALAR >& cpt(std::string name) const final {
131  return cpt(idFromName(name));
132  };
133 
134  /**
135  * Returns the utility table of a utility node.
136  * @throw NotFound If no variable's id matches varId.
137  */
138  virtual const Potential< GUM_SCALAR >& utility(NodeId varId) const;
139  virtual const Potential< GUM_SCALAR >& utility(std::string name) const final {
140  return utility(idFromName(name));
141  };
142 
143  /**
144  * Returns a constant reference to the VariableNodeMap of this Influence
145  * Diagram
146  */
147  const VariableNodeMap& variableNodeMap() const final;
148 
149  /**
150  * Returns true if node is a utility one
151  */
152  bool isUtilityNode(NodeId varId) const;
153  bool isUtilityNode(const std::string& name) const { return isUtilityNode(idFromName(name)); };
154  /**
155  * Returns true if node is a decision one
156  */
157  bool isDecisionNode(NodeId varId) const;
158  bool isDecisionNode(const std::string& name) const { return isDecisionNode(idFromName(name)); };
159 
160  /**
161  * Returns true if node is a chance one
162  */
163  bool isChanceNode(NodeId varId) const;
164  bool isChanceNode(const std::string& name) const { return isChanceNode(idFromName(name)); };
165  /**
166  * Returns the number of utility nodes
167  */
168  Size utilityNodeSize() const;
169 
170  /**
171  * Returns the number of chance nodes
172  */
173  Size chanceNodeSize() const;
174 
175  /**
176  * Returns the number of decision nodes
177  */
178  Size decisionNodeSize() const;
179 
180  /**
181  * Returns a constant reference over a variable given it's node id.
182  * @throw NotFound If no variable's id matches varId.
183  */
184  const DiscreteVariable& variable(NodeId id) const final;
185  const DiscreteVariable& variable(const std::string& name) const {
186  return variable(idFromName(name));
187  };
188 
189  /**
190  * Return id node from discrete var pointer.
191  * @throw NotFound If no variable matches var.
192  */
193  NodeId nodeId(const DiscreteVariable& var) const final;
194 
195  /// Getter by name
196  /// @throw NotFound if no such name exists in the graph.
197  NodeId idFromName(const std::string& name) const final;
198 
199  /// Getter by name
200  /// @throw NotFound if no such name exists in the graph.
201  const DiscreteVariable& variableFromName(const std::string& name) const final;
202 
203  /**
204  * Add a chance variable, it's associate node and it's CPT. The id of the
205  *new
206  * variable is automatically generated.
207  *
208  * The implementation of the Potential is by default a MultiDimArray.
209  *
210  * @param variable The variable added by copy.
211  * @param id The chosen id. If 0, the NodeGraphPart will choose.
212  * @warning give an id (not 0) should be reserved for rare and specific
213  *situations !!!
214  * @return the id of the added variable.
215  * @throws DuplicateElement if id(<>0) is already used
216  */
218 
219  /**
220  * Add a chance variable, it's associate node and it's CPT. The id of the new
221  * variable is automatically generated.
222  *
223  * The implementation of the Potential is by default a MultiDimArray.
224  *
225  * @param variable The variable added by copy.
226  * @param id The chosen id. If 0, the NodeGraphPart will choose.
227  * @warning give an id (not 0) should be reserved for rare and specific
228  *situations
229  *!!!
230  * @return the id of the added variable.
231  * @throws DuplicateElement if id(<>0) is already used
232  */
234 
235  /**
236  * Add a utility variable, it's associate node and it's UT. The id of the
237  *new variable is automatically generated.
238  *
239  * The implementation of the Utility is by default a MultiDimArray.
240  *
241  * @param variable The variable added by copy.
242  * @param id The chosen id. If 0, the NodeGraphPart will choose.
243  * @warning give an id (not 0) should be reserved for rare and specific
244  *situations !!!
245  * @return the id of the added variable.
246  * @throw InvalidArgument If variable has more than one label
247  * @throws DuplicateElement if id(<>0) is already used
248  */
250 
251  /**
252  * Add a decision variable. The id of the new
253  * variable is automatically generated.
254  *
255  * @param variable The variable added by copy.
256  * @param id The chosen id. If 0, the NodeGraphPart will choose.
257  * @warning give an id (not 0) should be reserved for rare and specific
258  *situations !!!
259  * @return the id of the added variable.
260  * @throws DuplicateElement if id(<>0) is already used
261  */
263 
264  /**
265  * Add a chance variable, it's associate node and it's CPT. The id of the
266  *new
267  * variable is automatically generated.
268  *
269  * @param variable The variable added by copy.
270  * @param aContent The content used for the variable potential.
271  * @param id The chosen id. If 0, the NodeGraphPart will choose.
272  * @warning give an id (not 0) should be reserved for rare and specific
273  *situations !!!
274  * @return the id of the added variable.
275  * @throws DuplicateElement if id(<>0) is already used
276  */
279  NodeId id = 0);
280 
281  /**
282  * Add a chance variable, it's associate node and it's CPT. The id of the
283  *new
284  * variable is automatically generated.
285  *
286  * @param variable The variable added by copy.
287  * @param aContent The content used for the variable utility.
288  * @param id The chosen id. If 0, the NodeGraphPart will choose.
289  * @warning give an id (not 0) should be reserved for rare and specific
290  *situations !!!
291  * @throw InvalidArgument If variable has more than one label
292  * @throws DuplicateElement if id(<>0) is already used
293  */
296  NodeId id = 0);
297 
298  /**
299  * Erase a Variable from the network and remove the variable from
300  * all his children.
301  * If no variable matches the id, then nothing is done.
302  *
303  * @param id The id of the variable to erase.
304  */
305  void erase(NodeId id);
306  void erase(const std::string& name) { erase(idFromName(name)); };
307 
308  /**
309  * Erase a Variable from the network and remove the variable from
310  * all his children.
311  * If no variable matches, then nothing is done.
312  *
313  * @param var The reference on the variable to remove.
314  */
315  void erase(const DiscreteVariable& var);
316 
317  /** we allow the user to change the name of a variable
318  * @throws DuplicateLabel if this name already exists
319  * @throws NotFound Raised if no nodes matches id.
320  */
321  void changeVariableName(NodeId id, const std::string& new_name);
322  void changeVariableName(const std::string& name, const std::string& new_name) {
323  changeVariableName(idFromName(name), new_name);
324  }
325 
326  /// @}
327  // ===========================================================================
328  /// @name Arc manipulation methods.
329  // ===========================================================================
330  /// @{
331 
332  /**
333  * Add an arc in the ID, and update diagram's potential nodes cpt if
334  *necessary.
335  *
336  * @param head and
337  * @param tail as NodeId
338  * @throw InvalidEdge If arc.tail and/or arc.head are not in the ID.
339  * @throw InvalidEdge if tail is a utility node
340  */
341  void addArc(NodeId tail, NodeId head);
342  void addArc(const std::string& tail, const std::string& head) {
343  addArc(idFromName(tail), idFromName(head));
344  }
345 
346  /**
347  * Removes an arc in the ID, and update diagram's potential nodes cpt if
348  *necessary.
349  *
350  * If (tail, head) doesn't exist, the nothing happens.
351  * @param arc The arc removed.
352  */
353  void eraseArc(const Arc& arc);
354 
355  /**
356  * Removes an arc in the ID, and update diagram's potential nodes cpt if
357  *necessary.
358  *
359  * If (tail, head) doesn't exist, the nothing happens.
360  * @param head and
361  * @param tail as NodeId
362  */
363  void eraseArc(NodeId tail, NodeId head);
364  void eraseArc(const std::string& tail, const std::string& head) {
365  eraseArc(idFromName(tail), idFromName(head));
366  }
367 
368  /// @}
369 
370  // ===========================================================================
371  /// @name Decisions methods
372  // ===========================================================================
373  /// @{
374 
375  /**
376  * True if a directed path exist with all decision nodes
377  */
378  bool decisionOrderExists() const;
379 
380  /**
381  * Returns the temporal Graph
382  */
383  gum::DAG* getDecisionGraph() const;
384 
385  /**
386  * Returns the sequence of decision nodes in the directed path
387  * @throw NotFound if such a path does not exist
388  */
389  std::vector< NodeId > decisionOrder() const;
390 
391  /**
392  * Returns true if a path exists between two nodes
393  */
394  bool existsPathBetween(NodeId src, NodeId dest) const;
395  bool existsPathBetween(const std::string& src, const std::string& dest) const {
396  return existsPathBetween(idFromName(src), idFromName(dest));
397  }
398 
399  /**
400  * Returns partial temporal ordering
401  * @throw NotFound if such a sequence does not exist
402  */
403  const List< NodeSet >& getPartialTemporalOrder(bool clear = true) const;
404 
405  /// @}
406 
407  protected:
408  /// Returns the moral graph of this InfluenceDiagram.
409  virtual void moralGraph_(UndiGraph& graph) const;
410 
411  /**
412  * Removing ancient table
413  */
414  void removeTables_();
415 
416  /**
417  * Copying tables from another influence diagram
418  */
419  void copyStructureAndTables_(const InfluenceDiagram< GUM_SCALAR >& IDsource);
420 
421  /**
422  * Add a node
423  */
425 
426  /**
427  * Returns the list of children decision for a given nodeId
428  */
430 
431  private:
432  /// Mapping between id and variable
434 
435  /// Mapping between potential variable's id and their CPT
437  /// Mapping between utility variable's id and their utility table
439 
440  /// The temporal order
442  };
443 
444 } /* namespace gum */
445 
446 #include <agrum/ID/influenceDiagram_tpl.h>
447 
448 #endif /* GUM_INF_DIAG_H */
static InfluenceDiagram< GUM_SCALAR > fastPrototype(const std::string &dotlike, Size domainSize=2)
Create an Influence Diagram with a dot-like syntax which specifies:
void addArc(NodeId tail, NodeId head)
Add an arc in the ID, and update diagram&#39;s potential nodes cpt if necessary.
NodeId idFromName(const std::string &name) const final
Getter by name.
bool isChanceNode(NodeId varId) const
Returns true if node is a chance one.
void erase(NodeId id)
Erase a Variable from the network and remove the variable from all his children.
NodeId addChanceNode(const DiscreteVariable &variable, NodeId id=0)
Add a chance variable, it&#39;s associate node and it&#39;s CPT.
bool existsPathBetween(NodeId src, NodeId dest) const
Returns true if a path exists between two nodes.
std::string toString() const
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643
const DiscreteVariable & variable(const std::string &name) const
Returns the CPT of a potential variable.
NodeId nodeId(const DiscreteVariable &var) const final
Return id node from discrete var pointer.
gum::DAG * getDecisionGraph() const
Returns the temporal Graph.
void removeTables_()
Removing ancient table.
bool existsPathBetween(const std::string &src, const std::string &dest) const
True if a directed path exist with all decision nodes.
NodeId addChanceNode(const DiscreteVariable &variable, MultiDimImplementation< GUM_SCALAR > *aContent, NodeId id=0)
Add a chance variable, it&#39;s associate node and it&#39;s CPT.
std::vector< NodeId > decisionOrder() const
Returns the sequence of decision nodes in the directed path.
Size decisionNodeSize() const
Returns the number of decision nodes.
virtual const Potential< GUM_SCALAR > & utility(NodeId varId) const
Returns the utility table of a utility node.
void changeVariableName(NodeId id, const std::string &new_name)
we allow the user to change the name of a variable
Size chanceNodeSize() const
Returns the number of chance nodes.
Size utilityNodeSize() const
Returns the number of utility nodes.
bool isChanceNode(const std::string &name) const
Returns the CPT of a potential variable.
void addArc(const std::string &tail, const std::string &head)
Add an arc in the ID, and update diagram&#39;s potential nodes cpt if necessary.
const DiscreteVariable & variableFromName(const std::string &name) const final
Getter by name.
virtual const Potential< GUM_SCALAR > & utility(std::string name) const final
Returns the CPT of a potential variable.
std::string toDot() const
void eraseArc(NodeId tail, NodeId head)
Removes an arc in the ID, and update diagram&#39;s potential nodes cpt if necessary.
const List< NodeSet > & getPartialTemporalOrder(bool clear=true) const
Returns partial temporal ordering.
NodeProperty< Potential< GUM_SCALAR > *> _utilityMap_
Mapping between utility variable&#39;s id and their utility table.
bool isDecisionNode(NodeId varId) const
Returns true if node is a decision one.
List< NodeSet > _temporalOrder_
The temporal order.
bool isUtilityNode(NodeId varId) const
Returns true if node is a utility one.
VariableNodeMap _variableMap_
Mapping between id and variable.
NodeId addNode_(const DiscreteVariable &variableType, NodeId DesiredId)
Add a node.
void changeVariableName(const std::string &name, const std::string &new_name)
Returns the CPT of a potential variable.
NodeId addUtilityNode(const DiscreteVariable &variable, MultiDimImplementation< GUM_SCALAR > *aContent, NodeId id=0)
Add a chance variable, it&#39;s associate node and it&#39;s CPT.
void eraseArc(const std::string &tail, const std::string &head)
Add an arc in the ID, and update diagram&#39;s potential nodes cpt if necessary.
bool decisionOrderExists() const
True if a directed path exist with all decision nodes.
Sequence< NodeId > getChildrenDecision_(NodeId parentDecision) const
Returns the list of children decision for a given nodeId.
void erase(const std::string &name)
Returns the CPT of a potential variable.
InfluenceDiagram< GUM_SCALAR > & operator=(const InfluenceDiagram< GUM_SCALAR > &source)
Copy Operator.
void copyStructureAndTables_(const InfluenceDiagram< GUM_SCALAR > &IDsource)
Copying tables from another influence diagram.
virtual void moralGraph_(UndiGraph &graph) const
Returns the moral graph of this InfluenceDiagram.
void erase(const DiscreteVariable &var)
Erase a Variable from the network and remove the variable from all his children.
void eraseArc(const Arc &arc)
Removes an arc in the ID, and update diagram&#39;s potential nodes cpt if necessary.
bool isUtilityNode(const std::string &name) const
Returns the CPT of a potential variable.
NodeId addUtilityNode(const DiscreteVariable &variable, NodeId id=0)
Add a utility variable, it&#39;s associate node and it&#39;s UT.
InfluenceDiagram()
Default constructor.
NodeId add(const DiscreteVariable &variable, NodeId id=0)
Add a chance variable, it&#39;s associate node and it&#39;s CPT.
InfluenceDiagram(const InfluenceDiagram< GUM_SCALAR > &source)
Copy Constructor.
virtual const Potential< GUM_SCALAR > & cpt(std::string name) const final
Returns the CPT of a potential variable.
NodeId addDecisionNode(const DiscreteVariable &variable, NodeId id=0)
Add a decision variable.
~InfluenceDiagram() override
Destructor.
const DiscreteVariable & variable(NodeId id) const final
Returns a constant reference over a variable given it&#39;s node id.
const VariableNodeMap & variableNodeMap() const final
Returns a constant reference to the VariableNodeMap of this Influence Diagram.
virtual const Potential< GUM_SCALAR > & cpt(NodeId varId) const
Returns the CPT of a potential variable.
bool isDecisionNode(const std::string &name) const
Returns the CPT of a potential variable.