aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
graphChangesSelector4DiGraph.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 /** @file
23  * @brief The mecanism to compute the next available graph changes for directed
24  * structure learning search algorithms.
25  *
26  * @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
27  */
28 #ifndef GUM_LEARNING_GRAPH_CHANGES_SELECTOR_4_DIGRAPH_H
29 #define GUM_LEARNING_GRAPH_CHANGES_SELECTOR_4_DIGRAPH_H
30 
31 #include <vector>
32 
33 #include <agrum/agrum.h>
34 #include <agrum/tools/core/priorityQueue.h>
35 #include <agrum/tools/core/sequence.h>
36 #include <agrum/tools/core/set.h>
37 #include <agrum/tools/graphs/diGraph.h>
38 #include <agrum/BN/learning/scores_and_tests/score.h>
39 #include <agrum/BN/learning/structureUtils/graphChange.h>
40 
41 namespace gum {
42 
43  namespace learning {
44 
45  /** @class GraphChangesSelector4DiGraph
46  * @brief The mecanism to compute the next available graph changes for
47  * directed structure learning search algorithms.
48  * @ingroup learning_group
49  */
50  template < typename STRUCTURAL_CONSTRAINT,
51  typename GRAPH_CHANGES_GENERATOR,
52  template < typename > class ALLOC = std::allocator >
54  public:
55  /// the type of the generator
56  using GeneratorType = GRAPH_CHANGES_GENERATOR;
57 
58  // ##########################################################################
59  /// @name Constructors / Destructors
60  // ##########################################################################
61  /// @{
62 
63  /// default constructor
64  GraphChangesSelector4DiGraph(Score< ALLOC >& score,
65  STRUCTURAL_CONSTRAINT& constraint,
66  GRAPH_CHANGES_GENERATOR& changes_generator);
67 
68  /// copy constructor
69  GraphChangesSelector4DiGraph(const GraphChangesSelector4DiGraph< STRUCTURAL_CONSTRAINT,
70  GRAPH_CHANGES_GENERATOR,
71  ALLOC >& from);
72 
73  /// move constructor
75  GraphChangesSelector4DiGraph< STRUCTURAL_CONSTRAINT, GRAPH_CHANGES_GENERATOR, ALLOC >&&
76  from);
77 
78  /// destructor
80 
81  /// @}
82 
83  // ##########################################################################
84  /// @name Operators
85  // ##########################################################################
86  /// @{
87 
88  /// copy operator
92  ALLOC >& from);
93 
94  /// move operator
96  operator=(
98  from);
99 
100  /// @}
101 
102  // ##########################################################################
103  /// @name Accessors / Modifiers
104  // ##########################################################################
105  /// @{
106 
107  /// returns the generator used by the selector
108  GeneratorType& graphChangeGenerator() const noexcept;
109 
110  /// indicates whether the selector still contains graph changes
111  bool empty();
112 
113  /** @brief indicates whether the selector contains graph changes related
114  * to
115  * the ith node */
116  bool empty(const NodeId i);
117 
118  /// returns the best graph change to examine
119  /** @throws NotFound exception is thrown if the selector is empty */
120  const GraphChange& bestChange();
121 
122  /// returns the best graph change to examine related to the ith node
123  /** The selector computes not only the best change possible but also the
124  * best changes impacting the parents' set of each node. This method
125  * allows to get the change that is considered the best for modifying the
126  * parents' set of the ith node.
127  * @throws NotFound exception is thrown if the selector is empty */
128  const GraphChange& bestChange(const NodeId i);
129 
130  /// return the score of the best graph change
131  /** @throws NotFound exception is thrown if the selector is empty */
132  double bestScore();
133 
134  /// return the score of the best graph change related to the ith node
135  /** The selector computes not only the best change possible but also the
136  * best changes impacting the parents' set of each node. This method
137  * allows to get the score of the change that is considered the best for
138  * modifying the parents' set of the ith node.
139  * @throws NotFound exception is thrown if the selector is empty */
140  double bestScore(const NodeId i);
141 
142  /// indicate to the selector that a change has been applied
143  void applyChange(const GraphChange& change);
144 
145  /// indicate to the selector that one of serveral changes has been applied
146  /** This function is to be used rather than applyChange when we wish to
147  * apply several changes at a time. It is faster than applyChange because
148  * it does not recomputes the scores. Then, after applying all changes,
149  * we shall compute the scores with function
150  * updateScoresAfterAppliedChanges (). See class GreedyHillClimbing for
151  * an illustration of the use of this method. */
152  void applyChangeWithoutScoreUpdate(const GraphChange& change);
153 
154  /// recompute all the scores after the application of several changes
155  /** This method needs COMPULSORILY be used after applications of
156  * applyChangeWithoutScoreUpdate in order to ensure the fact that
157  * functions bestScore and bestChange return correct answers. See class
158  * GreedyHillClimbing for an illustration of the use of this method. */
160 
161  /// indicates whether a given change is valid or not
162  bool isChangeValid(const GraphChange& change) const;
163 
164  /// sets the graph from which scores are computed
165  void setGraph(DiGraph& graph);
166 
167  /// returns the set of queues sorted by decreasing top priority
168  std::vector< std::pair< NodeId, double > > nodesSortedByBestScore() const;
169 
170  /// returns the set of queues top priorities
171  std::vector< std::pair< NodeId, double > > nodesUnsortedWithScore() const;
172 
173  /// @}
174 
175  private:
176  /// the scoring function
178 
179  /// the set of constraints used to determine valid changes
180  STRUCTURAL_CONSTRAINT* _constraint_;
181 
182  /// the generator that returns the set of possible changes
183  GRAPH_CHANGES_GENERATOR* _changes_generator_;
184 
185  /// a sequence containing all the possible changes
187 
188  /// the scores for the head and tail of all the changes
189  /** the scores are indexed by their index in sequence _changes_ */
190  std::vector< std::pair< double, double > > _change_scores_;
191 
192  /// for each node, a priority queue sorting GraphChanges by decreasing score
193  /** within each queue, the changes are determined by their index in
194  * sequence _changes_. */
195  NodeProperty< PriorityQueue< std::size_t, double, std::greater< double > > >
197 
198  /// a global priority queue indicating for each node its best score
199  PriorityQueue< NodeId, double, std::greater< double > > _node_queue_;
200 
201  /// the set of changes known to be currently illegal (due to the constraints)
202  /** within each queue, the changes are determined by their index in
203  * sequence _changes_. */
205 
206  /// the current score of each node
208 
209  /// the set of parents of each node (speeds-up score computations)
211 
212  /// indicates whether we need to recompute whether the queue is empty or not
213  bool _queues_valid_{false};
214 
215  /// the set of queues to update when applying several changes
217 
218  /// indicates whether a given change is valid or not
219  bool _isChangeValid_(const std::size_t index) const;
220 
221  /// put a change into the illegal set
222  void _invalidateChange_(const std::size_t change_index);
223 
224  /// remove the now legal changes from the illegal set
225  void _illegal2LegalChanges_(Set< std::size_t >& changes_to_recompute);
226 
227  /// finds the changes that are affected by a given node modification
228  void _findLegalChangesNeedingUpdate_(Set< std::size_t >& changes_to_recompute,
229  const NodeId target_node);
230 
231  /// perform the necessary updates of the scores
232  void _updateScores_(const Set< std::size_t >& changes_to_recompute);
233 
234  /// get from the graph change generator a new set of changes
235  void _getNewChanges_();
236  };
237 
238  } /* namespace learning */
239 
240 } /* namespace gum */
241 
242 /// always include templated methods
243 #include <agrum/BN/learning/structureUtils/graphChangesSelector4DiGraph_tpl.h>
244 
245 #endif /* GUM_LEARNING_GRAPH_CHANGES_SELECTOR_4_DIGRAPH_H */
void _invalidateChange_(const std::size_t change_index)
put a change into the illegal set
void _illegal2LegalChanges_(Set< std::size_t > &changes_to_recompute)
remove the now legal changes from the illegal set
bool empty()
indicates whether the selector still contains graph changes
Set< NodeId > _queues_to_update_
the set of queues to update when applying several changes
GeneratorType & graphChangeGenerator() const noexcept
returns the generator used by the selector
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643
bool _queues_valid_
indicates whether we need to recompute whether the queue is empty or not
GraphChangesSelector4DiGraph< STRUCTURAL_CONSTRAINT, GRAPH_CHANGES_GENERATOR, ALLOC > & operator=(const GraphChangesSelector4DiGraph< STRUCTURAL_CONSTRAINT, GRAPH_CHANGES_GENERATOR, ALLOC > &from)
copy operator
const GraphChange & bestChange()
returns the best graph change to examine
NodeProperty< double > _node_current_scores_
the current score of each node
void applyChange(const GraphChange &change)
indicate to the selector that a change has been applied
void _getNewChanges_()
get from the graph change generator a new set of changes
std::vector< std::pair< double, double > > _change_scores_
the scores for the head and tail of all the changes
void _findLegalChangesNeedingUpdate_(Set< std::size_t > &changes_to_recompute, const NodeId target_node)
finds the changes that are affected by a given node modification
Sequence< GraphChange > _changes_
a sequence containing all the possible changes
GraphChangesSelector4DiGraph< STRUCTURAL_CONSTRAINT, GRAPH_CHANGES_GENERATOR, ALLOC > & operator=(GraphChangesSelector4DiGraph< STRUCTURAL_CONSTRAINT, GRAPH_CHANGES_GENERATOR, ALLOC > &&from)
move operator
GRAPH_CHANGES_GENERATOR * _changes_generator_
the generator that returns the set of possible changes
void _updateScores_(const Set< std::size_t > &changes_to_recompute)
perform the necessary updates of the scores
void applyChangeWithoutScoreUpdate(const GraphChange &change)
indicate to the selector that one of serveral changes has been applied
NodeProperty< std::vector< NodeId, ALLOC< NodeId > > > _parents_
the set of parents of each node (speeds-up score computations)
const GraphChange & bestChange(const NodeId i)
returns the best graph change to examine related to the ith node
bool _isChangeValid_(const std::size_t index) const
indicates whether a given change is valid or not
double bestScore()
return the score of the best graph change
bool empty(const NodeId i)
indicates whether the selector contains graph changes related to the ith node
Set< std::size_t > _illegal_changes_
the set of changes known to be currently illegal (due to the constraints)
GraphChangesSelector4DiGraph(GraphChangesSelector4DiGraph< STRUCTURAL_CONSTRAINT, GRAPH_CHANGES_GENERATOR, ALLOC > &&from)
move constructor
GraphChangesSelector4DiGraph(Score< ALLOC > &score, STRUCTURAL_CONSTRAINT &constraint, GRAPH_CHANGES_GENERATOR &changes_generator)
default constructor
void updateScoresAfterAppliedChanges()
recompute all the scores after the application of several changes
std::vector< std::pair< NodeId, double > > nodesUnsortedWithScore() const
returns the set of queues top priorities
std::vector< std::pair< NodeId, double > > nodesSortedByBestScore() const
returns the set of queues sorted by decreasing top priority
STRUCTURAL_CONSTRAINT * _constraint_
the set of constraints used to determine valid changes
void setGraph(DiGraph &graph)
sets the graph from which scores are computed
Database(const std::string &filename, const BayesNet< GUM_SCALAR > &bn, const std::vector< std::string > &missing_symbols)
GraphChangesSelector4DiGraph(const GraphChangesSelector4DiGraph< STRUCTURAL_CONSTRAINT, GRAPH_CHANGES_GENERATOR, ALLOC > &from)
copy constructor
double bestScore(const NodeId i)
return the score of the best graph change related to the ith node
bool isChangeValid(const GraphChange &change) const
indicates whether a given change is valid or not