added single and multi core deviation
This commit is contained in:
parent
3e3af78ccd
commit
726cc6394f
@ -43,8 +43,8 @@ if __name__ == "__main__":
|
|||||||
random.seed(1000)
|
random.seed(1000)
|
||||||
# best single is 400/400 with 0,2 ca speed and 0,09 redraw / multi is 300/300 with 0.083
|
# best single is 400/400 with 0,2 ca speed and 0,09 redraw / multi is 300/300 with 0.083
|
||||||
neighborhood = MooreNeighborhood(EdgeRule.FIRST_AND_LAST_CELL_OF_DIMENSION_ARE_NEIGHBORS)
|
neighborhood = MooreNeighborhood(EdgeRule.FIRST_AND_LAST_CELL_OF_DIMENSION_ARE_NEIGHBORS)
|
||||||
ca = make_cellular_automaton(dimension=[100, 100], neighborhood=neighborhood, rule=TestRule(), state_class=MyState)
|
ca = make_cellular_automaton(dimension=[400, 400], neighborhood=neighborhood, rule=TestRule(), state_class=MyState)
|
||||||
ca_processor = CellularAutomatonProcessor(process_count=4, cellular_automaton=ca)
|
ca_processor = CellularAutomatonProcessor(process_count=1, cellular_automaton=ca)
|
||||||
|
|
||||||
ca_window = PyGameFor2D(window_size=[1000, 800], cellular_automaton=ca)
|
ca_window = PyGameFor2D(window_size=[1000, 800], cellular_automaton=ca)
|
||||||
ca_window.main_loop(cellular_automaton_processor=ca_processor, ca_iterations_per_draw=10)
|
ca_window.main_loop(cellular_automaton_processor=ca_processor, ca_iterations_per_draw=1)
|
||||||
|
Binary file not shown.
@ -3,31 +3,30 @@ from ctypes import c_float, c_bool
|
|||||||
|
|
||||||
|
|
||||||
class CellState:
|
class CellState:
|
||||||
_state_save_slot_count = 2
|
|
||||||
"""
|
"""
|
||||||
This is the base class for all cell states.
|
This is the base class for all cell states.
|
||||||
When using the cellular automaton display, inherit this class and implement get_state_draw_color.
|
When using the cellular automaton display, inherit this class and implement get_state_draw_color.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_state_save_slot_count = 2
|
||||||
|
|
||||||
def __init__(self, initial_state=(0., ), draw_first_state=True):
|
def __init__(self, initial_state=(0., ), draw_first_state=True):
|
||||||
self._state_slots = [RawArray(c_float, initial_state) for i in range(self.__class__._state_save_slot_count)]
|
self._state_slots = [list(initial_state) for i in range(self.__class__._state_save_slot_count)]
|
||||||
self._active = [RawValue(c_bool, False) for i in range(self.__class__._state_save_slot_count)]
|
self._active = [False for i in range(self.__class__._state_save_slot_count)]
|
||||||
self._active[0].value = True
|
self._active[0] = True
|
||||||
if draw_first_state:
|
self._dirty = draw_first_state
|
||||||
self._dirty = RawValue(c_bool, True)
|
|
||||||
else:
|
|
||||||
self._dirty = RawValue(c_bool, False)
|
|
||||||
|
|
||||||
def is_active(self, iteration):
|
def is_active(self, iteration):
|
||||||
return self._active[self.__calculate_slot(iteration)]
|
return self._active[self._calculate_slot(iteration)]
|
||||||
|
|
||||||
def set_active_for_next_iteration(self, iteration):
|
def set_active_for_next_iteration(self, iteration):
|
||||||
self._active[self.__calculate_slot(iteration + 1)].value = True
|
self._active[self._calculate_slot(iteration + 1)] = True
|
||||||
|
|
||||||
def is_set_for_redraw(self):
|
def is_set_for_redraw(self):
|
||||||
return self._dirty.value
|
return self._dirty
|
||||||
|
|
||||||
def was_redrawn(self):
|
def was_redrawn(self):
|
||||||
self._dirty.value = False
|
self._dirty = False
|
||||||
|
|
||||||
def get_state_of_last_iteration(self, current_iteration_index):
|
def get_state_of_last_iteration(self, current_iteration_index):
|
||||||
return self.get_state_of_iteration(current_iteration_index - 1)
|
return self.get_state_of_iteration(current_iteration_index - 1)
|
||||||
@ -37,7 +36,7 @@ class CellState:
|
|||||||
:param iteration: Uses the iteration index, to differ between concurrent states.
|
:param iteration: Uses the iteration index, to differ between concurrent states.
|
||||||
:return The state for this iteration.
|
:return The state for this iteration.
|
||||||
"""
|
"""
|
||||||
return self._state_slots[self.__calculate_slot(iteration)]
|
return self._state_slots[self._calculate_slot(iteration)]
|
||||||
|
|
||||||
def set_state_of_iteration(self, new_state, iteration):
|
def set_state_of_iteration(self, new_state, iteration):
|
||||||
""" Will set the new state for the iteration modulo number of saved states.
|
""" Will set the new state for the iteration modulo number of saved states.
|
||||||
@ -45,25 +44,50 @@ class CellState:
|
|||||||
:param iteration: Uses the iteration index, to differ between concurrent states.
|
:param iteration: Uses the iteration index, to differ between concurrent states.
|
||||||
:return True if state has changed.
|
:return True if state has changed.
|
||||||
"""
|
"""
|
||||||
|
changed = self._change_state(new_state, iteration)
|
||||||
|
self._dirty |= changed
|
||||||
|
self._active[self._calculate_slot(iteration)] = False
|
||||||
|
return changed
|
||||||
|
|
||||||
|
def _change_state(self, new_state, iteration):
|
||||||
current_state = self.get_state_of_iteration(iteration)
|
current_state = self.get_state_of_iteration(iteration)
|
||||||
|
|
||||||
changed = False
|
changed = False
|
||||||
for i in range(len(current_state)):
|
for i, ns in enumerate(new_state):
|
||||||
try:
|
try:
|
||||||
if current_state[i] != new_state[i]:
|
if current_state[i] != ns:
|
||||||
changed = True
|
changed = True
|
||||||
current_state[i] = new_state[i]
|
current_state[i] = ns
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise IndexError("New State length or type is invalid!")
|
raise IndexError("New State length or type is invalid!")
|
||||||
|
|
||||||
self._dirty.value |= changed
|
|
||||||
self._active[self.__calculate_slot(iteration)].value = False
|
|
||||||
return changed
|
return changed
|
||||||
|
|
||||||
def get_state_draw_color(self, iteration):
|
def get_state_draw_color(self, iteration):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def __calculate_slot(cls, iteration):
|
def _calculate_slot(cls, iteration):
|
||||||
return iteration % cls._state_save_slot_count
|
return iteration % cls._state_save_slot_count
|
||||||
|
|
||||||
|
|
||||||
|
class SynchronousCellState(CellState):
|
||||||
|
def __init__(self, initial_state=(0., ), draw_first_state=True):
|
||||||
|
super().__init__(initial_state, draw_first_state)
|
||||||
|
self._state_slots = [RawArray(c_float, initial_state) for i in range(self.__class__._state_save_slot_count)]
|
||||||
|
self._active = [RawValue(c_bool, False) for i in range(self.__class__._state_save_slot_count)]
|
||||||
|
self._active[0].value = True
|
||||||
|
self._dirty = RawValue(c_bool, draw_first_state)
|
||||||
|
|
||||||
|
def set_active_for_next_iteration(self, iteration):
|
||||||
|
self._active[self._calculate_slot(iteration + 1)].value = True
|
||||||
|
|
||||||
|
def is_set_for_redraw(self):
|
||||||
|
return self._dirty.value
|
||||||
|
|
||||||
|
def was_redrawn(self):
|
||||||
|
self._dirty.value = False
|
||||||
|
|
||||||
|
def set_state_of_iteration(self, new_state, iteration):
|
||||||
|
changed = self._change_state(new_state, iteration)
|
||||||
|
self._dirty.value |= changed
|
||||||
|
self._active[self._calculate_slot(iteration)].value = False
|
||||||
|
return changed
|
||||||
|
@ -17,11 +17,18 @@ class CellularAutomatonProcessor:
|
|||||||
self.ca = cellular_automaton
|
self.ca = cellular_automaton
|
||||||
cells = {i: (c.state, c.neighbours) for i, c in enumerate(self.ca.cells)}
|
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.pool = multiprocessing.Pool(processes=process_count,
|
self._evolve_method = lambda x, y: None
|
||||||
initializer=_init_process,
|
|
||||||
initargs=(cells,
|
if process_count > 1:
|
||||||
self.ca.evolution_rule,
|
self.pool = multiprocessing.Pool(processes=process_count,
|
||||||
self.ca.evolution_iteration_index))
|
initializer=_init_process,
|
||||||
|
initargs=(cells,
|
||||||
|
self.ca.evolution_rule,
|
||||||
|
self.ca.evolution_iteration_index))
|
||||||
|
self._evolve_method = self.pool.map
|
||||||
|
else:
|
||||||
|
_init_process(cells, self.ca.evolution_rule, self.ca.evolution_iteration_index)
|
||||||
|
self._evolve_method = lambda x, y: list(map(x, y))
|
||||||
for cell in self.ca.cells:
|
for cell in self.ca.cells:
|
||||||
del cell.neighbours
|
del cell.neighbours
|
||||||
|
|
||||||
@ -31,7 +38,7 @@ class CellularAutomatonProcessor:
|
|||||||
|
|
||||||
def evolve(self):
|
def evolve(self):
|
||||||
self.ca.evolution_iteration_index.value += 1
|
self.ca.evolution_iteration_index.value += 1
|
||||||
self.pool.map(_process_routine, self.evolve_range)
|
self._evolve_method(_process_routine, self.evolve_range)
|
||||||
|
|
||||||
|
|
||||||
global_cells = None
|
global_cells = None
|
||||||
|
Loading…
Reference in New Issue
Block a user