The R Project SVN R-packages

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
155 bates 1
/*
2
 * Copyright 1997, Regents of the University of Minnesota
3
 *
4
 * pqueue.c
5
 *
6
 * This file contains functions for manipulating the bucket list
7
 * representation of the gains associated with each vertex in a graph.
8
 * These functions are used by the refinement algorithms
9
 *
10
 * Started 9/2/94
11
 * George
12
 *
13
 * $Id: pqueue.c,v 1.1 2003/12/31 21:32:30 bates Exp $
14
 *
15
 */
16
 
17
#include <metis.h>
18
 
19
 
20
/*************************************************************************
21
* This function initializes the data structures of the priority queue
22
**************************************************************************/
23
void PQueueInit(CtrlType *ctrl, PQueueType *queue, int maxnodes, int maxgain)
24
{
25
  int i, j, ncore;
26
 
27
  queue->nnodes = 0;
28
  queue->maxnodes = maxnodes;
29
 
30
  queue->buckets = NULL;
31
  queue->nodes = NULL;
32
  queue->heap = NULL;
33
  queue->locator = NULL;
34
 
35
  if (maxgain > PLUS_GAINSPAN || maxnodes < 500)
36
    queue->type = 2;
37
  else
38
    queue->type = 1;
39
 
40
  if (queue->type == 1) {
41
    queue->pgainspan = amin(PLUS_GAINSPAN, maxgain);
42
    queue->ngainspan = amin(NEG_GAINSPAN, maxgain);
43
 
44
    j = queue->ngainspan+queue->pgainspan+1;
45
 
46
    ncore = 2 + (sizeof(ListNodeType)/sizeof(idxtype))*maxnodes + (sizeof(ListNodeType *)/sizeof(idxtype))*j;
47
 
48
    if (WspaceAvail(ctrl) > ncore) {
49
      queue->nodes = (ListNodeType *)idxwspacemalloc(ctrl, (sizeof(ListNodeType)/sizeof(idxtype))*maxnodes);
50
      queue->buckets = (ListNodeType **)idxwspacemalloc(ctrl, (sizeof(ListNodeType *)/sizeof(idxtype))*j);
51
      queue->mustfree = 0;
52
    }
53
    else { /* Not enough memory in the wspace, allocate it */
54
      queue->nodes = (ListNodeType *)idxmalloc((sizeof(ListNodeType)/sizeof(idxtype))*maxnodes, "PQueueInit: queue->nodes");
55
      queue->buckets = (ListNodeType **)idxmalloc((sizeof(ListNodeType *)/sizeof(idxtype))*j, "PQueueInit: queue->buckets");
56
      queue->mustfree = 1;
57
    }
58
 
59
    for (i=0; i<maxnodes; i++) 
60
      queue->nodes[i].id = i;
61
 
62
    for (i=0; i<j; i++)
63
      queue->buckets[i] = NULL;
64
 
65
    queue->buckets += queue->ngainspan;  /* Advance buckets by the ngainspan proper indexing */
66
    queue->maxgain = -queue->ngainspan;
67
  }
68
  else {
69
    queue->heap = (KeyValueType *)idxwspacemalloc(ctrl, (sizeof(KeyValueType)/sizeof(idxtype))*maxnodes);
70
    queue->locator = idxwspacemalloc(ctrl, maxnodes);
71
    idxset(maxnodes, -1, queue->locator);
72
  }
73
 
74
}
75
 
76
 
77
/*************************************************************************
78
* This function resets the buckets
79
**************************************************************************/
80
void PQueueReset(PQueueType *queue)
81
{
82
  int i, j;
83
  queue->nnodes = 0;
84
 
85
  if (queue->type == 1) {
86
    queue->maxgain = -queue->ngainspan;
87
 
88
    j = queue->ngainspan+queue->pgainspan+1;
89
    queue->buckets -= queue->ngainspan;  
90
    for (i=0; i<j; i++)
91
      queue->buckets[i] = NULL;
92
    queue->buckets += queue->ngainspan;  
93
  }
94
  else {
95
    idxset(queue->maxnodes, -1, queue->locator);
96
  }
97
 
98
}
99
 
