1
0
Fork 0

Correct project code-smells

better_develop
Filippo Martini 4 years ago
parent c93574650f
commit 50140c367c
  1. 4
      PyCTBN/PyCTBN/cache.py
  2. 2
      PyCTBN/PyCTBN/conditional_intensity_matrix.py
  3. 51
      PyCTBN/PyCTBN/network_graph.py
  4. 10
      PyCTBN/PyCTBN/parameters_estimator.py
  5. 2
      PyCTBN/PyCTBN/sample_path.py
  6. 2
      PyCTBN/PyCTBN/set_of_cims.py
  7. 4
      PyCTBN/PyCTBN/structure.py
  8. 21
      PyCTBN/PyCTBN/structure_estimator.py
  9. 6
      PyCTBN/PyCTBN/trajectory.py
  10. 963
      PyCTBN/tests/coverage.xml
  11. 25
      PyCTBN/tests/performance_comparisons.py
  12. 31
      PyCTBN/tests/test_json_importer.py
  13. 6
      PyCTBN/tests/test_networkgraph.py
  14. 2
      PyCTBN/tests/test_parameters_estimator.py
  15. 14
      PyCTBN/tests/test_sample_path.py
  16. 45
      PyCTBN/tests/test_structure_estimator.py
  17. 660
      coverage.xml

@ -4,7 +4,7 @@ import typing
from .set_of_cims import SetOfCims from .set_of_cims import SetOfCims
class Cache: class Cache(object):
"""This class acts as a cache of ``SetOfCims`` objects for a node. """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 :_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``. """Clear the contents both of ``_actual_cache`` and ``_list_of_sets_of_parents``.
""" """
del self._list_of_sets_of_parents[:] del self._list_of_sets_of_parents[:]
del self._actual_cache[:] del self._actual_cache[:]

@ -1,7 +1,7 @@
import numpy as np 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 """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. and state transition matrix and the actual CIM matrix.

@ -6,7 +6,7 @@ import numpy as np
from .structure import Structure from .structure import Structure
class NetworkGraph: class NetworkGraph(object):
"""Abstracts the infos contained in the Structure class in the form of a directed graph. """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 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) 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_indxs = self._aggregated_info_about_nodes_parents[1]
p_vals = self._aggregated_info_about_nodes_parents[2] 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, node_states = self.get_states_number(node_id)
p_vals)
self._transition_scalar_indexing_structure = self.build_transition_scalar_indexing_structure_for_a_node(node_id,
p_vals)
node_indx = self.get_node_indx(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) cols_number = self._graph_struct.total_variables_number
self._transition_filtering = self.build_transition_filtering_for_a_node(node_indx, p_indxs) self._time_scalar_indexing_structure = NetworkGraph.\
self._p_combs_structure = self.build_p_comb_structure_for_a_node(p_vals) 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: 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``. """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 get_node_indx = self.get_node_indx
p_indxes = [get_node_indx(node) for node in sorted_parents] p_indxes = [get_node_indx(node) for node in sorted_parents]
p_values = [self.get_states_number(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. """Builds an indexing structure for the computation of state residence times values.
:param node_id: the node label :param node_states: the node cardinality
:type node_id: string :type node_states: int
:param parents_vals: the caridinalites of the node's parents :param parents_vals: the caridinalites of the node's parents
:type parents_vals: List :type parents_vals: List
:return: The time indexing structure :return: The time indexing structure
:rtype: numpy.ndArray :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 = np.append(T_vector, parents_vals)
T_vector = T_vector.cumprod().astype(np.int) T_vector = T_vector.cumprod().astype(np.int)
return T_vector 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: -> np.ndarray:
"""Builds an indexing structure for the computation of state transitions values. """Builds an indexing structure for the computation of state transitions values.
:param node_id: the node label :param node_states_number: the node cardinality
:type node_id: string :type node_states_number: int
:param parents_vals: the caridinalites of the node's parents :param parents_vals: the caridinalites of the node's parents
:type parents_vals: List :type parents_vals: List
:return: The transition indexing structure :return: The transition indexing structure
:rtype: numpy.ndArray :rtype: numpy.ndArray
""" """
node_states_number = self.get_states_number(node_id)
M_vector = np.array([node_states_number, M_vector = np.array([node_states_number,
node_states_number]) node_states_number])
M_vector = np.append(M_vector, parents_vals) M_vector = np.append(M_vector, parents_vals)
M_vector = M_vector.cumprod().astype(np.int) M_vector = M_vector.cumprod().astype(np.int)
return M_vector 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`` Builds the necessary structure to filter the desired columns indicated by ``node_indx`` and ``p_indxs``
in the dataset. in the dataset.
@ -161,7 +166,9 @@ class NetworkGraph:
""" """
return np.append(np.array([node_indx], dtype=np.int), p_indxs).astype(np.int) 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`` """Builds the necessary structure to filter the desired columns indicated by ``node_indx`` and ``p_indxs``
in the dataset. in the dataset.
This structure will be used in the computation of the state transitions values. This structure will be used in the computation of the state transitions values.
@ -169,13 +176,15 @@ class NetworkGraph:
:type node_indx: int :type node_indx: int
:param p_indxs: the indexes of the node's parents :param p_indxs: the indexes of the node's parents
:type p_indxs: List :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 :return: The filtering structure for transitions estimation
:rtype: numpy.ndArray :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) 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 Builds the combinatorial structure that contains the combinations of all the values contained in
``parents_values``. ``parents_values``.

@ -6,7 +6,7 @@ from .set_of_cims import SetOfCims
from .network_graph import NetworkGraph 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 """Has the task of computing the cims of particular node given the trajectories and the net structure
in the graph ``_net_graph``. in the graph ``_net_graph``.
@ -45,7 +45,7 @@ class ParametersEstimator:
node_indx = self._net_graph.get_node_indx(node_id) node_indx = self._net_graph.get_node_indx(node_id)
state_res_times = self._single_set_of_cims._state_residence_times state_res_times = self._single_set_of_cims._state_residence_times
transition_matrices = self._single_set_of_cims._transition_matrices 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._trajectories.trajectory,
self._net_graph.time_filtering, self._net_graph.time_filtering,
self._net_graph.time_scalar_indexing_strucure, self._net_graph.time_scalar_indexing_strucure,
@ -58,7 +58,7 @@ class ParametersEstimator:
return self._single_set_of_cims return self._single_set_of_cims
@staticmethod @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, cols_filter: np.ndarray, scalar_indexes_struct: np.ndarray,
T: np.ndarray) -> None: T: np.ndarray) -> None:
"""Compute the state residence times for a node and fill the matrix ``T`` with the results """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])], 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) dtype=np.int64)
trj_tmp = trajectory[trajectory[:, int(trajectory.shape[1] / 2) + node_indx].astype(np.int) >= 0] 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), 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]) , minlength=scalar_indexing[-1]).reshape(-1, M.shape[1], M.shape[2])
M_raveled = M.ravel() M_raveled = M.ravel()
M_raveled[diag_indices] = 0 M_raveled[diag_indices] = 0
M_raveled[diag_indices] = np.sum(M, axis=2).ravel() M_raveled[diag_indices] = np.sum(M, axis=2).ravel()

@ -4,7 +4,7 @@ from .structure import Structure
from .trajectory import Trajectory 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 """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 cardinalites. Has the task of creating the objects ``Trajectory`` and ``Structure`` that will
contain the mentioned data. contain the mentioned data.

@ -4,7 +4,7 @@ import numpy as np
from .conditional_intensity_matrix import ConditionalIntensityMatrix from .conditional_intensity_matrix import ConditionalIntensityMatrix
class SetOfCims: class SetOfCims(object):
"""Aggregates all the CIMS of the node identified by the label _node_id. """Aggregates all the CIMS of the node identified by the label _node_id.
:param node_id: the node label :param node_id: the node label

@ -2,7 +2,7 @@ import typing as ty
import numpy as np import numpy as np
class Structure: class Structure(object):
"""Contains all the infos about the network structure(nodes labels, nodes caridinalites, edges, indexes) """Contains all the infos about the network structure(nodes labels, nodes caridinalites, edges, indexes)
:param nodes_labels_list: the symbolic names of the variables :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 \ np.array_equal(self._nodes_indexes_arr, other._nodes_indexes_arr) and \
self._edges_list == other._edges_list self._edges_list == other._edges_list
return NotImplemented return False

@ -17,7 +17,7 @@ from .sample_path import SamplePath
from .structure import Structure from .structure import Structure
class StructureEstimator: class StructureEstimator(object):
"""Has the task of estimating the network structure given the trajectories in ``samplepath``. """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 :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 = np.array(self._sample_path.structure.nodes_labels)
self._nodes_vals = self._sample_path.structure.nodes_values self._nodes_vals = self._sample_path.structure.nodes_values
self._nodes_indxs = self._sample_path.structure.nodes_indexes 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._exp_test_sign = exp_test_alfa
self._chi_test_alfa = chi_test_alfa self._chi_test_alfa = chi_test_alfa
self._cache = Cache() 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``: """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 :param node_ids: the list of nodes labels
@ -176,7 +177,7 @@ class StructureEstimator:
parent_indx = 0 parent_indx = 0
while parent_indx < len(u): while parent_indx < len(u):
removed = False 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] test_parent = u[parent_indx]
for parents_set in S: for parents_set in S:
if self.complete_test(test_parent, var_id, parents_set, child_states_numb, tot_vars_count): if self.complete_test(test_parent, var_id, parents_set, child_states_numb, tot_vars_count):
@ -189,7 +190,8 @@ class StructureEstimator:
b += 1 b += 1
self._cache.clear() 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: typing.Iterator:
"""Creates a list containing all possible subsets of the list ``u`` of size ``size``, """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``. 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. 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) 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 = self._sample_path._importer.file_path.rsplit('/', 1)[-1]
name = 'results_' + name name = name.split('.', 1)[0]
with open(name, 'w') as f: 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) json.dump(res, f)
def adjacency_matrix(self) -> np.ndarray: def adjacency_matrix(self) -> np.ndarray:

