1 /* Copyright 2004,2007,2009-2012 IPB, Universite de Bordeaux, INRIA & CNRS
2 **
3 ** This file is part of the Scotch software package for static mapping,
4 ** graph partitioning and sparse matrix ordering.
5 **
6 ** This software is governed by the CeCILL-C license under French law
7 ** and abiding by the rules of distribution of free software. You can
8 ** use, modify and/or redistribute the software under the terms of the
9 ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
10 ** URL: "http://www.cecill.info".
11 **
12 ** As a counterpart to the access to the source code and rights to copy,
13 ** modify and redistribute granted by the license, users are provided
14 ** only with a limited warranty and the software's author, the holder of
15 ** the economic rights, and the successive licensors have only limited
16 ** liability.
17 **
18 ** In this respect, the user's attention is drawn to the risks associated
19 ** with loading, using, modifying and/or developing or reproducing the
20 ** software by the user in light of its specific status of free software,
21 ** that may mean that it is complicated to manipulate, and that also
22 ** therefore means that it is reserved for developers and experienced
23 ** professionals having in-depth computer knowledge. Users are therefore
24 ** encouraged to load and test the software's suitability as regards
25 ** their requirements in conditions enabling the security of their
26 ** systems and/or data to be ensured and, more generally, to use and
27 ** operate it in the same conditions as regards security.
28 **
29 ** The fact that you are presently reading this means that you have had
30 ** knowledge of the CeCILL-C license and that you accept its terms.
31 */
32 /************************************************************/
33 /** **/
34 /** NAME : bgraph_bipart_st.c **/
35 /** **/
36 /** AUTHOR : Francois PELLEGRINI **/
37 /** Sebastien FOURESTIER (v6.0) **/
38 /** **/
39 /** FUNCTION : This module contains the strategy and **/
40 /** method tables for graph bipartitioning **/
41 /** methods. **/
42 /** **/
43 /** DATES : # Version 3.2 : from : 08 oct 1996 **/
44 /** to 13 sep 1998 **/
45 /** # Version 3.3 : from : 01 oct 1998 **/
46 /** to 12 mar 1999 **/
47 /** # Version 3.4 : from : 01 jun 2001 **/
48 /** to 01 jun 2001 **/
49 /** # Version 4.0 : from : 12 jan 2004 **/
50 /** to 20 aug 2004 **/
51 /** # Version 5.0 : from : 27 nov 2006 **/
52 /** to 29 may 2007 **/
53 /** # Version 5.1 : from : 26 oct 2009 **/
54 /** to 15 apr 2011 **/
55 /** # Version 6.0 : from : 23 fev 2011 **/
56 /** to 19 nov 2012 **/
57 /** **/
58 /************************************************************/
59
60 /*
61 ** The defines and includes.
62 */
63
64 #define BGRAPH_BIPART_ST
65
66 #include "module.h"
67 #include "common.h"
68 #include "fibo.h"
69 #include "gain.h"
70 #include "parser.h"
71 #include "graph.h"
72 #include "arch.h"
73 #include "mapping.h"
74 #include "graph_coarsen.h"
75 #include "bgraph.h"
76 #include "bgraph_bipart_bd.h"
77 #include "bgraph_bipart_df.h"
78 #include "bgraph_bipart_ex.h"
79 #include "bgraph_bipart_fm.h"
80 #include "bgraph_bipart_gg.h"
81 #include "bgraph_bipart_gp.h"
82 #include "bgraph_bipart_ml.h"
83 #include "bgraph_bipart_zr.h"
84 #include "bgraph_bipart_st.h"
85
86 /*
87 ** The static and global variables.
88 */
89
90 static Bgraph bgraphdummy; /*+ Dummy active graph for offset computations +*/
91
92 static union {
93 BgraphBipartBdParam param;
94 StratNodeMethodData padding;
95 } bgraphbipartstdefaultbd = { { 3, &stratdummy } };
96
97 static union {
98 BgraphBipartDfParam param;
99 StratNodeMethodData padding;
100 } bgraphbipartstdefaultdf = { { 40, BGRAPHBIPARTDFTYPEBAL } };
101
102 static union { /* Default parameters for bipartitioning methods */
103 BgraphBipartFmParam param; /* Parameter zone */
104 StratNodeMethodData padding; /* To avoid reading out of structure */
105 } bgraphbipartstdefaultfm = { { 80, ~0, 0.01L, BGRAPHBIPARTFMTYPEBOUNDARY } };
106
107 static union {
108 BgraphBipartGgParam param;
109 StratNodeMethodData padding;
110 } bgraphbipartstdefaultgg = { { 5 } };
111
112 static union {
113 BgraphBipartGpParam param;
114 StratNodeMethodData padding;
115 } bgraphbipartstdefaultgp = { { 5 } };
116
117 static union {
118 BgraphBipartMlParam param;
119 StratNodeMethodData padding;
120 } bgraphbipartstdefaultml = { { 100, 0.8L, &stratdummy, &stratdummy } };
121
122 static StratMethodTab bgraphbipartstmethtab[] = { /* Bipartitioning methods array */
123 { BGRAPHBIPARTSTMETHBD, "b", bgraphBipartBd, &bgraphbipartstdefaultbd },
124 { BGRAPHBIPARTSTMETHDF, "d", bgraphBipartDf, &bgraphbipartstdefaultdf },
125 { BGRAPHBIPARTSTMETHEX, "x", bgraphBipartEx, NULL },
126 { BGRAPHBIPARTSTMETHFM, "f", bgraphBipartFm, &bgraphbipartstdefaultfm },
127 { BGRAPHBIPARTSTMETHGG, "h", bgraphBipartGg, &bgraphbipartstdefaultgg },
128 { BGRAPHBIPARTSTMETHGP, "g", bgraphBipartGp, &bgraphbipartstdefaultgp },
129 { BGRAPHBIPARTSTMETHML, "m", bgraphBipartMl, &bgraphbipartstdefaultml },
130 { BGRAPHBIPARTSTMETHZR, "z", bgraphBipartZr, NULL },
131 { -1, NULL, NULL, NULL } };
132
133 static StratParamTab bgraphbipartstparatab[] = { /* Method parameter list */
134 { BGRAPHBIPARTSTMETHBD, STRATPARAMSTRAT, "bnd",
135 (byte *) &bgraphbipartstdefaultbd.param,
136 (byte *) &bgraphbipartstdefaultbd.param.stratbnd,
137 (void *) &bgraphbipartststratab },
138 { BGRAPHBIPARTSTMETHBD, STRATPARAMSTRAT, "org",
139 (byte *) &bgraphbipartstdefaultbd.param,
140 (byte *) &bgraphbipartstdefaultbd.param.stratorg,
141 (void *) &bgraphbipartststratab },
142 { BGRAPHBIPARTSTMETHBD, STRATPARAMINT, "width",
143 (byte *) &bgraphbipartstdefaultbd.param,
144 (byte *) &bgraphbipartstdefaultbd.param.distmax,
145 NULL },
146 { BGRAPHBIPARTSTMETHDF, STRATPARAMINT, "pass",
147 (byte *) &bgraphbipartstdefaultdf.param,
148 (byte *) &bgraphbipartstdefaultdf.param.passnbr,
149 NULL },
150 { BGRAPHBIPARTSTMETHDF, STRATPARAMCASE, "type",
151 (byte *) &bgraphbipartstdefaultdf.param,
152 (byte *) &bgraphbipartstdefaultdf.param.typeval,
153 (void *) "bk" },
154 { BGRAPHBIPARTSTMETHFM, STRATPARAMINT, "move",
155 (byte *) &bgraphbipartstdefaultfm.param,
156 (byte *) &bgraphbipartstdefaultfm.param.movenbr,
157 NULL },
158 { BGRAPHBIPARTSTMETHFM, STRATPARAMINT, "pass",
159 (byte *) &bgraphbipartstdefaultfm.param,
160 (byte *) &bgraphbipartstdefaultfm.param.passnbr,
161 NULL },
162 { BGRAPHBIPARTSTMETHFM, STRATPARAMDOUBLE, "bal",
163 (byte *) &bgraphbipartstdefaultfm.param,
164 (byte *) &bgraphbipartstdefaultfm.param.deltval,
165 NULL },
166 { BGRAPHBIPARTSTMETHFM, STRATPARAMCASE, "type",
167 (byte *) &bgraphbipartstdefaultfm.param,
168 (byte *) &bgraphbipartstdefaultfm.param.typeval,
169 (void *) "ab" },
170 { BGRAPHBIPARTSTMETHGG, STRATPARAMINT, "pass",
171 (byte *) &bgraphbipartstdefaultgg.param,
172 (byte *) &bgraphbipartstdefaultgg.param.passnbr,
173 NULL },
174 { BGRAPHBIPARTSTMETHML, STRATPARAMSTRAT, "asc",
175 (byte *) &bgraphbipartstdefaultml.param,
176 (byte *) &bgraphbipartstdefaultml.param.stratasc,
177 (void *) &bgraphbipartststratab },
178 { BGRAPHBIPARTSTMETHML, STRATPARAMSTRAT, "low",
179 (byte *) &bgraphbipartstdefaultml.param,
180 (byte *) &bgraphbipartstdefaultml.param.stratlow,
181 (void *) &bgraphbipartststratab },
182 { BGRAPHBIPARTSTMETHML, STRATPARAMINT, "vert",
183 (byte *) &bgraphbipartstdefaultml.param,
184 (byte *) &bgraphbipartstdefaultml.param.coarnbr,
185 NULL },
186 { BGRAPHBIPARTSTMETHML, STRATPARAMDOUBLE, "rat",
187 (byte *) &bgraphbipartstdefaultml.param,
188 (byte *) &bgraphbipartstdefaultml.param.coarrat,
189 NULL },
190 { BGRAPHBIPARTSTMETHNBR, STRATPARAMINT, NULL,
191 NULL, NULL, NULL } };
192
193 static StratParamTab bgraphbipartstcondtab[] = { /* Active graph condition parameter table */
194 { STRATNODECOND, STRATPARAMDOUBLE, "bal",
195 (byte *) &bgraphdummy,
196 (byte *) &bgraphdummy.bbalval,
197 NULL },
198 { STRATNODECOND, STRATPARAMINT, "edge",
199 (byte *) &bgraphdummy,
200 (byte *) &bgraphdummy.s.edgenbr,
201 NULL },
202 { STRATNODECOND, STRATPARAMINT, "levl",
203 (byte *) &bgraphdummy,
204 (byte *) &bgraphdummy.levlnum,
205 NULL },
206 { STRATNODECOND, STRATPARAMINT, "lmin0",
207 (byte *) &bgraphdummy,
208 (byte *) &bgraphdummy.compload0min,
209 NULL },
210 { STRATNODECOND, STRATPARAMINT, "lmax0",
211 (byte *) &bgraphdummy,
212 (byte *) &bgraphdummy.compload0max,
213 NULL },
214 { STRATNODECOND, STRATPARAMINT, "load",
215 (byte *) &bgraphdummy,
216 (byte *) &bgraphdummy.s.velosum,
217 NULL },
218 { STRATNODECOND, STRATPARAMINT, "load0",
219 (byte *) &bgraphdummy,
220 (byte *) &bgraphdummy.compload0,
221 NULL },
222 { STRATNODECOND, STRATPARAMINT, "vert",
223 (byte *) &bgraphdummy,
224 (byte *) &bgraphdummy.s.vertnbr,
225 NULL },
226 { STRATNODENBR, STRATPARAMINT, NULL,
227 NULL, NULL, NULL } };
228
229 StratTab bgraphbipartststratab = { /* Strategy tables for graph bipartitioning methods */
230 bgraphbipartstmethtab,
231 bgraphbipartstparatab,
232 bgraphbipartstcondtab };
233
234 /***********************************************/
235 /* */
236 /* This is the generic bipartitioning routine. */
237 /* */
238 /***********************************************/
239
240 /* This routine performs the bipartitioning of
241 ** the given active graph according to the
242 ** given strategy.
243 ** It returns:
244 ** - 0 : if bipartitioning could be computed.
245 ** - 1 : on error.
246 */
247
248 int
bgraphBipartSt(Bgraph * restrict const grafptr,const Strat * restrict const strat)249 bgraphBipartSt (
250 Bgraph * restrict const grafptr, /*+ Active graph to bipartition +*/
251 const Strat * restrict const strat) /*+ Bipartitioning strategy +*/
252 {
253 StratTest val; /* Result of condition evaluation */
254 BgraphStore savetab[2]; /* Results of the two strategies */
255 int o;
256 int o2;
257
258 #ifdef SCOTCH_DEBUG_BGRAPH2
259 if (sizeof (Gnum) != sizeof (INT)) {
260 errorPrint ("bgraphBipartSt: invalid type specification for parser variables");
261 return (1);
262 }
263 if ((sizeof (BgraphBipartFmParam) > sizeof (StratNodeMethodData)) ||
264 (sizeof (BgraphBipartGgParam) > sizeof (StratNodeMethodData)) ||
265 (sizeof (BgraphBipartMlParam) > sizeof (StratNodeMethodData))) {
266 errorPrint ("bgraphBipartSt: invalid type specification");
267 return (1);
268 }
269 #endif /* SCOTCH_DEBUG_BGRAPH2 */
270 #ifdef SCOTCH_DEBUG_BGRAPH1
271 if (strat->tabl != &bgraphbipartststratab) {
272 errorPrint ("bgraphBipartSt: invalid parameter (1)");
273 return (1);
274 }
275 #endif /* SCOTCH_DEBUG_BGRAPH1 */
276
277 o = 0;
278 switch (strat->type) {
279 case STRATNODECONCAT :
280 o = bgraphBipartSt (grafptr, strat->data.concat.strat[0]); /* Apply the first strategy */
281 if (o == 0) /* If it worked all right */
282 o |= bgraphBipartSt (grafptr, strat->data.concat.strat[1]); /* Then apply second strategy */
283 break;
284 case STRATNODECOND :
285 o = stratTestEval (strat->data.cond.test, &val, (void *) grafptr); /* Evaluate expression */
286 if (o == 0) { /* If evaluation was correct */
287 #ifdef SCOTCH_DEBUG_VGRAPH2
288 if ((val.typetest != STRATTESTVAL) ||
289 (val.typenode != STRATPARAMLOG)) {
290 errorPrint ("bgraphBipartSt: invalid test result");
291 o = 1;
292 break;
293 }
294 #endif /* SCOTCH_DEBUG_VGRAPH2 */
295 if (val.data.val.vallog == 1) /* If expression is true */
296 o = bgraphBipartSt (grafptr, strat->data.cond.strat[0]); /* Apply first strategy */
297 else { /* Else if expression is false */
298 if (strat->data.cond.strat[1] != NULL) /* And if there is an else statement */
299 o = bgraphBipartSt (grafptr, strat->data.cond.strat[1]); /* Apply second strategy */
300 }
301 }
302 break;
303 case STRATNODEEMPTY :
304 break;
305 case STRATNODESELECT :
306 if (((bgraphStoreInit (grafptr, &savetab[0])) != 0) || /* Allocate save areas */
307 ((bgraphStoreInit (grafptr, &savetab[1])) != 0)) {
308 errorPrint ("bgraphBipartSt: out of memory");
309 bgraphStoreExit (&savetab[0]);
310 return (1);
311 }
312
313 bgraphStoreSave (grafptr, &savetab[1]); /* Save initial bipartition */
314 o = bgraphBipartSt (grafptr, strat->data.select.strat[0]); /* Apply first strategy */
315 bgraphStoreSave (grafptr, &savetab[0]); /* Save its result */
316 bgraphStoreUpdt (grafptr, &savetab[1]); /* Restore initial bipartition */
317 o2 = bgraphBipartSt (grafptr, strat->data.select.strat[1]); /* Apply second strategy */
318
319 if ((o == 0) || (o2 == 0)) { /* If at least one method did bipartition */
320 Gnum compload0;
321 int b0;
322 int b1;
323
324 compload0 = grafptr->compload0avg + savetab[0].compload0dlt;
325 b0 = ((compload0 < grafptr->compload0min) ||
326 (compload0 > grafptr->compload0max)) ? 1 : o;
327 compload0 = grafptr->compload0avg + savetab[1].compload0dlt;
328 b1 = ((compload0 < grafptr->compload0min) ||
329 (compload0 > grafptr->compload0max)) ? 1 : o2;
330
331 do { /* Do we want to restore partition 0 ? */
332 if (b0 > b1)
333 break;
334 if (b0 == b1) { /* If both are valid or invalid */
335 if (b0 == 0) { /* If both are valid */
336 if ( (savetab[0].commload > grafptr->commload) || /* Compare on cut */
337 ((savetab[0].commload == grafptr->commload) &&
338 (abs (savetab[0].compload0dlt) > abs (grafptr->compload0dlt))))
339 break;
340 }
341 else { /* If both are invalid */
342 if ( (abs (savetab[0].compload0dlt) > abs (grafptr->compload0dlt)) || /* Compare on imbalance */
343 ((abs (savetab[0].compload0dlt) == abs (grafptr->compload0dlt)) &&
344 (savetab[0].commload > grafptr->commload)))
345 break;
346 }
347 }
348
349 bgraphStoreUpdt (grafptr, &savetab[0]); /* Restore its result */
350 } while (0);
351 }
352 if (o2 < o) /* o = min(o,o2): if one biparts, then bipart */
353 o = o2; /* Else if one stops, then stop, else error */
354
355 bgraphStoreExit (&savetab[0]); /* Free both save areas */
356 bgraphStoreExit (&savetab[1]);
357 break;
358 #ifdef SCOTCH_DEBUG_BGRAPH2
359 case STRATNODEMETHOD :
360 #else /* SCOTCH_DEBUG_BGRAPH2 */
361 default :
362 #endif /* SCOTCH_DEBUG_BGRAPH2 */
363 return (strat->tabl->methtab[strat->data.method.meth].func (grafptr, (void *) &strat->data.method.data));
364 #ifdef SCOTCH_DEBUG_BGRAPH2
365 default :
366 errorPrint ("bgraphBipartSt: invalid parameter (2)");
367 return (1);
368 #endif /* SCOTCH_DEBUG_BGRAPH2 */
369 }
370 return (o);
371 }
372