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 low-level 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 time-consuming, 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 time-consuming, 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(n-1)} 2` paths in `G` such that `\Omega` 618 distance between vertices `u` and `v`. 619 620 - Let `\Omega` be a set of `\frac {n(n-1)} 2` paths in `G` such that `\Omega` 613 621 contains exactly one shortest `u-v` 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):45--49, 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:651--661, 1993. 642 Chemistry*, 32A:651--661, 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: