~ubuntu-branches/ubuntu/trusty/scotch/trusty

« back to all changes in this revision

Viewing changes to src/libscotch/graph_induce.c

  • Committer: Bazaar Package Importer
  • Author(s): Christophe Prud'homme
  • Date: 2008-01-25 09:13:53 UTC
  • Revision ID: james.westby@ubuntu.com-20080125091353-zghdao60dfsyc2bt
Tags: upstream-5.0.1.dfsg
ImportĀ upstreamĀ versionĀ 5.0.1.dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2004,2007 ENSEIRB, 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       : graph_induce.c                          **/
 
35
/**                                                        **/
 
36
/**   AUTHOR     : Francois PELLEGRINI                     **/
 
37
/**                                                        **/
 
38
/**   FUNCTION   : This module handles the source graph    **/
 
39
/**                subgraph-making functions.              **/
 
40
/**                                                        **/
 
41
/**   DATES      : # Version 0.0  : from : 01 dec 1992     **/
 
42
/**                                 to     18 may 1993     **/
 
43
/**                # Version 1.3  : from : 30 apr 1994     **/
 
44
/**                                 to     18 may 1994     **/
 
45
/**                # Version 2.0  : from : 06 jun 1994     **/
 
46
/**                                 to     31 oct 1994     **/
 
47
/**                # Version 3.0  : from : 07 jul 1995     **/
 
48
/**                                 to     28 sep 1995     **/
 
49
/**                # Version 3.1  : from : 28 nov 1995     **/
 
50
/**                                 to     08 jun 1996     **/
 
51
/**                # Version 3.2  : from : 07 sep 1996     **/
 
52
/**                                 to     17 sep 1998     **/
 
53
/**                # Version 4.0  : from : 28 nov 2001     **/
 
54
/**                                 to     17 apr 2006     **/
 
55
/**                # Version 5.0  : from : 14 dec 2006     **/
 
56
/**                                 to     10 sep 2007     **/
 
57
/**                                                        **/
 
58
/**   NOTES      : # Several algorithms, such as the       **/
 
59
/**                  active graph building routine of      **/
 
60
/**                  bgraphInit2, assume that, for every   **/
 
61
/**                  vertex, remaining edges will be kept  **/
 
62
/**                  in the same order as in the original  **/
 
63
/**                  graph. This must be enforced.         **/
 
64
/**                                                        **/
 
65
/************************************************************/
 
66
 
 
67
/*
 
68
**  The defines and includes.
 
69
*/
 
70
 
 
71
#define GRAPH
 
72
#define GRAPH_INDUCE
 
73
 
 
74
#include "module.h"
 
75
#include "common.h"
 
76
#include "graph.h"
 
77
#include "graph_induce.h"
 
78
 
 
79
/****************************************/
 
80
/*                                      */
 
81
/* These routines handle source graphs. */
 
82
/*                                      */
 
83
/****************************************/
 
84
 
 
85
/* This routine builds the graph induced
 
86
** by the original graph and the list of
 
87
** selected vertices.
 
88
** The induced vnumtab array is the list
 
89
** array if the original graph does not have
 
90
** a vnumtab, or the proper subset of the
 
91
** original vnumtab else.
 
92
** It returns:
 
93
** - 0   : on success.
 
94
** - !0  : on error.
 
95
*/
 
96
 
 
97
int
 
98
graphInduceList (
 
99
const Graph * restrict const    orggrafptr,
 
100
const VertList * restrict const indlistptr,
 
101
Graph * restrict const          indgrafptr)
 
