How can I speed up the following code in Python? - python

I was trying to think of a faster way to implement this code. Tried vectorizing the init of the glider object, but could not figure out how to pass in the multiple values or perform an action such as the move() function on each of the objects.
def myFunc(fairy_dust):
for particle in fairy_dust:
temp = glider(particle[0], particle[1], particle[2], particle[3])
temp = temp.move()
particle[0] = temp.x
particle[1] = temp.y
particle[2] = temp.heading

Related

How to scale multiple images with a for loop?

I'm trying to use a for-loop to iterate through a list of self classes. I want to give each one the same scale.
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("Migue/m_normal.png")
self.quieto = pygame.image.load("Migue/m_normal.png")
self.andando = pygame.image.load("Migue/m_andando_normal.png")
self.image = pygame.transform.scale(self.image, sizenorm)
states = [self.quieto, self.andando]
for i in states:
i = pygame.transform.scale(i, sizenorm)
This wont work, but I can achieve the result using this:
self.quieto = pygame.transform.scale(self.quieto, sizenorm)
self.andando = pygame.transform.scale(self.andando, sizenorm)
The problem is that I have to make a lot of more states, and using that for loop would be shorter. However, it doesn't work like the lower example does. I don't know what's wrong with the loop.
You can create a list of the scaled objects and assign the elements of the list to the original attributes:
states = [self.quieto, self.andando]
states = [pygame.transform.scale(i, sizenorm) for i in states]
(self.quieto, self.andando) = states
This can even be written in a single line
(self.quieto, self.andando) = [pygame.transform.scale(i, sizenorm) for i in [self.quieto, self.andando]]
Alternatively, you can simply put the images in a list:
filenames = ["Migue/m_normal.png", "Migue/m_andando_normal.png"]
self.states = [pygame.transform.scale(pygame.image.load(n), sizenorm) for n in filenames]

Send matrix to python function from matlab

I have a matlab code that is going to use a PSO algorithm that is constructed in python, that as several parameters, knowing that one of those parameters is a 10x5 matrix, and is always giving me an error when i try to run the matlab code, so i put the code and the error that occurs next:
PS: I already tested the pso algorithm in python with same matrix, but when i use it in matlab, it doesn't work.
MATLAB code:
s = size(CurrentPop, 1);
velocity_matrix = [];
NewPop = [];
for gen = 1:gen_max
NewPop, velocity_matrix = py.pso_algorithm.pso(n_chr, n_par, CurrentPop, velocity_matrix, gen);
CurrentPop = EvaluateFirestation(NewPop, n_par, fuelmodels);
The error that appears that always occurs in the following line of the python function particles = particles_array[:, :n_par]:
Error using pso_algorithm>pso (line 46)
Python Error: TypeError: slice indices must be integers or None or have an index method
Python function 'pso' might not be able to accept at least one input argument at position 3. The function may require a specific data type that you can construct from the MATLAB array. For more information, see the documentation for Python function 'pso' and working with Python arrays.
Python function:
def pso(population, n_par, current_pop, velocity_matrix, generation):
# Initialization
# Population
particles_array = np.array(current_pop)
particles = particles_array[:, :n_par]
# Particle's best position
pbest_position = particles
# Fitness
# ULTIMA COLUNA DE CURRENT_POP
pbest_fitness = particles_array[:, n_par]
# Index of the best particle
gbest_index = np.argmin(pbest_fitness) # VAI BUSCAR O INDICE DO MENOR VALOR EM PBEST_FITNESS
# Global best particle position
gbest_position = pbest_position[gbest_index]
# Velocity (starting from 0 speed)
if generation == 1:
velocity = [[0.0 for j in range(n_par)] for i in range(population)]
else:
velocity = velocity_matrix
for n in range(population):
# Update the velocity of each particle
velocity[n] = update_velocity(particles[n], velocity[n], pbest_position[n], gbest_position, n_par)
# Move the particles to new position
particles[n] = update_position(particles[n], velocity[n])
particles = np.insert(particles, n_par, pbest_fitness, axis=1)
velocity = np.array(velocity)
# print(particles)
# print(velocity)
return particles, velocity

Creating an array of objects in Python for pygame