@ -3,9 +3,9 @@ import numpy as np
import typing import typing
class Trajectory: class Trajectory(object):
""" Abstracts the infos about a complete set of trajectories, represented as a numpy array of doubles (the time deltas) """ Abstracts the infos about a complete set of trajectories, represented as a numpy array of doubles
and a numpy matrix of ints (the changes of states). (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 :param list_of_columns: the list containing the times array and values matrix
:type list_of_columns: List :type list_of_columns: List

@ -1,963 +0,0 @@
<?xml version="1.0" ?>
<coverage version="5.2" timestamp="1597406229874" lines-valid="891" lines-covered="638" line-rate="0.716" branches-covered="0" branches-valid="0" branch-rate="0" complexity="0">
<!-- Generated by coverage.py: https://coverage.readthedocs.io -->
<!-- Based on https://raw.githubusercontent.com/cobertura/web/master/htdocs/xml/coverage-04.dtd -->
<sources>
<source></source>
</sources>
<packages>
<package name="." line-rate="1" branch-rate="0" complexity="0">
<classes>
<class name="test_json_importer.py" filename="test_json_importer.py" complexity="0" line-rate="1" branch-rate="0">
<methods/>
<lines>
<line number="1" hits="1"/>
<line number="2" hits="1"/>
<line number="3" hits="1"/>
<line number="4" hits="1"/>
<line number="5" hits="1"/>
<line number="6" hits="1"/>
<line number="7" hits="1"/>
<line number="8" hits="1"/>
<line number="10" hits="1"/>
<line number="12" hits="1"/>
<line number="16" hits="1"/>
<line number="18" hits="1"/>
<line number="19" hits="1"/>
<line number="20" hits="1"/>
<line number="22" hits="1"/>
<line number="23" hits="1"/>
<line number="24" hits="1"/>
<line number="25" hits="1"/>
<line number="26" hits="1"/>
<line number="27" hits="1"/>
<line number="28" hits="1"/>
<line number="29" hits="1"/>
<line number="30" hits="1"/>
<line number="31" hits="1"/>
<line number="32" hits="1"/>
<line number="33" hits="1"/>
<line number="34" hits="1"/>
<line number="36" hits="1"/>
<line number="37" hits="1"/>
<line number="38" hits="1"/>
<line number="39" hits="1"/>
<line number="40" hits="1"/>
<line number="41" hits="1"/>
<line number="42" hits="1"/>
<line number="43" hits="1"/>
<line number="44" hits="1"/>
<line number="45" hits="1"/>
<line number="47" hits="1"/>
<line number="48" hits="1"/>
<line number="49" hits="1"/>
<line number="50" hits="1"/>
<line number="51" hits="1"/>
<line number="53" hits="1"/>
<line number="54" hits="1"/>
<line number="55" hits="1"/>
<line number="57" hits="1"/>
<line number="58" hits="1"/>
<line number="59" hits="1"/>
<line number="61" hits="1"/>
<line number="62" hits="1"/>
<line number="63" hits="1"/>
<line number="64" hits="1"/>
<line number="66" hits="1"/>
<line number="67" hits="1"/>
<line number="68" hits="1"/>
<line number="69" hits="1"/>
<line number="71" hits="1"/>
<line number="72" hits="1"/>
<line number="73" hits="1"/>
<line number="74" hits="1"/>
<line number="75" hits="1"/>
<line number="76" hits="1"/>
<line number="77" hits="1"/>
<line number="78" hits="1"/>
<line number="80" hits="1"/>
<line number="82" hits="1"/>
<line number="84" hits="1"/>
<line number="85" hits="1"/>
<line number="86" hits="1"/>
<line number="87" hits="1"/>
<line number="88" hits="1"/>
<line number="89" hits="1"/>
<line number="90" hits="1"/>
<line number="92" hits="1"/>
<line number="93" hits="1"/>
<line number="94" hits="1"/>
<line number="95" hits="1"/>
<line number="96" hits="1"/>
<line number="97" hits="1"/>
<line number="98" hits="1"/>
<line number="99" hits="1"/>
<line number="101" hits="1"/>
<line number="102" hits="1"/>
<line number="103" hits="1"/>
<line number="104" hits="1"/>
<line number="105" hits="1"/>
<line number="107" hits="1"/>
<line number="108" hits="1"/>
<line number="109" hits="1"/>
<line number="110" hits="1"/>
<line number="111" hits="1"/>
<line number="112" hits="1"/>
<line number="113" hits="1"/>
<line number="114" hits="1"/>
<line number="115" hits="1"/>
<line number="116" hits="1"/>
<line number="117" hits="1"/>
<line number="118" hits="1"/>
<line number="119" hits="1"/>
<line number="120" hits="1"/>
<line number="121" hits="1"/>
<line number="122" hits="1"/>
<line number="124" hits="1"/>
<line number="125" hits="1"/>
<line number="126" hits="1"/>
<line number="127" hits="1"/>
<line number="128" hits="1"/>
<line number="129" hits="1"/>
<line number="131" hits="1"/>
<line number="132" hits="1"/>
<line number="133" hits="1"/>
<line number="134" hits="1"/>
<line number="136" hits="1"/>
<line number="138" hits="1"/>
<line number="139" hits="1"/>
<line number="140" hits="1"/>
<line number="141" hits="1"/>
<line number="142" hits="1"/>
<line number="143" hits="1"/>
<line number="145" hits="1"/>
<line number="146" hits="1"/>
<line number="147" hits="1"/>
<line number="154" hits="1"/>
<line number="156" hits="1"/>
<line number="157" hits="1"/>
<line number="158" hits="1"/>
<line number="160" hits="1"/>
<line number="161" hits="1"/>
<line number="162" hits="1"/>
<line number="163" hits="1"/>
<line number="164" hits="1"/>
<line number="166" hits="1"/>
<line number="169" hits="1"/>
<line number="170" hits="1"/>
</lines>
</class>
<class name="test_sample_path.py" filename="test_sample_path.py" complexity="0" line-rate="1" branch-rate="0">
<methods/>
<lines>
<line number="1" hits="1"/>
<line number="2" hits="1"/>
<line number="3" hits="1"/>
<line number="4" hits="1"/>
<line number="5" hits="1"/>
<line number="6" hits="1"/>
<line number="7" hits="1"/>
<line number="8" hits="1"/>
<line number="9" hits="1"/>
<line number="12" hits="1"/>
<line number="14" hits="1"/>
<line number="15" hits="1"/>
<line number="16" hits="1"/>
<line number="17" hits="1"/>
<line number="19" hits="1"/>
<line number="20" hits="1"/>
<line number="21" hits="1"/>
<line number="22" hits="1"/>
<line number="23" hits="1"/>
<line number="24" hits="1"/>
<line number="25" hits="1"/>
<line number="26" hits="1"/>
<line number="27" hits="1"/>
<line number="28" hits="1"/>
<line number="29" hits="1"/>
<line number="30" hits="1"/>
<line number="33" hits="1"/>
<line number="34" hits="1"/>
</lines>
</class>
<class name="test_trajectory.py" filename="test_trajectory.py" complexity="0" line-rate="1" branch-rate="0">
<methods/>
<lines>
<line number="1" hits="1"/>
<line number="2" hits="1"/>
<line number="3" hits="1"/>
<line number="4" hits="1"/>
<line number="6" hits="1"/>
<line number="9" hits="1"/>
<line number="11" hits="1"/>
<line number="12" hits="1"/>
<line number="13" hits="1"/>
<line number="14" hits="1"/>
<line number="15" hits="1"/>
<line number="16" hits="1"/>
<line number="17" hits="1"/>
<line number="18" hits="1"/>
<line number="20" hits="1"/>
<line number="21" hits="1"/>
<line number="22" hits="1"/>
<line number="24" hits="1"/>
<line number="25" hits="1"/>
<line number="26" hits="1"/>
<line number="27" hits="1"/>
<line number="28" hits="1"/>
<line number="30" hits="1"/>
<line number="31" hits="1"/>
<line number="32" hits="1"/>
<line number="33" hits="1"/>
<line number="35" hits="1"/>
<line number="36" hits="1"/>
<line number="37" hits="1"/>
<line number="38" hits="1"/>
<line number="40" hits="1"/>
<line number="41" hits="1"/>
<line number="42" hits="1"/>
<line number="43" hits="1"/>
<line number="46" hits="1"/>
<line number="47" hits="1"/>
</lines>
</class>
</classes>
</package>
<package name=".Users.Zalum.Desktop.Tesi.CTBN_Project.main_package.classes" line-rate="0.9059" branch-rate="0" complexity="0">
<classes>
<class name="abstract_importer.py" filename="/Users/Zalum/Desktop/Tesi/CTBN_Project/main_package/classes/abstract_importer.py" complexity="0" line-rate="0.8182" branch-rate="0">
<methods/>
<lines>
<line number="1" hits="1"/>
<line number="4" hits="1"/>
<line number="12" hits="1"/>
<line number="13" hits="1"/>
<line number="14" hits="1"/>
<line number="16" hits="1"/>
<line number="17" hits="1"/>
<line number="18" hits="0"/>
<line number="20" hits="1"/>
<line number="21" hits="1"/>
<line number="22" hits="0"/>
</lines>
</class>
<class name="abstract_sample_path.py" filename="/Users/Zalum/Desktop/Tesi/CTBN_Project/main_package/classes/abstract_sample_path.py" complexity="0" line-rate="0.8571" branch-rate="0">
<methods/>
<lines>
<line number="1" hits="1"/>
<line number="2" hits="1"/>
<line number="5" hits="1"/>
<line number="7" hits="1"/>
<line number="8" hits="1"/>
<line number="9" hits="1"/>
<line number="10" hits="1"/>
<line number="11" hits="1"/>
<line number="13" hits="1"/>
<line number="14" hits="1"/>
<line number="25" hits="0"/>
<line number="27" hits="1"/>
<line number="28" hits="1"/>
<line number="37" hits="0"/>
</lines>
</class>
<class name="json_importer.py" filename="/Users/Zalum/Desktop/Tesi/CTBN_Project/main_package/classes/json_importer.py" complexity="0" line-rate="1" branch-rate="0">
<methods/>
<lines>
<line number="2" hits="1"/>
<line number="3" hits="1"/>
<line number="4" hits="1"/>
<line number="5" hits="1"/>
<line number="8" hits="1"/>
<line number="30" hits="1"/>
<line number="32" hits="1"/>
<line number="33" hits="1"/>
<line number="34" hits="1"/>
<line number="35" hits="1"/>
<line number="36" hits="1"/>
<line number="37" hits="1"/>
<line number="38" hits="1"/>
<line number="39" hits="1"/>
<line number="40" hits="1"/>
<line number="41" hits="1"/>
<line number="42" hits="1"/>
<line number="44" hits="1"/>
<line number="52" hits="1"/>
<line number="53" hits="1"/>
<line number="54" hits="1"/>
<line number="55" hits="1"/>
<line number="56" hits="1"/>
<line number="57" hits="1"/>
<line number="59" hits="1"/>
<line number="67" hits="1"/>
<line number="69" hits="1"/>
<line number="78" hits="1"/>
<line number="81" hits="1"/>
<line number="92" hits="1"/>
<line number="96" hits="1"/>
<line number="97" hits="1"/>
<line number="98" hits="1"/>
<line number="99" hits="1"/>
<line number="100" hits="1"/>
<line number="102" hits="1"/>
<line number="116" hits="1"/>
<line number="117" hits="1"/>
<line number="118" hits="1"/>
<line number="122" hits="1"/>
<line number="134" hits="1"/>
<line number="136" hits="1"/>
<line number="149" hits="1"/>
<line number="150" hits="1"/>
<line number="151" hits="1"/>
<line number="152" hits="1"/>
<line number="153" hits="1"/>
<line number="154" hits="1"/>
<line number="156" hits="1"/>
<line number="171" hits="1"/>
<line number="172" hits="1"/>
<line number="174" hits="1"/>
<line number="175" hits="1"/>
<line number="176" hits="1"/>
<line number="177" hits="1"/>
<line number="179" hits="1"/>
<line number="189" hits="1"/>
<line number="190" hits="1"/>
<line number="191" hits="1"/>
<line number="193" hits="1"/>
<line number="194" hits="1"/>
<line number="195" hits="1"/>
<line number="196" hits="1"/>
<line number="198" hits="1"/>
<line number="201" hits="1"/>
<line number="209" hits="1"/>
<line number="212" hits="1"/>
<line number="214" hits="1"/>
<line number="222" hits="1"/>
<line number="224" hits="1"/>
<line number="228" hits="1"/>
<line number="229" hits="1"/>
<line number="231" hits="1"/>
<line number="232" hits="1"/>
<line number="233" hits="1"/>
<line number="234" hits="1"/>
<line number="235" hits="1"/>
<line number="236" hits="1"/>
<line number="237" hits="1"/>
<line number="238" hits="1"/>
<line number="240" hits="1"/>
<line number="241" hits="1"/>
<line number="242" hits="1"/>
<line number="244" hits="1"/>
<line number="245" hits="1"/>
<line number="246" hits="1"/>
<line number="248" hits="1"/>
<line number="249" hits="1"/>
<line number="250" hits="1"/>
</lines>
</class>
<class name="sample_path.py" filename="/Users/Zalum/Desktop/Tesi/CTBN_Project/main_package/classes/sample_path.py" complexity="0" line-rate="0.963" branch-rate="0">
<methods/>
<lines>
<line number="1" hits="1"/>
<line number="2" hits="1"/>
<line number="3" hits="1"/>
<line number="4" hits="1"/>
<line number="7" hits="1"/>
<line number="22" hits="1"/>
<line number="24" hits="1"/>
<line number="27" hits="1"/>
<line number="29" hits="1"/>
<line number="39" hits="1"/>
<line number="40" hits="1"/>
<line number="44" hits="1"/>
<line number="46" hits="1"/>
<line number="54" hits="1"/>
<line number="55" hits="1"/>
<line number="57" hits="1"/>
<line number="58" hits="1"/>
<line number="59" hits="1"/>
<line number="60" hits="1"/>
<line number="63" hits="1"/>
<line number="64" hits="1"/>
<line number="65" hits="1"/>
<line number="67" hits="1"/>
<line number="68" hits="1"/>
<line number="69" hits="1"/>
<line number="71" hits="1"/>
<line number="72" hits="0"/>
</lines>
</class>
<class name="structure.py" filename="/Users/Zalum/Desktop/Tesi/CTBN_Project/main_package/classes/structure.py" complexity="0" line-rate="0.65" branch-rate="0">
<methods/>
<lines>
<line number="1" hits="1"/>
<line number="2" hits="1"/>
<line number="5" hits="1"/>
<line number="16" hits="1"/>
<line number="18" hits="1"/>
<line number="19" hits="1"/>
<line number="20" hits="1"/>
<line number="21" hits="1"/>
<line number="22" hits="1"/>
<line number="24" hits="1"/>
<line number="25" hits="1"/>
<line number="28" hits="0"/>
<line number="30" hits="1"/>
<line number="31" hits="1"/>
<line number="32" hits="0"/>
<line number="34" hits="1"/>
<line number="35" hits="1"/>
<line number="36" hits="0"/>
<line number="38" hits="1"/>
<line number="39" hits="1"/>
<line number="40" hits="0"/>
<line number="42" hits="1"/>
<line number="43" hits="1"/>
<line number="44" hits="0"/>
<line number="46" hits="1"/>
<line number="47" hits="0"/>
<line number="49" hits="1"/>
<line number="50" hits="0"/>
<line number="51" hits="0"/>
<line number="53" hits="1"/>
<line number="54" hits="0"/>
<line number="56" hits="1"/>
<line number="57" hits="0"/>
<line number="58" hits="0"/>
<line number="60" hits="1"/>
<line number="61" hits="1"/>
<line number="64" hits="1"/>
<line number="66" hits="0"/>
<line number="67" hits="0"/>
<line number="72" hits="0"/>
</lines>
</class>
<class name="trajectory.py" filename="/Users/Zalum/Desktop/Tesi/CTBN_Project/main_package/classes/trajectory.py" complexity="0" line-rate="1" branch-rate="0">
<methods/>
<lines>
<line number="2" hits="1"/>
<line number="5" hits="1"/>
<line number="17" hits="1"/>
<line number="18" hits="1"/>
<line number="19" hits="1"/>
<line number="20" hits="1"/>
<line number="21" hits="1"/>
<line number="22" hits="1"/>
<line number="24" hits="1"/>
<line number="25" hits="1"/>
<line number="32" hits="1"/>
<line number="34" hits="1"/>
<line number="35" hits="1"/>
<line number="42" hits="1"/>
<line number="44" hits="1"/>
<line number="45" hits="1"/>
<line number="46" hits="1"/>
<line number="48" hits="1"/>
<line number="49" hits="1"/>
<line number="51" hits="1"/>
<line number="52" hits="1"/>
</lines>
</class>
</classes>
</package>
<package name=".Users.Zalum.Library.Python.3.8.lib.python.site-packages" line-rate="0.5234" branch-rate="0" complexity="0">
<classes>
<class name="six.py" filename="/Users/Zalum/Library/Python/3.8/lib/python/site-packages/six.py" complexity="0" line-rate="0.5234" branch-rate="0">
<methods/>
<lines>
<line number="21" hits="1"/>
<line number="23" hits="1"/>
<line number="25" hits="1"/>
<line number="26" hits="1"/>
<line number="27" hits="1"/>
<line number="28" hits="1"/>
<line number="29" hits="1"/>
<line number="31" hits="1"/>
<line number="32" hits="1"/>
<line number="36" hits="1"/>
<line number="37" hits="1"/>
<line number="38" hits="1"/>
<line number="40" hits="1"/>
<line number="41" hits="1"/>
<line number="42" hits="1"/>
<line number="43" hits="1"/>
<line number="44" hits="1"/>
<line number="45" hits="1"/>
<line number="47" hits="1"/>
<line number="49" hits="0"/>
<line number="50" hits="0"/>
<line number="51" hits="0"/>
<line number="52" hits="0"/>
<line number="53" hits="0"/>
<line number="55" hits="0"/>
<line number="57" hits="0"/>
<line number="60" hits="0"/>
<line number="62" hits="0"/>
<line number="63" hits="0"/>
<line number="64" hits="0"/>
<line number="65" hits="0"/>
<line number="66" hits="0"/>
<line number="68" hits="0"/>
<line number="71" hits="0"/>
<line number="72" hits="0"/>
<line number="75" hits="1"/>
<line number="77" hits="1"/>
<line number="80" hits="1"/>
<line number="82" hits="1"/>
<line number="83" hits="1"/>
<line number="86" hits="1"/>
<line number="88" hits="1"/>
<line number="89" hits="1"/>
<line number="91" hits="1"/>
<line number="92" hits="1"/>
<line number="93" hits="1"/>
<line number="94" hits="1"/>
<line number="97" hits="1"/>
<line number="98" hits="0"/>
<line number="99" hits="0"/>
<line number="100" hits="1"/>
<line number="103" hits="1"/>
<line number="105" hits="1"/>
<line number="106" hits="1"/>
<line number="107" hits="1"/>
<line number="108" hits="1"/>
<line number="109" hits="1"/>
<line number="110" hits="1"/>
<line number="112" hits="0"/>
<line number="114" hits="1"/>
<line number="115" hits="1"/>
<line number="117" hits="1"/>
<line number="118" hits="0"/>
<line number="119" hits="0"/>
<line number="120" hits="0"/>
<line number="121" hits="0"/>
<line number="124" hits="1"/>
<line number="126" hits="1"/>
<line number="127" hits="1"/>
<line number="128" hits="1"/>
<line number="130" hits="1"/>
<line number="131" hits="0"/>
<line number="132" hits="0"/>
<line number="133" hits="0"/>
<line number="136" hits="1"/>
<line number="139" hits="1"/>
<line number="141" hits="1"/>
<line number="142" hits="1"/>
<line number="143" hits="1"/>
<line number="144" hits="1"/>
<line number="145" hits="0"/>
<line number="146" hits="1"/>
<line number="147" hits="1"/>
<line number="148" hits="1"/>
<line number="149" hits="1"/>
<line number="151" hits="1"/>
<line number="152" hits="1"/>
<line number="154" hits="0"/>
<line number="155" hits="0"/>
<line number="156" hits="0"/>
<line number="157" hits="0"/>
<line number="159" hits="1"/>
<line number="160" hits="0"/>
<line number="161" hits="0"/>
<line number="164" hits="1"/>
<line number="173" hits="1"/>
<line number="174" hits="1"/>
<line number="175" hits="1"/>
<line number="177" hits="1"/>
<line number="178" hits="1"/>
<line number="179" hits="1"/>
<line number="181" hits="1"/>
<line number="182" hits="1"/>
<line number="184" hits="1"/>
<line number="185" hits="1"/>
<line number="186" hits="1"/>
<line number="187" hits="1"/>
<line number="189" hits="1"/>
<line number="190" hits="1"/>
<line number="191" hits="1"/>
<line number="192" hits="0"/>
<line number="193" hits="0"/>
<line number="195" hits="1"/>
<line number="196" hits="1"/>
<line number="198" hits="1"/>
<line number="199" hits="1"/>
<line number="200" hits="1"/>
<line number="201" hits="1"/>
<line number="202" hits="1"/>
<line number="203" hits="0"/>
<line number="205" hits="1"/>
<line number="206" hits="1"/>
<line number="207" hits="1"/>
<line number="209" hits="1"/>
<line number="216" hits="1"/>
<line number="218" hits="1"/>
<line number="222" hits="0"/>
<line number="223" hits="0"/>
<line number="224" hits="1"/>
<line number="226" hits="1"/>
<line number="229" hits="1"/>
<line number="232" hits="1"/>
<line number="235" hits="1"/>
<line number="307" hits="1"/>
<line number="308" hits="0"/>
<line number="312" hits="1"/>
<line number="313" hits="1"/>
<line number="314" hits="1"/>
<line number="315" hits="1"/>
<line number="316" hits="1"/>
<line number="318" hits="1"/>
<line number="320" hits="1"/>
<line number="321" hits="1"/>
<line number="324" hits="1"/>
<line number="329" hits="1"/>
<line number="356" hits="1"/>
<line number="357" hits="1"/>
<line number="358" hits="1"/>
<line number="360" hits="1"/>
<line number="362" hits="1"/>
<line number="366" hits="1"/>
<line number="371" hits="1"/>
<line number="376" hits="1"/>
<line number="377" hits="1"/>
<line number="378" hits="1"/>
<line number="380" hits="1"/>
<line number="382" hits="1"/>
<line number="386" hits="1"/>
<line number="391" hits="1"/>
<line number="428" hits="1"/>
<line number="429" hits="1"/>
<line number="430" hits="1"/>
<line number="432" hits="1"/>
<line number="434" hits="1"/>
<line number="438" hits="1"/>
<line number="443" hits="1"/>
<line number="449" hits="1"/>
<line number="450" hits="1"/>
<line number="451" hits="1"/>
<line number="453" hits="1"/>
<line number="455" hits="1"/>
<line number="459" hits="1"/>
<line number="464" hits="1"/>
<line number="467" hits="1"/>
<line number="468" hits="1"/>
<line number="469" hits="1"/>
<line number="471" hits="1"/>
<line number="473" hits="1"/>
<line number="477" hits="1"/>
<line number="480" hits="1"/>
<line number="481" hits="1"/>
<line number="482" hits="1"/>
<line number="483" hits="1"/>
<line number="484" hits="1"/>
<line number="485" hits="1"/>
<line number="487" hits="1"/>
<line number="488" hits="0"/>
<line number="490" hits="1"/>
<line number="494" hits="1"/>
<line number="496" hits="0"/>
<line number="499" hits="1"/>
<line number="501" hits="0"/>
<line number="502" hits="0"/>
<line number="503" hits="0"/>
<line number="504" hits="0"/>
<line number="505" hits="0"/>
<line number="506" hits="0"/>
<line number="507" hits="0"/>
<line number="510" hits="1"/>
<line number="511" hits="1"/>
<line number="512" hits="1"/>
<line number="514" hits="1"/>
<line number="515" hits="1"/>
<line number="516" hits="1"/>
<line number="517" hits="1"/>
<line number="519" hits="0"/>
<line number="520" hits="0"/>
<line number="522" hits="0"/>
<line number="523" hits="0"/>
<line number="524" hits="0"/>
<line number="525" hits="0"/>
<line number="528" hits="1"/>
<line number="529" hits="1"/>
<line number="530" hits="0"/>
<line number="531" hits="0"/>
<line number="532" hits="0"/>
<line number="533" hits="1"/>
<line number="536" hits="1"/>
<line number="537" hits="1"/>
<line number="538" hits="0"/>
<line number="539" hits="0"/>
<line number="540" hits="0"/>
<line number="543" hits="1"/>
<line number="544" hits="1"/>
<line number="545" hits="0"/>
<line number="547" hits="1"/>
<line number="549" hits="1"/>
<line number="550" hits="0"/>
<line number="552" hits="1"/>
<line number="554" hits="0"/>
<line number="555" hits="0"/>
<line number="557" hits="0"/>
<line number="558" hits="0"/>
<line number="560" hits="0"/>
<line number="561" hits="0"/>
<line number="563" hits="0"/>
<line number="565" hits="0"/>
<line number="566" hits="0"/>
<line number="568" hits="0"/>
<line number="569" hits="1"/>
<line number="573" hits="1"/>
<line number="574" hits="1"/>
<line number="575" hits="1"/>
<line number="576" hits="1"/>
<line number="577" hits="1"/>
<line number="578" hits="1"/>
<line number="581" hits="1"/>
<line number="582" hits="1"/>
<line number="583" hits="0"/>
<line number="585" hits="1"/>
<line number="586" hits="0"/>
<line number="588" hits="1"/>
<line number="589" hits="0"/>
<line number="591" hits="1"/>
<line number="592" hits="0"/>
<line number="594" hits="1"/>
<line number="596" hits="1"/>
<line number="598" hits="1"/>
<line number="600" hits="0"/>
<line number="601" hits="0"/>
<line number="603" hits="0"/>
<line number="604" hits="0"/>
<line number="606" hits="0"/>
<line number="607" hits="0"/>
<line number="609" hits="0"/>
<line number="610" hits="0"/>
<line number="612" hits="0"/>
<line number="614" hits="0"/>
<line number="616" hits="0"/>
<line number="618" hits="1"/>
<line number="619" hits="1"/>
<line number="620" hits="1"/>
<line number="622" hits="1"/>
<line number="626" hits="1"/>
<line number="627" hits="1"/>
<line number="628" hits="0"/>
<line number="630" hits="1"/>
<line number="631" hits="0"/>
<line number="632" hits="1"/>
<line number="633" hits="1"/>
<line number="634" hits="1"/>
<line number="635" hits="1"/>
<line number="636" hits="1"/>
<line number="637" hits="1"/>
<line number="638" hits="1"/>
<line number="639" hits="1"/>
<line number="640" hits="1"/>
<line number="641" hits="1"/>
<line number="642" hits="1"/>
<line number="643" hits="1"/>
<line number="644" hits="1"/>
<line number="645" hits="0"/>
<line number="646" hits="0"/>
<line number="647" hits="0"/>
<line number="649" hits="1"/>
<line number="650" hits="1"/>
<line number="651" hits="1"/>
<line number="653" hits="0"/>
<line number="654" hits="0"/>
<line number="657" hits="0"/>
<line number="658" hits="0"/>
<line number="659" hits="0"/>
<line number="660" hits="0"/>
<line number="662" hits="0"/>
<line number="663" hits="0"/>
<line number="665" hits="0"/>
<line number="666" hits="0"/>
<line number="667" hits="0"/>
<line number="668" hits="0"/>
<line number="669" hits="0"/>
<line number="670" hits="0"/>
<line number="671" hits="0"/>
<line number="672" hits="0"/>
<line number="673" hits="0"/>
<line number="674" hits="1"/>
<line number="675" hits="1"/>
<line number="678" hits="1"/>
<line number="679" hits="0"/>
<line number="682" hits="1"/>
<line number="683" hits="0"/>
<line number="686" hits="1"/>
<line number="687" hits="0"/>
<line number="690" hits="1"/>
<line number="691" hits="0"/>
<line number="694" hits="1"/>
<line number="695" hits="1"/>
<line number="697" hits="1"/>
<line number="698" hits="0"/>
<line number="699" hits="0"/>
<line number="700" hits="0"/>
<line number="701" hits="0"/>
<line number="702" hits="0"/>
<line number="703" hits="0"/>
<line number="705" hits="0"/>
<line number="706" hits="0"/>
<line number="709" hits="0"/>
<line number="711" hits="0"/>
<line number="712" hits="0"/>
<line number="713" hits="0"/>
<line number="714" hits="0"/>
<line number="715" hits="0"/>
<line number="716" hits="0"/>
<line number="717" hits="0"/>
<line number="718" hits="0"/>
<line number="719" hits="0"/>
<line number="721" hits="0"/>
<line number="729" hits="1"/>
<line number="730" hits="1"/>
<line number="737" hits="0"/>
<line number="738" hits="0"/>
<line number="741" hits="1"/>
<line number="742" hits="1"/>
<line number="743" hits="0"/>
<line number="745" hits="0"/>
<line number="746" hits="0"/>
<line number="747" hits="0"/>
<line number="749" hits="0"/>
<line number="750" hits="0"/>
<line number="751" hits="0"/>
<line number="753" hits="0"/>
<line number="756" hits="0"/>
<line number="757" hits="0"/>
<line number="758" hits="0"/>
<line number="759" hits="0"/>
<line number="760" hits="0"/>
<line number="761" hits="0"/>
<line number="762" hits="0"/>
<line number="763" hits="0"/>
<line number="764" hits="0"/>
<line number="765" hits="0"/>
<line number="766" hits="0"/>
<line number="767" hits="0"/>
<line number="768" hits="0"/>
<line number="769" hits="0"/>
<line number="770" hits="0"/>
<line number="771" hits="0"/>
<line number="772" hits="0"/>
<line number="773" hits="0"/>
<line number="774" hits="0"/>
<line number="775" hits="0"/>
<line number="776" hits="0"/>
<line number="777" hits="0"/>
<line number="778" hits="0"/>
<line number="779" hits="0"/>
<line number="780" hits="0"/>
<line number="781" hits="0"/>
<line number="782" hits="0"/>
<line number="783" hits="0"/>
<line number="785" hits="0"/>
<line number="786" hits="0"/>
<line number="787" hits="0"/>
<line number="788" hits="0"/>
<line number="789" hits="0"/>
<line number="790" hits="0"/>
<line number="791" hits="0"/>
<line number="792" hits="0"/>
<line number="793" hits="0"/>
<line number="794" hits="0"/>
<line number="795" hits="0"/>
<line number="796" hits="1"/>
<line number="797" hits="0"/>
<line number="799" hits="0"/>
<line number="800" hits="0"/>
<line number="801" hits="0"/>
<line number="802" hits="0"/>
<line number="803" hits="0"/>
<line number="804" hits="0"/>
<line number="806" hits="1"/>
<line number="808" hits="1"/>
<line number="814" hits="0"/>
<line number="817" hits="0"/>
<line number="818" hits="0"/>
<line number="819" hits="0"/>
<line number="820" hits="0"/>
<line number="821" hits="0"/>
<line number="823" hits="0"/>
<line number="824" hits="0"/>
<line number="825" hits="0"/>
<line number="826" hits="0"/>
<line number="827" hits="0"/>
<line number="828" hits="0"/>
<line number="830" hits="0"/>
<line number="832" hits="0"/>
<line number="834" hits="0"/>
<line number="837" hits="1"/>
<line number="840" hits="1"/>
<line number="845" hits="1"/>
<line number="847" hits="1"/>
<line number="848" hits="1"/>
<line number="851" hits="1"/>
<line number="852" hits="1"/>
<line number="853" hits="0"/>
<line number="855" hits="0"/>
<line number="856" hits="1"/>
<line number="858" hits="1"/>
<line number="859" hits="1"/>
<line number="860" hits="1"/>
<line number="861" hits="1"/>
<line number="864" hits="1"/>
<line number="866" hits="1"/>
<line number="867" hits="1"/>
<line number="868" hits="1"/>
<line number="869" hits="1"/>
<line number="870" hits="0"/>
<line number="871" hits="0"/>
<line number="872" hits="0"/>
<line number="873" hits="0"/>
<line number="874" hits="1"/>
<line number="875" hits="1"/>
<line number="876" hits="1"/>
<line number="877" hits="1"/>
<line number="878" hits="1"/>
<line number="879" hits="1"/>
<line number="882" hits="1"/>
<line number="893" hits="0"/>
<line number="894" hits="0"/>
<line number="895" hits="0"/>
<line number="896" hits="0"/>
<line number="898" hits="0"/>
<line number="901" hits="1"/>
<line number="912" hits="0"/>
<line number="913" hits="0"/>
<line number="914" hits="0"/>
<line number="915" hits="0"/>
<line number="916" hits="0"/>
<line number="917" hits="0"/>
<line number="918" hits="0"/>
<line number="921" hits="1"/>
<line number="932" hits="0"/>
<line number="933" hits="0"/>
<line number="934" hits="0"/>
<line number="935" hits="0"/>
<line number="937" hits="0"/>
<line number="940" hits="1"/>
<line number="948" hits="0"/>
<line number="949" hits="0"/>
<line number="950" hits="0"/>
<line number="953" hits="0"/>
<line number="954" hits="0"/>
<line number="955" hits="0"/>
<line number="961" hits="1"/>
<line number="962" hits="1"/>
<line number="963" hits="1"/>
<line number="964" hits="1"/>
<line number="968" hits="1"/>
<line number="969" hits="1"/>
<line number="974" hits="1"/>
<line number="976" hits="0"/>
<line number="977" hits="0"/>
<line number="978" hits="1"/>
<line number="980" hits="1"/>
</lines>
</class>
</classes>
</package>
</packages>
</coverage>

@ -4,6 +4,7 @@ import glob
import numpy as np import numpy as np
import pandas as pd import pandas as pd
import timeit import timeit
import psutil
from ..PyCTBN.sample_path import SamplePath from ..PyCTBN.sample_path import SamplePath
from ..PyCTBN.structure_estimator import StructureEstimator from ..PyCTBN.structure_estimator import StructureEstimator
@ -23,6 +24,7 @@ class PerformanceComparisons(unittest.TestCase):
cls.original_times = [] cls.original_times = []
cls.optimized_times = [] cls.optimized_times = []
cls.results = [] cls.results = []
cls.memory_usages = []
def test_time_comparisons(self): def test_time_comparisons(self):
for file_path in self.read_files: for file_path in self.read_files:
@ -48,6 +50,17 @@ class PerformanceComparisons(unittest.TestCase):
self.original_times[:] = [] self.original_times[:] = []
self.optimized_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): def aux_build_importer(self, indx):
self.importer.import_data(indx) self.importer.import_data(indx)
self.s1 = SamplePath(self.importer) self.s1 = SamplePath(self.importer)
@ -66,7 +79,17 @@ class PerformanceComparisons(unittest.TestCase):
name = name.split('.', 1)[0] name = name.split('.', 1)[0]
name = 'execution_times_' + name + '.csv' name = 'execution_times_' + name + '.csv'
path = os.path.abspath('./results/') 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 file_dest = path + '/' + name
df_results.to_csv(file_dest, index=False) df_results.to_csv(file_dest, index=False)

