# L-40 MCS 275 Wed 23 Apr 2008 : searchgraph.py

# Given the adjacency matrix of a graph,
# this scripts contains two functions:
# (1) to compute vertices with maximal degree,
# (2) to find a path between two vertices.

from numpy import *

def MaxDegrees(A):
   """
   The degree of a vertex v counts #edges
   that have v as an end point.
   Returns a tuple: first element is a list
   whose degree equals the second element.
   """
   n = len(A)
   d = [sum([A[i][j] for i in range(0,n)]) \
                     for j in range(0,n)]
   m = max(d)
   L = [(i,d[i]) for i in range(0,len(d))]
   F = filter(lambda (x,y): y == m, L)
   r = [ x for (x,y) in F ]
   return (r,m)

def FindPath(A,i,j,d,P):
   """
   Searches for a path between vertices i
   and j in a graph with adjacency matrix A,
   using at most d intermediary nodes.
   P contains the list of visited nodes.
   """
   if A[i][j] == 1:
      return P + [j]
   else:
      if d > 0:
         for k in range(0,len(A)):
            if A[i][k] == 1 and not k in P:
               KP = FindPath(A,k,j,d-1,P + [k])
               if KP[len(KP)-1] == j: return KP
      return P

def main():
   """
   Prompts the user for the number of vertices
   and generates a random adjacency matrix.
   """
   n = input('Give #vertices : ')
   B = random.randint(0,2,(n,n))
   A = (B + B.transpose()) % 2
   print A
   (b,d) = MaxDegrees(A)
   print 'best connected vertices : ', b
   print 'with degree ', d
   print 'finding a path '
   start = input('  give start vertex : ')
   target = input('  give target vertex : ')
   P = FindPath(A,start,target,n,[start])
   print 'path : ', P

if __name__ == "__main__": main()