100
 
101
/*************************************************************************
102
* This function frees the buckets
103
**************************************************************************/
104
void PQueueFree(CtrlType *ctrl, PQueueType *queue)
105
{
106
 
107
  if (queue->type == 1) {
108
    if (queue->mustfree) {
109
      queue->buckets -= queue->ngainspan;  
110
      GKfree(&queue->nodes, &queue->buckets, LTERM);
111
    } 
112
    else {
113
      idxwspacefree(ctrl, sizeof(ListNodeType *)*(queue->ngainspan+queue->pgainspan+1)/sizeof(idxtype));
114
      idxwspacefree(ctrl, sizeof(ListNodeType)*queue->maxnodes/sizeof(idxtype));
115
    }
116
  }
117
  else {
118
    idxwspacefree(ctrl, sizeof(KeyValueType)*queue->maxnodes/sizeof(idxtype));
119
    idxwspacefree(ctrl, queue->maxnodes);
120
  }
121
 
122
  queue->maxnodes = 0;
123
}
124
 
125
 
126
/*************************************************************************
127
* This function returns the number of nodes in the queue
128
**************************************************************************/
129
int PQueueGetSize(PQueueType *queue)
130
{
131
  return queue->nnodes;
132
}
133
 
134
 
135
/*************************************************************************
136
* This function adds a node of certain gain into a partition
137
**************************************************************************/
138
int PQueueInsert(PQueueType *queue, int node, int gain)
139
{
1128 bates 140
  int i, j/* , k */;
155 bates 141
  idxtype *locator;
142
  ListNodeType *newnode;
143
  KeyValueType *heap;
144
 
145
  if (queue->type == 1) {
146
    ASSERT(gain >= -queue->ngainspan && gain <= queue->pgainspan);
147
 
148
    /* Allocate and add the node */
149
    queue->nnodes++;
150
    newnode = queue->nodes + node;
151
 
152
    /* Attach this node in the doubly-linked list */
153
    newnode->next = queue->buckets[gain];
154
    newnode->prev = NULL;
155
    if (newnode->next != NULL)
156
      newnode->next->prev = newnode;
157
    queue->buckets[gain] = newnode;
158
 
159
    if (queue->maxgain < gain)
160
      queue->maxgain = gain;
161
  }
162
  else {
163
    ASSERT(CheckHeap(queue));
164
 
165
    heap = queue->heap;
166
    locator = queue->locator;
167
 
168
    ASSERT(locator[node] == -1);
169
 
170
    i = queue->nnodes++;
171
    while (i > 0) {
172
      j = (i-1)/2;
173
      if (heap[j].key < gain) {
174
        heap[i] = heap[j];
175
        locator[heap[i].val] = i;
176
        i = j;
177
      }
178
      else 
179
        break;
180
    }
181
    ASSERT(i >= 0);
182
    heap[i].key = gain;
183
    heap[i].val = node;
184
    locator[node] = i;
185
 
186
    ASSERT(CheckHeap(queue));
187
  }
188
 
189
  return 0;
190
}
191
 
192
 