102
{
 
103
  Gnum * restrict     orgindxtax;                 /* Based access to vertex translation array       */
 
104
  Gnum                indvertnbr;                 /* Number of vertices in induced graph            */
 
105
  Gnum                indvertnum;                 /* Number of current vertex in induced graph      */
 
106
  Gnum * restrict     indedgetab;                 /* Pointer to pre-allocated edge array            */
 
107
  Gnum                indedgenbr;                 /* (Approximate) number of edges in induced graph */
 
108
 
 
109
  memSet (indgrafptr, 0, sizeof (Graph));         /* Initialize graph fields */
 
110
  indgrafptr->flagval = GRAPHFREETABS | GRAPHVERTGROUP | GRAPHEDGEGROUP;
 
111
  indgrafptr->baseval = orggrafptr->baseval;
 
112
 
 
113
  indvertnbr = indlistptr->vnumnbr;
 
114
 
 
115
  if (orggrafptr->velotax != NULL) {
 
116
    if (memAllocGroup ((void **) (void *)
 
117
          &indgrafptr->verttax, (size_t) ((indvertnbr + 1) * sizeof (Gnum)),
 
118
          &indgrafptr->vnumtax, (size_t) ( indvertnbr      * sizeof (Gnum)),
 
119
          &indgrafptr->velotax, (size_t) ( indvertnbr      * sizeof (Gnum)), NULL) == NULL) {
 
120
      errorPrint ("graphInduceList: out of memory (1)");
 
121
      return     (1);                             /* Nothing to free because group allocation failed */
 
122
    }
 
123
    indgrafptr->velotax -= indgrafptr->baseval;
 
124
  }
 
125
  else {
 
126
    if (memAllocGroup ((void **) (void *)
 
127
          &indgrafptr->verttax, (size_t) ((indvertnbr + 1) * sizeof (Gnum)),
 
128
          &indgrafptr->vnumtax, (size_t) ( indvertnbr      * sizeof (Gnum)), NULL) == NULL) {
 
129
      errorPrint ("graphInduceList: out of memory (2)");
 
130
      return     (1);
 
131
    }
 
132
  }
 
133
  indgrafptr->verttax -= indgrafptr->baseval;     /* Adjust base of arrays */
 
134
  indgrafptr->vnumtax -= indgrafptr->baseval;
 
135
  indgrafptr->vertnbr  = indvertnbr;
 
136
  indgrafptr->vertnnd  = indvertnbr + indgrafptr->baseval;
 
137
 
 
138
  indedgenbr = ((indvertnbr * orggrafptr->degrmax) < orggrafptr->edgenbr) /* Choose best upper bound on number of edges */
 
139
               ? (indvertnbr * orggrafptr->degrmax) : orggrafptr->edgenbr;
 
140
  if (orggrafptr->edlotax != NULL)                /* If graph has edge weights */
 
141
    indedgenbr *= 2;                              /* Account for edge weights  */
 
142
 
 
143
  if (memAllocGroup ((void *)
 
144
        &indedgetab, (size_t) (indedgenbr          * sizeof (Gnum)), /* Pre-allocate space for edgetab (and edlotab)          */
 
145
        &orgindxtax, (size_t) (orggrafptr->vertnbr * sizeof (Gnum)), NULL) == NULL) { /* orgindxtab is at the end of the heap */
 
146
    errorPrint ("graphInduceList: out of memory (3)");
 
147
    graphExit  (indgrafptr);
 
148
    return     (1);
 
149
  }
 
150
 
 
151
/* TODO: Vertex list can be kept as it is the one of *graphOrderNd */
 
152
 
 
153
  memCpy (indgrafptr->vnumtax + indgrafptr->baseval, /* Copy vertex number array from list */
 
154
          indlistptr->vnumtab, indvertnbr * sizeof (Gnum));
 
155
 
 
156
  memSet (orgindxtax, ~0, orggrafptr->vertnbr * sizeof (Gnum)); /* Preset index array */
 
157
  orgindxtax -= orggrafptr->baseval;
 
158
 
 
159
  for (indvertnum = indgrafptr->baseval, indedgenbr = 0; /* Fill index array */
 
160
       indvertnum < indgrafptr->baseval + indvertnbr; indvertnum ++) {
 
161
    Gnum                orgvertnum;
 
162
 
 
163
    orgvertnum = indgrafptr->vnumtax[indvertnum];
 
164
 
 
165
    orgindxtax[orgvertnum] = indvertnum;          /* Mark selected vertices */
 
166
    indedgenbr += orggrafptr->vendtax[orgvertnum] - orggrafptr->verttax[orgvertnum];
 
167
  }
 
168
 
 
169
  return (graphInduce2 (orggrafptr, indgrafptr, indvertnbr, indedgenbr, indedgetab, orgindxtax));
 
170
}
 