@ -39,20 +39,22 @@ class TestJsonImporter(unittest.TestCase):
path = os.getcwd() path = os.getcwd()
path = path + '/data.json' path = path + '/data.json'
j1 = JsonImporter(path, '', '', '', '', '') j1 = JsonImporter(path, '', '', '', '', '')
#imported_data = j1.read_json_file()
self.assertTrue(self.ordered(data_set) == self.ordered(j1._raw_data)) self.assertTrue(self.ordered(data_set) == self.ordered(j1._raw_data))
os.remove('data.json') os.remove('data.json')
def test_read_json_file_not_found(self): def test_read_json_file_not_found(self):
path = os.getcwd() path = os.getcwd()
path = path + '/data.json' path = path + '/data.json'
#j1 = JsonImporter(path, '', '', '', '', '')
self.assertRaises(FileNotFoundError, 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): def test_normalize_trajectories(self):
j1 = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name') 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) 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])) 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): def test_compute_row_delta_single_samples_frame(self):
j1 = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name') j1 = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name')
#raw_data = j1.read_json_file()
j1._array_indx = 0 j1._array_indx = 0
j1._df_samples_list = j1.import_trajectories(j1._raw_data) j1._df_samples_list = j1.import_trajectories(j1._raw_data)
sample_frame = j1._df_samples_list[0] sample_frame = j1._df_samples_list[0]
@ -89,7 +90,6 @@ class TestJsonImporter(unittest.TestCase):
def test_compute_row_delta_in_all_frames(self): def test_compute_row_delta_in_all_frames(self):
j1 = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name') j1 = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name')
#raw_data = j1.read_json_file()
j1._array_indx = 0 j1._array_indx = 0
j1._df_samples_list = j1.import_trajectories(j1._raw_data) j1._df_samples_list = j1.import_trajectories(j1._raw_data)
j1._sorter = j1.build_sorter(j1._df_samples_list[0]) 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))]) 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) 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): def test_clear_data_frame_list(self):
j1 = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name') j1 = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name')
#raw_data = j1.read_json_file()
j1._array_indx = 0 j1._array_indx = 0
j1._df_samples_list = j1.import_trajectories(j1._raw_data) j1._df_samples_list = j1.import_trajectories(j1._raw_data)
j1._sorter = j1.build_sorter(j1._df_samples_list[0]) 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"}]}] raw_data = [{"dyn.str":[{"From":"X","To":"Z"},{"From":"Y","To":"Z"},{"From":"Z","To":"Y"}]}]
j1._array_indx = 0 j1._array_indx = 0
df_struct = j1.import_structure(raw_data) df_struct = j1.import_structure(raw_data)
#print(raw_data[0]['dyn.str'][0].items())
self.assertIsInstance(df_struct, pd.DataFrame) self.assertIsInstance(df_struct, pd.DataFrame)
def test_import_sampled_cims(self): def test_import_sampled_cims(self):
@ -155,9 +159,18 @@ class TestJsonImporter(unittest.TestCase):
j1._df_samples_list = j1.import_trajectories(raw_data) j1._df_samples_list = j1.import_trajectories(raw_data)
j1._sorter = j1.build_sorter(j1._df_samples_list[0]) j1._sorter = j1.build_sorter(j1._df_samples_list[0])
cims = j1.import_sampled_cims(raw_data, 0, 'dyn.cims') cims = j1.import_sampled_cims(raw_data, 0, 'dyn.cims')
#j1.import_variables(raw_data, j1.sorter)
self.assertEqual(list(cims.keys()), 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): def test_import_data(self):
j1 = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name') j1 = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name')
j1.import_data(0) j1.import_data(0)

