I want to create a new list (self.Input/self.Output) each time the while loop is called. And append this new list to another list at the end of it (self.Input_full/self.Output_full).
I have tried to reset the list at the start of the while loop with either just setting them back to empty: self.Output = [[],[],[],[]]
or deleting the information held by them: del self.Output[:]
but this didn't work, since then I got empty lists in the Full lists
import threading
class PepperCommandEvaluator(object):
def __init__(self):
self.Input = [[],[],[],[]]
self.Input_full = []
self.Output = [[],[],[],[]]
self.Output_full = []
self.count = 0
self.event = threading.Event()
def send_thread(self):
while self.count < 2:
self.count = self.count + 1
self.event.set()
sequence = [[1,1,1],[1,0,1],[1,3,3]]
for cmd in sequence:
rospy.loginfo("sending command")
rospy.Rate(0.5).sleep()
msg = Twist()
msg.linear.x = cmd[0]
msg.linear.y = cmd[1]
msg.angular.z = cmd[2]
t = rospy.get_rostime()
self.Input[0].append(cmd[0])
self.Input[1].append(cmd[1])
self.Input[2].append(cmd[2])
self.Input[3].append(t.secs + t.nsecs * 1e-9)
self.Input_full.append(self.Input)
self.event.clear()
def receive_thread(self,msg):
if self.event.isSet():
self.frame_id = msg.header.frame_id
self.x_odom = msg.pose.pose.position.x
self.y_odom = msg.pose.pose.position.y
self.z_odom = msg.pose.pose.position.z
self.ang_odom = msg.pose.pose.orientation.z
self.time = msg.header.stamp.secs
self.Output[0].append(self.x_odom)
self.Output[1].append(self.y_odom)
self.Output[2].append(self.ang_odom)
self.Output[3].append(self.time)
else:
self.Output_full.append(self.Output)
if __name__ == "__main__":
tros = PepperCommandEvaluator()
tros.send_thread()
My desired output is to get a new self.Input and self.Output_odom with each loop and append this list to the self.Input_full and self.Output_full_odom respectively.
In the end depending on the amount of times n the loop is ran, this should look like this:
self.Output_full = [[self.Output_1,self.Output_2,...,self.Output_n]]
Since lists in python are handled by reference, when you append the reference to Input to Input_full, then delete Input, you also delete the entry in Input_full. To avoid this, you want to append a copy of Input, then clear the real thing. You can also change the reference of Input to an empty list after appending it.
def send_thread(self):
while self.count < 2:
self.count = self.count + 1
self.event.set()
sequence = [[1,1,1],[1,0,1],[1,3,3]]
self.Input = [[],[],[]] # Reassigning to a new list at the top
for cmd in sequence:
rospy.loginfo("sending command")
rospy.Rate(0.5).sleep()
msg = Twist()
msg.linear.x = cmd[0]
msg.linear.y = cmd[1]
msg.angular.z = cmd[2]
t = rospy.get_rostime()
self.Input[0].append(cmd[0])
self.Input[1].append(cmd[1])
self.Input[2].append(cmd[2])
self.Input[3].append(t.secs + t.nsecs * 1e-9)
self.Input_full.append(self.Input)
self.event.clear()
Related
I am aware that there is another post asking about simulated printers but I didn't find any actual answers to my own question there.
class LinkedQueue :
class _Node :
__slots__ = '_element', '_next'
def __init__(self, element, next = None):
self._element = element
self._next = next
def __init__(self) :
self._head = None
self._tail = None
self._size = 0
def __len__(self) :
return self._size
def is_empty(self) :
return self._size == 0
def first(self) :
if self.is_empty() :
raise Empty('Queue is empty')
return self._head._element
def dequeue(self) :
if self.is_empty():
raise Empty('Queue is empty')
answer = self._head._element
self._head = self._head._next
self._size -= 1
if self.is_empty() :
self._tail = None
return answer
def enqueue(self, e) :
newest = self._Node(e,None)
if self.is_empty() :
self._head = newest
else :
self._tail._next = newest
self._tail = newest
self._size += 1
class Printer:
def __init__(self, name, job_queue):
self._name = name
self._job_queue
self._current_job = None
class Empty(Exception) :
pass
def main():
p_jobs = LinkedQueue()
red = Printer("Red", p_jobs) # Creates Printer Red
green = Printer("Green", p_jobs) # Creates Printer Green
print("\nOptions:\n 1. Add Job \n 2. Print Pages \n 3. Status \
\n 4. Quit")
i = 0
while True:
n = str(input("\nChoice (Type the number): "))
if n == '1': # Add Job
i += 1
p = int(input("\nHow many pages? "))
j = p_jobs.job_list(i,p,next)
p_jobs.enqueue(j)
if n == '2': # Print Job
print()
p_jobs.dequeue()
i -= 1
if n == '3': # Status
print()
if n == '4': # Quit
print("\nGoodbye!")
break
This is the provided code for us. We are supposed to simulate two printers that print out pages from jobs using LinkedQueue and Node.
I have the main function barebones w/c consists of 4 options:
Add Job, Print Jobs, Status, and Quit
I have trouble understanding how to use (refer) to the enqueue and dequeue methods. Can somebody break down each part of this program so I can at least understand where to start. I also would appreciate any hints that tell me where to go from here. Thank you.
EDIT: I added my main function w/c is basically just a UI
While this is by no means a complete answer, it shows how to print out what's currently in a LinkedQueue instance.
First, add the following method to the class. It will allow the contents to be iterated.
class LinkedQueue:
def __iter__(self):
if self.is_empty():
return None # No jobs in print queue.
cur = self._head
while cur:
yield cur._element
cur = cur._next
Here's something demonstrating how to use it:
def test():
q = LinkedQueue() # Create a queue.
# Add some jobs to the LinkedQueue.
for j in range(3):
pages = randint(1, 10)
q.enqueue(('job #{}'.format(j), pages))
# Show what's currently in the LinkedQueue.
for v in q:
print(v)
# Modify the LinkedQueue and then show what's left in it.
j = q.dequeue()
print('\nafter removing one job')
for v in q:
print(v)
I am somehow new to python. I needed to use tree to store some data (file paths), The problem is when I generate the tree it seems that all objects after the root reference the same object, although step by step debugging showed the opposite. Here is my (minimized) code:
first the node class:
class PathElement:
Element = ""
IsStatic = True
Children = []
ChildrenCount = 0
def __init__(self, Element, IsStatic=True):
self.Element = Element
self.IsStatic = IsStatic
if not IsStatic:
self.Element = []
def AddChild(self, Child):
print(self, " ", Child)
self.Children.append(Child)
self.ChildrenCount = len(self.Children)
return Child
The Children is list of PathElement nodes. The code that build the tree:
def UnFoldAndCheck(self):
Path = PathElement("root")
Handler = Path
Index = 0
Count = len(self.Path)
while Index < Count:
element = self.Path[Index]
if something:
Child = None
Child = PathElement(element)
Handler.AddChild(Child)
Handler = None #Those added to debug the problem
Handler = Child
elif other_thing:
if condition:
if some_large_condition:
ChildExec = None
ChildExec = PathElement(element, False)
for i in range(0, 5):
ChildExec.Element.append(self.Path[Index + i])
Handler.AddChild(ChildExec)
Handler = None
Handler = ChildExec
Index += 4
elif another_condition:
ChildOp = None
ChildOp = PathElement(element, False)
Handler.AddChild(ChildOp)
Handler = None
Handler = ChildOp
elif some_else_condition:
if condition:
ChildExec = None
ChildExec = PathElement(element, False)
for i in range(0, 3):
ChildExec.Element.append(self.Path[Index + i])
Handler.AddChild(ChildExec)
Handler = None
Handler = ChildExec
Index += 2
elif different_condition:
ChildExec = None
ChildExec = PathElement(element, False)
for i in range(0, 3):
ChildExec.Element.append(self.Path[Index + i])
Handler.AddChild(ChildExec)
Handler = None
Handler = ChildExec
Index += 1
Index += 1
return Path
My problem is that after the tree is built when I use it it will have always same structure:
root -> object with 3 exact nodes -> same object -> same object to infinity
while the expected is:
root -> object -> first children -> second children -> third children -> etc
I'm sure the problem is related to how python handle object references but I can't see where the problem exactly. Any help?
Update:
I reproduced the problem with smaller code (same class PathElement):
from PathElement import PathElement
Path = PathElement("root")
Handler = Path
for i in range(1,6):
Child = PathElement("child"+str(i))
Handler.AddChild(Child)
Handler = Child
Tree = Path
while True:
print(Tree.Element)
if len(Tree.Children) > 0:
Tree = Tree.Children[0]
else:
break
This code will make infinite loop
I guess you come from Java or a similar language. It's important to stick with Python's conventions (Jakob Sachs gave you va link to the Style Guide for Python Code) because that makes your mistakes are easier to identify.
Now, what's wrong here? When you wrote:
class PathElement():
Children = []
Element = ""
IsStatic = True
ChildrenCount = 0
You don't give the initial value of instance fields. You create an initialize class (static) fields. Hence, Children is a static field of the class PathElement. Here's a illustration of that:
class A():
i = []
a = A()
b = A()
a.i.append(1)
b.i.append(2)
assert a.i == b.i == [1,2]
What happens when you try to make read the leftmost part of the tree (child 0, child 0 of child 0, ...)?
while True:
print(Tree.Element)
if len(Tree.Children) > 0:
Tree = Tree.Children[0]
else:
break
Just replace Tree.Children by what it is really: PathElement.Children, that is the static field Children of the class PathElement:
while True:
print(Tree.Element)
if len(PathElement.Children) > 0:
Tree = PathElement.Children[0] # Tree has always the same value.
else:
break
Now, a example of what you can write:
class PathElement:
def __init__(self, element):
self.__element = element
self.__children = []
def add_child(self, child):
self.__children.append(child)
def children(self):
return list(self.__children)
def element(self):
return self.__element
path = ["a", "b", "c", "d", "e", "f"]
root = PathElement("root")
handler = root
while path:
child = PathElement(path.pop(0)) # you can put some conditions here, take more elements of path, ...
handler.add_child(child)
handler = child
def dfs(node):
for c in node.children():
yield c.element()
yield from dfs(c)
print (list(dfs(root)))
# a b c d e f
I am trying to create a BFS solution to the 8 puzzle problem in python. However after I 'get()' a node from the queue and find the puzzle state inside that node it seems the puzzle object has turned into a list object without the method 'getMoves()'. I am wondering why it is not still a Puzzle object?
import collections
import queue
class Node:
def __init__(self, Puzzle, last=None):
self.puzzle = Puzzle
self.last = last
def getPuzzle(self):
return self.puzzle
def getLast(self):
return self.last
class Puzzle:
def __init__(self, startState, goalState):
self.state = startState
self.goal = goalState
def getState():
return self.state
def getMoves(self):
currentState = self.state
possibleNewStates = []
zeroPos = currentState.index(0)
if zeroPos == 0:
possibleNewStates.append(move(0,1))
possibleNewStates.append(move(0,3))
elif zeroPos == 1:
possibleNewStates.append(move(1,0))
possibleNewStates.append(move(1,2))
possibleNewStates.append(move(1,4))
elif zeroPos == 2:
possibleNewStates.append(move(2,1))
possibleNewStates.append(move(2,5))
elif zeroPos == 3:
possibleNewStates.append(move(3,0))
possibleNewStates.append(move(3,4))
possibleNewStates.append(move(3,6))
elif zeroPos == 4:
possibleNewStates.append(self.move(4,1))
possibleNewStates.append(self.move(4,3))
possibleNewStates.append(self.move(4,5))
possibleNewStates.append(self.move(4,7))
elif zeroPos == 5:
possibleNewStates.append(move(5,2))
possibleNewStates.append(move(5,4))
possibleNewStates.append(move(5,8))
elif zeroPos == 6:
possibleNewStates.append(move(6,3))
possibleNewStates.append(move(6,7))
elif zeroPos == 7:
possibleNewStates.append(move(7,4))
possibleNewStates.append(move(7,6))
possibleNewStates.append(move(7,8))
else:
possibleNewStates.append(move(8,5))
possibleNewStates.append(move(8,7))
return possibleNewStates
def move(self, current, to):
changeState = self.state
save = changeState[to]
changeState[to] = changeState[current]
changeState[current] = save
return changeState
def printPuzzle(self):
copyState = self.state
print(copyState)
'''
for i in range(9):
if i == 2 or i == 5:
print((str)(copyState[i]))
else:
print((str)(copyState[i])+" ", end="")
print()
'''
def isSolved(self):
return self.state == self.goal
class Solver:
def __init__(self, Puzzle):
self.puzzle = Puzzle
def solveBFS(self):
puzzle = self.puzzle
startNode = Node(puzzle)
myQueue = queue.Queue(0)
myQueue.put(startNode)
myPuzzle = startNode.getPuzzle()
print(myPuzzle.isSolved())
while myQueue:
currentNode = myQueue.get()
currentPuzzle = currentNode.puzzle
if currentPuzzle == [0,1,2,3,4,5,6,7,8]:
return currentNode
nextMoves = currentPuzzle.getMoves() # << ERROR HERE
for state in nextMoves:
nextNode = Node(state, currentNode)
myQueue.put(nextNode)
startingState = [7,2,4,5,0,6,8,3,1]
goalState = [0,1,2,3,4,5,6,7,8]
myPuzzle = Puzzle(startingState, goalState)
mySolver = Solver(myPuzzle)
goalNode = mySolver.solveBFS()
goalPuzzle = goalNode.getPuzzle()
goalPuzzle.printPuzzle()
That's because in some cases, state must be a list when you create a new node:
nextMoves = currentPuzzle.getMoves()
for state in nextMoves:
nextNode = Node(state, currentNode)
Here state must've been a list returned from the Puzzle.getMoves() list:
def getMoves(self):
# ...
possibleNewStates = []
# append various objects to possibleNewStates.
return possibleNewStates
In getMoves() you use two callables to produces new states:
possibleNewStates.append(move(0,1))
and
possibleNewStates.append(self.move(4,1))
Puzzle.move() produces a list; you do some swapping on self.state which you set to a list:
def move(self, current, to):
changeState = self.state
save = changeState[to]
changeState[to] = changeState[current]
changeState[current] = save
return changeState
Note that this mutates self.state in-place; you did not create a copy of the value here.
self.state was set from the first argument to Puzzle(), which was a list:
startingState = [7,2,4,5,0,6,8,3,1]
goalState = [0,1,2,3,4,5,6,7,8]
myPuzzle = Puzzle(startingState, goalState)
so self.move() returns a list, not a Puzzle() instance.
You didn't share the definition of the move() global function; if this also produces a list then that's another cause of your Node.puzzle values becoming lists.
You probably want to correct all move() calls to use self.move(), and for self.move() to return a new Puzzle() instance. You'll need to create a copy of self.state list here too:
def move(self, current, to):
changeState = self.state[:] # create a copy
changeState[to], changeState[current] = changeState[current], changeState[to]
return Puzzle(changeState, self.goal)
All move() in getMoves() should be changed to self.move(). Otherwise you are working with an unbound Puzzle.
My basic idea was to create a linked list, and as each new value comes in, add 1/N times the new value and subtract 1/N times the first value, then move the pointer to first along by one and free the memory that had been associated with first.
This won't ultimately be implemented in Python but just to get the process clear in my head, I tried to write it in Python, but my implementation is flawed. Do I need a doubly linked list for this? Is there an alternative approach (not linked-list based) that would be better?
Here's my attempt so far:
class Link:
def __init__(self,val):
self.next = None
self.value = val
class LinkedList:
def __init__(self,maxlength):
self.current_link = None
self.maxlength = maxlength
self.sum = 0.
self.average = None
self.length = 0
self._first_link = None
def add_link(self,val):
new_link = Link(val)
new_link.next = self.current_link
self.current_link = new_link
if self._first_link is None:
self._first_link = self.current_link
self.sum += val
if self.length < self.maxlength:
self.length += 1
else:
self.sum -= self._first_link.value
self._first_link = self._first_link.next # this line is flawed
self.average = self.sum/self.length
def get_first(self):
return self._first_link.value
# Main
ll = LinkedList(5)
for ii in xrange(10):
ll.add_link(ii)
print ii,ll.get_first(),ll.average
The problem is that _first_link gets set to a value that doesn’t have a next. That is, _first_link gets set to the first item that's added, but its next is None, so I don't see how to move it along by 1 as I want to. This is what makes me wonder if a doubly linked list is needed.
I'd appreciate any advice.
I think the simplest implementation is to use a circular linked list (a.k.a. a ring):
class Link(object):
def __init__(self, value=0.0):
self.next = None
self.value = value
class LinkedRing(object):
def __init__(self, length):
self.sum = 0.0
self.length = length
self.current = Link()
# Initialize all the nodes:
last = self.current
for i in xrange(length-1): # one link is already created
last.next = Link()
last = last.next
last.next = self.current # close the ring
def add_val(self, val):
self.sum -= current.value
self.sum += val
self.current.value = val
self.current = self.current.next
def average(self):
return self.sum / self.length
# Test example:
rolling_sum = LinkedRing(5)
while True:
x = float(raw_input())
rolling_sum.add_val(x)
print(">> Average: %f" % rolling_sum.average())
You can implement this using collections.deque and the numerically stable math for maintaining running averages:
import collections
class AveragingBuffer(object):
def __init__(self, maxlen):
assert( maxlen>1)
self.q=collections.deque(maxlen=maxlen)
self.xbar=0.0
def append(self, x):
if len(self.q)==self.q.maxlen:
# remove first item, update running average
d=self.q.popleft()
self.xbar=self.xbar+(self.xbar-d)/float(len(self.q))
# append new item, update running average
self.q.append(x)
self.xbar=self.xbar+(x-self.xbar)/float(len(self.q))
if __name__=="__main__":
import scipy
ab=AveragingBuffer(10)
for i in xrange(32):
ab.append(scipy.rand())
print ab.xbar, scipy.average(ab.q), len(ab.q)
Okay, I thought of a solution that works in O[1] time. I'm still curious if anyone has a linked-list-based solution, but this solution avoids the LL entirely:
class Recent:
def __init__(self,maxlength):
self.maxlength = maxlength
self.length = 0
self.values = [0 for ii in xrange(maxlength)]
self.index = 0
self.total = 0.
self.average = 0.
def add_val(self,val):
last = self.values[self.index%self.maxlength]
self.values[self.index%self.maxlength] = val
self.total += val
self.total -= last
if self.length < self.maxlength:
self.length += 1
self.average = self.total / self.length
self.index += 1
def print_vals(self):
print ""
for ii in xrange(self.length):
print ii,self.values[ii%self.maxlength]
print "average:",self.average
# Example to show it works
rr = Recent(5)
for ii in xrange(3):
rr.add_val(ii)
rr.print_vals()
for ii in xrange(13):
rr.add_val(ii)
rr.print_vals()
This is just a very simple code and my reference is from here: http://www.mathcs.emory.edu/~cheung/Courses/323/Syllabus/Map/skip-list-impl.html#why-q
I think the insert function is okay but when I try to use the get() function, it doesn't return anything, instead it loops endlessly inside the searchEntry() part. I don't know what's wrong. In the insert() function, the searchEntry() operates well. It returns the reference to the floorEntry(k) entry containing a key that is smaller than the key that needs to be inserted in the skiplist. Please help me figure out the source of the error in the searchEntry() function. I'm sorry I'm not really good at this. Thank you!
from QuadLinkedList import QLLNode
import random
class Skippy:
def __init__(self):
self._p1 = QLLNode("MINUS_INF")
self._p2 = QLLNode("PLUS_INF")
self._head = self._p1
self._tail = self._p2
self._p1.setNext(self._p2)
self._p2.setPrev(self._p1)
self._height = 0
self._n = 0
def insert(self, key, value):
p = self.searchEntry(key)
print "p = " + str(p.getKey())
q = QLLNode(key, value)
q.setPrev(p)
q.setNext(p.getNext())
p.getNext().setPrev(q)
p.setNext(q)
i = 0
while random.randint(0,1) != 0:
if i >= self._height:
self._height += 1
newHead = QLLNode("MINUS_INF")
newTail = QLLNode("PLUS_INF")
newHead.setNext(newTail)
newHead.setDown(self._head)
newTail.setPrev(newHead)
newTail.setDown(self._tail)
self._head.setUp(newHead)
self._tail.setUp(newTail)
self._head = newHead
self._tail = newTail
while p.getUp() == None:
p = p.getPrev()
p = p.getUp()
e = QLLNode(key,None)
e.setPrev(p)
e.setNext(p.getNext())
e.setDown(q)
p.getNext().setPrev(e)
p.setNext(e)
q.setUp(e)
q = e
i += 1
self._n += 1
return None
def get(self, key):
p = self.searchEntry(key)
if key == p.getKey():
return p.getElement()
else:
return "There's None!"
def searchEntry(self, key):
p = self._head
while True:
while p.getNext().getKey() != "PLUS_INF" and p.getNext().getKey() <= key:
p = p.getNext()
if p.getDown() != None:
p = p.getDown()
else:
break
return p
The issue isn't in the code for searchEntry, which appears to have the correct logic. The problem is that the list structure is getting messed up. I believe the issue is with the code you have for adding a new level to the list in insert. Specifically this bit:
if i >= self._height: #make an empty level
self._height += 1
self._minus.setNext(self._plus)
self._minus.setDown(self._head)
self._plus.setPrev(self._minus)
self._plus.setDown(self._tail)
self._head.setUp(self._minus)
self._tail.setUp(self._plus)
self._head = self._minus
self._tail = self._plus
The thing that stands out to me about this code is that you're not creating any new nodes, just modifying existing ones, which is what is breaking your list structure. You need to create new head and tail nodes, I think, and link them into the top of the strucutre. (minus and plus are not part of the algorithm as described at your link, so I'm not sure what you're doing with them.) Probably you want something like this:
if i >= self._height: #make an empty level
self._height += 1
newHead = QLLNode("MINUS_INF")
newTail = QLLNode("PLUS_INF")
newHead.setNext(newTail)
newHead.setDown(self._head)
newTail.setPrev(newHead)
newTail.setDown(self._tail)
self._head.setUp(newHead)
self._head = newHead
self._tail.setUp(newTail)
self._tail = newTail