void OrientedGraph::permute(const Permutation& a) /* This function permutes the graph according to the permutation a, according to the usual rule : the edges of a(x) should be the image under a of the edge set of x. As usual, permuting values is easy : it is enough to apply a to the elements in the various edgelists. Permuting ranges is trickier, because it involves a^-1. It is assumed of course that a holds a permutation of size size(). */ { static BitMap b(0); static EdgeList e_buf(0); /* permute values */ for (SetElt x = 0; x < size(); ++x) { EdgeList& e = d_edge[x]; for (Ulong j = 0; j < e.size(); ++j) { e[j] = a[e[j]]; } } /* permute ranges */ b.setSize(size()); b.reset(); for (SetElt x = 0; x < size(); ++x) { if (b.getBit(x)) continue; if (a[x] == x) { /* fixed point */ b.setBit(x); continue; } for (SetElt y = a[x]; y != x; y = a[y]) { /* back up values for y */ e_buf.shallowCopy(d_edge[y]); /* put values for x in y */ d_edge[y].shallowCopy(d_edge[x]); /* store backup values in x */ d_edge[x].shallowCopy(e_buf); /* set bit */ b.setBit(y); } b.setBit(x); } }
void OrientedGraph::levelPartition(Partition& pi) const /* Assuming the graph has no oriented cycles, this function writes in pi the partition of the vertices according to their level, where sinks have level 0, then sinks in the remaining poset have level one, etc. NOTE : the implementation is simple-minded : we traverse the graph as many times as there are levels. */ { static BitMap b(0); static BitMap b1(0); b.setSize(size()); b.reset(); b1.setSize(size()); b1.reset(); pi.setSize(size()); Ulong count = 0; Ulong current_level = 0; while (count < size()) { for (SetElt x = 0; x < size(); ++x) { if (b.getBit(x)) continue; const EdgeList e = d_edge[x]; for (Ulong j = 0; j < e.size(); ++j) { if (!b.getBit(e[j])) /* next x */ goto nextx; } /* i we get here, x is the next element in the permutation */ pi[x] = current_level; b1.setBit(x); ++count; nextx: continue; } b.assign(b1); current_level++; } pi.setClassCount(current_level); return; }