@ -78,7 +78,8 @@ class TestNetworkGraph(unittest.TestCase):
aggr_info[0], aggr_info[2]) 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): 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) self.assertEqual(len(time_scalar_indexing), len(parents_indxs) + 1)
merged_list = parents_labels[:] merged_list = parents_labels[:]
merged_list.insert(0, node_id) 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, def aux_build_transition_scalar_indexing_structure_for_a_node(self, graph, node_id, parents_indxs, parents_labels,
parents_values): 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) parents_values)
self.assertEqual(len(transition_scalar_indexing), len(parents_indxs) + 2) self.assertEqual(len(transition_scalar_indexing), len(parents_indxs) + 2)
merged_list = parents_labels[:] merged_list = parents_labels[:]

@ -55,7 +55,7 @@ class TestParametersEstimatior(unittest.TestCase):
def cim_equality_test(self, cim1, cim2): def cim_equality_test(self, cim1, cim2):
for r1, r2 in zip(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): def aux_import_sampled_cims(self, cims_label):
i1 = JsonImporter(self.read_files[0], '', '', '', '', '') i1 = JsonImporter(self.read_files[0], '', '', '', '', '')

@ -2,6 +2,7 @@
import unittest import unittest
import glob import glob
import os import os
import random
from ..PyCTBN.json_importer import JsonImporter from ..PyCTBN.json_importer import JsonImporter
from ..PyCTBN.sample_path import SamplePath 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') importer = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name')
self.assertRaises(RuntimeError, SamplePath, importer) 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): def test_init(self):
importer = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name') importer = JsonImporter(self.read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name')
importer.import_data(0) importer.import_data(0)
@ -43,6 +50,13 @@ class TestSamplePath(unittest.TestCase):
self.assertIsInstance(s1.structure, Structure) self.assertIsInstance(s1.structure, Structure)
self.assertEqual(s1._total_variables_count, len(s1._importer.sorter)) 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__': if __name__ == '__main__':
unittest.main() unittest.main()

