diff --git a/PyCTBN/PyCTBN/cache.py b/PyCTBN/PyCTBN/cache.py index 97aa1a1..eea1013 100644 --- a/PyCTBN/PyCTBN/cache.py +++ b/PyCTBN/PyCTBN/cache.py @@ -4,7 +4,7 @@ import typing from .set_of_cims import SetOfCims -class Cache: +class Cache(object): """This class acts as a cache of ``SetOfCims`` objects for a node. :_list_of_sets_of_parents: a list of ``Sets`` objects of the parents to which the cim in cache at SAME @@ -51,4 +51,4 @@ class Cache: """Clear the contents both of ``_actual_cache`` and ``_list_of_sets_of_parents``. """ del self._list_of_sets_of_parents[:] - del self._actual_cache[:] \ No newline at end of file + del self._actual_cache[:] diff --git a/PyCTBN/PyCTBN/conditional_intensity_matrix.py b/PyCTBN/PyCTBN/conditional_intensity_matrix.py index 96a3ae2..4abfdd0 100644 --- a/PyCTBN/PyCTBN/conditional_intensity_matrix.py +++ b/PyCTBN/PyCTBN/conditional_intensity_matrix.py @@ -1,7 +1,7 @@ import numpy as np -class ConditionalIntensityMatrix: +class ConditionalIntensityMatrix(object): """Abstracts the Conditional Intesity matrix of a node as aggregation of the state residence times vector and state transition matrix and the actual CIM matrix. diff --git a/PyCTBN/PyCTBN/network_graph.py b/PyCTBN/PyCTBN/network_graph.py index 24d01c0..a18658f 100644 --- a/PyCTBN/PyCTBN/network_graph.py +++ b/PyCTBN/PyCTBN/network_graph.py @@ -6,7 +6,7 @@ import numpy as np from .structure import Structure -class NetworkGraph: +class NetworkGraph(object): """Abstracts the infos contained in the Structure class in the form of a directed graph. Has the task of creating all the necessary filtering and indexing structures for parameters estimation @@ -47,14 +47,16 @@ class NetworkGraph: self._aggregated_info_about_nodes_parents = self.get_ordered_by_indx_set_of_parents(node_id) p_indxs = self._aggregated_info_about_nodes_parents[1] p_vals = self._aggregated_info_about_nodes_parents[2] - self._time_scalar_indexing_structure = self.build_time_scalar_indexing_structure_for_a_node(node_id, - p_vals) - self._transition_scalar_indexing_structure = self.build_transition_scalar_indexing_structure_for_a_node(node_id, - p_vals) + node_states = self.get_states_number(node_id) node_indx = self.get_node_indx(node_id) - self._time_filtering = self.build_time_columns_filtering_for_a_node(node_indx, p_indxs) - self._transition_filtering = self.build_transition_filtering_for_a_node(node_indx, p_indxs) - self._p_combs_structure = self.build_p_comb_structure_for_a_node(p_vals) + cols_number = self._graph_struct.total_variables_number + self._time_scalar_indexing_structure = NetworkGraph.\ + build_time_scalar_indexing_structure_for_a_node(node_states, p_vals) + self._transition_scalar_indexing_structure = NetworkGraph.\ + build_transition_scalar_indexing_structure_for_a_node(node_states, p_vals) + self._time_filtering = NetworkGraph.build_time_columns_filtering_for_a_node(node_indx, p_indxs) + self._transition_filtering = NetworkGraph.build_transition_filtering_for_a_node(node_indx, p_indxs, cols_number) + self._p_combs_structure = NetworkGraph.build_p_comb_structure_for_a_node(p_vals) def add_nodes(self, list_of_nodes: typing.List) -> None: """Adds the nodes to the ``_graph`` contained in the list of nodes ``list_of_nodes``. @@ -112,42 +114,45 @@ class NetworkGraph: get_node_indx = self.get_node_indx p_indxes = [get_node_indx(node) for node in sorted_parents] p_values = [self.get_states_number(node) for node in sorted_parents] - return (sorted_parents, p_indxes, p_values) + return sorted_parents, p_indxes, p_values - def build_time_scalar_indexing_structure_for_a_node(self, node_id: str, parents_vals: typing.List) -> np.ndarray: + @staticmethod + def build_time_scalar_indexing_structure_for_a_node(node_states: int, + parents_vals: typing.List) -> np.ndarray: """Builds an indexing structure for the computation of state residence times values. - :param node_id: the node label - :type node_id: string + :param node_states: the node cardinality + :type node_states: int :param parents_vals: the caridinalites of the node's parents :type parents_vals: List :return: The time indexing structure :rtype: numpy.ndArray """ - T_vector = np.array([self.get_states_number(node_id)]) + T_vector = np.array([node_states]) T_vector = np.append(T_vector, parents_vals) T_vector = T_vector.cumprod().astype(np.int) return T_vector - def build_transition_scalar_indexing_structure_for_a_node(self, node_id: str, parents_vals: typing.List) \ + @staticmethod + def build_transition_scalar_indexing_structure_for_a_node(node_states_number: int, parents_vals: typing.List) \ -> np.ndarray: """Builds an indexing structure for the computation of state transitions values. - :param node_id: the node label - :type node_id: string + :param node_states_number: the node cardinality + :type node_states_number: int :param parents_vals: the caridinalites of the node's parents :type parents_vals: List :return: The transition indexing structure :rtype: numpy.ndArray """ - node_states_number = self.get_states_number(node_id) M_vector = np.array([node_states_number, node_states_number]) M_vector = np.append(M_vector, parents_vals) M_vector = M_vector.cumprod().astype(np.int) return M_vector - def build_time_columns_filtering_for_a_node(self, node_indx: int, p_indxs: typing.List) -> np.ndarray: + @staticmethod + def build_time_columns_filtering_for_a_node(node_indx: int, p_indxs: typing.List) -> np.ndarray: """ Builds the necessary structure to filter the desired columns indicated by ``node_indx`` and ``p_indxs`` in the dataset. @@ -161,7 +166,9 @@ class NetworkGraph: """ return np.append(np.array([node_indx], dtype=np.int), p_indxs).astype(np.int) - def build_transition_filtering_for_a_node(self, node_indx: int, p_indxs: typing.List) -> np.ndarray: + @staticmethod + def build_transition_filtering_for_a_node(node_indx: int, p_indxs: typing.List, nodes_number: int) \ + -> np.ndarray: """Builds the necessary structure to filter the desired columns indicated by ``node_indx`` and ``p_indxs`` in the dataset. This structure will be used in the computation of the state transitions values. @@ -169,13 +176,15 @@ class NetworkGraph: :type node_indx: int :param p_indxs: the indexes of the node's parents :type p_indxs: List + :param nodes_number: the total number of nodes in the dataset + :type nodes_number: int :return: The filtering structure for transitions estimation :rtype: numpy.ndArray """ - nodes_number = self._graph_struct.total_variables_number return np.array([node_indx + nodes_number, node_indx, *p_indxs], dtype=np.int) - def build_p_comb_structure_for_a_node(self, parents_values: typing.List) -> np.ndarray: + @staticmethod + def build_p_comb_structure_for_a_node(parents_values: typing.List) -> np.ndarray: """ Builds the combinatorial structure that contains the combinations of all the values contained in ``parents_values``. diff --git a/PyCTBN/PyCTBN/parameters_estimator.py b/PyCTBN/PyCTBN/parameters_estimator.py index a2d9140..01254e2 100644 --- a/PyCTBN/PyCTBN/parameters_estimator.py +++ b/PyCTBN/PyCTBN/parameters_estimator.py @@ -6,7 +6,7 @@ from .set_of_cims import SetOfCims from .network_graph import NetworkGraph -class ParametersEstimator: +class ParametersEstimator(object): """Has the task of computing the cims of particular node given the trajectories and the net structure in the graph ``_net_graph``. @@ -45,7 +45,7 @@ class ParametersEstimator: node_indx = self._net_graph.get_node_indx(node_id) state_res_times = self._single_set_of_cims._state_residence_times transition_matrices = self._single_set_of_cims._transition_matrices - ParametersEstimator.compute_state_res_time_for_node(node_indx, self._trajectories.times, + ParametersEstimator.compute_state_res_time_for_node(self._trajectories.times, self._trajectories.trajectory, self._net_graph.time_filtering, self._net_graph.time_scalar_indexing_strucure, @@ -58,7 +58,7 @@ class ParametersEstimator: return self._single_set_of_cims @staticmethod - def compute_state_res_time_for_node(node_indx: int, times: np.ndarray, trajectory: np.ndarray, + def compute_state_res_time_for_node(times: np.ndarray, trajectory: np.ndarray, cols_filter: np.ndarray, scalar_indexes_struct: np.ndarray, T: np.ndarray) -> None: """Compute the state residence times for a node and fill the matrix ``T`` with the results @@ -100,8 +100,8 @@ class ParametersEstimator: diag_indices = np.array([x * M.shape[1] + x % M.shape[1] for x in range(M.shape[0] * M.shape[1])], dtype=np.int64) trj_tmp = trajectory[trajectory[:, int(trajectory.shape[1] / 2) + node_indx].astype(np.int) >= 0] - M[:] = np.bincount(np.sum(trj_tmp[:, cols_filter] * scalar_indexing / scalar_indexing[0], axis=1).astype(np.int), - minlength=scalar_indexing[-1]).reshape(-1, M.shape[1], M.shape[2]) + M[:] = np.bincount(np.sum(trj_tmp[:, cols_filter] * scalar_indexing / scalar_indexing[0], axis=1).astype(np.int) + , minlength=scalar_indexing[-1]).reshape(-1, M.shape[1], M.shape[2]) M_raveled = M.ravel() M_raveled[diag_indices] = 0 M_raveled[diag_indices] = np.sum(M, axis=2).ravel() diff --git a/PyCTBN/PyCTBN/sample_path.py b/PyCTBN/PyCTBN/sample_path.py index 6f32cf8..2fc8c1f 100644 --- a/PyCTBN/PyCTBN/sample_path.py +++ b/PyCTBN/PyCTBN/sample_path.py @@ -4,7 +4,7 @@ from .structure import Structure from .trajectory import Trajectory -class SamplePath: +class SamplePath(object): """Aggregates all the informations about the trajectories, the real structure of the sampled net and variables cardinalites. Has the task of creating the objects ``Trajectory`` and ``Structure`` that will contain the mentioned data. diff --git a/PyCTBN/PyCTBN/set_of_cims.py b/PyCTBN/PyCTBN/set_of_cims.py index bbab975..7bb89f9 100644 --- a/PyCTBN/PyCTBN/set_of_cims.py +++ b/PyCTBN/PyCTBN/set_of_cims.py @@ -4,7 +4,7 @@ import numpy as np from .conditional_intensity_matrix import ConditionalIntensityMatrix -class SetOfCims: +class SetOfCims(object): """Aggregates all the CIMS of the node identified by the label _node_id. :param node_id: the node label diff --git a/PyCTBN/PyCTBN/structure.py b/PyCTBN/PyCTBN/structure.py index 4d31f19..7e39277 100644 --- a/PyCTBN/PyCTBN/structure.py +++ b/PyCTBN/PyCTBN/structure.py @@ -2,7 +2,7 @@ import typing as ty import numpy as np -class Structure: +class Structure(object): """Contains all the infos about the network structure(nodes labels, nodes caridinalites, edges, indexes) :param nodes_labels_list: the symbolic names of the variables @@ -105,5 +105,5 @@ class Structure: np.array_equal(self._nodes_indexes_arr, other._nodes_indexes_arr) and \ self._edges_list == other._edges_list - return NotImplemented + return False diff --git a/PyCTBN/PyCTBN/structure_estimator.py b/PyCTBN/PyCTBN/structure_estimator.py index ffa030b..5203f08 100644 --- a/PyCTBN/PyCTBN/structure_estimator.py +++ b/PyCTBN/PyCTBN/structure_estimator.py @@ -17,7 +17,7 @@ from .sample_path import SamplePath from .structure import Structure -class StructureEstimator: +class StructureEstimator(object): """Has the task of estimating the network structure given the trajectories in ``samplepath``. :param sample_path: the _sample_path object containing the trajectories and the real structure @@ -40,12 +40,13 @@ class StructureEstimator: self._nodes = np.array(self._sample_path.structure.nodes_labels) self._nodes_vals = self._sample_path.structure.nodes_values self._nodes_indxs = self._sample_path.structure.nodes_indexes - self._complete_graph = self.build_complete_graph(self._sample_path.structure.nodes_labels) + self._complete_graph = StructureEstimator.build_complete_graph(self._sample_path.structure.nodes_labels) self._exp_test_sign = exp_test_alfa self._chi_test_alfa = chi_test_alfa self._cache = Cache() - def build_complete_graph(self, node_ids: typing.List) -> nx.DiGraph: + @staticmethod + def build_complete_graph(node_ids: typing.List) -> nx.DiGraph: """Builds a complete directed graph (no self loops) given the nodes labels in the list ``node_ids``: :param node_ids: the list of nodes labels @@ -176,7 +177,7 @@ class StructureEstimator: parent_indx = 0 while parent_indx < len(u): removed = False - S = self.generate_possible_sub_sets_of_size(u, b, u[parent_indx]) + S = StructureEstimator.generate_possible_sub_sets_of_size(u, b, u[parent_indx]) test_parent = u[parent_indx] for parents_set in S: if self.complete_test(test_parent, var_id, parents_set, child_states_numb, tot_vars_count): @@ -189,7 +190,8 @@ class StructureEstimator: b += 1 self._cache.clear() - def generate_possible_sub_sets_of_size(self, u: typing.List, size: int, parent_label: str) -> \ + @staticmethod + def generate_possible_sub_sets_of_size(u: typing.List, size: int, parent_label: str) -> \ typing.Iterator: """Creates a list containing all possible subsets of the list ``u`` of size ``size``, that do not contains a the node identified by ``parent_label``. @@ -219,9 +221,12 @@ class StructureEstimator: The file is named as the input dataset but the `results_` word is appended to the results file. """ res = json_graph.node_link_data(self._complete_graph) - name = self._sample_path._importer.file_path.rsplit('/', 1)[-1] + str(self._sample_path._importer.dataset_id()) - name = 'results_' + name - with open(name, 'w') as f: + name = self._sample_path._importer.file_path.rsplit('/', 1)[-1] + name = name.split('.', 1)[0] + name += '_' + str(self._sample_path._importer.dataset_id()) + name += '.json' + file_name = 'results_' + name + with open(file_name, 'w') as f: json.dump(res, f) def adjacency_matrix(self) -> np.ndarray: diff --git a/PyCTBN/PyCTBN/trajectory.py b/PyCTBN/PyCTBN/trajectory.py index ae3ff93..1254016 100644 --- a/PyCTBN/PyCTBN/trajectory.py +++ b/PyCTBN/PyCTBN/trajectory.py @@ -3,9 +3,9 @@ import numpy as np import typing -class Trajectory: - """ Abstracts the infos about a complete set of trajectories, represented as a numpy array of doubles (the time deltas) - and a numpy matrix of ints (the changes of states). +class Trajectory(object): + """ Abstracts the infos about a complete set of trajectories, represented as a numpy array of doubles + (the time deltas) and a numpy matrix of ints (the changes of states). :param list_of_columns: the list containing the times array and values matrix :type list_of_columns: List diff --git a/PyCTBN/tests/coverage.xml b/PyCTBN/tests/coverage.xml deleted file mode 100644 index cef006f..0000000 --- a/PyCTBN/tests/coverage.xml +++ /dev/null @@ -1,963 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/PyCTBN/tests/performance_comparisons.py b/PyCTBN/tests/performance_comparisons.py index 8185644..622ca20 100644 --- a/PyCTBN/tests/performance_comparisons.py +++ b/PyCTBN/tests/performance_comparisons.py @@ -4,6 +4,7 @@ import glob import numpy as np import pandas as pd import timeit +import psutil from ..PyCTBN.sample_path import SamplePath from ..PyCTBN.structure_estimator import StructureEstimator @@ -23,6 +24,7 @@ class PerformanceComparisons(unittest.TestCase): cls.original_times = [] cls.optimized_times = [] cls.results = [] + cls.memory_usages = [] def test_time_comparisons(self): for file_path in self.read_files: @@ -48,6 +50,17 @@ class PerformanceComparisons(unittest.TestCase): self.original_times[:] = [] self.optimized_times[:] = [] + def test_memory_usage(self): + for file_path in self.read_files: + self.importer = JsonImporter(file_path, 'samples', 'dyn.str', 'variables', 'Time', 'Name') + self.aux_build_importer(0) + se1 = StructureEstimator(self.s1, 0.1, 0.1) + se1.ctpc_algorithm() + current_process = psutil.Process(os.getpid()) + mem = current_process.memory_info().rss + self.memory_usages.append((mem / 10 ** 6)) + self.save_memory_usage_data(self.memory_usages) + def aux_build_importer(self, indx): self.importer.import_data(indx) self.s1 = SamplePath(self.importer) @@ -66,7 +79,17 @@ class PerformanceComparisons(unittest.TestCase): name = name.split('.', 1)[0] name = 'execution_times_' + name + '.csv' path = os.path.abspath('./results/') - print(path) + file_dest = path + '/' + name + df_results.to_csv(file_dest, index=False) + + def save_memory_usage_data(self, data): + if not os.path.exists('memory_results'): + os.makedirs('memory_results') + df_results = pd.DataFrame({'memory_usage': data}) + name = self.importer.file_path.rsplit('/', 1)[-1] + name = name.split('.', 1)[0] + name = 'memory_usage_' + name + '.csv' + path = os.path.abspath('./memory_results/') file_dest = path + '/' + name df_results.to_csv(file_dest, index=False) diff --git a/PyCTBN/tests/test_json_importer.py b/PyCTBN/tests/test_json_importer.py index 4bbbe6d..2ac1baa 100644 --- a/PyCTBN/tests/test_json_importer.py +++ b/PyCTBN/tests/test_json_importer.py @@ -39,20 +39,22 @@ class TestJsonImporter(unittest.TestCase): path = os.getcwd() path = path + '/data.json' j1 = JsonImporter(path, '', '', '', '', '') - #imported_data = j1.read_json_file() self.assertTrue(self.ordered(data_set) == self.ordered(j1._raw_data)) os.remove('data.json') def test_read_json_file_not_found(self): path = os.getcwd() path = path + '/data.json' - #j1 = JsonImporter(path, '', '', '', '', '') self.assertRaises(FileNotFoundError, JsonImporter, path, '', '', '', '', '') + def test_build_sorter(self): + j1 = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name') + df_samples_list = j1.normalize_trajectories(j1._raw_data, 0, j1._samples_label) + sorter = j1.build_sorter(df_samples_list[0]) + self.assertListEqual(sorter, list(df_samples_list[0].columns.values)[1:]) + def test_normalize_trajectories(self): j1 = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name') - #raw_data = j1.read_json_file() - #print(raw_data) df_samples_list = j1.normalize_trajectories(j1._raw_data, 0, j1._samples_label) self.assertEqual(len(df_samples_list), len(j1._raw_data[0][j1._samples_label])) @@ -66,7 +68,6 @@ class TestJsonImporter(unittest.TestCase): def test_compute_row_delta_single_samples_frame(self): j1 = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name') - #raw_data = j1.read_json_file() j1._array_indx = 0 j1._df_samples_list = j1.import_trajectories(j1._raw_data) sample_frame = j1._df_samples_list[0] @@ -89,7 +90,6 @@ class TestJsonImporter(unittest.TestCase): def test_compute_row_delta_in_all_frames(self): j1 = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name') - #raw_data = j1.read_json_file() j1._array_indx = 0 j1._df_samples_list = j1.import_trajectories(j1._raw_data) j1._sorter = j1.build_sorter(j1._df_samples_list[0]) @@ -98,9 +98,14 @@ class TestJsonImporter(unittest.TestCase): list(j1.concatenated_samples.columns.values)[:len(list(j1._df_samples_list[0].columns.values))]) self.assertEqual(list(j1.concatenated_samples.columns.values)[0], j1._time_key) + def test_compute_row_delta_in_all_frames_not_init_sorter(self): + j1 = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name') + j1._array_indx = 0 + j1._df_samples_list = j1.import_trajectories(j1._raw_data) + self.assertRaises(RuntimeError, j1.compute_row_delta_in_all_samples_frames, j1._df_samples_list) + def test_clear_data_frame_list(self): j1 = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name') - #raw_data = j1.read_json_file() j1._array_indx = 0 j1._df_samples_list = j1.import_trajectories(j1._raw_data) j1._sorter = j1.build_sorter(j1._df_samples_list[0]) @@ -145,7 +150,6 @@ class TestJsonImporter(unittest.TestCase): raw_data = [{"dyn.str":[{"From":"X","To":"Z"},{"From":"Y","To":"Z"},{"From":"Z","To":"Y"}]}] j1._array_indx = 0 df_struct = j1.import_structure(raw_data) - #print(raw_data[0]['dyn.str'][0].items()) self.assertIsInstance(df_struct, pd.DataFrame) def test_import_sampled_cims(self): @@ -155,9 +159,18 @@ class TestJsonImporter(unittest.TestCase): j1._df_samples_list = j1.import_trajectories(raw_data) j1._sorter = j1.build_sorter(j1._df_samples_list[0]) cims = j1.import_sampled_cims(raw_data, 0, 'dyn.cims') - #j1.import_variables(raw_data, j1.sorter) self.assertEqual(list(cims.keys()), j1.sorter) + def test_dataset_id(self): + j1 = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name') + array_indx = 0 + j1.import_data(array_indx) + self.assertEqual(array_indx, j1.dataset_id()) + + def test_file_path(self): + j1 = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name') + self.assertEqual(j1.file_path, self.read_files[0]) + def test_import_data(self): j1 = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name') j1.import_data(0) diff --git a/PyCTBN/tests/test_networkgraph.py b/PyCTBN/tests/test_networkgraph.py index db1f727..f9794a4 100644 --- a/PyCTBN/tests/test_networkgraph.py +++ b/PyCTBN/tests/test_networkgraph.py @@ -78,7 +78,8 @@ class TestNetworkGraph(unittest.TestCase): aggr_info[0], aggr_info[2]) def aux_build_time_scalar_indexing_structure_for_a_node(self, graph, node_id, parents_indxs, parents_labels, parents_vals): - time_scalar_indexing = graph.build_time_scalar_indexing_structure_for_a_node(node_id, parents_vals) + node_states = graph.get_states_number(node_id) + time_scalar_indexing = NetworkGraph.build_time_scalar_indexing_structure_for_a_node(node_states, parents_vals) self.assertEqual(len(time_scalar_indexing), len(parents_indxs) + 1) merged_list = parents_labels[:] merged_list.insert(0, node_id) @@ -100,7 +101,8 @@ class TestNetworkGraph(unittest.TestCase): def aux_build_transition_scalar_indexing_structure_for_a_node(self, graph, node_id, parents_indxs, parents_labels, parents_values): - transition_scalar_indexing = graph.build_transition_scalar_indexing_structure_for_a_node(node_id, + node_states = graph.get_states_number(node_id) + transition_scalar_indexing = graph.build_transition_scalar_indexing_structure_for_a_node(node_states, parents_values) self.assertEqual(len(transition_scalar_indexing), len(parents_indxs) + 2) merged_list = parents_labels[:] diff --git a/PyCTBN/tests/test_parameters_estimator.py b/PyCTBN/tests/test_parameters_estimator.py index 44a9059..38994b9 100644 --- a/PyCTBN/tests/test_parameters_estimator.py +++ b/PyCTBN/tests/test_parameters_estimator.py @@ -55,7 +55,7 @@ class TestParametersEstimatior(unittest.TestCase): def cim_equality_test(self, cim1, cim2): for r1, r2 in zip(cim1, cim2): - self.assertTrue(np.all(np.isclose(r1, r2, 1e-01, 1e-01) == True)) + self.assertTrue(np.all(np.isclose(r1, r2, 1e-01, 1e-01) is True)) def aux_import_sampled_cims(self, cims_label): i1 = JsonImporter(self.read_files[0], '', '', '', '', '') diff --git a/PyCTBN/tests/test_sample_path.py b/PyCTBN/tests/test_sample_path.py index c372781..4286bac 100644 --- a/PyCTBN/tests/test_sample_path.py +++ b/PyCTBN/tests/test_sample_path.py @@ -2,6 +2,7 @@ import unittest import glob import os +import random from ..PyCTBN.json_importer import JsonImporter from ..PyCTBN.sample_path import SamplePath @@ -19,6 +20,12 @@ class TestSamplePath(unittest.TestCase): importer = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name') self.assertRaises(RuntimeError, SamplePath, importer) + def test_init_not_filled_dataframse(self): + importer = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name') + importer.import_data(0) + importer.clear_concatenated_frame() + self.assertRaises(RuntimeError, SamplePath, importer) + def test_init(self): importer = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name') importer.import_data(0) @@ -43,6 +50,13 @@ class TestSamplePath(unittest.TestCase): self.assertIsInstance(s1.structure, Structure) self.assertEqual(s1._total_variables_count, len(s1._importer.sorter)) + def test_build_structure_bad_sorter(self): + importer = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name') + importer.import_data(0) + s1 = SamplePath(importer) + random.shuffle(importer._sorter) + self.assertRaises(RuntimeError, s1.build_structure) + if __name__ == '__main__': unittest.main() diff --git a/PyCTBN/tests/test_structure_estimator.py b/PyCTBN/tests/test_structure_estimator.py index fe2e140..e3d63d7 100644 --- a/PyCTBN/tests/test_structure_estimator.py +++ b/PyCTBN/tests/test_structure_estimator.py @@ -3,11 +3,9 @@ import glob import math import os import unittest - +import json import networkx as nx import numpy as np -import psutil -from line_profiler import LineProfiler import timeit from ..PyCTBN.cache import Cache @@ -61,8 +59,8 @@ class TestStructureEstimator(unittest.TestCase): for node in self.s1.structure.nodes_labels: for b in range(nodes_numb): - sets = se1.generate_possible_sub_sets_of_size(self.s1.structure.nodes_labels, b, node) - sets2 = se1.generate_possible_sub_sets_of_size(self.s1.structure.nodes_labels, b, node) + sets = StructureEstimator.generate_possible_sub_sets_of_size(self.s1.structure.nodes_labels, b, node) + sets2 = StructureEstimator.generate_possible_sub_sets_of_size(self.s1.structure.nodes_labels, b, node) self.assertEqual(len(list(sets)), math.floor(math.factorial(nodes_numb - 1) / (math.factorial(b)*math.factorial(nodes_numb -1 - b)))) for sset in sets2: @@ -70,17 +68,8 @@ class TestStructureEstimator(unittest.TestCase): def test_time(self): se1 = StructureEstimator(self.s1, 0.1, 0.1) - lp = LineProfiler() - #lp.add_function(se1.complete_test) - #lp.add_function(se1.one_iteration_of_CTPC_algorithm) - #lp.add_function(se1.independence_test) - lp_wrapper = lp(se1.ctpc_algorithm) - lp_wrapper() - lp.print_stats() - #print("Last time", lp.dump_stats()) - #print("Exec Time", timeit.timeit(se1.ctpc_algorithm, number=1)) - print(se1._complete_graph.edges) - print(self.s1.structure.edges) + exec_time = timeit.timeit(se1.ctpc_algorithm, number=1) + print("Execution Time: ", exec_time) for ed in self.s1.structure.edges: self.assertIn(tuple(ed), se1._complete_graph.edges) tuples_edges = [tuple(rec) for rec in self.s1.structure.edges] @@ -89,15 +78,27 @@ class TestStructureEstimator(unittest.TestCase): if not(ed in tuples_edges): spurious_edges.append(ed) print("Spurious Edges:",spurious_edges) - print("Adj Matrix:", nx.adj_matrix(se1._complete_graph).toarray().astype(bool)) - #se1.save_results() - def test_memory(self): + def test_save_results(self): + se1 = StructureEstimator(self.s1, 0.1, 0.1) + se1.ctpc_algorithm() + se1.save_results() + name = self.s1._importer.file_path.rsplit('/', 1)[-1] + name = name.split('.', 1)[0] + name += '_' + str(self.s1._importer.dataset_id()) + name += '.json' + file_name = 'results_' + name + with open(file_name) as f: + js_graph = json.load(f) + result_graph = nx.json_graph.node_link_graph(js_graph) + self.assertFalse(nx.difference(se1._complete_graph, result_graph).edges) + os.remove(file_name) + + def test_adjacency_matrix(self): se1 = StructureEstimator(self.s1, 0.1, 0.1) se1.ctpc_algorithm() - current_process = psutil.Process(os.getpid()) - mem = current_process.memory_info().rss - print("Average Memory Usage in MB:", mem / 10**6) + adj_matrix = nx.adj_matrix(se1._complete_graph).toarray().astype(bool) + self.assertTrue(np.array_equal(adj_matrix, se1.adjacency_matrix())) if __name__ == '__main__': diff --git a/coverage.xml b/coverage.xml new file mode 100644 index 0000000..81c41d6 --- /dev/null +++ b/coverage.xml @@ -0,0 +1,660 @@ + + + + + + /Users/Zalum/Desktop/Tesi/PyCTBN + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +