6 * $Date: 2012-07-05 16:45:20 +0200 (Do, 05. Jul 2012) $
7 ***************************************************************/
10 * \brief Merges nodes with neighbour to get a Multilevel Graph
12 * \author Gereon Bartel
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/energybased/multilevelmixer/EdgeCoverMerger.h>
47 EdgeCoverMerger::EdgeCoverMerger()
48 :m_levelSizeFactor(2.0)
52 bool EdgeCoverMerger::buildOneLevel(MultilevelGraph
&MLG
)
54 Graph
&G
= MLG
.getGraph();
55 int level
= MLG
.getLevel() + 1;
56 m_substituteNodes
.init(G
, 0);
58 int numNodes
= G
.numberOfNodes();
64 NodeArray
<bool> nodeMarks(G
, false);
65 std::vector
<edge
> untouchedEdges
;
66 std::vector
<edge
> matching
;
67 std::vector
<edge
> edgeCover
;
68 std::vector
<edge
> rest
;
71 untouchedEdges
.push_back(e
);
74 while (!untouchedEdges
.empty())
76 int rndIndex
= randomNumber(0, (int)untouchedEdges
.size()-1);
77 edge randomEdge
= untouchedEdges
[rndIndex
];
78 untouchedEdges
[rndIndex
] = untouchedEdges
.back();
79 untouchedEdges
.pop_back();
81 node one
= randomEdge
->source();
82 node two
= randomEdge
->target();
83 if (!nodeMarks
[one
] && !nodeMarks
[two
]) {
84 matching
.push_back(randomEdge
);
85 nodeMarks
[one
] = true;
86 nodeMarks
[two
] = true;
88 rest
.push_back(randomEdge
);
94 int rndIndex
= randomNumber(0, (int)rest
.size()-1);
95 edge randomEdge
= rest
[rndIndex
];
96 rest
[rndIndex
] = rest
.back();
99 node one
= randomEdge
->source();
100 node two
= randomEdge
->target();
101 if (!nodeMarks
[one
] || !nodeMarks
[two
]) {
102 edgeCover
.push_back(randomEdge
);
103 nodeMarks
[one
] = true;
104 nodeMarks
[two
] = true;
110 while ((!matching
.empty() || !edgeCover
.empty()) && G
.numberOfNodes() > numNodes
/ m_levelSizeFactor
) {
114 if (!matching
.empty()) {
115 rndIndex
= randomNumber(0, (int)matching
.size()-1);
116 coveringEdge
= matching
[rndIndex
];
117 matching
[rndIndex
] = matching
.back();
120 rndIndex
= randomNumber(0, (int)edgeCover
.size()-1);
121 coveringEdge
= edgeCover
[rndIndex
];
122 edgeCover
[rndIndex
] = edgeCover
.back();
123 edgeCover
.pop_back();
129 // choose high degree node as parent!
130 mergeNode
= coveringEdge
->source();
131 parent
= coveringEdge
->target();
132 if (mergeNode
->degree() > parent
->degree()) {
133 mergeNode
= coveringEdge
->target();
134 parent
= coveringEdge
->source();
137 while(m_substituteNodes
[parent
] != 0) {
138 parent
= m_substituteNodes
[parent
];
140 while(m_substituteNodes
[mergeNode
] != 0) {
141 mergeNode
= m_substituteNodes
[mergeNode
];
144 if (MLG
.getNode(parent
->index()) != parent
145 || MLG
.getNode(mergeNode
->index()) != mergeNode
146 || parent
== mergeNode
)
151 retVal
= doMerge(MLG
, parent
, mergeNode
, level
);
158 void EdgeCoverMerger::setFactor(double factor
)
160 m_levelSizeFactor
= factor
;
164 // tracks substitute Nodes
165 bool EdgeCoverMerger::doMerge( MultilevelGraph
&MLG
, node parent
, node mergePartner
, int level
)
167 NodeMerge
* NM
= new NodeMerge(level
);
168 bool ret
= MLG
.changeNode(NM
, parent
, MLG
.radius(parent
), mergePartner
);
170 MLG
.moveEdgesToParent(NM
, mergePartner
, parent
, true, m_adjustEdgeLengths
);
171 ret
= MLG
.postMerge(NM
, mergePartner
);
176 m_substituteNodes
[mergePartner
] = parent
;