473,761 Members | 4,739 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Recursive structures

(This is a repost from another python newsgroup).
While using some nested data structures, I've seen that I'd like to
have a function that tells me if a given data structure contains one or
more cyclic references (a way to recognise a cycle in a graph is to do
a depth-first search, marking vertices along the way. An already marked
vertex means a cycle.)
Do you know where I can find a function like this?
To be more explicit about this function purpose, here are some asserts,
that call an hypothetical "isrecursiv e" function (I've added some
examples of big structures because I'd like such function to be fast
for them too):
l = [0]
m = [l, l]
assert isrecursive(m) == False

assert not isrecursive([[[[1]]]])

h = [0]
h[0] = h
print h
assert isrecursive(h)

n = 2000
v = [0] * n
for i in range(n):
v[i] = [0]
for i in range(n):
v[i][0] = v[i]
assert not (False in map(isrecursive , v) )

n = 10**5
h = range(n)
assert not isrecursive(h)
h[-1] = h
assert isrecursive(h)
h[0] = h
assert isrecursive(h)

h = [0]
h[0] = h
h = tuple(h)
print h
assert isrecursive(h)

d1 = {"a": 1}
d1["a"] = d1
print d1
assert isrecursive(d1)

# I presume that dict keys cannot be recursive
Thank you,
hugs,
Bearophile

Jul 18 '05 #1
7 1997
<be************ @lycos.com> wrote:
(This is a repost from another python newsgroup).
While using some nested data structures, I've seen that I'd like to
have a function that tells me if a given data structure contains one or
more cyclic references (a way to recognise a cycle in a graph is to do
a depth-first search, marking vertices along the way. An already marked
vertex means a cycle.)
Do you know where I can find a function like this?
To be more explicit about this function purpose, here are some asserts,
that call an hypothetical "isrecursiv e" function (I've added some
examples of big structures because I'd like such function to be fast
for them too):

l = [0]
m = [l, l]
assert isrecursive(m) == False

assert not isrecursive([[[[1]]]])

h = [0]
h[0] = h
print h
assert isrecursive(h)

n = 2000
v = [0] * n
for i in range(n):
v[i] = [0]
for i in range(n):
v[i][0] = v[i]
assert not (False in map(isrecursive , v) )

n = 10**5
h = range(n)
assert not isrecursive(h)
h[-1] = h
assert isrecursive(h)
h[0] = h
assert isrecursive(h)

h = [0]
h[0] = h
h = tuple(h)
print h
assert isrecursive(h)

d1 = {"a": 1}
d1["a"] = d1
print d1
assert isrecursive(d1)

# I presume that dict keys cannot be recursive


how about:

def isrecursive(x):
return "..." in repr(x)

(won't work if the structures can contain arbitrary strings, though...)

</F>

Jul 18 '05 #2
Am Mon, 20 Dec 2004 04:22:24 -0800 schrieb bearophileHUGS:
I've seen that I'd like to
have a function that tells me if a given data structure contains one or
more cyclic references


Hi,

does this help you?

from types import *

def isrecursive(obj , dict=None):
if dict==None:
dict={}
mytype=type(obj )
if mytype in [GeneratorType, SliceType]:
obj=list(obj)
mytype=ListType

l=[]
MethodWrapperTy pe=type(l.__del attr__)

if type(obj) in [NoneType, TypeType, BooleanType, IntType, LongType, FloatType, ComplexType,
StringType, UnicodeType, FunctionType, CodeType, ClassType, MethodType,
UnboundMethodTy pe, BuiltinMethodTy pe, BuiltinFunction Type,
ModuleType, FileType, XRangeType,
EllipsisType, TracebackType, FrameType, BufferType, StringType, MethodWrapperTy pe,
MethodWrapperTy pe]:
return 0
myid=id(obj)
if dict.has_key(my id):
return 1
dict[myid]=1
for attr in dir(obj):
value=getattr(o bj, attr)
if isrecursive(val ue, dict):
return 1
try:
for item in obj:
if isrecursive(ite m, dict):
return 1
except TypeError:
pass

try:
for key, value in obj.items():
if isrecursive(val ue, dict):
return 1
except AttributeError:
pass

return 0

def test_isrecursiv e():
s="sdf"
assert(not isrecursive(s))
l=[]
assert(not isrecursive(l))

l.append(l)
assert(isrecurs ive(l))
print "OK"

d={}
assert(not isrecursive(d))
d["foo"]=()
assert(not isrecursive(d))
d["foo2"]="foo2"
assert(not isrecursive(d))
d["foo3"]=d
assert(isrecurs ive(d))

if __name__=="__ma in__":
test_isrecursiv e()
--
Thomas Güttler, http://www.thomas-guettler.de/
Jul 18 '05 #3

Thomas Guettler wrote:
code to do the test


The following transformation of his code shows how exceptions
can be used to make code read more clearly. There are a few
issues (such as AVOIDITER) to decide on, and usually you are
inquiring about your own data structures (which you'll know
more about). Recursive data structures, like deepcopy, are
matters of interpretation of data, and cannot really be answered
without knowing what you mean by your data (and possibly why you
are inquiring). I have also done a few things to speed up the
code (my premature optimization sin) such as lifting constant
expressions to module load time.
from types import *
MethodWrapperTy pe = type([].__delattr__)

LEAVES = set([NoneType, TypeType, BooleanType, IntType, LongType,
FloatType, ComplexType, StringType, UnicodeType, FunctionType,
CodeType, ClassType, MethodType, UnboundMethodTy pe,
BuiltinMethodTy pe, BuiltinFunction Type, ModuleType, FileType,
XRangeType, EllipsisType, TracebackType, FrameType, BufferType,
StringType, MethodWrapperTy pe, MethodWrapperTy pe])

FORCELIST = set([GeneratorType, SliceType])
# these are dicey: can cause lots of side-effects
AVOIDITER = set()
# Here go things like itertools.count -- infinite generators

class RecursionFoundE rror(Exception) : pass

def walks(obj, seen):
identity = id(obj)
if identity in seen:
raise RecursionFoundE rror, obj
mytype = type(obj)
if mytype in LEAVES:
return
seen = seen.copy() # (obj, obj) is not recursive, so new copy
seen.add(identi ty)
if mytype in FORCELIST:
obj = list(obj) # this is a new obj, so not in the structure
mytype = ListType
for attr in dir(obj):
walks(getattr(o bj, attr), seen)

if mytype not in AVOIDITER:
try:
for item in obj:
walks(item, seen)
except TypeError:
pass
try:
for key, value in obj.items():
walks(key, seen) # Key might be object w/ hash method
walks(value, seen)
except AttributeError:
pass
def isrecursive(obj ):
try:
walks(obj, set())
except RecursionFoundE rror, err:
return True # err.args[0] is the looping object
return False
--Scott David Daniels
Sc***********@A cm.Org
Jul 18 '05 #4
Thank you very much Thomas Güttler for you quick answer, but I think
your program doesn't contain an algorithm to spot cycles (like the
usual cyclic graph algorithm). In my first post there was an assert to
spot this problem:

