Unexpected execution of MPI - python

I'm trying to parallelize a code in Python but I'm having some problems. This is the part of the code:
survivor = Survivor(32*2, 32*4)
if rank == 1:
a = 'audio/zombie_theme.ogg'
b = 'images/dungeon.jpg'
c = 'images/dead.jpg'
d = survivor.movement()
else:
a = None
b = None
c = None
d = None
a = comm.bcast(a, root=1)
b = comm.bcast(b, root=1)
c = comm.bcast(c, root=1)
d = comm.bcast(d, root=1)
if rank == 0:
pygame.mixer.music.load(a)
pygame.mixer.music.play(-1)
pygame.display.set_caption('Zombie Game')
screen = pygame.display.set_mode((display_width,display_height))
Tile.pre_init(screen)
clock = pygame.time.Clock()
dungeon = pygame.image.load(b)
keepPlaying = True
while keepPlaying:
screen.blit(dungeon, (0,0))
Zombie.spawn(total_frames, FPS)
Zombie.update(screen, survivor)
d
When I call d in the last line, shouldn't it call survivor.movement() defined in process 1? When I run the game, my main character does not move, as it's supposed to do. But, when I remove d from everywhere and put survivor.movement() in the last line, it works as expected. Could anybody help me?

d = survivor.movement
Delete curly braces. When you write d = movement() you actually assign d to whatever movement returns, not the function itself.

Related

Comparing two values every n second and run a code based on the current and previous compared results in a while loop in python

Here is something I am trying to do:
A is a value that is constantly changing, and B is a fixed value
compare A and B every 5 seconds
if A > B, do something
if A < B, do something else
but if the current compared result is the same as the previous one (like if the current result is A > B, and the previous result is also A > B), do nothing until the result changes.
repeat
I really don’t know what to do with the 4th one, could somebody give me a hint?
Huge thanks
As you have not mentioned any language preference, I am using python here.
import time
c = time.time()
if A>B:
state = True
''' Do the initial action for this state'''
elif A<B:
state = False
''' Do the initial action for this state'''
while True:
if (time.time() - c) >= 5:
c = time.time()
A = check_A() # some dummy function for illustration purpose
B = check_B() # some dummy function for illustration purpose
if A>B:
if not state:
state = True
''' Do something that you like '''
elif A<B:
if state:
state = False
''' Do something that you like '''
Here I have assumed that you do not want anything to happen when when A==B. The logic here that unless the state changes there will be no action for that particular state.
If here you do not want your code to be continuously running then you can use time.sleep(SLEEP_TIME).
import time
if A>B:
state = True
''' Do the initial action for this state'''
elif A<B:
state = False
''' Do the initial action for this state'''
while True:
time.sleep(5)
A = check_A() # some dummy function for illustration purpose
B = check_B() # some dummy function for illustration purpose
if A>B:
if not state:
state = True
''' Do something that you like '''
elif A<B:
if state:
state = False
''' Do something that you like '''
Store the previous comparision in a variable.
previousComparison = '';
while True:
time.sleep(5) # Sleep for 5 seconds
if a > b and previousComparision != 'AIsGreater':
#do 2.
previousComparision = 'AIsGreater'
if b > a and previousComparision = 'BIsGreater':
#do 3.
#previousComparision = 'BIsGreater'
You can just remember the previous value of B and compare it as well to determine if you need to do something
def update(val):
return (val + 7) % 1000 # example
A = 500
B = 0
previous_B = 100000
while True:
previous_B = B
B = update(B)
if previous_B < A and B > A:
print(B, 'Do something')
elif previous_B > A and B < A:
print(B, 'Do something else')
In order to do this, you can keep track of the previous result in an additional variable
import random
previous = None
a = 10
b = 2
i = 0
while(i < 20):
print (a, b)
if (a > b and previous != False):
print('do something')
elif (a < b and previous == False):
print('do something else')
previous = a < b
b = random.randint(0, 20)
i += 1

Can you stop the main function from running from an internal function