171
 
 
172
/* This routine builds the graph induced
 
173
** by the original graph and the vector
 
174
** of selected vertices.
 
175
** The induced vnumtab array is the list of
 
176
** selected vertices if the original graph
 
177
** does not have a vnumtab, or the proper
 
178
** subset of the original vnumtab else.
 
179
** It returns:
 
180
** - 0   : on success.
 
181
** - !0  : on error.
 
182
*/
 
183
 
 
184
int
 
185
graphInducePart (
 
186
const Graph * restrict const  orggrafptr,         /* Pointer to original graph             */
 
187
const GraphPart * const       orgparttax,         /* Based array of vertex partition flags */
 
188
const Gnum                    indvertnbr,         /* Number of vertices in selected part   */
 
189
const GraphPart               indpartval,         /* Partition value of vertices to keep   */
 
190
Graph * restrict const        indgrafptr)         /* Pointer to induced subgraph           */
 
191
{
 
192
  Gnum * restrict             orgindxtab;         /* Original to induced vertex translation array   */
 
193
  Gnum * restrict             orgindxtax;         /* Based access to vertex translation array       */
 
194
  Gnum                        indvertnum;         /* Number of current vertex in induced graph      */
 
195
  Gnum * restrict             indedgetab;         /* Pointer to pre-allocated edge array            */
 
196
  Gnum                        indedgenbr;         /* (Approximate) number of edges in induced graph */
 
197
  Gnum                        orgvertnum;
 
198
 
 
199
  memSet (indgrafptr, 0, sizeof (Graph));         /* Initialize graph fields */
 
200
  indgrafptr->flagval = GRAPHFREETABS | GRAPHVERTGROUP | GRAPHEDGEGROUP;
 
201
  indgrafptr->baseval = orggrafptr->baseval;
 
202
 
 
203
  indedgenbr = ((indvertnbr * orggrafptr->degrmax) < orggrafptr->edgenbr) /* Choose best upper bound on number of edges */
 
204
               ? (indvertnbr * orggrafptr->degrmax) : orggrafptr->edgenbr;
 
205
  if (orggrafptr->edlotax != NULL)                /* If graph has edge weights */
 
206
    indedgenbr *= 2;                              /* Account for edge weights  */
 
207
 
 
208
  if (orggrafptr->velotax != NULL) {
 
209
    if (memAllocGroup ((void **) (void *)
 
210
          &indgrafptr->verttax, (size_t) ((indvertnbr + 1) * sizeof (Gnum)),
 
211
          &indgrafptr->vnumtax, (size_t) ( indvertnbr      * sizeof (Gnum)),
 
212
          &indgrafptr->velotax, (size_t) ( indvertnbr      * sizeof (Gnum)), NULL) == NULL) {
 
213
      errorPrint ("graphInducePart: out of memory (1)");
 
214
      return     (1);                             /* Nothing to free because group allocation failed */
 
215
    }
 
216
    indgrafptr->velotax -= indgrafptr->baseval;
 
217
  }
 
218
  else {
 
219
    if (memAllocGroup ((void **) (void *)
 
220
          &indgrafptr->verttax, (size_t) ((indvertnbr + 1) * sizeof (Gnum)),
 
221
          &indgrafptr->vnumtax, (size_t) ( indvertnbr      * sizeof (Gnum)), NULL) == NULL) {
 
222
      errorPrint ("graphInducePart: out of memory (2)");
 
223
      return     (1);
 
224
    }
 
225
  }
 
226
  indgrafptr->verttax -= indgrafptr->baseval;     /* Adjust base of arrays */
 
227
  indgrafptr->vnumtax -= indgrafptr->baseval;
 
228
  indgrafptr->vertnbr  = indvertnbr;
 
229
  indgrafptr->vertnnd  = indvertnbr + indgrafptr->baseval;
 
230
 
 
231
  if (memAllocGroup ((void *)
 
232
        &indedgetab, (size_t) (indedgenbr          * sizeof (Gnum)), /* Pre-allocate space for edgetab (and edlotab)          */
 
233
        &orgindxtab, (size_t) (orggrafptr->vertnbr * sizeof (Gnum)), NULL) == NULL) { /* orgindxtab is at the end of the heap */
 
234
    errorPrint ("graphInducePart: out of memory (3)");
 
235
    graphExit  (indgrafptr);
 
236
    return     (1);
 
237
  }
 
238
  orgindxtax = orgindxtab - orggrafptr->baseval;
 
239
 
 
240
  for (indvertnum = indgrafptr->baseval, indedgenbr = 0, orgvertnum = orggrafptr->baseval; /* Fill index array */
 
241
       orgvertnum < orggrafptr->vertnnd; orgvertnum ++) {
 
242
    if (orgparttax[orgvertnum] == indpartval) {   /* If vertex should be kept */
 
243
      orgindxtax[orgvertnum] = indvertnum;        /* Mark selected vertex     */
 
244
      indgrafptr->vnumtax[indvertnum] = orgvertnum;
 
245
      indedgenbr += orggrafptr->vendtax[orgvertnum] - orggrafptr->verttax[orgvertnum];
 
246
      indvertnum ++;                              /* One more induced vertex created */
 
247
    }
 
248
    else
 
249
      orgindxtax[orgvertnum] = ~0;
 
250
  }
 
251
#ifdef SCOTCH_DEBUG_GRAPH2
 
252
  if ((indvertnum - indgrafptr->baseval) != indvertnbr) {
 
253
    errorPrint ("graphInducePart: inconsistent data");
 
254
    memFree    (indedgetab);
 
255
    graphExit  (indgrafptr);
 
256
    return     (1);
 
257
  }
 
258
#endif /* SCOTCH_DEBUG_GRAPH2 */
 
259
 
 
260
  return (graphInduce2 (orggrafptr, indgrafptr, indvertnbr, indedgenbr, indedgetab, orgindxtax));
 
261
}
 
