16#include <unordered_map>
23const std::string FILE_PATH =
"Data/data.csv";
79 CellsAlreadyInitialized = -1,
82 InvalidCellState = -4,
83 InvalidCellStateCondition = -5,
85 InvalidNumStates = -7,
86 NeighborhoodCellsMalloc = -8,
87 CustomRuleIsNull = -9,
88 RadiusLargerThanDimensions = -10
200 int set_new_cell_state(
int *cell_index,
int index_size,
201 T *neighborhood_cells,
int neighborhood_size,
202 T &new_cell_state,
void(
custom_rule)(
int *,
int, T *,
int, T &))
210 case CAEnums::Custom:
211 if (vector ==
nullptr && matrix ==
nullptr && tensor ==
nullptr)
213 new_cell_state.state = -1;
214 return CAEnums::CellsAreNull;
218 new_cell_state.state = -1;
219 return CAEnums::CustomRuleIsNull;
224 custom_rule(cell_index, index_size, neighborhood_cells, neighborhood_size, new_cell_state);
227 case CAEnums::Parity:
228 for (
int i = 0; i < neighborhood_size; i++)
231 sum += neighborhood_cells[i].state;
235 case CAEnums::Majority:
236 for (
int i = 0; i < neighborhood_size; i++)
239 auto it = state_votes_counter.find(neighborhood_cells[i].state);
240 if (it != state_votes_counter.end())
246 auto max_elem = max_element(state_votes_counter.begin(), state_votes_counter.end(),
248 new_cell_state.state = max_elem->first;
266 int get_state_from_neighborhood_1d(
int *cell_index,
int index_size, T &new_cell_state,
270 int i = cell_index[0];
271 int neighborhood_index = 0;
274 T *neighborhood_cells = malloc_neighborhood_array(index_size);
275 if (neighborhood_cells ==
nullptr)
277 return CAEnums::NeighborhoodCellsMalloc;
283 case CAEnums::Periodic:
284 generate_periodic_neighborhood_1d(cell_index, neighborhood_cells, neighborhood_index);
285 error_code = set_new_cell_state(cell_index, index_size, neighborhood_cells, neighborhood_index, new_cell_state,
custom_rule);
287 case CAEnums::Walled:
291 new_cell_state = vector[i];
295 case CAEnums::CutOff:
296 generate_cutoff_neighborhood_1d(cell_index, neighborhood_cells, neighborhood_index);
297 error_code = set_new_cell_state(cell_index, index_size, neighborhood_cells, neighborhood_index, new_cell_state,
custom_rule);
300 delete[] neighborhood_cells;
316 int get_state_from_neighborhood_2d(
int *cell_index,
int index_size, T &new_cell_state,
320 int i = cell_index[0];
321 int j = cell_index[1];
322 int neighborhood_index = 0;
325 T *neighborhood_cells = malloc_neighborhood_array(index_size);
326 if (neighborhood_cells ==
nullptr)
328 return CAEnums::NeighborhoodCellsMalloc;
333 case CAEnums::Periodic:
334 generate_periodic_neighborhood_2d(cell_index, neighborhood_cells, neighborhood_index);
335 error_code = set_new_cell_state(cell_index, index_size, neighborhood_cells, neighborhood_index, new_cell_state,
custom_rule);
337 case CAEnums::Walled:
341 new_cell_state = matrix[i][j];
345 case CAEnums::CutOff:
346 generate_cutoff_neighborhood_2d(cell_index, neighborhood_cells, neighborhood_index);
347 error_code = set_new_cell_state(cell_index, index_size, neighborhood_cells, neighborhood_index, new_cell_state,
custom_rule);
350 delete[] neighborhood_cells;
366 int get_state_from_neighborhood_3d(
int *cell_index,
int index_size, T &new_cell_state,
370 int i = cell_index[0];
371 int j = cell_index[1];
372 int k = cell_index[2];
373 int neighborhood_index = 0;
376 T *neighborhood_cells = malloc_neighborhood_array(index_size);
377 if (neighborhood_cells ==
nullptr)
379 return CAEnums::NeighborhoodCellsMalloc;
384 case CAEnums::Periodic:
385 generate_periodic_neighborhood_3d(cell_index, neighborhood_cells, neighborhood_index);
386 error_code = set_new_cell_state(cell_index, index_size, neighborhood_cells, neighborhood_index, new_cell_state,
custom_rule);
388 case CAEnums::Walled:
393 new_cell_state = tensor[i][j][k];
397 case CAEnums::CutOff:
398 generate_cutoff_neighborhood_3d(cell_index, neighborhood_cells, neighborhood_index);
399 error_code = set_new_cell_state(cell_index, index_size, neighborhood_cells, neighborhood_index, new_cell_state,
custom_rule);
402 delete[] neighborhood_cells;
414 void generate_periodic_neighborhood_1d(
int *cell_index, T *neighborhood_cells,
int &neighborhood_index)
416 int i = cell_index[0];
423 neighborhood_cells[neighborhood_index] = vector[periodic_i];
424 neighborhood_index++;
436 void generate_cutoff_neighborhood_1d(
int *cell_index, T *neighborhood_cells,
int &neighborhood_index)
438 int i = cell_index[0];
445 if (neighbor_i <= 0 || neighbor_i >=
axis1_dim)
451 neighborhood_cells[neighborhood_index] = vector[di];
452 neighborhood_index++;
464 void generate_periodic_neighborhood_2d(
int *cell_index, T *neighborhood_cells,
int &neighborhood_index)
466 int i = cell_index[0];
467 int j = cell_index[1];
486 neighborhood_cells[neighborhood_index] = matrix[periodic_i][periodic_j];
487 neighborhood_index++;
500 neighborhood_cells[neighborhood_index] = matrix[periodic_i][periodic_j];
501 neighborhood_index++;
515 void generate_cutoff_neighborhood_2d(
int *cell_index, T *neighborhood_cells,
int &neighborhood_index)
517 int i = cell_index[0];
518 int j = cell_index[1];
537 if ((neighbor_i <= 0 || neighbor_i >=
axis1_dim) || (neighbor_j <= 0 || neighbor_j >=
axis2_dim))
543 neighborhood_cells[neighborhood_index] = matrix[neighbor_i][neighbor_j];
544 neighborhood_index++;
557 if ((neighbor_i <= 0 || neighbor_i >=
axis1_dim) || (neighbor_j <= 0 || neighbor_j >=
axis2_dim))
563 neighborhood_cells[neighborhood_index] = matrix[neighbor_i][neighbor_j];
564 neighborhood_index++;
578 void generate_periodic_neighborhood_3d(
int *cell_index, T *neighborhood_cells,
int &neighborhood_index)
580 int i = cell_index[0];
581 int j = cell_index[1];
582 int k = cell_index[2];
605 neighborhood_cells[neighborhood_index] = tensor[periodic_i][periodic_j][periodic_k];
606 neighborhood_index++;
623 neighborhood_cells[neighborhood_index] = tensor[periodic_i][periodic_j][periodic_k];
624 neighborhood_index++;
639 void generate_cutoff_neighborhood_3d(
int *cell_index, T *neighborhood_cells,
int &neighborhood_index)
641 int i = cell_index[0];
642 int j = cell_index[1];
643 int k = cell_index[2];
666 if ((neighbor_i <= 0 || neighbor_i >=
axis1_dim) ||
667 (neighbor_j <= 0 || neighbor_j >=
axis2_dim) ||
668 (neighbor_k <= 0 || neighbor_k >=
axis3_dim))
674 neighborhood_cells[neighborhood_index] = tensor[neighbor_i][neighbor_j][neighbor_k];
675 neighborhood_index++;
692 if ((neighbor_i <= 0 || neighbor_i >=
axis1_dim) ||
693 (neighbor_j <= 0 || neighbor_j >=
axis2_dim) ||
694 (neighbor_k <= 0 || neighbor_k >=
axis3_dim))
700 neighborhood_cells[neighborhood_index] = tensor[neighbor_i][neighbor_j][neighbor_k];
701 neighborhood_index++;
714 T *malloc_neighborhood_array(
int rank)
722 T *neighborhood_cells =
new (std::nothrow) T[max_neighborhood_size];
723 return neighborhood_cells;
736 file.open(FILE_PATH, std::ios::app);
738 if (vector !=
nullptr)
742 file << vector[i].state <<
",";
745 else if (matrix !=
nullptr)
751 file << matrix[j][k].state <<
",";
755 else if (tensor !=
nullptr)
763 file << tensor[i][j][k].state <<
",";
770 return CAEnums::CellsAreNull;
784 file.open(FILE_PATH, std::ios::trunc | std::ios::out);
870 return CAEnums::InvalidRadius;
872 if (vector !=
nullptr)
876 return CAEnums::RadiusLargerThanDimensions;
879 else if (matrix !=
nullptr)
883 return CAEnums::RadiusLargerThanDimensions;
886 else if (tensor !=
nullptr)
890 return CAEnums::RadiusLargerThanDimensions;
908 next_vector =
nullptr;
910 next_matrix =
nullptr;
912 next_tensor =
nullptr;
923 if (vector !=
nullptr)
927 delete[] next_vector;
930 if (matrix !=
nullptr)
936 delete[] next_matrix[i];
940 delete[] next_matrix;
943 if (tensor !=
nullptr)
950 delete[] tensor[i][j];
951 delete[] next_tensor[i][j];
955 delete[] next_tensor[i];
960 delete[] next_tensor;
976 if (vector !=
nullptr)
978 return CAEnums::CellsAlreadyInitialized;
982 vector =
new (std::nothrow) T[
axis1_dim];
983 next_vector =
new (std::nothrow) T[
axis1_dim];
985 if (vector ==
nullptr || next_vector ==
nullptr)
987 return CAEnums::CellsMalloc;
993 vector[j].state = fill_value;
994 next_vector[j].state = fill_value;
1014 if (matrix !=
nullptr)
1016 return CAEnums::CellsAlreadyInitialized;
1021 matrix =
new (std::nothrow) T *[
axis1_dim];
1022 next_matrix =
new (std::nothrow) T *[
axis1_dim];
1024 if (matrix ==
nullptr || next_matrix ==
nullptr)
1026 return CAEnums::CellsMalloc;
1031 matrix[i] =
new (std::nothrow) T[
axis2_dim];
1032 next_matrix[i] =
new (std::nothrow) T[
axis2_dim];
1040 matrix[j][k].state = fill_value;
1041 next_matrix[j][k].state = fill_value;
1063 if (tensor !=
nullptr)
1065 return CAEnums::CellsAlreadyInitialized;
1071 tensor =
new (std::nothrow) T **[
axis1_dim];
1072 next_tensor =
new (std::nothrow) T **[
axis1_dim];
1074 if (tensor ==
nullptr || next_tensor ==
nullptr)
1076 return CAEnums::CellsMalloc;
1081 tensor[i] =
new (std::nothrow) T *[
axis2_dim];
1082 next_tensor[i] =
new (std::nothrow) T *[
axis2_dim];
1086 tensor[i][j] =
new (std::nothrow) T[
axis3_dim];
1087 next_tensor[i][j] =
new (std::nothrow) T[
axis3_dim];
1098 tensor[i][j][k].state = fill_value;
1099 next_tensor[i][j][k].state = fill_value;
1122 return CAEnums::InvalidCellStateCondition;
1126 double random_cell_state;
1128 if (vector !=
nullptr)
1132 random_cell_state = (double)rand() / RAND_MAX;
1133 if (random_cell_state < prob)
1135 vector[i].state = x_state;
1139 else if (matrix !=
nullptr)
1145 random_cell_state = (double)rand() / RAND_MAX;
1146 if (random_cell_state < prob)
1148 matrix[j][k].state = x_state;
1153 else if (tensor !=
nullptr)
1161 random_cell_state = (double)rand() / RAND_MAX;
1162 if (random_cell_state < prob)
1164 tensor[i][j][k].state = x_state;
1172 return CAEnums::CellsAreNull;
1199 if (vector !=
nullptr)
1204#pragma omp parallel for firstprivate(error_code) private(new_cell_state)
1208 int cell_index[index_size] = {i};
1209 new_cell_state = vector[i];
1210 error_code = get_state_from_neighborhood_1d(cell_index, index_size, new_cell_state,
custom_rule);
1214#pragma omp cancel for
1228 if (new_cell_state != empty_cell_state)
1230 next_vector[cell_index[0]] = new_cell_state;
1234 swap_states<T>(vector, next_vector,
axis1_dim);
1236 else if (matrix !=
nullptr)
1241#pragma omp parallel for firstprivate(error_code) private(new_cell_state)
1247 int cell_index[index_size] = {i, j};
1248 new_cell_state = matrix[i][j];
1249 error_code = get_state_from_neighborhood_2d(cell_index, index_size, new_cell_state,
custom_rule);
1253#pragma omp cancel for
1267 if (new_cell_state != empty_cell_state)
1269 next_matrix[cell_index[0]][cell_index[1]] = new_cell_state;
1276 else if (tensor !=
nullptr)
1280#pragma omp parallel for firstprivate(error_code) private(new_cell_state)
1288 int cell_index[index_size] = {i, j, k};
1289 new_cell_state = tensor[i][j][k];
1290 error_code = get_state_from_neighborhood_3d(cell_index, index_size, new_cell_state,
custom_rule);
1294#pragma omp cancel for
1308 if (new_cell_state != empty_cell_state)
1310 next_tensor[cell_index[0]][cell_index[1]][cell_index[2]] = new_cell_state;
1320 return CAEnums::CellsAreNull;
1325 error_code = append_log();
1339 return step(
nullptr);
1351 if (vector !=
nullptr)
1355 std::cout << vector[i].state <<
" ";
1357 std::cout << std::endl;
1359 else if (matrix !=
nullptr)
1365 std::cout << matrix[j][k].state <<
" ";
1367 std::cout << std::endl;
1370 else if (tensor !=
nullptr)
1374 std::cout <<
"Printing " << i <<
"'th slice of Tensor" << std::endl;
1379 std::cout << tensor[i][j][k].state <<
" ";
1381 std::cout << std::endl;
1387 return CAEnums::CellsAreNull;
1404 return (2 * rank * radius) + 1;
1408 return pow((2 * radius + 1), rank);
1423 counter.insert(std::make_pair(j, 0));
1501 int *neighborhood_cells,
int neighborhood_size,
1502 int &new_cell_state,
void(
custom_rule)(
int *,
int,
int *,
int,
int &));
std::unordered_map< int, int > MajorityCounter
counter type for determining which cell state is the majority
Definition: CAdatatypes.h:29
This header files contains utility functions used by CellularAutomata class.
bool is_diagonal_neighboring_cell_3d(int i, int j, int k)
determines if a cell is diagonal to the central cell if k == 0 then both i and j have be non-zero dia...
Definition: CA_utils.cpp:28
bool less_than_votes(const std::pair< int, int > &a, const std::pair< int, int > &b)
Determines if a has less votes than b.
Definition: CA_utils.cpp:49
bool is_diagonal_neighboring_cell_2d(int i, int j)
determines if a cell is diagonal to the central cell diagram of slice: 1 = diagonal cell 1 0 1 0 0 0 ...
Definition: CA_utils.cpp:19
int get_periodic_index(int i, int di, int axis_dim)
get the periodic index used for finding periodic boundary neighbors
Definition: CA_utils.cpp:54
A base CellularAutomata class that contains non-templated member variables and method definitions fro...
Definition: CAdatatypes.h:101
int axis1_dim
count of cells in first dimension
Definition: CAdatatypes.h:108
BaseCellularAutomata()
Construct a new Cellular Automata:: Cellular Automata object.
CAEnums::Rule rule_type
enum code for rule type
Definition: CAdatatypes.h:107
int setup_cell_states(int num_states)
Defines the range of cell states to be used in the CA object.
int num_states
integer code for number of states
Definition: CAdatatypes.h:106
int axis2_dim
count of cells in second dimension
Definition: CAdatatypes.h:109
int boundary_radius
declare a radius for the boundary
Definition: CAdatatypes.h:104
int setup_rule(CAEnums::Rule rule_type)
Setup the rule choice to specify the rule type to be used in CA object.
int axis3_dim
count of cells in third dimension
Definition: CAdatatypes.h:110
CAEnums::Boundary boundary_type
enum code to hold boundary
Definition: CAdatatypes.h:103
CAEnums::Neighborhood neighborhood_type
enum code to hold neighborhood type
Definition: CAdatatypes.h:105
void print_error_status(CAEnums::ErrorCode error)
Prints an error message for the given error code.
int setup_neighborhood(CAEnums::Neighborhood neighborhood_type)
Setup neighborhood with values from enum neighborhood.
virtual ~BaseCellularAutomata()
Destroy the Cellular Automata:: Cellular Automata object.
Definition: CAdatatypes.h:124
A CellularAutomata class for simulating cellular automata models.
Definition: CAdatatypes.h:176
T *** get_next_tensor()
Get the next state tensor cell grid.
Definition: CAdatatypes.h:851
int init_condition(int x_state, double prob)
Initializes the first state of the grid using random numbers.
Definition: CAdatatypes.h:1118
T *** get_tensor()
Get the tensor cell grid.
Definition: CAdatatypes.h:841
T ** get_matrix()
Get the matrix cell grid.
Definition: CAdatatypes.h:821
int setup_dimensions_1d(int axis1_dim, int fill_value=0)
Set up 1d array of cell states.
Definition: CAdatatypes.h:974
int step()
Simulates a cellular automata step.
Definition: CAdatatypes.h:1337
int print_grid()
Print the current state of the grid.
Definition: CAdatatypes.h:1349
int setup_dimensions_2d(int axis1_dim, int axis2_dim, int fill_value=0)
Set up 2d matrix of cell states.
Definition: CAdatatypes.h:1012
T * get_next_vector()
Get the next state vector cell grid.
Definition: CAdatatypes.h:811
int setup_boundary(CAEnums::Boundary bound_type, int radius)
Setup boundary with enum values from boundary and set the boundary radius.
Definition: CAdatatypes.h:866
int setup_dimensions_3d(int axis1_dim, int axis2_dim, int axis3_dim, int fill_value=0)
Set up 3d tensor of cell states.
Definition: CAdatatypes.h:1061
static int get_neighborhood_size(int rank, int radius, CAEnums::Neighborhood neighborhood_type)
calculates the neighborhood size using the rank, radius and neighborhood type
Definition: CAdatatypes.h:1400
static void initialize_majority_rule_counter(MajorityCounter &counter, int num_states)
initializes a MajorityCounter instance utilized by Majority rule
Definition: CAdatatypes.h:1418
T * get_vector()
Get the vector cell grid.
Definition: CAdatatypes.h:801
int step(void(custom_rule)(int *, int, T *, int, T &))
Simulates a cellular automata step.
Definition: CAdatatypes.h:1192
~CellularAutomata()
Destroy the Cellular Automata object.
Definition: CAdatatypes.h:920
CellularAutomata()
Construct a new Cellular Automata object.
Definition: CAdatatypes.h:904
T ** get_next_matrix()
Get the next state matrix cell grid.
Definition: CAdatatypes.h:831
Enum namespace that contains various enum definitions used by CellularAutomata.
Definition: CAdatatypes.h:36
Neighborhood
enum containing the different type of neighborhoods the CellularAutomata class supports
Definition: CAdatatypes.h:43
Rule
enum containing the different type of rules the CellularAutomata class supports for it's transitions
Definition: CAdatatypes.h:66
ErrorCode
enum containing the various error codes the CellularAutomata class can return
Definition: CAdatatypes.h:78
Boundary
enum containing the different type of boundaries the CellularAutomata class supports
Definition: CAdatatypes.h:54
void custom_rule(int *cell_index, const int index_size, int *neighborhood_cells, const int neighborhood_size, int &new_cell_state)
Test custom rule function for setting a new cell state for the cell at cell_index.
Definition: test_CA.cpp:23