1 /*
2 * Copyright 1997, Regents of the University of Minnesota
3 *
4 * refine.c
5 *
6 * This file contains the driving routines for multilevel refinement
7 *
8 * Started 7/24/97
9 * George
10 *
11 * $Id: refine.c,v 1.1 1998/11/27 17:59:29 karypis Exp $
12 */
13
14 #include "metis.h"
15
16
17 /*************************************************************************
18 * This function is the entry point of refinement
19 **************************************************************************/
Refine2Way(CtrlType * ctrl,GraphType * orggraph,GraphType * graph,int * tpwgts,float ubfactor)20 void Refine2Way(CtrlType *ctrl, GraphType *orggraph, GraphType *graph, int *tpwgts, float ubfactor)
21 {
22
23 IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->UncoarsenTmr));
24
25 /* Compute the parameters of the coarsest graph */
26 Compute2WayPartitionParams(ctrl, graph);
27
28 for (;;) {
29 ASSERT(CheckBnd(graph));
30
31 IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->RefTmr));
32 switch (ctrl->RType) {
33 case 1:
34 Balance2Way(ctrl, graph, tpwgts, ubfactor);
35 FM_2WayEdgeRefine(ctrl, graph, tpwgts, 8);
36 break;
37 default:
38 graclus_errexit("Unknown refinement type: %d\n", ctrl->RType);
39 }
40 IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->RefTmr));
41
42 if (graph == orggraph)
43 break;
44
45 graph = graph->finer;
46 IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->ProjectTmr));
47 Project2WayPartition(ctrl, graph);
48 IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->ProjectTmr));
49 }
50
51 IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->UncoarsenTmr));
52 }
53
54
55 /*************************************************************************
56 * This function allocates memory for 2-way edge refinement
57 **************************************************************************/
Allocate2WayPartitionMemory(CtrlType * ctrl,GraphType * graph)58 void Allocate2WayPartitionMemory(CtrlType *ctrl, GraphType *graph)
59 {
60 int nvtxs;
61
62 nvtxs = graph->nvtxs;
63
64 graph->rdata = idxmalloc(5*nvtxs+2, "Allocate2WayPartitionMemory: rdata");
65 graph->pwgts = graph->rdata;
66 graph->where = graph->rdata + 2;
67 graph->id = graph->rdata + nvtxs + 2;
68 graph->ed = graph->rdata + 2*nvtxs + 2;
69 graph->bndptr = graph->rdata + 3*nvtxs + 2;
70 graph->bndind = graph->rdata + 4*nvtxs + 2;
71 }
72
73
74 /*************************************************************************
75 * This function computes the initial id/ed
76 **************************************************************************/
Compute2WayPartitionParams(CtrlType * ctrl,GraphType * graph)77 void Compute2WayPartitionParams(CtrlType *ctrl, GraphType *graph)
78 {
79 int i, j, k, l, nvtxs, nbnd, mincut;
80 idxtype *xadj, *vwgt, *adjncy, *adjwgt, *pwgts;
81 idxtype *id, *ed, *where;
82 idxtype *bndptr, *bndind;
83 int me, other;
84
85 nvtxs = graph->nvtxs;
86 xadj = graph->xadj;
87 vwgt = graph->vwgt;
88 adjncy = graph->adjncy;
89 adjwgt = graph->adjwgt;
90
91 where = graph->where;
92 pwgts = idxset(2, 0, graph->pwgts);
93 id = idxset(nvtxs, 0, graph->id);
94 ed = idxset(nvtxs, 0, graph->ed);
95 bndptr = idxset(nvtxs, -1, graph->bndptr);
96 bndind = graph->bndind;
97
98
99 /*------------------------------------------------------------
100 / Compute now the id/ed degrees
101 /------------------------------------------------------------*/
102 nbnd = mincut = 0;
103 for (i=0; i<nvtxs; i++) {
104 ASSERT(where[i] >= 0 && where[i] <= 1);
105 me = where[i];
106 pwgts[me] += vwgt[i];
107
108 for (j=xadj[i]; j<xadj[i+1]; j++) {
109 if (me == where[adjncy[j]])
110 id[i] += adjwgt[j];
111 else
112 ed[i] += adjwgt[j];
113 }
114
115 if (ed[i] > 0 || xadj[i] == xadj[i+1]) {
116 mincut += ed[i];
117 bndptr[i] = nbnd;
118 bndind[nbnd++] = i;
119 }
120 }
121
122 graph->mincut = mincut/2;
123 graph->nbnd = nbnd;
124
125 ASSERT(pwgts[0]+pwgts[1] == idxsum(nvtxs, vwgt));
126 }
127
128
129
130 /*************************************************************************
131 * This function projects a partition, and at the same time computes the
132 * parameters for refinement.
133 **************************************************************************/
Project2WayPartition(CtrlType * ctrl,GraphType * graph)134 void Project2WayPartition(CtrlType *ctrl, GraphType *graph)
135 {
136 int i, j, k, nvtxs, nbnd, me;
137 idxtype *xadj, *adjncy, *adjwgt, *adjwgtsum;
138 idxtype *cmap, *where, *id, *ed, *bndptr, *bndind;
139 idxtype *cwhere, *cid, *ced, *cbndptr;
140 GraphType *cgraph;
141
142 cgraph = graph->coarser;
143 cwhere = cgraph->where;
144 cid = cgraph->id;
145 ced = cgraph->ed;
146 cbndptr = cgraph->bndptr;
147
148 nvtxs = graph->nvtxs;
149 cmap = graph->cmap;
150 xadj = graph->xadj;
151 adjncy = graph->adjncy;
152 adjwgt = graph->adjwgt;
153 adjwgtsum = graph->adjwgtsum;
154
155 Allocate2WayPartitionMemory(ctrl, graph);
156
157 where = graph->where;
158 id = idxset(nvtxs, 0, graph->id);
159 ed = idxset(nvtxs, 0, graph->ed);
160 bndptr = idxset(nvtxs, -1, graph->bndptr);
161 bndind = graph->bndind;
162
163
164 /* Go through and project partition and compute id/ed for the nodes */
165 for (i=0; i<nvtxs; i++) {
166 k = cmap[i];
167 where[i] = cwhere[k];
168 cmap[i] = cbndptr[k];
169 }
170
171 for (nbnd=0, i=0; i<nvtxs; i++) {
172 me = where[i];
173
174 id[i] = adjwgtsum[i];
175
176 if (xadj[i] == xadj[i+1]) {
177 bndptr[i] = nbnd;
178 bndind[nbnd++] = i;
179 }
180 else {
181 if (cmap[i] != -1) { /* If it is an interface node. Note that cmap[i] = cbndptr[cmap[i]] */
182 for (j=xadj[i]; j<xadj[i+1]; j++) {
183 if (me != where[adjncy[j]])
184 ed[i] += adjwgt[j];
185 }
186 id[i] -= ed[i];
187
188 if (ed[i] > 0 || xadj[i] == xadj[i+1]) {
189 bndptr[i] = nbnd;
190 bndind[nbnd++] = i;
191 }
192 }
193 }
194 }
195
196 graph->mincut = cgraph->mincut;
197 graph->nbnd = nbnd;
198 idxcopy(2, cgraph->pwgts, graph->pwgts);
199
200 FreeGraph(graph->coarser);
201 graph->coarser = NULL;
202
203 }
204
205