262
 
 
263
/* This routine finalizes the building
 
264
** of the induced subgraph.
 
265
** It returns:
 
266
** - 0   : on success.
 
267
** - !0  : on error.
 
268
*/
 
269
 
 
270
static
 
271
int
 
272
graphInduce2 (
 
273
const Graph * restrict const  orggrafptr,         /* Pointer to original graph                          */
 
274
Graph * restrict const        indgrafptr,         /* Pointer to induced graph                           */
 
275
const Gnum                    indvertnbr,         /* Number of vertices in induced graph                */
 
276
const Gnum                    indedgenbr,         /* (Upper bound of) number of edges in induced graph  */
 
277
Gnum * restrict const         indedgetab,         /* Pointer to pre-allocated edge and edge load arrays */
 
278
const Gnum * restrict const   orgindxtax)         /* Array of numbers of selected vertices              */
 
279
{
 
280
  Gnum                indvertnum;                 /* Current induced vertex number              */
 
281
  Gnum                indvelosum;                 /* Overall induced vertex load                */
 
282
  Gnum                indedlosum;                 /* Overall induced edge load                  */
 
283
  Gnum                indedgenum;                 /* Number of current induced edge             */
 
284
  Gnum                orgvertnum;                 /* Number of current vertex in original graph */
 
285
  Gnum                orgedgenum;                 /* Number of current edge in original graph   */
 
286
 
 
287
  if (orggrafptr->edlotax != NULL) {
 
288
    memOffset ((void *) indedgetab,
 
289
               &indgrafptr->edgetax, (size_t) (indedgenbr * sizeof (Gnum)),
 
290
               &indgrafptr->edlotax, (size_t) (indedgenbr * sizeof (Gnum)), NULL);
 
291
    indgrafptr->edgetax -= indgrafptr->baseval;
 
292
    indgrafptr->edlotax -= indgrafptr->baseval;
 
293
  }
 
294
  else
 
295
    indgrafptr->edgetax = indedgetab - indgrafptr->baseval;
 
296
 
 
297
  indvelosum = (indgrafptr->velotax == NULL) ? indgrafptr->vertnbr : 0;
 
298
  indedlosum = 0;
 
299
  for (indvertnum = indedgenum = indgrafptr->baseval;
 
300
       indvertnum < indgrafptr->vertnnd; indvertnum ++) {
 
301
    orgvertnum = indgrafptr->vnumtax[indvertnum];
 
302
    indgrafptr->verttax[indvertnum] = indedgenum;
 
303
    if (indgrafptr->velotax != NULL) {            /* If graph has vertex weights */
 
304
      indvelosum +=                               /* Accumulate vertex loads     */
 
305
      indgrafptr->velotax[indvertnum] = orggrafptr->velotax[orgvertnum];
 
306
    }
 
307
 
 
308
    if (indgrafptr->edlotax != NULL) {            /* If graph has edge weights */
 
309
      for (orgedgenum = orggrafptr->verttax[orgvertnum];
 
310
           orgedgenum < orggrafptr->vendtax[orgvertnum]; orgedgenum ++) {
 
311
        if (orgindxtax[orggrafptr->edgetax[orgedgenum]] != ~0) { /* If edge should be kept */
 
312
          indedlosum                     +=
 
313
          indgrafptr->edlotax[indedgenum] = orggrafptr->edlotax[orgedgenum];
 
314
          indgrafptr->edgetax[indedgenum] = orgindxtax[orggrafptr->edgetax[orgedgenum]];
 
315
          indedgenum ++;
 
316
        }
 
317
      }
 
318
    }
 
319
    else {
 
320
      for (orgedgenum = orggrafptr->verttax[orgvertnum];
 
321
           orgedgenum < orggrafptr->vendtax[orgvertnum]; orgedgenum ++) {
 
322
        if (orgindxtax[orggrafptr->edgetax[orgedgenum]] != ~0) { /* If edge should be kept */
 
323
          indgrafptr->edgetax[indedgenum] = orgindxtax[orggrafptr->edgetax[orgedgenum]];
 
324
          indedgenum ++;
 
325
        }
 
326
      }
 
327
    }
 
328
  }
 
329
  indgrafptr->verttax[indvertnum] = indedgenum;   /* Mark end of edge array                      */
 
330
  indgrafptr->vendtax  = indgrafptr->verttax + 1; /* Use compact representation of vertex arrays */
 
331
  indgrafptr->vertnbr = indvertnum - indgrafptr->baseval;
 
332
  indgrafptr->vertnnd = indvertnum;
 
333
  indgrafptr->velosum = indvelosum;
 
334
  indgrafptr->edgenbr = indedgenum - indgrafptr->baseval; /* Set actual number of edges */
 
335
  indgrafptr->edlosum = (indgrafptr->edlotax != NULL) ? indedlosum : indgrafptr->edgenbr;
 
336
  indgrafptr->degrmax = orggrafptr->degrmax;      /* Induced maximum degree is likely to be the one of the original graph */
 
337
 
 
338
  if (indgrafptr->edlotax != NULL) {              /* Re-allocate arrays and delete orgindxtab             */
 
339
    size_t              indedlooftval;            /* Offset of edge load array with respect to edge array */
 
340
 
 
341
    indedlooftval = indgrafptr->edlotax - indgrafptr->edgetax;
 
342
    indgrafptr->edgetax  = memRealloc (indgrafptr->edgetax + indgrafptr->baseval, (indedlooftval + indgrafptr->edgenbr) * sizeof (Gnum));
 
343
    indgrafptr->edgetax -= indgrafptr->baseval;
 
344
    indgrafptr->edlotax  = indgrafptr->edgetax + indedlooftval; /* Use old index into old array as new index */
 
345
  }
 
346
  else {
 
347
    indgrafptr->edgetax  = memRealloc (indgrafptr->edgetax + indgrafptr->baseval, indgrafptr->edgenbr * sizeof (Gnum));
 
348
    indgrafptr->edgetax -= indgrafptr->baseval;
 
349
  }
 
350
 
 
351
  if (orggrafptr->vnumtax != NULL) {              /* Adjust vnumtax */
 
352
    for (indvertnum = indgrafptr->baseval; indvertnum < indgrafptr->vertnnd; indvertnum ++)
 
353
      indgrafptr->vnumtax[indvertnum] = orggrafptr->vnumtax[indgrafptr->vnumtax[indvertnum]];
 
354
  }
 
355
 
 
356
#ifdef SCOTCH_DEBUG_GRAPH2
 
357
  if (graphCheck (indgrafptr) != 0) {             /* Check graph consistency */
 
358
    errorPrint ("graphInduce2: inconsistent graph data");
 
359
    graphExit  (indgrafptr);
 
360
    return     (1);
 
361
  }
 
362
#endif /* SCOTCH_DEBUG_GRAPH2 */
 
363
 
 
364
  return (0);
 
365
}