diff --git a/.coverage b/.coverage
new file mode 100644
index 0000000..4272673
Binary files /dev/null and b/.coverage differ
diff --git a/.coveragerc b/.coveragerc
new file mode 100644
index 0000000..fb1b0bf
--- /dev/null
+++ b/.coveragerc
@@ -0,0 +1,3 @@
+[run]
+omit =
+ */tests/*
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 3e16c78..30c8ca0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,4 +5,5 @@ __pycache__
**/PyCTBN.egg-info
**/dist
**/results_data
-**/.scannerwork
\ No newline at end of file
+**/.scannerwork
+**/build
\ No newline at end of file
diff --git a/CTBN_Diagramma_Dominio.pdf b/CTBN_Diagramma_Dominio.pdf
new file mode 100644
index 0000000..e6e1c83
Binary files /dev/null and b/CTBN_Diagramma_Dominio.pdf differ
diff --git a/CTBN_project_dominio.pdf b/CTBN_project_dominio.pdf
deleted file mode 100644
index 6bceea1..0000000
Binary files a/CTBN_project_dominio.pdf and /dev/null differ
diff --git a/PyCTBN/PyCTBN/__init__.py b/PyCTBN/PyCTBN/__init__.py
index 023c0f1..faff79c 100644
--- a/PyCTBN/PyCTBN/__init__.py
+++ b/PyCTBN/PyCTBN/__init__.py
@@ -1,8 +1,8 @@
-import PyCTBN.estimators
-from PyCTBN.estimators import *
-import PyCTBN.optimizers
-from PyCTBN.optimizers import *
-import PyCTBN.structure_graph
-from PyCTBN.structure_graph import *
-import PyCTBN.utility
-from PyCTBN.utility import *
\ No newline at end of file
+import PyCTBN.PyCTBN.estimators
+from PyCTBN.PyCTBN.estimators import *
+import PyCTBN.PyCTBN.optimizers
+from PyCTBN.PyCTBN.optimizers import *
+import PyCTBN.PyCTBN.structure_graph
+from PyCTBN.PyCTBN.structure_graph import *
+import PyCTBN.PyCTBN.utility
+from PyCTBN.PyCTBN.utility import *
\ No newline at end of file
diff --git a/PyCTBN/PyCTBN/estimators/parameters_estimator.py b/PyCTBN/PyCTBN/estimators/parameters_estimator.py
index 4754d58..6b6883b 100644
--- a/PyCTBN/PyCTBN/estimators/parameters_estimator.py
+++ b/PyCTBN/PyCTBN/estimators/parameters_estimator.py
@@ -107,32 +107,6 @@ class ParametersEstimator(object):
M_raveled[diag_indices] = 0
M_raveled[diag_indices] = np.sum(M, axis=2).ravel()
- def init_sets_cims_container(self):
- self.sets_of_cims_struct = acims.SetsOfCimsContainer(self.net_graph.nodes,
- self.net_graph.nodes_values,
- self.net_graph.get_ordered_by_indx_parents_values_for_all_nodes(),
- self.net_graph.p_combs)
-
- def compute_parameters(self):
- #print(self.net_graph.get_nodes())
- #print(self.amalgamated_cims_struct.sets_of_cims)
- #enumerate(zip(self.net_graph.get_nodes(), self.amalgamated_cims_struct.sets_of_cims))
- for indx, aggr in enumerate(zip(self.net_graph.nodes, self.sets_of_cims_struct.sets_of_cims)):
- #print(self.net_graph.time_filtering[indx])
- #print(self.net_graph.time_scalar_indexing_strucure[indx])
- self.compute_state_res_time_for_node(self.net_graph.get_node_indx(aggr[0]), self.sample_path.trajectories.times,
- self.sample_path.trajectories.trajectory,
- self.net_graph.time_filtering[indx],
- self.net_graph.time_scalar_indexing_strucure[indx],
- aggr[1]._state_residence_times)
- #print(self.net_graph.transition_filtering[indx])
- #print(self.net_graph.transition_scalar_indexing_structure[indx])
- self.compute_state_transitions_for_a_node(self.net_graph.get_node_indx(aggr[0]),
- self.sample_path.trajectories.complete_trajectory,
- self.net_graph.transition_filtering[indx],
- self.net_graph.transition_scalar_indexing_structure[indx],
- aggr[1]._transition_matrices)
- aggr[1].build_cims(aggr[1]._state_residence_times, aggr[1]._transition_matrices)
diff --git a/PyCTBN/PyCTBN/estimators/structure_constraint_based_estimator.py b/PyCTBN/PyCTBN/estimators/structure_constraint_based_estimator.py
index 7d5721e..822427c 100644
--- a/PyCTBN/PyCTBN/estimators/structure_constraint_based_estimator.py
+++ b/PyCTBN/PyCTBN/estimators/structure_constraint_based_estimator.py
@@ -226,8 +226,13 @@ class StructureConstraintBasedEstimator(StructureEstimator):
self._nodes,
total_vars_numb_array)
#list_edges_partial = [ctpc_algo(n,total_vars_numb) for n in self._nodes]
+
+ 'Update the graph'
+ edges = set(itertools.chain.from_iterable(list_edges_partial))
+ self._complete_graph = nx.DiGraph()
+ self._complete_graph.add_edges_from(edges)
- return set(itertools.chain.from_iterable(list_edges_partial))
+ return edges
def estimate_structure(self,disable_multiprocessing:bool=False):
diff --git a/PyCTBN/PyCTBN/estimators/structure_estimator.py b/PyCTBN/PyCTBN/estimators/structure_estimator.py
index fbf8ea9..19e64b0 100644
--- a/PyCTBN/PyCTBN/estimators/structure_estimator.py
+++ b/PyCTBN/PyCTBN/estimators/structure_estimator.py
@@ -9,7 +9,7 @@ import numpy as np
from networkx.readwrite import json_graph
from abc import ABC
-
+import os
import abc
from ..utility.cache import Cache
@@ -104,11 +104,11 @@ class StructureEstimator(object):
json.dump(res, f)
- def remove_diagonal_elements(self, matrix):
- m = matrix.shape[0]
- strided = np.lib.stride_tricks.as_strided
- s0, s1 = matrix.strides
- return strided(matrix.ravel()[1:], shape=(m - 1, m), strides=(s0 + s1, s1)).reshape(m, -1)
+ #def remove_diagonal_elements(self, matrix):
+ # m = matrix.shape[0]
+ # strided = np.lib.stride_tricks.as_strided
+ # s0, s1 = matrix.strides
+ # return strided(matrix.ravel()[1:], shape=(m - 1, m), strides=(s0 + s1, s1)).reshape(m, -1)
@abc.abstractmethod
@@ -137,49 +137,47 @@ class StructureEstimator(object):
:rtype: List
"""
if not self._sample_path.has_prior_net_structure:
- raise RuntimeError("Can not compute spurious edges with no prior net structure!")
+ return []
real_graph = nx.DiGraph()
real_graph.add_nodes_from(self._sample_path.structure.nodes_labels)
real_graph.add_edges_from(self._sample_path.structure.edges)
return nx.difference(real_graph, self._complete_graph).edges
- def save_plot_estimated_structure_graph(self) -> None:
- """Plot the estimated structure in a graphical model style.
- Spurious edges are colored in red.
- """
- graph_to_draw = nx.DiGraph()
- spurious_edges = self.spurious_edges()
- non_spurious_edges = list(set(self._complete_graph.edges) - set(spurious_edges))
- print(non_spurious_edges)
- edges_colors = ['red' if edge in spurious_edges else 'black' for edge in self._complete_graph.edges]
- graph_to_draw.add_edges_from(spurious_edges)
- graph_to_draw.add_edges_from(non_spurious_edges)
- pos = nx.spring_layout(graph_to_draw, k=0.5*1/np.sqrt(len(graph_to_draw.nodes())), iterations=50,scale=10)
- options = {
- "node_size": 2000,
- "node_color": "white",
- "edgecolors": "black",
- 'linewidths':2,
- "with_labels":True,
- "font_size":13,
- 'connectionstyle': 'arc3, rad = 0.1',
- "arrowsize": 15,
- "arrowstyle": '<|-',
- "width": 1,
- "edge_color":edges_colors,
- }
-
- nx.draw(graph_to_draw, pos, **options)
- ax = plt.gca()
- ax.margins(0.20)
- plt.axis("off")
- name = self._sample_path._importer.file_path.rsplit('/', 1)[-1]
- name = name.split('.', 1)[0]
- name += '_' + str(self._sample_path._importer.dataset_id())
- name += '.png'
- plt.savefig(name)
- plt.clf()
- print("Estimated Structure Plot Saved At: ", os.path.abspath(name))
+ def save_plot_estimated_structure_graph(self, file_path: str) -> None:
+ """Plot the estimated structure in a graphical model style, use .png extension.
+ Spurious edges are colored in red if a prior structure is present.
+
+ :param file_path: path to save the file to
+ :type: string
+ """
+ graph_to_draw = nx.DiGraph()
+ spurious_edges = self.spurious_edges()
+ non_spurious_edges = list(set(self._complete_graph.edges) - set(spurious_edges))
+ edges_colors = ['red' if edge in spurious_edges else 'black' for edge in self._complete_graph.edges]
+ graph_to_draw.add_edges_from(spurious_edges)
+ graph_to_draw.add_edges_from(non_spurious_edges)
+ pos = nx.spring_layout(graph_to_draw, k=0.5*1/np.sqrt(len(graph_to_draw.nodes())), iterations=50,scale=10)
+ options = {
+ "node_size": 2000,
+ "node_color": "white",
+ "edgecolors": "black",
+ 'linewidths':2,
+ "with_labels":True,
+ "font_size":13,
+ 'connectionstyle': 'arc3, rad = 0.1',
+ "arrowsize": 15,
+ "arrowstyle": '<|-',
+ "width": 1,
+ "edge_color":edges_colors,
+ }
+
+ nx.draw(graph_to_draw, pos, **options)
+ ax = plt.gca()
+ ax.margins(0.20)
+ plt.axis("off")
+ plt.savefig(file_path)
+ plt.clf()
+ print("Estimated Structure Plot Saved At: ", os.path.abspath(file_path))
diff --git a/PyCTBN/PyCTBN/estimators/structure_score_based_estimator.py b/PyCTBN/PyCTBN/estimators/structure_score_based_estimator.py
index 2903db3..cf55d7c 100644
--- a/PyCTBN/PyCTBN/estimators/structure_score_based_estimator.py
+++ b/PyCTBN/PyCTBN/estimators/structure_score_based_estimator.py
@@ -156,6 +156,11 @@ class StructureScoreBasedEstimator(StructureEstimator):
except Exception as e:
print(f"errore: {e}")
+
+ 'Update the graph'
+ self._complete_graph = nx.DiGraph()
+ self._complete_graph.add_edges_from(set_list_edges)
+
return set_list_edges
diff --git a/PyCTBN/PyCTBN/optimizers/tabu_search.py b/PyCTBN/PyCTBN/optimizers/tabu_search.py
index e15dd40..3a6fd92 100644
--- a/PyCTBN/PyCTBN/optimizers/tabu_search.py
+++ b/PyCTBN/PyCTBN/optimizers/tabu_search.py
@@ -104,7 +104,7 @@ class TabuSearch(Optimizer):
self.tabu_length = len(other_nodes)
if self.tabu_rules_duration is None:
- self.tabu_tabu_rules_durationength = len(other_nodes)
+ self.tabu_rules_duration = len(other_nodes)
'inizialize the data structures'
tabu_set = set()
diff --git a/PyCTBN/PyCTBN/structure_graph/network_graph.py b/PyCTBN/PyCTBN/structure_graph/network_graph.py
index 623981d..6fb3639 100644
--- a/PyCTBN/PyCTBN/structure_graph/network_graph.py
+++ b/PyCTBN/PyCTBN/structure_graph/network_graph.py
@@ -36,15 +36,15 @@ class NetworkGraph(object):
self._transition_filtering = None
self._p_combs_structure = None
- def init_graph(self):
- self.add_nodes(self._nodes_labels)
- self.add_edges(self.graph_struct.edges)
- self.aggregated_info_about_nodes_parents = self.get_ord_set_of_par_of_all_nodes()
- self._fancy_indexing = self.build_fancy_indexing_structure(0)
- self.build_scalar_indexing_structures()
- self.build_time_columns_filtering_structure()
- self.build_transition_columns_filtering_structure()
- self._p_combs_structure = self.build_p_combs_structure()
+ #def init_graph(self):
+ # self.add_nodes(self._nodes_labels)
+ # self.add_edges(self.graph_struct.edges)
+ # self.aggregated_info_about_nodes_parents = self.get_ord_set_of_par_of_all_nodes()
+ # self._fancy_indexing = self.build_fancy_indexing_structure(0)
+ # self.build_scalar_indexing_structures()
+ # self.build_time_columns_filtering_structure()
+ # self.build_transition_columns_filtering_structure()
+ # self._p_combs_structure = self.build_p_combs_structure()
def fast_init(self, node_id: str) -> None:
"""Initializes all the necessary structures for parameters estimation of the node identified by the label
diff --git a/PyCTBN/PyCTBN/structure_graph/structure.py b/PyCTBN/PyCTBN/structure_graph/structure.py
index a9d60cc..f79c875 100644
--- a/PyCTBN/PyCTBN/structure_graph/structure.py
+++ b/PyCTBN/PyCTBN/structure_graph/structure.py
@@ -74,11 +74,11 @@ class Structure(object):
self._edges_list = list()
def add_edge(self,edge: tuple):
- self._edges_list.append(tuple)
- print(self._edges_list)
+ self._edges_list.append(edge)
+
def remove_edge(self,edge: tuple):
- self._edges_list.remove(tuple)
+ self._edges_list.remove(edge)
def contains_edge(self,edge:tuple) -> bool:
return edge in self._edges_list
diff --git a/PyCTBN/PyCTBN/utility/sample_importer.py b/PyCTBN/PyCTBN/utility/sample_importer.py
index 05073c8..b0b6e8f 100644
--- a/PyCTBN/PyCTBN/utility/sample_importer.py
+++ b/PyCTBN/PyCTBN/utility/sample_importer.py
@@ -32,7 +32,7 @@ class SampleImporter(AbstractImporter):
'If the data are not DataFrame, it will be converted'
if isinstance(variables,list) or isinstance(variables,np.ndarray):
variables = pd.DataFrame(variables)
- if isinstance(variables,list) or isinstance(variables,np.ndarray):
+ if isinstance(prior_net_structure,list) or isinstance(prior_net_structure,np.ndarray):
prior_net_structure=pd.DataFrame(prior_net_structure)
super(SampleImporter, self).__init__(trajectory_list =trajectory_list,
@@ -48,9 +48,6 @@ class SampleImporter(AbstractImporter):
samples_list= self._df_samples_list
- if isinstance(samples_list, np.ndarray):
- samples_list = samples_list.tolist()
-
self.compute_row_delta_in_all_samples_frames(samples_list)
def build_sorter(self, sample_frame: pd.DataFrame) -> typing.List:
@@ -61,5 +58,5 @@ class SampleImporter(AbstractImporter):
return columns_header
- def dataset_id(self) -> object:
- pass
\ No newline at end of file
+ def dataset_id(self) -> str:
+ return str("")
\ No newline at end of file
diff --git a/PyCTBN/__init__.py b/PyCTBN/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/PyCTBN/test_data/networks_and_trajectories_binary_data_01_3.json b/PyCTBN/test_data/networks_and_trajectories_binary_data_01_3.json
new file mode 100644
index 0000000..a287826
Binary files /dev/null and b/PyCTBN/test_data/networks_and_trajectories_binary_data_01_3.json differ
diff --git a/PyCTBN/test_data/networks_and_trajectories_binary_data_02_10_1.json b/PyCTBN/test_data/networks_and_trajectories_binary_data_02_10_1.json
new file mode 100644
index 0000000..1fb0d3e
Binary files /dev/null and b/PyCTBN/test_data/networks_and_trajectories_binary_data_02_10_1.json differ
diff --git a/PyCTBN/test_data/networks_and_trajectories_ternary_data_01_6_1.json b/PyCTBN/test_data/networks_and_trajectories_ternary_data_01_6_1.json
new file mode 100644
index 0000000..efda696
Binary files /dev/null and b/PyCTBN/test_data/networks_and_trajectories_ternary_data_01_6_1.json differ
diff --git a/PyCTBN/tests/estimators/__init__.py b/PyCTBN/tests/estimators/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/PyCTBN/tests/estimators/test_structure_constraint_based_estimator.py b/PyCTBN/tests/estimators/test_structure_constraint_based_estimator.py
index 96834dc..9370c82 100644
--- a/PyCTBN/tests/estimators/test_structure_constraint_based_estimator.py
+++ b/PyCTBN/tests/estimators/test_structure_constraint_based_estimator.py
@@ -50,15 +50,127 @@ class TestStructureConstraintBasedEstimator(unittest.TestCase):
cls.s1.build_trajectories()
cls.s1.build_structure()
- def test_structure(self):
+ def test_structure_1(self):
true_edges = copy.deepcopy(self.s1.structure.edges)
true_edges = set(map(tuple, true_edges))
se1 = StructureConstraintBasedEstimator(self.s1,0.1,0.1)
- edges = se1.estimate_structure(disable_multiprocessing=False)
+ edges = se1.estimate_structure(True)
-
+ self.assertFalse(se1.spurious_edges())
self.assertEqual(edges, true_edges)
+
+
+ def test_structure_2(self):
+ with open("./PyCTBN/test_data/networks_and_trajectories_binary_data_02_10_1.json") as f:
+ raw_data = json.load(f)
+
+ trajectory_list_raw= raw_data["samples"]
+
+ trajectory_list = [pd.DataFrame(sample) for sample in trajectory_list_raw]
+
+ variables= pd.DataFrame(raw_data["variables"])
+ prior_net_structure = pd.DataFrame(raw_data["dyn.str"])
+
+
+ self.importer = SampleImporter(
+ trajectory_list=trajectory_list,
+ variables=variables,
+ prior_net_structure=prior_net_structure
+ )
+
+ self.importer.import_data()
+ #cls.s1 = sp.SamplePath(cls.importer)
+
+ #cls.traj = cls.s1.concatenated_samples
+
+ # print(len(cls.traj))
+ self.s1 = SamplePath(self.importer)
+ self.s1.build_trajectories()
+ self.s1.build_structure()
+
+ true_edges = copy.deepcopy(self.s1.structure.edges)
+ true_edges = set(map(tuple, true_edges))
+
+ se1 = StructureConstraintBasedEstimator(self.s1,0.1,0.1)
+ edges = se1.estimate_structure(True)
+
+
+ 'calculate precision and recall'
+ n_missing_edges = 0
+ n_added_fake_edges = 0
+
+
+ n_added_fake_edges = len(edges.difference(true_edges))
+
+ n_missing_edges = len(true_edges.difference(edges))
+
+ n_true_positive = len(true_edges) - n_missing_edges
+
+ precision = n_true_positive / (n_true_positive + n_added_fake_edges)
+
+ recall = n_true_positive / (n_true_positive + n_missing_edges)
+
+ self.assertGreaterEqual(precision,0.75)
+ self.assertGreaterEqual(recall,0.75)
+
+
+ def test_structure_3(self):
+ with open("./PyCTBN/test_data/networks_and_trajectories_ternary_data_01_6_1.json") as f:
+ raw_data = json.load(f)
+
+ trajectory_list_raw= raw_data["samples"]
+
+ trajectory_list = [pd.DataFrame(sample) for sample in trajectory_list_raw]
+
+ variables= pd.DataFrame(raw_data["variables"])
+ prior_net_structure = pd.DataFrame(raw_data["dyn.str"])
+
+
+ self.importer = SampleImporter(
+ trajectory_list=trajectory_list,
+ variables=variables,
+ prior_net_structure=prior_net_structure
+ )
+
+ self.importer.import_data()
+ #cls.s1 = sp.SamplePath(cls.importer)
+
+ #cls.traj = cls.s1.concatenated_samples
+
+ # print(len(cls.traj))
+ self.s1 = SamplePath(self.importer)
+ self.s1.build_trajectories()
+ self.s1.build_structure()
+
+ true_edges = copy.deepcopy(self.s1.structure.edges)
+ true_edges = set(map(tuple, true_edges))
+
+ se1 = StructureConstraintBasedEstimator(self.s1,0.1,0.1)
+ edges = se1.estimate_structure(True)
+
+
+ 'calculate precision and recall'
+ n_missing_edges = 0
+ n_added_fake_edges = 0
+
+
+ n_added_fake_edges = len(edges.difference(true_edges))
+
+ n_missing_edges = len(true_edges.difference(edges))
+
+ n_true_positive = len(true_edges) - n_missing_edges
+
+ precision = n_true_positive / (n_true_positive + n_added_fake_edges)
+
+ recall = n_true_positive / (n_true_positive + n_missing_edges)
+
+ self.assertGreaterEqual(precision,0.75)
+ self.assertGreaterEqual(recall,0.75)
+
+
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/PyCTBN/tests/estimators/test_structure_constraint_based_estimator_server.py b/PyCTBN/tests/estimators/test_structure_constraint_based_estimator_server.py
deleted file mode 100644
index a524515..0000000
--- a/PyCTBN/tests/estimators/test_structure_constraint_based_estimator_server.py
+++ /dev/null
@@ -1,59 +0,0 @@
-
-import glob
-import math
-import os
-import unittest
-
-import networkx as nx
-import numpy as np
-import psutil
-from line_profiler import LineProfiler
-
-from ...PyCTBN.utility.cache import Cache
-from ...PyCTBN.structure_graph.sample_path import SamplePath
-from ...PyCTBN.estimators.structure_constraint_based_estimator import StructureConstraintBasedEstimator
-from ...PyCTBN.utility.json_importer import JsonImporter
-
-from multiprocessing import set_start_method
-
-import copy
-
-
-class TestStructureConstraintBasedEstimator(unittest.TestCase):
- @classmethod
- def setUpClass(cls):
- pass
-
- def test_structure(self):
- #cls.read_files = glob.glob(os.path.join('../../data', "*.json"))
- self.importer = JsonImporter("./PyCTBN/test_data/networks_and_trajectories_binary_data_01_3.json", 'samples', 'dyn.str', 'variables', 'Time', 'Name')
- self.s1 = SamplePath(self.importer)
- self.s1.build_trajectories()
- self.s1.build_structure()
-
- true_edges = copy.deepcopy(self.s1.structure.edges)
- true_edges = set(map(tuple, true_edges))
-
-
- se1 = StructureConstraintBasedEstimator(self.s1,0.1,0.1)
- edges = se1.estimate_structure(disable_multiprocessing=False)
-
-
- self.importer = JsonImporter("./PyCTBN/test_data/networks_and_trajectories_binary_data_01_3.json", 'samples', 'dyn.str', 'variables', 'Time', 'Name')
- self.s1 = SamplePath(self.importer)
- self.s1.build_trajectories()
- self.s1.build_structure()
-
- true_edges = copy.deepcopy(self.s1.structure.edges)
- true_edges = set(map(tuple, true_edges))
-
-
- se1 = StructureConstraintBasedEstimator(self.s1,0.1,0.1)
- edges = se1.estimate_structure(disable_multiprocessing=True)
-
-
-
- self.assertEqual(edges, true_edges)
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/PyCTBN/tests/estimators/test_structure_estimator.py b/PyCTBN/tests/estimators/test_structure_estimator.py
new file mode 100644
index 0000000..30b9e18
--- /dev/null
+++ b/PyCTBN/tests/estimators/test_structure_estimator.py
@@ -0,0 +1,118 @@
+
+import glob
+import math
+import os
+import unittest
+import json
+import networkx as nx
+import numpy as np
+import timeit
+
+from ...PyCTBN.utility.cache import Cache
+from ...PyCTBN.structure_graph.sample_path import SamplePath
+from ...PyCTBN.estimators.structure_constraint_based_estimator import StructureConstraintBasedEstimator
+from ...PyCTBN.utility.json_importer import JsonImporter
+
+
+class TestStructureEstimator(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.read_files = glob.glob(os.path.join('./PyCTBN/test_data', "*.json"))
+ cls.importer = JsonImporter('./PyCTBN/test_data/networks_and_trajectories_binary_data_01_3.json', 'samples', 'dyn.str', 'variables', 'Time', 'Name')
+ cls.importer.import_data(0)
+ cls.s1 = SamplePath(cls.importer)
+ cls.s1.build_trajectories()
+ cls.s1.build_structure()
+
+ def test_init(self):
+ exp_alfa = 0.1
+ chi_alfa = 0.1
+ se1 = StructureConstraintBasedEstimator(self.s1, exp_alfa, chi_alfa)
+ self.assertEqual(self.s1, se1._sample_path)
+ self.assertTrue(np.array_equal(se1._nodes, np.array(self.s1.structure.nodes_labels)))
+ self.assertTrue(np.array_equal(se1._nodes_indxs, self.s1.structure.nodes_indexes))
+ self.assertTrue(np.array_equal(se1._nodes_vals, self.s1.structure.nodes_values))
+ self.assertEqual(se1._exp_test_sign, exp_alfa)
+ self.assertEqual(se1._chi_test_alfa, chi_alfa)
+ self.assertIsInstance(se1._complete_graph, nx.DiGraph)
+ self.assertIsInstance(se1._cache, Cache)
+
+ def test_build_complete_graph(self):
+ exp_alfa = 0.1
+ chi_alfa = 0.1
+ nodes_numb = len(self.s1.structure.nodes_labels)
+ se1 = StructureConstraintBasedEstimator(self.s1, exp_alfa, chi_alfa)
+ cg = se1.build_complete_graph(self.s1.structure.nodes_labels)
+ self.assertEqual(len(cg.edges), nodes_numb*(nodes_numb - 1))
+ for node in self.s1.structure.nodes_labels:
+ no_self_loops = self.s1.structure.nodes_labels[:]
+ no_self_loops.remove(node)
+ for n2 in no_self_loops:
+ self.assertIn((node, n2), cg.edges)
+ #se1.save_plot_estimated_structure_graph()
+
+ def test_build_removable_edges_matrix(self):
+ exp_alfa = 0.1
+ chi_alfa = 0.1
+ known_edges = self.s1.structure.edges[0:2]
+ se1 = StructureConstraintBasedEstimator(self.s1, exp_alfa, chi_alfa, known_edges)
+ for edge in known_edges:
+ i = self.s1.structure.get_node_indx(edge[0])
+ j = self.s1.structure.get_node_indx(edge[1])
+ self.assertFalse(se1._removable_edges_matrix[i][j])
+
+ def test_generate_possible_sub_sets_of_size(self):
+ exp_alfa = 0.1
+ chi_alfa = 0.1
+ nodes_numb = len(self.s1.structure.nodes_labels)
+ se1 = StructureConstraintBasedEstimator(self.s1, exp_alfa, chi_alfa)
+
+ for node in self.s1.structure.nodes_labels:
+ for b in range(nodes_numb):
+ sets = StructureConstraintBasedEstimator.generate_possible_sub_sets_of_size(self.s1.structure.nodes_labels, b, node)
+ sets2 = StructureConstraintBasedEstimator.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:
+ self.assertFalse(node in sset)
+
+ def test_time(self):
+ known_edges = []
+ se1 = StructureConstraintBasedEstimator(self.s1, 0.1, 0.1, known_edges,25)
+ 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)
+ #print("Spurious Edges:", se1.spurious_edges())
+ #se1.save_plot_estimated_structure_graph()
+
+ def test_save_results(self):
+ se1 = StructureConstraintBasedEstimator(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 = StructureConstraintBasedEstimator(self.s1, 0.1, 0.1)
+ se1.ctpc_algorithm()
+ adj_matrix = nx.adj_matrix(se1._complete_graph).toarray().astype(bool)
+ self.assertTrue(np.array_equal(adj_matrix, se1.adjacency_matrix()))
+
+ def test_save_plot_estimated_graph(self):
+ se1 = StructureConstraintBasedEstimator(self.s1, 0.1, 0.1)
+ edges = se1.estimate_structure(disable_multiprocessing=True)
+ se1.save_plot_estimated_structure_graph('./networks_and_trajectories_ternary_data_3.png')
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/PyCTBN/tests/estimators/test_structure_score_based_estimator.py b/PyCTBN/tests/estimators/test_structure_score_based_estimator.py
index 742fa21..69efe60 100644
--- a/PyCTBN/tests/estimators/test_structure_score_based_estimator.py
+++ b/PyCTBN/tests/estimators/test_structure_score_based_estimator.py
@@ -1,5 +1,4 @@
-import sys
-sys.path.append("../../PyCTBN/")
+
import glob
import math
import os
@@ -54,14 +53,38 @@ class TestStructureScoreBasedEstimator(unittest.TestCase):
cls.s1.build_trajectories()
cls.s1.build_structure()
+ def test_structure_monoprocesso(self):
+ with open("./PyCTBN/test_data/networks_and_trajectories_binary_data_01_3.json") as f:
+ raw_data = json.load(f)
+
+ trajectory_list_raw= raw_data[0]["samples"]
+
+ trajectory_list = [pd.DataFrame(sample) for sample in trajectory_list_raw]
+
+ variables= pd.DataFrame(raw_data[0]["variables"])
+ prior_net_structure = pd.DataFrame(raw_data[0]["dyn.str"])
- def test_structure(self):
+ self.importer = SampleImporter(
+ trajectory_list=trajectory_list,
+ variables=variables,
+ prior_net_structure=prior_net_structure
+ )
+
+ self.importer.import_data()
+ #cls.s1 = sp.SamplePath(cls.importer)
+
+ #cls.traj = cls.s1.concatenated_samples
+
+ # print(len(cls.traj))
+ self.s1 = SamplePath(self.importer)
+ self.s1.build_trajectories()
+ self.s1.build_structure()
true_edges = copy.deepcopy(self.s1.structure.edges)
true_edges = set(map(tuple, true_edges))
- se1 = StructureScoreBasedEstimator(self.s1,known_edges = [('X','Q')])
+ se1 = StructureScoreBasedEstimator(self.s1)
edges = se1.estimate_structure(
max_parents = None,
iterations_number = 100,
@@ -74,7 +97,147 @@ class TestStructureScoreBasedEstimator(unittest.TestCase):
self.assertEqual(edges, true_edges)
+
+ def test_structure_1(self):
+ true_edges = copy.deepcopy(self.s1.structure.edges)
+ true_edges = set(map(tuple, true_edges))
+
+
+ se1 = StructureScoreBasedEstimator(self.s1)
+ edges = se1.estimate_structure(
+ max_parents = None,
+ iterations_number = 100,
+ patience = 35,
+ tabu_length = 15,
+ tabu_rules_duration = 15,
+ optimizer = 'hill',
+ disable_multiprocessing=False
+ )
+
+
+ self.assertEqual(edges, true_edges)
+
+ def test_structure_2(self):
+ with open("./PyCTBN/test_data/networks_and_trajectories_binary_data_02_10_1.json") as f:
+ raw_data = json.load(f)
+
+ trajectory_list_raw= raw_data["samples"]
+
+ trajectory_list = [pd.DataFrame(sample) for sample in trajectory_list_raw]
+
+ variables= pd.DataFrame(raw_data["variables"])
+ prior_net_structure = pd.DataFrame(raw_data["dyn.str"])
+
+
+ self.importer = SampleImporter(
+ trajectory_list=trajectory_list,
+ variables=variables,
+ prior_net_structure=prior_net_structure
+ )
+
+ self.importer.import_data()
+ #cls.s1 = sp.SamplePath(cls.importer)
+
+ #cls.traj = cls.s1.concatenated_samples
+
+ # print(len(cls.traj))
+ self.s1 = SamplePath(self.importer)
+ self.s1.build_trajectories()
+ self.s1.build_structure()
+
+ true_edges = copy.deepcopy(self.s1.structure.edges)
+ true_edges = set(map(tuple, true_edges))
+
+ se1 = StructureScoreBasedEstimator(self.s1)
+ edges = se1.estimate_structure(
+ max_parents = None,
+ iterations_number = 100,
+ patience = 35,
+ tabu_length = 15,
+ tabu_rules_duration = 15,
+ optimizer = 'hill',
+ disable_multiprocessing=True
+ )
+ 'calculate precision and recall'
+ n_missing_edges = 0
+ n_added_fake_edges = 0
+
+
+ n_added_fake_edges = len(edges.difference(true_edges))
+
+ n_missing_edges = len(true_edges.difference(edges))
+
+ n_true_positive = len(true_edges) - n_missing_edges
+
+ precision = n_true_positive / (n_true_positive + n_added_fake_edges)
+
+ recall = n_true_positive / (n_true_positive + n_missing_edges)
+
+ self.assertGreaterEqual(precision,0.75)
+ self.assertGreaterEqual(recall,0.75)
+
+ def test_structure_3(self):
+ with open("./PyCTBN/test_data/networks_and_trajectories_ternary_data_01_6_1.json") as f:
+ raw_data = json.load(f)
+
+ trajectory_list_raw= raw_data["samples"]
+
+ trajectory_list = [pd.DataFrame(sample) for sample in trajectory_list_raw]
+
+ variables= raw_data["variables"]
+ prior_net_structure = raw_data["dyn.str"]
+
+
+ self.importer = SampleImporter(
+ trajectory_list=trajectory_list,
+ variables=variables,
+ prior_net_structure=prior_net_structure
+ )
+
+ self.importer.import_data()
+ #cls.s1 = sp.SamplePath(cls.importer)
+
+ #cls.traj = cls.s1.concatenated_samples
+
+ # print(len(cls.traj))
+ self.s1 = SamplePath(self.importer)
+ self.s1.build_trajectories()
+ self.s1.build_structure()
+
+ true_edges = copy.deepcopy(self.s1.structure.edges)
+ true_edges = set(map(tuple, true_edges))
+
+ known_edges = self.s1.structure.edges[0:2]
+
+ se1 = StructureScoreBasedEstimator(self.s1,known_edges=known_edges)
+ edges = se1.estimate_structure(
+ max_parents = 4,
+ iterations_number = 100,
+ patience = 35,
+ tabu_length = 15,
+ tabu_rules_duration = 15,
+ optimizer = 'hill',
+ disable_multiprocessing=True
+ )
+
+ 'calculate precision and recall'
+ n_missing_edges = 0
+ n_added_fake_edges = 0
+
+
+ n_added_fake_edges = len(edges.difference(true_edges))
+
+ n_missing_edges = len(true_edges.difference(edges))
+
+ n_true_positive = len(true_edges) - n_missing_edges
+
+ precision = n_true_positive / (n_true_positive + n_added_fake_edges)
+
+ recall = n_true_positive / (n_true_positive + n_missing_edges)
+
+ self.assertGreaterEqual(precision,0.75)
+ self.assertGreaterEqual(recall,0.75)
if __name__ == '__main__':
diff --git a/PyCTBN/tests/estimators/test_structure_score_based_estimator_server.py b/PyCTBN/tests/estimators/test_structure_score_based_estimator_server.py
deleted file mode 100644
index b21ea7a..0000000
--- a/PyCTBN/tests/estimators/test_structure_score_based_estimator_server.py
+++ /dev/null
@@ -1,79 +0,0 @@
-
-import glob
-import math
-import os
-import unittest
-
-import networkx as nx
-import numpy as np
-import psutil
-from line_profiler import LineProfiler
-import copy
-
-from ...PyCTBN.utility.cache import Cache
-from ...PyCTBN.structure_graph.sample_path import SamplePath
-from ...PyCTBN.estimators.structure_score_based_estimator import StructureScoreBasedEstimator
-from ...PyCTBN.utility.json_importer import JsonImporter
-
-
-
-class TestStructureScoreBasedEstimator(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- pass
-
-
-
- def test_structure(self):
- #cls.read_files = glob.glob(os.path.join('../../data', "*.json"))
- self.importer = JsonImporter("./PyCTBN/test_data/networks_and_trajectories_binary_data_01_3.json", 'samples', 'dyn.str', 'variables', 'Time', 'Name')
- self.s1 = SamplePath(self.importer)
- self.s1.build_trajectories()
- self.s1.build_structure()
-
- true_edges = copy.deepcopy(self.s1.structure.edges)
- true_edges = set(map(tuple, true_edges))
-
-
- se1 = StructureScoreBasedEstimator(self.s1)
- edges = se1.estimate_structure(
- max_parents = None,
- iterations_number = 100,
- patience = 35,
- tabu_length = 15,
- tabu_rules_duration = 15,
- optimizer = 'tabu',
- disable_multiprocessing=False
- )
-
-
- self.importer = JsonImporter("./PyCTBN/test_data/networks_and_trajectories_binary_data_01_3.json", 'samples', 'dyn.str', 'variables', 'Time', 'Name')
- self.s1 = SamplePath(self.importer)
- self.s1.build_trajectories()
- self.s1.build_structure()
-
- true_edges = copy.deepcopy(self.s1.structure.edges)
- true_edges = set(map(tuple, true_edges))
-
-
- se1 = StructureScoreBasedEstimator(self.s1)
- edges = se1.estimate_structure(
- max_parents = None,
- iterations_number = 100,
- patience = 35,
- tabu_length = 15,
- tabu_rules_duration = 15,
- optimizer = 'tabu',
- disable_multiprocessing=True
- )
-
-
-
- self.assertEqual(edges, true_edges)
-
-
-
-if __name__ == '__main__':
- unittest.main()
-
diff --git a/PyCTBN/tests/optimizers/__init__.py b/PyCTBN/tests/optimizers/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/PyCTBN/tests/optimizers/test_hill_climbing_search.py b/PyCTBN/tests/optimizers/test_hill_climbing_search.py
index 2b05236..d2fd3e2 100644
--- a/PyCTBN/tests/optimizers/test_hill_climbing_search.py
+++ b/PyCTBN/tests/optimizers/test_hill_climbing_search.py
@@ -9,11 +9,14 @@ import numpy as np
import psutil
from line_profiler import LineProfiler
import copy
+import json
+import pandas as pd
from ...PyCTBN.structure_graph.sample_path import SamplePath
from ...PyCTBN.estimators.structure_score_based_estimator import StructureScoreBasedEstimator
from ...PyCTBN.utility.json_importer import JsonImporter
+from ...PyCTBN.utility.sample_importer import SampleImporter
@@ -38,16 +41,75 @@ class TestHillClimbingSearch(unittest.TestCase):
se1 = StructureScoreBasedEstimator(self.s1)
edges = se1.estimate_structure(
- max_parents = None,
+ max_parents = 2,
iterations_number = 40,
patience = None,
- optimizer = 'hill'
+ optimizer = 'hill',
+ disable_multiprocessing=True
)
self.assertEqual(edges, true_edges)
+ def test_structure_3(self):
+ with open("./PyCTBN/test_data/networks_and_trajectories_ternary_data_01_6_1.json") as f:
+ raw_data = json.load(f)
+ trajectory_list_raw= raw_data["samples"]
+
+ trajectory_list = [pd.DataFrame(sample) for sample in trajectory_list_raw]
+
+ variables= raw_data["variables"]
+ prior_net_structure = raw_data["dyn.str"]
+
+
+ self.importer = SampleImporter(
+ trajectory_list=trajectory_list,
+ variables=variables,
+ prior_net_structure=prior_net_structure
+ )
+
+ self.importer.import_data()
+ #cls.s1 = sp.SamplePath(cls.importer)
+
+ #cls.traj = cls.s1.concatenated_samples
+
+ # print(len(cls.traj))
+ self.s1 = SamplePath(self.importer)
+ self.s1.build_trajectories()
+ self.s1.build_structure()
+
+ true_edges = copy.deepcopy(self.s1.structure.edges)
+ true_edges = set(map(tuple, true_edges))
+
+ known_edges = self.s1.structure.edges[0:2]
+
+ se1 = StructureScoreBasedEstimator(self.s1,known_edges=known_edges)
+ edges = se1.estimate_structure(
+ max_parents = 3,
+ iterations_number = 100,
+ patience = 40,
+ optimizer = 'hill',
+ disable_multiprocessing=True
+ )
+
+ 'calculate precision and recall'
+ n_missing_edges = 0
+ n_added_fake_edges = 0
+
+
+ n_added_fake_edges = len(edges.difference(true_edges))
+
+ n_missing_edges = len(true_edges.difference(edges))
+
+ n_true_positive = len(true_edges) - n_missing_edges
+
+ precision = n_true_positive / (n_true_positive + n_added_fake_edges)
+
+ recall = n_true_positive / (n_true_positive + n_missing_edges)
+
+ self.assertGreaterEqual(precision,0.75)
+ self.assertGreaterEqual(recall,0.75)
if __name__ == '__main__':
unittest.main()
diff --git a/PyCTBN/tests/optimizers/test_tabu_search.py b/PyCTBN/tests/optimizers/test_tabu_search.py
index 3349dd7..8fdc67a 100644
--- a/PyCTBN/tests/optimizers/test_tabu_search.py
+++ b/PyCTBN/tests/optimizers/test_tabu_search.py
@@ -13,14 +13,11 @@ from line_profiler import LineProfiler
import copy
import json
-import utility.cache as ch
-import structure_graph.sample_path as sp
-import estimators.structure_score_based_estimator as se
-import utility.json_importer as ji
-import utility.sample_importer as si
-
-
-
+from ...PyCTBN.utility.cache import Cache
+from ...PyCTBN.structure_graph.sample_path import SamplePath
+from ...PyCTBN.estimators.structure_score_based_estimator import StructureScoreBasedEstimator
+from ...PyCTBN.utility.json_importer import JsonImporter
+from ...PyCTBN.utility.sample_importer import SampleImporter
class TestTabuSearch(unittest.TestCase):
@@ -40,7 +37,7 @@ class TestTabuSearch(unittest.TestCase):
prior_net_structure = pd.DataFrame(raw_data[0]["dyn.str"])
- cls.importer = si.SampleImporter(
+ cls.importer = SampleImporter(
trajectory_list=trajectory_list,
variables=variables,
prior_net_structure=prior_net_structure
@@ -52,7 +49,7 @@ class TestTabuSearch(unittest.TestCase):
#cls.traj = cls.s1.concatenated_samples
# print(len(cls.traj))
- cls.s1 = sp.SamplePath(cls.importer)
+ cls.s1 = SamplePath(cls.importer)
cls.s1.build_trajectories()
cls.s1.build_structure()
#cls.s1.clear_memory()
@@ -63,21 +60,79 @@ class TestTabuSearch(unittest.TestCase):
true_edges = copy.deepcopy(self.s1.structure.edges)
true_edges = set(map(tuple, true_edges))
- se1 = se.StructureScoreBasedEstimator(self.s1)
+ se1 = StructureScoreBasedEstimator(self.s1)
edges = se1.estimate_structure(
max_parents = None,
iterations_number = 100,
patience = 20,
- tabu_length = 10,
- tabu_rules_duration = 10,
optimizer = 'tabu',
- disable_multiprocessing=False
+ disable_multiprocessing=True
)
self.assertEqual(edges, true_edges)
+ def test_structure_3(self):
+ with open("./PyCTBN/test_data/networks_and_trajectories_ternary_data_01_6_1.json") as f:
+ raw_data = json.load(f)
+
+ trajectory_list_raw= raw_data["samples"]
+
+ trajectory_list = [pd.DataFrame(sample) for sample in trajectory_list_raw]
+
+ variables= raw_data["variables"]
+ prior_net_structure = raw_data["dyn.str"]
+
+
+ self.importer = SampleImporter(
+ trajectory_list=trajectory_list,
+ variables=variables,
+ prior_net_structure=prior_net_structure
+ )
+
+ self.importer.import_data()
+ #cls.s1 = sp.SamplePath(cls.importer)
+
+ #cls.traj = cls.s1.concatenated_samples
+
+ # print(len(cls.traj))
+ self.s1 = SamplePath(self.importer)
+ self.s1.build_trajectories()
+ self.s1.build_structure()
+
+ true_edges = copy.deepcopy(self.s1.structure.edges)
+ true_edges = set(map(tuple, true_edges))
+
+ known_edges = self.s1.structure.edges[0:2]
+
+ se1 = StructureScoreBasedEstimator(self.s1,known_edges=known_edges)
+ edges = se1.estimate_structure(
+ max_parents = 4,
+ iterations_number = 100,
+ patience = 40,
+ tabu_length = 3,
+ tabu_rules_duration = 3,
+ optimizer = 'tabu',
+ disable_multiprocessing=True
+ )
+
+ 'calculate precision and recall'
+ n_missing_edges = 0
+ n_added_fake_edges = 0
+
+
+ n_added_fake_edges = len(edges.difference(true_edges))
+
+ n_missing_edges = len(true_edges.difference(edges))
+
+ n_true_positive = len(true_edges) - n_missing_edges
+
+ precision = n_true_positive / (n_true_positive + n_added_fake_edges)
+
+ recall = n_true_positive / (n_true_positive + n_missing_edges)
+ self.assertGreaterEqual(precision,0.75)
+ self.assertGreaterEqual(recall,0.75)
if __name__ == '__main__':
unittest.main()
diff --git a/PyCTBN/tests/structure_graph/__init__.py b/PyCTBN/tests/structure_graph/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/PyCTBN/tests/structure_graph/test_sample_path.py b/PyCTBN/tests/structure_graph/test_sample_path.py
index 3d9635d..2111d72 100644
--- a/PyCTBN/tests/structure_graph/test_sample_path.py
+++ b/PyCTBN/tests/structure_graph/test_sample_path.py
@@ -54,7 +54,8 @@ class TestSamplePath(unittest.TestCase):
importer = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name')
importer.import_data(0)
s1 = SamplePath(importer)
- random.shuffle(importer._sorter)
+ importer._sorter[0],importer._sorter[1]= importer._sorter[1],importer._sorter[0]
+
self.assertRaises(RuntimeError, s1.build_structure)
def test_build_saplepath_no_prior_net_structure(self):
@@ -66,7 +67,17 @@ class TestSamplePath(unittest.TestCase):
s1.build_structure()
self.assertFalse(s1.structure.edges)
+ def test_buid_samplepath_no_variables(self):
+ importer = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name')
+ importer.import_data(0)
+ importer._df_variables = None
+ self.assertRaises(RuntimeError, SamplePath, importer)
+ def test_buid_samplepath_no_concatenated_samples(self):
+ importer = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name')
+ importer.import_data(0)
+ importer._concatenated_samples = None
+ self.assertRaises(RuntimeError, SamplePath, importer)
if __name__ == '__main__':
unittest.main()
diff --git a/PyCTBN/tests/structure_graph/test_structure.py b/PyCTBN/tests/structure_graph/test_structure.py
index a80b91c..df4289e 100644
--- a/PyCTBN/tests/structure_graph/test_structure.py
+++ b/PyCTBN/tests/structure_graph/test_structure.py
@@ -28,6 +28,15 @@ class TestStructure(unittest.TestCase):
for indx, var in enumerate(self.labels):
self.assertEqual(var, s1.get_node_id(indx))
+ def test_edges_operations(self):
+ s1 = Structure(self.labels, self.indxs, self.vals, self.edges, self.vars_numb)
+
+ self.assertTrue(s1.contains_edge(('X','Z')))
+ s1.add_edge(('Z','X'))
+ self.assertTrue(s1.contains_edge(('Z','X')))
+ s1.remove_edge(('Z','X'))
+ self.assertFalse(s1.contains_edge(('Z','X')))
+
def test_get_node_indx(self):
l2 = self.labels[:]
l2.remove('Y')
@@ -71,6 +80,7 @@ class TestStructure(unittest.TestCase):
s1 = Structure(self.labels, self.indxs, self.vals, self.edges, self.vars_numb)
s2 = Structure(self.labels, self.indxs, self.vals, self.edges, self.vars_numb)
self.assertEqual(s1, s2)
+ self.assertNotEqual(s1,4)
def test_repr(self):
s1 = Structure(self.labels, self.indxs, self.vals, self.edges, self.vars_numb)
diff --git a/PyCTBN/tests/structure_graph/test_trajectory.py b/PyCTBN/tests/structure_graph/test_trajectory.py
index b06b17b..d68f2c1 100644
--- a/PyCTBN/tests/structure_graph/test_trajectory.py
+++ b/PyCTBN/tests/structure_graph/test_trajectory.py
@@ -2,6 +2,7 @@
import unittest
import numpy as np
import glob
+import os
from ...PyCTBN.structure_graph.trajectory import Trajectory
from ...PyCTBN.utility.json_importer import JsonImporter
@@ -10,7 +11,7 @@ class TestTrajectory(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
- cls.read_files = glob.glob(os.path.join('./test_data', "*.json"))
+ cls.read_files = glob.glob(os.path.join('./PyCTBN/test_data', "*.json"))
cls.importer = JsonImporter(cls.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name')
cls.importer.import_data(0)
@@ -22,6 +23,8 @@ class TestTrajectory(unittest.TestCase):
self.assertTrue(np.array_equal(self.importer.concatenated_samples.iloc[:, 1: len(self.importer.sorter) + 1], t1.trajectory))
self.assertEqual(len(self.importer.sorter) + 1, t1._original_cols_number)
+ self.assertEqual(self.importer.concatenated_samples.iloc[:,1:].to_numpy().shape[0], t1.size())
+ print(t1)
if __name__ == '__main__':
unittest.main()
diff --git a/PyCTBN/tests/utility/__init__.py b/PyCTBN/tests/utility/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/PyCTBN/tests/utility/test_json_importer.py b/PyCTBN/tests/utility/test_json_importer.py
index 9ae1aad..877805b 100644
--- a/PyCTBN/tests/utility/test_json_importer.py
+++ b/PyCTBN/tests/utility/test_json_importer.py
@@ -152,7 +152,7 @@ class TestJsonImporter(unittest.TestCase):
def test_file_path(self):
j1 = JsonImporter("./PyCTBN/test_data/networks_and_trajectories_binary_data_01_3.json", 'samples', 'dyn.str', 'variables', 'Time', 'Name')
- self.assertEqual(j1.file_path, "./PyCTBN/data/networks_and_trajectories_binary_data_01_3.json")
+ self.assertEqual(j1.file_path, "./PyCTBN/test_data/networks_and_trajectories_binary_data_01_3.json")
def test_import_data(self):
j1 = JsonImporter("./PyCTBN/test_data/networks_and_trajectories_binary_data_01_3.json", 'samples', 'dyn.str', 'variables', 'Time', 'Name')
diff --git a/PyCTBN/tests/utility/test_sample_importer.py b/PyCTBN/tests/utility/test_sample_importer.py
index 596e5d2..aa9a5a7 100644
--- a/PyCTBN/tests/utility/test_sample_importer.py
+++ b/PyCTBN/tests/utility/test_sample_importer.py
@@ -33,13 +33,15 @@ class TestSampleImporter(unittest.TestCase):
prior_net_structure=self.prior_net_structure
)
- sample_importer.import_data()
+ sample_importer.import_data(['X','Y','Z'])
s1 = SamplePath(sample_importer)
s1.build_trajectories()
s1.build_structure()
s1.clear_memory()
+ data_id= sample_importer.dataset_id()
+ self.assertEqual(data_id,"")
self.assertEqual(len(s1._importer._df_samples_list), 300)
self.assertIsInstance(s1._importer._df_samples_list,list)
self.assertIsInstance(s1._importer._df_samples_list[0],pd.DataFrame)
diff --git a/PyCTBN/basic_main.py b/basic_main.py
similarity index 100%
rename from PyCTBN/basic_main.py
rename to basic_main.py
diff --git a/coverage copy.xml b/coverage copy.xml
new file mode 100644
index 0000000..0d526b2
--- /dev/null
+++ b/coverage copy.xml
@@ -0,0 +1,2219 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/coverage.xml b/coverage.xml
new file mode 100644
index 0000000..79064a3
--- /dev/null
+++ b/coverage.xml
@@ -0,0 +1,1207 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PyCTBN/setup.py b/setup.py
similarity index 100%
rename from PyCTBN/setup.py
rename to setup.py