00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "overlap_graph.h"
00026 #include "disjoint_set.h"
00027 #include "priority_queue.h"
00028 #include "list.h"
00029 #include "debug.h"
00030
00031 #include <errno.h>
00032 #include <sys/types.h>
00033 #include <stdlib.h>
00034 #include <stdio.h>
00035 #include <stdint.h>
00036
00037
00038
00039
00040 struct edge {
00041 off_t weight;
00042 size_t src_id;
00043 size_t dst_id;
00044 int removed;
00045 struct edge *next;
00046 };
00047
00048
00049
00050
00051 struct vertex {
00052 segment_t *segment;
00053 off_t mapping;
00054 off_t self_loop_weight;
00055 size_t in_degree;
00056 size_t out_degree;
00057 int visited;
00058 struct edge *head;
00059
00060 };
00061
00062
00063
00064
00065 struct overlap_graph {
00066 struct vertex *vertices;
00067 size_t capacity;
00068 size_t size;
00069 struct edge tail;
00070 };
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 static off_t calculate_overlap(off_t start1, off_t size1, off_t start2,
00088 off_t size2)
00089 {
00090 if (size1 == 0 || size2 == 0)
00091 return 0;
00092
00093 off_t end1 = start1 + size1 - 1;
00094 off_t end2 = start2 + size2 - 1;
00095
00096 off_t overlap = 0;
00097
00098 if (start2 >= start1 && start2 <= end1)
00099 overlap = end1 - start2 + 1;
00100
00101 if (end2 >= start1 && end2 <= end1) {
00102 if (overlap == 0)
00103 overlap = end2 - start1 + 1;
00104 else
00105 overlap -= end1 - end2;
00106 }
00107
00108 if (start2 < start1 && end2 > end1)
00109 overlap = size1;
00110
00111 return overlap;
00112 }
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 static int overlap_graph_add_edge(overlap_graph_t *g, size_t src_id, size_t dst_id,
00125 off_t weight)
00126 {
00127 g->vertices[src_id].out_degree += 1;
00128
00129
00130 struct edge *e = g->vertices[src_id].head;
00131 while (e->next != &g->tail) {
00132 if (e->next->dst_id == dst_id)
00133 break;
00134 e = e->next;
00135 }
00136
00137
00138 if (e->next == &g->tail) {
00139 struct edge *edst = malloc (sizeof *edst);
00140 if (edst == NULL)
00141 return_error(ENOMEM);
00142
00143 g->vertices[dst_id].in_degree += 1;
00144
00145 edst->src_id = src_id;
00146 edst->dst_id = dst_id;
00147 edst->removed = 0;
00148
00149 edst->next = e->next;
00150 e->next = edst;
00151 }
00152
00153
00154 e->next->weight = weight;
00155
00156 return 0;
00157 }
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 static int topo_visit(overlap_graph_t *g, size_t n, list_t *list)
00170 {
00171 int err;
00172
00173 struct vertex *v = &g->vertices[n];
00174
00175
00176 v->visited = 1;
00177
00178
00179 struct edge *e = v->head->next;
00180 while (e != &g->tail) {
00181 struct vertex *vtmp = &g->vertices[e->dst_id];
00182 if (e->removed == 0 && vtmp->visited == 0) {
00183 err = topo_visit(g, e->dst_id, list);
00184 if (err)
00185 return_error(err);
00186 }
00187
00188 e = e->next;
00189 }
00190
00191
00192 struct vertex_entry *entry;
00193 entry = malloc(sizeof(struct vertex_entry));
00194 if (entry == NULL)
00195 return_error(ENOMEM);
00196
00197
00198 entry->segment = v->segment;
00199 entry->mapping = v->mapping;
00200 entry->self_loop_weight = v->self_loop_weight;
00201
00202
00203 struct list_node *head =
00204 list_head(list);
00205
00206 list_insert_after(head, &entry->ln);
00207
00208 return 0;
00209 }
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 int overlap_graph_new(overlap_graph_t **g, size_t capacity)
00224 {
00225 if (g == NULL)
00226 return_error(EINVAL);
00227
00228 overlap_graph_t *p;
00229
00230 p = malloc (sizeof *p);
00231 if (p == NULL)
00232 return_error(ENOMEM);
00233
00234 p->vertices = malloc(capacity * sizeof *p->vertices);
00235 if (p->vertices == NULL) {
00236 free (p);
00237 return_error(ENOMEM);
00238 }
00239
00240 p->capacity = capacity;
00241 p->size = 0;
00242 p->tail.next = &p->tail;
00243
00244 *g = p;
00245
00246 return 0;
00247 }
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 int overlap_graph_free(overlap_graph_t *g)
00260 {
00261
00262 size_t i;
00263 for (i = 0; i < g->size; i++) {
00264 struct vertex *v = &g->vertices[i];
00265 segment_free(v->segment);
00266
00267
00268 struct edge *e = v->head;
00269 while (e != &g->tail) {
00270 struct edge *next = e->next;
00271 free(e);
00272 e = next;
00273 }
00274 }
00275
00276 free(g->vertices);
00277 free(g);
00278
00279 return 0;
00280 }
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291 int overlap_graph_add_segment(overlap_graph_t *g, segment_t *seg,
00292 off_t mapping)
00293 {
00294 if (g == NULL || seg == NULL || mapping < 0)
00295 return_error(EINVAL);
00296
00297
00298 if (g->size >= g->capacity) {
00299 size_t new_capacity = ((5 * g->capacity) / 4) + 1;
00300 struct vertex *t = realloc(g->vertices, new_capacity * sizeof *t);
00301 if (t == NULL)
00302 return_error(ENOMEM);
00303
00304 g->vertices = t;
00305 g->capacity = new_capacity;
00306 }
00307
00308
00309 struct vertex *v = &g->vertices[g->size++];
00310
00311 int err = segment_copy(seg, &v->segment);
00312 if (err)
00313 return_error(err);
00314
00315 v->mapping = mapping;
00316 v->self_loop_weight = 0;
00317 v->in_degree = 0;
00318 v->out_degree = 0;
00319 v->visited = 0;
00320 v->head = malloc(sizeof *v->head);
00321 if (v->head == NULL) {
00322 segment_free(v->segment);
00323 return_error(ENOMEM);
00324 }
00325 v->head->next = &g->tail;
00326
00327 off_t seg_size;
00328 segment_get_size(seg, &seg_size);
00329 off_t seg_start;
00330 segment_get_start(seg, &seg_start);
00331
00332
00333
00334
00335
00336
00337
00338 size_t i;
00339 for (i = 0; i < g->size - 1; i++) {
00340 struct vertex *vtmp = &g->vertices[i];
00341 off_t vstart;
00342 segment_get_start(vtmp->segment, &vstart);
00343 off_t vsize;
00344 segment_get_size(vtmp->segment, &vsize);
00345
00346
00347 off_t overlap1 = calculate_overlap(vstart, vsize, mapping, seg_size);
00348
00349 off_t overlap2 = calculate_overlap(seg_start, seg_size, vtmp->mapping,
00350 vsize);
00351
00352
00353 if (overlap1 != 0)
00354 overlap_graph_add_edge(g, i, g->size - 1, overlap1);
00355 if (overlap2 != 0)
00356 overlap_graph_add_edge(g, g->size - 1, i, overlap2);
00357 }
00358
00359
00360 v->self_loop_weight = calculate_overlap(seg_start, seg_size, mapping,
00361 seg_size);
00362
00363 return 0;
00364 }
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377 int overlap_graph_remove_cycles(overlap_graph_t *g)
00378 {
00379 if (g == NULL)
00380 return_error(EINVAL);
00381
00382
00383
00384
00385
00386
00387 disjoint_set_t *ds;
00388 int err = disjoint_set_new(&ds, g->size);
00389 if (err)
00390 return_error(err);
00391
00392
00393 priority_queue_t *pq;
00394 err = priority_queue_new(&pq, g->size);
00395 if (err) {
00396 disjoint_set_free(ds);
00397 return_error(err);
00398 }
00399
00400
00401 size_t i;
00402 for (i = 0; i < g->size; i++) {
00403 struct vertex *v = &g->vertices[i];
00404
00405 v->in_degree = 0;
00406 v->out_degree = 0;
00407
00408 struct edge *e = v->head->next;
00409 while (e != &g->tail) {
00410
00411 e->removed = 1;
00412 err = priority_queue_add(pq, e, e->weight, NULL);
00413 if (err)
00414 goto out;
00415 e = e->next;
00416 }
00417 }
00418
00419
00420
00421
00422
00423 size_t pq_size;
00424 while (!priority_queue_get_size(pq, &pq_size) && pq_size > 0) {
00425 struct edge *e;
00426 err = priority_queue_remove_max(pq, (void **)&e);
00427 if (err)
00428 goto out;
00429
00430 size_t set1;
00431 size_t set2;
00432 err = disjoint_set_find(ds, &set1, e->src_id);
00433 if (err)
00434 goto out;
00435 err = disjoint_set_find(ds, &set2, e->dst_id);
00436 if (err)
00437 goto out;
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459 if (set1 != set2 || g->vertices[e->dst_id].out_degree == 0
00460 || g->vertices[e->src_id].in_degree == 0) {
00461
00462 e->removed = 0;
00463
00464 err = disjoint_set_union(ds, e->src_id, e->dst_id);
00465 if (err)
00466 goto out;
00467
00468 g->vertices[e->dst_id].in_degree += 1;
00469
00470 g->vertices[e->src_id].out_degree += 1;
00471
00472 }
00473 }
00474
00475 priority_queue_free(pq);
00476 disjoint_set_free(ds);
00477
00478 return 0;
00479
00480 out:
00481 priority_queue_free(pq);
00482
00483 disjoint_set_free(ds);
00484
00485 return_error(err);
00486 }
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496 int overlap_graph_export_dot(overlap_graph_t *g, int fd)
00497 {
00498 if (g == NULL)
00499 return_error(EINVAL);
00500
00501 FILE *fp = fdopen(fd, "w");
00502 if (fp == NULL)
00503 return_error(EINVAL);
00504
00505
00506 fprintf(fp, "digraph overlap_graph {\n");
00507
00508
00509 size_t i;
00510 for (i = 0; i < g->size; i++) {
00511 struct vertex *v = &g->vertices[i];
00512
00513
00514 fprintf(fp, "%zu [label = \"%zu-%zu/%zu\"]\n", i, i, v->in_degree,
00515 v->out_degree);
00516
00517
00518 if (v->self_loop_weight != 0) {
00519 fprintf(fp, "%zu -> %zu [label = %jd]\n", i, i,
00520 (intmax_t)v->self_loop_weight);
00521 }
00522
00523
00524
00525
00526
00527 struct edge *e = v->head->next;
00528 while (e != &g->tail) {
00529 fprintf(fp, "%zu -> %zu [label = %jd%s]\n", e->src_id, e->dst_id,
00530 (intmax_t)e->weight,
00531 e->removed == 1 ? " style = dotted" : "");
00532 e = e->next;
00533 }
00534 }
00535
00536 fprintf(fp, "}\n");
00537 fflush(fp);
00538
00539 return 0;
00540 }
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551 int overlap_graph_get_removed_edges(overlap_graph_t *g, list_t **edges)
00552 {
00553 if (g == NULL || edges == NULL)
00554 return_error(EINVAL);
00555
00556 int err = list_new(edges, struct edge_entry, ln);
00557 if (err)
00558 return_error(err);
00559
00560
00561 size_t i;
00562 for (i = 0; i < g->size; i++) {
00563 struct vertex *v = &g->vertices[i];
00564
00565
00566 struct edge *e = v->head->next;
00567 while (e != &g->tail) {
00568
00569 if (e->removed == 0) {
00570 e = e->next;
00571 continue;
00572 }
00573
00574
00575 struct edge_entry *entry;
00576 entry = malloc(sizeof(struct edge_entry));
00577 if (entry == NULL)
00578 return_error(ENOMEM);
00579
00580
00581 entry->src = v->segment;
00582 entry->dst = g->vertices[e->dst_id].segment;
00583 entry->dst_mapping = g->vertices[e->dst_id].mapping;
00584 entry->weight = e->weight;
00585
00586
00587 err = list_insert_before(list_tail(*edges), &entry->ln);
00588 if (err)
00589 goto fail;
00590
00591 e = e->next;
00592 }
00593 }
00594
00595 return 0;
00596
00597 fail:
00598 {
00599
00600 struct list_node *node;
00601 struct list_node *tmp;
00602
00603 list_for_each_safe(list_head(*edges)->next, node, tmp) {
00604 struct edge_entry *entry = list_entry(node, struct edge_entry, ln);
00605 free(entry);
00606 }
00607
00608 list_free(*edges);
00609
00610 return_error(err);
00611 }
00612 }
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625 int overlap_graph_get_vertices_topo(overlap_graph_t *g, list_t **vertices)
00626 {
00627 if (g == NULL || vertices == NULL)
00628 return_error(EINVAL);
00629
00630
00631 int err = list_new(vertices, struct vertex_entry, ln);
00632 if (err)
00633 return_error(err);
00634
00635
00636 size_t i;
00637 for (i = 0; i < g->size; i++) {
00638 struct vertex *v = &g->vertices[i];
00639 v->visited = 0;
00640 }
00641
00642
00643
00644
00645 for (i = 0; i < g->size; i++) {
00646 struct vertex *v = &g->vertices[i];
00647 if (v->visited == 0) {
00648 err = topo_visit(g, i, *vertices);
00649 if (err)
00650 goto fail;
00651 }
00652 }
00653
00654 return 0;
00655
00656 fail:
00657 {
00658
00659 struct list_node *node;
00660 struct list_node *tmp;
00661
00662 list_for_each_safe(list_head(*vertices)->next, node, tmp) {
00663 struct vertex_entry *entry = list_entry(node, struct vertex_entry, ln);
00664 free(entry);
00665 }
00666
00667 list_free(*vertices);
00668
00669 return_error(err);
00670 }
00671 }
00672