Ticket #10885: trac10885-efficiency_improvment.patch

File trac10885-efficiency_improvment.patch, 8.7 KB (added by ylchapuy, 10 years ago)

apply after trac_10885.patch

  • sage/graphs/base/c_graph.pyx

    # HG changeset patch
    # User YLC <y@l.c>
    # Date 1299781042 -3600
    # Node ID e48617ca9b33093a267897cddb601892f91d5948
    # Parent  a89bf1d7cfa850a31a9785bbfa64d449c5a2b1b5
    #10885 - reviewer efficiency improvment
    
    diff -r a89bf1d7cfa8 -r e48617ca9b33 sage/graphs/base/c_graph.pyx
    a b  
    25042504        return list(a & b)
    25052505
    25062506def floyd_warshall(gg, paths = True, distances = False):
    2507     r""" 
     2507    r"""
    25082508    Computes the shortest path/distances between all pairs of vertices.
    25092509
    25102510    For more information on the Floyd-Warshall algorithm, see the `Wikipedia
     
    25252525
    25262526        Depending on the input, this function return the dictionary of paths,
    25272527        the dictionary of distances, or a pair of dictionaries
    2528         ``(distances,paths)`` where ``distance[u][v]`` denotes the distance of a
     2528        ``(distances, paths)`` where ``distance[u][v]`` denotes the distance of a
    25292529        shortest path from `u` to `v` and ``paths[u][v]`` denotes an inneighbor
    25302530        `w` of `v` such that `dist(u,v)= 1 + dist(u,w)`.
    25312531
     
    25702570        sage: len(p) == dist[u][v] + 2
    25712571        True
    25722572    """
    2573     from sage.rings.infinity import Infinity   
     2573    from sage.rings.infinity import Infinity
    25742574    cdef CGraph g = <CGraph> gg._backend._cg
    2575     cdef int n = max(g.verts())+1
     2575
     2576    cdef list gverts = g.verts()
     2577
     2578    cdef int n = max(gverts) + 1
    25762579
    25772580    if n > <unsigned short> -1:
    25782581        raise ValueError("The graph backend contains more than "+(<unsigned short> -1)+" nodes")
    25792582
    2580     # Dictionaries of distance, precedent element, and integers
    2581     cdef dict d_prec = dict()
    2582     cdef dict d_dist = dict()
    2583     cdef dict tmp
    2584 
     2583    # All this just creates two tables prec[n][n] and dist[n][n]
     2584    cdef unsigned short * t_prec
     2585    cdef unsigned short * t_dist
     2586    cdef unsigned short ** prec
     2587    cdef unsigned short ** dist
     2588
     2589    cdef int i
    25852590    cdef int v_int
    25862591    cdef int u_int
    25872592    cdef int w_int
    2588     cdef int i
    2589 
    2590     # All this just creates two tables prec[n][n] and dist[n][n]
    2591     cdef unsigned short * t_prec = <unsigned short *> sage_malloc(n*n*sizeof(short))
    2592     cdef unsigned short * t_dist = <unsigned short *> sage_malloc(n*n*sizeof(short))
    2593     cdef unsigned short ** prec = <unsigned short **> sage_malloc(n*sizeof(short *))
    2594     cdef unsigned short ** dist = <unsigned short **> sage_malloc(n*sizeof(short *))
    2595     prec[0] = t_prec
     2593
     2594    # init dist
     2595    t_dist = <unsigned short *> sage_malloc(n*n*sizeof(short))
     2596    dist = <unsigned short **> sage_malloc(n*sizeof(short *))
    25962597    dist[0] = t_dist
    2597 
    25982598    for 1 <= i< n:
    2599         prec[i] = prec[i-1] + n
    26002599        dist[i] = dist[i-1] + n
    2601 
    2602     # Initializing prec and dist
    2603     memset(t_prec, 0, n*n*sizeof(short))
    26042600    memset(t_dist, -1, n*n*sizeof(short))
    2605 
    26062601    # Copying the adjacency matrix (vertices at distance 1)
    2607     for v_int in g.verts():
    2608         prec[v_int][v_int] = v_int     
     2602    for v_int in gverts:
    26092603        dist[v_int][v_int] =  0
    26102604        for u_int in g.out_neighbors(v_int):
    26112605            dist[v_int][u_int] = 1
    2612             prec[v_int][u_int] = v_int
     2606
     2607    if paths:
     2608        # init prec
     2609        t_prec = <unsigned short *> sage_malloc(n*n*sizeof(short))
     2610        prec = <unsigned short **> sage_malloc(n*sizeof(short *))
     2611        prec[0] = t_prec
     2612        for 1 <= i< n:
     2613            prec[i] = prec[i-1] + n
     2614        memset(t_prec, 0, n*n*sizeof(short))
     2615        # Copying the adjacency matrix (vertices at distance 1)
     2616        for v_int in gverts:
     2617            prec[v_int][v_int] = v_int
     2618            for u_int in g.out_neighbors(v_int):
     2619                prec[v_int][u_int] = v_int
    26132620
    26142621    # The algorithm itself.
    2615 
    2616     for w_int in g.verts():
    2617         for v_int in g.verts():
    2618             for u_int in g.verts():
    2619 
     2622    cdef unsigned short *dv, *dw
     2623    cdef int dvw
     2624    cdef int val
     2625
     2626    for w_int in gverts:
     2627        dw = dist[w_int]
     2628        for v_int in gverts:
     2629            dv = dist[v_int]
     2630            dvw = dv[w_int]
     2631            for u_int in gverts:
     2632                val = dvw + dw[u_int]
    26202633                # If it is shorter to go from u to v through w, do it
    2621                 if dist[v_int][u_int] > dist[v_int][w_int] + dist[w_int][u_int]:
    2622                     dist[v_int][u_int] = dist[v_int][w_int] + dist[w_int][u_int]
    2623                     prec[v_int][u_int] = prec[w_int][u_int]
    2624 
    2625     # If the paths are to be returned
     2634                if dv[u_int] > val:
     2635                    dv[u_int] = val
     2636                    if paths:
     2637                        prec[v_int][u_int] = prec[w_int][u_int]
     2638
     2639    # Dictionaries of distance, precedent element, and integers
     2640    cdef dict d_prec
     2641    cdef dict d_dist
     2642    cdef dict tmp_prec
     2643    cdef dict tmp_dist
     2644
     2645    cdef dict ggbvi = gg._backend.vertex_ints
     2646    cdef dict ggbvl = gg._backend.vertex_labels
     2647
     2648    if paths: d_prec = {}
     2649    if distances: d_dist = {}
     2650    for v_int in gverts:
     2651        if paths: tmp_prec = {}
     2652        if distances: tmp_dist = {}
     2653        v = vertex_label(v_int, ggbvi, ggbvl, g)
     2654        for u_int in gverts:
     2655            u = vertex_label(u_int, ggbvi, ggbvl, g)
     2656            if paths:
     2657                tmp_prec[u] = (None if v == u
     2658                               else vertex_label(prec[v_int][u_int], ggbvi, ggbvl, g))
     2659            if distances:
     2660                tmp_dist[u] = (dv[u_int] if (dv[u_int] != <unsigned short> -1)
     2661                               else Infinity)
     2662        if paths: d_prec[v] = tmp_prec
     2663        if distances: d_dist[v] = tmp_dist
     2664
    26262665    if paths:
    2627         for v_int in g.verts():
    2628             tmp = dict()
    2629             v = vertex_label(v_int, gg._backend.vertex_ints, gg._backend.vertex_labels, gg._backend._cg)
    2630 
    2631             for u_int in g.verts():
    2632                 u = vertex_label(u_int, gg._backend.vertex_ints, gg._backend.vertex_labels, gg._backend._cg)
    2633                 w = (None if v == u
    2634                      else vertex_label(prec[v_int][u_int], gg._backend.vertex_ints, gg._backend.vertex_labels, gg._backend._cg))
    2635                 tmp[u] = w
    2636                
    2637             d_prec[v] = tmp
    2638 
    2639     sage_free(t_prec)
    2640     sage_free(prec)
    2641 
    2642     # If the distances are to be returned
    2643     if distances:
    2644         for v_int in g.verts():
    2645             tmp = dict()
    2646             v = vertex_label(v_int, gg._backend.vertex_ints, gg._backend.vertex_labels, gg._backend._cg)
    2647 
    2648             for u_int in g.verts():
    2649                 u = vertex_label(u_int, gg._backend.vertex_ints, gg._backend.vertex_labels, gg._backend._cg)
    2650 
    2651                 tmp[u] = dist[v_int][u_int] if (dist[v_int][u_int] != <unsigned short> -1) else Infinity
    2652                
    2653             d_dist[v] = tmp
     2666        sage_free(t_prec)
     2667        sage_free(prec)
    26542668
    26552669    sage_free(t_dist)
    26562670    sage_free(dist)
    26572671
    26582672    if distances and paths:
    26592673        return d_dist, d_prec
    2660     elif paths:
     2674    if paths:
    26612675        return d_prec
    2662     else:
     2676    if distances:
    26632677        return d_dist
    26642678
    26652679cdef class Search_iterator:
  • sage/graphs/generic_graph.py

    diff -r a89bf1d7cfa8 -r e48617ca9b33 sage/graphs/generic_graph.py
    a b  
    1042010420        pred = {}
    1042110421        verts = self.vertices()
    1042210422        for u in verts:
    10423             dist[u] = {}
    10424             pred[u] = {}
     10423            du = {}
     10424            pu = {}
    1042510425            for v in verts:
    1042610426                if self.has_edge(u, v):
    1042710427                    if by_weight is False:
    10428                         dist[u][v] = 1
    10429                     elif self.edge_label(u, v) is None or self.edge_label(u, v) == {}:
    10430                         dist[u][v] = default_weight
     10428                        du[v] = 1
    1043110429                    else:
    10432                         dist[u][v] = self.edge_label(u, v)
    10433                     pred[u][v] = u
     10430                        edge_label = self.edge_label(u, v)
     10431                        if edge_label is None or edge_label == {}:
     10432                            du[v] = default_weight
     10433                        else:
     10434                            du[v] = edge_label
     10435                    pu[v] = u
    1043410436                else:
    10435                     dist[u][v] = Infinity
    10436                     pred[u][v] = None
    10437             dist[u][u] = 0
     10437                    du[v] = Infinity
     10438                    pu[v] = None
     10439            du[u] = 0
     10440            dist[u] = du
     10441            pred[u] = pu
    1043810442
    1043910443        for w in verts:
     10444            dw = dist[w]
    1044010445            for u in verts:
     10446                du = dist[u]
    1044110447                for v in verts:
    10442                     if dist[u][v] > dist[u][w] + dist[w][v]:
    10443                         dist[u][v] = dist[u][w] + dist[w][v]
     10448                    if du[v] > du[w] + dw[v]:
     10449                        du[v] = du[w] + dw[v]
    1044410450                        pred[u][v] = pred[w][v]
    10445        
     10451
    1044610452        return dist, pred
    1044710453
    1044810454    def wiener_index(self):