Ticket #12306: trac_12306_doc.patch
File trac_12306_doc.patch, 13.0 KB (added by , 9 years ago) 


sage/graphs/distances_all_pairs.pyx
# HG changeset patch # User Nathann Cohen <nathann.cohen@gmail.com> # Date 1328543944 3600 # Node ID 5801d5b792d7e74db75dc7a17ef30f952a1e7a58 # Parent 0496509fc841807607b539df67804bbef9695afd trac 12306  Static sparse graphs for fast lowlevel computations  documentation diff git a/sage/graphs/distances_all_pairs.pyx b/sage/graphs/distances_all_pairs.pyx
a b 4 4 This module implements a few functions that deal with the computation of 5 5 distances or shortest paths between all pairs of vertices. 6 6 7 Because these functions involve listing many times the (out)neighborhoods of 8 (di)graphs, it is useful in terms of efficiency to build a temporary copy of 9 the graph in a data structure that makes it easy to compute quickly. These 10 functions also work on large volume of data, typically dense matrices of size 11 `n^2`, and are expected to return corresponding dictionaries of size `n^2`, 12 where the integers corresponding to the vertices have first been converted to 13 the vertices' labels. Sadly, this last translating operation turns out to be the 14 most timeconsuming, and for this reason it is also nice to have a Cython 15 module, and version of these functions that return C arrays, in order to avoid 16 these operations when they are not necessary. 7 **Efficiency** : Because these functions involve listing many times the 8 (out)neighborhoods of (di)graphs, it is useful in terms of efficiency to build 9 a temporary copy of the graph in a data structure that makes it easy to compute 10 quickly. These functions also work on large volume of data, typically dense 11 matrices of size `n^2`, and are expected to return corresponding dictionaries of 12 size `n^2`, where the integers corresponding to the vertices have first been 13 converted to the vertices' labels. Sadly, this last translating operation turns 14 out to be the most timeconsuming, and for this reason it is also nice to have a 15 Cython module, and version of these functions that return C arrays, in order to 16 avoid these operations when they are not necessary. 17 18 **Memory cost** : The methods implemented in the current module sometimes need large 19 amounts of memory to return their result. Storing the distances between all 20 pairs of vertices in a graph on `1500` vertices as a dictionary of dictionaries 21 takes around 200MB, while storing the same information as a C array requires 22 4MB. 23 17 24 18 25 The module's main function 19 26  … … 51 58  ``gg`` a (Di)Graph. 52 59 53 60  ``unsigned short * predecessors``  a pointer toward an array of size 54 `n^2\ text{sizeof(unsigned short)}`. Set to ``NULL`` if you do not want to55 compute the predecessors.61 `n^2\cdot\text{sizeof(unsigned short)}`. Set to ``NULL`` if you do not 62 want to compute the predecessors. 56 63 57 64  ``unsigned short * distances``  a pointer toward an array of size 58 `n^2\text{sizeof(unsigned short)}`. The computation of the distances is 59 necessary for the algorithm, so this value can **not** be set to ``NULL``. 65 `n^2\cdot\text{sizeof(unsigned short)}`. The computation of the distances 66 is necessary for the algorithm, so this value can **not** be set to 67 ``NULL``. 60 68 61 69  ``unsigned short * eccentricity``  a pointer toward an array of size 62 `n\ text{sizeof(unsigned short)}`. Set to ``NULL`` if you do not want to63 compute the eccentricity.70 `n\cdot\text{sizeof(unsigned short)}`. Set to ``NULL`` if you do not want 71 to compute the eccentricity. 64 72 65 73 **Technical details** 66 74 … … 108 116 # http://www.gnu.org/licenses/ 109 117 ############################################################################## 110 118 111 include "../misc/bitset_pxd.pxi" 119 include "../misc/bitset_pxd.pxi" 112 120 include "../misc/bitset.pxi" 113 121 from sage.graphs.base.c_graph cimport CGraph 114 122 from sage.graphs.base.c_graph cimport vertex_label … … 130 138 131 139 cdef list int_to_vertex = gg.vertices() 132 140 cdef int i 133 141 134 142 cdef int n = len(int_to_vertex) 135 143 136 144 if n > <unsigned short> 1: … … 178 186 # left to right The list of the first vertex's outneighbors, then the 179 187 # second's, then the third's, ... 180 188 # 181 # The outneighbors of vertex i are enumerated from 189 # The outneighbors of vertex i are enumerated from 182 190 # 183 191 # p_vertices[i] to p_vertices[i+1]  1 184 192 # (if p_vertices[i] is equal to p_vertices[i+1], then i has no outneighbours) 185 193 # 186 # This data structure is well documented in the module 194 # This data structure is well documented in the module 187 195 # sage.graphs.base.static_sparse_graph 188 196 189 197 cdef short_digraph sd … … 320 328 """ 321 329 322 330 cdef int n = G.order() 323 331 324 332 if n == 0: 325 333 return {} 326 334 … … 348 356 349 357 d_tmp[int_to_vertex[j]] = None 350 358 d[int_to_vertex[j]] = d_tmp 351 359 352 360 c_predecessors += n 353 361 354 362 sage_free(predecessors) 355 363 return d 356 364 … … 385 393 sage: from sage.graphs.distances_all_pairs import distances_all_pairs 386 394 sage: g = graphs.PetersenGraph() 387 395 sage: distances_all_pairs(g) 388 {0: {0: 0, 1: 1, 2: 2, 3: 2, 4: 1, 5: 1, 6: 2, 7: 2, 8: 2, 9: 2}, 389 1: {0: 1, 1: 0, 2: 1, 3: 2, 4: 2, 5: 2, 6: 1, 7: 2, 8: 2, 9: 2}, 390 2: {0: 2, 1: 1, 2: 0, 3: 1, 4: 2, 5: 2, 6: 2, 7: 1, 8: 2, 9: 2}, 391 3: {0: 2, 1: 2, 2: 1, 3: 0, 4: 1, 5: 2, 6: 2, 7: 2, 8: 1, 9: 2}, 392 4: {0: 1, 1: 2, 2: 2, 3: 1, 4: 0, 5: 2, 6: 2, 7: 2, 8: 2, 9: 1}, 393 5: {0: 1, 1: 2, 2: 2, 3: 2, 4: 2, 5: 0, 6: 2, 7: 1, 8: 1, 9: 2}, 394 6: {0: 2, 1: 1, 2: 2, 3: 2, 4: 2, 5: 2, 6: 0, 7: 2, 8: 1, 9: 1}, 395 7: {0: 2, 1: 2, 2: 1, 3: 2, 4: 2, 5: 1, 6: 2, 7: 0, 8: 2, 9: 1}, 396 8: {0: 2, 1: 2, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1, 7: 2, 8: 0, 9: 2}, 396 {0: {0: 0, 1: 1, 2: 2, 3: 2, 4: 1, 5: 1, 6: 2, 7: 2, 8: 2, 9: 2}, 397 1: {0: 1, 1: 0, 2: 1, 3: 2, 4: 2, 5: 2, 6: 1, 7: 2, 8: 2, 9: 2}, 398 2: {0: 2, 1: 1, 2: 0, 3: 1, 4: 2, 5: 2, 6: 2, 7: 1, 8: 2, 9: 2}, 399 3: {0: 2, 1: 2, 2: 1, 3: 0, 4: 1, 5: 2, 6: 2, 7: 2, 8: 1, 9: 2}, 400 4: {0: 1, 1: 2, 2: 2, 3: 1, 4: 0, 5: 2, 6: 2, 7: 2, 8: 2, 9: 1}, 401 5: {0: 1, 1: 2, 2: 2, 3: 2, 4: 2, 5: 0, 6: 2, 7: 1, 8: 1, 9: 2}, 402 6: {0: 2, 1: 1, 2: 2, 3: 2, 4: 2, 5: 2, 6: 0, 7: 2, 8: 1, 9: 1}, 403 7: {0: 2, 1: 2, 2: 1, 3: 2, 4: 2, 5: 1, 6: 2, 7: 0, 8: 2, 9: 1}, 404 8: {0: 2, 1: 2, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1, 7: 2, 8: 0, 9: 2}, 397 405 9: {0: 2, 1: 2, 2: 2, 3: 2, 4: 1, 5: 2, 6: 1, 7: 1, 8: 2, 9: 0}} 398 406 """ 399 407 … … 423 431 424 432 425 433 d[int_to_vertex[j]] = d_tmp 426 434 427 435 c_distances += n 428 436 429 437 sage_free(distances) 430 438 return d 431 439 … … 457 465 sage: from sage.graphs.distances_all_pairs import distances_and_predecessors_all_pairs 458 466 sage: g = graphs.PetersenGraph() 459 467 sage: distances_and_predecessors_all_pairs(g) 460 ({0: {0: 0, 1: 1, 2: 2, 3: 2, 4: 1, 5: 1, 6: 2, 7: 2, 8: 2, 9: 2}, 461 1: {0: 1, 1: 0, 2: 1, 3: 2, 4: 2, 5: 2, 6: 1, 7: 2, 8: 2, 9: 2}, 462 2: {0: 2, 1: 1, 2: 0, 3: 1, 4: 2, 5: 2, 6: 2, 7: 1, 8: 2, 9: 2}, 463 3: {0: 2, 1: 2, 2: 1, 3: 0, 4: 1, 5: 2, 6: 2, 7: 2, 8: 1, 9: 2}, 464 4: {0: 1, 1: 2, 2: 2, 3: 1, 4: 0, 5: 2, 6: 2, 7: 2, 8: 2, 9: 1}, 465 5: {0: 1, 1: 2, 2: 2, 3: 2, 4: 2, 5: 0, 6: 2, 7: 1, 8: 1, 9: 2}, 466 6: {0: 2, 1: 1, 2: 2, 3: 2, 4: 2, 5: 2, 6: 0, 7: 2, 8: 1, 9: 1}, 467 7: {0: 2, 1: 2, 2: 1, 3: 2, 4: 2, 5: 1, 6: 2, 7: 0, 8: 2, 9: 1}, 468 8: {0: 2, 1: 2, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1, 7: 2, 8: 0, 9: 2}, 468 ({0: {0: 0, 1: 1, 2: 2, 3: 2, 4: 1, 5: 1, 6: 2, 7: 2, 8: 2, 9: 2}, 469 1: {0: 1, 1: 0, 2: 1, 3: 2, 4: 2, 5: 2, 6: 1, 7: 2, 8: 2, 9: 2}, 470 2: {0: 2, 1: 1, 2: 0, 3: 1, 4: 2, 5: 2, 6: 2, 7: 1, 8: 2, 9: 2}, 471 3: {0: 2, 1: 2, 2: 1, 3: 0, 4: 1, 5: 2, 6: 2, 7: 2, 8: 1, 9: 2}, 472 4: {0: 1, 1: 2, 2: 2, 3: 1, 4: 0, 5: 2, 6: 2, 7: 2, 8: 2, 9: 1}, 473 5: {0: 1, 1: 2, 2: 2, 3: 2, 4: 2, 5: 0, 6: 2, 7: 1, 8: 1, 9: 2}, 474 6: {0: 2, 1: 1, 2: 2, 3: 2, 4: 2, 5: 2, 6: 0, 7: 2, 8: 1, 9: 1}, 475 7: {0: 2, 1: 2, 2: 1, 3: 2, 4: 2, 5: 1, 6: 2, 7: 0, 8: 2, 9: 1}, 476 8: {0: 2, 1: 2, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1, 7: 2, 8: 0, 9: 2}, 469 477 9: {0: 2, 1: 2, 2: 2, 3: 2, 4: 1, 5: 2, 6: 1, 7: 1, 8: 2, 9: 0}}, 470 {0: {0: None, 1: 0, 2: 1, 3: 4, 4: 0, 5: 0, 6: 1, 7: 5, 8: 5, 9: 4}, 471 1: {0: 1, 1: None, 2: 1, 3: 2, 4: 0, 5: 0, 6: 1, 7: 2, 8: 6, 9: 6}, 472 2: {0: 1, 1: 2, 2: None, 3: 2, 4: 3, 5: 7, 6: 1, 7: 2, 8: 3, 9: 7}, 473 3: {0: 4, 1: 2, 2: 3, 3: None, 4: 3, 5: 8, 6: 8, 7: 2, 8: 3, 9: 4}, 474 4: {0: 4, 1: 0, 2: 3, 3: 4, 4: None, 5: 0, 6: 9, 7: 9, 8: 3, 9: 4}, 475 5: {0: 5, 1: 0, 2: 7, 3: 8, 4: 0, 5: None, 6: 8, 7: 5, 8: 5, 9: 7}, 476 6: {0: 1, 1: 6, 2: 1, 3: 8, 4: 9, 5: 8, 6: None, 7: 9, 8: 6, 9: 6}, 477 7: {0: 5, 1: 2, 2: 7, 3: 2, 4: 9, 5: 7, 6: 9, 7: None, 8: 5, 9: 7}, 478 8: {0: 5, 1: 6, 2: 3, 3: 8, 4: 3, 5: 8, 6: 8, 7: 5, 8: None, 9: 6}, 478 {0: {0: None, 1: 0, 2: 1, 3: 4, 4: 0, 5: 0, 6: 1, 7: 5, 8: 5, 9: 4}, 479 1: {0: 1, 1: None, 2: 1, 3: 2, 4: 0, 5: 0, 6: 1, 7: 2, 8: 6, 9: 6}, 480 2: {0: 1, 1: 2, 2: None, 3: 2, 4: 3, 5: 7, 6: 1, 7: 2, 8: 3, 9: 7}, 481 3: {0: 4, 1: 2, 2: 3, 3: None, 4: 3, 5: 8, 6: 8, 7: 2, 8: 3, 9: 4}, 482 4: {0: 4, 1: 0, 2: 3, 3: 4, 4: None, 5: 0, 6: 9, 7: 9, 8: 3, 9: 4}, 483 5: {0: 5, 1: 0, 2: 7, 3: 8, 4: 0, 5: None, 6: 8, 7: 5, 8: 5, 9: 7}, 484 6: {0: 1, 1: 6, 2: 1, 3: 8, 4: 9, 5: 8, 6: None, 7: 9, 8: 6, 9: 6}, 485 7: {0: 5, 1: 2, 2: 7, 3: 2, 4: 9, 5: 7, 6: 9, 7: None, 8: 5, 9: 7}, 486 8: {0: 5, 1: 6, 2: 3, 3: 8, 4: 3, 5: 8, 6: 8, 7: 5, 8: None, 9: 6}, 479 487 9: {0: 4, 1: 6, 2: 7, 3: 4, 4: 9, 5: 7, 6: 9, 7: 9, 8: 6, 9: None}}) 480 488 """ 481 489 482 490 from sage.rings.infinity import Infinity 483 491 cdef int n = G.order() 484 492 485 493 if n == 0: 486 494 return {}, {} 487 495 … … 518 526 519 527 d_distance[int_to_vertex[j]] = t_distance 520 528 d_predecessor[int_to_vertex[j]] = t_predecessor 521 529 522 530 c_distances += n 523 531 c_predecessor += n 524 532 … … 599 607 # Wiener index # 600 608 ################ 601 609 602 def wiener_index(G): 603 r""" 604 Returns the Wiener index of the graph. 605 606 The Wiener index of a graph `G` can be defined in two equivalent 607 ways [KRG96b]_ : 608 610 def wiener_index(G): 611 r""" 612 Returns the Wiener index of the graph. 613 614 The Wiener index of a graph `G` can be defined in two equivalent 615 ways [KRG96b]_ : 616 609 617  `W(G) = \frac 1 2 \sum_{u,v\in G} d(u,v)` where `d(u,v)` denotes the 610 distance between vertices `u` and `v`. 611 612  Let `\Omega` be a set of `\frac {n(n1)} 2` paths in `G` such that `\Omega` 618 distance between vertices `u` and `v`. 619 620  Let `\Omega` be a set of `\frac {n(n1)} 2` paths in `G` such that `\Omega` 613 621 contains exactly one shortest `uv` path for each set `\{u,v\}` of 614 vertices in `G`. Besides, `\forall e\in E(G)`, let `\Omega(e)` denote the 615 paths from `\Omega` containing `e`. We then have 622 vertices in `G`. Besides, `\forall e\in E(G)`, let `\Omega(e)` denote the 623 paths from `\Omega` containing `e`. We then have 616 624 `W(G) = \sum_{e\in E(G)}\Omega(e)`. 617 618 EXAMPLE:619 620 From [GYLL93c]_, cited in [KRG96b]_::621 622 sage: g=graphs.PathGraph(10)623 sage: w=lambda x: (x*(x*x 1)/6)624 sage: g.wiener_index()==w(10)625 True626 627 REFERENCE:628 625 629 .. [KRG96b] S. Klavzar, A. Rajapakse, and I. Gutman. The Szeged and the 626 EXAMPLE: 627 628 From [GYLL93c]_, cited in [KRG96b]_:: 629 630 sage: g=graphs.PathGraph(10) 631 sage: w=lambda x: (x*(x*x 1)/6) 632 sage: g.wiener_index()==w(10) 633 True 634 635 REFERENCE: 636 637 .. [KRG96b] S. Klavzar, A. Rajapakse, and I. Gutman. The Szeged and the 630 638 Wiener index of graphs. *Applied Mathematics Letters*, 9(5):4549, 1996. 631 632 .. [GYLL93c] I. Gutman, Y.N. Yeh, S.L. Lee, and Y.L. Luo. Some recent 639 640 .. [GYLL93c] I. Gutman, Y.N. Yeh, S.L. Lee, and Y.L. Luo. Some recent 633 641 results in the theory of the Wiener number. *Indian Journal of 634 Chemistry*, 32A:651661, 1993. 642 Chemistry*, 32A:651661, 1993. 635 643 """ 636 if not G.is_connected(): 637 from sage.rings.infinity import Infinity 638 return +Infinity 644 if not G.is_connected(): 645 from sage.rings.infinity import Infinity 646 return +Infinity 639 647 640 648 cdef unsigned short * distances = c_distances_all_pairs(G) 641 649 cdef int NN = G.order()*G.order() … … 645 653 s += distances[i] 646 654 sage_free(distances) 647 655 return s/2 648 656 649 657 650 658 651 659 ################## … … 732 740 733 741 sage: g = graphs.DiamondGraph() 734 742 sage: floyd_warshall(g, paths = False, distances = True) 735 {0: {0: 0, 1: 1, 2: 1, 3: 2}, 736 1: {0: 1, 1: 0, 2: 1, 3: 1}, 737 2: {0: 1, 1: 1, 2: 0, 3: 1}, 743 {0: {0: 0, 1: 1, 2: 1, 3: 2}, 744 1: {0: 1, 1: 0, 2: 1, 3: 1}, 745 2: {0: 1, 1: 1, 2: 0, 3: 1}, 738 746 3: {0: 2, 1: 1, 2: 1, 3: 0}} 739 747 740 748 TESTS: