neuropercolation/src/cellular_automaton/cellular_automaton.py

82 lines
2.9 KiB
Python
Raw Normal View History

import multiprocessing
2018-12-01 14:14:22 +00:00
import time
2018-12-01 19:37:18 +00:00
from cellular_automaton.ca_grid import Grid
from cellular_automaton.ca_rule import Rule
2018-12-02 16:45:08 +00:00
from cellular_automaton.ca_neighborhood import Neighborhood
2018-12-01 14:14:22 +00:00
class CellularAutomaton:
2018-12-02 16:45:08 +00:00
def __init__(self, dimension: list, neighborhood: Neighborhood, rule_: Rule=None, thread_count: int=4):
self.grid = Grid(dimension, neighborhood)
self.rule = rule_
2018-12-02 16:45:08 +00:00
self._thread_count = thread_count
self.iteration = 0
self.test_number = 0
2018-12-01 14:14:22 +00:00
2018-12-01 19:37:18 +00:00
def set_rule(self, rule: Rule):
self.rule = rule
2018-12-01 19:37:18 +00:00
def set_thread_count(self, thread_count: int):
self._thread_count = thread_count
2018-12-02 16:45:08 +00:00
def get_iteration_index(self):
return self.iteration
2018-12-02 16:45:08 +00:00
2018-12-01 19:37:18 +00:00
def evolve(self):
""" Evolves all active cells for one time step.
:return: True if all cells are inactive.
"""
2018-12-02 16:45:08 +00:00
if self._all_cells_are_inactive():
return True
else:
self.iteration += 1
self._start_multi_process_cell_evolution()
2018-12-02 16:45:08 +00:00
return False
def _start_multi_process_cell_evolution(self):
""" Evolves the cells in separate threads """
lists_of_cell_names = self._create_list_of_cell_names_lists_for_all_threads()
2018-12-02 16:45:08 +00:00
self.grid.clear_active_cells()
jobs = self._start_treads_to_evolve_grid(lists_of_cell_names)
self._wait_for_all_threads_to_finish(jobs)
print(self.test_number)
2018-12-01 14:14:22 +00:00
2018-12-02 16:45:08 +00:00
def _all_cells_are_inactive(self):
return len(self.grid.get_names_of_active_cells()) == 0
def _create_list_of_cell_names_lists_for_all_threads(self):
2018-12-02 16:45:08 +00:00
active_cells = self.grid.get_names_of_active_cells()
2018-12-01 19:37:18 +00:00
cell_count_per_thread = int(len(active_cells) / self._thread_count)
return self._divide_list_in_parts_of_size(active_cells, cell_count_per_thread)
2018-12-01 19:37:18 +00:00
@staticmethod
def _divide_list_in_parts_of_size(active_cells: list, cell_count_per_thread: int):
2018-12-01 19:37:18 +00:00
return [active_cells[i:i + cell_count_per_thread]
for i in range(0, len(active_cells), cell_count_per_thread)]
def _start_treads_to_evolve_grid(self, lists_of_cell_names):
jobs = []
2018-12-01 14:14:22 +00:00
for t in range(self._thread_count):
process = multiprocessing.Process(target=_evolve_cells, args=(self, lists_of_cell_names[t]))
jobs.append(process)
process.start()
return jobs
2018-12-01 14:14:22 +00:00
2018-12-01 19:37:18 +00:00
@staticmethod
def _wait_for_all_threads_to_finish(jobs):
for process in jobs:
process.join()
def _evolve_cells(cellular_automaton, cell_names: list):
time.sleep(2)
cellular_automaton.test_number += 1
print(cellular_automaton.grid)
for cell_name in cell_names:
cell_info = cellular_automaton.grid.get_cell_and_neighbors(cell_name)
active = cellular_automaton.rule.evolve_cell(cell_info[0], cell_info[1], cellular_automaton.iteration)
if active:
cellular_automaton.grid.set_cell_and_neighbours_active(cell_info)