I guess there's no need to review the algorithm in post #31 right? I'll admit I still haven't taken the time to look in detail. Here's a way without a stack:

Code:

import numpy as np
data = [[1,5,8],[3,6],[],[3],[],[],[],[],[17],[], \
[4],[22,23,24],[],[],[],[4],[],[20],[],[5], \
[8],[29],[],[],[12],[],[5],[],[4,22],[27]]
visited = np.zeros(len(data))
def main():
for i in range(len(data)):
if not visited[i]:
recurse(i, [i])
def recurse(node, parents):
visited[node] = 1
if not data[node]:
return
# check for membership chain
for i in range(len(parents)):
for j in data[node]:
if parents[i] == j:
printerr(i, parents)
# recurse
for i in data[node]:
if not visited[i]:
nextParents = parents[:]
nextParents.append(i)
recurse(i, nextParents)
def printerr(start, L):
s = ""
for i in L[start:len(L)]:
s += str(i) + " contains "
s += str(L[start])
print s
main()

Output:

Code:

3 contains 3
8 contains 17 contains 20 contains 8

Note that the chain is written in the other direction, so from left to right it's "contains" rather than "is a member of".

I'm unsure of what other comments to add, because I don't know if it will be easy for others to read the code as-is. It's the same set of data I made up for the program in post #18.