193
/*************************************************************************
194
* This function deletes a node from a partition and reinserts it with
195
* an updated gain
196
**************************************************************************/
197
int PQueueDelete(PQueueType *queue, int node, int gain)
198
{
199
  int i, j, newgain, oldgain;
200
  idxtype *locator;
201
  ListNodeType *newnode, **buckets;
202
  KeyValueType *heap;
203
 
204
  if (queue->type == 1) {
205
    ASSERT(gain >= -queue->ngainspan && gain <= queue->pgainspan);
206
    ASSERT(queue->nnodes > 0);
207
 
208
    buckets = queue->buckets;
209
    queue->nnodes--;
210
    newnode = queue->nodes+node;
211
 
212
    /* Remove newnode from the doubly-linked list */
213
    if (newnode->prev != NULL)
214
      newnode->prev->next = newnode->next;
215
    else
216
      buckets[gain] = newnode->next;
217
    if (newnode->next != NULL)
218
      newnode->next->prev = newnode->prev;
219
 
220
    if (buckets[gain] == NULL && gain == queue->maxgain) {
221
      if (queue->nnodes == 0) 
222
        queue->maxgain = -queue->ngainspan;
223
      else 
224
        for (; buckets[queue->maxgain]==NULL; queue->maxgain--);
225
    }
226
  }
227
  else { /* Heap Priority Queue */
228
    heap = queue->heap;
229
    locator = queue->locator;
230
 
231
    ASSERT(locator[node] != -1);
232
    ASSERT(heap[locator[node]].val == node);
233
 
234
    ASSERT(CheckHeap(queue));
235
 
236
    i = locator[node];
237
    locator[node] = -1;
238
 
239
    if (--queue->nnodes > 0 && heap[queue->nnodes].val != node) {
240
      node = heap[queue->nnodes].val;
241
      newgain = heap[queue->nnodes].key;
242
      oldgain = heap[i].key;
243
 
244
      if (oldgain < newgain) { /* Filter-up */
245
        while (i > 0) {
246
          j = (i-1)>>1;
247
          if (heap[j].key < newgain) {
248
            heap[i] = heap[j];
249
            locator[heap[i].val] = i;
250
            i = j;
251
          }
252
          else 
253
            break;
254
        }
255
      }
256
      else { /* Filter down */
257
        while ((j=2*i+1) < queue->nnodes) {
258
          if (heap[j].key > newgain) {
259
            if (j+1 < queue->nnodes && heap[j+1].key > heap[j].key)
260
              j = j+1;
261
            heap[i] = heap[j];
262
            locator[heap[i].val] = i;
263
            i = j;
264
          }
265
          else if (j+1 < queue->nnodes && heap[j+1].key > newgain) {
266
            j = j+1;
267
            heap[i] = heap[j];
268
            locator[heap[i].val] = i;
269
            i = j;
270
          }
271
          else
272
            break;
273
        }
274
      }
275
 
276
      heap[i].key = newgain;
277
      heap[i].val = node;
278
      locator[node] = i;
279
    }
280
 
281
    ASSERT(CheckHeap(queue));
282
  }
283
 
284
  return 0;
285
}
286
 
287
 
288
 
289
/*************************************************************************
290
* This function deletes a node from a partition and reinserts it with
291
* an updated gain
292
**************************************************************************/
293
int PQueueUpdate(PQueueType *queue, int node, int oldgain, int newgain)
294
{
295
  int i, j;
296
  idxtype *locator;
1128 bates 297
/*   ListNodeType *newnode; */
155 bates 298
  KeyValueType *heap;
299
 
300
  if (oldgain == newgain) 
301
    return 0;
302
 
303
  if (queue->type == 1) {
304
    /* First delete the node and then insert it */
305
    PQueueDelete(queue, node, oldgain);
306
    return PQueueInsert(queue, node, newgain);
307
  }
308
  else { /* Heap Priority Queue */
309
    heap = queue->heap;
310
    locator = queue->locator;
311
 
312
    ASSERT(locator[node] != -1);
313
    ASSERT(heap[locator[node]].val == node);
314
    ASSERT(heap[locator[node]].key == oldgain);
315
    ASSERT(CheckHeap(queue));
316
 
317
    i = locator[node];
318
 
319
    if (oldgain < newgain) { /* Filter-up */
320
      while (i > 0) {
321
        j = (i-1)>>1;
322
        if (heap[j].key < newgain) {
323
          heap[i] = heap[j];
324
          locator[heap[i].val] = i;
325
          i = j;
326
        }
327
        else 
328
          break;
329
      }
330
    }
331
    else { /* Filter down */
332
      while ((j=2*i+1) < queue->nnodes) {
333
        if (heap[j].key > newgain) {
334
          if (j+1 < queue->nnodes && heap[j+1].key > heap[j].key)
335
            j = j+1;
336
          heap[i] = heap[j];
337
          locator[heap[i].val] = i;
338
          i = j;
339
        }
340
        else if (j+1 < queue->nnodes && heap[j+1].key > newgain) {
341
          j = j+1;
342
          heap[i] = heap[j];
343
          locator[heap[i].val] = i;
344
          i = j;
345
        }
346
        else
347
          break;
348
      }
349
    }
350
 
351
    heap[i].key = newgain;
352
    heap[i].val = node;
353
    locator[node] = i;
354
 
355
    ASSERT(CheckHeap(queue));
356
  }
357
 
358
  return 0;
359
}
360
 
