changed grid to factory

This commit is contained in:
Richard Feistenauer 2019-02-03 18:26:31 +01:00
parent 9c855c507a
commit 743d6f4548
4 changed files with 75 additions and 88 deletions

View File

@ -3,6 +3,9 @@
from cellular_automaton.ca_cell_state import CellState from cellular_automaton.ca_cell_state import CellState
from cellular_automaton.ca_rule import Rule from cellular_automaton.ca_rule import Rule
from cellular_automaton.cellular_automaton import CellularAutomaton, CellularAutomatonProcessor
from cellular_automaton.ca_factory import Factory
class TestRule(Rule): class TestRule(Rule):
@staticmethod @staticmethod
@ -31,23 +34,24 @@ class MyState(CellState):
return [red, 0, 0] return [red, 0, 0]
def make_cellular_automaton(dimension, neighborhood, rule, state_class):
ca_factory = Factory()
cells = ca_factory.make_cellular_automaton(dimension=dimension, neighborhood=neighborhood, state_class=state_class)
return CellularAutomaton(cells, dimension, rule)
if __name__ == "__main__": if __name__ == "__main__":
import random import random
from multiprocessing import freeze_support from multiprocessing import freeze_support
from cellular_automaton.cellular_automaton import CellularAutomaton, CellularAutomatonProcessor
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_grid import Grid
freeze_support() freeze_support()
random.seed(1000) random.seed(1000)
dimension = [100, 100] # best is 400/400 with 0,2 ca speed and 0,09 redraw
rule = TestRule() neighborhood = MooreNeighborhood(EdgeRule.FIRST_AND_LAST_CELL_OF_DIMENSION_ARE_NEIGHBORS)
grid = Grid(dimension=dimension, # best is 400/400 with 0,2 ca speed and 0,09 redraw ca = make_cellular_automaton(dimension=[100, 100], neighborhood=neighborhood, rule=TestRule(), state_class=MyState)
neighborhood=MooreNeighborhood(EdgeRule.FIRST_AND_LAST_CELL_OF_DIMENSION_ARE_NEIGHBORS),
state_class=MyState)
ca = CellularAutomaton(tuple(grid.get_cells().values()), dimension, rule)
ca_window = PyGameFor2D(window_size=[1000, 800], cellular_automaton=ca) ca_window = PyGameFor2D(window_size=[1000, 800], cellular_automaton=ca)
ca_processor = CellularAutomatonProcessor(process_count=4, cellular_automaton=ca) ca_processor = CellularAutomatonProcessor(process_count=4, cellular_automaton=ca)
ca_window.main_loop(cellular_automaton_processor=ca_processor, ca_window.main_loop(cellular_automaton_processor=ca_processor,

View File

@ -77,7 +77,7 @@ class PyGameFor2D:
size = asizeof.asizeof(self._cellular_automaton) size = asizeof.asizeof(self._cellular_automaton)
cProfile.runctx("cap.evolve_x_times(10)", None, locals(), "performance_test") cProfile.runctx("cap.evolve_x_times(10)", None, locals(), "performance_test")
print("PERFORMANCE") print("PERFORMANCE")
p = pstats.Stats('performance_test2') p = pstats.Stats('performance_test')
p.strip_dirs() p.strip_dirs()
# sort by cumulative time in a function # sort by cumulative time in a function
p.sort_stats('cumulative').print_stats(10) p.sort_stats('cumulative').print_stats(10)

View File

@ -0,0 +1,61 @@
from cellular_automaton.ca_cell import Cell, CellState
from cellular_automaton.ca_neighborhood import Neighborhood
from typing import Type
class Factory:
def __init__(self):
self._dimension = None
self._state_class = None
self._cells = {}
def make_cellular_automaton(self,
dimension,
neighborhood: Type[Neighborhood],
state_class: Type[CellState]):
self._dimension = dimension
self._state_class = state_class
self.__create_cells()
self.__set_cell_neighbours(self._cells, neighborhood)
return tuple(self._cells.values())
def __create_cells(self, dimension_index=0, coordinate=None):
""" Recursively steps down the dimensions to create cells in n dimensions and adds them to a dict.
:param dimension_index: The index indicating which dimension is currently traversed.
:param coordinate: The coordinate generated so far.
(each recursion adds one dimension to the coordinate.
"""
coordinate = _instantiate_coordinate_if_necessary(coordinate)
try:
self.__recursive_step_down_dimensions(coordinate, dimension_index)
except IndexError:
coordinate_string = _join_coordinate(coordinate)
self._cells[coordinate_string] = Cell(self._state_class, coordinate)
def __recursive_step_down_dimensions(self, coordinate, dimension_index):
""" For the range of the current dimension, recalls the recursion method.
:param coordinate: The coordinate so far.
:param dimension_index: The current dimension lvl.
"""
for cell_index in range(self._dimension[dimension_index]):
new_cod = coordinate + [cell_index]
self.__create_cells(dimension_index + 1, new_cod)
def __set_cell_neighbours(self, cells, neighborhood):
for cell in cells.values():
n_coordinates = neighborhood.calculate_cell_neighbor_coordinates(cell.get_coordinate(),
self._dimension)
cell.set_neighbours([cells[_join_coordinate(coordinate)].get_state() for coordinate in n_coordinates])
def _instantiate_coordinate_if_necessary(coordinate):
if coordinate is None:
coordinate = []
return coordinate
def _join_coordinate(coordinate):
return '-'.join(str(x) for x in coordinate)

View File

@ -1,78 +0,0 @@
from cellular_automaton.ca_cell import Cell
from cellular_automaton.ca_neighborhood import Neighborhood
class Grid:
def __init__(self, dimension: list, neighborhood: Neighborhood, state_class):
self._dimension = dimension
self._cells = {}
self._active_cells = {}
self._state_class = state_class
self._init_cells(neighborhood)
def _init_cells(self, neighborhood):
self._create_cells()
self._set_cell_neighbours(neighborhood)
self._active_cells = self._cells.copy()
self._set_all_cells_active()
def _create_cells(self, dimension_index=0, coordinate=None):
""" Recursively steps down the dimensions to create cells in n dimensions and adds them to a dict.
:param dimension_index: The index indicating which dimension is currently traversed.
:param coordinate: The coordinate generated so far.
(each recursion adds one dimension to the coordinate.
"""
coordinate = _instantiate_coordinate_if_necessary(coordinate)
try:
self._recursive_step_down_dimensions(coordinate, dimension_index, self._create_cells)
except IndexError:
coordinate_string = _join_coordinate(coordinate)
self._cells[coordinate_string] = Cell(self._state_class, coordinate)
def _recursive_step_down_dimensions(self, coordinate, dimension_index, recursion_method):
""" For the range of the current dimension, recalls the recursion method.
:param coordinate: The coordinate so far.
:param dimension_index: The current dimension lvl.
:param recursion_method: The method to call for recursion.
"""
for cell_index in range(self._dimension[dimension_index]):
new_cod = coordinate + [cell_index]
recursion_method(dimension_index + 1, new_cod)
def _set_cell_neighbours(self, neighborhood):
for cell in self._cells.values():
neighbours_coordinates = neighborhood.calculate_cell_neighbor_coordinates(cell.get_coordinate(),
self._dimension)
cell.set_neighbours(list(map(self._get_cell_state_by_coordinate, neighbours_coordinates)))
def _get_cell_state_by_coordinate(self, coordinate):
return self._cells[_join_coordinate(coordinate)].get_state()
def _set_all_cells_active(self):
for cell_key, cell in self._cells.items():
self._active_cells[cell_key] = cell
def get_active_cell_names(self):
return list(self._active_cells.keys())
def get_active_cells(self):
return self._active_cells
def get_cells(self):
return self._cells
def get_dimension(self):
return self._dimension
def _instantiate_coordinate_if_necessary(coordinate):
if coordinate is None:
coordinate = []
return coordinate
def _join_coordinate(coordinate):
return '-'.join(str(x) for x in coordinate)