Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Let us start with the following code:

def findAllPaths( G, startVertex, length ):

    vertices  = G.vertices()
    edges     = G.edges( labels=False )
    sim_edges = [ (k,j) for (j,k) in edges if j != k ]
    edges    += sim_edges

    edges . sort()

    paths = [ [ startVertex, ] ]
    L     = 0

    while L < length:
        paths = [ pat + [ vertex, ]
                  for pat in paths
                  for vertex in vertices
                  if ( pat[-1], vertex ) in edges ]
        L += 1
    return paths


G = graphs.OctahedralGraph()
pathsG7 = findAllPaths( G, 0, 7 )

for path in pathsG7:
    print ''.join( [ str(v) for v in path ] )

(There was no check for length in ZZ and length >=0 with a corresponding traceback information.) The result list ends with

04545420
04545421
04545424
04545425
04545430
04545431
04545434
04545435
04545451
04545452
04545453
04545454

One more check:

sage: len( pathsG7 )
16384
sage: 4^7
16384

The code uses a simple recursion and computes relatively quick the $4^7$ paths starting from node $0$ inside the octahedral graph. The recursion scheme is not optimal, since the while block is simply structured w.r.t. the constructive path length, which covers the values $0,1,2,3,4,5,6,7$, parallel to the "split" $7 = 1+1+1+1+1+1+1 $.

A better recursion would have been to "split in two almost equal parts", writing $7=4+3$, then make dictionaries for all paths of length $4$ and $3$, with keys (starting + ending points). The while block would join them. This is going almost to the half of the length. Now write $4=2+2$ and $3=2+1$, and so on. (It is a kind of quicksort-splitting of the number.) Then further split $2=1+1$. Starting with $27$ instead of $7$ (and having a rather sparse adjacency), we would then write:

  • either $27=16+8+2+1$, and each programmer would already feel happy,
  • or $27=14+13$, $14=7+7$ and $13=6+7$, and $7=4+3$, $6=3+3$, and... and each programmer would hate the boss for this idea.

The coding effort can now be chosen depending on the graph and the length... I tried something like:

def quickFindAllPaths( G, startVertex, length ):

    vertices  = G.vertices()
    edges     = G.edges( labels=False )
    sim_edges = [ (k,j) for (j,k) in edges if j != k ]
    edges    += sim_edges

    twopowerlogs = [ k
                     for k in [ 0 .. ceil( log(length) / log(2) ) ]
                     if  2**k <= length ]    # sorry, i never trust numeric approximations

    dic = {}    # dic of lists, k -> { v -> paths from v of length k }
    dic[0] = dict( [ ( v, [ [x,w] for (x,w) in edges if v == x ] )
                     for v in vertices ] )    # paths of len = 2^0
    for k in twopowerlogs:
        if k == 0:    continue
        dic[k] = {}
        print "k=", k
        pprint.pprint( dic[k-1] )
        for v in vertices:
            dic[k] [ v ] = [ vw + wx[1:]
                             for w  in vertices
                             for vw in dic[k-1] [ v ]
                             for wx in dic[k-1] [ w ]
                             if  vw[-1] == w ]    # paths of len 2^(k-1)+ 2^(k-1) = 2^k
    # and finally we join...
    digits = length.digits( base=2 )
    relevant_k_list = [ k
                        for k in range( len( digits ) )
                        if  digits[ k ] ]

    relevant_k_list . reverse()


    j = 0
    k0 = relevant_k_list[ 0 ]
    paths = dic[ k0 ] [ startVertex ]


    while j < len( relevant_k_list ) - 1:
        j += 1
        k  = relevant_k_list[ j ]
        paths = [ pathtow + pathfromw[1:]
                  for w in vertices
                  for pathtow   in paths
                  for pathfromw in dic[k] [ w ]
                  if  pathtow[-1] == w ]

    return paths

G = graphs.OctahedralGraph()
quickpathsG7 = quickFindAllPaths( G, 0, 7 )
quickpathsG7 . sort()

for path in quickpathsG7:
    print ''.join( [ str(v) for v in path ] )

Sorry for not documenting the function properly, best, write a better version. (The list comprehensions make the computation suboptimal.)