Don't import ogdf namespace
[TortoiseGit.git] / ext / OGDF / src / planarity / SubgraphPlanarizer.cpp
blobf5e73b5824d6fccbf3c9a3875cd85e5ca83a7a3d
1 /*
2 * $Revision: 2599 $
4 * last checkin:
5 * $Author: chimani $
6 * $Date: 2012-07-15 22:39:24 +0200 (So, 15. Jul 2012) $
7 ***************************************************************/
9 /** \file
10 * \brief Implements class SubgraphPlanarizer.
12 * \author Markus Chimani
14 * \par License:
15 * This file is part of the Open Graph Drawing Framework (OGDF).
17 * \par
18 * Copyright (C)<br>
19 * See README.txt in the root directory of the OGDF installation for details.
21 * \par
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
26 * for details.
28 * \par
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.
34 * \par
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/planarity/SubgraphPlanarizer.h>
44 #include <ogdf/planarity/FastPlanarSubgraph.h>
45 #include <ogdf/planarity/VariableEmbeddingInserter.h>
47 namespace ogdf
50 SubgraphPlanarizer::SubgraphPlanarizer()
52 FastPlanarSubgraph* s= new FastPlanarSubgraph();
53 s->runs(100);
54 m_subgraph.set(s);
56 VariableEmbeddingInserter* i = new VariableEmbeddingInserter();
57 i->removeReinsert(VariableEmbeddingInserter::rrAll);
58 m_inserter.set(i);
60 m_permutations = 1;
61 m_setTimeout = true;
64 Module::ReturnType SubgraphPlanarizer::doCall(PlanRep &PG,
65 int cc,
66 const EdgeArray<int> &cost,
67 const EdgeArray<bool> &forbid,
68 const EdgeArray<unsigned int> &subgraphs,
69 int& crossingNumber)
71 OGDF_ASSERT(m_permutations >= 1);
73 OGDF_ASSERT(!(useSubgraphs()) || useCost()); // ersetze durch exception handling
75 double startTime;
76 usedTime(startTime);
78 if(m_setTimeout)
79 m_subgraph.get().timeLimit(m_timeLimit);
81 List<edge> deletedEdges;
82 PG.initCC(cc);
83 EdgeArray<int> costPG(PG);
84 edge e;
85 forall_edges(e,PG)
86 costPG[e] = cost[PG.original(e)];
87 ReturnType retValue = m_subgraph.get().call(PG, costPG, deletedEdges);
88 if(isSolution(retValue) == false)
89 return retValue;
91 for(ListIterator<edge> it = deletedEdges.begin(); it.valid(); ++it)
92 *it = PG.original(*it);
94 bool foundSolution = false;
95 CrossingStructure cs;
96 for(int i = 1; i <= m_permutations; ++i)
98 const int nG = PG.numberOfNodes();
100 for(ListConstIterator<edge> it = deletedEdges.begin(); it.valid(); ++it)
101 PG.delCopy(PG.copy(*it));
103 deletedEdges.permute();
105 if(m_setTimeout)
106 m_inserter.get().timeLimit(
107 (m_timeLimit >= 0) ? max(0.0,m_timeLimit - usedTime(startTime)) : -1);
109 ReturnType ret;
110 if(useForbid()) {
111 if(useCost()) {
112 if(useSubgraphs())
113 ret = m_inserter.get().call(PG, cost, forbid, deletedEdges, subgraphs);
114 else
115 ret = m_inserter.get().call(PG, cost, forbid, deletedEdges);
116 } else
117 ret = m_inserter.get().call(PG, forbid, deletedEdges);
118 } else {
119 if(useCost()) {
120 if(useSubgraphs())
121 ret = m_inserter.get().call(PG, cost, deletedEdges, subgraphs);
122 else
123 ret = m_inserter.get().call(PG, cost, deletedEdges);
124 } else
125 ret = m_inserter.get().call(PG, deletedEdges);
128 if(isSolution(ret) == false)
129 continue; // no solution found, that's bad...
131 if(!useCost())
132 crossingNumber = PG.numberOfNodes() - nG;
133 else {
134 crossingNumber = 0;
135 node n;
136 forall_nodes(n, PG) {
137 if(PG.original(n) == 0) { // dummy found -> calc cost
138 edge e1 = PG.original(n->firstAdj()->theEdge());
139 edge e2 = PG.original(n->lastAdj()->theEdge());
140 if(useSubgraphs()) {
141 int subgraphCounter = 0;
142 for(int i=0; i<32; i++) {
143 if(((subgraphs[e1] & (1<<i))!=0) && ((subgraphs[e2] & (1<<i)) != 0))
144 subgraphCounter++;
146 crossingNumber += (subgraphCounter*cost[e1] * cost[e2]);
147 } else
148 crossingNumber += cost[e1] * cost[e2];
153 if(i == 1 || crossingNumber < cs.weightedCrossingNumber()) {
154 foundSolution = true;
155 cs.init(PG, crossingNumber);
158 if(localLogMode() == LM_STATISTIC) {
159 if(m_permutations <= 200 ||
160 i <= 10 || (i <= 30 && (i % 2) == 0) || (i > 30 && i <= 100 && (i % 5) == 0) || ((i % 10) == 0))
161 sout() << "\t" << cs.weightedCrossingNumber();
164 PG.initCC(cc);
166 if(m_timeLimit >= 0 && usedTime(startTime) >= m_timeLimit) {
167 if(foundSolution == false)
168 return retTimeoutInfeasible; // not able to find a solution...
169 break;
173 cs.restore(PG,cc); // restore best solution in PG
174 crossingNumber = cs.weightedCrossingNumber();
176 OGDF_ASSERT(isPlanar(PG) == true);
178 return retFeasible;
182 void SubgraphPlanarizer::CrossingStructure::init(PlanRep &PG, int weightedCrossingNumber)
184 m_weightedCrossingNumber = weightedCrossingNumber;
185 m_crossings.init(PG.original());
187 m_numCrossings = 0;
188 NodeArray<int> index(PG,-1);
189 node v;
190 forall_nodes(v,PG)
191 if(PG.isDummy(v))
192 index[v] = m_numCrossings++;
194 edge ePG;
195 forall_edges(ePG,PG)
197 if(PG.original(ePG->source()) != 0) {
198 edge e = PG.original(ePG);
199 ListConstIterator<edge> it = PG.chain(e).begin();
200 for(++it; it.valid(); ++it) {
201 //cout << index[(*it)->source()] << " ";
202 m_crossings[e].pushBack(index[(*it)->source()]);
208 void SubgraphPlanarizer::CrossingStructure::restore(PlanRep &PG, int cc)
210 //PG.initCC(cc);
212 Array<node> id2Node(0,m_numCrossings-1,0);
214 SListPure<edge> edges;
215 PG.allEdges(edges);
217 for(SListConstIterator<edge> itE = edges.begin(); itE.valid(); ++itE)
219 edge ePG = *itE;
220 edge e = PG.original(ePG);
222 SListConstIterator<int> it;
223 for(it = m_crossings[e].begin(); it.valid(); ++it)
225 node x = id2Node[*it];
226 edge ePGOld = ePG;
227 ePG = PG.split(ePG);
228 node y = ePG->source();
230 if(x == 0) {
231 id2Node[*it] = y;
232 } else {
233 PG.moveTarget(ePGOld, x);
234 PG.moveSource(ePG, x);
235 PG.delNode(y);
241 } // namspace ogdf