Scippy

SCIP

Solving Constraint Integer Programs

tclique_graph.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program */
4 /* TCLIQUE --- Algorithm for Maximum Cliques */
5 /* */
6 /* Copyright (C) 1996-2014 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* TCLIQUE is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with TCLIQUE; see the file COPYING. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file tclique_graph.c
17  * @brief graph data part of algorithm for maximum cliques
18  * @author Tobias Achterberg
19  * @author Ralf Borndoerfer
20  * @author Zoltan Kormos
21  * @author Kati Wolter
22  */
23 
24 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
25 
26 #include <stdio.h>
27 #include <string.h>
28 #include <assert.h>
29 
30 #include "tclique/tclique.h"
31 #include "tclique/tclique_def.h"
32 #include "blockmemshell/memory.h"
33 
34 
35 typedef struct _HEAD_ADJ{
36  int first;
37  int last;
38 } HEAD_ADJ;
39 
40 struct TCLIQUE_Graph
41 {
42  int nnodes; /**< number of nodes in graph */
43  int nedges; /**< number of edges in graph */
44  TCLIQUE_WEIGHT* weights; /**< weight of nodes */
45  int* degrees; /**< degree of nodes */
46  int* adjnodes; /**< adjacent nodes of edges */
47  HEAD_ADJ* adjedges; /**< pointer to first and one after last adjacent edge of nodes */
48  int sizenodes; /**< size of arrays concerning nodes (weights, degrees and adjedges) */
49  int sizeedges; /**< size of arrays concerning edges (adjnodes) */
50  int* cacheddegrees; /**< number of adjacent cached edges for each node */
51  int* cachedorigs; /**< origin nodes of cached edges */
52  int* cacheddests; /**< destination nodes of cached edges */
53  int ncachededges; /**< number of cached edges (not yet inserted in all data structures) */
54  int sizecachededges; /**< size of arrays concerning cached edges */
55 };
56 
57 
58 
59 
60 /*
61  * Interface Methods used by the TClique algorithm
62  */
63 
64 /** gets number of nodes in the graph */
65 TCLIQUE_GETNNODES(tcliqueGetNNodes)
66 {
67  assert(tcliquegraph != NULL);
68 
69  return tcliquegraph->nnodes;
70 }
71 
72 /** gets weight of nodes in the graph */
73 TCLIQUE_GETWEIGHTS(tcliqueGetWeights)
74 {
75  assert(tcliquegraph != NULL);
76 
77  return tcliquegraph->weights;
78 }
79 
80 /** returns, whether the edge (node1, node2) is in the graph */
81 TCLIQUE_ISEDGE(tcliqueIsEdge)
82 {
83  int* currentadjedge;
84  int* lastadjedge;
85  int tmp;
86 
87  assert(tcliquegraph != NULL);
88  assert(tcliquegraph->ncachededges == 0);
89  assert(0 <= node1 && node1 < tcliquegraph->nnodes);
90  assert(0 <= node2 && node2 < tcliquegraph->nnodes);
91 
92  if( node1 < node2 )
93  {
94  tmp = node1;
95  node1 = node2;
96  node2 = tmp;
97  }
98 
99  currentadjedge = tcliqueGetFirstAdjedge(tcliquegraph, node1);
100  lastadjedge = tcliqueGetLastAdjedge(tcliquegraph, node1);
101 
102  if( currentadjedge > lastadjedge || *lastadjedge < node2 )
103  return FALSE;
104 
105  /* checks if node2 is contained in adjacency list of node1
106  * (list is ordered by adjacent nodes) */
107  while( currentadjedge <= lastadjedge )
108  {
109  if( *currentadjedge >= node2 )
110  {
111  if( *currentadjedge == node2 )
112  return TRUE;
113  else
114  break;
115  }
116  currentadjedge++;
117  }
118 
119  return FALSE;
120 }
121 
122 /* selects all nodes from a given set of nodes which are adjacent to a given node
123  * and returns the number of selected nodes
124  */
125 TCLIQUE_SELECTADJNODES(tcliqueSelectAdjnodes)
126 {
127  int nadjnodes;
128  int* currentadjedge;
129  int* lastadjedge;
130  int i;
131 
132  assert(tcliquegraph != NULL);
133  assert(tcliquegraph->ncachededges == 0);
134  assert(0 <= node && node < tcliquegraph->nnodes);
135  assert(nnodes == 0 || nodes != NULL);
136  assert(adjnodes != NULL);
137 
138  nadjnodes = 0;
139  currentadjedge = tcliqueGetFirstAdjedge(tcliquegraph, node);
140  lastadjedge = tcliqueGetLastAdjedge(tcliquegraph, node);
141 
142  /* checks for each node in given set nodes, if it is adjacent to given node
143  * (adjacent nodes are ordered by node index)
144  */
145  for( i = 0; i < nnodes; i++ )
146  {
147  assert(0 <= nodes[i] && nodes[i] < tcliquegraph->nnodes);
148  assert(i == 0 || nodes[i-1] < nodes[i]);
149  for( ; currentadjedge <= lastadjedge; currentadjedge++ )
150  {
151  if( *currentadjedge >= nodes[i] )
152  {
153  /* current node is adjacent to given node */
154  if( *currentadjedge == nodes[i] )
155  {
156  adjnodes[nadjnodes] = nodes[i];
157  nadjnodes++;
158  }
159  break;
160  }
161  }
162  }
163 
164  return nadjnodes;
165 }
166 
167 
168 
169 
170 /*
171  * External Interface Methods to access the graph (this can be changed without affecting the TClique algorithm)
172  */
173 
174 /** creates graph data structure */
176  TCLIQUE_GRAPH** tcliquegraph /**< pointer to store graph data structure */
177  )
178 {
179  assert(tcliquegraph != NULL);
180 
181  ALLOC_FALSE( BMSallocMemory(tcliquegraph) );
182 
183  (*tcliquegraph)->nnodes = 0;
184  (*tcliquegraph)->nedges = 0;
185  (*tcliquegraph)->weights = NULL;
186  (*tcliquegraph)->degrees = NULL;
187  (*tcliquegraph)->adjnodes = NULL;
188  (*tcliquegraph)->adjedges = NULL;
189  (*tcliquegraph)->sizenodes = 0;
190  (*tcliquegraph)->sizeedges = 0;
191  (*tcliquegraph)->cacheddegrees = NULL;
192  (*tcliquegraph)->cachedorigs = NULL;
193  (*tcliquegraph)->cacheddests = NULL;
194  (*tcliquegraph)->ncachededges = 0;
195  (*tcliquegraph)->sizecachededges = 0;
196 
197  return TRUE;
198 }
199 
200 /** frees graph data structure */
202  TCLIQUE_GRAPH** tcliquegraph /**< pointer to graph data structure */
203  )
204 {
205  assert(tcliquegraph != NULL);
206 
207  if( *tcliquegraph != NULL )
208  {
209  if ( (*tcliquegraph)->adjedges != NULL )
210  {
211  BMSfreeMemoryArray(&(*tcliquegraph)->adjedges);
212  BMSfreeMemoryArray(&(*tcliquegraph)->adjnodes);
213  BMSfreeMemoryArray(&(*tcliquegraph)->degrees);
214  BMSfreeMemoryArray(&(*tcliquegraph)->weights);
215  }
216  if ( (*tcliquegraph)->cacheddegrees )
217  {
218  BMSfreeMemoryArrayNull(&(*tcliquegraph)->cacheddegrees);
219  BMSfreeMemoryArrayNull(&(*tcliquegraph)->cachedorigs);
220  BMSfreeMemoryArrayNull(&(*tcliquegraph)->cacheddests);
221  }
222  BMSfreeMemory(tcliquegraph);
223  }
224 }
225 
226 /** ensures, that arrays concerning edges in graph data structure can store at least num entries */
227 static
229  TCLIQUE_GRAPH* tcliquegraph, /**< graph data structure */
230  int num /**< minimum number of entries concerning edges to store */
231  )
232 {
233  assert(tcliquegraph != NULL);
234 
235  if( num > tcliquegraph->sizeedges )
236  {
237  int newsize;
238 
239  newsize = 2*tcliquegraph->sizeedges;
240  if( newsize < num )
241  newsize = num;
242 
243  ALLOC_FALSE( BMSreallocMemoryArray(&tcliquegraph->adjnodes, newsize) );
244  tcliquegraph->sizeedges = newsize;
245  }
246 
247  assert(num <= tcliquegraph->sizeedges);
248 
249  return TRUE;
250 }
251 
252 /** ensures, that arrays concerning cached edges in graph data structure can store at least num entries */
253 static
255  TCLIQUE_GRAPH* tcliquegraph, /**< graph data structure */
256  int num /**< minimum number of entries concerning cached edges to store */
257  )
258 {
259  assert(tcliquegraph != NULL);
260 
261  if( num > tcliquegraph->sizecachededges )
262  {
263  int newsize;
264 
265  newsize = 2*tcliquegraph->sizecachededges;
266  if( newsize < num )
267  newsize = num;
268 
269  ALLOC_FALSE( BMSreallocMemoryArray(&tcliquegraph->cachedorigs, newsize) );
270  ALLOC_FALSE( BMSreallocMemoryArray(&tcliquegraph->cacheddests, newsize) );
271  tcliquegraph->sizecachededges = newsize;
272  }
273 
274  assert(num <= tcliquegraph->sizecachededges);
275 
276  return TRUE;
277 }
278 
279 /** ensures, that arrays concerning nodes in graph data structure can store at least num entries */
280 static
282  TCLIQUE_GRAPH* tcliquegraph, /**< graph data structure */
283  int num /**< minimum number of entries concerning nodes to store */
284  )
285 {
286  assert(tcliquegraph != NULL);
287 
288  if( !tcliqueEnsureSizeEdges(tcliquegraph, 1) )
289  return FALSE;
290  assert(tcliquegraph->adjnodes != NULL);
291 
292  if( num > tcliquegraph->sizenodes )
293  {
294  int newsize;
295  int i;
296 
297  newsize = 2*tcliquegraph->sizenodes;
298  if( newsize < num )
299  newsize = num;
300 
301  ALLOC_FALSE( BMSreallocMemoryArray(&tcliquegraph->weights, newsize) );
302  ALLOC_FALSE( BMSreallocMemoryArray(&tcliquegraph->degrees, newsize) );
303  ALLOC_FALSE( BMSreallocMemoryArray(&tcliquegraph->adjedges, newsize) );
304 
305  for( i = tcliquegraph->sizenodes; i < newsize; i++ )
306  {
307  tcliquegraph->weights[i] = 0;
308  tcliquegraph->degrees[i] = 0;
309  tcliquegraph->adjedges[i].first = tcliquegraph->nedges;
310  tcliquegraph->adjedges[i].last = tcliquegraph->nedges;
311  }
312 
313  if( tcliquegraph->ncachededges > 0 )
314  {
315  assert(tcliquegraph->cacheddegrees != NULL);
316  ALLOC_FALSE( BMSreallocMemoryArray(&tcliquegraph->cacheddegrees, newsize) );
317  for( i = tcliquegraph->sizenodes; i < newsize; i++ )
318  tcliquegraph->cacheddegrees[i] = 0;
319  }
320 
321  tcliquegraph->sizenodes = newsize;
322  }
323  assert(num <= tcliquegraph->sizenodes);
324 
325  return TRUE;
326 }
327 
328 
329 /** adds nodes up to the given node number to graph data structure (intermediate nodes have weight 0) */
331  TCLIQUE_GRAPH* tcliquegraph, /**< graph data structure */
332  int node, /**< node number to add */
333  TCLIQUE_WEIGHT weight /**< weight of node to add */
334  )
335 {
336  assert(weight >= 0);
337 
338  if( !tcliqueEnsureSizeNodes(tcliquegraph, node + 1) )
339  return FALSE;
340 
341  tcliquegraph->weights[node] = weight;
342 
343  assert(tcliquegraph->degrees[node] == 0);
344  assert(tcliquegraph->adjedges[node].first <= tcliquegraph->nedges);
345  assert(tcliquegraph->adjedges[node].last == tcliquegraph->adjedges[node].first);
346  tcliquegraph->nnodes = MAX(tcliquegraph->nnodes, node+1);
347 
348  return TRUE;
349 }
350 
351 /** changes weight of node in graph data structure */
353  TCLIQUE_GRAPH* tcliquegraph, /**< graph data structure */
354  int node, /**< node to set new weight */
355  TCLIQUE_WEIGHT weight /**< new weight of node (allready scaled) */
356  )
357 {
358  assert(0 <= node && node < tcliqueGetNNodes(tcliquegraph));
359  assert(weight >= 0);
360 
361  tcliquegraph->weights[node] = weight;
362 }
363 
364 /** adds edge (node1, node2) to graph data structure (node1 and node2 have to be contained in
365  * graph data structure);
366  * new edges are cached, s.t. the graph data structures are not correct until a call to tcliqueFlush();
367  * you have to make sure, that no double edges are inserted
368  */
370  TCLIQUE_GRAPH* tcliquegraph, /**< graph data structure */
371  int node1, /**< start node of edge to add */
372  int node2 /**< end node of edge to add */
373  )
374 {
375  assert(tcliquegraph != NULL);
376  assert(0 <= node1 && node1 < tcliquegraph->nnodes);
377  assert(0 <= node2 && node2 < tcliquegraph->nnodes);
378  assert(node1 != node2);
379 
380  if( !tcliqueEnsureSizeCachedEdges(tcliquegraph, tcliquegraph->ncachededges + 2) )
381  return FALSE;
382 
383  /* make sure, the array for counting the cached node degrees exists */
384  if( tcliquegraph->ncachededges == 0 && tcliquegraph->sizenodes > 0 )
385  {
386  assert(tcliquegraph->cacheddegrees == NULL);
387  ALLOC_FALSE( BMSallocMemoryArray(&tcliquegraph->cacheddegrees, tcliquegraph->sizenodes) );
388  BMSclearMemoryArray(tcliquegraph->cacheddegrees, tcliquegraph->sizenodes);
389  }
390  assert(tcliquegraph->cacheddegrees != NULL);
391 
392  /* just remember both new half edges in the cache; the full insertion is done later on demand */
393  tcliquegraph->cachedorigs[tcliquegraph->ncachededges] = node1;
394  tcliquegraph->cacheddests[tcliquegraph->ncachededges] = node2;
395  tcliquegraph->ncachededges++;
396  tcliquegraph->cachedorigs[tcliquegraph->ncachededges] = node2;
397  tcliquegraph->cacheddests[tcliquegraph->ncachededges] = node1;
398  tcliquegraph->ncachededges++;
399  tcliquegraph->cacheddegrees[node1]++;
400  tcliquegraph->cacheddegrees[node2]++;
401 
402  return TRUE;
403 }
404 
405 /** inserts all cached edges into the data structures */
407  TCLIQUE_GRAPH* tcliquegraph /**< graph data structure */
408  )
409 {
410  assert(tcliquegraph != NULL);
411 
412  /* check, whether there are cached edges */
413  if( tcliquegraph->ncachededges > 0 )
414  {
415  int ninsertedholes;
416  int pos;
417  int n;
418  int i;
419 
420  /* reallocate adjnodes array to be able to store all additional edges */
421  if( !tcliqueEnsureSizeEdges(tcliquegraph, tcliquegraph->nedges + tcliquegraph->ncachededges) )
422  return FALSE;
423  assert(tcliquegraph->adjnodes != NULL);
424  assert(tcliquegraph->adjedges != NULL);
425 
426  /* move the old edges in the adjnodes array, s.t. there is enough free space for the additional edges */
427  ninsertedholes = 0;
428  pos = tcliquegraph->nedges + tcliquegraph->ncachededges - 1;
429  for( n = tcliquegraph->nnodes-1; ; --n ) /* no abort criterion, because at n == 0, the loop is break'ed */
430  {
431  int olddegree;
432 
433  assert(n >= 0);
434  assert(tcliquegraph->adjedges[n].last - tcliquegraph->adjedges[n].first == tcliquegraph->degrees[n]);
435 
436  /* increase the degree of the node */
437  olddegree = tcliquegraph->degrees[n];
438  tcliquegraph->degrees[n] += tcliquegraph->cacheddegrees[n];
439 
440  /* skip space for new edges */
441  pos -= tcliquegraph->cacheddegrees[n];
442  ninsertedholes += tcliquegraph->cacheddegrees[n];
443  assert(ninsertedholes <= tcliquegraph->ncachededges);
444  if( ninsertedholes == tcliquegraph->ncachededges )
445  break;
446  assert(n > 0);
447 
448  /* move old edges */
449  for( i = tcliquegraph->adjedges[n].last - 1; i >= tcliquegraph->adjedges[n].first; --i, --pos )
450  {
451  assert(0 <= i && i < pos && pos < tcliquegraph->nedges + tcliquegraph->ncachededges);
452  tcliquegraph->adjnodes[pos] = tcliquegraph->adjnodes[i];
453  }
454 
455  /* adjust the first and last edge pointers of the node */
456  tcliquegraph->adjedges[n].first = pos+1;
457  tcliquegraph->adjedges[n].last = pos+1 + olddegree;
458 
459  assert(n == tcliquegraph->nnodes-1
460  || tcliquegraph->adjedges[n].first + tcliquegraph->degrees[n] == tcliquegraph->adjedges[n+1].first);
461  }
462  assert(ninsertedholes == tcliquegraph->ncachededges);
463  assert(tcliquegraph->adjedges[n].last == pos+1);
464 #ifndef NDEBUG
465  for( --n; n >= 0; --n )
466  assert(tcliquegraph->cacheddegrees[n] == 0);
467 #endif
468 
469  /* insert the cached edges into the adjnodes array */
470  for( i = 0; i < tcliquegraph->ncachededges; ++i )
471  {
472  int dest;
473 
474  n = tcliquegraph->cachedorigs[i];
475  dest = tcliquegraph->cacheddests[i];
476  assert(0 <= n && n < tcliquegraph->nnodes);
477  assert(0 <= dest && dest < tcliquegraph->nnodes);
478  assert(tcliquegraph->adjedges[n].last <= tcliquegraph->nedges + tcliquegraph->ncachededges);
479  assert(n == tcliquegraph->nnodes-1 || tcliquegraph->adjedges[n].last <= tcliquegraph->adjedges[n+1].first);
480  assert(n == tcliquegraph->nnodes-1
481  || tcliquegraph->adjedges[n].first + tcliquegraph->degrees[n] == tcliquegraph->adjedges[n+1].first);
482 
483  /* edges of each node must be sorted by increasing destination node number */
484  for( pos = tcliquegraph->adjedges[n].last;
485  pos > tcliquegraph->adjedges[n].first && dest < tcliquegraph->adjnodes[pos-1]; --pos )
486  {
487  tcliquegraph->adjnodes[pos] = tcliquegraph->adjnodes[pos-1];
488  }
489  tcliquegraph->adjnodes[pos] = dest;
490  tcliquegraph->adjedges[n].last++;
491 
492  assert(n == tcliquegraph->nnodes-1 || tcliquegraph->adjedges[n].last <= tcliquegraph->adjedges[n+1].first);
493  }
494 
495  /* update the number of edges */
496  tcliquegraph->nedges += tcliquegraph->ncachededges;
497 
498  /* free the cache */
499  BMSfreeMemoryArray(&tcliquegraph->cacheddegrees);
500  BMSfreeMemoryArray(&tcliquegraph->cachedorigs);
501  BMSfreeMemoryArray(&tcliquegraph->cacheddests);
502  tcliquegraph->ncachededges = 0;
503  tcliquegraph->sizecachededges = 0;
504  }
505 
506  /* the cache should now be freed */
507  assert(tcliquegraph->ncachededges == 0);
508  assert(tcliquegraph->sizecachededges == 0);
509  assert(tcliquegraph->cacheddegrees == NULL);
510  assert(tcliquegraph->cachedorigs == NULL);
511  assert(tcliquegraph->cacheddests == NULL);
512 
513 #ifndef NDEBUG
514  /* check integrity of the data structures */
515  {
516  int pos;
517  int n;
518 
519  pos = 0;
520  for( n = 0; n < tcliquegraph->nnodes; ++n )
521  {
522  int i;
523 
524  assert(tcliquegraph->adjedges[n].first == pos);
525  assert(tcliquegraph->adjedges[n].last == tcliquegraph->adjedges[n].first + tcliquegraph->degrees[n]);
526 
527  for( i = tcliquegraph->adjedges[n].first; i < tcliquegraph->adjedges[n].last-1; ++i )
528  {
529  assert(tcliquegraph->adjnodes[i] < tcliquegraph->adjnodes[i+1]);
530  }
531  pos = tcliquegraph->adjedges[n].last;
532  }
533  assert(pos == tcliquegraph->nedges);
534  }
535 #endif
536 
537  return TRUE;
538 }
539 
540 /** loads graph data structure from file */
542  TCLIQUE_GRAPH** tcliquegraph, /**< pointer to store graph data structure */
543  const char* filename, /**< name of file with graph data */
544  double scaleval, /**< value to scale weights (only integral part of scaled weights is considered) */
545  char* probname, /**< buffer to store the name of the problem */
546  int sizeofprobname /**< size of buffer to store the name of the problem */
547  )
548 {
549  FILE* file;
550  double weight;
551  int node1;
552  int node2;
553  int currentnode;
554  int i;
555  int result;
556  char* charresult;
557  char* tmp;
558 
559  assert(tcliquegraph != NULL);
560  assert(scaleval > 0.0);
561 
562  /* open file */
563  if( (file = fopen(filename, "r")) == NULL )
564  {
565  if( (file = fopen("default.dat", "r")) == NULL )
566  {
567  infoMessage("\nCan't open file: %s", filename);
568  return FALSE;
569  }
570  }
571 
572  if( !tcliqueCreate(tcliquegraph) )
573  {
574  fclose(file);
575  return FALSE;
576  }
577 
578  /* set name of problem, copies 'sizeofprobname' characters into probname */
579  charresult = fgets(probname, sizeofprobname, file);
580  if( charresult == NULL )
581  {
582  infoMessage("Error while reading probname in file %s", filename);
583  fclose(file);
584  return FALSE;
585  }
586 
587  /* allocate temporary memory for skipping rest of problem name */
588  BMSallocMemoryArray(&tmp, sizeofprobname +1 );
589  BMScopyMemoryArray(tmp, probname, sizeofprobname);
590  probname[sizeofprobname-1] = '\0';
591  tmp[sizeofprobname] = '\0';
592 
593  /* continue reading until we reach the end of the problem name */
594  while( (int) strlen(tmp) == sizeofprobname && tmp[strlen(tmp)-1] != '\n' )
595  {
596  charresult = fgets(tmp, sizeofprobname, file);
597 
598  if( charresult == NULL )
599  {
600  infoMessage("Error while reading probname in file %s", filename);
601  fclose(file);
602  return FALSE;
603  }
604  }
605 
606  /* free temporary memory */
607  BMSfreeMemoryArray(&tmp);
608 
609  /* set number of nodes and number of edges in graph */
610  result = fscanf(file, "%d", &(*tcliquegraph)->nnodes);
611  if( result == EOF )
612  {
613  infoMessage("Error while reading number of nodes in file %s", filename);
614  fclose(file);
615  return FALSE;
616  }
617 
618  result = fscanf(file, "%d", &(*tcliquegraph)->nedges);
619  if( result == EOF )
620  {
621  infoMessage("Error while reading number of edges in file %s", filename);
622  fclose(file);
623  return FALSE;
624  }
625 
626  if( (*tcliquegraph)->nnodes < 0 || (*tcliquegraph)->nedges < 0 )
627  {
628  infoMessage("\nInvalid number of %s (%d) in file: %s", (*tcliquegraph)->nnodes < 0 ? "nodes" : "edges",
629  (*tcliquegraph)->nnodes < 0 ? (*tcliquegraph)->nnodes : (*tcliquegraph)->nedges, filename);
630  fclose(file);
631  return FALSE;
632  }
633 
634  /* set data structures for tclique,
635  * if an error occured, close the file before returning */
636  if( BMSallocMemoryArray(&(*tcliquegraph)->weights, (*tcliquegraph)->nnodes) == NULL )
637  {
638  infoMessage("Run out of memory while reading file %s", filename);
639  (void) fclose(file);
640  return FALSE;
641  }
642 
643  if( BMSallocMemoryArray(&(*tcliquegraph)->degrees, (*tcliquegraph)->nnodes) == NULL )
644  {
645  infoMessage("Run out of memory while reading file %s", filename);
646  (void) fclose(file);
647  return FALSE;
648  }
649 
650  if( BMSallocMemoryArray(&(*tcliquegraph)->adjnodes, (*tcliquegraph)->nedges) == NULL )
651  {
652  infoMessage("Run out of memory while reading file %s", filename);
653  (void) fclose(file);
654  return FALSE;
655  }
656 
657  if( BMSallocMemoryArray(&(*tcliquegraph)->adjedges, (*tcliquegraph)->nnodes) == NULL )
658  {
659  infoMessage("Run out of memory while reading file %s", filename);
660  (void) fclose(file);
661  return FALSE;
662  }
663 
664  /* set weights of all nodes (scaled!) */
665  for( i = 0; i < (*tcliquegraph)->nnodes; i++ )
666  {
667  result = fscanf(file, "%lf", &weight);
668  if( result == EOF )
669  {
670  infoMessage("Error while reading weights of nodes in file %s", filename);
671  fclose(file);
672  return FALSE;
673  }
674 
675  (*tcliquegraph)->weights[i] = (TCLIQUE_WEIGHT)(weight * scaleval);
676  assert((*tcliquegraph)->weights[i] >= 0);
677  }
678 
679  /* set adjacent edges and degree of all nodes */
680  currentnode = -1;
681  for( i = 0; i < (*tcliquegraph)->nedges; i++ )
682  {
683  /* read edge (node1, node2) */
684  result = fscanf(file, "%d%d", &node1, &node2);
685  if( result == EOF )
686  {
687  infoMessage("Error while reading edges in file %s", filename);
688  fclose(file);
689  return FALSE;
690  }
691 
692  if( node1 < 0 || node2 < 0 )
693  {
694  infoMessage("\nInvalid node index (%d) in file: %s", node1 < 0 ? node1 : node2, filename);
695  fclose(file);
696  return FALSE;
697  }
698 
699  /* (node1, node2) is the first adjacent edge of node1 */
700  if( node1 != currentnode )
701  {
702  currentnode = node1;
703  (*tcliquegraph)->degrees[currentnode] = 0;
704  (*tcliquegraph)->adjedges[currentnode].first = i;
705  (*tcliquegraph)->adjedges[currentnode].last = (*tcliquegraph)->adjedges[currentnode].first;
706  }
707  (*tcliquegraph)->degrees[currentnode]++;
708  (*tcliquegraph)->adjnodes[i] = node2;
709  (*tcliquegraph)->adjedges[currentnode].last++;
710  }
711 
712  /* close file */
713  fclose(file);
714 
715  return TRUE;
716 }
717 
718 /** saves graph data structure to file */
720  TCLIQUE_GRAPH* tcliquegraph, /**< graph data structure */
721  const char* filename, /**< name of file to create */
722  double scaleval, /**< value to unscale weights with */
723  const char* probname /**< name of the problem */
724  )
725 {
726  FILE* file;
727  int i;
728  int j;
729 
730  assert(tcliquegraph != NULL);
731  assert(scaleval > 0.0);
732 
733  /* create file */
734  if( (file = fopen(filename, "w")) == NULL )
735  {
736  infoMessage("\nCan't create file: %s", filename);
737  return FALSE;
738  }
739 
740  /* write name of problem, number of nodes and number of edges in graph */
741  fprintf(file, "%s\n", probname);
742  fprintf(file, "%d\n", tcliquegraph->nnodes);
743  fprintf(file, "%d\n", tcliquegraph->nedges);
744 
745  /* write weights of all nodes (scaled!) */
746  for( i = 0; i < tcliquegraph->nnodes; i++ )
747  fprintf(file, "%f\n", (double)tcliquegraph->weights[i]/scaleval);
748 
749  /* write edges */
750  for( i = 0; i < tcliquegraph->nnodes; i++ )
751  {
752  for( j = tcliquegraph->adjedges[i].first; j < tcliquegraph->adjedges[i].last; j++ )
753  fprintf(file, "%d %d\n", i, tcliquegraph->adjnodes[j]);
754  }
755 
756  /* close file */
757  fclose(file);
758 
759  return TRUE;
760 }
761 
762 /** gets number of edges in the graph */
764  TCLIQUE_GRAPH* tcliquegraph /**< pointer to graph data structure */
765  )
766 {
767  assert(tcliquegraph != NULL);
768 
769  return tcliquegraph->nedges + tcliquegraph->ncachededges;
770 }
771 
772 /** gets degree of nodes in graph */
774  TCLIQUE_GRAPH* tcliquegraph /**< pointer to graph data structure */
775  )
776 {
777  assert(tcliquegraph != NULL);
778  assert(tcliquegraph->ncachededges == 0);
779 
780  return tcliquegraph->degrees;
781 }
782 
783 /** gets adjacent nodes of edges in graph */
785  TCLIQUE_GRAPH* tcliquegraph /**< pointer to graph data structure */
786  )
787 {
788  assert(tcliquegraph != NULL);
789  assert(tcliquegraph->ncachededges == 0);
790 
791  return tcliquegraph->adjnodes;
792 }
793 
794 /** gets pointer to first adjacent edge of given node in graph */
796  TCLIQUE_GRAPH* tcliquegraph, /**< pointer to graph data structure */
797  int node /**< given node */
798  )
799 {
800  HEAD_ADJ* adjedges;
801  int* adjnodes;
802 
803  assert(tcliquegraph != NULL);
804  assert(tcliquegraph->ncachededges == 0);
805  assert(0 <= node && node < tcliquegraph->nnodes);
806 
807  adjedges = tcliquegraph->adjedges;
808  assert(adjedges != NULL);
809  assert(adjedges[node].first >= 0);
810  assert(adjedges[node].first <= tcliqueGetNEdges(tcliquegraph));
811 
812  adjnodes = tcliqueGetAdjnodes(tcliquegraph);
813  assert(adjnodes != NULL);
814 
815  return &adjnodes[adjedges[node].first];
816 }
817 
818 /** gets pointer to last adjacent edge of given node in graph */
820  TCLIQUE_GRAPH* tcliquegraph, /**< pointer to graph data structure */
821  int node /**< given node */
822  )
823 {
824  HEAD_ADJ* adjedges;
825  int* adjnodes;
826 #ifndef NDEBUG
827  int* degrees;
828 #endif
829 
830  assert(tcliquegraph != NULL);
831  assert(tcliquegraph->ncachededges == 0);
832  assert(0 <= node && node < tcliquegraph->nnodes);
833 
834  adjedges = tcliquegraph->adjedges;
835 #ifndef NDEBUG
836  degrees = tcliqueGetDegrees(tcliquegraph);
837 #endif
838  assert(adjedges != NULL);
839  assert(degrees[node] == 0 || adjedges[node].last-1 >= 0);
840  assert(adjedges[node].last-1 <= tcliqueGetNEdges(tcliquegraph));
841 
842  assert(adjedges[node].last - adjedges[node].first == degrees[node]);
843 
844  adjnodes = tcliqueGetAdjnodes(tcliquegraph);
845  assert(adjnodes != NULL);
846 
847  return &adjnodes[adjedges[node].last-1];
848 }
849 
850 /* prints graph data structure */
852  TCLIQUE_GRAPH* tcliquegraph /**< pointer to graph data structure */
853  )
854 {
855  const int* weights;
856  int* degrees;
857  int i;
858 
859  assert(tcliquegraph != NULL);
860  assert(tcliquegraph->ncachededges == 0);
861 
862  degrees = tcliqueGetDegrees(tcliquegraph);
863  weights = tcliqueGetWeights(tcliquegraph);
864 
865  infoMessage("nnodes=%d, nedges=%d\n", tcliqueGetNNodes(tcliquegraph), tcliqueGetNEdges(tcliquegraph));
866  for( i = 0; i < tcliqueGetNNodes(tcliquegraph); i++ )
867  {
868  int* currentadjedge;
869  int* lastadjedge;
870 
871  infoMessage("node %d: weight=%d, degree=%d, adjnodes=\n[ ", i, weights[i], degrees[i]);
872 
873  currentadjedge = tcliqueGetFirstAdjedge(tcliquegraph, i);
874  lastadjedge = tcliqueGetLastAdjedge(tcliquegraph, i);
875  assert(lastadjedge + 1 - currentadjedge == degrees[i]);
876 
877  for( ; currentadjedge <= lastadjedge; currentadjedge++ )
878  {
879  infoMessage("%d, ", *currentadjedge);
880  }
881  infoMessage("]\n");
882  }
883 }
884