Processing math: 100%
Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

answered 7 years ago

dan_fulea gravatar image

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 47 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.)