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