1

I can't figure out why my implementation of Reverse Cuthill–McKee algorithm is returning at the wrong place. Basically, it produces the correct result, but when I run the code, it returns a different value.

Here is a full code with a graph, could some one please explain this behavior?

import numpy as np

A=np.diag(np.ones(8))

nzc=[[4],[2,5,7],[1,4],[6],[0,2],[1,7],[3],[1,5]]

for i in range(len(nzc)):
    for j in nzc[i]:
        A[i,j]=1

# define the Result queue
R = ["C"]*A.shape[0]


def getDegree(Graph):
    """
    find the degree of each node. That is the number
    of neighbours or connections.
    (number of non-zero elements) in each row minus 1.
    Graph is a Cubic Matrix.
    """
    degree = [0]*Graph.shape[0]
    for row in range(Graph.shape[0]):
        degree[row] = len(np.flatnonzero(Graph[row]))-1
    return degree
    
# find the starting point, the parent
degree = getDegree(A)

adj = getAdjcncy(A)
degree2=degree[::]
adj2 = adj[::]
digar=np.array(degree2)
pivots = list(np.where(digar == digar.min())[0])

def main_loop2(deg,start, adj,R):
    degcp=deg[:]
    digar=np.array(deg)
    # use np.where here to get indecies of minimums
    if start not in R:
        R.append(start)
        degcp.pop(start)
        if start in pivots:
           pivots.pop(start)
           print "p: ", pivots
    Q=adj[start]
    for idx, item in enumerate(Q):
        if item not in R:
            R.append(item)
            print "R", R
    print "starts", adj[R[-1]]
    Q=adj[R[-1]]
    if set(Q).issubset(set(R)) and len(R) < len(degcp) :
         print "will now look for new pivot"
         p = pivots[0]
         pivots.pop(0)
         print "pivots", pivots
         print "starting with" , p
         main_loop2(deg,p,adj,R)
         return 'this is never reached'
    elif len(R) < len(degcp):
         main_loop2(deg,R[-1],adj,R)
         return 'wrong'
    else:
         print "will return R"
         print type(R)
         return R      
    
inl=[]
Res = main_loop2(degree2,0, adj,inl)

print(Res)

output:

Degrees: [1, 3, 2, 1, 2, 2, 1, 2]
0
p:  [3, 6]
R [0, 4]
starts [0, 2]
R  2 degcp 7
R [0, 4, 2]
starts [1, 4]
R  3 degcp 8
R [0, 4, 2, 1]
starts [2, 5, 7]
R  4 degcp 8
R [0, 4, 2, 1, 5]
R [0, 4, 2, 1, 5, 7]
starts [1, 5]
will now look for new pivot
pivots [6]
starting with 3
R [0, 4, 2, 1, 5, 7, 3, 6]
starts [3]
will return R
<type 'list'>
wrong

So the question is:
Why is the function working OK at all cycles of the recursion, but in the last one, it returns the value wrong? The output shows that the last else is only reached once, yet, a list is not returned, and I am quite helpless here. I would appreciate if someone shed some light on this.

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
oz123
  • 27,559
  • 27
  • 125
  • 187

1 Answers1

3

The top level of your recursive call goes into here:

elif len(R) < len(degcp):
     main_loop2(deg,R[-1],adj,R)
     return 'wrong'

Whatever happens further inside the recursive call to main_loop2 doesn't matter; when it comes back out, it will execute the return 'wrong' statement. You need to actually return the value the innermost call produces, all the way back out to the top level - it's not going to magically happen for you.

Did you mean to return main_loop2(...)?

tzaman
  • 46,925
  • 11
  • 90
  • 115
  • on a second read, I now understand your answer. I see your point. I did not know that function called inside a function actually returns. Is this always the case with recursion or just with python? – oz123 Nov 08 '12 at 05:22
  • Every language with function calls behaves this way (barring tail recursion optimization). Each call creates a new entry on the call stack, each `return` only returns to the previous stack frame ; whether that was a previous copy of itself or some other function entirely makes no difference. – tzaman Nov 08 '12 at 05:27