I am currently working on a project to wirelessly control my neo-pixel lights. I have an infinite loop in one of my functions to create a rainbow effect. The only problem is when the next function needs to be called (i.e to turn off the lights) the program won't stop looping through the first loop. I was wondering is it was possible to stop a function from running via an internal function and if it was how to go about doing it. I would appreciate any help anyone could give me.
Thanks in advance,
Henry G
Here is my code:
from flask import Flask
import board
import neopixel
import time
# Choose an open pin connected to the Data In of the NeoPixel strip, i.e. board.D18
pixel_pin = board.D18
# The number of LEDs
num_pixels = 20
# The order of the LED colors - RGB or GRB. Some LED Strips - like ours - have red and green reversed!
ORDER = neopixel.GRB
pixels = neopixel.NeoPixel(pixel_pin, num_pixels, brightness=0.7, auto_write=False, pixel_order=ORDER)
app = Flask(__name__)
rainOn = False
triggered = False
go = False
#app.route('/')
def index():
return 'Hello world'
#app.route('/rgb/<r>/<g>/<b>')
def color(r, g, b):
global go
go = False
global pixels
pixels.fill((int(r), int(g), int(b)))
pixels.show()
return 'The color you have chosen is now showing!'
#app.route('/off')
def off():
global go
global rainOn
rainOn = False
go = False
global pixels
pixels.fill((0, 0, 0))
pixels.show()
return 'The lights are now off!'
#app.route('/rainbow')
def rainbow():
global go
global triggered
global rainOn
rainOn = True
triggered = True
go = True
while go == True:
def end():
go = False
return
def wheel(pos):
if pos < 0 or pos > 255:
r = g = b = 0
elif pos < 85:
r = int(pos * 3)
g = int(255 - pos*3)
b = 0
elif pos < 170:
pos -= 85
r = int(255 - pos*3)
g = 0
b = int(pos*3)
else:
pos -= 170
r = 0
g = int(pos*3)
b = int(255 - pos*3)
return (r, g, b) if ORDER == neopixel.RGB or ORDER == neopixel.GRB else (r, g, b, 0)
def rainbow_cycle(wait):
global rainOn
global triggered
global go
if go == True and triggered == True and rainOn == True:
for j in range(255 ** 255):
for i in range(num_pixels):
pixel_index = (i * 256 // num_pixels) + j
pixels[i] = wheel(pixel_index & 255)
pixels.show()
time.sleep(wait)
elif go == False or triggered == False or rainOn == False:
end()
while rainOn == True and triggered == True and go == True:
rainbow_cycle(0.0035)
return 'Rainbow off'
return 'Done'
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0')

if statement wont take variable 'a' and 'b' when declared in python if statement

I have been curious about how to simplify my work. But for now, my
problem is how to pass variables through functions and to get this If
statement to work. The variable a and b need to pass into the if
statement to check if the string is in the array 'colors' or
'other_colors'
import random;
hot_spot=0;
colors = ['R','G','B','O','P']
other_colors =['RED','GREEN','BLUE','ORANGE','PURPLE']
guesser_array=[]
def code_maker():
code_maker_array=[]
for i in range(4):
ran = random.randint(0,4)
print (ran)
code_maker_array.append(colors[ran])
print(code_maker_array)
return code_maker_array
x = code_maker()
def code_breaker():
trys = 0;
cbi = input('please put in r,g,b,o,p or red,green,blue,orange,purple_ ')
cbi = cbi.upper()
if ( isinstance(cbi,str) == True):
print ('it is a string')
print (cbi)
for i in range(4):
if (len(cbi)>=3):
a = other_colors[i].find(cbi)
else:
b = colors[i].find(cbi)
if (a >= 0 or b >= 0):
print ('yummmeiabui aebfiahfu dsdsde')
y = code_breaker()
"""
def code_checker(x):
print (x)
code_checker(x)
"""
Try this:
import random
hot_spot=0
colors = ['R','G','B','O','P']
other_colors =['RED','GREEN','BLUE','ORANGE','PURPLE']
guesser_array=[]
def code_maker():
code_maker_array=[]
for i in range(4):
ran = random.randint(0,4)
print (ran)
code_maker_array.append(colors[ran])
print(code_maker_array)
return code_maker_array
x = code_maker()
def code_breaker():
trys = 0;
cbi = input('please put in r,g,b,o,p or red,green,blue,orange,purple_ ')
cbi = cbi.upper()
if ( isinstance(cbi,str) == True):
print ('it is a string')
print (cbi)
for i in range(4):
a=b=0 #This line added
if (len(cbi)>=3):
a = other_colors[i].find(cbi)
else:
b = colors[i].find(cbi)
if (a >= 0 or b >= 0):
print ('yummmeiabui aebfiahfu dsdsde')
y = code_breaker()
"""
def code_checker(x):
print (x)
code_checker(x)
"""
The variables a and b you have defined run out of scope as soon as their respective if blocks end. To prevent this, you can simply define them by initializing them to 0 (or any other value) outside of the if statement.
While Lucefer's answer simplified code a lot, I added this because defining variables in an outer scope like this is and modifying their values later on (in the if blocks in your case) is a very common practice, you might find it helpful somewhere else as well.
remove this whole code segment
for i in range(4):
if (len(cbi)>=3):
a = other_colors[i].find(cbi)
else:
b = colors[i].find(cbi)
if (a >= 0 or b >= 0):
print ('yummmeiabui aebfiahfu dsdsde')
just simply add
if( (cbi in other_colors) or (cbi in colors) ):
print ('yummmeiabui aebfiahfu dsdsde')

How to implement overwriting in my current "Redo" function in Python?

I have (along with the help of my buddy #Nuclearman who answered one of my other questions) partly implemented a redo function in my program, which is a turtle graphics program that draws any letter pressed on the keyboard pressed by the user onto the turtle graphics canvas. I say "partly" because although it does redo, it does not do what it was meant for, which is overwrite the last undone letter with a new one if one is called by the user. For example, suppose you wrote "HELLO" on the canvas and undid up to "H". You then wanted to replace the "E", with, lets say, an "A". So you draw an "A". When you press redo, it is supposed to now show "HAL" right? Well, that is not the case with my redo. My redo instead, following the example I gave, outputs this:
It draws the E over the A! Well, that is not what the redo is meant for! So, how could I make so that the turtle would draw "HAL" instead of whatever is happening in the image above and implement this based on my current redo function shown below? Any help is greatly appreciated! :)
My Redo function:
def Clear():
# Clear the canvas
clear()
speed(0)
tracer(0,0)
def redoHandler():
if undoHandler.handling == True and draw.drawing == True and len(newerdeq) > 0:
# "newerdeq" is my 'forward' stack for the redo to be possible
redoHandler.handling = True
if not hasattr(redoHandler, "counter"):
redoHandler.counter = 0
redoHandler.counter += 1
draw.counter += 1
print("`draw` has been called {} times.".format(draw.counter))
Clear()
ui = newerdeq.pop() #<-- Pop redone items...
function.append(ui) #<-- back to the "undo" function stack.
penup()
try:
goto(o,p)
except:
goto(-200, 100)
pendown()
try:
# Now execute all the items (from an earlier queue that all letter functions go to first) if defined as a Point class or as a function
for i in function:
k = i.getXY()
penup()
goto(k)
pendown()
hk = i.getletterheight()
global letter_height
letter_height = hk
rk = i.getletterwidth()
global letter_width
letter_width = rk
hw = i.getwidth()
width(hw)
op = i.getcolor()
try:
color(op)
except:
for g in colors:
cp = g.getcolor2()
colormode(255)
color(cp)
j = i.getfunction()
j()
except:
i()
update()
Well, I solved it. It was a very simple fix. All I had to do was in the queue that each letter is executed, just put:
if len(newerdeq) > 0:
newerdeq.pop()
Like this:
def draw(x):
draw.drawing = True
if not hasattr(draw, 'counter'):
draw.counter = 0
global drawing
q.put(x)
process = False
drawingLock.acquire()
if not drawing:
process = True
drawing = True
drawingLock.release()
if process:
if not q.empty():
v = xcor()
y = ycor()
c = pencolor()
w = width()
ph = letter_height
pw = letter_width
x()
po = Point(v,y,c,w,isdown(),x,ph,pw)
function.append(po)
if len(newerdeq) > 0:
newerdeq.pop() #<-- Here it is... fixed.
draw.counter += 1
print("`draw` has been called {} times.".format(draw.counter))
if x == draw_W:
draw_W.drawing = True
draw_W.counter += 1
draw.counter -= 1
elif x == draw_Y:
draw_Y.drawing = True
draw_Y.counter += 1
draw.counter -= 1
global h
h = (x)
drawingLock.acquire()
drawing = False
drawingLock.release()

Python - how to distinguish between 2 objects of the same name in a list

So i'm making a genetic algorithm in python. The goal is for the "organism" to get to the top of the screen (x,20). I have a loop that creates the population which is a list of objects of type "Organism". Here is the code for the Organism class:
class Organism(object):
def __init__(self, genes,ID):
self.genes = genes
self.position = [0,0]
self.thisTime=str()
self.geneTranslation = []
self.ID=ID
def move(self,d):
if d == "f" or d == "forward":
self.position[1] += 1
elif d == "b" or d == "back":
self.position[1] -= 1
elif d == "r" or d == "right":
self.position[0] += 1
elif d == "l" or d == "left":
self.position[0] -= 1
print(self.position)
def isInContactWith(self,point):
point = list(point)
if self.position == point:
return True
else:
return False
def run(self):
for i in range(0,4):
if i == 0:
self.geneTranslation.extend(["f"] * self.genes[0])
elif i == 1:
self.geneTranslation.extend(["b"] * self.genes[1])
elif i == 2:
self.geneTranslation.extend(["r"] * self.genes[2])
elif i == 3:
self.geneTranslation.extend(["l"] * self.genes[3])
r.shuffle(self.geneTranslation)
for x in range(1,20):
self.thisTime = r.choice(self.geneTranslation)
self.move(self.thisTime)
As you can see, the genes specify the chance of a particular move. The problem is in the for loop that creates the population and runs it(ive added prints for debugging):
population = []
yValues={}
running = True
BestOrganism=Organism([25,25,25,25],0)
SecondOrganism=Organism([25,25,25,25],1)
for count in range(5):
for x in range(10):
a = lambda: r.randint(0, 3)
c = lambda: r.randint(-1, 1)
b = BestOrganism.genes
anOrganism = Organism(b,x)
anOrganism.genes[a()]+=c()
population.append(anOrganism)
for j in range(len(population)):
print("Organism " + str(population[j].ID) + str(population[j].genes))
population[j].run()
yValues[population[j].ID]=population[j].position[1]
if population[j].position[1]>=20:
print(population[j].genes)
running = False
break
BestOrganism=max(yValues)
for k in range(len(population)):
if population[k].ID==BestOrganism:
BestOrganism=population[k]
print(yValues[max(yValues)])
print(str(population)+"\n"+str(yValues)+"\n"+str(BestOrganism.genes))
population=[]
yValues={}
No errors pop up but, whenever I try to "mutate" a particular part of the organism's genes with anOrganism.genes[a()]=c(), it ends up mutating every organism in the list, even the ones not yet created, so that all of their genes are the exact same at the end (as seen in the final product). Why is python doing this?
It's because of this line: anOrganism = Organism(b,popPos).
So on the first iteration of the loop, you create an Organism and set the self.genes to b. Then you modify the .genes of that organism you just created.
When you iterate through the loop again, you are creating a new organism but with the same exact list, so it has the changes from the previous one.
Basically, there is only one b, and you are setting the .genes attribute of every organism to point to that single list. So any and everytime you change it, it changes for all of the organisms.
What you need to do is be sending in a copy of b to the constructor of Organism.
And then change the line anOrganism = Organism(b,popPos) to be
anOrganism = Organism(list(b), popPos)
The key is these lines:
b = BestOrganism.genes
anOrganism = Organism(b,popPos)
The list of genes will be shared by every organism created by that line. That is, anOrganism.genes is exactly the same object as BestOrganism.genes. So a change to BestOrganism.genes is seen in anOrganism.genes.
Python has an easy way to make a copy of a list, using "slicing". Change the line to this:
anOrganism = Organism(b[:],popPos)
Now anOrganism has its own genes, starting off identical to but still distinct from BestOrganism's genes.
Postscript:
Here is a simplified form, using literal ints instead of the random functions:
>>> class Organism(object):
... def __init__(self, genes, ID):
... self.genes = genes
... self.ID = ID
...
>>> zero = Organism([25,25,25,25],0)
>>> one = Organism(zero.genes, 1)
>>> two = Organism(zero.genes[:], 2)
>>> one.genes[2] += 5
>>> two.genes[3] += 7
>>> zero.genes
[25, 25, 30, 25]
>>> one.genes
[25, 25, 30, 25]
>>> two.genes
[25, 25, 25, 32]
>>>

Categories

Resources