1 /*
2 * This file is part of the RingDecomposerLib, licensed
3 * under BSD New license (see LICENSE in the root directory).
4 * Copyright (c) 2016
5 * University of Hamburg, ZBH - Center for Bioinformatics
6 * Niek Andresen, Florian Flachsenberg, Matthias Rarey
7 *
8 * Please cite:
9 *
10 * Kolodzik, A.; Urbaczek, S.; Rarey, M.
11 * Unique Ring Families: A Chemically Meaningful Description
12 * of Molecular Ring Topologies.
13 * J. Chem. Inf. Model., 2012, 52 (8), pp 2013-2021
14 *
15 * Flachsenberg, F.; Andresen, N.; Rarey, M.
16 * RingDecomposerLib: An Open-Source Implementation of
17 * Unique Ring Families and Other Cycle Bases.
18 * J. Chem. Inf. Model., 2017, 57 (2), pp 122-126
19 */
20
21 #include <assert.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <limits.h>
25 #include <string.h>
26 #include <float.h>
27 #include <math.h>
28
29 #include "RingDecomposerLib.h"
30
31 #include "RDLapsp.h"
32 #include "RDLbitset.h"
33 #include "RDLcycleFams.h"
34 #include "RDLdataStruct.h"
35 #include "RDLgraph.h"
36 #include "RDLhandler.h"
37 #include "RDLinfo.h"
38 #include "RDLrelation.h"
39 #include "RDLtarjan.h"
40 #include "RDLutility.h"
41
42 const unsigned RDL_RESERVED_START = 64;
43
44 /* define some constants */
45 const unsigned RDL_INVALID_RESULT = UINT_MAX;
46 const unsigned RDL_DUPLICATE_EDGE = UINT_MAX - 1;
47 const unsigned RDL_NO_RINGSYSTEM = UINT_MAX - 2;
48 const double RDL_INVALID_RC_COUNT = DBL_MAX;
49
50 /* public, set the global output function */
RDL_setOutputFunction(RDL_outputFunction func)51 void RDL_setOutputFunction(RDL_outputFunction func)
52 {
53 RDL_outputFunc = func;
54 }
55
56 /* public */
RDL_initNewGraph(unsigned V)57 RDL_graph *RDL_initNewGraph(unsigned V)
58 {
59 return RDL_initNewGraph_g(V, 1);
60 }
61
62 /* public, add an edge with range check! */
RDL_addUEdge(RDL_graph * gra,RDL_node from,RDL_node to)63 unsigned RDL_addUEdge(RDL_graph *gra, RDL_node from, RDL_node to)
64 {
65 return RDL_addUEdge_g(gra, from, to);
66 }
67
68 /* public, the calculation routine */
RDL_calculate(RDL_graph * gra)69 RDL_data *RDL_calculate(RDL_graph *gra)
70 {
71 RDL_data *data;
72 unsigned i, j, k, urf_index, rcf_index;
73 unsigned nof_relevant_fams, nof_relevant_fams_sum;
74
75 if (!gra) {
76 RDL_outputFunc(RDL_ERROR, "The graph is NULL.\n");
77 return NULL;
78 }
79
80 /* we can't calculate anything if there isn't at least one node */
81 if(!gra->V) {
82 RDL_outputFunc(RDL_ERROR, "The graph has no nodes.\n");
83 return NULL;
84 }
85
86 data = malloc(sizeof(*data));
87
88 /* FIRST STEP: TARJAN */
89 data->bccGraphs = RDL_tarjanBCC(gra);
90 data->nofURFs = 0;
91 data->nofRCFs = 0;
92
93 /* allocate result structures */
94 data->spiPerBCC = malloc(data->bccGraphs->nof_bcc * sizeof(*data->spiPerBCC));
95 data->CFsPerBCC = malloc(data->bccGraphs->nof_bcc * sizeof(*data->CFsPerBCC));
96 data->urfInfoPerBCC = malloc(data->bccGraphs->nof_bcc * sizeof(*data->urfInfoPerBCC));
97 data->nofURFsPerBCC = malloc(data->bccGraphs->nof_bcc * sizeof(*data->nofURFsPerBCC));
98 data->nofRCFsPerBCC = malloc(data->bccGraphs->nof_bcc * sizeof(*data->nofRCFsPerBCC));
99
100 /* the followeing steps are performed for each BCC */
101 for (i = 0; i < data->bccGraphs->nof_bcc; ++i) {
102 /* solve APSP problem */
103 data->spiPerBCC[i] = RDL_AllPairsShortestPaths(data->bccGraphs->bcc_graphs[i]);
104 /* calculate RCFs with Vismara's algortihm */
105 data->CFsPerBCC[i] = RDL_findCycleFams(data->bccGraphs->bcc_graphs[i], data->spiPerBCC[i]);
106 /* this can fail if the BCC is to large */
107 if (!data->CFsPerBCC[i]) {
108 /* delete families and APSP information UPTO current index */
109 for (j = 0; j < i; ++j) {
110 RDL_deleteAPSP(data->spiPerBCC[j], data->bccGraphs->bcc_graphs[j]->V);
111 RDL_deleteCycleFams(data->CFsPerBCC[j]);
112 if (data->nofURFsPerBCC[j] > 0) {
113 RDL_deleteURFInfo(data->urfInfoPerBCC[j]);
114 }
115 }
116 /* delete APSP for current index (there is no RCF info) */
117 RDL_deleteAPSP(data->spiPerBCC[i], data->bccGraphs->bcc_graphs[i]->V);
118
119 /* free alloced per BCC structures */
120 free(data->spiPerBCC);
121 free(data->CFsPerBCC);
122 free(data->nofURFsPerBCC);
123 free(data->nofRCFsPerBCC);
124 free(data->urfInfoPerBCC);
125 /* and of course the BCC graph */
126 RDL_deleteBCCGraph(data->bccGraphs);
127 /* free resulting struct */
128 free(data);
129
130 return NULL;
131 }
132 if(data->CFsPerBCC[i]->nofFams > 0) {
133 /* if there is at least one RCF, check URF relation */
134 data->urfInfoPerBCC[i] = RDL_checkURFRelation(data->CFsPerBCC[i],
135 data->bccGraphs->bcc_graphs[i], data->spiPerBCC[i]);
136 data->nofURFsPerBCC[i] = data->urfInfoPerBCC[i]->nofURFs;
137
138 nof_relevant_fams = 0;
139 /* count RCFs */
140 for (j = 0; j < data->CFsPerBCC[i]->nofFams; ++j) {
141 if (data->CFsPerBCC[i]->fams[j]->mark) {
142 ++nof_relevant_fams;
143 }
144 }
145
146 nof_relevant_fams_sum = 0;
147 for (j = 0; j < data->nofURFsPerBCC[i]; ++j) {
148 nof_relevant_fams_sum += data->urfInfoPerBCC[i]->nofCFsPerURF[j];
149 }
150
151 if (nof_relevant_fams != nof_relevant_fams_sum) {
152 RDL_outputFunc(RDL_ERROR, "different number of relevant families!\n");
153 /* internal check, should never happen */
154 assert(0);
155 }
156 data->nofRCFsPerBCC[i] = nof_relevant_fams;
157 }
158 else {
159 data->nofURFsPerBCC[i] = 0;
160 data->nofRCFsPerBCC[i] = 0;
161 }
162 data->nofURFs += data->nofURFsPerBCC[i];
163 data->nofRCFs += data->nofRCFsPerBCC[i];
164 }
165
166 /* create a mapping from URFs to BCCs */
167 data->urf_to_bcc = malloc(data->nofURFs * sizeof(*data->urf_to_bcc));
168 /* create a mapping from RCFs to URFs */
169 data->rcf_to_urf = malloc(data->nofRCFs * sizeof(*data->rcf_to_urf));
170 urf_index = 0;
171 rcf_index = 0;
172 for (i = 0; i < data->bccGraphs->nof_bcc; ++i) {
173 for (j = 0; j < data->nofURFsPerBCC[i]; ++j, ++urf_index) {
174 data->urf_to_bcc[urf_index][0] = i;
175 data->urf_to_bcc[urf_index][1] = j;
176 for (k = 0; k < data->urfInfoPerBCC[i]->nofCFsPerURF[j]; ++k, ++rcf_index) {
177 data->rcf_to_urf[rcf_index][0] = urf_index;
178 data->rcf_to_urf[rcf_index][1] = k;
179 }
180 }
181 }
182
183 data->graph = gra;
184
185 return data;
186 }
187
188 /* public, free memory */
RDL_deleteData(RDL_data * data)189 void RDL_deleteData(RDL_data *data)
190 {
191 unsigned i;
192
193 for (i = 0; i < data->bccGraphs->nof_bcc; ++i) {
194 RDL_deleteAPSP(data->spiPerBCC[i], data->bccGraphs->bcc_graphs[i]->V);
195 RDL_deleteCycleFams(data->CFsPerBCC[i]);
196 if (data->nofURFsPerBCC[i] > 0) {
197 RDL_deleteURFInfo(data->urfInfoPerBCC[i]);
198 }
199 }
200 free(data->spiPerBCC);
201 free(data->CFsPerBCC);
202 free(data->nofURFsPerBCC);
203 free(data->nofRCFsPerBCC);
204 free(data->urfInfoPerBCC);
205 RDL_deleteBCCGraph(data->bccGraphs);
206 free(data->urf_to_bcc);
207 free(data->rcf_to_urf);
208
209 RDL_deleteGraph(data->graph);
210 free(data);
211 }
212
213 /* public, get the total number of URFs */
RDL_getNofURF(const RDL_data * data)214 unsigned RDL_getNofURF(const RDL_data *data)
215 {
216 if (!data) {
217 RDL_outputFunc(RDL_ERROR, "RDL_data is NULL!\n");
218 return RDL_INVALID_RESULT;
219 }
220 return data->nofURFs;
221 }
222
223 /* public, get the total number of RCFs */
RDL_getNofRCF(const RDL_data * data)224 unsigned RDL_getNofRCF(const RDL_data *data)
225 {
226 if (!data) {
227 RDL_outputFunc(RDL_ERROR, "RDL_data is NULL!\n");
228 return RDL_INVALID_RESULT;
229 }
230 return data->nofRCFs;
231 }
232
233 /*
234 * private
235 * return the weight for INTERNAL indices,
236 * urf_internal_index relative to bcc_index and rcf_internal_index relative to URF
237 */
RDL_getWeight_internal(const RDL_data * data,unsigned bcc_index,unsigned urf_internal_index,unsigned rcf_internal_index)238 static unsigned RDL_getWeight_internal(const RDL_data *data,
239 unsigned bcc_index, unsigned urf_internal_index, unsigned rcf_internal_index)
240 {
241 return data->urfInfoPerBCC[bcc_index]->URFs[urf_internal_index][rcf_internal_index]->weight;
242 }
243
244 /* public, get weight for the given URF */
RDL_getWeightForURF(const RDL_data * data,unsigned index)245 unsigned RDL_getWeightForURF(const RDL_data *data, unsigned index)
246 {
247 unsigned bcc_index, internal_index;
248 if (!data) {
249 RDL_outputFunc(RDL_ERROR, "RDL_data is NULL!\n");
250 return RDL_INVALID_RESULT;
251 }
252
253 if (index >= data->nofURFs) {
254 RDL_outputFunc(RDL_ERROR, "invalid index: %u\n", index);
255 return RDL_INVALID_RESULT;
256 }
257 /* ger internal index */
258 bcc_index = data->urf_to_bcc[index][0];
259 internal_index = data->urf_to_bcc[index][1];
260 return RDL_getWeight_internal(data, bcc_index, internal_index, 0);
261 }
262
263 /* public, get weight for the given RCF */
RDL_getWeightForRCF(const RDL_data * data,unsigned index)264 unsigned RDL_getWeightForRCF(const RDL_data *data, unsigned index)
265 {
266 unsigned bcc_index, urf_internal_index, rcf_internal_index, urf_index;
267 if (!data) {
268 RDL_outputFunc(RDL_ERROR, "RDL_data is NULL!\n");
269 return RDL_INVALID_RESULT;
270 }
271
272 if (index >= data->nofRCFs) {
273 RDL_outputFunc(RDL_ERROR, "invalid index: %u\n", index);
274 return RDL_INVALID_RESULT;
275 }
276
277 /* map rcf to urf and urf to bcc */
278 urf_index = data->rcf_to_urf[index][0];
279 rcf_internal_index = data->rcf_to_urf[index][1];
280 bcc_index = data->urf_to_bcc[urf_index][0];
281 urf_internal_index = data->urf_to_bcc[urf_index][1];
282 return RDL_getWeight_internal(data, bcc_index,
283 urf_internal_index, rcf_internal_index);
284 }
285
286 /*
287 * private
288 * return the nodes for INTERNAL indices,
289 * urf_internal_index relative to bcc_index and rcf_internal_index relative to URF
290 */
RDL_getNodes_internal(const RDL_data * data,unsigned bcc_index,unsigned urf_internal_index,unsigned rcf_internal_index,char * atoms)291 static void RDL_getNodes_internal(const RDL_data *data, unsigned bcc_index,
292 unsigned urf_internal_index, unsigned rcf_internal_index, char* atoms)
293 {
294 const RDL_cfam **URF;
295 char *visited;
296 const RDL_graph* graph;
297
298 graph = data->bccGraphs->bcc_graphs[bcc_index];
299
300 URF = (const RDL_cfam **)data->urfInfoPerBCC[bcc_index]->URFs[urf_internal_index];
301
302 visited = malloc(graph->V * sizeof(*visited));
303
304 /* BFS on both shortest path graphs */
305 memset(visited, 0, graph->V * sizeof(*visited));
306 RDL_giveVertices(URF[rcf_internal_index]->r, URF[rcf_internal_index]->q,
307 atoms, data->spiPerBCC[bcc_index], visited);
308
309 memset(visited, 0, graph->V * sizeof(*visited));
310 RDL_giveVertices(URF[rcf_internal_index]->r, URF[rcf_internal_index]->p,
311 atoms, data->spiPerBCC[bcc_index], visited);
312
313 if(URF[rcf_internal_index]->x < UINT_MAX) /*even cycle*/ {
314 atoms[URF[rcf_internal_index]->x] = 1;
315 }
316 free(visited);
317 }
318
319
320 /* private
321 * gives an array of indices of nodes that are contained in the URF with the
322 * given index. Array is terminated by UINT_MAX
323 */
RDL_getNodesURF(const RDL_data * data,unsigned index)324 static RDL_node *RDL_getNodesURF(const RDL_data *data, unsigned index)
325 {
326 unsigned i,nofFams,nextfree=0,alloced, bcc_index, internal_index;
327 char *atoms;
328 RDL_node *result;
329 const RDL_graph* graph;
330
331 bcc_index = data->urf_to_bcc[index][0];
332 internal_index = data->urf_to_bcc[index][1];
333 graph = data->bccGraphs->bcc_graphs[bcc_index];
334 atoms = malloc(graph->V * sizeof(*atoms));
335 memset(atoms, 0, graph->V * sizeof(*atoms));
336
337 nofFams = data->urfInfoPerBCC[bcc_index]->nofCFsPerURF[internal_index];
338 alloced = RDL_RESERVED_START;
339 result = malloc(alloced * sizeof(*result));
340
341 /* iterate over all RCFs in this URFs and collect data in one bitset (atoms) */
342 for(i=0; i<nofFams; ++i) {
343 RDL_getNodes_internal(data, bcc_index, internal_index, i, atoms);
344 }
345
346 /* translate into a dynamic table */
347 for(i=0; i<graph->V; ++i) {
348 if(atoms[i] == 1) {
349 if(nextfree == alloced) {/*double the size*/
350 alloced *= 2;
351 result = realloc(result, alloced*sizeof(*result));
352 }
353 result[nextfree++] = data->bccGraphs->node_from_bcc_mapping[bcc_index][i];
354 }
355 }
356
357 result = realloc(result, (nextfree+1)*sizeof(*result));
358
359 result[nextfree] = UINT_MAX;
360 free(atoms);
361
362 return result;
363 }
364
365 /* private
366 * gives an array of indices of nodes that are contained in the RRF with the
367 * given index. Array is terminated by UINT_MAX
368 */
RDL_getNodesRCF(const RDL_data * data,unsigned index)369 static RDL_node *RDL_getNodesRCF(const RDL_data *data, unsigned index)
370 {
371 unsigned i,nextfree=0,alloced, bcc_index,
372 urf_internal_index, rcf_internal_index, urf_index;
373 char *atoms;
374 RDL_node *result;
375 const RDL_graph* graph;
376
377 urf_index = data->rcf_to_urf[index][0];
378 rcf_internal_index = data->rcf_to_urf[index][1];
379 bcc_index = data->urf_to_bcc[urf_index][0];
380 urf_internal_index = data->urf_to_bcc[urf_index][1];
381 graph = data->bccGraphs->bcc_graphs[bcc_index];
382 atoms = malloc(graph->V * sizeof(*atoms));
383 memset(atoms, 0, graph->V * sizeof(*atoms));
384
385 alloced = RDL_RESERVED_START;
386 result = malloc(alloced * sizeof(*result));
387
388 /* save the nodes into bitset */
389 RDL_getNodes_internal(data, bcc_index, urf_internal_index,
390 rcf_internal_index, atoms);
391
392 /* translate into a dynamic table */
393 for(i=0; i<graph->V; ++i) {
394 if(atoms[i] == 1) {
395 if(nextfree == alloced) {/*double the size*/
396 alloced *= 2;
397 result = realloc(result, alloced*sizeof(*result));
398 }
399 result[nextfree++] = data->bccGraphs->node_from_bcc_mapping[bcc_index][i];
400 }
401 }
402
403 result = realloc(result, (nextfree+1)*sizeof(*result));
404
405 result[nextfree] = UINT_MAX;
406 free(atoms);
407
408 return result;
409 }
410
411 /* public, calculate the number of RCs */
RDL_getNofRC(const RDL_data * data)412 double RDL_getNofRC(const RDL_data *data)
413 {
414 double result = 0, intermediate;
415 unsigned i;
416
417 if (!data) {
418 RDL_outputFunc(RDL_ERROR, "RDL_data is NULL!\n");
419 return RDL_INVALID_RC_COUNT;
420 }
421
422 /* add up results for URFs */
423 for (i = 0; i < data->nofURFs; ++i) {
424 intermediate = RDL_getNofRCForURF(data, i);
425 if (intermediate == RDL_INVALID_RC_COUNT) {
426 return RDL_INVALID_RC_COUNT;
427 }
428
429 result += intermediate;
430 }
431
432 return result;
433 }
434
435 /*
436 * private
437 * return the # RCs for INTERNAL indices,
438 * urf_internal_index relative to bcc_index and rcf_internal_index relative to URF
439 */
RDL_getNofRCForRCF_internal(const RDL_data * data,unsigned bcc_index,unsigned urf_internal_index,unsigned rcf_internal_index)440 static double RDL_getNofRCForRCF_internal(const RDL_data *data,
441 unsigned bcc_index, unsigned urf_internal_index,
442 unsigned rcf_internal_index)
443 {
444 double nofPaths1, nofPaths2, result;
445 const double prod_limit = sqrt(DBL_MAX) - 1.0;
446 const RDL_cfam** URF;
447 const RDL_graph* graph;
448
449 result = 0.0;
450
451 graph = data->bccGraphs->bcc_graphs[bcc_index];
452
453 URF = (const RDL_cfam **)data->urfInfoPerBCC[bcc_index]->URFs[urf_internal_index];
454
455 /* count the number of paths one both sides */
456 nofPaths1 = RDL_countPaths(URF[rcf_internal_index]->r, URF[rcf_internal_index]->q,
457 graph->V, data->spiPerBCC[bcc_index]);
458 nofPaths2 = RDL_countPaths(URF[rcf_internal_index]->r, URF[rcf_internal_index]->p,
459 graph->V, data->spiPerBCC[bcc_index]);
460
461 result = nofPaths1 * nofPaths2;
462
463 /* check if either of the number paths is larger than what we can multiply */
464 if (nofPaths1 >= prod_limit || nofPaths2 >= prod_limit) {
465 RDL_outputFunc(RDL_WARNING, "result overflow when counting paths!\n");
466 return RDL_INVALID_RC_COUNT;
467 }
468
469 return result;
470 }
471
472 /* public, return the # RCs for given RCF */
RDL_getNofRCForRCF(const RDL_data * data,unsigned index)473 double RDL_getNofRCForRCF(const RDL_data *data, unsigned index)
474 {
475 unsigned bcc_index, urf_id, urf_internal_index, rcf_internal_index;
476
477 if (!data) {
478 RDL_outputFunc(RDL_ERROR, "RDL_data is NULL!\n");
479 return RDL_INVALID_RC_COUNT;
480 }
481
482 if (index >= data->nofRCFs) {
483 RDL_outputFunc(RDL_ERROR, "invalid index: %u\n", index);
484 return RDL_INVALID_RC_COUNT;
485 }
486
487 /* map indices */
488 urf_id = data->rcf_to_urf[index][0];
489 rcf_internal_index = data->rcf_to_urf[index][1];
490
491 bcc_index = data->urf_to_bcc[urf_id][0];
492 urf_internal_index = data->urf_to_bcc[urf_id][1];
493
494 return RDL_getNofRCForRCF_internal(data, bcc_index,
495 urf_internal_index, rcf_internal_index);
496 }
497
498 /* public, return the # RCs for given URF */
RDL_getNofRCForURF(const RDL_data * data,unsigned index)499 double RDL_getNofRCForURF(const RDL_data *data, unsigned index)
500 {
501 unsigned i,nofFams, bcc_index, internal_index;
502 double result=0, prod;
503
504 const double sum_limit = DBL_MAX/2.0 - 1.0;
505
506 if (!data) {
507 RDL_outputFunc(RDL_ERROR, "RDL_data is NULL!\n");
508 return RDL_INVALID_RC_COUNT;
509 }
510
511 if (index >= data->nofURFs) {
512 RDL_outputFunc(RDL_ERROR, "invalid index: %u\n", index);
513 return RDL_INVALID_RC_COUNT;
514 }
515
516 /* map indices */
517 bcc_index = data->urf_to_bcc[index][0];
518 internal_index = data->urf_to_bcc[index][1];
519
520 nofFams = data->urfInfoPerBCC[bcc_index]->nofCFsPerURF[internal_index];
521
522 /* iterate all RCFs in this URF */
523 for(i=0; i<nofFams; ++i) {
524 prod = RDL_getNofRCForRCF_internal(data, bcc_index, internal_index, i);
525
526 /* check if any summand is larger than limit */
527 if (prod >= sum_limit || result >= sum_limit) {
528 RDL_outputFunc(RDL_WARNING, "result overflow when counting paths!\n");
529 return RDL_INVALID_RC_COUNT;
530 }
531
532 result += prod;
533 }
534
535 return result;
536 }
537
538 /* private
539 * return the edges for INTERNAL indices,
540 * urf_internal_index relative to bcc_index and rcf_internal_index relative to URF
541 */
RDL_getEdges_internal(const RDL_data * data,unsigned bcc_index,unsigned urf_internal_index,unsigned rcf_internal_index,char * edges)542 static void RDL_getEdges_internal(const RDL_data *data,
543 unsigned bcc_index, unsigned urf_internal_index,
544 unsigned rcf_internal_index, char* edges)
545 {
546 const RDL_cfam **URF;
547 char *visited;
548 const RDL_graph* graph;
549
550 graph = data->bccGraphs->bcc_graphs[bcc_index];
551
552 URF = (const RDL_cfam **)data->urfInfoPerBCC[bcc_index]->URFs[urf_internal_index];
553
554 /* perform BFS on both paths and collect edges */
555 visited = malloc(graph->V * sizeof(*visited));
556 memset(visited, 0, graph->V * sizeof(*visited));
557
558 RDL_giveEdges(URF[rcf_internal_index]->r, URF[rcf_internal_index]->q,
559 edges, graph, data->spiPerBCC[bcc_index], visited);
560
561 memset(visited, 0, graph->V * sizeof(*visited));
562 RDL_giveEdges(URF[rcf_internal_index]->r, URF[rcf_internal_index]->p,
563 edges, graph, data->spiPerBCC[bcc_index], visited);
564
565 /*
566 * in contrast to the nodes, we have to add additional edges, because we're
567 * looking at cycles...
568 */
569 if(URF[rcf_internal_index]->x < UINT_MAX) /*even cycle*/ {
570 edges[RDL_edgeId(graph,URF[rcf_internal_index]->q,URF[rcf_internal_index]->x)] = 1;
571 edges[RDL_edgeId(graph,URF[rcf_internal_index]->p,URF[rcf_internal_index]->x)] = 1;
572 }
573 else /*odd cycle*/ {
574 edges[RDL_edgeId(graph,URF[rcf_internal_index]->q,URF[rcf_internal_index]->p)] = 1;
575 }
576 free(visited);
577 }
578
579
580 /* private
581 * gives an array of indices of edges that are contained in the URF with the
582 * given index. Array is terminated by UINT_MAX
583 */
RDL_getEdgesURF(const RDL_data * data,unsigned index)584 static unsigned *RDL_getEdgesURF(const RDL_data *data, unsigned index)
585 {
586 unsigned i,nofFams,nextfree=0,alloced, bcc_index, internal_index;
587 char *edges;
588 unsigned *result;
589 const RDL_graph* graph;
590
591 /* map indices */
592 bcc_index = data->urf_to_bcc[index][0];
593 internal_index = data->urf_to_bcc[index][1];
594 graph = data->bccGraphs->bcc_graphs[bcc_index];
595 edges = malloc(graph->E * sizeof(*edges));
596 memset(edges, 0, graph->E * sizeof(*edges));
597
598 nofFams = data->urfInfoPerBCC[bcc_index]->nofCFsPerURF[internal_index];
599 alloced = RDL_RESERVED_START;
600 result = malloc(alloced * sizeof(*result));
601
602 /* iterate over all RCFs in this URF and collect results in bitset (edges) */
603 for(i=0; i<nofFams; ++i) {
604 RDL_getEdges_internal(data, bcc_index, internal_index, i, edges);
605 }
606
607 /* translate into dynamic table */
608 for(i=0; i<graph->E; ++i) {
609 if(edges[i] == 1) {
610 if(nextfree == alloced)
611 {/*double the size*/
612 alloced *= 2;
613 result = realloc(result, alloced*sizeof(*result));
614 }
615 result[nextfree++] = data->bccGraphs->edge_from_bcc_mapping[bcc_index][i];
616 }
617 }
618 result = realloc(result, (nextfree+1)*sizeof(*result));
619
620 result[nextfree] = UINT_MAX;
621
622 free(edges);
623 return result;
624 }
625
626 /* private
627 * gives an array of indices of edges that are contained in the RCF with the
628 * given index. Array is terminated by UINT_MAX
629 */
RDL_getEdgesRCF(const RDL_data * data,unsigned index)630 static unsigned *RDL_getEdgesRCF(const RDL_data *data, unsigned index)
631 {
632 unsigned j,nextfree=0,alloced, urf_index, bcc_index,
633 urf_internal_index, rcf_internal_index;
634 char *edges;
635 unsigned *result;
636 const RDL_graph* graph;
637
638 /* index mapping */
639 urf_index = data->rcf_to_urf[index][0];
640 rcf_internal_index = data->rcf_to_urf[index][1];
641 bcc_index = data->urf_to_bcc[urf_index][0];
642 urf_internal_index = data->urf_to_bcc[urf_index][1];
643 graph = data->bccGraphs->bcc_graphs[bcc_index];
644 edges = malloc(graph->E * sizeof(*edges));
645 memset(edges, 0, graph->E * sizeof(*edges));
646
647 alloced = RDL_RESERVED_START;
648 result = malloc(alloced * sizeof(*result));
649
650 RDL_getEdges_internal(data, bcc_index, urf_internal_index,
651 rcf_internal_index, edges);
652
653 /* translate into dynamic table */
654 for(j=0; j<graph->E; ++j) {
655 if(edges[j] == 1) {
656 if(nextfree == alloced)
657 {/*double the size*/
658 alloced *= 2;
659 result = realloc(result, alloced*sizeof(*result));
660 }
661 result[nextfree++] = data->bccGraphs->edge_from_bcc_mapping[bcc_index][j];
662 }
663 }
664
665 result = realloc(result, (nextfree+1)*sizeof(*result));
666
667 result[nextfree] = UINT_MAX;
668
669 free(edges);
670 return result;
671 }
672
673
674 /* private, calls getNodesURF() or getEdgesURF() depending on mode 'a' or 'b' */
RDL_giveURF(const RDL_data * data,unsigned index,char mode)675 static unsigned *RDL_giveURF(const RDL_data *data, unsigned index, char mode)
676 {
677 unsigned *result;
678 if(mode == 'a')
679 {
680 result = RDL_getNodesURF(data, index);
681 }
682 else if(mode == 'b')
683 {
684 result = RDL_getEdgesURF(data, index);
685 }
686 else
687 {
688 RDL_outputFunc(RDL_ERROR, "tried to call 'RDL_giveURF()' with invalid mode '%c'\n", mode);
689 /* cannot occur when using interface */
690 assert(0);
691 return NULL;
692 }
693
694 return result;
695 }
696
697 /* private, calls getNodesRCF() or getEdgesRCF() depending on mode 'a' or 'b' */
RDL_giveRCF(const RDL_data * data,unsigned index,char mode)698 static unsigned *RDL_giveRCF(const RDL_data *data, unsigned index, char mode)
699 {
700 unsigned *result;
701 if(mode == 'a')
702 {
703 result = RDL_getNodesRCF(data, index);
704 }
705 else if(mode == 'b')
706 {
707 result = RDL_getEdgesRCF(data, index);
708 }
709 else
710 {
711 RDL_outputFunc(RDL_ERROR, "tried to call 'RDL_giveRCF()' with invalid mode '%c'\n", mode);
712 /* cannot occur when using interface */
713 assert(0);
714 return NULL;
715 }
716
717 return result;
718 }
719
720 /* public, function for retrieving nodes in an URF */
RDL_getNodesForURF(const RDL_data * data,unsigned index,RDL_node ** ptr)721 unsigned RDL_getNodesForURF(const RDL_data *data, unsigned index, RDL_node **ptr)
722 {
723 unsigned i;
724
725 if (!data) {
726 RDL_outputFunc(RDL_ERROR, "RDL_data is NULL!\n");
727 (*ptr) = malloc(sizeof(**ptr));
728 return RDL_INVALID_RESULT;
729 }
730
731 if (index >= data->nofURFs) {
732 RDL_outputFunc(RDL_ERROR, "invalid index: %u\n", index);
733 (*ptr) = malloc(sizeof(**ptr));
734 return RDL_INVALID_RESULT;
735 }
736
737 (*ptr) = RDL_getNodesURF(data, index);
738 for(i=0; (*ptr)[i]<UINT_MAX; ++i); /*counts the number of atoms*/
739 return i;
740 }
741
742 /* public, function for retrieving nodes in an RCF */
RDL_getNodesForRCF(const RDL_data * data,unsigned index,RDL_node ** ptr)743 unsigned RDL_getNodesForRCF(const RDL_data *data, unsigned index, RDL_node **ptr)
744 {
745 unsigned i;
746
747 if (!data) {
748 RDL_outputFunc(RDL_ERROR, "RDL_data is NULL!\n");
749 (*ptr) = malloc(sizeof(**ptr));
750 return RDL_INVALID_RESULT;
751 }
752
753 if (index >= data->nofRCFs) {
754 RDL_outputFunc(RDL_ERROR, "invalid index: %u\n", index);
755 (*ptr) = malloc(sizeof(**ptr));
756 return RDL_INVALID_RESULT;
757 }
758
759 (*ptr) = RDL_getNodesRCF(data, index);
760 for(i=0; (*ptr)[i]<UINT_MAX; ++i); /*counts the number of atoms*/
761 return i;
762 }
763
764 /* public, function for retrieving edges of URF */
RDL_getEdgesForURF(const RDL_data * data,unsigned index,RDL_edge ** ptr)765 unsigned RDL_getEdgesForURF(const RDL_data *data, unsigned index, RDL_edge **ptr)
766 {
767 unsigned nextfree, alloced;
768 RDL_edge *result;
769 unsigned *edgeIndices;
770 unsigned i;
771
772 if (!data) {
773 RDL_outputFunc(RDL_ERROR, "RDL_data is NULL!\n");
774 (*ptr) = malloc(sizeof(**ptr));
775 return RDL_INVALID_RESULT;
776 }
777
778 if (index >= data->nofURFs) {
779 RDL_outputFunc(RDL_ERROR, "invalid index: %u\n", index);
780 (*ptr) = malloc(sizeof(**ptr));
781 return RDL_INVALID_RESULT;
782 }
783
784 nextfree = 0;
785 alloced = RDL_RESERVED_START;
786 result = malloc(alloced * sizeof(*result));
787 edgeIndices = RDL_getEdgesURF(data, index);
788 /* translate result from edge indices to edges */
789 for(i=0; edgeIndices[i]<UINT_MAX; ++i)
790 {
791 if(nextfree == alloced)/*more space needed in result*/
792 {
793 alloced *= 2; /* double the space */
794 result = realloc(result, alloced * sizeof(*result));
795 }
796 result[nextfree][0] = data->graph->edges[edgeIndices[i]][0];
797 result[nextfree][1] = data->graph->edges[edgeIndices[i]][1];
798 ++nextfree;
799 }
800 result = realloc(result, nextfree * sizeof(*result));
801 free(edgeIndices);
802 (*ptr) = result;
803 return nextfree;
804 }
805
806 /* public, function for retrieving edges of RCF */
RDL_getEdgesForRCF(const RDL_data * data,unsigned index,RDL_edge ** ptr)807 unsigned RDL_getEdgesForRCF(const RDL_data *data, unsigned index, RDL_edge **ptr)
808 {
809 unsigned nextfree, alloced;
810 RDL_edge *result;
811 unsigned *edgeIndices;
812 unsigned i;
813
814 if (!data) {
815 RDL_outputFunc(RDL_ERROR, "RDL_data is NULL!\n");
816 (*ptr) = malloc(sizeof(**ptr));
817 return RDL_INVALID_RESULT;
818 }
819
820 if (index >= data->nofRCFs) {
821 RDL_outputFunc(RDL_ERROR, "invalid index: %u\n", index);
822 (*ptr) = malloc(sizeof(**ptr));
823 return RDL_INVALID_RESULT;
824 }
825
826 nextfree = 0;
827 alloced = RDL_RESERVED_START;
828 result = malloc(alloced * sizeof(*result));
829 edgeIndices = RDL_getEdgesRCF(data, index);
830 /* translate result from edge indices to edges */
831 for(i=0; edgeIndices[i]<UINT_MAX; ++i)
832 {
833 if(nextfree == alloced)/*more space needed in result*/
834 {
835 alloced *= 2; /* double the space */
836 result = realloc(result, alloced * sizeof(*result));
837 }
838 result[nextfree][0] = data->graph->edges[edgeIndices[i]][0];
839 result[nextfree][1] = data->graph->edges[edgeIndices[i]][1];
840 ++nextfree;
841 }
842 result = realloc(result, nextfree * sizeof(*result));
843 free(edgeIndices);
844 (*ptr) = result;
845 return nextfree;
846 }
847
848 /* public, to delete result of RDL_getCyclesChar() */
RDL_deleteCyclesChar(char ** cycles)849 void RDL_deleteCyclesChar(char **cycles)
850 {
851 unsigned i;
852 for(i=0; cycles[i]!=NULL; ++i)
853 {
854 free(cycles[i]);
855 }
856 free(cycles);
857 }
858
859 /* public, delete cycle */
RDL_deleteCycle(RDL_cycle * cycle)860 void RDL_deleteCycle(RDL_cycle *cycle)
861 {
862 free(cycle->edges);
863 free(cycle);
864 }
865
866 /* public, delete cycles */
RDL_deleteCycles(RDL_cycle ** cycles,unsigned number)867 void RDL_deleteCycles(RDL_cycle **cycles, unsigned number)
868 {
869 unsigned i;
870 for(i=0; i<number; ++i)
871 {
872 RDL_deleteCycle(cycles[i]);
873 }
874 free(cycles);
875 }
876
877 /*
878 * private
879 * Gives all families containing the object, which can be an atom or a bond.
880 mode:
881 - 'a': nodes
882 - 'b': edges
883 returns an array of integers containing all indices of families containing the
884 object. The array ends with a terminating UINT_MAX on its last position and has
885 to be deallocated with 'free()'
886 */
RDL_listFamilies(const RDL_data * data,unsigned object,char mode,char family)887 static unsigned *RDL_listFamilies(const RDL_data *data, unsigned object,
888 char mode, char family)
889 {
890 unsigned *result;
891 unsigned nof_families;
892 unsigned nextfree=0, alloced=RDL_RESERVED_START;
893 unsigned *objects;
894 unsigned i,j, bcc_index, target_bcc, urf_index;
895 char contained, can_be_contained;
896
897 if(!(mode == 'a' || mode == 'b'))
898 {
899 RDL_outputFunc(RDL_ERROR, "tried to call 'RDL_listFamilies()' with invalid mode '%c'\n",mode);
900 /* cannot occur when using interface */
901 assert(0);
902 return NULL;
903 }
904
905 unsigned* (*giveFamily) (const RDL_data*, unsigned, char) = NULL;
906
907 if (family == 'u') {
908 nof_families = data->nofURFs;
909 giveFamily = RDL_giveURF;
910 }
911 else if (family == 'r') {
912 nof_families = data->nofRCFs;
913 giveFamily = RDL_giveRCF;
914 }
915 else {
916 RDL_outputFunc(RDL_ERROR, "tried to call 'RDL_listFamilies()' with invalid family '%c'\n",family);
917 /* cannot occur when using interface */
918 assert(0);
919 return NULL;
920 }
921
922 result=malloc(alloced * sizeof(*result));
923 for(i = 0; i < nof_families; ++i)
924 {
925 if (family == 'u') {
926 urf_index = i;
927 }
928 else if (family == 'r') {
929 urf_index = data->rcf_to_urf[i][0];
930 }
931
932 bcc_index = data->urf_to_bcc[urf_index][0];
933
934 /*
935 * check if object belongs to this BCC at all,
936 * if not it can't be in the URF either
937 */
938 can_be_contained = 0;
939 if (mode == 'a') {
940 for (j = 0; j < data->bccGraphs->nof_bcc_per_node[object]; ++j) {
941 target_bcc = data->bccGraphs->node_to_bcc_mapping[object][2*j];
942 if (target_bcc == bcc_index) {
943 can_be_contained = 1;
944 break;
945 }
946 }
947 }
948 else {
949 target_bcc = data->bccGraphs->edge_to_bcc_mapping[object][0];
950 if (target_bcc == bcc_index) {
951 can_be_contained = 1;
952 }
953 }
954
955 contained = 0;
956 if (can_be_contained) {
957 objects = giveFamily(data, i, mode);
958 for(j=0; objects[j]<UINT_MAX; ++j)
959 {
960 if(objects[j] == object)
961 {
962 contained = 1;
963 break;
964 }
965 }
966 free(objects);
967 }
968 if (contained) {
969 if(nextfree == alloced) {
970 alloced *= 2;
971 result = realloc(result, alloced*sizeof(*result));
972 }
973 result[nextfree++] = i;
974 }
975 }
976
977 result = realloc(result, (nextfree+1)*sizeof(*result));
978 result[nextfree] = UINT_MAX;
979 return result;
980 }
981
982 /* private, get families containing a node */
RDL_getFamiliesContainingNode_internal(const RDL_data * data,RDL_node object,unsigned ** ptr,char family)983 static unsigned RDL_getFamiliesContainingNode_internal(
984 const RDL_data *data, RDL_node object, unsigned **ptr,
985 char family)
986 {
987 unsigned i;
988
989 if (!data) {
990 RDL_outputFunc(RDL_ERROR, "RDL_data is NULL!\n");
991 (*ptr) = malloc(sizeof(**ptr));
992 return RDL_INVALID_RESULT;
993 }
994
995 if (object >= data->graph->V) {
996 RDL_outputFunc(RDL_ERROR, "invalid node: %u\n", object);
997 (*ptr) = malloc(sizeof(**ptr));
998 return RDL_INVALID_RESULT;
999 }
1000
1001 if (data->nofURFs < 1) {
1002 (*ptr) = malloc(sizeof(**ptr));
1003 return 0;
1004 }
1005
1006 *ptr = RDL_listFamilies(data, object, 'a', family);
1007 for(i=0; (*ptr)[i]<UINT_MAX; ++i);
1008 return i;
1009 }
1010
1011 /* public, get the RCF indices with this node */
RDL_getRCFsContainingNode(const RDL_data * data,RDL_node object,unsigned ** ptr)1012 unsigned RDL_getRCFsContainingNode(const RDL_data *data, RDL_node object,
1013 unsigned **ptr)
1014 {
1015 return RDL_getFamiliesContainingNode_internal(data, object, ptr, 'r');
1016 }
1017
1018 /* public, get the URF indices with this node */
RDL_getURFsContainingNode(const RDL_data * data,RDL_node object,unsigned ** ptr)1019 unsigned RDL_getURFsContainingNode(const RDL_data *data, RDL_node object,
1020 unsigned **ptr)
1021 {
1022 return RDL_getFamiliesContainingNode_internal(data, object, ptr, 'u');
1023 }
1024
1025 /* private, get the family indices with this edge */
RDL_getFamiliesContainingEdge_internal(const RDL_data * data,RDL_node node1,RDL_node node2,unsigned ** ptr,char family)1026 static unsigned RDL_getFamiliesContainingEdge_internal(
1027 const RDL_data *data, RDL_node node1, RDL_node node2, unsigned **ptr,
1028 char family)
1029 {
1030 unsigned i, edge;
1031
1032 if (!data) {
1033 RDL_outputFunc(RDL_ERROR, "RDL_data is NULL!\n");
1034 (*ptr) = malloc(sizeof(**ptr));
1035 return RDL_INVALID_RESULT;
1036 }
1037
1038 if (node1 >= data->graph->V || node2 >= data->graph->V) {
1039 RDL_outputFunc(RDL_ERROR, "invalid edge: %u %u\n", node1, node2);
1040 (*ptr) = malloc(sizeof(**ptr));
1041 return RDL_INVALID_RESULT;
1042 }
1043
1044 edge = RDL_edgeId(data->graph, node1, node2);
1045
1046 /* check if this edge exists at all */
1047 if (edge == RDL_INVALID_RESULT) {
1048 RDL_outputFunc(RDL_ERROR, "invalid edge: %u %u\n", node1, node2);
1049 (*ptr) = malloc(sizeof(**ptr));
1050 return RDL_INVALID_RESULT;
1051 }
1052
1053 if (data->nofURFs < 1) {
1054 (*ptr) = malloc(sizeof(**ptr));
1055 return 0;
1056 }
1057
1058 *ptr = RDL_listFamilies(data, edge, 'b', family);
1059 for(i=0; (*ptr)[i]<UINT_MAX; ++i);
1060 return i;
1061 }
1062
1063
1064 /* public, get the RCF indices with this edge */
RDL_getRCFsContainingEdge(const RDL_data * data,RDL_node node1,RDL_node node2,unsigned ** ptr)1065 unsigned RDL_getRCFsContainingEdge(const RDL_data *data, RDL_node node1,
1066 RDL_node node2, unsigned **ptr)
1067 {
1068 return RDL_getFamiliesContainingEdge_internal(data, node1, node2, ptr, 'r');
1069 }
1070
1071 /* public, get the URF indices with this edge */
RDL_getURFsContainingEdge(const RDL_data * data,RDL_node node1,RDL_node node2,unsigned ** ptr)1072 unsigned RDL_getURFsContainingEdge(const RDL_data *data, RDL_node node1,
1073 RDL_node node2, unsigned **ptr)
1074 {
1075 return RDL_getFamiliesContainingEdge_internal(data, node1, node2, ptr, 'u');
1076 }
1077
1078 /* public, get the number of URFs that this node is part of */
RDL_getNofURFContainingNode(const RDL_data * data,RDL_node node)1079 unsigned RDL_getNofURFContainingNode(const RDL_data *data, RDL_node node)
1080 {
1081 unsigned number;
1082 unsigned *arr;
1083 number = RDL_getURFsContainingNode(data, node, &arr);
1084 free(arr);
1085 return number;
1086 }
1087
1088 /* public, get the number of URFs that this edge is part of */
RDL_getNofURFContainingEdge(const RDL_data * data,RDL_node node1,RDL_node node2)1089 unsigned RDL_getNofURFContainingEdge(const RDL_data *data, RDL_node node1, RDL_node node2)
1090 {
1091 unsigned number;
1092 unsigned *arr;
1093 number = RDL_getURFsContainingEdge(data, node1, node2, &arr);
1094 free(arr);
1095 return number;
1096 }
1097
1098 /* public, get the number of RCFs that this node is part of */
RDL_getNofRCFContainingNode(const RDL_data * data,RDL_node node)1099 unsigned RDL_getNofRCFContainingNode(const RDL_data *data, RDL_node node)
1100 {
1101 unsigned number;
1102 unsigned *arr;
1103 number = RDL_getRCFsContainingNode(data, node, &arr);
1104 free(arr);
1105 return number;
1106 }
1107
1108 /* public, get the number of RCFs that this edge is part of */
RDL_getNofRCFContainingEdge(const RDL_data * data,RDL_node node1,RDL_node node2)1109 unsigned RDL_getNofRCFContainingEdge(const RDL_data *data, RDL_node node1, RDL_node node2)
1110 {
1111 unsigned number;
1112 unsigned *arr;
1113 number = RDL_getRCFsContainingEdge(data, node1, node2, &arr);
1114 free(arr);
1115 return number;
1116 }
1117
1118 /* construct a SSSR */
RDL_getSSSR(const RDL_data * data,RDL_cycle *** ptr)1119 unsigned RDL_getSSSR(const RDL_data *data, RDL_cycle ***ptr)
1120 {
1121 unsigned j, k, rcf=0, urf=0;
1122 RDL_cycle **result;
1123 unsigned size, added, currBond;
1124 unsigned bcc_index, internal_index;
1125 char* prototype;
1126 const RDL_graph* curr_graph;
1127 unsigned total_counter, alloced;
1128 unsigned edge;
1129 unsigned char *currentCycle;
1130 unsigned char **basisCycles;
1131 unsigned char **prototypesForGaussian;
1132 unsigned currentBasisCyclesSize;
1133 unsigned oldBasisCyclesSize;
1134 unsigned compressedSize = 0;
1135 const unsigned char* empty_cycle;
1136
1137
1138 if (!data) {
1139 RDL_outputFunc(RDL_ERROR, "RDL_data is NULL!\n");
1140 (*ptr) = malloc(sizeof(**ptr));
1141 return RDL_INVALID_RESULT;
1142 }
1143
1144 if (data->nofURFs < 1) {
1145 (*ptr) = malloc(sizeof(**ptr));
1146 return 0;
1147 }
1148
1149 total_counter = 0;
1150 if (data->graph->E < data->graph->V) {
1151 /*
1152 * if E - V + 1 < 1 <=> E - V < 0 <=> E < V
1153 *
1154 * graph is not connected and our heuristic for reservation
1155 * fails => allocate something ;)
1156 * */
1157 alloced = RDL_RESERVED_START;
1158 }
1159 else {
1160 alloced = data->graph->E - data->graph->V + 1;
1161 }
1162 result = malloc(alloced * sizeof(*result));
1163
1164 /* calculate basis for each BCC (and therefore for each CC) */
1165
1166 for (bcc_index = 0; bcc_index < data->bccGraphs->nof_bcc; ++bcc_index) {
1167 curr_graph = data->bccGraphs->bcc_graphs[bcc_index];
1168
1169 size=curr_graph->E - curr_graph->V + 1;
1170
1171 basisCycles = malloc(size * sizeof(*basisCycles));
1172 prototypesForGaussian =
1173 malloc(data->nofURFsPerBCC[bcc_index] * sizeof(*prototypesForGaussian));
1174
1175 /* copy the prototypes for gaussian elimination */
1176 /*
1177 * it is sufficient to take the first prototype for each URF
1178 * (the other's are linearly dependent anyway
1179 */
1180 for (internal_index = 0;
1181 internal_index < data->nofURFsPerBCC[bcc_index]; ++internal_index) {
1182 compressedSize = RDL_bitset_compressed(&(prototypesForGaussian[internal_index]),
1183 data->urfInfoPerBCC[bcc_index]->URFs[internal_index][0]->prototype,
1184 curr_graph->E);
1185 }
1186
1187 empty_cycle = malloc(compressedSize * sizeof(*empty_cycle));
1188 memset((unsigned char*)empty_cycle, 0, compressedSize * sizeof(*empty_cycle));
1189
1190 added = 0;
1191 currentBasisCyclesSize = 0;
1192
1193 for (internal_index = 0;
1194 internal_index < data->nofURFsPerBCC[bcc_index]; ++internal_index, ++urf) {
1195
1196 currentCycle = malloc(compressedSize * sizeof(*currentCycle));
1197 memcpy(currentCycle, prototypesForGaussian[internal_index],
1198 compressedSize * sizeof(*currentCycle));
1199
1200 /*
1201 * basisCycles is in row echelon form!result = realloc(result, nextfree * sizeof(*result));
1202 * [this corresponds to "add row operation"]
1203 */
1204 for (k = 0; k < currentBasisCyclesSize; ++k) {
1205 if (RDL_bitset_test(currentCycle, k)) {
1206 RDL_bitset_xor_inplace(currentCycle, basisCycles[k], compressedSize);
1207 }
1208 }
1209
1210 if (RDL_bitset_empty(currentCycle, empty_cycle, compressedSize)) {
1211 free(currentCycle);
1212 continue;
1213 }
1214 /*
1215 * the current cycle is indepedent of equal and smaller
1216 * sized cycles => part of the basis
1217 */
1218 oldBasisCyclesSize = currentBasisCyclesSize;
1219 basisCycles[currentBasisCyclesSize] = currentCycle;
1220 ++currentBasisCyclesSize;
1221
1222 /*
1223 * this is where the magic is happening: ensure that the basis is
1224 * indeed in row echelon form (we use the property throughout the algorithm)
1225 *
1226 * swap columns such that indeed the current ring with index currentBasisCycleSize-1
1227 * has a 1 at column currentBasisCycleSize-1
1228 * => ROW ECHELON FORM
1229 *
1230 * [this corresponds to the "swap columns operation" of gaussian elimination]
1231 */
1232 if (!RDL_bitset_test(currentCycle, oldBasisCyclesSize)) {
1233 for (k = oldBasisCyclesSize + 1; k < curr_graph->E; ++k) {
1234 if (RDL_bitset_test(currentCycle, k)) {
1235 RDL_swap_columns(basisCycles, currentBasisCyclesSize, oldBasisCyclesSize, k);
1236 RDL_swap_columns(prototypesForGaussian, data->nofURFsPerBCC[bcc_index], oldBasisCyclesSize, k);
1237 break;
1238 }
1239 }
1240 }
1241
1242 prototype = data->urfInfoPerBCC[bcc_index]->URFs[internal_index][0]->prototype;
1243
1244 /* can happen for unconnected graphs */
1245 if (total_counter >= alloced) {
1246 alloced *= 2;
1247 result = realloc(result, (alloced) * sizeof(*result));
1248 }
1249
1250 currBond = 0;
1251 result[total_counter] = malloc(sizeof(**result));
1252 result[total_counter]->edges = malloc(data->urfInfoPerBCC[bcc_index]->URFs[internal_index][0]->weight *
1253 sizeof(*(result[total_counter]->edges)));
1254 result[total_counter]->weight = data->urfInfoPerBCC[bcc_index]->URFs[internal_index][0]->weight;
1255 result[total_counter]->urf = urf;
1256 result[total_counter]->rcf = rcf;
1257 for(j=0; j < curr_graph->E; ++j) {
1258 if(prototype[j] == 1) {
1259 edge = data->bccGraphs->edge_from_bcc_mapping[bcc_index][j];
1260 result[total_counter]->edges[currBond][0] = data->graph->edges[edge][0];
1261 result[total_counter]->edges[currBond][1] = data->graph->edges[edge][1];
1262 ++currBond;
1263 }
1264 }
1265
1266 rcf += data->urfInfoPerBCC[bcc_index]->nofCFsPerURF[internal_index];
1267
1268 /*if enough inRDL_dependent cycles were found, break out of the loop*/
1269 ++total_counter;
1270 if(++added == size) {
1271 break;
1272 }
1273 }
1274
1275 for (k = 0; k < currentBasisCyclesSize; ++k) {
1276 free(basisCycles[k]);
1277 }
1278 free(basisCycles);
1279
1280 for (k = 0; k < data->nofURFsPerBCC[bcc_index]; ++k) {
1281 free(prototypesForGaussian[k]);
1282 }
1283 free(prototypesForGaussian);
1284 free((void*)empty_cycle);
1285 }
1286
1287 result = realloc(result, total_counter * sizeof(*result));
1288
1289 (*ptr) = result;
1290 return total_counter;
1291 }
1292
1293 /* public, get the RCPs */
RDL_getRCPrototypes(const RDL_data * data,RDL_cycle *** ptr)1294 unsigned RDL_getRCPrototypes(const RDL_data *data, RDL_cycle ***ptr)
1295 {
1296 RDL_cycle **result;
1297 unsigned nof_urf;
1298 unsigned nofRel=0, rcf=0;
1299 unsigned currFam=0, currEdge;
1300 unsigned i,j,k;
1301 const char* prototype;
1302 unsigned bcc_index, mapped_edge;
1303
1304 if (!data) {
1305 RDL_outputFunc(RDL_ERROR, "RDL_data is NULL!\n");
1306 (*ptr) = malloc(sizeof(**ptr));
1307 return RDL_INVALID_RESULT;
1308 }
1309
1310 if (data->nofURFs < 1) {
1311 (*ptr) = malloc(sizeof(**ptr));
1312 return 0;
1313 }
1314
1315 for (i = 0; i < data->bccGraphs->nof_bcc; ++i) {
1316 for (j = 0; j < data->nofURFsPerBCC[i]; ++j) {
1317 nofRel += data->urfInfoPerBCC[i]->nofCFsPerURF[j];
1318 }
1319 }
1320
1321 /*allocate space*/
1322 result = malloc(nofRel * sizeof(*result));
1323
1324 for (bcc_index = 0; bcc_index < data->bccGraphs->nof_bcc; ++bcc_index) {
1325 nof_urf = data->nofURFsPerBCC[bcc_index];
1326 for (i = 0; i < nof_urf; ++i) {
1327 for (j = 0; j < data->urfInfoPerBCC[bcc_index]->nofCFsPerURF[i]; ++j, ++rcf) {
1328 prototype = data->urfInfoPerBCC[bcc_index]->URFs[i][j]->prototype;
1329 result[currFam] = malloc(sizeof(**result));
1330 result[currFam]->edges = malloc(data->urfInfoPerBCC[bcc_index]->URFs[i][j]->weight *
1331 sizeof(*result[currFam]->edges));
1332 result[currFam]->weight = data->urfInfoPerBCC[bcc_index]->URFs[i][j]->weight;
1333 result[currFam]->urf = i;
1334 result[currFam]->rcf = rcf;
1335 currEdge = 0;
1336 for (k = 0; k < data->bccGraphs->bcc_graphs[bcc_index]->E; ++k) {
1337 if (prototype[k] == 1) {
1338 mapped_edge = data->bccGraphs->edge_from_bcc_mapping[bcc_index][k];
1339 result[currFam]->edges[currEdge][0] = data->graph->edges[mapped_edge][0];
1340 result[currFam]->edges[currEdge][1] = data->graph->edges[mapped_edge][1];
1341 ++currEdge;
1342 }
1343 }
1344 ++currFam;
1345 }
1346 }
1347 }
1348
1349 (*ptr) = result;
1350 return nofRel;
1351 }
1352
1353 /* public, get an RDL_cycleIterator for RCFs */
RDL_getRCyclesForRCFIterator(const RDL_data * data,unsigned index)1354 RDL_cycleIterator* RDL_getRCyclesForRCFIterator(const RDL_data *data, unsigned index)
1355 {
1356 RDL_cycleIterator* it;
1357 unsigned rcf_internal_index, urf_internal_index, urf_index;
1358 unsigned bcc_index;
1359
1360 if (!data) {
1361 RDL_outputFunc(RDL_ERROR, "RDL_data is NULL!\n");
1362 return NULL;
1363 }
1364
1365 if (index >= data->nofRCFs) {
1366 RDL_outputFunc(RDL_ERROR, "invalid index: %u\n", index);
1367 return NULL;
1368 }
1369
1370 urf_index = data->rcf_to_urf[index][0];
1371 rcf_internal_index = data->rcf_to_urf[index][1];
1372 bcc_index = data->urf_to_bcc[urf_index][0];
1373 urf_internal_index = data->urf_to_bcc[urf_index][1];
1374
1375 it = RDL_initCycleIterator(RDL_RCF_IT,
1376 rcf_internal_index, rcf_internal_index,
1377 urf_internal_index, urf_internal_index,
1378 bcc_index, bcc_index,
1379 'b', data);
1380
1381 return it;
1382 }
1383
1384 /* public, get an RDL_cycleIterator for URFs */
RDL_getRCyclesForURFIterator(const RDL_data * data,unsigned index)1385 RDL_cycleIterator* RDL_getRCyclesForURFIterator(const RDL_data *data, unsigned index)
1386 {
1387 RDL_cycleIterator* it;
1388 unsigned urf_internal_index, bcc_index;
1389
1390 if (!data) {
1391 RDL_outputFunc(RDL_ERROR, "RDL_data is NULL!\n");
1392 return NULL;
1393 }
1394
1395 if (index >= data->nofURFs) {
1396 RDL_outputFunc(RDL_ERROR, "invalid index: %u\n", index);
1397 return NULL;
1398 }
1399
1400 bcc_index = data->urf_to_bcc[index][0];
1401 urf_internal_index = data->urf_to_bcc[index][1];
1402
1403 it = RDL_initCycleIterator(
1404 RDL_URF_IT,
1405 0, 0,
1406 urf_internal_index, urf_internal_index,
1407 bcc_index, bcc_index,
1408 'b', data);
1409
1410 return it;
1411 }
1412
1413 /* public, get an RDL_cycleIterator for all RCs */
RDL_getRCyclesIterator(const RDL_data * data)1414 RDL_cycleIterator* RDL_getRCyclesIterator(const RDL_data *data)
1415 {
1416 RDL_cycleIterator* it;
1417
1418 if (!data) {
1419 RDL_outputFunc(RDL_ERROR, "RDL_data is NULL!\n");
1420 return NULL;
1421 }
1422
1423 it = RDL_initCycleIterator(
1424 RDL_ALL_IT,
1425 0, 0,
1426 0, 0,
1427 0, data->bccGraphs->nof_bcc-1,
1428 'b', data);
1429
1430 return it;
1431 }
1432
1433 /* private, get RCs from an RDL_cycleIterator */
RDL_getRCycles_internal(const RDL_data * data,RDL_cycle *** ptr,RDL_cycleIterator * it)1434 static unsigned RDL_getRCycles_internal(
1435 const RDL_data *data, RDL_cycle ***ptr, RDL_cycleIterator* it)
1436 {
1437 RDL_cycle **result;
1438 unsigned alloced, nextfree;
1439
1440 alloced = RDL_RESERVED_START;
1441 nextfree = 0;
1442 result = malloc(alloced * sizeof(*result));
1443
1444 while (!RDL_cycleIteratorAtEnd(it)) {
1445 if(nextfree == alloced) {
1446 alloced *= 2;
1447 result = realloc(result, alloced * sizeof(*result));
1448 }
1449 result[nextfree] = RDL_cycleIteratorGetCycle(it);
1450 ++nextfree;
1451
1452 RDL_cycleIteratorNext(it);
1453 }
1454 RDL_deleteCycleIterator(it);
1455
1456 result = realloc(result, nextfree * sizeof(*result));
1457
1458 *ptr = result;
1459 return nextfree;
1460 }
1461
1462 /* public, get all RCs */
RDL_getRCycles(const RDL_data * data,RDL_cycle *** ptr)1463 unsigned RDL_getRCycles(const RDL_data *data, RDL_cycle ***ptr)
1464 {
1465 RDL_cycleIterator* it;
1466
1467 it = RDL_getRCyclesIterator(data);
1468
1469 if (it == NULL) {
1470 RDL_outputFunc(RDL_ERROR, "Iterator is NULL!\n");
1471 (*ptr) = malloc(sizeof(**ptr));
1472 return RDL_INVALID_RESULT;
1473 }
1474
1475 return RDL_getRCycles_internal(data, ptr, it);
1476 }
1477
1478 /* public, get all RCs for given URF */
RDL_getRCyclesForURF(const RDL_data * data,unsigned index,RDL_cycle *** ptr)1479 unsigned RDL_getRCyclesForURF(const RDL_data *data, unsigned index, RDL_cycle ***ptr)
1480 {
1481 RDL_cycleIterator* it;
1482
1483 it = RDL_getRCyclesForURFIterator(data, index);
1484
1485 if (it == NULL) {
1486 RDL_outputFunc(RDL_ERROR, "Iterator is NULL!\n");
1487 (*ptr) = malloc(sizeof(**ptr));
1488 return RDL_INVALID_RESULT;
1489 }
1490
1491 return RDL_getRCycles_internal(data, ptr, it);
1492 }
1493
1494 /* public, get all RCs for given RCF */
RDL_getRCyclesForRCF(const RDL_data * data,unsigned index,RDL_cycle *** ptr)1495 unsigned RDL_getRCyclesForRCF(const RDL_data *data, unsigned index, RDL_cycle ***ptr)
1496 {
1497 RDL_cycleIterator* it;
1498
1499 it = RDL_getRCyclesForRCFIterator(data, index);
1500
1501 if (it == NULL) {
1502 RDL_outputFunc(RDL_ERROR, "Iterator is NULL!\n");
1503 (*ptr) = malloc(sizeof(**ptr));
1504 return RDL_INVALID_RESULT;
1505 }
1506
1507 return RDL_getRCycles_internal(data, ptr, it);
1508 }
1509
1510 /* public, utils function for converting cycle to bitset representation */
RDL_translateCycArray(const RDL_data * data,RDL_cycle ** array,unsigned number,char *** ptr)1511 unsigned RDL_translateCycArray(const RDL_data *data, RDL_cycle **array,
1512 unsigned number, char ***ptr)
1513 {
1514 unsigned i,j,RDL_edgeIdx;
1515 char **result;
1516
1517 if (!data) {
1518 RDL_outputFunc(RDL_ERROR, "RDL_data is NULL!\n");
1519 (*ptr) = RDL_alloc2DCharArray(0, 0);
1520 return RDL_INVALID_RESULT;
1521 }
1522
1523 if (number < 1) {
1524 (*ptr) = RDL_alloc2DCharArray(0, 0);
1525 return 0;
1526 }
1527
1528 result = RDL_alloc2DCharArray(number, data->graph->E);
1529 for(i=0; i<number; ++i)/*initialize to 0s*/
1530 {
1531 for(j=0; j<data->graph->E; ++j)
1532 {
1533 result[i][j] = 0;
1534 }
1535 }
1536
1537 for(i=0; i<number; ++i)
1538 {
1539 for(j=0; j<array[i]->weight; ++j)
1540 {
1541 RDL_edgeIdx = RDL_edgeId(data->graph, array[i]->edges[j][0],
1542 array[i]->edges[j][1]);
1543 result[i][RDL_edgeIdx] = 1;
1544 }
1545 }
1546 (*ptr) = result;
1547 return number;
1548 }
1549
1550 /* public, delete an edge array */
RDL_deleteEdgeIdxArray(char ** cycles,unsigned num)1551 void RDL_deleteEdgeIdxArray(char **cycles, unsigned num)
1552 {
1553 RDL_delete2DCharArray(cycles, num);
1554 }
1555
1556 /* public, get the edges of the graph */
RDL_getEdgeArray(const RDL_data * data,RDL_edge ** ptr)1557 unsigned RDL_getEdgeArray(const RDL_data *data, RDL_edge **ptr)
1558 {
1559 RDL_edge *result;
1560 unsigned idx;
1561
1562 if (!data) {
1563 RDL_outputFunc(RDL_ERROR, "RDL_data is NULL!\n");
1564 (*ptr) = malloc(sizeof(**ptr));
1565 return RDL_INVALID_RESULT;
1566 }
1567
1568 result = malloc(data->graph->E * sizeof(*result));
1569 for(idx=0; idx<data->graph->E; ++idx)
1570 {
1571 result[idx][0] = data->graph->edges[idx][0];
1572 result[idx][1] = data->graph->edges[idx][1];
1573 }
1574 (*ptr) = result;
1575 return data->graph->E;
1576 }
1577
1578 /* public, get the number of edges in the graph */
RDL_getNofEdges(const RDL_data * data)1579 unsigned RDL_getNofEdges(const RDL_data *data)
1580 {
1581 if (!data) {
1582 RDL_outputFunc(RDL_ERROR, "RDL_data is NULL!\n");
1583 return RDL_INVALID_RESULT;
1584 }
1585 return data->graph->E;
1586 }
1587
1588 /* public, get the number of ringsystems calculated */
RDL_getNofRingsystems(const RDL_data * data)1589 unsigned RDL_getNofRingsystems(const RDL_data* data)
1590 {
1591 if (!data) {
1592 RDL_outputFunc(RDL_ERROR, "RDL_data is NULL!\n");
1593 return RDL_INVALID_RESULT;
1594 }
1595
1596 return data->bccGraphs->nof_bcc;
1597 }
1598
1599 /* public, get the number of nodes for the ring sytem */
RDL_getNofNodesForRingsystem(const RDL_data * data,unsigned idx)1600 unsigned RDL_getNofNodesForRingsystem(const RDL_data *data, unsigned idx)
1601 {
1602 if (!data) {
1603 RDL_outputFunc(RDL_ERROR, "RDL_data is NULL!\n");
1604 return RDL_INVALID_RESULT;
1605 }
1606
1607 if(idx >= data->bccGraphs->nof_bcc) {
1608 RDL_outputFunc(RDL_ERROR, "idx %d is out of range!\n", idx);
1609 return RDL_INVALID_RESULT;
1610 }
1611
1612 return data->bccGraphs->bcc_graphs[idx]->V;
1613 }
1614
1615 /* public, get the number of edges for the ring sytem */
RDL_getNofEdgesForRingsystem(const RDL_data * data,unsigned idx)1616 unsigned RDL_getNofEdgesForRingsystem(const RDL_data *data, unsigned idx)
1617 {
1618 if (!data) {
1619 RDL_outputFunc(RDL_ERROR, "RDL_data is NULL!\n");
1620 return RDL_INVALID_RESULT;
1621 }
1622
1623 if(idx >= data->bccGraphs->nof_bcc) {
1624 RDL_outputFunc(RDL_ERROR, "idx %d is out of range!\n", idx);
1625 return RDL_INVALID_RESULT;
1626 }
1627
1628 return data->bccGraphs->bcc_graphs[idx]->E;
1629
1630 }
1631
1632 /* public, get the edge for the ring sytem */
RDL_getEdgesForRingsystem(const RDL_data * data,unsigned idx,RDL_edge ** edges)1633 unsigned RDL_getEdgesForRingsystem(
1634 const RDL_data *data, unsigned idx, RDL_edge** edges)
1635 {
1636 unsigned i, edge;
1637
1638 if (!data) {
1639 RDL_outputFunc(RDL_ERROR, "RDL_data is NULL!\n");
1640 (*edges) = malloc(sizeof(**edges));
1641 return RDL_INVALID_RESULT;
1642 }
1643
1644 if(idx >= data->bccGraphs->nof_bcc) {
1645 RDL_outputFunc(RDL_ERROR, "idx %d is out of range!\n", idx);
1646 (*edges) = malloc(sizeof(**edges));
1647 return RDL_INVALID_RESULT;
1648 }
1649
1650 (*edges) = malloc(data->bccGraphs->bcc_graphs[idx]->E * sizeof(**edges));
1651
1652 for (i = 0; i < data->bccGraphs->bcc_graphs[idx]->E; ++i) {
1653 edge = data->bccGraphs->edge_from_bcc_mapping[idx][i];
1654 (*edges)[i][0] = data->graph->edges[edge][0];
1655 (*edges)[i][1] = data->graph->edges[edge][1];
1656 }
1657
1658 return data->bccGraphs->bcc_graphs[idx]->E;
1659 }
1660
1661 /* public, get the nodes for the ring sytem */
RDL_getNodesForRingsystem(const RDL_data * data,unsigned idx,RDL_node ** nodes)1662 unsigned RDL_getNodesForRingsystem(
1663 const RDL_data *data, unsigned idx, RDL_node** nodes)
1664 {
1665 unsigned i, node;
1666
1667 if (!data) {
1668 RDL_outputFunc(RDL_ERROR, "RDL_data is NULL!\n");
1669 (*nodes) = malloc(sizeof(**nodes));
1670 return RDL_INVALID_RESULT;
1671 }
1672
1673 if(idx >= data->bccGraphs->nof_bcc) {
1674 RDL_outputFunc(RDL_ERROR, "idx %d is out of range!\n", idx);
1675 (*nodes) = malloc(sizeof(**nodes));
1676 return RDL_INVALID_RESULT;
1677 }
1678
1679 (*nodes) = malloc(data->bccGraphs->bcc_graphs[idx]->V * sizeof(*nodes));
1680
1681 for (i = 0; i < data->bccGraphs->bcc_graphs[idx]->V; ++i) {
1682 node = data->bccGraphs->node_from_bcc_mapping[idx][i];
1683 (*nodes)[i] = node;
1684 }
1685
1686 return data->bccGraphs->bcc_graphs[idx]->V;
1687 }
1688
1689 /* public, get the ringsystem an edge belongs to */
RDL_getRingsystemForEdge(const RDL_data * data,unsigned from,unsigned to)1690 unsigned RDL_getRingsystemForEdge(
1691 const RDL_data* data, unsigned from, unsigned to)
1692 {
1693 unsigned edge;
1694
1695 edge = RDL_getEdgeId(data, from, to);
1696
1697 if (edge == RDL_INVALID_RESULT) {
1698 return RDL_INVALID_RESULT;
1699 }
1700
1701 return data->bccGraphs->edge_to_bcc_mapping[edge][0];
1702 }
1703
1704 /* public, get the ID of an edge */
RDL_getEdgeId(const RDL_data * data,unsigned from,unsigned to)1705 unsigned RDL_getEdgeId(const RDL_data *data, unsigned from, unsigned to)
1706 {
1707 if (!data) {
1708 RDL_outputFunc(RDL_ERROR, "RDL_data is NULL!\n");
1709 return RDL_INVALID_RESULT;
1710 }
1711
1712 if (!data->graph) {
1713 RDL_outputFunc(RDL_ERROR, "RDL_graph is NULL!\n");
1714 return RDL_INVALID_RESULT;
1715 }
1716
1717 if (from >= data->graph->V || to >= data->graph->V) {
1718 RDL_outputFunc(RDL_ERROR, "invalid edge %u %u\n", from, to);
1719 return RDL_INVALID_RESULT;
1720 }
1721
1722 return RDL_edgeId(data->graph, from, to);
1723 }
1724