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