361
 
362
 
363
/*************************************************************************
364
* This function deletes a node from a partition and reinserts it with
365
* an updated gain
366
**************************************************************************/
367
void PQueueUpdateUp(PQueueType *queue, int node, int oldgain, int newgain)
368
{
369
  int i, j;
370
  idxtype *locator;
371
  ListNodeType *newnode, **buckets;
372
  KeyValueType *heap;
373
 
374
  if (oldgain == newgain) 
375
    return;
376
 
377
  if (queue->type == 1) {
378
    ASSERT(oldgain >= -queue->ngainspan && oldgain <= queue->pgainspan);
379
    ASSERT(newgain >= -queue->ngainspan && newgain <= queue->pgainspan);
380
    ASSERT(queue->nnodes > 0);
381
 
382
    buckets = queue->buckets;
383
    newnode = queue->nodes+node;
384
 
385
    /* First delete the node */
386
    if (newnode->prev != NULL)
387
      newnode->prev->next = newnode->next;
388
    else
389
      buckets[oldgain] = newnode->next;
390
    if (newnode->next != NULL)
391
      newnode->next->prev = newnode->prev;
392
 
393
    /* Attach this node in the doubly-linked list */
394
    newnode->next = buckets[newgain];
395
    newnode->prev = NULL;
396
    if (newnode->next != NULL)
397
      newnode->next->prev = newnode;
398
    buckets[newgain] = newnode;
399
 
400
    if (queue->maxgain < newgain)
401
      queue->maxgain = newgain;
402
  }
403
  else { /* Heap Priority Queue */
404
    heap = queue->heap;
405
    locator = queue->locator;
406
 
407
    ASSERT(locator[node] != -1);
408
    ASSERT(heap[locator[node]].val == node);
409
    ASSERT(heap[locator[node]].key == oldgain);
410
    ASSERT(CheckHeap(queue));
411
 
412
 
413
    /* Here we are just filtering up since the newgain is greater than the oldgain */
414
    i = locator[node];
415
    while (i > 0) {
416
      j = (i-1)>>1;
417
      if (heap[j].key < newgain) {
418
        heap[i] = heap[j];
419
        locator[heap[i].val] = i;
420
        i = j;
421
      }
422
      else 
423
        break;
424
    }
425
 
426
    heap[i].key = newgain;
427
    heap[i].val = node;
428
    locator[node] = i;
429
 
430
    ASSERT(CheckHeap(queue));
431
  }
432
 
433
}
434
 
435
 