I create the objects
class Disk:
def __init__(self,number,colour,position,size):
self.size = size
self.colour = colour
self.number = number
self.position = position
def Render(self,screen):
pygame.draw.rect(screen,self.colour,(self.position,self.size))
I am trying to create an array of this object using user input (for right now I am just making my own number)
Colours are a seperate array that I've created (it works)
def drawDisk(screen,colours):
num = 5
for i in range (num):
disk[i] = Disk(i,colours[i*num],(0+(i*15),500-(i*50)),(400 -(i*30),50))
disk[i].Render(screen)
My program works except for when I try creating an array of disks and using those disks instead of hard coding each individual disk.
You haven't defined disk. You are trying to simultaneously create the list and the items in it and iterate over it, but haven't actually told Python what disk is supposed to be. Try:
def drawDisk(screen, colours):
disk = [Disk(i, colours[i], (0+(i*15), 500-(i*50)), (400 -(i*30), 50))
for i in range(len(colours))] # create and fill disk
# list comprehension, equivalent to:
# disk = []
# for i in range(len(colours)):
# disk.append(Disk(i, colours[i], ...))
for d in disk:
d.Render(screen) # use items in disk
return disk # for use elsewhere

Python for x in list basic question

I am trying to create a function which will load a whole lot of images and map them to appropriate names in PyGame. I'm not all that great with python and this really has me stuck. My current code is this:
tile1 = pygame.image.load("/one.bmp")
tile2 = pygame.image.load("/two.bmp")
tile3 = pygame.image.load("/three.bmp")
and it keeps going on for about 20 tiles. The thing is I just found out that I need a lot more and was wondering how I could do this using a for x in y loop. My basic idea was:
tile = ['/one.bmp', '/two.bmp', '/three.bmp']
tilelist = [1,2,3]
for tile in tile:
tilelist[x] = pygame.image.load(tile)
or something like that but I'm not quite there. I was also wondering if it could be done using dictionaries.
Any help would be appreciated, thanks :)
List comprehensions to the rescue.
tiles = ['/one.bmp', '/two.bmp', '/three.bmp']
tilelist = [pygame.img.load(tile) for tile in tiles]
As #isakkarlsson commented,
...or easier(?) tilelist = map(pygame.img.load, tiles)
To load the data
tile = ['/one.bmp', '/two.bmp', '/three.bmp']
imageMap = {}
for t in tile:
imageMap[t] = pygame.img.load(t)
Then you have all the data in a dictionary and can loop through the file names using imageMap.keys() or the index directly into the dictionary to get a particular image.

depth-first algorithm in python does not work

I have some project which I decide to do in Python. In brief: I have list of lists. Each of them also have lists, sometimes one-element, sometimes more. It looks like this:
rules=[
[[1],[2],[3,4,5],[4],[5],[7]]
[[1],[8],[3,7,8],[3],[45],[12]]
[[31],[12],[43,24,57],[47],[2],[43]]
]
The point is to compare values from numpy array to values from this rules (elements of rules table). We are comparing some [x][y] point to first element (e.g. 1 in first element), then, if it is true, value [x-1][j] from array with second from list and so on. Five first comparisons must be true to change value of [x][y] point. I've wrote sth like this (main function is SimulateLoop, order are switched because simulate2 function was written after second one):
def simulate2(self, i, j, w, rule):
data = Data(rule)
if w.world[i][j] in data.c:
if w.world[i-1][j] in data.n:
if w.world[i][j+1] in data.e:
if w.world[i+1][j] in data.s:
if w.world[i][j-1] in data.w:
w.world[i][j] = data.cc[0]
else: return
else: return
else: return
else: return
else: return
def SimulateLoop(self,w):
for z in range(w.steps):
for i in range(2,w.x-1):
for j in range(2,w.y-1):
for rule in w.rules:
self.simulate2(i,j,w,rule)
Data class:
class Data:
def __init__(self, rule):
self.c = rule[0]
self.n = rule[1]
self.e = rule[2]
self.s = rule[3]
self.w = rule[4]
self.cc = rule[5]
NumPy array is a object from World class. Rules is list as described above, parsed by function obtained from another program (GPL License).
To be honest it seems to work fine, but it does not. I was trying other possibilities, without luck. It is working, interpreter doesn't return any errors, but somehow values in array changing wrong. Rules are good because it was provided by program from which I've obtained parser for it (GPL license).
Maybe it will be helpful - it is Perrier's Loop, modified Langton's loop (artificial life).
Will be very thankful for any help!
)
I am not familiar with Perrier's Loop, but if you code something like famous "game life" you would have done simple mistake: store the next generation in the same array thus corrupting it.
Normally you store the next generation in temporary array and do copy/swap after the sweep, like in this sketch:
def do_step_in_game_life(world):
next_gen = zeros(world.shape) # <<< Tmp array here
Nx, Ny = world.shape
for i in range(1, Nx-1):
for j in range(1, Ny-1):
neighbours = sum(world[i-1:i+2, j-1:j+2]) - world[i,j]
if neighbours < 3:
next_gen[i,j] = 0
elif ...
world[:,:] = next_gen[:,:] # <<< Saving computed next generation

Categories