6 * $Date: 2012-07-07 17:14:54 +0200 (Sa, 07. Jul 2012) $
7 ***************************************************************/
10 * \brief Implementation of the FastPlanarSubgraph.
12 * Class is derived from base class PlanarSubgraphModule
13 * and implements the interface for the Planarization algorithm
16 * \author Sebastian Leipert
19 * This file is part of the Open Graph Drawing Framework (OGDF).
23 * See README.txt in the root directory of the OGDF installation for details.
26 * This program is free software; you can redistribute it and/or
27 * modify it under the terms of the GNU General Public License
28 * Version 2 or 3 as published by the Free Software Foundation;
29 * see the file LICENSE.txt included in the packaging of this file
33 * This program is distributed in the hope that it will be useful,
34 * but WITHOUT ANY WARRANTY; without even the implied warranty of
35 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36 * GNU General Public License for more details.
39 * You should have received a copy of the GNU General Public
40 * License along with this program; if not, write to the Free
41 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
42 * Boston, MA 02110-1301, USA.
44 * \see http://www.gnu.org/copyleft/gpl.html
45 ***************************************************************/
48 #include <ogdf/basic/basic.h>
49 #include <ogdf/basic/Array.h>
50 #include <ogdf/basic/SList.h>
51 #include <ogdf/basic/simple_graph_alg.h>
52 #include <ogdf/basic/extended_graph_alg.h>
53 #include <ogdf/internal/planarity/PlanarSubgraphPQTree.h>
54 #include <ogdf/internal/planarity/PlanarLeafKey.h>
55 #include <ogdf/planarity/FastPlanarSubgraph.h>
60 // Prepares the planarity test and the planar embedding
61 Module::ReturnType
FastPlanarSubgraph::doCall(
63 const List
<edge
> & /*preferedEdges*/,
65 const EdgeArray
<int> *pCost
,
66 bool /*preferedImplyPlanar*/)
71 if (G
.numberOfEdges() < 9)
76 NodeArray
<node
> tableNodes(G
,0);
77 EdgeArray
<edge
> tableEdges(G
,0);
78 NodeArray
<bool> mark(G
,0);
80 EdgeArray
<int> componentID(G
);
83 // Determine Biconnected Components
84 int bcCount
= biconnectedComponents(G
,componentID
);
86 // Determine edges per biconnected component
87 Array
<SList
<edge
> > blockEdges(0,bcCount
-1);
92 blockEdges
[componentID
[e
]].pushFront(e
);
95 // Determine nodes per biconnected component.
96 Array
<SList
<node
> > blockNodes(0,bcCount
-1);
98 for (i
= 0; i
< bcCount
; i
++)
100 SListIterator
<edge
> it
;
101 for (it
= blockEdges
[i
].begin(); it
.valid(); ++it
)
104 if (!mark
[e
->source()])
106 blockNodes
[i
].pushBack(e
->source());
107 mark
[e
->source()] = true;
109 if (!mark
[e
->target()])
111 blockNodes
[i
].pushBack(e
->target());
112 mark
[e
->target()] = true;
115 SListIterator
<node
> itn
;
116 for (itn
= blockNodes
[i
].begin(); itn
.valid(); ++itn
)
121 // Perform Planarization for every biconnected component
124 if (G
.numberOfEdges() > 4)
125 computeDelEdges(G
,pCost
,0,delEdges
);
128 for (i
= 0; i
< bcCount
; i
++)
132 SListIterator
<node
> itn
;
133 for (itn
= blockNodes
[i
].begin(); itn
.valid(); ++ itn
)
136 node w
= C
.newNode();
141 SListIterator
<edge
> it
;
142 for (it
= blockEdges
[i
].begin(); it
.valid(); ++it
)
145 edge f
= C
.newEdge(tableNodes
[e
->source()],tableNodes
[e
->target()]);
149 // Construct a translation table for the edges.
150 // Necessary, since edges are deleted in a new graph.
151 // that represents the biconnectedcomponent of the original graph.
152 EdgeArray
<edge
> backTableEdges(C
,0);
153 for (it
= blockEdges
[i
].begin(); it
.valid(); ++it
)
154 backTableEdges
[tableEdges
[*it
]] = *it
;
156 // gets the deletec Edges of the biconnected component
157 List
<edge
> delEdgesOfBC
;
160 if (C
.numberOfEdges() > 4)
161 computeDelEdges(C
,pCost
,&backTableEdges
,delEdgesOfBC
);
163 // get the original edges that are deleted and
164 // put them on the list delEdges.
165 while (!delEdgesOfBC
.empty())
166 delEdges
.pushBack(backTableEdges
[delEdgesOfBC
.popFrontRet()]);
175 void FastPlanarSubgraph::computeDelEdges(
177 const EdgeArray
<int> *pCost
,
178 const EdgeArray
<edge
> *backTableEdges
,
179 List
<edge
> &delEdges
)
183 // Compute st-numbering
184 NodeArray
<int> numbering(G
,0);
185 stNumber(G
,numbering
);
187 planarize(G
,numbering
,delEdges
);
190 int bestSolution
= INT_MAX
;
192 for(int i
= 1; i
<= m_nRuns
&& bestSolution
> 1; ++i
)
194 List
<edge
> currentDelEdges
;
196 // Compute (randomized) st-numbering
197 NodeArray
<int> numbering(G
,0);
198 stNumber(G
,numbering
,0,0,true);
200 planarize(G
,numbering
,currentDelEdges
);
204 int currentSolution
= currentDelEdges
.size();
206 if(currentSolution
< bestSolution
) {
207 bestSolution
= currentSolution
;
209 delEdges
.conc(currentDelEdges
);
213 int currentSolution
= 0;
214 ListConstIterator
<edge
> it
;
215 for(it
= currentDelEdges
.begin(); it
.valid(); ++it
)
216 if(backTableEdges
!= 0)
217 currentSolution
+= (*pCost
)[(*backTableEdges
)[*it
]];
219 currentSolution
+= (*pCost
)[*it
];
221 if(currentSolution
< bestSolution
) {
222 bestSolution
= currentSolution
;
224 delEdges
.conc(currentDelEdges
);
234 // Performs a planarity test on a biconnected component
235 // of G. numbering contains an st-numbering of the component.
236 void FastPlanarSubgraph::planarize(
238 NodeArray
<int> &numbering
,
239 List
<edge
> &delEdges
)
243 NodeArray
<SListPure
<PlanarLeafKey
<whaInfo
*>* > > inLeaves(G
);
244 NodeArray
<SListPure
<PlanarLeafKey
<whaInfo
*>* > > outLeaves(G
);
245 Array
<node
> table(G
.numberOfNodes()+1);
250 forall_adj_edges(e
,v
)
252 if (numbering
[e
->opposite(v
)] > numbering
[v
])
253 // sideeffect: ignores selfloops
255 PlanarLeafKey
<whaInfo
*>* L
= OGDF_NEW PlanarLeafKey
<whaInfo
*>(e
);
256 inLeaves
[v
].pushFront(L
);
259 table
[numbering
[v
]] = v
;
264 SListIterator
<PlanarLeafKey
<whaInfo
*>* > it
;
265 for (it
= inLeaves
[v
].begin(); it
.valid(); ++it
)
267 PlanarLeafKey
<whaInfo
*>* L
= *it
;
268 outLeaves
[L
->userStructKey()->opposite(v
)].pushFront(L
);
272 SList
<PQLeafKey
<edge
,whaInfo
*,bool>*> totalEliminatedKeys
;
274 PlanarSubgraphPQTree T
;
275 T
.Initialize(inLeaves
[table
[1]]);
276 for (int i
= 2; i
< G
.numberOfNodes(); i
++)
278 SList
<PQLeafKey
<edge
,whaInfo
*,bool>*> eliminatedKeys
;
279 T
.Reduction(outLeaves
[table
[i
]],eliminatedKeys
);
281 totalEliminatedKeys
.conc(eliminatedKeys
);
282 T
.ReplaceRoot(inLeaves
[table
[i
]]);
283 T
.emptyAllPertinentNodes();
287 SListIterator
<PQLeafKey
<edge
,whaInfo
*,bool>* > it
;
288 for (it
= totalEliminatedKeys
.begin(); it
.valid(); ++it
)
290 edge e
= (*it
)->userStructKey();
291 delEdges
.pushBack(e
);
297 while (!inLeaves
[v
].empty())
299 PlanarLeafKey
<whaInfo
*>* L
= inLeaves
[v
].popFrontRet();
304 T
.Cleanup(); // Explicit call for destructor necessary. This allows to call virtual
305 // funtion CleanNode for freeing node information class.