aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
graphChangesSelector4DiGraph.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 /** @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
70  const GraphChangesSelector4DiGraph< STRUCTURAL_CONSTRAINT,
71  GRAPH_CHANGES_GENERATOR,
72  ALLOC >& from);
73 
74  /// move constructor
76  GraphChangesSelector4DiGraph< STRUCTURAL_CONSTRAINT,
77  GRAPH_CHANGES_GENERATOR,
78  ALLOC >&& from);
79 
80  /// destructor
82 
83  /// @}
84 
85  // ##########################################################################
86  /// @name Operators
87  // ##########################################################################
88  /// @{
89 
90  /// copy operator
93  ALLOC >&
96  ALLOC >& from);
97 
98  /// move operator
101  ALLOC >&
104  ALLOC >&& from);
105 
106  /// @}
107 
108  // ##########################################################################
109  /// @name Accessors / Modifiers
110  // ##########################################################################
111  /// @{
112 
113  /// returns the generator used by the selector
114  GeneratorType& graphChangeGenerator() const noexcept;
115 
116  /// indicates whether the selector still contains graph changes
117  bool empty();
118 
119  /** @brief indicates whether the selector contains graph changes related
120  * to
121  * the ith node */
122  bool empty(const NodeId i);
123 
124  /// returns the best graph change to examine
125  /** @throws NotFound exception is thrown if the selector is empty */
126  const GraphChange& bestChange();
127 
128  /// returns the best graph change to examine related to the ith node
129  /** The selector computes not only the best change possible but also the
130  * best changes impacting the parents' set of each node. This method
131  * allows to get the change that is considered the best for modifying the
132  * parents' set of the ith node.
133  * @throws NotFound exception is thrown if the selector is empty */
134  const GraphChange& bestChange(const NodeId i);
135 
136  /// return the score of the best graph change
137  /** @throws NotFound exception is thrown if the selector is empty */
138  double bestScore();
139 
140  /// return the score of the best graph change related to the ith node
141  /** The selector computes not only the best change possible but also the
142  * best changes impacting the parents' set of each node. This method
143  * allows to get the score of the change that is considered the best for
144  * modifying the parents' set of the ith node.
145  * @throws NotFound exception is thrown if the selector is empty */
146  double bestScore(const NodeId i);
147 
148  /// indicate to the selector that a change has been applied
149  void applyChange(const GraphChange& change);
150 
151  /// indicate to the selector that one of serveral changes has been applied
152  /** This function is to be used rather than applyChange when we wish to
153  * apply several changes at a time. It is faster than applyChange because
154  * it does not recomputes the scores. Then, after applying all changes,
155  * we shall compute the scores with function
156  * updateScoresAfterAppliedChanges (). See class GreedyHillClimbing for
157  * an illustration of the use of this method. */
158  void applyChangeWithoutScoreUpdate(const GraphChange& change);
159 
160  /// recompute all the scores after the application of several changes
161  /** This method needs COMPULSORILY be used after applications of
162  * applyChangeWithoutScoreUpdate in order to ensure the fact that
163  * functions bestScore and bestChange return correct answers. See class
164  * GreedyHillClimbing for an illustration of the use of this method. */
166 
167  /// indicates whether a given change is valid or not
168  bool isChangeValid(const GraphChange& change) const;
169 
170  /// sets the graph from which scores are computed
171  void setGraph(DiGraph& graph);
172 
173  /// returns the set of queues sorted by decreasing top priority
174  std::vector< std::pair< NodeId, double > > nodesSortedByBestScore() const;
175 
176  /// returns the set of queues top priorities
177  std::vector< std::pair< NodeId, double > > nodesUnsortedWithScore() const;
178 
179  /// @}
180 
181  private:
182  /// the scoring function
184 
185  /// the set of constraints used to determine valid changes
186  STRUCTURAL_CONSTRAINT* constraint__;
187 
188  /// the generator that returns the set of possible changes
189  GRAPH_CHANGES_GENERATOR* changes_generator__;
190 
191  /// a sequence containing all the possible changes
193 
194  /// the scores for the head and tail of all the changes
195  /** the scores are indexed by their index in sequence changes__ */
196  std::vector< std::pair< double, double > > change_scores__;
197 
198  /// for each node, a priority queue sorting GraphChanges by decreasing score
199  /** within each queue, the changes are determined by their index in
200  * sequence changes__. */
201  NodeProperty< PriorityQueue< std::size_t, double, std::greater< double > > >
203 
204  /// a global priority queue indicating for each node its best score
205  PriorityQueue< NodeId, double, std::greater< double > > node_queue__;
206 
207  /// the set of changes known to be currently illegal (due to the constraints)
208  /** within each queue, the changes are determined by their index in
209  * sequence changes__. */
211 
212  /// the current score of each node
214 
215  /// the set of parents of each node (speeds-up score computations)
217 
218  /// indicates whether we need to recompute whether the queue is empty or not
219  bool queues_valid__{false};
220 
221  /// the set of queues to update when applying several changes
223 
224  /// indicates whether a given change is valid or not
225  bool isChangeValid__(const std::size_t index) const;
226 
227  /// put a change into the illegal set
228  void invalidateChange__(const std::size_t change_index);
229 
230  /// remove the now legal changes from the illegal set
231  void illegal2LegalChanges__(Set< std::size_t >& changes_to_recompute);
232 
233  /// finds the changes that are affected by a given node modification
234  void
235  findLegalChangesNeedingUpdate__(Set< std::size_t >& changes_to_recompute,
236  const NodeId target_node);
237 
238  /// perform the necessary updates of the scores
239  void updateScores__(const Set< std::size_t >& changes_to_recompute);
240 
241  /// get from the graph change generator a new set of changes
242  void getNewChanges__();
243  };
244 
245  } /* namespace learning */
246 
247 } /* namespace gum */
248 
249 /// always include templated methods
250 #include <agrum/BN/learning/structureUtils/graphChangesSelector4DiGraph_tpl.h>
251 
252 #endif /* GUM_LEARNING_GRAPH_CHANGES_SELECTOR_4_DIGRAPH_H */
bool isChangeValid__(const std::size_t index) const
indicates whether a given change is valid or not
bool empty()
indicates whether the selector still contains graph changes
GeneratorType & graphChangeGenerator() const noexcept
returns the generator used by the selector
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669
NodeProperty< std::vector< NodeId, ALLOC< NodeId > > > parents__
the set of parents of each node (speeds-up score computations)
void updateScores__(const Set< std::size_t > &changes_to_recompute)
perform the necessary updates of the scores
Set< NodeId > queues_to_update__
the set of queues to update when applying several changes
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
void applyChange(const GraphChange &change)
indicate to the selector that a change has been applied
void illegal2LegalChanges__(Set< std::size_t > &changes_to_recompute)
remove the now legal changes from the illegal set
void findLegalChangesNeedingUpdate__(Set< std::size_t > &changes_to_recompute, const NodeId target_node)
finds the changes that are affected by a given node modification
Set< std::size_t > illegal_changes__
the set of changes known to be currently illegal (due to the constraints)
void getNewChanges__()
get from the graph change generator a new set of changes
GraphChangesSelector4DiGraph< STRUCTURAL_CONSTRAINT, GRAPH_CHANGES_GENERATOR, ALLOC > & operator=(GraphChangesSelector4DiGraph< STRUCTURAL_CONSTRAINT, GRAPH_CHANGES_GENERATOR, ALLOC > &&from)
move operator
void applyChangeWithoutScoreUpdate(const GraphChange &change)
indicate to the selector that one of serveral changes has been applied
bool queues_valid__
indicates whether we need to recompute whether the queue is empty or not
STRUCTURAL_CONSTRAINT * constraint__
the set of constraints used to determine valid changes
const GraphChange & bestChange(const NodeId i)
returns the best graph change to examine related to the ith node
GRAPH_CHANGES_GENERATOR * changes_generator__
the generator that returns the set of possible changes
NodeProperty< double > node_current_scores__
the current score of each node
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
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< double, double > > change_scores__
the scores for the head and tail of all the changes
std::vector< std::pair< NodeId, double > > nodesSortedByBestScore() const
returns the set of queues sorted by decreasing top priority
void setGraph(DiGraph &graph)
sets the graph from which scores are computed
Sequence< GraphChange > changes__
a sequence containing all the possible changes
Database(const std::string &filename, const BayesNet< GUM_SCALAR > &bn, const std::vector< std::string > &missing_symbols)
void invalidateChange__(const std::size_t change_index)
put a change into the illegal set
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