73 for (
const auto node: dag) {
75 nb_children.
insert(node, nb_ch);
77 if (!nb_ch) leaves.
insert(node);
80 nb_parents.
insert(node, nb_pa);
82 if (!nb_pa) roots.
insert(node);
93 while (!roots.
empty()) {
97 node_ancestors.
insert(node, 1);
101 for (
const auto ch: node_children) {
105 if (!nb_parents[ch]) { roots.
insert(ch); }
112 for (
const auto node: dag) {
116 while (!leaves.
empty()) {
120 node_descendants.
insert(node, 1);
124 for (
const auto pa: node_parents) {
128 if (!nb_children[pa]) { leaves.
insert(pa); }
142 for (
const auto& modif: modifs) {
143 Arc arc(modif.tail(), modif.head());
145 switch (modif.type()) {
147 if (deletions.
exists(arc)) ++deletions[arc];
148 else deletions.
insert(arc, 1);
153 if (modif.tail() == modif.head())
return true;
155 if (additions.
exists(arc)) ++additions[arc];
156 else additions.
insert(arc, 1);
161 if (deletions.
exists(arc)) ++deletions[arc];
162 else deletions.
insert(arc, 1);
164 arc =
Arc(modif.head(), modif.tail());
166 if (additions.
exists(arc)) ++additions[arc];
167 else additions.
insert(arc, 1);
178 if (deletions.
exists(iter.key())) {
179 Size& nb_del = deletions[iter.key()];
180 Size& nb_add = iter.val();
182 if (nb_del > nb_add) {
183 additions.
erase(iter);
185 }
else if (nb_del < nb_add) {
186 deletions.
erase(iter.key());
189 deletions.
erase(iter.key());
190 additions.
erase(iter);
198 for (
const auto& modif: modifs) {
199 extremities.
insert(modif.tail());
200 extremities.
insert(modif.head());
208 for (
const auto& modif: modifs) {
209 if (!ancestors.
exists(modif.tail())) {
218 if (!ancestors.
exists(modif.head())) {
239 for (
auto iter = deletions.
cbegin(); iter != deletions.
cend(); ++iter) {
240 const Arc& arc = iter.key();
248 set_to_del.
insert(head, 1);
251 for (
auto iter = anc_tail.
cbegin(); iter != anc_tail.
cend(); ++iter) {
252 _delWeightedSet_(descendants[iter.key()], set_to_del, descendants[iter.key()][tail]);
256 set_to_del = anc_tail;
257 set_to_del.
insert(tail, 1);
260 for (
auto iter = desc_head.
cbegin(); iter != desc_head.
cend(); ++iter) {
261 _delWeightedSet_(ancestors[iter.key()], set_to_del, ancestors[iter.key()][head]);
276 for (
auto iter = additions.
cbegin(); iter != additions.
cend(); ++iter) {
277 const Arc& arc = iter.key();
283 if (anc_tail.
exists(head)) {
return true; }
289 set_to_add.
insert(tail, 1);
292 for (
auto iter = desc_head.
cbegin(); iter != desc_head.
cend(); ++iter) {
293 _addWeightedSet_(ancestors[iter.key()], set_to_add, ancestors[iter.key()][head]);
297 set_to_add = desc_head;
298 set_to_add.
insert(head, 1);
301 for (
auto iter = anc_tail.
cbegin(); iter != anc_tail.
cend(); ++iter) {
302 _addWeightedSet_(descendants[iter.key()], set_to_add, descendants[iter.key()][tail]);
312 if (
_dag_.existsArc(tail, head))
return;
319 _dag_.addArc(tail, head);
328 set_to_add.
insert(tail, 1);
331 for (
auto iter = desc_head.
cbegin(); iter != desc_head.
cend(); ++iter) {
336 set_to_add = desc_head;
337 set_to_add.
insert(head, 1);
340 for (
auto iter = anc_tail.
cbegin(); iter != anc_tail.
cend(); ++iter) {
348 if (!
_dag_.existsArc(tail, head))
return;
359 set_to_del.
insert(head, 1);
362 for (
auto iter = anc_tail.
cbegin(); iter != anc_tail.
cend(); ++iter) {
367 set_to_del = anc_tail;
368 set_to_del.
insert(tail, 1);
371 for (
auto iter = desc_head.
cbegin(); iter != desc_head.
cend(); ++iter) {
A class for detecting directed cycles in DAGs when trying to apply many changes to the graph.
A class for detecting directed cycles in DAGs when trying to apply many changes to the graph.
const NodeSet & parents(NodeId id) const
returns the set of nodes with arc ingoing to a given node
NodeSet children(const NodeSet &ids) const
returns the set of children of a set of nodes
The base class for all directed edges.
GUM_NODISCARD NodeId head() const
returns the head of the arc
GUM_NODISCARD NodeId tail() const
returns the tail of the arc
bool hasCycleFromModifications(const std::vector< Change > &modifs) const
indicates whether a set of modifications would create a cycle
NodeProperty< NodeProperty< Size > > _descendants_
the set of descendants of each node in the dag
void _addWeightedSet_(NodeProperty< Size > &nodeset, const NodeProperty< Size > &set_to_add, Size multiplier) const
adds a weighted nodeset to another (weights are added)
void addArc(NodeId x, NodeId y)
adds a new arc to the current DAG
void setDAG(const DAG &dag)
sets the initial DAG from which changes shall be applied
NodeProperty< NodeProperty< Size > > _ancestors_
the set of ancestors of each node in the dag
void _delWeightedSet_(NodeProperty< Size > &nodeset, const NodeProperty< Size > &set_to_del, Size multiplier) const
removes a weighted nodeset from another (weights are subtracted)
void eraseArc(NodeId x, NodeId y)
removes an arc from the current DAG
DiGraph _dag_
the initial dag from which modifications are applied
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
bool hasCycleFromAddition(NodeId x, NodeId y) const noexcept
indicates whether an arc addition would create a cycle
The class for generic Hash Tables.
const iterator_safe & endSafe() noexcept
Returns the safe iterator pointing to the end of the hashtable.
void erase(const Key &key)
Removes a given element from the hash table.
bool exists(const Key &key) const
Checks whether there exists an element with a given key in the hashtable.
const_iterator cbegin() const
Returns an unsafe const_iterator pointing to the beginning of the hashtable.
const const_iterator & cend() const noexcept
Returns the unsafe const_iterator pointing to the end of the hashtable.
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
iterator_safe beginSafe()
Returns the safe iterator pointing to the beginning of the hashtable.
Exception : existence of a directed cycle in a graph.
Generic doubly linked lists.
Val & front() const
Returns a reference to first element of a list, if any.
bool empty() const noexcept
Returns a boolean indicating whether the chained list is empty.
void popFront()
Removes the first element of a List, if any.
Val & insert(const Val &val)
Inserts a new element at the end of the chained list (alias of pushBack).
Exception : operation not allowed.
Size size() const noexcept
Returns the number of elements in the set.
void insert(const Key &k)
Inserts a new element into the set.
#define GUM_ERROR(type, msg)
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Size NodeId
Type for node ids.
HashTable< NodeId, VAL > NodeProperty
Property on graph elements.
Set< NodeId > NodeSet
Some typdefs and define for shortcuts ...
gum is the global namespace for all aGrUM entities
Header file of gum::Sequence, a class for storing (ordered) sequences of objects.