redraw speedup though use of generator
This commit is contained in:
parent
68ac036203
commit
f26a74d224
@ -2,11 +2,12 @@
|
|||||||
|
|
||||||
import random
|
import random
|
||||||
|
|
||||||
from cellular_automaton.cellular_automaton import CellularAutomaton
|
from cellular_automaton.cellular_automaton import CellularAutomaton, CellularAutomatonEvolver
|
||||||
from cellular_automaton.ca_rule import Rule
|
from cellular_automaton.ca_rule import Rule
|
||||||
from cellular_automaton.ca_neighborhood import MooreNeighborhood, EdgeRule
|
from cellular_automaton.ca_neighborhood import MooreNeighborhood, EdgeRule
|
||||||
from cellular_automaton.ca_display import PyGameFor2D
|
from cellular_automaton.ca_display import PyGameFor2D
|
||||||
from cellular_automaton.ca_cell_state import CellState
|
from cellular_automaton.ca_cell_state import CellState
|
||||||
|
from cellular_automaton.ca_grid import Grid
|
||||||
|
|
||||||
|
|
||||||
class TestRule(Rule):
|
class TestRule(Rule):
|
||||||
@ -43,6 +44,8 @@ class MyStatus(CellState):
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
random.seed(1000)
|
random.seed(1000)
|
||||||
rule = TestRule()
|
rule = TestRule()
|
||||||
ca = CellularAutomaton([400, 400], MooreNeighborhood(EdgeRule.FIRST_AND_LAST_CELL_OF_DIMENSION_ARE_NEIGHBORS), rule)
|
ca = CellularAutomaton(Grid([400, 400], MooreNeighborhood(EdgeRule.FIRST_AND_LAST_CELL_OF_DIMENSION_ARE_NEIGHBORS)),
|
||||||
ca_window = PyGameFor2D([1000, 800], ca, 5)
|
rule)
|
||||||
|
ca_evolver = CellularAutomatonEvolver(2)
|
||||||
|
ca_window = PyGameFor2D([1000, 800], ca, ca_evolver, 5)
|
||||||
ca_window.main_loop()
|
ca_window.main_loop()
|
||||||
|
@ -2,49 +2,45 @@ import pygame
|
|||||||
import time
|
import time
|
||||||
import operator
|
import operator
|
||||||
|
|
||||||
from cellular_automaton.cellular_automaton import CellularAutomaton
|
from cellular_automaton.cellular_automaton import CellularAutomaton, CellularAutomatonEvolver
|
||||||
|
|
||||||
|
|
||||||
|
class _DisplayInfo:
|
||||||
|
def __init__(self, grid_size, grid_pos, cell_size, screen):
|
||||||
|
self.grid_size = grid_size
|
||||||
|
self.grid_pos = grid_pos
|
||||||
|
self.cell_size = cell_size
|
||||||
|
self.screen = screen
|
||||||
|
|
||||||
|
|
||||||
class DisplayFor2D:
|
class DisplayFor2D:
|
||||||
def __init__(self, grid_rect: list, cellular_automaton: CellularAutomaton, screen):
|
def __init__(self, grid_rect: list, cellular_automaton: CellularAutomaton, screen):
|
||||||
self.grid_size = grid_rect[-2:]
|
|
||||||
self.grid_pos = grid_rect[:2]
|
|
||||||
self._cellular_automaton = cellular_automaton
|
self._cellular_automaton = cellular_automaton
|
||||||
self.screen = screen
|
cell_size = self._calculate_cell_display_size(grid_rect[-2:])
|
||||||
|
self._display_info = _DisplayInfo(grid_rect[-2:], grid_rect[:2], cell_size, screen)
|
||||||
self.cell_size = self._calculate_cell_display_size()
|
|
||||||
|
|
||||||
self._surfaces_to_update = []
|
|
||||||
|
|
||||||
def set_cellular_automaton(self, cellular_automaton):
|
def set_cellular_automaton(self, cellular_automaton):
|
||||||
self._cellular_automaton = cellular_automaton
|
self._cellular_automaton = cellular_automaton
|
||||||
|
|
||||||
def _redraw_cellular_automaton(self):
|
def _redraw_cellular_automaton(self):
|
||||||
for cell in self._cellular_automaton.grid.get_cells().values():
|
pygame.display.update(list(_cell_redraw_rectangles(self._cellular_automaton.grid.get_cells().values(),
|
||||||
self._redraw_cell(cell)
|
self._cellular_automaton.evolution_iteration_index,
|
||||||
pygame.display.update(self._surfaces_to_update)
|
self._display_info)))
|
||||||
self._surfaces_to_update = []
|
|
||||||
|
|
||||||
def _redraw_cell(self, cell):
|
def _calculate_cell_display_size(self, grid_size):
|
||||||
if cell.is_set_for_redraw:
|
|
||||||
cell_color = cell.state.get_state_draw_color(self._cellular_automaton.get_iteration_index())
|
|
||||||
surface_pos = self._calculate_cell_position(cell)
|
|
||||||
surface_pos = list(map(operator.add, surface_pos, self.grid_pos))
|
|
||||||
self._surfaces_to_update.append(self.screen.fill(cell_color, (surface_pos, self.cell_size)))
|
|
||||||
cell.is_set_for_redraw = False
|
|
||||||
|
|
||||||
def _calculate_cell_position(self, cell):
|
|
||||||
return list(map(operator.mul, self.cell_size, cell.coordinate))
|
|
||||||
|
|
||||||
def _calculate_cell_display_size(self):
|
|
||||||
grid_dimension = self._cellular_automaton.grid.get_dimension()
|
grid_dimension = self._cellular_automaton.grid.get_dimension()
|
||||||
return list(map(operator.truediv, self.grid_size, grid_dimension))
|
return list(map(operator.truediv, grid_size, grid_dimension))
|
||||||
|
|
||||||
|
|
||||||
class PyGameFor2D:
|
class PyGameFor2D:
|
||||||
def __init__(self, windows_size: list, cellular_automaton: CellularAutomaton, ca_iterations_per_draw):
|
def __init__(self,
|
||||||
|
windows_size: list,
|
||||||
|
cellular_automaton: CellularAutomaton,
|
||||||
|
cellular_automaton_evolver: CellularAutomatonEvolver,
|
||||||
|
ca_iterations_per_draw):
|
||||||
self._window_size = windows_size
|
self._window_size = windows_size
|
||||||
self._cellular_automaton = cellular_automaton
|
self._cellular_automaton = cellular_automaton
|
||||||
|
self._cellular_automaton_evolver = cellular_automaton_evolver
|
||||||
self._ca_steps_per_draw = ca_iterations_per_draw
|
self._ca_steps_per_draw = ca_iterations_per_draw
|
||||||
|
|
||||||
pygame.init()
|
pygame.init()
|
||||||
@ -69,7 +65,7 @@ class PyGameFor2D:
|
|||||||
|
|
||||||
while running:
|
while running:
|
||||||
time_ca_start = time.time()
|
time_ca_start = time.time()
|
||||||
self._cellular_automaton.evolve_x_times(self._ca_steps_per_draw)
|
self._cellular_automaton_evolver.evolve_x_times(self._cellular_automaton, self._ca_steps_per_draw)
|
||||||
time_ca_end = time.time()
|
time_ca_end = time.time()
|
||||||
self.ca_display._redraw_cellular_automaton()
|
self.ca_display._redraw_cellular_automaton()
|
||||||
time_ds_end = time.time()
|
time_ds_end = time.time()
|
||||||
@ -79,3 +75,16 @@ class PyGameFor2D:
|
|||||||
if event.type == pygame.QUIT:
|
if event.type == pygame.QUIT:
|
||||||
running = False
|
running = False
|
||||||
|
|
||||||
|
|
||||||
|
def _cell_redraw_rectangles(cells, evolution_index, display_info):
|
||||||
|
for cell in cells:
|
||||||
|
if cell.is_set_for_redraw:
|
||||||
|
cell_color = cell.state.get_state_draw_color(evolution_index)
|
||||||
|
cell_pos = _calculate_cell_position(display_info.cell_size, cell)
|
||||||
|
surface_pos = list(map(operator.add, cell_pos, display_info.grid_pos))
|
||||||
|
yield display_info.screen.fill(cell_color, (surface_pos, display_info.cell_size))
|
||||||
|
cell.is_set_for_redraw = False
|
||||||
|
|
||||||
|
|
||||||
|
def _calculate_cell_position(cell_size, cell):
|
||||||
|
return list(map(operator.mul, cell_size, cell.coordinate))
|
||||||
|
@ -6,11 +6,13 @@ class Grid:
|
|||||||
def __init__(self, dimension: list, neighborhood: Neighborhood):
|
def __init__(self, dimension: list, neighborhood: Neighborhood):
|
||||||
self._dimension = dimension
|
self._dimension = dimension
|
||||||
self._cells = {}
|
self._cells = {}
|
||||||
self._neighborhood = neighborhood
|
self._active_cells = {}
|
||||||
|
|
||||||
|
self._init_cells(neighborhood)
|
||||||
|
|
||||||
|
def _init_cells(self, neighborhood):
|
||||||
self._create_cells()
|
self._create_cells()
|
||||||
self._set_cell_neighbours()
|
self._set_cell_neighbours(neighborhood)
|
||||||
|
|
||||||
self._active_cells = self._cells.copy()
|
self._active_cells = self._cells.copy()
|
||||||
self._set_all_cells_active()
|
self._set_all_cells_active()
|
||||||
|
|
||||||
@ -68,10 +70,10 @@ class Grid:
|
|||||||
new_cod = coordinate + [cell_index]
|
new_cod = coordinate + [cell_index]
|
||||||
recursion_method(dimension_index + 1, new_cod)
|
recursion_method(dimension_index + 1, new_cod)
|
||||||
|
|
||||||
def _set_cell_neighbours(self):
|
def _set_cell_neighbours(self, neighborhood):
|
||||||
for cell in self._cells.values():
|
for cell in self._cells.values():
|
||||||
neighbours_coordinates = self._neighborhood.calculate_cell_neighbor_coordinates(cell.coordinate,
|
neighbours_coordinates = neighborhood.calculate_cell_neighbor_coordinates(cell.coordinate,
|
||||||
self._dimension)
|
self._dimension)
|
||||||
cell.neighbours = list(map(self._get_cell_by_coordinate, neighbours_coordinates))
|
cell.neighbours = list(map(self._get_cell_by_coordinate, neighbours_coordinates))
|
||||||
|
|
||||||
def _get_cell_by_coordinate(self, coordinate):
|
def _get_cell_by_coordinate(self, coordinate):
|
||||||
|
@ -1,61 +1,54 @@
|
|||||||
from cellular_automaton.ca_grid import Grid
|
from cellular_automaton.ca_grid import Grid
|
||||||
from cellular_automaton.ca_rule import Rule
|
from cellular_automaton.ca_rule import Rule
|
||||||
from cellular_automaton.ca_neighborhood import Neighborhood
|
|
||||||
|
|
||||||
|
|
||||||
class CellularAutomaton:
|
class CellularAutomaton:
|
||||||
def __init__(self, dimension: list, neighborhood: Neighborhood, evolution_rule: Rule=None):
|
def __init__(self, grid: Grid, evolution_rule: Rule):
|
||||||
self.grid = Grid(dimension, neighborhood)
|
self.grid = grid
|
||||||
self.evolution_rule = evolution_rule
|
self.evolution_rule = evolution_rule
|
||||||
self.iteration = 0
|
self.evolution_iteration_index = 0
|
||||||
self.test_number = 0
|
|
||||||
|
|
||||||
def set_rule(self, rule: Rule):
|
|
||||||
""" Set new evolution rule.
|
|
||||||
:param rule:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
self.evolution_rule = rule
|
|
||||||
|
|
||||||
def get_iteration_index(self):
|
class CellularAutomatonEvolver:
|
||||||
""" Get the count of evolution cycles done.
|
def __init__(self, process_count: int = 1):
|
||||||
:return: Evolution steps done.
|
self.__processes = process_count
|
||||||
"""
|
self.__cellular_automaton = None
|
||||||
return self.iteration
|
|
||||||
|
|
||||||
def evolve_x_times(self, evolutions: int):
|
def evolve_x_times(self, cellular_automaton: CellularAutomaton, evolution_steps: int):
|
||||||
""" Evolve all cells for x time steps.
|
""" Evolve all cells for x time steps.
|
||||||
:param evolutions: the count of evolutions done.
|
:param evolution_steps: the count of evolutions done.
|
||||||
:return: True if all cells are inactive
|
:return: True if all cells are inactive
|
||||||
"""
|
"""
|
||||||
for evo in range(evolutions):
|
for evo in range(evolution_steps):
|
||||||
finished = self.evolve()
|
finished = self.evolve(cellular_automaton)
|
||||||
if finished:
|
if finished:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def evolve(self):
|
def evolve(self, cellular_automaton: CellularAutomaton):
|
||||||
""" Evolves all active cells for one time step.
|
""" Evolves all active cells for one time step.
|
||||||
:return: True if all cells are inactive.
|
:return: True if all cells are inactive.
|
||||||
"""
|
"""
|
||||||
|
self.__cellular_automaton = cellular_automaton
|
||||||
if self._is_evolution_finished():
|
if self._is_evolution_finished():
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
self.iteration += 1
|
cellular_automaton.evolution_iteration_index += 1
|
||||||
self._evolve_all_active_cells()
|
self._evolve_all_active_cells()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def _is_evolution_finished(self):
|
||||||
|
return len(self.__cellular_automaton.grid.get_active_cell_names()) == 0
|
||||||
|
|
||||||
def _evolve_all_active_cells(self):
|
def _evolve_all_active_cells(self):
|
||||||
active_cells = self.grid.get_active_cells()
|
active_cells = self.__cellular_automaton.grid.get_active_cells()
|
||||||
self.grid.clear_active_cells()
|
self.__cellular_automaton.grid.clear_active_cells()
|
||||||
self._evolve_cells(active_cells.values())
|
self._evolve_cells(active_cells.values())
|
||||||
|
|
||||||
def _is_evolution_finished(self):
|
|
||||||
return len(self.grid.get_active_cell_names()) == 0
|
|
||||||
|
|
||||||
def _evolve_cells(self, cells: list):
|
def _evolve_cells(self, cells: list):
|
||||||
|
cellular_automaton = self.__cellular_automaton
|
||||||
for cell in cells:
|
for cell in cells:
|
||||||
active = self.evolution_rule.evolve_cell(cell, self.iteration)
|
active = cellular_automaton.evolution_rule.evolve_cell(cell, cellular_automaton.evolution_iteration_index)
|
||||||
|
|
||||||
if active:
|
if active:
|
||||||
self.grid.set_cells_active([cell] + cell.neighbours)
|
cellular_automaton.grid.set_cells_active([cell] + cell.neighbours)
|
||||||
|
Loading…
Reference in New Issue
Block a user