removed coordinate string from cells dict

This commit is contained in:
Richard Feistenauer 2019-02-15 20:02:57 +01:00
parent be5546c833
commit 4c44cc1002
7 changed files with 35 additions and 40 deletions

Binary file not shown.

View File

@ -3,22 +3,21 @@ from typing import Type
class Cell: class Cell:
def __init__(self, state_class: Type[CellState], coordinate): def __init__(self, state_class: Type[CellState]):
self.coordinate = coordinate
self.state = state_class() self.state = state_class()
self.neighbours = [] self.neighbours = []
@staticmethod @staticmethod
def evolve_if_ready(cell, rule, iteration): def evolve_if_ready(cell, rule, iteration):
if cell[0].is_active(iteration): if cell.state.is_active(iteration):
new_state = rule(cell[0].get_state_of_last_iteration(iteration), new_state = rule(cell.state.get_state_of_last_iteration(iteration),
[n.get_state_of_last_iteration(iteration) for n in cell[1]]) [n.get_state_of_last_iteration(iteration) for n in cell.neighbours])
Cell.set_new_state_and_activate(cell, new_state, iteration) Cell.set_new_state_and_activate(cell, new_state, iteration)
@staticmethod @staticmethod
def set_new_state_and_activate(cell, new_state: CellState, iteration): def set_new_state_and_activate(cell, new_state: CellState, iteration):
changed = cell[0].set_state_of_iteration(new_state, iteration) changed = cell.state.set_state_of_iteration(new_state, iteration)
if changed: if changed:
cell[0].set_active_for_next_iteration(iteration) cell.state.set_active_for_next_iteration(iteration)
for n in cell[1]: for n in cell.neighbours:
n.set_active_for_next_iteration(iteration) n.set_active_for_next_iteration(iteration)

View File

@ -29,10 +29,10 @@ class DisplayFor2D:
pygame.display.update(update_rects) pygame.display.update(update_rects)
def _cell_redraw_rectangles(self): def _cell_redraw_rectangles(self):
for cell in self._cellular_automaton.cells: for coordinate, cell in self._cellular_automaton.cells.items():
if cell.state.is_set_for_redraw(): if cell.state.is_set_for_redraw():
cell_color = cell.state.get_state_draw_color(self._cellular_automaton.evolution_iteration_index) cell_color = cell.state.get_state_draw_color(self._cellular_automaton.evolution_iteration_index)
cell_pos = _calculate_cell_position(self._display_info.cell_size, cell) cell_pos = _calculate_cell_position(self._display_info.cell_size, coordinate)
surface_pos = list(map(operator.add, cell_pos, self._display_info.grid_pos)) surface_pos = list(map(operator.add, cell_pos, self._display_info.grid_pos))
yield self._display_info.screen.fill(cell_color, (surface_pos, self._display_info.cell_size)) yield self._display_info.screen.fill(cell_color, (surface_pos, self._display_info.cell_size))
cell.state.was_redrawn() cell.state.was_redrawn()
@ -97,5 +97,5 @@ class PyGameFor2D:
print("SIZE: " + "{0:.4f}".format(size / (1024 * 1024)) + "MB") print("SIZE: " + "{0:.4f}".format(size / (1024 * 1024)) + "MB")
def _calculate_cell_position(cell_size, cell): def _calculate_cell_position(cell_size, coordinate):
return list(map(operator.mul, cell_size, cell.coordinate)) return list(map(operator.mul, cell_size, coordinate))

View File

@ -12,23 +12,18 @@ class CAFactory:
cells = CAFactory._make_cells(dimension, state_class) cells = CAFactory._make_cells(dimension, state_class)
CAFactory._apply_neighbourhood_to_cells(cells, neighborhood, dimension) CAFactory._apply_neighbourhood_to_cells(cells, neighborhood, dimension)
return tuple(cells.values()) return cells
@staticmethod @staticmethod
def _make_cells(dimension, state_class): def _make_cells(dimension, state_class):
cells = {} cells = {}
for c in itertools.product(*[range(d) for d in dimension]): for c in itertools.product(*[range(d) for d in dimension]):
coordinate_string = _join_coordinate(c) cells[tuple(c)] = Cell(state_class)
cells[coordinate_string] = Cell(state_class, c)
return cells return cells
@staticmethod @staticmethod
def _apply_neighbourhood_to_cells(cells, neighborhood, dimension): def _apply_neighbourhood_to_cells(cells, neighborhood, dimension):
for cell in cells.values(): for coordinate, cell in cells.items():
n_coordinates = neighborhood.calculate_cell_neighbor_coordinates(cell.coordinate, dimension) n_coordinates = neighborhood.calculate_cell_neighbor_coordinates(coordinate, dimension)
cell.neighbours = [cells[_join_coordinate(coordinate)].state for coordinate in n_coordinates] cell.neighbours = [cells[tuple(nc)].state for nc in n_coordinates]
def _join_coordinate(coordinate):
return '-'.join(str(x) for x in coordinate)

View File

