This source file includes following definitions.
- opal_graph_vertex_construct
- opal_graph_vertex_destruct
- opal_graph_edge_construct
- opal_graph_edge_destruct
- opal_graph_construct
- opal_graph_destruct
- opal_adjacency_list_construct
- opal_adjacency_list_destruct
- delete_all_edges_conceded_to_vertex
- opal_graph_add_vertex
- opal_graph_add_edge
- opal_graph_remove_edge
- opal_graph_remove_vertex
- opal_graph_adjacent
- opal_graph_get_order
- opal_graph_get_size
- opal_graph_find_vertex
- opal_graph_get_graph_vertices
- opal_graph_get_adjacent_vertices
- opal_graph_spf
- compare_vertex_distance
- opal_graph_dijkstra
- opal_graph_duplicate
- opal_graph_print
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 #include "opal_config.h"
  25 
  26 #include "opal/class/opal_list.h"
  27 #include "opal/constants.h"
  28 #include "opal/class/opal_graph.h"
  29 #include "opal/util/output.h"
  30 
  31 static int compare_vertex_distance(const void *item1, const void *item2);
  32 
  33 
  34 
  35 
  36 
  37 
  38 static void opal_graph_vertex_construct(opal_graph_vertex_t *vertex);
  39 static void opal_graph_vertex_destruct(opal_graph_vertex_t *vertex);
  40 
  41 OBJ_CLASS_INSTANCE(
  42     opal_graph_vertex_t,
  43     opal_list_item_t,
  44     opal_graph_vertex_construct,
  45     opal_graph_vertex_destruct
  46 );
  47 
  48 
  49 static void opal_graph_edge_construct(opal_graph_edge_t *edge);
  50 static void opal_graph_edge_destruct(opal_graph_edge_t *edge);
  51 
  52 OBJ_CLASS_INSTANCE(
  53     opal_graph_edge_t,
  54     opal_list_item_t,
  55     opal_graph_edge_construct,
  56     opal_graph_edge_destruct
  57 );
  58 
  59 static void opal_graph_construct(opal_graph_t *graph);
  60 static void opal_graph_destruct(opal_graph_t *graph);
  61 
  62 OBJ_CLASS_INSTANCE(
  63     opal_graph_t,
  64     opal_object_t,
  65     opal_graph_construct,
  66     opal_graph_destruct
  67 );
  68 
  69 static void opal_adjacency_list_construct(opal_adjacency_list_t *aj_list);
  70 static void opal_adjacency_list_destruct(opal_adjacency_list_t *aj_list);
  71 
  72 OBJ_CLASS_INSTANCE(
  73     opal_adjacency_list_t,
  74     opal_list_item_t,
  75     opal_adjacency_list_construct,
  76     opal_adjacency_list_destruct
  77 );
  78 
  79 
  80 
  81 
  82 
  83 
  84 
  85 
  86 
  87 static void opal_graph_vertex_construct(opal_graph_vertex_t *vertex)
  88 {
  89     vertex->in_adj_list = NULL;
  90     vertex->in_graph = NULL;
  91     vertex->vertex_data = NULL;
  92     vertex->sibling = NULL;
  93     vertex->copy_vertex_data = NULL;
  94     vertex->free_vertex_data = NULL;
  95     vertex->alloc_vertex_data = NULL;
  96     vertex->compare_vertex = NULL;
  97     vertex->print_vertex = NULL;
  98 }
  99 
 100 static void opal_graph_vertex_destruct(opal_graph_vertex_t *vertex)
 101 {
 102     vertex->in_adj_list = NULL;
 103     vertex->in_graph = NULL;
 104     vertex->sibling = NULL;
 105     vertex->copy_vertex_data = NULL;
 106     vertex->alloc_vertex_data = NULL;
 107     vertex->compare_vertex = NULL;
 108     if (NULL != vertex->free_vertex_data) {
 109         vertex->free_vertex_data(vertex->vertex_data);
 110     }
 111     vertex->vertex_data = NULL;
 112     vertex->print_vertex = NULL;
 113 }
 114 
 115 
 116 
 117 
 118 
 119 
 120 
 121 
 122 static void opal_graph_edge_construct(opal_graph_edge_t *edge)
 123 {
 124     edge->end = NULL;
 125     edge->start = NULL;
 126     edge->weight = 0;
 127     edge->in_adj_list = NULL;
 128 }
 129 
 130 
 131 static void opal_graph_edge_destruct(opal_graph_edge_t *edge)
 132 {
 133     edge->end = NULL;
 134     edge->start = NULL;
 135     edge->weight = 0;
 136     edge->in_adj_list = NULL;
 137 }
 138 
 139 
 140 
 141 
 142 
 143 
 144 
 145 
 146 
 147 static void opal_graph_construct(opal_graph_t *graph)
 148 {
 149     graph->adjacency_list = OBJ_NEW(opal_list_t);
 150     graph->number_of_vertices = 0;
 151     graph->number_of_edges = 0;
 152 }
 153 
 154 static void opal_graph_destruct(opal_graph_t *graph)
 155 {
 156     OPAL_LIST_RELEASE(graph->adjacency_list);
 157     graph->number_of_vertices = 0;
 158     graph->number_of_edges = 0;
 159 }
 160 
 161 
 162 
 163 
 164 
 165 
 166 
 167 static void opal_adjacency_list_construct(opal_adjacency_list_t *aj_list)
 168 {
 169     aj_list->vertex = NULL;
 170     aj_list->edges = OBJ_NEW(opal_list_t);
 171 }
 172 
 173 static void opal_adjacency_list_destruct(opal_adjacency_list_t *aj_list)
 174 {
 175    aj_list->vertex = NULL;
 176    OPAL_LIST_RELEASE(aj_list->edges);
 177 }
 178 
 179 
 180 
 181 
 182 
 183 
 184 
 185 
 186 static void delete_all_edges_conceded_to_vertex(opal_graph_t *graph, opal_graph_vertex_t *vertex)
 187 {
 188     opal_adjacency_list_t *aj_list;
 189     opal_graph_edge_t *edge, *next;
 190 
 191     
 192 
 193 
 194     OPAL_LIST_FOREACH(aj_list, graph->adjacency_list, opal_adjacency_list_t) {
 195         
 196 
 197 
 198         OPAL_LIST_FOREACH_SAFE(edge, next, aj_list->edges, opal_graph_edge_t) {
 199             
 200 
 201 
 202             if (edge->end == vertex) {
 203                 
 204                 opal_list_remove_item(edge->in_adj_list->edges, (opal_list_item_t*)edge);
 205                 
 206                 OBJ_RELEASE(edge);
 207             }
 208         }
 209     }
 210 }
 211 
 212 
 213 
 214 
 215 
 216 
 217 
 218 
 219 void opal_graph_add_vertex(opal_graph_t *graph, opal_graph_vertex_t *vertex)
 220 {
 221    opal_adjacency_list_t *aj_list;
 222 
 223    
 224 
 225 
 226    OPAL_LIST_FOREACH(aj_list, graph->adjacency_list, opal_adjacency_list_t) {
 227        if (aj_list->vertex == vertex) {
 228            
 229            return;
 230        }
 231    }
 232    
 233    aj_list = OBJ_NEW(opal_adjacency_list_t);
 234    aj_list->vertex = vertex;
 235    
 236    vertex->in_adj_list = aj_list;
 237    
 238    opal_list_append(graph->adjacency_list, (opal_list_item_t*)aj_list);
 239    
 240    vertex->in_graph = graph;
 241    
 242    graph->number_of_vertices++;
 243 }
 244 
 245 
 246 
 247 
 248 
 249 
 250 
 251 
 252 
 253 
 254 
 255 
 256 
 257 int opal_graph_add_edge(opal_graph_t *graph, opal_graph_edge_t *edge)
 258 {
 259     opal_adjacency_list_t *aj_list, *start_aj_list= NULL;
 260     bool end_found = false;
 261 
 262 
 263     
 264 
 265 
 266     OPAL_LIST_FOREACH(aj_list, graph->adjacency_list, opal_adjacency_list_t) {
 267         if (aj_list->vertex == edge->start) {
 268             start_aj_list = aj_list;
 269         }
 270         if (aj_list->vertex == edge->end) {
 271             end_found = true;
 272         }
 273     }
 274     
 275 
 276 
 277 
 278     if (NULL == start_aj_list || false == end_found) {
 279         return OPAL_ERROR;
 280     }
 281     
 282     edge->in_adj_list=start_aj_list;
 283     
 284     opal_list_append(start_aj_list->edges, (opal_list_item_t*)edge);
 285     
 286     graph->number_of_edges++;
 287     return OPAL_SUCCESS;
 288 }
 289 
 290 
 291 
 292 
 293 
 294 
 295 
 296 
 297 
 298 
 299 
 300 
 301 
 302 void opal_graph_remove_edge (opal_graph_t *graph, opal_graph_edge_t *edge)
 303 {
 304     
 305     opal_list_remove_item(edge->in_adj_list->edges, (opal_list_item_t*)edge);
 306     
 307     graph->number_of_edges--;
 308     
 309 }
 310 
 311 
 312 
 313 
 314 
 315 
 316 
 317 
 318 
 319 
 320 void opal_graph_remove_vertex(opal_graph_t *graph, opal_graph_vertex_t *vertex)
 321 {
 322     opal_adjacency_list_t *adj_list;
 323 
 324     
 325 
 326     adj_list = vertex->in_adj_list;
 327     
 328 
 329 
 330 
 331     opal_list_remove_item(graph->adjacency_list, (opal_list_item_t*)adj_list);
 332     OBJ_RELEASE(adj_list);
 333     
 334 
 335 
 336     delete_all_edges_conceded_to_vertex(graph, vertex);
 337     
 338     OBJ_RELEASE(vertex);
 339     
 340     graph->number_of_vertices--;
 341 }
 342 
 343 
 344 
 345 
 346 
 347 
 348 
 349 
 350 
 351 
 352 
 353 
 354 uint32_t opal_graph_adjacent(opal_graph_t *graph, opal_graph_vertex_t *vertex1, opal_graph_vertex_t *vertex2)
 355 {
 356     opal_adjacency_list_t *adj_list;
 357     opal_graph_edge_t *edge;
 358 
 359     
 360 
 361 
 362     if (graph != vertex1->in_graph) {
 363         OPAL_OUTPUT((0,"opal_graph_adjacent 1 Vertex1 %p not in the graph %p\n",(void *)vertex1,(void *)graph));
 364         return DISTANCE_INFINITY;
 365     }
 366     
 367 
 368 
 369     if (graph != vertex2->in_graph) {
 370         OPAL_OUTPUT((0,"opal_graph_adjacent 2 Vertex2 %p not in the graph %p\n",(void *)vertex2,(void *)graph));
 371         return DISTANCE_INFINITY;
 372     }
 373     
 374 
 375 
 376 
 377     if (vertex1 == vertex2) {
 378         return 0;
 379     }
 380     
 381 
 382 
 383 
 384     adj_list = (opal_adjacency_list_t *) vertex1->in_adj_list;
 385     OPAL_LIST_FOREACH(edge, adj_list->edges, opal_graph_edge_t) {
 386         if (edge->end == vertex2) {
 387             
 388             return edge->weight;
 389         }
 390     }
 391     
 392     return DISTANCE_INFINITY;
 393 }
 394 
 395 
 396 
 397 
 398 
 399 
 400 
 401 
 402 
 403 int opal_graph_get_order(opal_graph_t *graph)
 404 {
 405     return graph->number_of_vertices;
 406 }
 407 
 408 
 409 
 410 
 411 
 412 
 413 
 414 
 415 
 416 int opal_graph_get_size(opal_graph_t *graph)
 417 {
 418     return graph->number_of_edges;
 419 }
 420 
 421 
 422 
 423 
 424 
 425 
 426 
 427 
 428 
 429 
 430 opal_graph_vertex_t *opal_graph_find_vertex(opal_graph_t *graph, void *vertex_data)
 431 {
 432     opal_adjacency_list_t *aj_list;
 433 
 434     
 435 
 436 
 437     OPAL_LIST_FOREACH(aj_list, graph->adjacency_list, opal_adjacency_list_t) {
 438         if (NULL != aj_list->vertex->compare_vertex) {
 439             
 440             if (0 == aj_list->vertex->compare_vertex(aj_list->vertex->vertex_data, vertex_data)) {
 441                 
 442                 return aj_list->vertex;
 443             }
 444         }
 445     }
 446     
 447     return NULL;
 448 }
 449 
 450 
 451 
 452 
 453 
 454 
 455 
 456 
 457 
 458 
 459 
 460 
 461 
 462 
 463 int opal_graph_get_graph_vertices(opal_graph_t *graph, opal_pointer_array_t *vertices_list)
 464 {
 465     opal_adjacency_list_t *aj_list;
 466 
 467     
 468 
 469 
 470     if (0 == graph->number_of_vertices) {
 471         return 0;
 472     }
 473     
 474     OPAL_LIST_FOREACH(aj_list, graph->adjacency_list, opal_adjacency_list_t) {
 475         
 476         opal_pointer_array_add(vertices_list,(void *)aj_list->vertex);
 477     }
 478     
 479     return graph->number_of_vertices;
 480 }
 481 
 482 
 483 
 484 
 485 
 486 
 487 
 488 
 489 
 490 
 491 
 492 
 493 
 494 
 495 int opal_graph_get_adjacent_vertices(opal_graph_t *graph, opal_graph_vertex_t *vertex, opal_value_array_t *adjacents)
 496 {
 497     opal_adjacency_list_t *adj_list;
 498     opal_graph_edge_t *edge;
 499     int adjacents_number;
 500     vertex_distance_from_t distance_from;
 501 
 502     
 503 
 504 
 505     if (graph != vertex->in_graph) {
 506         OPAL_OUTPUT((0,"Vertex %p not in the graph %p\n", (void *)vertex, (void *)graph));
 507         return 0;
 508     }
 509     
 510 
 511 
 512     adj_list = (opal_adjacency_list_t *) vertex->in_adj_list;
 513     
 514     adjacents_number = opal_list_get_size(adj_list->edges);
 515     
 516     OPAL_LIST_FOREACH(edge, adj_list->edges, opal_graph_edge_t) {
 517         
 518         distance_from.vertex = edge->end;
 519         distance_from.weight = edge->weight;
 520         opal_value_array_append_item(adjacents, &distance_from);
 521     }
 522     
 523     return adjacents_number;
 524 }
 525 
 526 
 527 
 528 
 529 
 530 
 531 
 532 
 533 
 534 
 535 
 536 uint32_t opal_graph_spf(opal_graph_t *graph, opal_graph_vertex_t *vertex1, opal_graph_vertex_t *vertex2)
 537 {
 538     opal_value_array_t *distance_array;
 539     uint32_t items_in_distance_array, spf = DISTANCE_INFINITY;
 540     vertex_distance_from_t *vertex_distance;
 541     uint32_t i;
 542 
 543     
 544 
 545 
 546     if (graph != vertex1->in_graph) {
 547         OPAL_OUTPUT((0,"opal_graph_spf 1 Vertex1 %p not in the graph %p\n",(void *)vertex1,(void *)graph));
 548         return DISTANCE_INFINITY;
 549     }
 550     
 551 
 552 
 553     if (graph != vertex2->in_graph) {
 554         OPAL_OUTPUT((0,"opal_graph_spf 2 Vertex2 %p not in the graph %p\n",(void *)vertex2,(void *)graph));
 555         return DISTANCE_INFINITY;
 556     }
 557     
 558 
 559 
 560     distance_array = OBJ_NEW(opal_value_array_t);
 561     opal_value_array_init(distance_array, sizeof(vertex_distance_from_t));
 562     opal_value_array_reserve(distance_array,50);
 563     items_in_distance_array = opal_graph_dijkstra(graph, vertex1, distance_array);
 564     
 565 
 566 
 567 
 568     for (i = 0; i < items_in_distance_array; i++) {
 569         vertex_distance = opal_value_array_get_item(distance_array, i);
 570         if (vertex_distance->vertex == vertex2) {
 571             spf = vertex_distance->weight;
 572             break;
 573         }
 574     }
 575     OBJ_RELEASE(distance_array);
 576     
 577     return spf;
 578 }
 579 
 580 
 581 
 582 
 583 
 584 
 585 
 586 
 587 
 588 
 589 
 590 
 591 
 592 
 593 static int compare_vertex_distance(const void *item1, const void *item2)
 594 {
 595     vertex_distance_from_t *vertex_dist1, *vertex_dist2;
 596 
 597     
 598     vertex_dist1 = (vertex_distance_from_t *)item1;
 599     vertex_dist2 = (vertex_distance_from_t *)item2;
 600 
 601     
 602     if (vertex_dist1->weight > vertex_dist2->weight) {
 603         return 1;
 604     }
 605     
 606     else if (vertex_dist1->weight == vertex_dist2->weight) {
 607         return 0;
 608     }
 609     
 610     return -1;
 611 }
 612 
 613 
 614 
 615 
 616 
 617 
 618 
 619 
 620 
 621 
 622 
 623 
 624 
 625 
 626 uint32_t opal_graph_dijkstra(opal_graph_t *graph, opal_graph_vertex_t *vertex, opal_value_array_t *distance_array)
 627 {
 628     int graph_order;
 629     vertex_distance_from_t *Q, *q_start, *current_vertex;
 630     opal_adjacency_list_t *adj_list;
 631     int number_of_items_in_q;
 632     int i;
 633     uint32_t weight;
 634 
 635 
 636     
 637 
 638 
 639     if (graph != vertex->in_graph) {
 640         OPAL_OUTPUT((0,"opal:graph:dijkstra: vertex %p not in the graph %p\n",(void *)vertex,(void *)graph));
 641         return 0;
 642     }
 643     
 644     graph_order = opal_graph_get_order(graph);
 645     Q = (vertex_distance_from_t *)malloc(graph_order * sizeof(vertex_distance_from_t));
 646     
 647     q_start = Q;
 648     
 649     i = 0;
 650     OPAL_LIST_FOREACH(adj_list, graph->adjacency_list, opal_adjacency_list_t) {
 651         
 652         Q[i].vertex = adj_list->vertex;
 653         
 654 
 655 
 656 
 657         Q[i++].weight = (adj_list->vertex == vertex) ? 0 : DISTANCE_INFINITY;
 658     }
 659     number_of_items_in_q = i;
 660     
 661     qsort(q_start, number_of_items_in_q, sizeof(vertex_distance_from_t), compare_vertex_distance);
 662     
 663     while (number_of_items_in_q > 0) {
 664         
 665         current_vertex = q_start;
 666         
 667         q_start++;
 668         
 669         number_of_items_in_q--;
 670         
 671         for (i = 0; i < number_of_items_in_q; i++) {
 672             weight = opal_graph_adjacent(graph, current_vertex->vertex, q_start[i].vertex);
 673             
 674 
 675 
 676 
 677 
 678 
 679 
 680             if (current_vertex->weight + weight < q_start[i].weight) {
 681                 q_start[i].weight = weight + current_vertex->weight;
 682             }
 683         }
 684         
 685         qsort(q_start, number_of_items_in_q, sizeof(vertex_distance_from_t), compare_vertex_distance);
 686     }
 687     
 688     for (i = 0; i < graph_order-1; i++) {
 689         opal_value_array_append_item(distance_array, (void *)&(Q[i+1]));
 690     }
 691     
 692     free(Q);
 693     
 694     return graph_order - 1;
 695 }
 696 
 697 
 698 
 699 
 700 
 701 
 702 
 703 
 704 
 705 
 706 void opal_graph_duplicate(opal_graph_t **dest, opal_graph_t *src)
 707 {
 708     opal_adjacency_list_t *aj_list;
 709     opal_graph_vertex_t *vertex;
 710     opal_graph_edge_t *edge, *new_edge;
 711 
 712     
 713     *dest = OBJ_NEW(opal_graph_t);
 714     
 715     OPAL_LIST_FOREACH(aj_list, src->adjacency_list, opal_adjacency_list_t) {
 716         
 717         vertex = OBJ_NEW(opal_graph_vertex_t);
 718         
 719         vertex->sibling = aj_list->vertex;
 720         
 721         aj_list->vertex->sibling = vertex;
 722         
 723         if (NULL != aj_list->vertex->alloc_vertex_data) {
 724             vertex->vertex_data = aj_list->vertex->alloc_vertex_data();
 725             vertex->alloc_vertex_data = aj_list->vertex->alloc_vertex_data;
 726         }
 727         
 728         if (NULL != aj_list->vertex->copy_vertex_data) {
 729             aj_list->vertex->copy_vertex_data(&(vertex->vertex_data), aj_list->vertex->vertex_data);
 730             vertex->copy_vertex_data = aj_list->vertex->copy_vertex_data;
 731         }
 732         
 733         vertex->free_vertex_data = aj_list->vertex->free_vertex_data;
 734         vertex->print_vertex = aj_list->vertex->print_vertex;
 735         vertex->compare_vertex = aj_list->vertex->compare_vertex;
 736         vertex->in_graph = *dest;
 737         
 738         opal_graph_add_vertex(*dest, vertex);
 739     }
 740     
 741 
 742 
 743     
 744     OPAL_LIST_FOREACH(aj_list, src->adjacency_list, opal_adjacency_list_t) {
 745         
 746         OPAL_LIST_FOREACH(edge, aj_list->edges, opal_graph_edge_t) {
 747             
 748             new_edge = OBJ_NEW(opal_graph_edge_t);
 749             
 750             new_edge->weight = edge->weight;
 751             
 752             new_edge->start = edge->start->sibling;
 753             new_edge->end = edge->end->sibling;
 754             
 755             opal_graph_add_edge(*dest, new_edge);
 756         }
 757     }
 758 }
 759 
 760 
 761 
 762 
 763 
 764 void opal_graph_print(opal_graph_t *graph)
 765 {
 766     opal_adjacency_list_t *aj_list;
 767     opal_graph_edge_t *edge;
 768     char *tmp_str1, *tmp_str2;
 769     bool need_free1, need_free2;
 770 
 771     
 772     opal_output(0, "      Graph         ");
 773     opal_output(0, "====================");
 774     
 775     OPAL_LIST_FOREACH(aj_list, graph->adjacency_list, opal_adjacency_list_t) {
 776         
 777         if (NULL != aj_list->vertex->print_vertex) {
 778             need_free1 = true;
 779             tmp_str1 = aj_list->vertex->print_vertex(aj_list->vertex->vertex_data);
 780         }
 781         else {
 782             need_free1 = false;
 783             tmp_str1 = "";
 784         }
 785         
 786         opal_output(0, "V(%s) Connections:",tmp_str1);
 787         
 788         OPAL_LIST_FOREACH(edge, aj_list->edges, opal_graph_edge_t) {
 789             
 790             if (NULL != edge->end->print_vertex) {
 791                 need_free2 = true;
 792                 tmp_str2 = edge->end->print_vertex(edge->end->vertex_data);
 793             }
 794             else {
 795                 need_free2 = false;
 796                 tmp_str2 = "";
 797             }
 798             
 799             opal_output(0, "    E(%s -> %d -> %s)",tmp_str1, edge->weight, tmp_str2);
 800             if (need_free2) {
 801                 free(tmp_str2);
 802             }
 803         }
 804         if (need_free1) {
 805             free(tmp_str1);
 806         }
 807     }
 808 }
 809