aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
influenceDiagram.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright 2005-2020 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 >&
109  operator=(const InfluenceDiagram< GUM_SCALAR >& source);
110 
111  /// @}
112 
113  /// @return Returns a dot representation of this Influence Diagram.
114  std::string toDot() const;
115 
116  /// @return Returns a string representation of this Influence Diagram.
117  std::string toString() const;
118 
119  void clear();
120 
121  // ===========================================================================
122  /// @name Variable manipulation methods.
123  // ===========================================================================
124  /// @{
125 
126  /**
127  * Returns the CPT of a potential variable.
128  * @throw NotFound If no variable's id matches varId.
129  */
130  virtual const Potential< GUM_SCALAR >& cpt(NodeId varId) const;
131  virtual const Potential< GUM_SCALAR >& cpt(std::string name) const final {
132  return cpt(idFromName(name));
133  };
134 
135  /**
136  * Returns the utility table of a utility node.
137  * @throw NotFound If no variable's id matches varId.
138  */
139  virtual const Potential< GUM_SCALAR >& utility(NodeId varId) const;
140  virtual const Potential< GUM_SCALAR >& utility(std::string name) const final {
141  return utility(idFromName(name));
142  };
143 
144  /**
145  * Returns a constant reference to the VariableNodeMap of this Influence
146  * Diagram
147  */
148  const VariableNodeMap& variableNodeMap() const final;
149 
150  /**
151  * Returns true if node is a utility one
152  */
153  bool isUtilityNode(NodeId varId) const;
154  bool isUtilityNode(const std::string& name) const {
155  return isUtilityNode(idFromName(name));
156  };
157  /**
158  * Returns true if node is a decision one
159  */
160  bool isDecisionNode(NodeId varId) const;
161  bool isDecisionNode(const std::string& name) const {
162  return isDecisionNode(idFromName(name));
163  };
164 
165  /**
166  * Returns true if node is a chance one
167  */
168  bool isChanceNode(NodeId varId) const;
169  bool isChanceNode(const std::string& name) const {
170  return isChanceNode(idFromName(name));
171  };
172  /**
173  * Returns the number of utility nodes
174  */
175  Size utilityNodeSize() const;
176 
177  /**
178  * Returns the number of chance nodes
179  */
180  Size chanceNodeSize() const;
181 
182  /**
183  * Returns the number of decision nodes
184  */
185  Size decisionNodeSize() const;
186 
187  /**
188  * Returns a constant reference over a variable given it's node id.
189  * @throw NotFound If no variable's id matches varId.
190  */
191  const DiscreteVariable& variable(NodeId id) const final;
192 
193  /**
194  * Return id node from discrete var pointer.
195  * @throw NotFound If no variable matches var.
196  */
197  NodeId nodeId(const DiscreteVariable& var) const final;
198 
199  /// Getter by name
200  /// @throw NotFound if no such name exists in the graph.
201  NodeId idFromName(const std::string& name) const final;
202 
203  /// Getter by name
204  /// @throw NotFound if no such name exists in the graph.
205  const DiscreteVariable& variableFromName(const std::string& name) const final;
206 
207  /**
208  * Add a chance variable, it's associate node and it's CPT. The id of the
209  *new
210  * variable is automatically generated.
211  *
212  * The implementation of the Potential is by default a MultiDimArray.
213  *
214  * @param variable The variable added by copy.
215  * @param id The chosen id. If 0, the NodeGraphPart will choose.
216  * @warning give an id (not 0) should be reserved for rare and specific
217  *situations !!!
218  * @return the id of the added variable.
219  * @throws DuplicateElement if id(<>0) is already used
220  */
222 
223  /**
224  * Add a chance variable, it's associate node and it's CPT. The id of the new
225  * variable is automatically generated.
226  *
227  * The implementation of the Potential is by default a MultiDimArray.
228  *
229  * @param variable The variable added by copy.
230  * @param id The chosen id. If 0, the NodeGraphPart will choose.
231  * @warning give an id (not 0) should be reserved for rare and specific
232  *situations
233  *!!!
234  * @return the id of the added variable.
235  * @throws DuplicateElement if id(<>0) is already used
236  */
238 
239  /**
240  * Add a utility variable, it's associate node and it's UT. The id of the
241  *new variable is automatically generated.
242  *
243  * The implementation of the Utility is by default a MultiDimArray.
244  *
245  * @param variable The variable added by copy.
246  * @param id The chosen id. If 0, the NodeGraphPart will choose.
247  * @warning give an id (not 0) should be reserved for rare and specific
248  *situations !!!
249  * @return the id of the added variable.
250  * @throw InvalidArgument If variable has more than one label
251  * @throws DuplicateElement if id(<>0) is already used
252  */
254 
255  /**
256  * Add a decision variable. The id of the new
257  * variable is automatically generated.
258  *
259  * @param variable The variable added by copy.
260  * @param id The chosen id. If 0, the NodeGraphPart will choose.
261  * @warning give an id (not 0) should be reserved for rare and specific
262  *situations !!!
263  * @return the id of the added variable.
264  * @throws DuplicateElement if id(<>0) is already used
265  */
267 
268  /**
269  * Add a chance variable, it's associate node and it's CPT. The id of the
270  *new
271  * variable is automatically generated.
272  *
273  * @param variable The variable added by copy.
274  * @param aContent The content used for the variable potential.
275  * @param id The chosen id. If 0, the NodeGraphPart will choose.
276  * @warning give an id (not 0) should be reserved for rare and specific
277  *situations !!!
278  * @return the id of the added variable.
279  * @throws DuplicateElement if id(<>0) is already used
280  */
283  NodeId id = 0);
284 
285  /**
286  * Add a chance variable, it's associate node and it's CPT. The id of the
287  *new
288  * variable is automatically generated.
289  *
290  * @param variable The variable added by copy.
291  * @param aContent The content used for the variable utility.
292  * @param id The chosen id. If 0, the NodeGraphPart will choose.
293  * @warning give an id (not 0) should be reserved for rare and specific
294  *situations !!!
295  * @throw InvalidArgument If variable has more than one label
296  * @throws DuplicateElement if id(<>0) is already used
297  */
300  NodeId id = 0);
301 
302  /**
303  * Erase a Variable from the network and remove the variable from
304  * all his children.
305  * If no variable matches the id, then nothing is done.
306  *
307  * @param id The id of the variable to erase.
308  */
309  void erase(NodeId id);
310  void erase(const std::string& name) { erase(idFromName(name)); };
311 
312  /**
313  * Erase a Variable from the network and remove the variable from
314  * all his children.
315  * If no variable matches, then nothing is done.
316  *
317  * @param var The reference on the variable to remove.
318  */
319  void erase(const DiscreteVariable& var);
320 
321  /** we allow the user to change the name of a variable
322  * @throws DuplicateLabel if this name already exists
323  * @throws NotFound Raised if no nodes matches id.
324  */
325  void changeVariableName(NodeId id, const std::string& new_name);
326  void changeVariableName(const std::string& name, const std::string& new_name) {
327  changeVariableName(idFromName(name), new_name);
328  }
329 
330  /// @}
331  // ===========================================================================
332  /// @name Arc manipulation methods.
333  // ===========================================================================
334  /// @{
335 
336  /**
337  * Add an arc in the ID, and update diagram's potential nodes cpt if
338  *necessary.
339  *
340  * @param head and
341  * @param tail as NodeId
342  * @throw InvalidEdge If arc.tail and/or arc.head are not in the ID.
343  * @throw InvalidEdge if tail is a utility node
344  */
345  void addArc(NodeId tail, NodeId head);
346  void addArc(const std::string& tail, const std::string& head) {
347  addArc(idFromName(tail), idFromName(head));
348  }
349 
350  /**
351  * Removes an arc in the ID, and update diagram's potential nodes cpt if
352  *necessary.
353  *
354  * If (tail, head) doesn't exist, the nothing happens.
355  * @param arc The arc removed.
356  */
357  void eraseArc(const Arc& arc);
358 
359  /**
360  * Removes an arc in the ID, and update diagram's potential nodes cpt if
361  *necessary.
362  *
363  * If (tail, head) doesn't exist, the nothing happens.
364  * @param head and
365  * @param tail as NodeId
366  */
367  void eraseArc(NodeId tail, NodeId head);
368  void eraseArc(const std::string& tail, const std::string& head) {
369  eraseArc(idFromName(tail), idFromName(head));
370  }
371 
372  /// @}
373 
374  // ===========================================================================
375  /// @name Decisions methods
376  // ===========================================================================
377  /// @{
378 
379  /**
380  * True if a directed path exist with all decision nodes
381  */
382  bool decisionOrderExists() const;
383 
384  /**
385  * Returns the temporal Graph
386  */
387  gum::DAG* getDecisionGraph() const;
388 
389  /**
390  * Returns the sequence of decision nodes in the directed path
391  * @throw NotFound if such a path does not exist
392  */
393  std::vector< NodeId > decisionOrder() const;
394 
395  /**
396  * Returns true if a path exists between two nodes
397  */
398  bool existsPathBetween(NodeId src, NodeId dest) const;
399  bool existsPathBetween(const std::string& src, const std::string& dest) const {
400  return existsPathBetween(idFromName(src), idFromName(dest));
401  }
402 
403  /**
404  * Returns partial temporal ordering
405  * @throw NotFound if such a sequence does not exist
406  */
407  const List< NodeSet >& getPartialTemporalOrder(bool clear = true) const;
408 
409  /// @}
410 
411  protected:
412  /// Returns the moral graph of this InfluenceDiagram.
413  virtual void moralGraph_(UndiGraph& graph) const;
414 
415  /**
416  * Removing ancient table
417  */
418  void removeTables_();
419 
420  /**
421  * Copying tables from another influence diagram
422  */
423  void copyStructureAndTables_(const InfluenceDiagram< GUM_SCALAR >& IDsource);
424 
425  /**
426  * Add a node
427  */
429 
430  /**
431  * Returns the list of children decision for a given nodeId
432  */
434 
435  private:
436  /// Mapping between id and variable
438 
439  /// Mapping between potential variable's id and their CPT
441  /// Mapping between utility variable's id and their utility table
443 
444  /// The temporal order
446  };
447 
448 } /* namespace gum */
449 
450 #include <agrum/ID/influenceDiagram_tpl.h>
451 
452 #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:669
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.
VariableNodeMap variableMap__
Mapping between id and variable.
bool isDecisionNode(NodeId varId) const
Returns true if node is a decision one.
bool isUtilityNode(NodeId varId) const
Returns true if node is a utility one.
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.
List< NodeSet > temporalOrder__
The temporal order.
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.
NodeProperty< Potential< GUM_SCALAR > *> utilityMap__
Mapping between utility variable&#39;s id and their utility table.