Iam trying to iterate through a tree, find a random instance, mutate it then exit but am having problems with recursion.
Note concerning escaping the loop after mutation I have tried raising an exception but it just exits the iterations of children and keeps iterating the parents.
import random as random
rnd=random.random
class Found(Exception): pass
def displayRandomNode(self,indent=0,probchange=0.1):
try:
if rnd()<probchange:
raise Found
elif hasattr(self,"children"):
for c in self.children:
displayRandomNode(c,indent+1,probchange)
except Found:
if type(self)==float: pass
else:
print (' '*indent),self
Note: The classes I am iterating though look like this,(the fw class is not altered directly only its instance within the children), the class node may have children of all three classes in a list.
class node:
def __init__(self,fw,children):
self.function=fw.function
self.name=fw.name
self.children=children
class paramnode:
def __init__(self,idx):
self.idx=idx
class constnode:
def __init__(self,v):
self.v=v
You should avoid using exception handling for normal flow, keep it for error handling.
Here is a possibility:
def displayRandomNode(self,indent=0,probchange=0.1):
if not hasattr(self,"children") or rnd() < probchange:
return (self, indent)
else:
c = random.choice(self.children)
return displayRandomNode(c,indent+1,probchange)
Here is another, more like your code idea of going through the whole tree with a little probability to exit at each node. Beware that it may exit without finding anything.
def displayRandomNode(self,indent=0,probchange=0.1):
if rnd() < probchange:
return (self, indent)
elif hasattr(self,"children"):
res = None
for c in self.children:
res = displayRandomNode(c,indent+1,probchange)
if res:
break
return res
Related
For the stack class below
class stack(list):
def __init__(self):
self.stack = []
self.top = -1
def isempty(self):
return self.stack == []
def push(self,x):
S.top = S.top + 1
return self.stack.append(x)
S = stack()
S.isempty() #True
S.push(5) #[5]
S.push(100) #[5,100]
print(S) # Returns empty stack []
Why does it not return the updated [5,100]?
The problem that you're asking about is that you're inheriting from list, even though you're not trying to act like a list. All this is doing is causing confusion. In particular, you're letting the list superclass define how your objects get displayed, and since you never do anything like self.append, only self.stack.append, that means it's always going to display like an empty list.
Once you fix that, your objects will always print something like this:
<__main__.stack at 0x11d919dd8>
If you want to customize that, you need to write a __repr__ method, and decide what you want it to look like.
class stack:
def __init__(self):
self.stack = []
self.top = -1
def __repr__(self):
return f'<stack({self.stack})>'
def isempty(self):
return self.stack == []
def push(self,x):
S.top = S.top + 1
return self.stack.append(x)
There are additional bugs in your code—you've still got a method that mutates the global S instead of self, and you're returning the result of list.append, which always returns None, and maybe more beyond—but these two changes will together solve the specific problem you're asking about.
I'm trying to implement an iterator class for not-necessarily-binary trees in Python. After the iterator is constructed with a tree's root node, its next() function can be called repeatedly to traverse the tree in depth-first order (e.g., this order), finally returning None when there are no nodes left.
Here is the basic Node class for a tree:
class Node(object):
def __init__(self, title, children=None):
self.title = title
self.children = children or []
self.visited = False
def __str__(self):
return self.title
As you can see above, I introduced a visited property to the nodes for my first approach, since I didn't see a way around it. With that extra measure of state, the Iterator class looks like this:
class Iterator(object):
def __init__(self, root):
self.stack = []
self.current = root
def next(self):
if self.current is None:
return None
self.stack.append(self.current)
self.current.visited = True
# Root case
if len(self.stack) == 1:
return self.current
while self.stack:
self.current = self.stack[-1]
for child in self.current.children:
if not child.visited:
self.current = child
return child
self.stack.pop()
This is all well and good, but I want to get rid of the need for the visited property, without resorting to recursion or any other alterations to the Node class.
All the state I need should be taken care of in the iterator, but I'm at a loss about how that can be done. Keeping a visited list for the whole tree is non-scalable and out of the question, so there must be a clever way to use the stack.
What especially confuses me is this--since the next() function, of course, returns, how can I remember where I've been without marking anything or using excess storage? Intuitively, I think of looping over children, but that logic is broken/forgotten when the next() function returns!
UPDATE - Here is a small test:
tree = Node(
'A', [
Node('B', [
Node('C', [
Node('D')
]),
Node('E'),
]),
Node('F'),
Node('G'),
])
iter = Iterator(tree)
out = object()
while out:
out = iter.next()
print out
If you really must avoid recursion, this iterator works:
from collections import deque
def node_depth_first_iter(node):
stack = deque([node])
while stack:
# Pop out the first element in the stack
node = stack.popleft()
yield node
# push children onto the front of the stack.
# Note that with a deque.extendleft, the first on in is the last
# one out, so we need to push them in reverse order.
stack.extendleft(reversed(node.children))
With that said, I think that you're thinking about this too hard. A good-ole' (recursive) generator also does the trick:
class Node(object):
def __init__(self, title, children=None):
self.title = title
self.children = children or []
def __str__(self):
return self.title
def __iter__(self):
yield self
for child in self.children:
for node in child:
yield node
both of these pass your tests:
expected = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
# Test recursive generator using Node.__iter__
assert [str(n) for n in tree] == expected
# test non-recursive Iterator
assert [str(n) for n in node_depth_first_iter(tree)] == expected
and you can easily make Node.__iter__ use the non-recursive form if you prefer:
def __iter__(self):
return node_depth_first_iter(self)
That could still potentially hold every label, though. I want the
iterator to keep only a subset of the tree at a time.
But you already are holding everything. Remember that an object is essentially a dictionary with an entry for each attribute. Having self.visited = False in the __init__ of Node means you are storing a redundant "visited" key and False value for every single Node object no matter what. A set, at least, also has the potential of not holding every single node ID. Try this:
class Iterator(object):
def __init__(self, root):
self.visited_ids = set()
...
def next(self):
...
#self.current.visited = True
self.visited_ids.add(id(self.current))
...
#if not child.visited:
if id(child) not in self.visited_ids:
Looking up the ID in the set should be just as fast as accessing a node's attribute. The only way this can be more wasteful than your solution is the overhead of the set object itself (not its elements), which is only a concern if you have multiple concurrent iterators (which you obviously don't, otherwise the node visited attribute couldn't be useful to you).
I have been subclassing an Python's random number generator to make a generator that doesn't repeat results (it's going to be used to generate unique id's for a simulator) and I was just testing to see if it was consistent in it's behavior after it has been loaded from a previours state
Before people ask:
It's a singleton class
No there's nothing else that should be using that instance (a tear down sees to that)
Yes I tested it without the singleton instance to check
and yes when I create this subclass I do call a new instance ( super(nrRand,self).__init__())
And yes according to another post I should get consistent results see: Rolling back the random number generator in python?
Below is my test code:
def test_stateSavingConsitantcy(self):
start = int(self.r.random())
for i in xrange(start):
self.r.random()
state = self.r.getstate()
next = self.r.random()
self.r.setstate(state)
nnext = self.r.random()
self.assertEqual(next, nnext, "Number generation not constant got {0} expecting {1}".format(nnext,next))
Any help that can be provided would greatly appreciated
EDIT:
Here is my subclass as requested
class Singleton(type):
_instances = {}
def __call__(self, *args, **kwargs):
if self not in self._instances:
self._instances[self] = super(Singleton,self).__call__(*args,**kwargs)
return self._instances[self]
class nrRand(Random):
__metaclass__ = Singleton
'''
classdocs
'''
def __init__(self):
'''
Constructor
'''
super(nrRand,self).__init__()
self.previous = []
def random(self):
n = super(nrRand,self).random()
while n in self.previous:
n = super(nrRand,self).random()
self.previous.append(n)
return n
def seed(self,x):
if x is None:
x = long(time.time()*1000)
self.previous = []
count = x
nSeed = 0
while count < 0:
nSeed = super(nrRand,self).random()
count -= 1
super(nrRand,self).seed(nSeed)
while nSeed < 0:
super(nrRand,self).seed(nSeed)
count -= 1
def getstate(self):
return (self.previous, super(nrRand,self).getstate())
def setstate(self,state):
self.previous = state[0]
super(nrRand,self).setstate(state[1])
getstate and setstate only manipulate the state the Random class knows about; neither method knows that you also need to roll back the set of previously-generated numbers. You're rolling back the state inherited from Random, but then the object sees that it's already produced the next number and skips it. If you want getstate and setstate to work properly, you'll have to override them to set the state of the set of already-generated numbers.
UPDATE:
def getstate(self):
return (self.previous, super(nrRand,self).getstate())
This shouldn't directly use self.previous. Since you don't make a copy, you're returning the actual object used to keep track of what numbers have been produced. When the RNG produces a new number, the state returned by getstate reflects the new number. You need to copy self.previous, like so:
def getstate(self):
return (self.previous[:], super(nrRand, self).getstate())
I also recommend making a copy in setstate:
def setstate(self, state):
previous, parent_state = state
self.previous = previous[:]
super(nrRand, self).setstate(parent_state)
I have created a tree object in python using the following code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import re,sys,codecs
neg_markers_en=[u'not',u"napt",u'no',u'nobody',u'none',u'never']
class Node:
def __init__(self,name=None,parent=None,sentence_number=0):
self.name=name
self.next=list()
self.parent=parent
self.depth=0
self.n_of_neg=0
self.subordinate=None
self.foo=None
def print_node(self):
print self.name,'contains',[(x.name,x.depth,x.foo) for x in self.next]
for x in self.next:
x.print_node()
def get_negation(self):
for x in self.next:
if x.n_of_neg!=0:
print unicode(x.depth)+u' |||',
try:
x.look_for_parent_vp()
except: print 'not in a VP',
try:
x.look_for_parent_sent()
except: print '***'
x.get_negation()
def look_for_parent_vp(self):
if self.parent.name=='VP':
self.parent.print_nont()
else:
self.parent.look_for_parent_vp()
def look_for_parent_sent(self):
if self.parent.name=='S' or self.parent.name=='SBAR':
#This is to send out to a text file, along with what it covers
print '||| '+ self.parent.name,
try:
self.parent.check_subordinate()
self.parent.print_nont()
print '\n'
except:
print u'no sub |||',
self.parent.print_nont()
print '\n'
elif self.parent=='None': print 'root |||'
else:
self.parent.look_for_parent_sent()
def print_nont(self):
for x in self.next:
if x.next==[]:
print unicode(x.name),
else: x.print_nont()
def mark_subordinate(self):
for x in self.next:
if x.name=='SBAR':
x.subordinate='sub'
else: x.subordinate='main'
x.mark_subordinate()
def check_subordinate(self):
if self.subordinate=='sub':
print u'sub |||',
else:
self.parent.check_subordinate()
def create_tree(tree):
#replace "n't" with 'napt' so to avoid errors in splitting
tree=tree.replace("n't",'napt')
lista=filter(lambda x: x!=' ',re.findall(r"\w+|\W",tree))
start_node=Node(name='*NULL*')
current_node=start_node
for i in range(len(lista)-1):
if lista[i]=='(':
next_node=Node()
next_node.parent=current_node
next_node.depth=current_node.depth+1
current_node.next.append(next_node)
current_node=next_node
elif lista[i]==')':
current_node=current_node.parent
else:
if lista[i-1]=='(' or lista[i-1]==')':
current_node.name=lista[i]
else:
next_node=Node()
next_node.name=lista[i]
next_node.parent=current_node
#marks the depth of the node
next_node.depth=current_node.depth+1
if lista[i] in neg_markers_en:
current_node.n_of_neg+=1
current_node.next.append(next_node)
return start_node
Now all the nodes are linked so that the children nodes of a parent node are appended to a list and each one of these child nodes are referred back to their parent through the instance parent.
I have the following problem:
For each node whose name is 'S' or 'SBAR' (let's call it node_to_check), I have to look if any of its children node's name is either 'S' or 'SBAR'; if this is NOT the case I want to transform .foo attribute of the node_to_check into 'atom'.
I was thinking of something like this:
def find_node_to_check(self):
for next in self.next:
if next.name == 'S' or next.name == 'SBAR':
is_present = check_children(next)
if is_present == 'no':
find_node_to_check(next)
else:
self.foo = 'atom'
def check_children(self):
for next in self.next:
# is this way of returning correct?
if next.name == 'S' or next.name == 'SBAR':
return 'no'
else:
check_sents(next)
return 'yes'
I included in my question also the code that I have written so far. A tree structure is created in the function create_tree(tree); the input tree is a bracketed notation from the Stanford Parser.
When trying to design a novel class, knowing what you need it to do informs how you construct it. Stubbing works well here, for example:
class Node:
"""A vertex of an n-adic tree"""
def __init__(self, name):
"""since you used sentence, I assumed n-adic
but that may be wrong and then you might want
left and right children instead of a list or dictionary
of children"""
pass
def append_children(self, children):
"""adds a sequence of child Nodes to self"""
pass
def create_child(self, name):
"""creates a new Named node and adds it as a child"""
pass
def delete_child(self, name):
"""deletes a named child from self or throws exception"""
pass
And so on. Do children need to be ordered? Do you ever need to delete a node (and descendants)? Would you be able to pre-build a list of children or would you have to do it one at a time. Do you really want to store the fact that a Node is terminal (that's redundant) or do you want is_terminal() to return children is None?
Starting some programming with python at school now, and I don't know how to proceed with this problem. Any thoughts?
Input consists of integer separated by line breaks. Your program should submit them in a linked list, traverse the linked list and print the highest number.
Something to take the first number, and do an action which says "if the next number is bigger, take that one, else, keep the current number, and head down the list and repeat"
Then when it gets to the end of the list, it prints the value it has.
from sys import stdin
class Kubbe:
vekt = None
neste = None
def __init__(self, vekt):
self.vekt = vekt
self.neste = None
def spor(kubbe):
# WRITE YOUR CODE HERE
# Creates linked list
forste = None
siste = None
for linje in stdin:
forrige_siste = siste
siste = Kubbe(int(linje))
if forste == None:
forste = siste
else:
forrige_siste.neste = siste
# Calls the solution function and prints the result
print spor(forste)
Input: example
54
37
100
123
1
54
Required output
123
"Linked lists" are rarely used in Python -- normally, one uses just list, the Python built-in list, which is actually more of a "dynamic vector". So, it's peculiar to see a linked list specified as part of the exercise's constraints.
But the main point is, the code you're showing is already creating a linked list -- the head is at forste, and, for each node, the next-node pointer at .neste, the payload at .vekt. So, presumably, that's not what you're asking about, no matter the text of your question.
The simple way to loop through your linked list once you have fully constructed it (i.e., at the end of the current code for spor) is
current = forste
while current is not None:
...process current.vekt...
current = current.neste
In your case, the logic for the "process" part is of course, as your Q's text already says:
if current.vekt > themax:
themax = current.vekt
The only subtlety is, you need to initially set themax, before this while loop to "the lowest possible number"; in recent versions of Python, "minus infinity" is reliably recorded and compared (though only as a float, it still compares correctly to ints), so
themax = float('-inf')
would work. More elegant might be to initially set the maximum to the first payload, avoiding messing with infinity.
Here's an answer based on your own code and language. Sorry if the new variable and function names do not translate well, as I don't speak Norwegian (Google Language Tools is my friend).
Comment: Like airplane Air Traffic Control the default language of most international programming forums such as StackOverflow is English. If you use it, you are likely to get quicker, better, and more answers -- and it probably makes the question and related answers useful to the largest number of other folks. Just my 2 øre... ;-)
from sys import stdin
class Kubbe:
vekt = None
neste = None
def __init__(self, vekt):
self.vekt = vekt
self.neste = None
def spor():
# WRITE YOUR CODE HERE
# Creates linked list
forste = None
siste = None
while True:
try:
linje = raw_input()
except EOFError:
break
forrige_siste = siste
siste = Kubbe(int(linje))
if forste == None:
forste = siste
else:
forrige_siste.neste = siste
return forste
def finne_maksimal(lenketliste):
storste = None
if lenketliste is not None:
storste = lenketliste.vekt
gjeldende = lenketliste.neste
while gjeldende is not None:
if gjeldende.vekt > storste:
storste = gjeldende.vekt
gjeldende = gjeldende.neste
return storste
lenketliste = spor()
storste = finne_maksimal(lenketliste)
if lenketliste is None:
print "tom liste"
else:
print "storste er", storste
There is a builtin function in Python called reduce, which traverses a list and "compresses" it with a given function. That is, if you have a list of five elements [a,b,c,d,e] and a function f, it will effectively do
temp = f(a,b)
temp = f( temp, c )
...
You should be able to use this to write a very neat solution.
If you want to be less abstract, you will need to iterate over each element of the list in turn, storing the greatest number so far in a variable. Change the variable only if the element you have reached is greater than the value of said variable.
This seems to work with your input (works in both python 2 and 3). Notice how max works with duck typing of Python!
This version works with Python3 also from file.
import sys
class Kubbe:
vekt = None
neste = None
def __init__(self, vekt):
self.vekt = vekt
self.neste = None
def spor():
# WRITE YOUR CODE HERE
# Creates linked list
forste = None
siste = None
while True:
linje = sys.stdin.readline().rstrip()
if not linje:
break
forrige_siste, siste = siste, Kubbe(int(linje))
if forste is None:
forste = siste
else:
forrige_siste.neste = siste
return forste
def traverse(linkedlist):
while linkedlist is not None:
yield linkedlist.vekt
linkedlist=linkedlist.neste
# Calls the solution function and prints the result
linkedlist=spor()
for item in traverse(linkedlist):
print(item)
# use builtin max:
print('Maximum is %i' % max(traverse(linkedlist)))
# if not allowed:
m = linkedlist.vekt
for item in traverse(linkedlist.neste):
if item > m: m = item
print(m)
The below code would work. The Node class represents the LinkedList Node. The LinkedList class defines the methods to add node at the end of the Linked List and find_max will traverse through the list and return the node with largest key.
class Node(object):
def __init__(self, key, next_node):
self.key = key
self.next_node = next_node
class LinkedList(object):
def __init__(self):
self.head = None
def append(self, key):
# Create a new Node
new_node = Node(key, None)
if (self.head == None):
self.head = new_node
else:
tmp = self.head
while(tmp.next_node != None):
tmp = tmp.next_node
tmp.next_node = new_node
def find_max(self):
tmp = self.head
max_num = 0
while(tmp != None):
if (tmp.key > max_num):
max_num = tmp.key
tmp = tmp.next_node
return max_num