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