aGrUM  0.14.2
DAGCycleDetector_inl.h
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005 by Christophe GONZALES and Pierre-Henri WUILLEMIN *
3  * {prenom.nom}_at_lip6.fr *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19  ***************************************************************************/
27 namespace gum {
28 
29  /* ===========================================================================
30  */
31  // CHANGES
32  /* ===========================================================================
33  */
34 
35  // default constructor
37  NodeId tail,
38  NodeId head) noexcept :
39  __type{type},
40  __tail{tail}, __head{head} {
41  GUM_CONSTRUCTOR(DAGCycleDetector::Change);
42  }
43 
44  // copy constructor
45  INLINE
47  __type{from.__type}, __tail{from.__tail}, __head{from.__head} {
48  GUM_CONS_CPY(DAGCycleDetector::Change);
49  }
50 
51  // move constructor
52  INLINE
54  __type{from.__type}, __tail{from.__tail}, __head{from.__head} {
55  GUM_CONS_MOV(DAGCycleDetector::Change);
56  }
57 
58  // destructor
60  GUM_DESTRUCTOR(DAGCycleDetector::Change);
61  }
62 
63  // copy operator
65  operator=(const DAGCycleDetector::Change& from) noexcept {
66  __type = from.__type;
67  __tail = from.__tail;
68  __head = from.__head;
69  return *this;
70  }
71 
72  // move operator
75  __type = from.__type;
76  __tail = from.__tail;
77  __head = from.__head;
78  return *this;
79  }
80 
83  noexcept {
84  return __type;
85  }
86 
88  INLINE NodeId DAGCycleDetector::Change::tail() const noexcept { return __tail; }
89 
91  INLINE NodeId DAGCycleDetector::Change::head() const noexcept { return __head; }
92 
93  /* ===========================================================================
94  */
95  // ArcAdd
96  /* ===========================================================================
97  */
98 
103  GUM_CONSTRUCTOR(DAGCycleDetector::ArcAdd);
104  }
105 
107  INLINE
109  DAGCycleDetector::Change(from.type(), from.tail(), from.head()) {
110  GUM_CONS_CPY(DAGCycleDetector::ArcAdd);
111  }
112 
114  INLINE
117  std::move(from.type()), std::move(from.tail()), std::move(from.head())) {
118  GUM_CONS_MOV(DAGCycleDetector::ArcAdd);
119  }
120 
123  GUM_DESTRUCTOR(DAGCycleDetector::ArcAdd);
124  }
125 
128  operator=(const DAGCycleDetector::ArcAdd& from) noexcept {
130  return *this;
131  }
132 
136  DAGCycleDetector::Change::operator=(std::move(from));
137  return *this;
138  }
139 
140  /* ===========================================================================
141  */
142  // ArcDel
143  /* ===========================================================================
144  */
145 
150  GUM_CONSTRUCTOR(DAGCycleDetector::ArcDel);
151  }
152 
154  INLINE
156  DAGCycleDetector::Change(from.type(), from.tail(), from.head()) {
157  GUM_CONS_CPY(DAGCycleDetector::ArcDel);
158  }
159 
161  INLINE
164  std::move(from.type()), std::move(from.tail()), std::move(from.head())) {
165  GUM_CONS_MOV(DAGCycleDetector::ArcDel);
166  }
167 
170  GUM_DESTRUCTOR(DAGCycleDetector::ArcDel);
171  }
172 
175  operator=(const DAGCycleDetector::ArcDel& from) noexcept {
177  return *this;
178  }
179 
183  DAGCycleDetector::Change::operator=(std::move(from));
184  return *this;
185  }
186 
187  /* ===========================================================================
188  */
189  // ArcReverse
190  /* ===========================================================================
191  */
192 
195  NodeId head) noexcept :
198  GUM_CONSTRUCTOR(DAGCycleDetector::ArcReverse);
199  }
200 
203  const DAGCycleDetector::ArcReverse& from) noexcept :
204  DAGCycleDetector::Change(from.type(), from.tail(), from.head()) {
205  GUM_CONS_CPY(DAGCycleDetector::ArcReverse);
206  }
207 
210  DAGCycleDetector::ArcReverse&& from) noexcept :
212  std::move(from.type()), std::move(from.tail()), std::move(from.head())) {
213  GUM_CONS_MOV(DAGCycleDetector::ArcReverse);
214  }
215 
218  GUM_DESTRUCTOR(DAGCycleDetector::ArcReverse);
219  }
220 
225  return *this;
226  }
227 
231  DAGCycleDetector::Change::operator=(std::move(from));
232  return *this;
233  }
234 
235  /* ===========================================================================
236  */
237  // DAGCycleDetector
238  /* ===========================================================================
239  */
240 
243  GUM_CONSTRUCTOR(DAGCycleDetector);
244  }
245 
248  __dag(from.__dag), __ancestors(from.__ancestors),
250  GUM_CONS_CPY(DAGCycleDetector);
251  }
252 
255  __dag(std::move(from.__dag)), __ancestors(std::move(from.__ancestors)),
256  __descendants(std::move(from.__descendants)) {
257  GUM_CONS_MOV(DAGCycleDetector);
258  }
259 
262  GUM_DESTRUCTOR(DAGCycleDetector);
263  }
264 
268  if (this != &from) {
269  __dag = from.__dag;
270  __ancestors = from.__ancestors;
272  }
273 
274  return *this;
275  }
276 
279  if (this != &from) {
280  __dag = std::move(from.__dag);
281  __ancestors = std::move(from.__ancestors);
282  __descendants = std::move(from.__descendants);
283  }
284 
285  return *this;
286  }
287 
290  noexcept {
291  return __descendants[y].exists(x);
292  }
293 
296  noexcept {
297  return (__ancestors[y][x] > 1);
298  }
299 
302  noexcept {
303  return false;
304  }
305 
307  INLINE
309  const NodeProperty< Size >& set_to_add,
310  Size multiplier) const {
311  for (auto iter = set_to_add.cbegin(); iter != set_to_add.cend(); ++iter) {
312  if (nodeset.exists(iter.key())) {
313  nodeset[iter.key()] += iter.val() * multiplier;
314  } else {
315  nodeset.insert(iter.key(), iter.val() * multiplier);
316  }
317  }
318  }
319 
321  INLINE
323  const NodeProperty< Size >& set_to_del,
324  Size multiplier) const {
325  for (auto iter = set_to_del.cbegin(); iter != set_to_del.cend(); ++iter) {
326  if (nodeset.exists(iter.key())) {
327  Size& weight = nodeset[iter.key()];
328  weight -= iter.val() * multiplier;
329 
330  if (!weight) { nodeset.erase(iter.key()); }
331  }
332  }
333  }
334 
337  INLINE
339  NodeProperty< Size >& result_set,
340  const NodeProperty< Size >& set_to_restrict,
341  const NodeSet& extremities) const {
342  for (auto iter = set_to_restrict.cbegin(); iter != set_to_restrict.cend();
343  ++iter) {
344  if (extremities.exists(iter.key())) {
345  result_set.insert(iter.key(), iter.val());
346  }
347  }
348  }
349 
351  INLINE void DAGCycleDetector::reverseArc(NodeId tail, NodeId head) {
352  if (hasCycleFromReversal(tail, head)) {
354  "the arc would create a directed into a DAG");
355  }
356 
357  eraseArc(tail, head);
358  addArc(head, tail);
359  }
360 
362  INLINE bool DAGCycleDetector::operator==(const DAGCycleDetector& from) const {
363  return ( //( __dagmodel == from.__dagmodel ) &&
364  (__ancestors == from.__ancestors) && (__descendants == from.__descendants));
365  }
366 
368  INLINE bool DAGCycleDetector::operator!=(const DAGCycleDetector& from) const {
369  return !operator==(from);
370  }
371 
372 } /* namespace gum */
A class for detecting directed cycles in DAGs when trying to apply many changes to the graph...
DiGraph __dag
the initial dag from which modifications are applied
the base class indicating the possible changes
NodeId tail() const noexcept
indicates the tail of the arc involved in the modification
ArcAdd & operator=(const ArcAdd &from) noexcept
copy operator
void erase(const Key &key)
Removes a given element from the hash table.
void eraseArc(NodeId x, NodeId y)
removes an arc from the current DAG
void __addWeightedSet(NodeProperty< Size > &nodeset, const NodeProperty< Size > &set_to_add, Size multiplier) const
adds a weighted nodeset to another (weights are added)
ArcDel(NodeId tail, NodeId head) noexcept
default constructor
STL namespace.
bool exists(const Key &key) const
Checks whether there exists an element with a given key in the hashtable.
void addArc(NodeId x, NodeId y)
adds a new arc to the current DAG
void __delWeightedSet(NodeProperty< Size > &nodeset, const NodeProperty< Size > &set_to_del, Size multiplier) const
removes a weighted nodeset from another (weights are subtracted)
ChangeType type() const noexcept
returns the type of the operation
void __restrictWeightedSet(NodeProperty< Size > &result_set, const NodeProperty< Size > &set_to_restrict, const NodeSet &extrmities) const
put into a weighted nodeset the nodes of another weighted set that belong to a set of arc extremities...
ArcReverse(NodeId tail, NodeId head) noexcept
default constructor
ChangeType __type
the type of modification
the class to indicate that we wish to reverse an arc
gum is the global namespace for all aGrUM entities
Definition: agrum.h:25
Change & operator=(const Change &from) noexcept
The class for generic Hash Tables.
Definition: hashTable.h:676
DAGCycleDetector & operator=(const DAGCycleDetector &from)
copy operator
bool exists(const Key &k) const
Indicates whether a given elements belong to the set.
Definition: set_tpl.h:604
NodeId head() const noexcept
indicates the head of the arc involved in the modification
const const_iterator & cend() const noexcept
Returns the unsafe const_iterator pointing to the end of the hashtable.
the class to indicate that we wish to add a new arc
Change(ChangeType type, NodeId tail, NodeId head) noexcept
const_iterator cbegin() const
Returns an unsafe const_iterator pointing to the beginning of the hashtable.
ArcReverse & operator=(const ArcReverse &from) noexcept
copy operator
NodeId __head
the head of the arc to be modified
bool operator!=(const DAGCycleDetector &from) const
check the inequality between two DAGCycleDetectors
bool hasCycleFromAddition(NodeId x, NodeId y) const noexcept
indicates whether an arc addition would create a cycle
NodeId __tail
the tail of the arc to be modified
NodeProperty< NodeProperty< Size > > __descendants
the set of descendants of each node in the dag
NodeProperty< NodeProperty< Size > > __ancestors
the set of ancestors of each node in the dag
bool hasCycleFromReversal(NodeId x, NodeId y) const noexcept
indicates wether an arc reversal would create a cycle
bool hasCycleFromDeletion(NodeId x, NodeId y) const noexcept
indicates whether an arc deletion would create a cycle
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition: types.h:45
ArcDel & operator=(const ArcDel &from) noexcept
copy operator
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
DAGCycleDetector() noexcept
default constructor
the class to indicate that we wish to remove an arc
bool operator==(const DAGCycleDetector &from) const
check the equality between two DAGCycleDetectors
Size NodeId
Type for node ids.
Definition: graphElements.h:97
ArcAdd(NodeId tail, NodeId head) noexcept
default constructor
#define GUM_ERROR(type, msg)
Definition: exceptions.h:52
void reverseArc(NodeId x, NodeId y)
reverses an arc from the DAG