-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgknv_crossings_reducer.hpp
232 lines (183 loc) · 6.41 KB
/
gknv_crossings_reducer.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
#ifndef _WAILEA_DIRECTED_GKNV_CROSSINGS_REDUCER_HPP_
#define _WAILEA_DIRECTED_GKNV_CROSSINGS_REDUCER_HPP_
#include <iostream>
#include <string>
#include <list>
#include <vector>
#include <exception>
#include "directed/di_base.hpp"
#ifdef UNIT_TESTS
#include "gtest/gtest_prod.h"
#endif
/**
* @file directed/gknv_crossing_reducer.hpp
*
* @brief it tries to reduce the number of crossings for a given acyclic
* digraph whose nodes are given acyclic ranks
*
* @reference [GKNV] E. R. Gansner, E. Koutsofios, S. C. North, and
* K.-P Vo. A technique for drawing directed graphs. IEEE
* Transactions on Software Engineering, 19(3):214–230,
* March 1993.
*/
namespace Wailea {
namespace Directed {
using namespace std;
using namespace Wailea::Directed;
/** @class GKNVcrossingsReducer
*
* @brief
*/
class GKNVcrossingsReducer {
public:
/** @brief constructor
*
* @param G (in/out): The inpug digraph
*/
inline GKNVcrossingsReducer(DiGraph& G):mG(G){;}
inline virtual ~GKNVcrossingsReducer(){;}
/** @brief main function to attempt to reduce the number of crossings
* of edges using GKNV heuristics for a given node rank assignment
*
* @param ranks (in/out): outer vector represents the ranks and the inner
* vector at each rank holds the nodes in that rank.
* After a call, the nodes in an inner vector are arranged
*
* @param numIterations (in): number of iterations to apply the heuristics
*
* @return number of crossings with the resultant node arrangement.
*
*/
long reduce(vector<vector<node_list_it_t> >& ranks, long numIterations);
private:
/** @brief reorder the nodes in each rank based on DFS.
*
* @param ranks (in/out): ranks. Each rank has an ordered list of nodes.
*/
void initialOrderByDFS(vector<vector<node_list_it_t> >& ranks);
/** @brief one iteration of median heuristic either forward or backward
*
* @param oldRanks (in): current node arrangement.
*
* @param newRanks (out): new node arrangement
*
* @param forward (in): true if the direction is from rank 0 forward.
* false if the direction is down to 0 backward.
*/
void applyMedianHeuristic(
vector<vector<node_list_it_t> >& oldRanks,
vector<vector<node_list_it_t> >& newRanks,
bool forward
);
/** @brief applies transpose heuristic. Swap two adjacent nodes in the
* the same rank and see if it reduces the crossings.
*
* @param ranks (in/out): node arrangement
*/
void applyTransposeHeuristic(vector<vector<node_list_it_t> >& ranks);
/** @brief try swapping the adjacent nodes on the left hand side.
* Used for the first two adjacent ranks
*
* @param leftRank (in): rank[0]
*
* @param rightRank (in): rank[1]
*/
void tryTransposeLeft(
vector<node_list_it_t>& leftRank,
vector<node_list_it_t>& rightRank
);
/** @brief try swapping the adjacent nodes on the mid rank.
*
* @param leftRank (in): rank[i-1]
*
* @param midRank (in): rank[i]
*
* @param rightRank (in): rank[i+1]
*/
void tryTransposeMid(
vector<node_list_it_t>& leftRank,
vector<node_list_it_t>& midRank,
vector<node_list_it_t>& rightRank
);
/** @brief try swapping the adjacent nodes on the left hand side.
* Used for the last two adjacent ranks
*
* @param leftRank (in): rank[last -1]
*
* @param rightRank (in): rank[last]
*/
void tryTransposeRight(
vector<node_list_it_t>& leftRank,
vector<node_list_it_t>& rightRank
);
/** @brief calculates the number of crossings in the input graph in mG.
*
* @param ranks (in): ranks. Each rank has an ordered list of nodes.
*
* @return number of crossings
*/
long calculateNumberOfCrossings(vector<vector<node_list_it_t> >& ranks);
/** @brief calculates the number of crossings between
* two consecutive ranks as a bipartite graph
*
* @param leftNodes (in): ordered list of nodes on the left hand side,
* assuming the graph flows from left to right.
*
* @param rightNodes (in): ordered list of nodes on the right hand side.
*
* @return number of crossings
*/
long calculateNumberOfCrossings(
vector<node_list_it_t>& leftNodes,
vector<node_list_it_t>& rightNodes
);
/** @brief reorder the right hand side of the nodes based on the median
* heuristic described in GKNV.
*
* @param leftNodes (in): ordered list of left nodes.
*
* @param rightNodes (in): ordered list of right nodes.
*
* @param newRightNodes (out): reordered list of right nodes.
*/
void reorderRightSideByMedianHeuristic(
vector<node_list_it_t>& leftNodes,
vector<node_list_it_t>& rightNodes,
vector<node_list_it_t>& newRightNodes
);
/** @brief reorder the left hand side of the nodes based on the median
* heuristic described in GKNV.
*
* @param leftNodes (in): ordered list of left nodes.
*
* @param rightNodes (in): ordered list of right nodes.
*
* @param newLeftNodes (out): reordered list of left nodes.
*/
void reorderLeftSideByMedianHeuristic(
vector<node_list_it_t>& leftNodes,
vector<node_list_it_t>& rightNodes,
vector<node_list_it_t>& newLeftNodes
);
/** @brief based on the current node ordering in each rank,
* reorder the incident edge lists of the nodes.
*
* @param ranks (in): ranks. Each rank has an ordered list of nodes.
*/
void rearrangeIncidenceLists(
vector<vector<node_list_it_t> >& ranks
);
/** @brief the input graph */
DiGraph& mG;
/** @brief utility functions for std::sort() to rearrange the
* incident edge list of nodes.
*/
static bool nodeCompSrc(edge_list_it_t it1, edge_list_it_t it2);
static bool nodeCompDst(edge_list_it_t it1, edge_list_it_t it2);
#ifdef UNIT_TESTS
friend class GKNVcrossingsReducerTests;
#endif
};
}// namespace Directed
}// namespace Wailea
#endif /* _WAILEA_DIRECTED_GKNV_CROSSINGS_REDUCER_HPP_*/