l = [0]
m = [l, l]
print m
print isrecursive(m)

Gives:
[[0], [0]]
1

m contains a shared reference, but not a recursive one.
Thank you Fredrik Lundh too,
bear hugs,
Bearophile

Jul 18 '05 #5
Scott David Daniels wrote:
if mytype not in AVOIDITER:
try:
for item in obj:
walks(item, seen)
except TypeError:
pass
try:
for key, value in obj.items():
walks(key, seen) # Key might be object w/ hash method
walks(value, seen)
except AttributeError:
pass


You might also write this section something like:

if mytype not in AVOIDITER:
try:
itr = iter(obj)
except TypeError:
pass
else:
for item in itr:
walks(item, seen)
try:
walks(obj[item], seen)
except TypeError:
pass

This should allow you to support any mapping type that supports iter()
over the keys and the __getitem__ protocol.

Steve
Jul 18 '05 #6
be************@ lycos.com wrote:
While using some nested data structures, I've seen that I'd like to
have a function that tells me if a given data structure contains one or
more cyclic references (a way to recognise a cycle in a graph is to do
a depth-first search, marking vertices along the way. An already marked
vertex means a cycle.)
Do you know where I can find a function like this?


http://python.org/doc/current/lib/mo...t.html#l2h-749
Jul 18 '05 #7
Leif K-Brooks:
http://python.org/doc/current/lib/mo...t.html#l2h-749


Thank you very much, I see that the function is already there, even
with the same name :-)

I've seen that it doesn't work for all my tests, like this one with n =
3000:

from pprint import isrecursive
from time import clock
n = 950
print "n =", n
l = []
for i in xrange(n): l = [n-i, l]
if n < 30: print l
t = clock()
assert not isrecursive(l)
print round(clock()-t, 3), "s"

In the function _safe_repr of the pprint.py module there is a recursive
call:
orepr, oreadable, orecur = _safe_repr(o, context, maxlevels, level)

Probably this _safe_repr function can be modified (with a lot of work?)
to be iterative (using a list as a stack) to avoid such stack overflows
(the list too can overflow, but its capacity is enough for most
purposes). Python doesn't have C-like unsafe buffer overrun, so using a
list as stack probably improves security a little, and probably makes
_safe_repr faster.

See you,
Bearophile

Jul 18 '05 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

19
2293
by: Carlos Ribeiro | last post by:
Hello all, Here I am using some deeply nested, tree-like data structures. In some situations I need to traverse the tree; the old-style way to do it is to write a recursive method on the node class, as in: def walk(self): """old-style recursive tree traversal""" child.do_something for child in childs:
4
1920
by: Magnus Lie Hetland | last post by:
Hi! I've been looking at ways of dealing with nested structures in regexps (becuase I figured that would be faster than the Python parsing code I've currently got) and came across a few interesting things... First there is this, mentioning the (?<DEPTH>) and (?<-DEPTH>) constructs of the .NET regexp matcher: http://www.rassoc.com/gregr/weblog/archive.aspx?post=590
7
2658
by: aurora | last post by:
I love generator and I use it a lot. Lately I've been writing some recursive generator to traverse tree structures. After taking closer look I have some concern on its performance. Let's take the inorder traversal from http://www.python.org/peps/pep-0255.html as an example. def inorder(t): if t: for x in inorder(t.left):
25
2830
by: Mike MacSween | last post by:
Regular viewers may want to turn off now. This will be an orchestral management system. Musicians and other staff being booked/paid for jobs. A job may contain other jobs, e.g: World Tour contains US leg and Europe leg (and others) US leg contains State tours (and others)
0
9554
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9377
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10136
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9989
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9925
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9811
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8814
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7358
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
1
3913
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.