2019-02-23 15:20:48 +00:00
|
|
|
"""
|
|
|
|
Copyright 2019 Richard Feistenauer
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
"""
|
|
|
|
|
2019-01-31 12:38:48 +00:00
|
|
|
import multiprocessing
|
2019-02-16 17:05:26 +00:00
|
|
|
from multiprocessing import freeze_support
|
2019-02-15 18:33:15 +00:00
|
|
|
from ctypes import c_int
|
2018-12-01 14:14:22 +00:00
|
|
|
|
|
|
|
|
2019-01-06 10:21:46 +00:00
|
|
|
class CellularAutomatonProcessor:
|
2019-02-15 18:33:15 +00:00
|
|
|
def __init__(self, cellular_automaton):
|
|
|
|
self._ca = cellular_automaton
|
|
|
|
|
|
|
|
def evolve_x_times(self, x):
|
|
|
|
for x in range(x):
|
|
|
|
self.evolve()
|
|
|
|
|
|
|
|
def evolve(self):
|
2019-02-16 17:05:26 +00:00
|
|
|
i = self._ca.current_evolution_step
|
2019-02-15 18:33:15 +00:00
|
|
|
r = self._ca.evolution_rule.evolve_cell
|
2019-02-16 17:05:26 +00:00
|
|
|
list(map(lambda c: c.evolve_if_ready(r, i), tuple(self._ca.cells.values())))
|
2019-02-23 15:20:48 +00:00
|
|
|
self._ca.current_evolution_step += 1
|
2019-02-15 18:33:15 +00:00
|
|
|
|
2019-02-23 15:20:10 +00:00
|
|
|
def get_dimension(self):
|
|
|
|
return self._ca.dimension
|
|
|
|
|
|
|
|
def get_cells(self):
|
|
|
|
return self._ca.cells
|
|
|
|
|
|
|
|
def get_current_evolution_step(self):
|
|
|
|
return self._ca.current_evolution_step
|
|
|
|
|
|
|
|
def get_current_rule(self):
|
|
|
|
return self._ca.evolution_rule
|
|
|
|
|
2019-02-15 18:33:15 +00:00
|
|
|
|
|
|
|
class CellularAutomatonMultiProcessor(CellularAutomatonProcessor):
|
|
|
|
def __init__(self, cellular_automaton, process_count: int = 2):
|
2019-02-16 17:05:26 +00:00
|
|
|
freeze_support()
|
2019-02-15 18:33:15 +00:00
|
|
|
if process_count < 1:
|
|
|
|
raise ValueError
|
2019-02-15 19:02:57 +00:00
|
|
|
|
2019-02-15 18:33:15 +00:00
|
|
|
super().__init__(cellular_automaton)
|
2019-02-15 19:02:57 +00:00
|
|
|
|
|
|
|
self.evolve_range = range(len(self._ca.cells))
|
2019-02-23 15:20:10 +00:00
|
|
|
self._ca.current_evolution_step = multiprocessing.RawValue(c_int, self._ca.current_evolution_step)
|
2019-02-16 17:05:26 +00:00
|
|
|
self.__init_processes_and_clean_cell_instances(process_count)
|
|
|
|
|
|
|
|
def __init_processes_and_clean_cell_instances(self, process_count):
|
2019-02-15 18:33:15 +00:00
|
|
|
self.pool = multiprocessing.Pool(processes=process_count,
|
|
|
|
initializer=_init_process,
|
2019-02-15 19:02:57 +00:00
|
|
|
initargs=(tuple(self._ca.cells.values()),
|
|
|
|
self._ca.evolution_rule,
|
2019-02-23 15:20:10 +00:00
|
|
|
self._ca.current_evolution_step))
|
2019-02-03 16:17:57 +00:00
|
|
|
|
|
|
|
def evolve(self):
|
2019-02-15 18:33:15 +00:00
|
|
|
self.pool.map(_process_routine, self.evolve_range)
|
2019-02-23 15:20:48 +00:00
|
|
|
self._ca.current_evolution_step.value += 1
|
2019-02-03 16:17:57 +00:00
|
|
|
|
2019-02-23 15:20:10 +00:00
|
|
|
def get_current_evolution_step(self):
|
|
|
|
return self._ca.current_evolution_step.value
|
|
|
|
|
2019-02-03 16:17:57 +00:00
|
|
|
|
|
|
|
global_cells = None
|
|
|
|
global_rule = None
|
2019-02-16 17:05:26 +00:00
|
|
|
global_evolution_step = None
|
2019-02-03 16:17:57 +00:00
|
|
|
|
|
|
|
|
|
|
|
def _init_process(cells, rule, index):
|
2019-02-16 17:05:26 +00:00
|
|
|
global global_rule, global_cells, global_evolution_step
|
2019-02-03 16:17:57 +00:00
|
|
|
global_cells = cells
|
|
|
|
global_rule = rule
|
2019-02-16 17:05:26 +00:00
|
|
|
global_evolution_step = index
|
2019-02-03 16:17:57 +00:00
|
|
|
|
|
|
|
|
|
|
|
def _process_routine(i):
|
2019-02-16 17:05:26 +00:00
|
|
|
global_cells[i].evolve_if_ready(global_rule.evolve_cell, global_evolution_step.value)
|