aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
schedule.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 Class containing a schedule of operations to perform on multidims
24  *
25  * @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
26  */
27 #ifndef GUM_SCHEDULE_H
28 #define GUM_SCHEDULE_H
29 
30 #include <utility>
31 
32 #include <agrum/agrum.h>
33 
34 #include <agrum/tools/core/hashTable.h>
35 #include <agrum/tools/core/set.h>
36 #include <agrum/tools/graphs/DAG.h>
37 #include <agrum/tools/graphs/graphElements.h>
38 
39 #include <agrum/tools/graphicalModels/inference/scheduler/scheduleCliqueStoreMultiDim.h>
40 #include <agrum/tools/graphicalModels/inference/scheduler/scheduleCombine.h>
41 #include <agrum/tools/graphicalModels/inference/scheduler/scheduleDeleteMultiDim.h>
42 #include <agrum/tools/graphicalModels/inference/scheduler/scheduleOperation.h>
43 #include <agrum/tools/graphicalModels/inference/scheduler/scheduleProject.h>
44 #include <agrum/tools/graphicalModels/inference/scheduler/scheduleSeparatorStoreMultiDim.h>
45 
46 namespace gum {
47 
48  /**
49  * @class Schedule
50  * @brief Class containing a schedule of operations to perform on multidims
51  *
52  * A Schedule class contains a set of operations to be scheduled. It is able
53  *to
54  * indicate which operations can currently be performed (because all their
55  * arguments have already been computed). In addition, it is possible to
56  *insert
57  * new operations into the schedule (at a specific place) and to remove some
58  * operations.
59  *
60  * @warning In the Schedule class does not guarantee that the schedule can
61  *always
62  * be performed, i.e., that there always exists a sequence in which all the
63  * operations of the schedule can be performed. It is up to the user to check
64  * this (function schedulePossible () may help here).
65  */
66  template < typename GUM_SCALAR >
67  class Schedule {
68  public:
69  /// to identify correctly the ids that correspond to ScheduleOperation ids
70  using OperationId = Idx;
71 
72  /// to identify correctly the ids that correspond to ScheduleMultiDim ids
73  using MultiDimId = Idx;
74 
75  // ############################################################################
76  /// @name Constructors / Destructors
77  // ############################################################################
78  /// @{
79 
80  /// default constructor (construct an empty sequence)
81  Schedule();
82 
83  /// copy constructor
84  Schedule(const Schedule< GUM_SCALAR >&);
85 
86  /// destructor
87  ~Schedule();
88 
89  /// @}
90 
91  // ############################################################################
92  /// @name Operators
93  // ############################################################################
94 
95  /// @{
96 
97  /// copy operator
98  Schedule< GUM_SCALAR >& operator=(const Schedule< GUM_SCALAR >&);
99 
100  /// @}
101 
102  // ############################################################################
103  /// @name Accessors/Modifiers
104  // ############################################################################
105  /// @{
106 
107  /// inserts an operation to be scheduled
108  /** The Schedule class is able to determined by itself when the operation
109  * should be performed.
110  * @warning operations are inserted by copy */
112 
113  /** @brief adds a constraint indicating that an operation cannot be
114  * performed
115  * before another one */
116  void forceAfter(const ScheduleOperation< GUM_SCALAR >& op_to_force,
117  const ScheduleOperation< GUM_SCALAR >& op_before);
118  void forceAfter(NodeId op_to_force, NodeId op_before);
119 
120  /** @brief adds a constraint indicating that an operation cannot be
121  * performed
122  * before a set of operations */
123  void
124  forceAfter(const ScheduleOperation< GUM_SCALAR >& op_to_force,
125  const Set< const ScheduleOperation< GUM_SCALAR >* >& ops_before);
126  void forceAfter(NodeId op_to_force, const NodeSet& ops_before);
127 
128  /** @brief adds a constraint indicating that an operation must be performed
129  * before another one */
130  void forceBefore(const ScheduleOperation< GUM_SCALAR >& op_to_force,
131  const ScheduleOperation< GUM_SCALAR >& op_after);
132  void forceBefore(NodeId op_to_force, NodeId op_after);
133 
134  /** @brief adds a constraint indicating that an operation must be performed
135  * before a set of operations */
136  void
137  forceBefore(const ScheduleOperation< GUM_SCALAR >& op_to_force,
138  const Set< const ScheduleOperation< GUM_SCALAR >* >& ops_after);
139  void forceBefore(NodeId op_to_force, const NodeSet& ops_after);
140 
141  /// returns a DAG indicating in which order the operations can be performed
142  /** In this DAG, each node corresponds to an operation and an operation
143  * can be performed only if its ancestors have all been performed. */
144  const DAG& scheduling_dag() const;
145 
146  /// returns the scheduleOperation corresponding to an id in the DAG
147  /** @throws NotFound exception is raised if the DAG does not contain the id
148  */
149  const ScheduleOperation< GUM_SCALAR >& operation(NodeId) const;
150 
151  /// returns the id of the node corresponding to a given ScheduleOperation
152  /** @throws NotFound exception is raised the operation does not belong to
153  * the Schedule */
154  NodeId nodeId(const ScheduleOperation< GUM_SCALAR >&) const;
155 
156  /// resturns the association between operations anf nodeIds
157  const NodeProperty< const ScheduleOperation< GUM_SCALAR >* >&
158  operations() const;
159 
160  /// returns the set of operations involving a given multidim table
161  const NodeSet&
164 
165  /// returns the set of ScheduleOperations that can be executed at once
166  /** The scheduleOperations that can be executed at once are those that
167  have no parent or whose parents have already been executed. */
168  const NodeSet& availableOperations() const;
169 
170  /// executes a given operation (if this one is available)
171  /** Note that, whenever an operation is performed, the list of available
172  * operations is updated and the operation itslef is removed from the
173  * schedule
174  * @throws OperationNotAllowed exception is thrown if the operation cannot
175  * be
176  * executed yet because some of its arguments have not already been computed
177  * @throws NotFound exception is thrown if the operation cannot be found */
178  void execute(NodeId);
179  void execute(const ScheduleOperation< GUM_SCALAR >&);
180 
181  /** @brief returns an estimation of the number of elementary operations
182  * needed
183  * to perform a given ScheduleOperation */
184  float nbOperations(NodeId) const;
185  float nbOperations(ScheduleOperation< GUM_SCALAR >&) const;
186 
187  /// returns the memory consumption used during the execution of an operation
188  /** Actually, this function does not return a precise account of the memory
189  * used by the scheduleOperation but a rough estimate based on the sizes
190  * of the tables involved in the operation.
191  * @return a pair of memory consumption: the first one is the maximum
192  * amount of memory used during the ScheduleOperation and the second one is
193  * the
194  * amount of memory still used at the end of the operation ( the memory used
195  * by
196  * the resulting table ) */
197  std::pair< long, long > memoryUsage(NodeId) const;
198  std::pair< long, long > memoryUsage(ScheduleOperation< GUM_SCALAR >&) const;
199 
200  /// @}
201 
202  private:
203  /// the DAG of the operations to perform
204  /** Operations can be scheduled as a DAG: nodes without parents can be
205  * executed directly. The other nodes need their parents to be executed to
206  * get all their arguments constructed. */
207  mutable DAG dag__;
208 
209  /// a hashtable assigning to each node of the DAG an operation
211 
212  /// a hashtable assigning to each operation id a node id in the DAG
214 
215  /** @brief a hashtable assigning to each ScheduleMultiDim resulting from a
216  * computation the MultiDimOperation node id that created it */
218 
219  /// a list of operations whose parents are not properly set
220  /** when entering operations to be performed in a "wrong" order, it may
221  * happen that the parents of some operations in the DAG are not properly
222  * set (the parents being inserted after the child). We keep a list of
223  * such nodes and, whenever we wish to perform the schedule or get its DAG,
224  * we compute the correct set of parents of the operations of this list
225  * and, when this is done, we remove them from the list. As such, when the
226  * list is empty, the schedule can be performed. */
228 
229  /// the set of operations that can be executed at once
231 
232  /// for each multidim, store the set of operations involving it
234 
235  /** @brief updates the set of parents for the nodes whoses parents are not
236  * correct yet and update accordingly the available operations */
237  void updateWrongParents__() const;
238  };
239 
240 } /* namespace gum */
241 
242 // always include the template implementation
243 #include <agrum/tools/graphicalModels/inference/scheduler/schedule_tpl.h>
244 
245 #endif /* GUM_SCHEDULE_H */
float nbOperations(ScheduleOperation< GUM_SCALAR > &) const
inserts an operation to be scheduled
void forceBefore(NodeId op_to_force, const NodeSet &ops_after)
inserts an operation to be scheduled
void execute(NodeId)
executes a given operation (if this one is available)
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669
void execute(const ScheduleOperation< GUM_SCALAR > &)
inserts an operation to be scheduled
void forceAfter(NodeId op_to_force, NodeId op_before)
inserts an operation to be scheduled
NodeId nodeId(const ScheduleOperation< GUM_SCALAR > &) const
returns the id of the node corresponding to a given ScheduleOperation
Schedule(const Schedule< GUM_SCALAR > &)
copy constructor
NodeProperty< ScheduleOperation< GUM_SCALAR > *> node2operation__
a hashtable assigning to each node of the DAG an operation
Definition: schedule.h:210
std::pair< long, long > memoryUsage(ScheduleOperation< GUM_SCALAR > &) const
inserts an operation to be scheduled
void forceAfter(const ScheduleOperation< GUM_SCALAR > &op_to_force, const Set< const ScheduleOperation< GUM_SCALAR > * > &ops_before)
adds a constraint indicating that an operation cannot be performed before a set of operations ...
NodeId insert(const ScheduleOperation< GUM_SCALAR > &)
inserts an operation to be scheduled
const NodeSet & operationsInvolving(const ScheduleMultiDim< GUM_SCALAR > &table) const
returns the set of operations involving a given multidim table
const DAG & scheduling_dag() const
returns a DAG indicating in which order the operations can be performed
const NodeSet & availableOperations() const
returns the set of ScheduleOperations that can be executed at once
~Schedule()
destructor
Schedule< GUM_SCALAR > & operator=(const Schedule< GUM_SCALAR > &)
copy operator
HashTable< OperationId, NodeId > operation2node__
a hashtable assigning to each operation id a node id in the DAG
Definition: schedule.h:213
std::pair< long, long > memoryUsage(NodeId) const
returns the memory consumption used during the execution of an operation
const NodeSet & operationsInvolving(MultiDimId table_id) const
inserts an operation to be scheduled
HashTable< MultiDimId, NodeSet *> multidim2operations__
for each multidim, store the set of operations involving it
Definition: schedule.h:233
NodeSet operations_available__
the set of operations that can be executed at once
Definition: schedule.h:230
const ScheduleOperation< GUM_SCALAR > & operation(NodeId) const
returns the scheduleOperation corresponding to an id in the DAG
Schedule()
default constructor (construct an empty sequence)
void forceBefore(const ScheduleOperation< GUM_SCALAR > &op_to_force, const Set< const ScheduleOperation< GUM_SCALAR > * > &ops_after)
adds a constraint indicating that an operation must be performed before a set of operations ...
HashTable< MultiDimId, NodeId > created_multidims__
a hashtable assigning to each ScheduleMultiDim resulting from a computation the MultiDimOperation nod...
Definition: schedule.h:217
DAG dag__
the DAG of the operations to perform
Definition: schedule.h:207
void forceAfter(NodeId op_to_force, const NodeSet &ops_before)
inserts an operation to be scheduled
void forceBefore(NodeId op_to_force, NodeId op_after)
inserts an operation to be scheduled
void updateWrongParents__() const
updates the set of parents for the nodes whoses parents are not correct yet and update accordingly th...
float nbOperations(NodeId) const
returns an estimation of the number of elementary operations needed to perform a given ScheduleOperat...
const NodeProperty< const ScheduleOperation< GUM_SCALAR > *> & operations() const
resturns the association between operations anf nodeIds
NodeSet operations_with_wrong_parents__
a list of operations whose parents are not properly set
Definition: schedule.h:227