6 * $Date: 2012-07-06 15:04:28 +0200 (Fr, 06. Jul 2012) $
7 ***************************************************************/
10 * \brief Implements class UpwardPlanarSubgraphSimple which computes
11 * an upward planar subgraph of a single-source acyclic digraph
13 * \author Hoi-Ming Wong
16 * This file is part of the Open Graph Drawing Framework (OGDF).
20 * See README.txt in the root directory of the OGDF installation for details.
23 * This program is free software; you can redistribute it and/or
24 * modify it under the terms of the GNU General Public License
25 * Version 2 or 3 as published by the Free Software Foundation;
26 * see the file LICENSE.txt included in the packaging of this file
30 * This program is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * GNU General Public License for more details.
36 * You should have received a copy of the GNU General Public
37 * License along with this program; if not, write to the Free
38 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
39 * Boston, MA 02110-1301, USA.
41 * \see http://www.gnu.org/copyleft/gpl.html
42 ***************************************************************/
44 #include <ogdf/upward/FeasibleUpwardPlanarSubgraph.h>
45 #include <ogdf/upward/UpwardPlanarModule.h>
46 #include <ogdf/upward/FaceSinkGraph.h>
47 #include <ogdf/basic/simple_graph_alg.h>
52 Module::ReturnType
FeasibleUpwardPlanarSubgraph::call(
55 adjEntry
&extFaceHandle
,
62 UpwardPlanarModule upMod
;
63 OGDF_ASSERT(!upMod
.upwardPlanarityTest(G
));
68 //current fups, its embedding and the removed edges
70 List
<edge
> delEdges_cur
;
72 call(G
, FUPS
, extFaceHandle
, delEdges
, multisources
);
74 for (int i
= 1; i
< runs
; ++i
) {
75 adjEntry extFaceHandle_cur
;
76 call(G
, FUPS_cur
, extFaceHandle_cur
, delEdges_cur
, multisources
);
79 if (delEdges_cur
.size() < delEdges
.size()) {
81 extFaceHandle
= FUPS
.copy(FUPS_cur
.original(extFaceHandle_cur
->theEdge()))->adjSource();
82 delEdges
= delEdges_cur
;
85 return Module::retFeasible
;
89 Module::ReturnType
FeasibleUpwardPlanarSubgraph::call(
92 adjEntry
&extFaceHandle
,
99 hasSingleSource(G
, s_orig
);
100 List
<edge
> nonTreeEdges_orig
;
101 getSpanTree(FUPS
, nonTreeEdges_orig
, true, multisources
);
102 CombinatorialEmbedding
Gamma(FUPS
);
103 nonTreeEdges_orig
.permute(); // random order
105 //insert nonTreeEdges
106 UpwardPlanarModule upMod
;
107 while (!nonTreeEdges_orig
.empty()) {
108 // make identical copy GC of Fups
109 //and insert e_orig in GC
111 edge e_orig
= nonTreeEdges_orig
.popFrontRet();
112 //node a = GC.copy(e_orig->source());
113 //node b = GC.copy(e_orig->target());
116 if (upMod
.upwardPlanarEmbed(GC
)) { //upward embedded the fups and check feasibility
117 CombinatorialEmbedding
Beta(GC
);
119 //choose a arbitrary feasibel ext. face
120 FaceSinkGraph
fsg(Beta
, GC
.copy(s_orig
));
121 SList
<face
> ext_faces
;
122 fsg
.possibleExternalFaces(ext_faces
);
123 OGDF_ASSERT(!ext_faces
.empty());
124 Beta
.setExternalFace(ext_faces
.front());
126 GraphCopy M
= GC
; // use a identical copy of GC to constrcut the merge graph of GC
127 adjEntry extFaceHandle_cur
= getAdjEntry(Beta
, GC
.copy(s_orig
), Beta
.externalFace());
128 adjEntry adj_orig
= GC
.original(extFaceHandle_cur
->theEdge())->adjSource();
130 if (constructMergeGraph(M
, adj_orig
, nonTreeEdges_orig
)) {
132 extFaceHandle
= FUPS
.copy(GC
.original(extFaceHandle_cur
->theEdge()))->adjSource();
136 //Beta is not feasible
137 delEdges
.pushBack(e_orig
);
141 // not ok, GC is not feasible
142 delEdges
.pushBack(e_orig
);
146 return Module::retFeasible
;
150 void FeasibleUpwardPlanarSubgraph::getSpanTree(GraphCopy
&GC
, List
<edge
> &delEdges
, bool random
, bool multisource
)
153 if (GC
.numberOfNodes() == 1)
154 return; // nothing to do
156 hasSingleSource(GC
, s
);
157 NodeArray
<bool> visited(GC
, false);
158 EdgeArray
<bool> isTreeEdge(GC
,false);
161 // the original graph is a multisource graph. The sources are connected with the super source s.
162 // so do not delete the incident edges of s
164 // put all incident edges of the source to treeEdges
167 isTreeEdge
[adj
->theEdge()] = true;
168 visited
[adj
->theEdge()->target()];
169 toDo
.pushBack(adj
->theEdge()->target());
176 //traversing with dfs
177 forall_listiterators(node
, it
, toDo
) {
180 forall_adj(adj
, start
) {
181 node v
= adj
->theEdge()->target();
183 dfs_visit(GC
, adj
->theEdge(), visited
, isTreeEdge
, random
);
187 // delete all non tree edgesEdges to obtain a span tree
190 forall_edges(e
, GC
) {
196 delEdges
.pushBack(GC
.original(e
));
203 void FeasibleUpwardPlanarSubgraph::dfs_visit(
206 NodeArray
<bool> &visited
,
207 EdgeArray
<bool> &treeEdges
,
212 G
.outEdges(e
->target(), elist
);
213 if (!elist
.empty()) {
216 ListIterator
<edge
> it
;
217 for (it
= elist
.begin(); it
.valid(); ++it
) {
219 if (!visited
[ee
->target()])
220 dfs_visit(G
, ee
, visited
, treeEdges
, random
);
223 visited
[e
->target()] = true;
227 bool FeasibleUpwardPlanarSubgraph::constructMergeGraph(
230 const List
<edge
> &orig_edges
)
232 CombinatorialEmbedding
Beta(M
);
234 //set ext. face of Beta
235 adjEntry ext_adj
= M
.copy(adj_orig
->theEdge())->adjSource();
236 Beta
.setExternalFace(Beta
.rightFace(ext_adj
));
238 FaceSinkGraph
fsg(Beta
, M
.copy(adj_orig
->theNode()));
239 SList
<node
> aug_nodes
;
240 SList
<edge
> aug_edges
;
242 fsg
.possibleExternalFaces(fList
); // use this method to call the methode checkForest()
243 node v_ext
= fsg
.faceNodeOf(Beta
.externalFace());
245 OGDF_ASSERT(v_ext
!= 0);
247 fsg
.stAugmentation(v_ext
, M
, aug_nodes
, aug_edges
);
249 //add the deleted edges
250 forall_listiterators(edge
, it
, orig_edges
) {
251 node a
= M
.copy((*it
)->source());
252 node b
= M
.copy((*it
)->target());
255 return (isAcyclic(M
));
261 } // end namespace ogdf