aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
DAGCycleDetector_inl.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 A class for detecting directed cycles in DAGs when trying to apply
24  * many changes to the graph
25  *
26  * @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
27  */
28 
29 namespace gum {
30 
31  /* ===========================================================================
32  */
33  // CHANGES
34  /* ===========================================================================
35  */
36 
37  // default constructor
39  NodeId tail,
40  NodeId head) noexcept :
41  type__{type},
42  tail__{tail}, head__{head} {
44  }
45 
46  // copy constructor
47  INLINE
51  }
52 
53  // move constructor
54  INLINE
58  }
59 
60  // destructor
63  }
64 
65  // copy operator
67  const DAGCycleDetector::Change& from) noexcept {
68  type__ = from.type__;
69  tail__ = from.tail__;
70  head__ = from.head__;
71  return *this;
72  }
73 
74  // move operator
76  DAGCycleDetector::Change&& from) noexcept {
77  type__ = from.type__;
78  tail__ = from.tail__;
79  head__ = from.head__;
80  return *this;
81  }
82 
83  /// returns the type of the operation
85  DAGCycleDetector::Change::type() const noexcept {
86  return type__;
87  }
88 
89  /// indicates the tail of the arc involved in the modification
90  INLINE NodeId DAGCycleDetector::Change::tail() const noexcept { return tail__; }
91 
92  /// indicates the head of the arc involved in the modification
93  INLINE NodeId DAGCycleDetector::Change::head() const noexcept { return head__; }
94 
95  /* ===========================================================================
96  */
97  // ArcAdd
98  /* ===========================================================================
99  */
100 
101  /// default constructor
104  tail,
105  head) {
107  }
108 
109  /// copy constructor
110  INLINE
114  }
115 
116  /// move constructor
117  INLINE
120  std::move(from.tail()),
121  std::move(from.head())) {
123  }
124 
125  /// destructor
128  }
129 
130  /// copy operator
132  const DAGCycleDetector::ArcAdd& from) noexcept {
134  return *this;
135  }
136 
137  /// move operator
139  DAGCycleDetector::ArcAdd&& from) noexcept {
141  return *this;
142  }
143 
144  /* ===========================================================================
145  */
146  // ArcDel
147  /* ===========================================================================
148  */
149 
150  /// default constructor
153  tail,
154  head) {
156  }
157 
158  /// copy constructor
159  INLINE
163  }
164 
165  /// move constructor
166  INLINE
169  std::move(from.tail()),
170  std::move(from.head())) {
172  }
173 
174  /// destructor
177  }
178 
179  /// copy operator
181  const DAGCycleDetector::ArcDel& from) noexcept {
183  return *this;
184  }
185 
186  /// move operator
188  DAGCycleDetector::ArcDel&& from) noexcept {
190  return *this;
191  }
192 
193  /* ===========================================================================
194  */
195  // ArcReverse
196  /* ===========================================================================
197  */
198 
199  /// default constructor
201  NodeId head) noexcept :
203  tail,
204  head) {
206  }
207 
208  /// copy constructor
210  const DAGCycleDetector::ArcReverse& from) noexcept :
213  }
214 
215  /// move constructor
217  DAGCycleDetector::ArcReverse&& from) noexcept :
219  std::move(from.tail()),
220  std::move(from.head())) {
222  }
223 
224  /// destructor
227  }
228 
229  /// copy operator
231  const DAGCycleDetector::ArcReverse& from) noexcept {
233  return *this;
234  }
235 
236  /// move operator
238  DAGCycleDetector::ArcReverse&& from) noexcept {
240  return *this;
241  }
242 
243  /* ===========================================================================
244  */
245  // DAGCycleDetector
246  /* ===========================================================================
247  */
248 
249  /// default constructor
252  }
253 
254  /// copy constructor
259  }
260 
261  /// move constructor
266  }
267 
268  /// destructor
271  }
272 
273  /// copy operator
276  if (this != &from) {
277  dag__ = from.dag__;
280  }
281 
282  return *this;
283  }
284 
285  /// move operator
287  if (this != &from) {
288  dag__ = std::move(from.dag__);
291  }
292 
293  return *this;
294  }
295 
296  /// indicates whether an arc addition would create a cycle
298  NodeId y) const noexcept {
299  return descendants__[y].exists(x);
300  }
301 
302  /// indicates wether an arc reversal would create a cycle
304  NodeId y) const noexcept {
305  return (ancestors__[y][x] > 1);
306  }
307 
308  /// indicates whether an arc deletion would create a cycle
310  NodeId y) const noexcept {
311  return false;
312  }
313 
314  /// adds a nodeset to another (nodes are weighted, so weights are added)
315  INLINE
317  const NodeProperty< Size >& set_to_add,
318  Size multiplier) const {
319  for (auto iter = set_to_add.cbegin(); iter != set_to_add.cend(); ++iter) {
320  if (nodeset.exists(iter.key())) {
321  nodeset[iter.key()] += iter.val() * multiplier;
322  } else {
324  }
325  }
326  }
327 
328  /// removes a weighted nodeset from another (weights are subtracted)
329  INLINE
331  const NodeProperty< Size >& set_to_del,
332  Size multiplier) const {
333  for (auto iter = set_to_del.cbegin(); iter != set_to_del.cend(); ++iter) {
334  if (nodeset.exists(iter.key())) {
335  Size& weight = nodeset[iter.key()];
336  weight -= iter.val() * multiplier;
337 
338  if (!weight) { nodeset.erase(iter.key()); }
339  }
340  }
341  }
342 
343  /** @brief put into a weighted nodeset the nodes of another weighted set that
344  * belong to a set of arc extremities */
345  INLINE
349  const NodeSet& extremities) const {
350  for (auto iter = set_to_restrict.cbegin(); iter != set_to_restrict.cend();
351  ++iter) {
352  if (extremities.exists(iter.key())) {
354  }
355  }
356  }
357 
358  /// reverses an arc from the DAG
362  "the arc would create a directed into a DAG");
363  }
364 
365  eraseArc(tail, head);
366  addArc(head, tail);
367  }
368 
369  /// check the equality between two DAGCycleDetectors
371  return ( //( dagmodel__ == from.dagmodel__ ) &&
373  }
374 
375  /// check the inequality between two DAGCycleDetectors
377  return !operator==(from);
378  }
379 
380 } /* namespace gum */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669