1
/* This software was developed by Bruce Hendrickson and Robert Leland *
2
* at Sandia National Laboratories under US Department of Energy *
3
* contract DE-AC04-76DP00789 and is copyrighted by Sandia Corporation. */
11
/* Move vertices between domains to ensure each domain is connected. */
12
/* Note: This will likely result in load imbalance. */
14
void connect_enforce(graph, nvtxs, using_ewgts, assignment, goal, nsets_tot,
16
struct vtx_data **graph; /* data structure for graph */
17
int nvtxs; /* number of vertices in full graph */
18
int using_ewgts; /* are edge weights being used? */
19
short *assignment; /* set number of each vtx (length n) */
20
double *goal; /* desired sizes for each set */
21
int nsets_tot; /* total number sets created */
22
int *total_move; /* total number of vertices moved */
23
int *max_move; /* largest connected component moved */
25
struct vtx_data **subgraph; /* data structure for domain graph */
26
int subnvtxs; /* number of vertices in a domain */
27
int subnedges; /* number of edges in a domain */
28
struct heap *heap; /* data structure for sorting set sizes */
29
int *heap_map; /* pointers from sets to heap locations */
30
int *list_ptrs; /* header of vtx list for each domain */
31
int *setlists; /* linked list of vtxs for each domain */
32
int *vtxlist; /* space for breadth first search list */
33
int *comp_lists; /* list of vtxs in each connected comp */
34
int *clist_ptrs; /* pointers to heads of comp_lists */
35
short *subsets; /* list of active domains (all of them) */
36
short *subsets2; /* list of active domains (all of them) */
37
double *set_size; /* weighted sizes of different partitions */
38
double size; /* size of subset being moved to new domain */
39
int *bndy_list; /* list of domains adjacent to component */
40
double *bndy_size; /* size of these boundaries */
41
double *comp_size; /* sizes of different connected components */
42
double comp_size_max; /* size of largest connected component */
43
int comp_max_index; /* which component is largest? */
44
int *glob2loc; /* global to domain renumbering */
45
int *loc2glob; /* domain to global renumbering */
46
short *degree; /* number of neighbors of a vertex */
47
short *comp_flag; /* component number for each vtx */
48
double ewgt; /* edge weight */
49
int nbndy; /* number of sets adjecent to component */
50
int domain; /* which subdomain I'm working on */
51
int new_domain; /* subdomain to move some vertices to */
52
double max_bndy; /* max connectivity to other domain */
53
int ncomps; /* number of connected components */
54
int change; /* how many vertices change set? */
55
int max_change; /* largest subset moved together */
56
int vtx; /* vertex in a connected component */
57
int set; /* set a neighboring vertex is in */
58
int i, j, k, l; /* loop counters */
59
double heap_extract_max();
60
int make_maps(), find_comps();
61
void make_setlists(), make_subgraph(), remake_graph();
62
void heap_build(), heap_update_val();
67
/* Allocate space & initialize some values. */
69
set_size = smalloc(nsets_tot * sizeof(double));
70
bndy_size = smalloc(nsets_tot * sizeof(double));
71
bndy_list = smalloc(nsets_tot * sizeof(int));
73
setlists = smalloc((nvtxs + 1) * sizeof(int));
74
list_ptrs = smalloc(nsets_tot * sizeof(int));
76
glob2loc = smalloc((nvtxs + 1) * sizeof(int));
77
loc2glob = smalloc((nvtxs + 1) * sizeof(int));
78
subsets = smalloc(nsets_tot * sizeof(short));
79
heap = (struct heap *)
80
smalloc((nsets_tot + 1) * sizeof(struct heap));
81
heap_map = smalloc(nsets_tot * sizeof(int));
83
for (i = 0; i < nsets_tot; i++) {
90
for (i = 1; i <= nvtxs; i++) {
91
set_size[assignment[i]] += graph[i]->vwgt;
94
for (i = 0; i < nsets_tot; i++) {
96
heap[i+1].val = set_size[i] - goal[i];
99
make_setlists(setlists, list_ptrs, nsets_tot, subsets, assignment,
102
heap_build(heap, nsets_tot, heap_map);
104
for (i = 0; i < nsets_tot; i++) {
105
/* Find largest remaining set to work on next */
106
size = heap_extract_max(heap, nsets_tot - i, &domain, heap_map);
108
/* Construct subdomain graph. */
109
subnvtxs = make_maps(setlists, list_ptrs, domain, glob2loc,
113
subgraph = (struct vtx_data **)
114
smalloc((subnvtxs + 1) * sizeof(struct vtx_data *));
115
degree = smalloc((subnvtxs + 1) * sizeof(short));
117
make_subgraph(graph, subgraph, subnvtxs, &subnedges, assignment,
118
domain, glob2loc, loc2glob, degree, using_ewgts);
120
/* Find connected components. */
121
comp_flag = smalloc((subnvtxs + 1) * sizeof(short));
122
vtxlist = smalloc(subnvtxs * sizeof(int));
123
ncomps = find_comps(subgraph, subnvtxs, comp_flag, vtxlist);
126
/* Restore original graph */
127
remake_graph(subgraph, subnvtxs, loc2glob, degree, using_ewgts);
133
/* Figure out sizes of components */
134
comp_size = smalloc(ncomps * sizeof(double));
135
for (j = 0; j < ncomps; j++) {
138
for (j = 1; j <= subnvtxs; j++) {
139
comp_size[comp_flag[j]] += graph[loc2glob[j]]->vwgt;
142
for (j = 0; j < ncomps; j++) {
143
if (comp_size[j] > comp_size_max) {
144
comp_size_max = comp_size[j];
148
for (j = 0; j < ncomps; j++) {
149
if (j != comp_max_index) {
150
change += comp_size[j];
151
if (comp_size[j] > max_change) max_change = comp_size[j];
156
/* Make data structures for traversing components */
157
comp_lists = smalloc((subnvtxs + 1) * sizeof(int));
158
clist_ptrs = smalloc(ncomps * sizeof(int));
159
if (ncomps > nsets_tot) {
160
subsets2 = smalloc(ncomps * sizeof(short));
161
for (j = 0; j < ncomps; j++) subsets2[j] = j;
163
else subsets2 = subsets;
164
make_setlists(comp_lists, clist_ptrs, ncomps, subsets2, comp_flag,
165
NULL, subnvtxs, TRUE);
166
if (ncomps > nsets_tot) {
170
/* Move all but the largest component. */
172
for (j = 0; j < ncomps; j++)
173
if (j != comp_max_index) {
175
/* Figure out to which other domain it is most connected. */
180
for (l = 1; l <= graph[vtx]->nedges; l++) {
181
set = assignment[graph[vtx]->edges[l]];
183
if (bndy_size[set] == 0)
184
bndy_list[nbndy++] = set;
186
ewgt = graph[vtx]->ewgts[l];
187
bndy_size[set] += ewgt;
194
/* Select a new domain. */
195
/* Instead of just big boundary, penalize too-large sets. */
196
/* Could be more aggressive to improve balance. */
199
for (k = 0; k < nbndy; k++) {
201
if (bndy_size[l] * goal[l] / (set_size[l] + 1) > max_bndy) {
202
new_domain = bndy_list[k];
203
max_bndy = bndy_size[l] * goal[l] / (set_size[l] + 1);
206
if (new_domain == -1) {
207
printf("Error in connect_enforce: new_domain = -1. Disconnected graph?\n");
211
/* Clear bndy_size array */
212
for (k = 0; k < nbndy; k++)
213
bndy_size[bndy_list[k]] = 0;
221
assignment[vtx] = new_domain;
222
size += graph[vtx]->vwgt;
224
/* Finally, update setlists and list_ptrs */
225
/* Note: current domain setlist now bad, but not used
227
setlists[vtx] = list_ptrs[new_domain];
228
list_ptrs[new_domain] = vtx;
233
printf("Updating set %d (from %d) to size %g\n", new_domain, domain,
234
set_size[new_domain] + size - goal[new_domain]);
236
if (heap_map[new_domain] > 0) {
237
set_size[new_domain] += size;
238
heap_update_val(heap, heap_map[new_domain],
239
set_size[new_domain] - goal[new_domain], heap_map);
261
*total_move = change;
262
*max_move = max_change;