@ -3,11 +3,9 @@ import glob
import math import math
import os import os
import unittest import unittest
import json
import networkx as nx import networkx as nx
import numpy as np import numpy as np
import psutil
from line_profiler import LineProfiler
import timeit import timeit
from ..PyCTBN.cache import Cache from ..PyCTBN.cache import Cache
@ -61,8 +59,8 @@ class TestStructureEstimator(unittest.TestCase):
for node in self.s1.structure.nodes_labels: for node in self.s1.structure.nodes_labels:
for b in range(nodes_numb): for b in range(nodes_numb):
sets = 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 = se1.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) / self.assertEqual(len(list(sets)), math.floor(math.factorial(nodes_numb - 1) /
(math.factorial(b)*math.factorial(nodes_numb -1 - b)))) (math.factorial(b)*math.factorial(nodes_numb -1 - b))))
for sset in sets2: for sset in sets2:
@ -70,17 +68,8 @@ class TestStructureEstimator(unittest.TestCase):
def test_time(self): def test_time(self):
se1 = StructureEstimator(self.s1, 0.1, 0.1) se1 = StructureEstimator(self.s1, 0.1, 0.1)
lp = LineProfiler() exec_time = timeit.timeit(se1.ctpc_algorithm, number=1)
#lp.add_function(se1.complete_test) print("Execution Time: ", exec_time)
#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)
for ed in self.s1.structure.edges: for ed in self.s1.structure.edges:
self.assertIn(tuple(ed), se1._complete_graph.edges) self.assertIn(tuple(ed), se1._complete_graph.edges)
tuples_edges = [tuple(rec) for rec in self.s1.structure.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): if not(ed in tuples_edges):
spurious_edges.append(ed) spurious_edges.append(ed)
print("Spurious Edges:",spurious_edges) 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 = StructureEstimator(self.s1, 0.1, 0.1)
se1.ctpc_algorithm() se1.ctpc_algorithm()
current_process = psutil.Process(os.getpid()) adj_matrix = nx.adj_matrix(se1._complete_graph).toarray().astype(bool)
mem = current_process.memory_info().rss self.assertTrue(np.array_equal(adj_matrix, se1.adjacency_matrix()))
print("Average Memory Usage in MB:", mem / 10**6)
if __name__ == '__main__': if __name__ == '__main__':

