6 * $Date: 2012-07-05 16:45:20 +0200 (Do, 05. Jul 2012) $
7 ***************************************************************/
10 * \brief Definition of coffman graham ranking algorithm for Sugiyama
12 * \author Till Schäfer
15 * This file is part of the Open Graph Drawing Framework (OGDF).
19 * See README.txt in the root directory of the OGDF installation for details.
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License
24 * Version 2 or 3 as published by the Free Software Foundation;
25 * see the file LICENSE.txt included in the packaging of this file
29 * This program is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 * GNU General Public License for more details.
35 * You should have received a copy of the GNU General Public
36 * License along with this program; if not, write to the Free
37 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
38 * Boston, MA 02110-1301, USA.
40 * \see http://www.gnu.org/copyleft/gpl.html
41 ***************************************************************/
43 #include <ogdf/layered/CoffmanGrahamRanking.h>
44 #include <ogdf/basic/ModuleOption.h>
45 #include <ogdf/layered/DfsAcyclicSubgraph.h>
46 #include <ogdf/basic/GraphCopy.h>
50 CoffmanGrahamRanking::CoffmanGrahamRanking() : m_w(3)
52 m_subgraph
.set(new DfsAcyclicSubgraph());
56 void CoffmanGrahamRanking::call (const Graph
& G
, NodeArray
<int>& rank
)
61 m_subgraph
.get().callAndReverse(gc
);
62 removeTransitiveEdges(gc
);
64 List
<Tuple2
<node
, int> > ready_nodes
;
65 NodeArray
<int> deg(gc
);
66 NodeArray
<int> pi(gc
);
75 deg
[v
] = edges
.size();
77 ready_nodes
.pushBack(Tuple2
<node
,int>(v
,0));
83 while(!ready_nodes
.empty()) {
84 v
= ready_nodes
.popFrontRet().x1();
89 if ((adj
->theEdge()->source()) == v
) {
90 node u
= adj
->twinNode();
93 insert(u
,ready_nodes
);
100 List
<node
> ready
, waiting
;
104 gc
.outEdges(v
, edges
);
105 deg
[v
] = edges
.size();
107 insert(v
,ready
,pi
); // ready.append(v);
113 for (k
= 1; !ready
.empty(); k
++) {
115 for (i
= 1; i
<= m_w
&& !ready
.empty(); i
++) {
116 node u
= ready
.popFrontRet();
117 rank
[gc
.original(u
)] = k
;
119 gc
.inEdges
<List
<edge
> >(u
, edges
);
120 for (ListIterator
<edge
> it
= edges
.begin(); it
.valid() ; ++it
){
121 if (--deg
[(*it
)->source()] == 0){
122 waiting
.pushBack((*it
)->source());
127 while (!waiting
.empty()) {
128 insert(waiting
.popFrontRet(), ready
, pi
);
134 rank
[v
] = k
- rank
[v
];
141 void CoffmanGrahamRanking::insert (node u
, List
<Tuple2
<node
,int> > &ready_nodes
)
145 for( ListIterator
<Tuple2
<node
,int> > it
= ready_nodes
.rbegin(); it
.valid(); --it
) {
147 int sigma
= (*it
).x2();
150 ready_nodes
.insertAfter(Tuple2
<node
,int>(u
,j
), it
);
154 if (sigma
> j
) continue;
156 const _int_set
&x
= m_s
[u
], &y
= m_s
[v
];
157 int k
= min(x
.length(), y
.length());
159 while (j
< k
&& x
[j
] == y
[j
]) {
164 if (x
.length() < y
.length()) continue;
167 ready_nodes
.insertAfter(Tuple2
<node
,int>(u
,sigma
), it
);
171 if (x
[j
] < y
[j
]) continue;
174 ready_nodes
.insert(Tuple2
<node
,int>(u
,sigma
), it
);
178 ready_nodes
.pushFront(Tuple2
<node
,int>(u
,j
));
182 void CoffmanGrahamRanking::insert (node v
, List
<node
> &ready
, const NodeArray
<int> &pi
)
184 for( ListIterator
<node
> it
= ready
.rbegin(); it
.valid(); --it
) {
185 if (pi
[v
] <= pi
[*it
]) {
186 ready
.insertAfter(v
, it
);
195 void CoffmanGrahamRanking::dfs(node v
)
203 if ((adj
->theEdge()->source()) == v
) {
209 if ((mark
[w
] & 1) == 0) {
216 void CoffmanGrahamRanking::removeTransitiveEdges (Graph
& G
)
222 visited
= new StackPure
<node
>();
225 G
.outEdges
<List
<edge
> >(v
, vout
);
226 /* alternative: iterate over all adjELements (only out Edges)
228 * forall_adj(adj,v) {
229 * if ((adj->theEdge()->source()) == v) ...
231 * In this solution a List is generated, because we iterate three times
232 * over this subset of adjElements
234 for (ListIterator
<edge
> it
= vout
.begin(); it
.valid() ; ++it
){
235 w
= (*it
)-> target();
240 for (ListIterator
<edge
> it
= vout
.begin(); it
.valid() ; ++it
){
241 w
= (*it
)-> target();
244 if ((mark
[w
] & 1) == 0) {
250 for (ListIterator
<edge
> it
= vout
.begin(); it
.valid() ; ++it
){
251 node u
= (*it
)->target();
256 while (!visited
->empty())
257 mark
[visited
->pop()] = 0;