@ -25,7 +25,7 @@ class CellularAutomatonProcessor:
self._ca.evolution_iteration_index += 1 self._ca.evolution_iteration_index += 1
i = self._ca.evolution_iteration_index i = self._ca.evolution_iteration_index
r = self._ca.evolution_rule.evolve_cell r = self._ca.evolution_rule.evolve_cell
list(map(lambda c: Cell.evolve_if_ready((c.state, c.neighbours), r, i), self._ca.cells)) list(map(lambda c: Cell.evolve_if_ready((c.state, c.neighbours), r, i), tuple(self._ca.cells.items())))
# print(sum(1 for c in self._ca.cells if c.state.is_set_for_redraw())) # print(sum(1 for c in self._ca.cells if c.state.is_set_for_redraw()))
@ -33,25 +33,25 @@ class CellularAutomatonMultiProcessor(CellularAutomatonProcessor):
def __init__(self, cellular_automaton, process_count: int = 2): def __init__(self, cellular_automaton, process_count: int = 2):
if process_count < 1: if process_count < 1:
raise ValueError raise ValueError
super().__init__(cellular_automaton) super().__init__(cellular_automaton)
self.ca = cellular_automaton
cells = {i: (c.state, c.neighbours) for i, c in enumerate(self.ca.cells)} self.evolve_range = range(len(self._ca.cells))
self.evolve_range = range(len(self.ca.cells))
self.evolution_iteration_index = multiprocessing.RawValue(c_int, -1) self.evolution_iteration_index = multiprocessing.RawValue(c_int, -1)
self.pool = multiprocessing.Pool(processes=process_count, self.pool = multiprocessing.Pool(processes=process_count,
initializer=_init_process, initializer=_init_process,
initargs=(cells, initargs=(tuple(self._ca.cells.values()),
self.ca.evolution_rule, self._ca.evolution_rule,
self.evolution_iteration_index)) self.evolution_iteration_index))
self._evolve_method = self.pool.map self._evolve_method = self.pool.map
for cell in self.ca.cells: for cell in self._ca.cells.values():
del cell.neighbours del cell.neighbours
def evolve(self): def evolve(self):
self.ca.evolution_iteration_index += 1 self._ca.evolution_iteration_index += 1
self.evolution_iteration_index.value = self.ca.evolution_iteration_index self.evolution_iteration_index.value = self._ca.evolution_iteration_index
self.pool.map(_process_routine, self.evolve_range) self.pool.map(_process_routine, self.evolve_range)

View File

@ -12,14 +12,14 @@ class TestState(CellState):
class TestCellState(unittest.TestCase): class TestCellState(unittest.TestCase):
def setUp(self): def setUp(self):
self.cell = [TestState(), []] self.cell = Cell(TestState)
self.neighbours = [TestState() for x in range(5)] self.neighbours = [TestState() for x in range(5)]
for neighbour in self.neighbours: for neighbour in self.neighbours:
neighbour.set_state_of_iteration((0, ), 0) neighbour.set_state_of_iteration((0, ), 0)
self.cell[1] = self.neighbours self.cell.neighbours = self.neighbours
def cell_and_neighbours_active(self, iteration): def cell_and_neighbours_active(self, iteration):
self.neighbours.append(self.cell[0]) self.neighbours.append(self.cell.state)
all_active = True all_active = True
for state in self.neighbours: for state in self.neighbours:
if not state.is_active(iteration): if not state.is_active(iteration):

View File

@ -28,31 +28,32 @@ class TestCAFactory(unittest.TestCase):
with mock.patch.object(CAFactory, '_make_cells', return_value={1: True}): with mock.patch.object(CAFactory, '_make_cells', return_value={1: True}):
with mock.patch.object(CAFactory, '_apply_neighbourhood_to_cells'): with mock.patch.object(CAFactory, '_apply_neighbourhood_to_cells'):
cells = CAFactory.make_cellular_automaton([10], Neighborhood, CellState) cells = CAFactory.make_cellular_automaton([10], Neighborhood, CellState)
self.assertEqual(cells, (True, )) self.assertEqual(tuple(cells.values()), (True, ))
def test_1dimension_coordinates(self): def test_1dimension_coordinates(self):
fac = TestFac() fac = TestFac()
c = fac.make_cells([3], CellState) c = fac.make_cells([3], CellState)
self.assertEqual(list(c.keys()), ['0', '1', '2']) self.assertEqual(list(c.keys()), [(0,), (1,), (2,)])
def test_2dimension_coordinates(self): def test_2dimension_coordinates(self):
fac = TestFac() fac = TestFac()
c = fac.make_cells([2, 2], CellState) c = fac.make_cells([2, 2], CellState)
self.assertEqual(list(c.keys()), ['0-0', '0-1', '1-0', '1-1']) self.assertEqual(list(c.keys()), [(0, 0), (0, 1), (1, 0), (1, 1)])
def test_3dimension_coordinates(self): def test_3dimension_coordinates(self):
fac = TestFac() fac = TestFac()
c = fac.make_cells([2, 2, 2], CellState) c = fac.make_cells([2, 2, 2], CellState)
self.assertEqual(list(c.keys()), ['0-0-0', '0-0-1', '0-1-0', '0-1-1', '1-0-0', '1-0-1', '1-1-0', '1-1-1']) self.assertEqual(list(c.keys()), [(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1),
(1, 0, 0), (1, 0, 1), (1, 1, 0), (1, 1, 1)])
def test_apply_neighbourhood(self): def test_apply_neighbourhood(self):
fac = TestFac() fac = TestFac()
cells = fac.make_cells([3, 3], CellState) cells = fac.make_cells([3, 3], CellState)
fac.apply_neighbourhood(cells, MooreNeighborhood(EdgeRule.IGNORE_EDGE_CELLS), [3, 3]) fac.apply_neighbourhood(cells, MooreNeighborhood(EdgeRule.IGNORE_EDGE_CELLS), [3, 3])
neighbours = self.__create_neighbour_list_of_cell('1-1', cells) neighbours = self.__create_neighbour_list_of_cell((1, 1), cells)
self.assertEqual(set(neighbours), set(cells['1-1'].neighbours)) self.assertEqual(set(neighbours), set(cells[(1, 1)].neighbours))
@staticmethod @staticmethod
def __create_neighbour_list_of_cell(cell_id, cells): def __create_neighbour_list_of_cell(cell_id, cells):