2018-12-08 16:45:06 +00:00
|
|
|
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)
|
2018-12-08 16:45:06 +00:00
|
|
|
self.rule = rule_
|
2018-12-02 16:45:08 +00:00
|
|
|
self._thread_count = thread_count
|
2018-12-08 16:45:06 +00:00
|
|
|
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):
|
2018-12-08 16:45:06 +00:00
|
|
|
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):
|
2018-12-08 16:45:06 +00:00
|
|
|
return self.iteration
|
2018-12-02 16:45:08 +00:00
|
|
|
|
2018-12-01 19:37:18 +00:00
|
|
|
def evolve(self):
|
2018-12-08 16:45:06 +00:00
|
|
|
""" 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:
|
2018-12-08 16:45:06 +00:00
|
|
|
self.iteration += 1
|
|
|
|
self._start_multi_process_cell_evolution()
|
2018-12-02 16:45:08 +00:00
|
|
|
return False
|
|
|
|
|
2018-12-08 16:45:06 +00:00
|
|
|
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()
|
2018-12-08 16:45:06 +00:00
|
|
|
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
|
|
|
|
|
2018-12-08 16:45:06 +00:00
|
|
|
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)
|
2018-12-08 16:45:06 +00:00
|
|
|
return self._divide_list_in_parts_of_size(active_cells, cell_count_per_thread)
|
2018-12-01 19:37:18 +00:00
|
|
|
|
|
|
|
@staticmethod
|
2018-12-08 16:45:06 +00:00
|
|
|
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)]
|
|
|
|
|
2018-12-08 16:45:06 +00:00
|
|
|
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):
|
2018-12-08 16:45:06 +00:00
|
|
|
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
|
2018-12-08 16:45:06 +00:00
|
|
|
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)
|