added multi processing, extremly slow though
This commit is contained in:
parent
ac2a6216b3
commit
a8d17f6fe9
@ -2,7 +2,7 @@
|
||||
|
||||
import random
|
||||
|
||||
from cellular_automaton.cellular_automaton import CellularAutomaton, CellularAutomatonEvolver
|
||||
from cellular_automaton.cellular_automaton import CellularAutomaton, CellularAutomatonProcessor
|
||||
from cellular_automaton.ca_rule import Rule
|
||||
from cellular_automaton.ca_neighborhood import MooreNeighborhood, EdgeRule
|
||||
from cellular_automaton.ca_display import PyGameFor2D
|
||||
@ -12,22 +12,32 @@ from cellular_automaton.ca_grid import Grid
|
||||
|
||||
class TestRule(Rule):
|
||||
def evolve_cell(self, cell, iteration_index):
|
||||
active = False
|
||||
neighbors = cell.neighbours
|
||||
if cell.state is None:
|
||||
rand = random.randrange(0, 101, 1)
|
||||
if rand <= 99:
|
||||
cell.state = MyStatus(0)
|
||||
else:
|
||||
cell.state = MyStatus(1)
|
||||
cell.is_set_for_redraw = True
|
||||
active = True
|
||||
elif len(neighbors) == 8:
|
||||
left_neighbour_state = neighbors[0].state.get_status_of_iteration(iteration_index - 1)
|
||||
return self._init_state(cell)
|
||||
else:
|
||||
return self._evolve_state(cell, iteration_index)
|
||||
|
||||
@staticmethod
|
||||
def _evolve_state(cell, iteration_index):
|
||||
try:
|
||||
left_neighbour_state = cell.neighbours[0].state.get_status_of_iteration(iteration_index - 1)
|
||||
active = cell.state.set_status_of_iteration(left_neighbour_state, iteration_index)
|
||||
if active:
|
||||
cell.is_set_for_redraw = True
|
||||
return active
|
||||
return active
|
||||
except IndexError:
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def _init_state(cell):
|
||||
rand = random.randrange(0, 101, 1)
|
||||
if rand <= 99:
|
||||
cell.state = MyStatus(0)
|
||||
return False
|
||||
else:
|
||||
cell.state = MyStatus(1)
|
||||
cell.is_set_for_redraw = True
|
||||
return True
|
||||
|
||||
|
||||
class MyStatus(CellState):
|
||||
@ -44,8 +54,10 @@ class MyStatus(CellState):
|
||||
if __name__ == "__main__":
|
||||
random.seed(1000)
|
||||
rule = TestRule()
|
||||
ca = CellularAutomaton(Grid([400, 400], MooreNeighborhood(EdgeRule.FIRST_AND_LAST_CELL_OF_DIMENSION_ARE_NEIGHBORS)),
|
||||
rule)
|
||||
ca_evolver = CellularAutomatonEvolver(2)
|
||||
ca_window = PyGameFor2D([1000, 800], ca, ca_evolver, 5)
|
||||
ca_window.main_loop()
|
||||
grid = Grid(dimension=[400, 400],
|
||||
neighborhood=MooreNeighborhood(EdgeRule.FIRST_AND_LAST_CELL_OF_DIMENSION_ARE_NEIGHBORS))
|
||||
ca = CellularAutomaton(grid, rule)
|
||||
ca_window = PyGameFor2D(window_size=[1000, 800], cellular_automaton=ca)
|
||||
ca_processor = CellularAutomatonProcessor(process_count=8)
|
||||
ca_window.main_loop(cellular_automaton_processor=ca_processor,
|
||||
ca_iterations_per_draw=5)
|
||||
|
@ -30,3 +30,6 @@ class CellState:
|
||||
|
||||
def get_state_draw_color(self, iteration):
|
||||
raise NotImplementedError
|
||||
|
||||
def __str__(self):
|
||||
return str(self._state_slots)
|
||||
|
@ -2,7 +2,7 @@ import pygame
|
||||
import time
|
||||
import operator
|
||||
|
||||
from cellular_automaton.cellular_automaton import CellularAutomaton, CellularAutomatonEvolver
|
||||
from cellular_automaton.cellular_automaton import CellularAutomaton, CellularAutomatonProcessor
|
||||
|
||||
|
||||
class _DisplayInfo:
|
||||
@ -33,22 +33,16 @@ class DisplayFor2D:
|
||||
|
||||
|
||||
class PyGameFor2D:
|
||||
def __init__(self,
|
||||
windows_size: list,
|
||||
cellular_automaton: CellularAutomaton,
|
||||
cellular_automaton_evolver: CellularAutomatonEvolver,
|
||||
ca_iterations_per_draw):
|
||||
self._window_size = windows_size
|
||||
def __init__(self, window_size: list, cellular_automaton: CellularAutomaton):
|
||||
self._window_size = window_size
|
||||
self._cellular_automaton = cellular_automaton
|
||||
self._cellular_automaton_evolver = cellular_automaton_evolver
|
||||
self._ca_steps_per_draw = ca_iterations_per_draw
|
||||
|
||||
pygame.init()
|
||||
pygame.display.set_caption("Cellular Automaton")
|
||||
self._screen = pygame.display.set_mode(self._window_size)
|
||||
self._font = pygame.font.SysFont("monospace", 15)
|
||||
|
||||
self.ca_display = DisplayFor2D([0, 30, windows_size[0], windows_size[1]-30], cellular_automaton, self._screen)
|
||||
self.ca_display = DisplayFor2D([0, 30, window_size[0], window_size[1] - 30], cellular_automaton, self._screen)
|
||||
|
||||
def _print_process_duration(self, time_ca_end, time_ca_start, time_ds_end):
|
||||
self._screen.fill([0, 0, 0], ((0, 0), (self._window_size[0], 30)))
|
||||
@ -60,12 +54,12 @@ class PyGameFor2D:
|
||||
update_rect = self._screen.blit(label, pos)
|
||||
pygame.display.update(update_rect)
|
||||
|
||||
def main_loop(self):
|
||||
def main_loop(self, cellular_automaton_processor: CellularAutomatonProcessor, ca_iterations_per_draw):
|
||||
running = True
|
||||
|
||||
while running:
|
||||
time_ca_start = time.time()
|
||||
self._cellular_automaton_evolver.evolve_x_times(self._cellular_automaton, self._ca_steps_per_draw)
|
||||
cellular_automaton_processor.evolve_x_times(self._cellular_automaton, ca_iterations_per_draw)
|
||||
time_ca_end = time.time()
|
||||
self.ca_display._redraw_cellular_automaton()
|
||||
time_ds_end = time.time()
|
||||
|
@ -1,5 +1,9 @@
|
||||
from cellular_automaton.ca_grid import Grid
|
||||
from cellular_automaton.ca_rule import Rule
|
||||
from cellular_automaton.ca_cell_state import CellState
|
||||
|
||||
from multiprocessing import Process, Pipe, Array, Value
|
||||
import multiprocessing
|
||||
|
||||
|
||||
class CellularAutomaton:
|
||||
@ -9,14 +13,22 @@ class CellularAutomaton:
|
||||
self.evolution_iteration_index = 0
|
||||
|
||||
|
||||
class CellularAutomatonEvolver:
|
||||
class _EvolutionProcess:
|
||||
def __init__(self, process: Process, pipe: Pipe):
|
||||
self.process = process
|
||||
self.pipe = pipe
|
||||
self.cell = None
|
||||
|
||||
|
||||
class CellularAutomatonProcessor:
|
||||
def __init__(self, process_count: int = 1):
|
||||
self.__processes = process_count
|
||||
self._processes = list(_create_processes(process_count))
|
||||
self.__cellular_automaton = None
|
||||
|
||||
def evolve_x_times(self, cellular_automaton: CellularAutomaton, evolution_steps: int):
|
||||
""" Evolve all cells for x time steps.
|
||||
:param evolution_steps: the count of evolutions done.
|
||||
:param cellular_automaton: The cellular automaton to evolve.
|
||||
:param evolution_steps: The count of evolutions done.
|
||||
:return: True if all cells are inactive
|
||||
"""
|
||||
for evo in range(evolution_steps):
|
||||
@ -27,10 +39,12 @@ class CellularAutomatonEvolver:
|
||||
|
||||
def evolve(self, cellular_automaton: CellularAutomaton):
|
||||
""" Evolves all active cells for one time step.
|
||||
:param cellular_automaton: The cellular automaton to evolve.
|
||||
:return: True if all cells are inactive.
|
||||
"""
|
||||
self.__cellular_automaton = cellular_automaton
|
||||
if self._is_evolution_finished():
|
||||
print("finished")
|
||||
return True
|
||||
else:
|
||||
cellular_automaton.evolution_iteration_index += 1
|
||||
@ -44,11 +58,115 @@ class CellularAutomatonEvolver:
|
||||
active_cells = self.__cellular_automaton.grid.get_active_cells()
|
||||
self.__cellular_automaton.grid.clear_active_cells()
|
||||
self._evolve_cells(active_cells.values())
|
||||
print(len(self.__cellular_automaton.grid.get_active_cells()))
|
||||
|
||||
def _evolve_cells(self, cells: list):
|
||||
def _evolve_cells(self, cells):
|
||||
cellular_automaton = self.__cellular_automaton
|
||||
for cell in cells:
|
||||
active = cellular_automaton.evolution_rule.evolve_cell(cell, cellular_automaton.evolution_iteration_index)
|
||||
processes = self._processes
|
||||
process_count = len(processes)
|
||||
for i, cell in enumerate(cells):
|
||||
evolution_process = processes[i % process_count]
|
||||
if evolution_process.cell:
|
||||
response = evolution_process.pipe.recv()
|
||||
evolved_cell = evolution_process.cell
|
||||
evolved_cell.state = response[0]
|
||||
evolved_cell.is_set_for_redraw |= response[1]
|
||||
if evolved_cell.is_set_for_redraw:
|
||||
cellular_automaton.grid.set_cells_active([evolved_cell] + evolved_cell.neighbours)
|
||||
evolution_process.cell = None
|
||||
|
||||
if active:
|
||||
cell_info = self.read_cell_info(cell, cellular_automaton.evolution_iteration_index)
|
||||
evolution_process.pipe.send(cell_info)
|
||||
evolution_process.cell = cell
|
||||
|
||||
for evolution_process in processes:
|
||||
response = evolution_process.pipe.recv()
|
||||
cell = evolution_process.cell
|
||||
cell.state = response[0]
|
||||
cell.is_set_for_redraw |= response[1]
|
||||
if cell.is_set_for_redraw:
|
||||
cellular_automaton.grid.set_cells_active([cell] + cell.neighbours)
|
||||
evolution_process.cell = None
|
||||
|
||||
# if cellular_automaton.evolution_rule.evolve_cell(cell.state, cellular_automaton.evolution_iteration_index):
|
||||
# cellular_automaton.grid.set_cells_active([cell] + cell.neighbours)
|
||||
|
||||
@staticmethod
|
||||
def read_cell_info(cell, iteration):
|
||||
coordinate = cell.coordinate
|
||||
return [coordinate, cell.state, [n.state for n in cell.neighbours], iteration]
|
||||
|
||||
# if cell.state is not None:
|
||||
# cell_state = cell.state.get_status_of_iteration(iteration - 1)
|
||||
# else:
|
||||
# cell_state = None
|
||||
#
|
||||
# neighbor_states = []
|
||||
# for neighbor in cell.neighbours:
|
||||
# if neighbor.state is not None:
|
||||
# neighbor_state = neighbor.state.get_status_of_iteration(iteration - 1)
|
||||
# else:
|
||||
# neighbor_state = None
|
||||
# neighbor_states.append(neighbor_state)
|
||||
#
|
||||
# return [coordinate, cell_state, neighbor_states]
|
||||
|
||||
|
||||
def _create_processes(count):
|
||||
for i in range(count):
|
||||
parent_pipe_connection, child_pipe_connection = Pipe()
|
||||
p = Process(target=process_routine, args=(child_pipe_connection, ))
|
||||
p.start()
|
||||
yield _EvolutionProcess(p, parent_pipe_connection)
|
||||
|
||||
|
||||
def process_routine(pipe_conn: Pipe):
|
||||
while True:
|
||||
info = pipe_conn.recv()
|
||||
pipe_conn.send(evolve_cell(*info))
|
||||
|
||||
|
||||
def evolve_cell(coordinate, cell_state, neighbor_states, index):
|
||||
if cell_state is None:
|
||||
return _init_state()
|
||||
else:
|
||||
new_state = _evolve_state(cell_state, neighbor_states, index)
|
||||
if new_state is None:
|
||||
print(",".join([str(x) for x in neighbor_states]))
|
||||
return [cell_state, False]
|
||||
else:
|
||||
changed = cell_state.set_status_of_iteration(new_state, index)
|
||||
return [cell_state, changed]
|
||||
|
||||
|
||||
def _evolve_state(cell_state, neighbor_states, index):
|
||||
try:
|
||||
left_neighbour_state = neighbor_states[0].get_status_of_iteration(index - 1)
|
||||
return left_neighbour_state
|
||||
except (IndexError, AttributeError):
|
||||
return None
|
||||
|
||||
|
||||
import random
|
||||
|
||||
|
||||
def _init_state():
|
||||
rand = random.randrange(0, 101, 1)
|
||||
if rand <= 99:
|
||||
return [MyStatus(0), False]
|
||||
else:
|
||||
return [MyStatus(1), True]
|
||||
|
||||
|
||||
class MyStatus(CellState):
|
||||
def __init__(self, initial_state):
|
||||
super().__init__(initial_state)
|
||||
|
||||
def get_state_draw_color(self, iteration):
|
||||
red = 0
|
||||
if self._state_slots[iteration % 2][0]:
|
||||
red = 255
|
||||
return [red, 0, 0]
|
||||
|
||||
def __str__(self):
|
||||
return super().__str__()
|
||||
|
Loading…
Reference in New Issue
Block a user