@ -0,0 +1,660 @@
<?xml version="1.0" ?>
<coverage version="5.3" timestamp="1607879719119" lines-valid="579" lines-covered="575" line-rate="0.9931" branches-covered="0" branches-valid="0" branch-rate="0" complexity="0">
<!-- Generated by coverage.py: https://coverage.readthedocs.io -->
<!-- Based on https://raw.githubusercontent.com/cobertura/web/master/htdocs/xml/coverage-04.dtd -->
<sources>
<source>/Users/Zalum/Desktop/Tesi/PyCTBN</source>
</sources>
<packages>
<package name="PyCTBN" line-rate="1" branch-rate="0" complexity="0">
<classes>
<class name="__init__.py" filename="PyCTBN/__init__.py" complexity="0" line-rate="1" branch-rate="0">
<methods/>
<lines/>
</class>
</classes>
</package>
<package name="PyCTBN.PyCTBN" line-rate="0.9931" branch-rate="0" complexity="0">
<classes>
<class name="__init__.py" filename="PyCTBN/PyCTBN/__init__.py" complexity="0" line-rate="1" branch-rate="0">
<methods/>
<lines/>
</class>
<class name="abstract_importer.py" filename="PyCTBN/PyCTBN/abstract_importer.py" complexity="0" line-rate="0.9636" branch-rate="0">
<methods/>
<lines>
<line number="2" hits="1"/>
<line number="3" hits="1"/>
<line number="4" hits="1"/>
<line number="7" hits="1"/>
<line number="28" hits="1"/>
<line number="31" hits="1"/>
<line number="32" hits="1"/>
<line number="33" hits="1"/>
<line number="34" hits="1"/>
<line number="35" hits="1"/>
<line number="36" hits="1"/>
<line number="38" hits="1"/>
<line number="39" hits="1"/>
<line number="48" hits="0"/>
<line number="50" hits="1"/>
<line number="69" hits="1"/>
<line number="70" hits="1"/>
<line number="71" hits="1"/>
<line number="72" hits="1"/>
<line number="73" hits="1"/>
<line number="74" hits="1"/>
<line number="76" hits="1"/>
<line number="92" hits="1"/>
<line number="93" hits="1"/>
<line number="94" hits="1"/>
<line number="95" hits="1"/>
<line number="96" hits="1"/>
<line number="98" hits="1"/>
<line number="99" hits="1"/>
<line number="100" hits="1"/>
<line number="101" hits="1"/>
<line number="102" hits="1"/>
<line number="104" hits="1"/>
<line number="112" hits="1"/>
<line number="113" hits="1"/>
<line number="115" hits="1"/>
<line number="118" hits="1"/>
<line number="120" hits="1"/>
<line number="121" hits="1"/>
<line number="125" hits="0"/>
<line number="127" hits="1"/>
<line number="128" hits="1"/>
<line number="129" hits="1"/>
<line number="131" hits="1"/>
<line number="132" hits="1"/>
<line number="133" hits="1"/>
<line number="135" hits="1"/>
<line number="136" hits="1"/>
<line number="137" hits="1"/>
<line number="139" hits="1"/>
<line number="140" hits="1"/>
<line number="141" hits="1"/>
<line number="143" hits="1"/>
<line number="144" hits="1"/>
<line number="145" hits="1"/>
</lines>
</class>
<class name="cache.py" filename="PyCTBN/PyCTBN/cache.py" complexity="0" line-rate="1" branch-rate="0">
<methods/>
<lines>
<line number="2" hits="1"/>
<line number="4" hits="1"/>
<line number="7" hits="1"/>
<line number="15" hits="1"/>
<line number="18" hits="1"/>
<line number="19" hits="1"/>
<line number="21" hits="1"/>
<line number="32" hits="1"/>
<line number="33" hits="1"/>
<line number="34" hits="1"/>
<line number="35" hits="1"/>
<line number="36" hits="1"/>
<line number="38" hits="1"/>
<line number="47" hits="1"/>
<line number="48" hits="1"/>
<line number="50" hits="1"/>
<line number="53" hits="1"/>
<line number="54" hits="1"/>
</lines>
</class>
<class name="conditional_intensity_matrix.py" filename="PyCTBN/PyCTBN/conditional_intensity_matrix.py" complexity="0" line-rate="1" branch-rate="0">
<methods/>
<lines>
<line number="1" hits="1"/>
<line number="4" hits="1"/>
<line number="14" hits="1"/>
<line number="17" hits="1"/>
<line number="18" hits="1"/>
<line number="19" hits="1"/>
<line number="21" hits="1"/>
<line number="25" hits="1"/>
<line number="26" hits="1"/>
<line number="28" hits="1"/>
<line number="29" hits="1"/>
<line number="30" hits="1"/>
<line number="32" hits="1"/>
<line number="33" hits="1"/>
<line number="34" hits="1"/>
<line number="36" hits="1"/>
<line number="37" hits="1"/>
<line number="38" hits="1"/>
<line number="40" hits="1"/>
<line number="41" hits="1"/>
</lines>
</class>
<class name="json_importer.py" filename="PyCTBN/PyCTBN/json_importer.py" complexity="0" line-rate="1" branch-rate="0">
<methods/>
<lines>
<line number="2" hits="1"/>
<line number="3" hits="1"/>
<line number="4" hits="1"/>
<line number="6" hits="1"/>
<line number="9" hits="1"/>
<line number="32" hits="1"/>
<line number="41" hits="1"/>
<line number="42" hits="1"/>
<line number="43" hits="1"/>
<line number="44" hits="1"/>
<line number="45" hits="1"/>
<line number="46" hits="1"/>
<line number="47" hits="1"/>
<line number="48" hits="1"/>
<line number="49" hits="1"/>
<line number="51" hits="1"/>
<line number="57" hits="1"/>
<line number="58" hits="1"/>
<line number="59" hits="1"/>
<line number="60" hits="1"/>
<line number="61" hits="1"/>
<line number="62" hits="1"/>
<line number="63" hits="1"/>
<line number="65" hits="1"/>
<line number="73" hits="1"/>
<line number="75" hits="1"/>
<line number="83" hits="1"/>
<line number="85" hits="1"/>
<line number="93" hits="1"/>
<line number="95" hits="1"/>
<line number="101" hits="1"/>
<line number="102" hits="1"/>
<line number="103" hits="1"/>
<line number="105" hits="1"/>
<line number="117" hits="1"/>
<line number="119" hits="1"/>
<line number="132" hits="1"/>
<line number="133" hits="1"/>
<line number="134" hits="1"/>
<line number="135" hits="1"/>
<line number="137" hits="1"/>
<line number="140" hits="1"/>
<line number="141" hits="1"/>
<line number="142" hits="1"/>
<line number="144" hits="1"/>
<line number="147" hits="1"/>
<line number="148" hits="1"/>
<line number="150" hits="1"/>
<line number="151" hits="1"/>
<line number="153" hits="1"/>
<line number="166" hits="1"/>
<line number="167" hits="1"/>
<line number="168" hits="1"/>
<line number="169" hits="1"/>
<line number="170" hits="1"/>
<line number="171" hits="1"/>
<line number="172" hits="1"/>
</lines>
</class>
<class name="network_graph.py" filename="PyCTBN/PyCTBN/network_graph.py" complexity="0" line-rate="0.9919" branch-rate="0">
<methods/>
<lines>
<line number="2" hits="1"/>
<line number="3" hits="1"/>
<line number="4" hits="1"/>
<line number="6" hits="1"/>
<line number="9" hits="1"/>
<line number="26" hits="1"/>
<line number="29" hits="1"/>
<line number="30" hits="1"/>
<line number="31" hits="1"/>
<line number="32" hits="1"/>
<line number="33" hits="1"/>
<line number="34" hits="1"/>
<line number="35" hits="1"/>
<line number="36" hits="1"/>
<line number="38" hits="1"/>
<line number="45" hits="1"/>
<line number="46" hits="1"/>
<line number="47" hits="1"/>
<line number="48" hits="1"/>
<line number="49" hits="1"/>
<line number="50" hits="1"/>
<line number="51" hits="1"/>
<line number="52" hits="1"/>
<line number="53" hits="1"/>
<line number="55" hits="1"/>
<line number="57" hits="1"/>
<line number="58" hits="1"/>
<line number="59" hits="1"/>
<line number="61" hits="1"/>
<line number="68" hits="1"/>
<line number="69" hits="1"/>
<line number="70" hits="1"/>
<line number="71" hits="1"/>
<line number="72" hits="1"/>
<line number="73" hits="1"/>
<line number="75" hits="1"/>
<line number="81" hits="1"/>
<line number="83" hits="1"/>
<line number="87" hits="1"/>
<line number="88" hits="1"/>
<line number="89" hits="1"/>
<line number="91" hits="1"/>
<line number="94" hits="1"/>
<line number="95" hits="1"/>
<line number="96" hits="1"/>
<line number="97" hits="1"/>
<line number="98" hits="1"/>
<line number="99" hits="1"/>
<line number="101" hits="1"/>
<line number="110" hits="1"/>
<line number="111" hits="1"/>
<line number="112" hits="1"/>
<line number="113" hits="1"/>
<line number="114" hits="1"/>
<line number="115" hits="1"/>
<line number="116" hits="1"/>
<line number="117" hits="1"/>
<line number="119" hits="1"/>
<line number="120" hits="1"/>
<line number="131" hits="1"/>
<line number="132" hits="1"/>
<line number="133" hits="1"/>
<line number="134" hits="1"/>
<line number="136" hits="1"/>
<line number="137" hits="1"/>
<line number="148" hits="1"/>
<line number="150" hits="1"/>
<line number="151" hits="1"/>
<line number="152" hits="1"/>
<line number="154" hits="1"/>
<line number="155" hits="1"/>
<line number="167" hits="1"/>
<line number="169" hits="1"/>
<line number="170" hits="1"/>
<line number="184" hits="1"/>
<line number="186" hits="1"/>
<line number="187" hits="1"/>
<line number="197" hits="1"/>
<line number="198" hits="1"/>
<line number="199" hits="1"/>
<line number="200" hits="1"/>
<line number="201" hits="1"/>
<line number="202" hits="1"/>
<line number="203" hits="1"/>
<line number="204" hits="1"/>
<line number="205" hits="1"/>
<line number="207" hits="1"/>
<line number="208" hits="1"/>
<line number="210" hits="1"/>
<line number="218" hits="1"/>
<line number="220" hits="1"/>
<line number="221" hits="1"/>
<line number="223" hits="1"/>
<line number="224" hits="1"/>
<line number="226" hits="1"/>
<line number="227" hits="0"/>
<line number="229" hits="1"/>
<line number="230" hits="1"/>
<line number="231" hits="1"/>
<line number="233" hits="1"/>
<line number="234" hits="1"/>
<line number="235" hits="1"/>
<line number="237" hits="1"/>
<line number="238" hits="1"/>
<line number="239" hits="1"/>
<line number="241" hits="1"/>
<line number="242" hits="1"/>
<line number="243" hits="1"/>
<line number="245" hits="1"/>
<line number="246" hits="1"/>
<line number="247" hits="1"/>
<line number="249" hits="1"/>
<line number="250" hits="1"/>
<line number="251" hits="1"/>
<line number="253" hits="1"/>
<line number="254" hits="1"/>
<line number="255" hits="1"/>
<line number="257" hits="1"/>
<line number="258" hits="1"/>
<line number="259" hits="1"/>
<line number="261" hits="1"/>
<line number="262" hits="1"/>
<line number="263" hits="1"/>
</lines>
</class>
<class name="parameters_estimator.py" filename="PyCTBN/PyCTBN/parameters_estimator.py" complexity="0" line-rate="1" branch-rate="0">
<methods/>
<lines>
<line number="2" hits="1"/>
<line number="4" hits="1"/>
<line number="5" hits="1"/>
<line number="6" hits="1"/>
<line number="9" hits="1"/>
<line number="20" hits="1"/>
<line number="23" hits="1"/>
<line number="24" hits="1"/>
<line number="25" hits="1"/>
<line number="27" hits="1"/>
<line number="33" hits="1"/>
<line number="34" hits="1"/>
<line number="35" hits="1"/>
<line number="37" hits="1"/>
<line number="45" hits="1"/>
<line number="46" hits="1"/>
<line number="47" hits="1"/>
<line number="48" hits="1"/>
<line number="53" hits="1"/>
<line number="57" hits="1"/>
<line number="58" hits="1"/>
<line number="60" hits="1"/>
<line number="61" hits="1"/>
<line number="79" hits="1"/>
<line number="84" hits="1"/>
<line number="85" hits="1"/>
<line number="100" hits="1"/>
<line number="102" hits="1"/>
<line number="103" hits="1"/>
<line number="105" hits="1"/>
<line number="106" hits="1"/>
<line number="107" hits="1"/>
</lines>
</class>
<class name="sample_path.py" filename="PyCTBN/PyCTBN/sample_path.py" complexity="0" line-rate="1" branch-rate="0">
<methods/>
<lines>
<line number="2" hits="1"/>
<line number="3" hits="1"/>
<line number="4" hits="1"/>
<line number="7" hits="1"/>
<line number="18" hits="1"/>
<line number="21" hits="1"/>
<line number="22" hits="1"/>
<line number="24" hits="1"/>
<line number="25" hits="1"/>
<line number="27" hits="1"/>
<line number="28" hits="1"/>
<line number="29" hits="1"/>
<line number="30" hits="1"/>
<line number="32" hits="1"/>
<line number="36" hits="1"/>
<line number="39" hits="1"/>
<line number="41" hits="1"/>
<line number="45" hits="1"/>
<line number="46" hits="1"/>
<line number="48" hits="1"/>
<line number="49" hits="1"/>
<line number="50" hits="1"/>
<line number="51" hits="1"/>
<line number="52" hits="1"/>
<line number="53" hits="1"/>
<line number="56" hits="1"/>
<line number="57" hits="1"/>
<line number="58" hits="1"/>
<line number="60" hits="1"/>
<line number="61" hits="1"/>
<line number="62" hits="1"/>
<line number="64" hits="1"/>
<line number="65" hits="1"/>
<line number="66" hits="1"/>
</lines>
</class>
<class name="set_of_cims.py" filename="PyCTBN/PyCTBN/set_of_cims.py" complexity="0" line-rate="1" branch-rate="0">
<methods/>
<lines>
<line number="1" hits="1"/>
<line number="2" hits="1"/>
<line number="4" hits="1"/>
<line number="7" hits="1"/>
<line number="23" hits="1"/>
<line number="26" hits="1"/>
<line number="27" hits="1"/>
<line number="28" hits="1"/>
<line number="29" hits="1"/>
<line number="30" hits="1"/>
<line number="31" hits="1"/>
<line number="32" hits="1"/>
<line number="33" hits="1"/>
<line number="35" hits="1"/>
<line number="38" hits="1"/>
<line number="39" hits="1"/>
<line number="40" hits="1"/>
<line number="42" hits="1"/>
<line number="44" hits="1"/>
<line number="47" hits="1"/>
<line number="56" hits="1"/>
<line number="57" hits="1"/>
<line number="58" hits="1"/>
<line number="59" hits="1"/>
<line number="60" hits="1"/>
<line number="61" hits="1"/>
<line number="62" hits="1"/>
<line number="64" hits="1"/>
<line number="75" hits="1"/>
<line number="76" hits="1"/>
<line number="78" hits="1"/>
<line number="79" hits="1"/>
<line number="81" hits="1"/>
<line number="82" hits="1"/>
<line number="83" hits="1"/>
<line number="85" hits="1"/>
<line number="86" hits="1"/>
<line number="87" hits="1"/>
<line number="89" hits="1"/>
<line number="90" hits="1"/>
</lines>
</class>
<class name="structure.py" filename="PyCTBN/PyCTBN/structure.py" complexity="0" line-rate="0.9783" branch-rate="0">
<methods/>
<lines>
<line number="1" hits="1"/>
<line number="2" hits="1"/>
<line number="5" hits="1"/>
<line number="20" hits="1"/>
<line number="24" hits="1"/>
<line number="25" hits="1"/>
<line number="26" hits="1"/>
<line number="27" hits="1"/>
<line number="28" hits="1"/>
<line number="30" hits="1"/>
<line number="34" hits="1"/>
<line number="35" hits="1"/>
<line number="36" hits="1"/>
<line number="37" hits="1"/>
<line number="38" hits="1"/>
<line number="41" hits="1"/>
<line number="42" hits="1"/>
<line number="43" hits="1"/>
<line number="45" hits="1"/>
<line number="46" hits="1"/>
<line number="47" hits="1"/>
<line number="49" hits="1"/>
<line number="50" hits="1"/>
<line number="51" hits="1"/>
<line number="53" hits="1"/>
<line number="54" hits="1"/>
<line number="55" hits="1"/>
<line number="57" hits="1"/>
<line number="58" hits="1"/>
<line number="59" hits="1"/>
<line number="61" hits="1"/>
<line number="69" hits="1"/>
<line number="71" hits="1"/>
<line number="79" hits="1"/>
<line number="80" hits="1"/>
<line number="82" hits="1"/>
<line number="83" hits="1"/>
<line number="85" hits="1"/>
<line number="93" hits="1"/>
<line number="94" hits="1"/>
<line number="96" hits="1"/>
<line number="97" hits="1"/>
<line number="100" hits="1"/>
<line number="102" hits="1"/>
<line number="103" hits="1"/>
<line number="108" hits="0"/>
</lines>
</class>
<class name="structure_estimator.py" filename="PyCTBN/PyCTBN/structure_estimator.py" complexity="0" line-rate="1" branch-rate="0">
<methods/>
<lines>
<line number="2" hits="1"/>
<line number="3" hits="1"/>
<line number="4" hits="1"/>
<line number="5" hits="1"/>
<line number="6" hits="1"/>
<line number="7" hits="1"/>
<line number="8" hits="1"/>
<line number="9" hits="1"/>
<line number="10" hits="1"/>
<line number="12" hits="1"/>
<line number="13" hits="1"/>
<line number="14" hits="1"/>
<line number="15" hits="1"/>
<line number="16" hits="1"/>
<line number="17" hits="1"/>
<line number="20" hits="1"/>
<line number="36" hits="1"/>
<line number="39" hits="1"/>
<line number="40" hits="1"/>
<line number="41" hits="1"/>
<line number="42" hits="1"/>
<line number="43" hits="1"/>
<line number="44" hits="1"/>
<line number="45" hits="1"/>
<line number="46" hits="1"/>
<line number="48" hits="1"/>
<line number="49" hits="1"/>
<line number="57" hits="1"/>
<line number="58" hits="1"/>
<line number="59" hits="1"/>
<line number="60" hits="1"/>
<line number="62" hits="1"/>
<line number="81" hits="1"/>
<line number="82" hits="1"/>
<line number="83" hits="1"/>
<line number="85" hits="1"/>
<line number="86" hits="1"/>
<line number="87" hits="1"/>
<line number="88" hits="1"/>
<line number="90" hits="1"/>
<line number="91" hits="1"/>
<line number="93" hits="1"/>
<line number="94" hits="1"/>
<line number="95" hits="1"/>
<line number="96" hits="1"/>
<line number="97" hits="1"/>
<line number="98" hits="1"/>
<line number="99" hits="1"/>
<line number="100" hits="1"/>
<line number="101" hits="1"/>
<line number="102" hits="1"/>
<line number="103" hits="1"/>
<line number="104" hits="1"/>
<line number="105" hits="1"/>
<line number="106" hits="1"/>
<line number="108" hits="1"/>
<line number="109" hits="1"/>
<line number="110" hits="1"/>
<line number="111" hits="1"/>
<line number="112" hits="1"/>
<line number="113" hits="1"/>
<line number="114" hits="1"/>
<line number="115" hits="1"/>
<line number="116" hits="1"/>
<line number="118" hits="1"/>
<line number="119" hits="1"/>
<line number="120" hits="1"/>
<line number="121" hits="1"/>
<line number="122" hits="1"/>
<line number="123" hits="1"/>
<line number="125" hits="1"/>
<line number="140" hits="1"/>
<line number="141" hits="1"/>
<line number="142" hits="1"/>
<line number="143" hits="1"/>
<line number="144" hits="1"/>
<line number="145" hits="1"/>
<line number="146" hits="1"/>
<line number="147" hits="1"/>
<line number="148" hits="1"/>
<line number="149" hits="1"/>
<line number="151" hits="1"/>
<line number="152" hits="1"/>
<line number="153" hits="1"/>
<line number="155" hits="1"/>
<line number="156" hits="1"/>
<line number="157" hits="1"/>
<line number="158" hits="1"/>
<line number="159" hits="1"/>
<line number="161" hits="1"/>
<line number="162" hits="1"/>
<line number="163" hits="1"/>
<line number="165" hits="1"/>
<line number="173" hits="1"/>
<line number="174" hits="1"/>
<line number="175" hits="1"/>
<line number="176" hits="1"/>
<line number="177" hits="1"/>
<line number="178" hits="1"/>
<line number="179" hits="1"/>
<line number="180" hits="1"/>
<line number="181" hits="1"/>
<line number="182" hits="1"/>
<line number="183" hits="1"/>
<line number="184" hits="1"/>
<line number="185" hits="1"/>
<line number="186" hits="1"/>
<line number="187" hits="1"/>
<line number="188" hits="1"/>
<line number="189" hits="1"/>
<line number="190" hits="1"/>
<line number="191" hits="1"/>
<line number="193" hits="1"/>
<line number="194" hits="1"/>
<line number="208" hits="1"/>
<line number="209" hits="1"/>
<line number="210" hits="1"/>
<line number="212" hits="1"/>
<line number="215" hits="1"/>
<line number="216" hits="1"/>
<line number="217" hits="1"/>
<line number="219" hits="1"/>
<line number="223" hits="1"/>
<line number="224" hits="1"/>
<line number="225" hits="1"/>
<line number="226" hits="1"/>
<line number="227" hits="1"/>
<line number="228" hits="1"/>
<line number="229" hits="1"/>
<line number="230" hits="1"/>
<line number="232" hits="1"/>
<line number="238" hits="1"/>
</lines>
</class>
<class name="trajectory.py" filename="PyCTBN/PyCTBN/trajectory.py" complexity="0" line-rate="1" branch-rate="0">
<methods/>
<lines>
<line number="2" hits="1"/>
<line number="3" hits="1"/>
<line number="6" hits="1"/>
<line number="18" hits="1"/>
<line number="21" hits="1"/>
<line number="22" hits="1"/>
<line number="23" hits="1"/>
<line number="24" hits="1"/>
<line number="25" hits="1"/>
<line number="27" hits="1"/>
<line number="28" hits="1"/>
<line number="29" hits="1"/>
<line number="31" hits="1"/>
<line number="32" hits="1"/>
<line number="33" hits="1"/>
<line number="35" hits="1"/>
<line number="36" hits="1"/>
<line number="37" hits="1"/>
<line number="39" hits="1"/>
<line number="40" hits="1"/>
<line number="42" hits="1"/>
<line number="43" hits="1"/>
</lines>
</class>
</classes>
</package>
</packages>
</coverage>