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