multi processing fast and running with some tests
This commit is contained in:
parent
d1820ebc58
commit
9c855c507a
11
performance.txt
Normal file
11
performance.txt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# With 100x100 10 times
|
||||||
|
|
||||||
|
Try One
|
||||||
|
TOTAL TIME: 0.1217s
|
||||||
|
SIZE: 21.7525MB
|
||||||
|
|
||||||
|
TOTAL TIME: 0.1171s # Only set on change
|
||||||
|
SIZE: 21.7525MB # process size 51,4 / main(75,9)
|
||||||
|
|
||||||
|
TOTAL TIME: 0.1161s
|
||||||
|
SIZE: 20.3338MB # removed grid
|
@ -39,14 +39,16 @@ if __name__ == "__main__":
|
|||||||
from cellular_automaton.ca_neighborhood import MooreNeighborhood, EdgeRule
|
from cellular_automaton.ca_neighborhood import MooreNeighborhood, EdgeRule
|
||||||
from cellular_automaton.ca_display import PyGameFor2D
|
from cellular_automaton.ca_display import PyGameFor2D
|
||||||
from cellular_automaton.ca_grid import Grid
|
from cellular_automaton.ca_grid import Grid
|
||||||
|
|
||||||
freeze_support()
|
freeze_support()
|
||||||
random.seed(1000)
|
random.seed(1000)
|
||||||
|
dimension = [100, 100]
|
||||||
rule = TestRule()
|
rule = TestRule()
|
||||||
grid = Grid(dimension=[200, 200], # best is 400/400 with 0,2 ca speed and 0,09 redraw
|
grid = Grid(dimension=dimension, # best is 400/400 with 0,2 ca speed and 0,09 redraw
|
||||||
neighborhood=MooreNeighborhood(EdgeRule.FIRST_AND_LAST_CELL_OF_DIMENSION_ARE_NEIGHBORS),
|
neighborhood=MooreNeighborhood(EdgeRule.FIRST_AND_LAST_CELL_OF_DIMENSION_ARE_NEIGHBORS),
|
||||||
state_class=MyState)
|
state_class=MyState)
|
||||||
ca = CellularAutomaton(grid, rule)
|
ca = CellularAutomaton(tuple(grid.get_cells().values()), dimension, rule)
|
||||||
ca_window = PyGameFor2D(window_size=[1000, 800], cellular_automaton=ca)
|
ca_window = PyGameFor2D(window_size=[1000, 800], cellular_automaton=ca)
|
||||||
ca_processor = CellularAutomatonProcessor(process_count=2, cellular_automaton=ca)
|
ca_processor = CellularAutomatonProcessor(process_count=4, cellular_automaton=ca)
|
||||||
ca_window.main_loop(cellular_automaton_processor=ca_processor,
|
ca_window.main_loop(cellular_automaton_processor=ca_processor,
|
||||||
ca_iterations_per_draw=5)
|
ca_iterations_per_draw=5)
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
from cellular_automaton.ca_cell_state import CellState
|
from cellular_automaton.ca_cell_state import CellState
|
||||||
|
from typing import Type
|
||||||
|
|
||||||
|
|
||||||
class Cell:
|
class Cell:
|
||||||
def __init__(self, state_class: CellState.__class__, coordinate: list):
|
def __init__(self, state_class: Type[CellState], coordinate: list):
|
||||||
self._coordinate = coordinate
|
self._coordinate = coordinate
|
||||||
self._state = state_class()
|
self._state = state_class()
|
||||||
self._neighbours = []
|
self._neighbours = []
|
||||||
@ -16,29 +17,20 @@ class Cell:
|
|||||||
def get_coordinate(self):
|
def get_coordinate(self):
|
||||||
return self._coordinate
|
return self._coordinate
|
||||||
|
|
||||||
def evolve_if_ready(self, rule):
|
def evolve_if_ready(self, rule, iteration):
|
||||||
if self._neighbours_are_younger():
|
if self._state.is_active(iteration):
|
||||||
if self._state.is_active():
|
new_state = rule(self._state.get_state_of_last_iteration(iteration), self.get_neighbour_states(iteration))
|
||||||
new_state = rule(self._state.get_current_state(), self.get_neighbour_states())
|
self.set_new_state_and_activate(new_state, iteration)
|
||||||
self.set_new_state_and_activate(new_state)
|
|
||||||
|
|
||||||
self._state.increase_age()
|
def get_neighbour_states(self, index):
|
||||||
|
return [n.get_state_of_last_iteration(index) for n in self._neighbours]
|
||||||
|
|
||||||
def _neighbours_are_younger(self):
|
def set_new_state_and_activate(self, new_state: CellState, iteration):
|
||||||
for n in self._neighbours:
|
changed = self._state.set_state_of_iteration(new_state, iteration)
|
||||||
if n.get_age() < self._state.get_age():
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def get_neighbour_states(self):
|
|
||||||
return [n.get_state_of_iteration(self._state.get_age()) for n in self._neighbours]
|
|
||||||
|
|
||||||
def set_new_state_and_activate(self, new_state: CellState):
|
|
||||||
changed = self._state.set_current_state(new_state)
|
|
||||||
if changed:
|
if changed:
|
||||||
self._set_active()
|
self._set_active_for_next_iteration(iteration)
|
||||||
|
|
||||||
def _set_active(self):
|
def _set_active_for_next_iteration(self, iteration):
|
||||||
self._state.set_active_for_next_iteration(self._state.get_age() + 1)
|
self._state.set_active_for_next_iteration(iteration)
|
||||||
for n in self._neighbours:
|
for n in self._neighbours:
|
||||||
n.set_active_for_next_iteration(self._state.get_age() + 1)
|
n.set_active_for_next_iteration(iteration)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
from multiprocessing import Array, Value
|
from multiprocessing import RawArray, RawValue
|
||||||
|
from ctypes import c_float, c_bool
|
||||||
|
|
||||||
|
|
||||||
class CellState:
|
class CellState:
|
||||||
@ -8,45 +9,35 @@ class CellState:
|
|||||||
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.
|
||||||
"""
|
"""
|
||||||
def __init__(self, initial_state=(0., ), draw_first_state=True):
|
def __init__(self, initial_state=(0., ), draw_first_state=True):
|
||||||
self._state_slots = [Array('d', initial_state) for i in range(self.__class__._state_save_slot_count)]
|
self._state_slots = [RawArray(c_float, initial_state) for i in range(self.__class__._state_save_slot_count)]
|
||||||
self._active = Value('i', 1)
|
self._active = [RawValue(c_bool, False) for i in range(self.__class__._state_save_slot_count)]
|
||||||
self._age = Value('i', 0)
|
self._active[0].value = True
|
||||||
if draw_first_state:
|
if draw_first_state:
|
||||||
self._dirty = Value('i', 1)
|
self._dirty = RawValue(c_bool, True)
|
||||||
else:
|
else:
|
||||||
self._dirty = Value('i', 0)
|
self._dirty = RawValue(c_bool, False)
|
||||||
|
|
||||||
def get_age(self):
|
|
||||||
return self._age.value
|
|
||||||
|
|
||||||
def get_current_state(self):
|
|
||||||
return self.get_state_of_iteration(self.get_age())
|
|
||||||
|
|
||||||
def get_state_of_iteration(self, iteration):
|
def get_state_of_iteration(self, iteration):
|
||||||
""" Will return the state for the iteration modulo number of saved states.
|
""" Will return the state for the iteration modulo number of saved states.
|
||||||
: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[iteration % self.__class__._state_save_slot_count]
|
return self._state_slots[self.__calculate_slot(iteration)]
|
||||||
|
|
||||||
def is_active(self):
|
def __calculate_slot(self, iteration):
|
||||||
return self._active.value > self._age.value
|
return iteration % self.__class__._state_save_slot_count
|
||||||
|
|
||||||
|
def is_active(self, 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.value = max(self._active.value, iteration + 1)
|
self._active[self.__calculate_slot(iteration + 1)].value = True
|
||||||
|
|
||||||
def increase_age(self):
|
|
||||||
with self._age.get_lock():
|
|
||||||
self._age.value += 1
|
|
||||||
|
|
||||||
def is_set_for_redraw(self):
|
def is_set_for_redraw(self):
|
||||||
return self._dirty != 1
|
return self._dirty.value
|
||||||
|
|
||||||
def was_redrawn(self):
|
def was_redrawn(self):
|
||||||
self._dirty = 0
|
self._dirty.value = False
|
||||||
|
|
||||||
def set_current_state(self, new_state):
|
|
||||||
return self.set_state_of_iteration(new_state, self.get_age() + 1)
|
|
||||||
|
|
||||||
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)
|
||||||
@ -65,16 +56,13 @@ class CellState:
|
|||||||
try:
|
try:
|
||||||
if current_state[i] != new_state[i]:
|
if current_state[i] != new_state[i]:
|
||||||
changed = True
|
changed = True
|
||||||
|
|
||||||
current_state[i] = new_state[i]
|
current_state[i] = new_state[i]
|
||||||
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._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
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return str(self._state_slots)
|
|
||||||
|
@ -2,6 +2,11 @@ import pygame
|
|||||||
import time
|
import time
|
||||||
import operator
|
import operator
|
||||||
|
|
||||||
|
import cProfile
|
||||||
|
import pstats
|
||||||
|
from pympler import asizeof
|
||||||
|
|
||||||
|
|
||||||
from cellular_automaton.cellular_automaton import CellularAutomaton, CellularAutomatonProcessor
|
from cellular_automaton.cellular_automaton import CellularAutomaton, CellularAutomatonProcessor
|
||||||
|
|
||||||
|
|
||||||
@ -19,16 +24,13 @@ class DisplayFor2D:
|
|||||||
cell_size = self._calculate_cell_display_size(grid_rect[-2:])
|
cell_size = self._calculate_cell_display_size(grid_rect[-2:])
|
||||||
self._display_info = _DisplayInfo(grid_rect[-2:], grid_rect[:2], cell_size, screen)
|
self._display_info = _DisplayInfo(grid_rect[-2:], grid_rect[:2], cell_size, screen)
|
||||||
|
|
||||||
def set_cellular_automaton(self, cellular_automaton):
|
def redraw_cellular_automaton(self):
|
||||||
self._cellular_automaton = cellular_automaton
|
pygame.display.update(list(_cell_redraw_rectangles(self._cellular_automaton.cells,
|
||||||
|
0,
|
||||||
def _redraw_cellular_automaton(self):
|
|
||||||
pygame.display.update(list(_cell_redraw_rectangles(self._cellular_automaton.grid.get_cells().values(),
|
|
||||||
self._cellular_automaton.evolution_iteration_index,
|
|
||||||
self._display_info)))
|
self._display_info)))
|
||||||
|
|
||||||
def _calculate_cell_display_size(self, grid_size):
|
def _calculate_cell_display_size(self, grid_size):
|
||||||
grid_dimension = self._cellular_automaton.grid.get_dimension()
|
grid_dimension = self._cellular_automaton.dimension
|
||||||
return list(map(operator.truediv, grid_size, grid_dimension))
|
return list(map(operator.truediv, grid_size, grid_dimension))
|
||||||
|
|
||||||
|
|
||||||
@ -36,7 +38,7 @@ class PyGameFor2D:
|
|||||||
def __init__(self, window_size: list, cellular_automaton: CellularAutomaton):
|
def __init__(self, window_size: list, cellular_automaton: CellularAutomaton):
|
||||||
self._window_size = window_size
|
self._window_size = window_size
|
||||||
self._cellular_automaton = cellular_automaton
|
self._cellular_automaton = cellular_automaton
|
||||||
|
self._cellular_automaton_proocessor = None
|
||||||
pygame.init()
|
pygame.init()
|
||||||
pygame.display.set_caption("Cellular Automaton")
|
pygame.display.set_caption("Cellular Automaton")
|
||||||
self._screen = pygame.display.set_mode(self._window_size)
|
self._screen = pygame.display.set_mode(self._window_size)
|
||||||
@ -56,20 +58,34 @@ class PyGameFor2D:
|
|||||||
|
|
||||||
def main_loop(self, cellular_automaton_processor: CellularAutomatonProcessor, ca_iterations_per_draw):
|
def main_loop(self, cellular_automaton_processor: CellularAutomatonProcessor, ca_iterations_per_draw):
|
||||||
running = True
|
running = True
|
||||||
|
cellular_automaton_processor.evolve()
|
||||||
|
first = True
|
||||||
while running:
|
while running:
|
||||||
|
pygame.event.get()
|
||||||
time_ca_start = time.time()
|
time_ca_start = time.time()
|
||||||
|
if first:
|
||||||
|
self._evolve_with_performance(cellular_automaton_processor, time_ca_start)
|
||||||
|
first = False
|
||||||
|
else:
|
||||||
|
cellular_automaton_processor.evolve()
|
||||||
time_ca_end = time.time()
|
time_ca_end = time.time()
|
||||||
self.ca_display._redraw_cellular_automaton()
|
self.ca_display.redraw_cellular_automaton()
|
||||||
time_ds_end = time.time()
|
time_ds_end = time.time()
|
||||||
self._print_process_duration(time_ca_end, time_ca_start, time_ds_end)
|
self._print_process_duration(time_ca_end, time_ca_start, time_ds_end)
|
||||||
|
|
||||||
time.sleep(0.5)
|
def _evolve_with_performance(self, cap, time_ca_start):
|
||||||
|
size = asizeof.asizeof(self._cellular_automaton)
|
||||||
for event in pygame.event.get():
|
cProfile.runctx("cap.evolve_x_times(10)", None, locals(), "performance_test")
|
||||||
if event.type == pygame.QUIT:
|
print("PERFORMANCE")
|
||||||
cellular_automaton_processor.stop()
|
p = pstats.Stats('performance_test2')
|
||||||
running = False
|
p.strip_dirs()
|
||||||
|
# sort by cumulative time in a function
|
||||||
|
p.sort_stats('cumulative').print_stats(10)
|
||||||
|
# sort by time spent in a function
|
||||||
|
p.sort_stats('time').print_stats(10)
|
||||||
|
time_ca_end = time.time()
|
||||||
|
print("TOTAL TIME: " + "{0:.4f}".format(time_ca_end - time_ca_start) + "s")
|
||||||
|
print("SIZE: " + "{0:.4f}".format(size / (1024 * 1024)) + "MB")
|
||||||
|
|
||||||
|
|
||||||
def _cell_redraw_rectangles(cells, evolution_index, display_info):
|
def _cell_redraw_rectangles(cells, evolution_index, display_info):
|
||||||
|
@ -17,9 +17,6 @@ class Neighborhood:
|
|||||||
self.edge_rule = edge_rule
|
self.edge_rule = edge_rule
|
||||||
self.grid_dimensions = []
|
self.grid_dimensions = []
|
||||||
|
|
||||||
def get_relative_neighbor_coordinates(self):
|
|
||||||
return self._neighbors
|
|
||||||
|
|
||||||
def calculate_cell_neighbor_coordinates(self, cell_coordinate, grid_dimensions):
|
def calculate_cell_neighbor_coordinates(self, cell_coordinate, grid_dimensions):
|
||||||
""" Get a list of coordinates for the cell neighbors. The EdgeRule can reduce the returned neighbor count.
|
""" Get a list of coordinates for the cell neighbors. The EdgeRule can reduce the returned neighbor count.
|
||||||
:param cell_coordinate: The coordinate of the cell to get the neighbors
|
:param cell_coordinate: The coordinate of the cell to get the neighbors
|
||||||
|
@ -1,39 +1,49 @@
|
|||||||
import multiprocessing
|
import multiprocessing
|
||||||
|
|
||||||
from cellular_automaton.ca_grid import Grid
|
|
||||||
from cellular_automaton.ca_rule import Rule
|
from cellular_automaton.ca_rule import Rule
|
||||||
|
|
||||||
|
|
||||||
class CellularAutomaton:
|
class CellularAutomaton:
|
||||||
def __init__(self, grid: Grid, evolution_rule: Rule):
|
def __init__(self, cells, dimension, evolution_rule: Rule):
|
||||||
self.grid = grid
|
self.cells = cells
|
||||||
|
self.dimension = dimension
|
||||||
self.evolution_rule = evolution_rule
|
self.evolution_rule = evolution_rule
|
||||||
self.evolution_iteration_index = 0
|
self.evolution_iteration_index = multiprocessing.RawValue('i', -1)
|
||||||
|
|
||||||
|
|
||||||
class CellularAutomatonProcessor:
|
class CellularAutomatonProcessor:
|
||||||
def __init__(self, cellular_automaton, process_count: int = 1):
|
def __init__(self, cellular_automaton, process_count: int = 1):
|
||||||
self.active = multiprocessing.Value('i', 1)
|
self.ca = cellular_automaton
|
||||||
cells = list(cellular_automaton.grid.get_cells().values())
|
self.evolve_range = range(len(self.ca.cells))
|
||||||
chunk_size = int(len(cells) / process_count)
|
self.pool = multiprocessing.Pool(processes=process_count,
|
||||||
self._processes = [multiprocessing.Process(target=_process_routine,
|
initializer=_init_process,
|
||||||
name=str(i),
|
initargs=(self.ca.cells,
|
||||||
args=(cells[i*chunk_size:i*chunk_size + chunk_size],
|
self.ca.evolution_rule,
|
||||||
cellular_automaton.evolution_rule,
|
self.ca.evolution_iteration_index))
|
||||||
self.active))
|
for cell in self.ca.cells:
|
||||||
for i in range(process_count)]
|
cell.set_neighbours(None)
|
||||||
for p in self._processes:
|
|
||||||
p.start()
|
|
||||||
self.__cellular_automaton = None
|
|
||||||
|
|
||||||
def stop(self):
|
def evolve_x_times(self, x):
|
||||||
self.active.value = 0
|
for x in range(x):
|
||||||
for p in self._processes:
|
self.evolve()
|
||||||
p.join()
|
|
||||||
|
def evolve(self):
|
||||||
|
self.ca.evolution_iteration_index.value += 1
|
||||||
|
self.pool.map(_process_routine, self.evolve_range)
|
||||||
|
|
||||||
|
|
||||||
def _process_routine(cells, rule, active):
|
global_cells = None
|
||||||
while active.value == 1:
|
global_rule = None
|
||||||
for cell in cells:
|
global_iteration = None
|
||||||
cell.evolve_if_ready(rule.evolve_cell)
|
|
||||||
|
|
||||||
|
def _init_process(cells, rule, index):
|
||||||
|
global global_rule, global_cells, global_iteration
|
||||||
|
global_cells = cells
|
||||||
|
global_rule = rule
|
||||||
|
global_iteration = index
|
||||||
|
|
||||||
|
|
||||||
|
def _process_routine(i):
|
||||||
|
global_cells[i].evolve_if_ready(global_rule.evolve_cell, global_iteration.value)
|
||||||
|
|
||||||
|
@ -1,12 +1,41 @@
|
|||||||
import sys
|
import sys
|
||||||
sys.path.append('../src')
|
sys.path.append('../src')
|
||||||
|
|
||||||
|
import cellular_automaton.ca_cell_state as cas
|
||||||
import cellular_automaton.ca_cell as cac
|
import cellular_automaton.ca_cell as cac
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
|
||||||
|
class TestState(cas.CellState):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
|
||||||
class TestCellState(unittest.TestCase):
|
class TestCellState(unittest.TestCase):
|
||||||
pass
|
def setUp(self):
|
||||||
|
self.cell = cac.Cell(TestState, [])
|
||||||
|
self.neighbours = [TestState() for x in range(5)]
|
||||||
|
for neighbour in self.neighbours:
|
||||||
|
neighbour.set_state_of_iteration((0, ), 0)
|
||||||
|
self.cell.set_neighbours(self.neighbours)
|
||||||
|
|
||||||
|
def cell_and_neighbours_active(self, iteration):
|
||||||
|
self.neighbours.append(self.cell.get_state())
|
||||||
|
all_active = True
|
||||||
|
for state in self.neighbours:
|
||||||
|
if not state.is_active(iteration):
|
||||||
|
all_active = False
|
||||||
|
return all_active
|
||||||
|
|
||||||
|
def test_evolve_activation(self):
|
||||||
|
self.cell.evolve_if_ready((lambda a, b: (1,)), 0)
|
||||||
|
all_active = self.cell_and_neighbours_active(1)
|
||||||
|
self.assertTrue(all_active)
|
||||||
|
|
||||||
|
def test_evolve_activation_on_no_change(self):
|
||||||
|
self.cell.evolve_if_ready((lambda a, b: (0,)), 0)
|
||||||
|
all_active = self.cell_and_neighbours_active(1)
|
||||||
|
self.assertFalse(all_active)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -22,6 +22,21 @@ class TestCellState(unittest.TestCase):
|
|||||||
cell_state.set_state_of_iteration(new_state=(1,), iteration=0)
|
cell_state.set_state_of_iteration(new_state=(1,), iteration=0)
|
||||||
self.assertEqual(tuple(cell_state.get_state_of_iteration(1)), (0,))
|
self.assertEqual(tuple(cell_state.get_state_of_iteration(1)), (0,))
|
||||||
|
|
||||||
|
def test_redraw_state_on_change(self):
|
||||||
|
cell_state = cs.CellState(initial_state=(0,), draw_first_state=False)
|
||||||
|
cell_state.set_state_of_iteration(new_state=(1,), iteration=0)
|
||||||
|
self.assertTrue(cell_state.is_set_for_redraw())
|
||||||
|
|
||||||
|
def test_redraw_state_on_nochange(self):
|
||||||
|
cell_state = cs.CellState(initial_state=(0,), draw_first_state=False)
|
||||||
|
cell_state.set_state_of_iteration(new_state=(0,), iteration=0)
|
||||||
|
self.assertFalse(cell_state.is_set_for_redraw())
|
||||||
|
|
||||||
|
def test_active_state_after_set(self):
|
||||||
|
cell_state = cs.CellState(initial_state=(0,), draw_first_state=False)
|
||||||
|
cell_state.set_state_of_iteration(new_state=(1,), iteration=0)
|
||||||
|
self.assertFalse(cell_state.is_active(1))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
40
test/test_neighborhood.py
Normal file
40
test/test_neighborhood.py
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import sys
|
||||||
|
sys.path.append('../src')
|
||||||
|
|
||||||
|
import cellular_automaton.ca_neighborhood as csn
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
|
||||||
|
class TestCellState(unittest.TestCase):
|
||||||
|
def check_neighbors(self, neighborhood, neighborhood_sets):
|
||||||
|
for neighborhood_set in neighborhood_sets:
|
||||||
|
neighbors = neighborhood.calculate_cell_neighbor_coordinates(neighborhood_set[0], [3, 3])
|
||||||
|
if neighborhood_set[1] != neighbors:
|
||||||
|
print((neighborhood_set[1]), (neighbors))
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def test_ignore_missing_neighbors(self):
|
||||||
|
neighborhood = csn.MooreNeighborhood(csn.EdgeRule.IGNORE_MISSING_NEIGHBORS_OF_EDGE_CELLS)
|
||||||
|
n00 = [[0, 0], [[1, 0], [0, 1], [1, 1]]]
|
||||||
|
n11 = [[1, 1], [[0, 0], [1, 0], [2, 0], [0, 1], [2, 1], [0, 2], [1, 2], [2, 2]]]
|
||||||
|
n22 = [[2, 2], [[1, 1], [2, 1], [1, 2]]]
|
||||||
|
self.assertTrue(self.check_neighbors(neighborhood, [n00, n11, n22]))
|
||||||
|
|
||||||
|
def test_ignore_edge_cells(self):
|
||||||
|
neighborhood = csn.MooreNeighborhood(csn.EdgeRule.IGNORE_EDGE_CELLS)
|
||||||
|
n00 = [[0, 0], []]
|
||||||
|
n11 = [[1, 1], [[0, 0], [1, 0], [2, 0], [0, 1], [2, 1], [0, 2], [1, 2], [2, 2]]]
|
||||||
|
n22 = [[2, 2], []]
|
||||||
|
self.assertTrue(self.check_neighbors(neighborhood, [n00, n11, n22]))
|
||||||
|
|
||||||
|
def test_cyclic_dimensions(self):
|
||||||
|
neighborhood = csn.MooreNeighborhood(csn.EdgeRule.FIRST_AND_LAST_CELL_OF_DIMENSION_ARE_NEIGHBORS)
|
||||||
|
n00 = [[0, 0], [[2, 2], [0, 2], [1, 2], [2, 0], [1, 0], [2, 1], [0, 1], [1, 1]]]
|
||||||
|
n11 = [[1, 1], [[0, 0], [1, 0], [2, 0], [0, 1], [2, 1], [0, 2], [1, 2], [2, 2]]]
|
||||||
|
n22 = [[2, 2], [[1, 1], [2, 1], [0, 1], [1, 2], [0, 2], [1, 0], [2, 0], [0, 0]]]
|
||||||
|
self.assertTrue(self.check_neighbors(neighborhood, [n00, n11, n22]))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
Loading…
Reference in New Issue
Block a user