|
|
@ -1,62 +1,54 @@ |
|
|
|
|
|
|
|
import sys |
|
|
|
|
|
|
|
sys.path.append('./classes/') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import typing |
|
|
|
import typing |
|
|
|
import structure as st |
|
|
|
|
|
|
|
import networkx as nx |
|
|
|
import networkx as nx |
|
|
|
import numpy as np |
|
|
|
import numpy as np |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import structure as st |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class NetworkGraph: |
|
|
|
class NetworkGraph: |
|
|
|
""" |
|
|
|
"""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 structures for parameters estimation |
|
|
|
|
|
|
|
|
|
|
|
:param graph_struct: the ``Structure`` object from which infos about the net will be extracted |
|
|
|
:_graph_struct: the Structure object from which infos about the net will be extracted |
|
|
|
:type graph_struct: Structure |
|
|
|
:_graph: directed _graph |
|
|
|
:_graph: directed graph |
|
|
|
:nodes_labels: the symbolic names of the variables |
|
|
|
:_aggregated_info_about_nodes_parents: a structure that contains all the necessary infos |
|
|
|
:nodes_indexes: the indexes of the nodes |
|
|
|
about every parents of the node of which all the indexing and filtering structures will be constructed. |
|
|
|
:nodes_values: the cardinalites of the nodes |
|
|
|
|
|
|
|
:_aggregated_info_about_nodes_parents: a structure that contains all the necessary infos about every parents of every |
|
|
|
|
|
|
|
node in the net |
|
|
|
|
|
|
|
:_fancy_indexing: the indexes of every parent of every node in the net |
|
|
|
|
|
|
|
:_time_scalar_indexing_structure: the indexing structure for state res time estimation |
|
|
|
:_time_scalar_indexing_structure: the indexing structure for state res time estimation |
|
|
|
:_transition_scalar_indexing_structure: the indexing structure for transition computation |
|
|
|
:_transition_scalar_indexing_structure: the indexing structure for transition computation |
|
|
|
:_time_filtering: the columns filtering structure used in the computation of the state res times |
|
|
|
:_time_filtering: the columns filtering structure used in the computation of the state res times |
|
|
|
:_transition_filtering: the columns filtering structure used in the computation of the transition |
|
|
|
:_transition_filtering: the columns filtering structure used in the computation of the transition |
|
|
|
from one state to another |
|
|
|
from one state to another |
|
|
|
:self._p_combs_structure: all the possible parents states combination for every node in the net |
|
|
|
:_p_combs_structure: all the possible parents states combination for the node of interest |
|
|
|
""" |
|
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, graph_struct: st.Structure): |
|
|
|
def __init__(self, graph_struct: st.Structure): |
|
|
|
""" |
|
|
|
"""Constructor Method |
|
|
|
Parameters: |
|
|
|
|
|
|
|
:graph_struct:the Structure object from which infos about the net will be extracted |
|
|
|
|
|
|
|
""" |
|
|
|
""" |
|
|
|
self._graph_struct = graph_struct |
|
|
|
self._graph_struct = graph_struct |
|
|
|
self._graph = nx.DiGraph() |
|
|
|
self._graph = nx.DiGraph() |
|
|
|
self._nodes_indexes = self._graph_struct.nodes_indexes |
|
|
|
|
|
|
|
self._nodes_labels = self._graph_struct.nodes_labels |
|
|
|
|
|
|
|
self._nodes_values = self._graph_struct.nodes_values |
|
|
|
|
|
|
|
self._aggregated_info_about_nodes_parents = None |
|
|
|
self._aggregated_info_about_nodes_parents = None |
|
|
|
self._fancy_indexing = None |
|
|
|
|
|
|
|
self._time_scalar_indexing_structure = None |
|
|
|
self._time_scalar_indexing_structure = None |
|
|
|
self._transition_scalar_indexing_structure = None |
|
|
|
self._transition_scalar_indexing_structure = None |
|
|
|
self._time_filtering = None |
|
|
|
self._time_filtering = None |
|
|
|
self._transition_filtering = None |
|
|
|
self._transition_filtering = None |
|
|
|
self._p_combs_structure = None |
|
|
|
self._p_combs_structure = None |
|
|
|
|
|
|
|
|
|
|
|
def fast_init(self, node_id: str): |
|
|
|
def fast_init(self, node_id: str) -> None: |
|
|
|
""" |
|
|
|
"""Initializes all the necessary structures for parameters estimation of the node identified by the label |
|
|
|
Initializes all the necessary structures for parameters estimation of the node identified by the label node_id |
|
|
|
node_id |
|
|
|
Parameters: |
|
|
|
|
|
|
|
node_id: the label of the node |
|
|
|
:param node_id: the label of the node |
|
|
|
Returns: |
|
|
|
:type node_id: string |
|
|
|
void |
|
|
|
|
|
|
|
""" |
|
|
|
""" |
|
|
|
self.add_nodes(self._nodes_labels) |
|
|
|
self.add_nodes(self._graph_struct.nodes_labels) |
|
|
|
self.add_edges(self._graph_struct.edges) |
|
|
|
self.add_edges(self._graph_struct.edges) |
|
|
|
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) |
|
|
|
self._fancy_indexing = self._aggregated_info_about_nodes_parents[1] |
|
|
|
p_indxs = self._aggregated_info_about_nodes_parents[1] |
|
|
|
p_indxs = self._fancy_indexing |
|
|
|
|
|
|
|
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, |
|
|
|
self._time_scalar_indexing_structure = self.build_time_scalar_indexing_structure_for_a_node(node_id, |
|
|
|
p_vals) |
|
|
|
p_vals) |
|
|
@ -67,48 +59,39 @@ class NetworkGraph: |
|
|
|
self._transition_filtering = self.build_transition_filtering_for_a_node(node_indx, p_indxs) |
|
|
|
self._transition_filtering = self.build_transition_filtering_for_a_node(node_indx, p_indxs) |
|
|
|
self._p_combs_structure = self.build_p_comb_structure_for_a_node(p_vals) |
|
|
|
self._p_combs_structure = self.build_p_comb_structure_for_a_node(p_vals) |
|
|
|
|
|
|
|
|
|
|
|
def add_nodes(self, list_of_nodes: typing.List): |
|
|
|
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. |
|
|
|
|
|
|
|
Sets all the properties that identify a nodes (index, positional index, cardinality) |
|
|
|
Sets all the properties that identify a nodes (index, positional index, cardinality) |
|
|
|
|
|
|
|
|
|
|
|
Parameters: |
|
|
|
:param list_of_nodes: the nodes to add to ``_graph`` |
|
|
|
list_of_nodes: the nodes to add to _graph |
|
|
|
:type list_of_nodes: List |
|
|
|
Returns: |
|
|
|
|
|
|
|
void |
|
|
|
|
|
|
|
""" |
|
|
|
""" |
|
|
|
nodes_indxs = self._nodes_indexes |
|
|
|
nodes_indxs = self._graph_struct.nodes_indexes |
|
|
|
nodes_vals = self._graph_struct.nodes_values |
|
|
|
nodes_vals = self._graph_struct.nodes_values |
|
|
|
pos = 0 |
|
|
|
pos = 0 |
|
|
|
for id, node_indx, node_val in zip(list_of_nodes, nodes_indxs, nodes_vals): |
|
|
|
for id, node_indx, node_val in zip(list_of_nodes, nodes_indxs, nodes_vals): |
|
|
|
self._graph.add_node(id, indx=node_indx, val=node_val, pos_indx=pos) |
|
|
|
self._graph.add_node(id, indx=node_indx, val=node_val, pos_indx=pos) |
|
|
|
pos += 1 |
|
|
|
pos += 1 |
|
|
|
|
|
|
|
|
|
|
|
def add_edges(self, list_of_edges: typing.List): |
|
|
|
def add_edges(self, list_of_edges: typing.List) -> None: |
|
|
|
""" |
|
|
|
"""Add the edges to the ``_graph`` contained in the list ``list_of_edges``. |
|
|
|
Add the edges to the _graph contained in the list list_of_edges. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Parameters: |
|
|
|
:param list_of_edges: the list containing of tuples containing the edges |
|
|
|
list_of_edges |
|
|
|
:type list_of_edges: List |
|
|
|
Returns: |
|
|
|
|
|
|
|
void |
|
|
|
|
|
|
|
""" |
|
|
|
""" |
|
|
|
self._graph.add_edges_from(list_of_edges) |
|
|
|
self._graph.add_edges_from(list_of_edges) |
|
|
|
|
|
|
|
|
|
|
|
def get_ordered_by_indx_set_of_parents(self, node: str) -> typing.Tuple: |
|
|
|
def get_ordered_by_indx_set_of_parents(self, node: str) -> typing.Tuple: |
|
|
|
""" |
|
|
|
"""Builds the aggregated structure that holds all the infos relative to the parent set of the node, namely |
|
|
|
Builds the aggregated structure that holds all the infos relative to the parent set of the node, namely |
|
|
|
|
|
|
|
(parents_labels, parents_indexes, parents_cardinalities). |
|
|
|
(parents_labels, parents_indexes, parents_cardinalities). |
|
|
|
N.B. The parent set is sorted using the list of sorted nodes nodes |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Parameters: |
|
|
|
|
|
|
|
node: the label of the node |
|
|
|
|
|
|
|
Returns: |
|
|
|
|
|
|
|
a tuple containing all the parent set infos |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
:param node: the label of the node |
|
|
|
|
|
|
|
:type node: string |
|
|
|
|
|
|
|
:return: a tuple containing all the parent set infos |
|
|
|
|
|
|
|
:rtype: Tuple |
|
|
|
""" |
|
|
|
""" |
|
|
|
parents = self.get_parents_by_id(node) |
|
|
|
parents = self.get_parents_by_id(node) |
|
|
|
nodes = self._nodes_labels |
|
|
|
nodes = self._graph_struct.nodes_labels |
|
|
|
d = {v: i for i, v in enumerate(nodes)} |
|
|
|
d = {v: i for i, v in enumerate(nodes)} |
|
|
|
sorted_parents = sorted(parents, key=lambda v: d[v]) |
|
|
|
sorted_parents = sorted(parents, key=lambda v: d[v]) |
|
|
|
get_node_indx = self.get_node_indx |
|
|
|
get_node_indx = self.get_node_indx |
|
|
@ -117,15 +100,14 @@ class NetworkGraph: |
|
|
|
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: |
|
|
|
def build_time_scalar_indexing_structure_for_a_node(self, node_id: str, 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 |
|
|
|
Parameters: |
|
|
|
:type node_id: string |
|
|
|
node_id: the node label |
|
|
|
:param parents_vals: the caridinalites of the node's parents |
|
|
|
parents_vals: the caridinalites of the node's parents |
|
|
|
:type parents_vals: List |
|
|
|
Returns: |
|
|
|
:return: The time indexing structure |
|
|
|
a numpy array. |
|
|
|
:rtype: numpy.ndArray |
|
|
|
|
|
|
|
|
|
|
|
""" |
|
|
|
""" |
|
|
|
T_vector = np.array([self.get_states_number(node_id)]) |
|
|
|
T_vector = np.array([self.get_states_number(node_id)]) |
|
|
|
T_vector = np.append(T_vector, parents_vals) |
|
|
|
T_vector = np.append(T_vector, parents_vals) |
|
|
@ -134,15 +116,14 @@ class NetworkGraph: |
|
|
|
|
|
|
|
|
|
|
|
def build_transition_scalar_indexing_structure_for_a_node(self, node_id: str, parents_vals: typing.List) \ |
|
|
|
def build_transition_scalar_indexing_structure_for_a_node(self, node_id: str, 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 |
|
|
|
Parameters: |
|
|
|
:type node_id: string |
|
|
|
node_id: the node label |
|
|
|
:param parents_vals: the caridinalites of the node's parents |
|
|
|
parents_vals: the caridinalites of the node's parents |
|
|
|
:type parents_vals: List |
|
|
|
Returns: |
|
|
|
:return: The transition indexing structure |
|
|
|
a numpy array. |
|
|
|
:rtype: numpy.ndArray |
|
|
|
|
|
|
|
|
|
|
|
""" |
|
|
|
""" |
|
|
|
node_states_number = self.get_states_number(node_id) |
|
|
|
node_states_number = self.get_states_number(node_id) |
|
|
|
M_vector = np.array([node_states_number, |
|
|
|
M_vector = np.array([node_states_number, |
|
|
@ -153,37 +134,41 @@ class NetworkGraph: |
|
|
|
|
|
|
|
|
|
|
|
def build_time_columns_filtering_for_a_node(self, node_indx: int, p_indxs: typing.List) -> np.ndarray: |
|
|
|
def build_time_columns_filtering_for_a_node(self, node_indx: int, p_indxs: typing.List) -> np.ndarray: |
|
|
|
""" |
|
|
|
""" |
|
|
|
Builds the necessary structure to filter the desired columns indicated by node_indx and p_indxs in the dataset. |
|
|
|
Builds the necessary structure to filter the desired columns indicated by ``node_indx`` and ``p_indxs`` |
|
|
|
|
|
|
|
in the dataset. |
|
|
|
This structute will be used in the computation of the state res times. |
|
|
|
This structute will be used in the computation of the state res times. |
|
|
|
Parameters: |
|
|
|
:param node_indx: the index of the node |
|
|
|
node_indx: the index of the node |
|
|
|
:type node_indx: int |
|
|
|
p_indxs: the indexes of the node's parents |
|
|
|
:param p_indxs: the indexes of the node's parents |
|
|
|
Returns: |
|
|
|
:type p_indxs: List |
|
|
|
a numpy array |
|
|
|
:return: The filtering structure for times estimation |
|
|
|
|
|
|
|
:rtype: numpy.ndArray |
|
|
|
""" |
|
|
|
""" |
|
|
|
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, p_indxs) -> np.ndarray: |
|
|
|
def build_transition_filtering_for_a_node(self, 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. |
|
|
|
This structute will be used in the computation of the state transitions values. |
|
|
|
This structure will be used in the computation of the state transitions values. |
|
|
|
Parameters: |
|
|
|
:param node_indx: the index of the node |
|
|
|
node_indx: the index of the node |
|
|
|
:type node_indx: int |
|
|
|
p_indxs: the indexes of the node's parents |
|
|
|
:param p_indxs: the indexes of the node's parents |
|
|
|
Returns: |
|
|
|
:type p_indxs: List |
|
|
|
a numpy array |
|
|
|
:return: The filtering structure for transitions estimation |
|
|
|
|
|
|
|
:rtype: numpy.ndArray |
|
|
|
""" |
|
|
|
""" |
|
|
|
nodes_number = self._graph_struct.total_variables_number |
|
|
|
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: |
|
|
|
def build_p_comb_structure_for_a_node(self, parents_values: typing.List) -> np.ndarray: |
|
|
|
""" |
|
|
|
""" |
|
|
|
Builds the combinatory structure that contains the combinations of all the values contained in parents_values. |
|
|
|
Builds the combinatorial structure that contains the combinations of all the values contained in |
|
|
|
|
|
|
|
``parents_values``. |
|
|
|
|
|
|
|
|
|
|
|
Parameters: |
|
|
|
:param parents_values: the cardinalities of the nodes |
|
|
|
parents_values: the cardinalities of the nodes |
|
|
|
:type parents_values: List |
|
|
|
Returns: |
|
|
|
:return: A numpy matrix containing a grid of the combinations |
|
|
|
a numpy matrix containinga grid of the combinations |
|
|
|
:rtype: numpy.ndArray |
|
|
|
""" |
|
|
|
""" |
|
|
|
tmp = [] |
|
|
|
tmp = [] |
|
|
|
for val in parents_values: |
|
|
|
for val in parents_values: |
|
|
@ -198,21 +183,28 @@ class NetworkGraph: |
|
|
|
parents_comb = np.array([[]], dtype=np.int) |
|
|
|
parents_comb = np.array([[]], dtype=np.int) |
|
|
|
return parents_comb |
|
|
|
return parents_comb |
|
|
|
|
|
|
|
|
|
|
|
def get_parents_by_id(self, node_id): |
|
|
|
def get_parents_by_id(self, node_id) -> typing.List: |
|
|
|
|
|
|
|
"""Returns a list of labels of the parents of the node ``node_id`` |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
:param node_id: the node label |
|
|
|
|
|
|
|
:type node_id: string |
|
|
|
|
|
|
|
:return: a List of labels of the parents |
|
|
|
|
|
|
|
:rtype: List |
|
|
|
|
|
|
|
""" |
|
|
|
return list(self._graph.predecessors(node_id)) |
|
|
|
return list(self._graph.predecessors(node_id)) |
|
|
|
|
|
|
|
|
|
|
|
def get_states_number(self, node_id): |
|
|
|
def get_states_number(self, node_id) -> int: |
|
|
|
return self._graph.nodes[node_id]['val'] |
|
|
|
return self._graph.nodes[node_id]['val'] |
|
|
|
|
|
|
|
|
|
|
|
def get_node_indx(self, node_id): |
|
|
|
def get_node_indx(self, node_id) -> int: |
|
|
|
return nx.get_node_attributes(self._graph, 'indx')[node_id] |
|
|
|
return nx.get_node_attributes(self._graph, 'indx')[node_id] |
|
|
|
|
|
|
|
|
|
|
|
def get_positional_node_indx(self, node_id): |
|
|
|
def get_positional_node_indx(self, node_id) -> int: |
|
|
|
return self._graph.nodes[node_id]['pos_indx'] |
|
|
|
return self._graph.nodes[node_id]['pos_indx'] |
|
|
|
|
|
|
|
|
|
|
|
@property |
|
|
|
@property |
|
|
|
def nodes(self) -> typing.List: |
|
|
|
def nodes(self) -> typing.List: |
|
|
|
return self._nodes_labels |
|
|
|
return self._graph_struct.nodes_labels |
|
|
|
|
|
|
|
|
|
|
|
@property |
|
|
|
@property |
|
|
|
def edges(self) -> typing.List: |
|
|
|
def edges(self) -> typing.List: |
|
|
@ -220,11 +212,11 @@ class NetworkGraph: |
|
|
|
|
|
|
|
|
|
|
|
@property |
|
|
|
@property |
|
|
|
def nodes_indexes(self) -> np.ndarray: |
|
|
|
def nodes_indexes(self) -> np.ndarray: |
|
|
|
return self._nodes_indexes |
|
|
|
return self._graph_struct.nodes_indexes |
|
|
|
|
|
|
|
|
|
|
|
@property |
|
|
|
@property |
|
|
|
def nodes_values(self) -> np.ndarray: |
|
|
|
def nodes_values(self) -> np.ndarray: |
|
|
|
return self._nodes_values |
|
|
|
return self._graph_struct.nodes_values |
|
|
|
|
|
|
|
|
|
|
|
@property |
|
|
|
@property |
|
|
|
def time_scalar_indexing_strucure(self) -> np.ndarray: |
|
|
|
def time_scalar_indexing_strucure(self) -> np.ndarray: |
|
|
@ -246,7 +238,8 @@ class NetworkGraph: |
|
|
|
def p_combs(self) -> np.ndarray: |
|
|
|
def p_combs(self) -> np.ndarray: |
|
|
|
return self._p_combs_structure |
|
|
|
return self._p_combs_structure |
|
|
|
|
|
|
|
|
|
|
|
"""##############These Methods are actually unused but could become useful in the near future################""" |
|
|
|
""" |
|
|
|
|
|
|
|
##############These Methods are actually unused but could become useful in the near future################ |
|
|
|
|
|
|
|
|
|
|
|
def init_graph(self): |
|
|
|
def init_graph(self): |
|
|
|
self.add_nodes(self._nodes_labels) |
|
|
|
self.add_nodes(self._nodes_labels) |
|
|
@ -302,4 +295,5 @@ class NetworkGraph: |
|
|
|
pass |
|
|
|
pass |
|
|
|
else: |
|
|
|
else: |
|
|
|
fancy_indx = [i[1] for i in self._aggregated_info_about_nodes_parents] |
|
|
|
fancy_indx = [i[1] for i in self._aggregated_info_about_nodes_parents] |
|
|
|
return fancy_indx |
|
|
|
return fancy_indx |
|
|
|
|
|
|
|
""" |