436
/*************************************************************************
437
* This function returns the vertex with the largest gain from a partition
438
* and removes the node from the bucket list
439
**************************************************************************/
440
int PQueueGetMax(PQueueType *queue)
441
{
442
  int vtx, i, j, gain, node;
443
  idxtype *locator;
444
  ListNodeType *tptr;
445
  KeyValueType *heap;
446
 
447
  if (queue->nnodes == 0)
448
    return -1;
449
 
450
  queue->nnodes--;
451
 
452
  if (queue->type == 1) {
453
    tptr = queue->buckets[queue->maxgain];
454
    queue->buckets[queue->maxgain] = tptr->next;
455
    if (tptr->next != NULL) {
456
      tptr->next->prev = NULL;
457
    }
458
    else {
459
      if (queue->nnodes == 0) {
460
        queue->maxgain = -queue->ngainspan;
461
      }
462
      else 
463
        for (; queue->buckets[queue->maxgain]==NULL; queue->maxgain--);
464
    }
465
 
466
    return tptr->id;
467
  }
468
  else {
469
    heap = queue->heap;
470
    locator = queue->locator;
471
 
472
    vtx = heap[0].val;
473
    locator[vtx] = -1;
474
 
475
    if ((i = queue->nnodes) > 0) {
476
      gain = heap[i].key;
477
      node = heap[i].val;
478
      i = 0;
479
      while ((j=2*i+1) < queue->nnodes) {
480
        if (heap[j].key > gain) {
481
          if (j+1 < queue->nnodes && heap[j+1].key > heap[j].key)
482
            j = j+1;
483
          heap[i] = heap[j];
484
          locator[heap[i].val] = i;
485
          i = j;
486
        }
487
        else if (j+1 < queue->nnodes && heap[j+1].key > gain) {
488
          j = j+1;
489
          heap[i] = heap[j];
490
          locator[heap[i].val] = i;
491
          i = j;
492
        }
493
        else
494
          break;
495
      }
496
 
497
      heap[i].key = gain;
498
      heap[i].val = node;
499
      locator[node] = i;
500
    }
501
 
502
    ASSERT(CheckHeap(queue));
503
    return vtx;
504
  }
505
}
506
 
507
 
508
/*************************************************************************
509
* This function returns the vertex with the largest gain from a partition
510
**************************************************************************/
511
int PQueueSeeMax(PQueueType *queue)
512
{
513
  int vtx;
514
 
515
  if (queue->nnodes == 0)
516
    return -1;
517
 
518
  if (queue->type == 1) 
519
    vtx = queue->buckets[queue->maxgain]->id;
520
  else
521
    vtx = queue->heap[0].val;
522
 
523
  return vtx;
524
}
525
 
526
 
527
/*************************************************************************
528
* This function returns the vertex with the largest gain from a partition
529
**************************************************************************/
530
int PQueueGetKey(PQueueType *queue)
531
{
532
  int key;
533
 
534
  if (queue->nnodes == 0)
535
    return -1;
536
 
537
  if (queue->type == 1) 
538
    key = queue->maxgain;
539
  else
540
    key = queue->heap[0].key;
541
 
542
  return key;
543
}
544
 
545
 
546
 
547
 
548
/*************************************************************************
549
* This functions checks the consistency of the heap
550
**************************************************************************/
551
int CheckHeap(PQueueType *queue)
552
{
553
  int i, j, nnodes;
554
  idxtype *locator;
555
  KeyValueType *heap;
556
 
557
  heap = queue->heap;
558
  locator = queue->locator;
559
  nnodes = queue->nnodes;
560
 
561
  if (nnodes == 0)
562
    return 1;
563
 
564
  ASSERT(locator[heap[0].val] == 0);
565
  for (i=1; i<nnodes; i++) {
566
    ASSERTP(locator[heap[i].val] == i, ("%d %d %d %d\n", nnodes, i, heap[i].val, locator[heap[i].val])); 
567
    ASSERTP(heap[i].key <= heap[(i-1)/2].key, ("%d %d %d %d %d\n", i, (i-1)/2, nnodes, heap[i].key, heap[(i-1)/2].key));
568
  }
569
  for (i=1; i<nnodes; i++)
570
    ASSERT(heap[i].key <= heap[0].key);
571
 
572
  for (j=i=0; i<queue->maxnodes; i++) {
573
    if (locator[i] != -1)
574
      j++;
575
  }
576
  ASSERTP(j == nnodes, ("%d %d\n", j, nnodes));
577
 
578
  return 1;
579
}