1
0
Fork 0

Added DOCSTRING and Comments to most of the classes; Some refactorings on methods

parallel_struct_est
philpMartin 4 years ago
parent 78e00ae3e4
commit 38111c41fe
  1. 3
      .gitignore
  2. 63
      main_package/classes/dynamic_graph.py
  3. 101
      main_package/classes/importer.py
  4. 16
      main_package/classes/node.py
  5. 15
      main_package/classes/sample_path.py
  6. 22
      main_package/classes/trajectory.py

3
.gitignore vendored

@ -1 +1,2 @@
__pycache__ __pycache__
.vscode

@ -4,6 +4,18 @@ import node
class DynamicGraph(): class DynamicGraph():
"""
Rappresenta un grafo dinamico con la seguente struttura:
{Key: {Arcs:{node_object: #in_arcs.....}, Time:t, Node:node_object}.....}
Key = lo state_id del nodo
Arcs = la lista di adiacenza del nodo identificato dalla stringa state_id, contenente oggetti di tipo Node
Time = lo state residence time del nodo identificato dalla stringa state_id
Node = L'oggetto Node con lo stesso state_id pari a Key e node_id opportunamento inizalizzato
:sample_path: le traiettorie/a da cui costruire il grafo
:graph: la struttura dinamica che definisce il grafo
:states_number: il numero di nodi contenuti nel grafo graph
"""
def __init__(self, sample_path): def __init__(self, sample_path):
self.sample_path = sample_path self.sample_path = sample_path
@ -11,6 +23,10 @@ class DynamicGraph():
self.states_number = 0 self.states_number = 0
def initialize_graph(self, trajectory): def initialize_graph(self, trajectory):
"""
Data la traiettoria trajectory inizializza le chiavi del dizionario graph e crea le opportune sottostrutture interne.
"""
for(node_id,state) in enumerate(trajectory.get_states()): for(node_id,state) in enumerate(trajectory.get_states()):
n = node.Node(state, node_id) n = node.Node(state, node_id)
self.graph[state] = {"Arcs":{}, "Time":0.0, "Node":n} self.graph[state] = {"Arcs":{}, "Time":0.0, "Node":n}
@ -24,30 +40,55 @@ class DynamicGraph():
self.add_transaction(matrix_traj, indx) self.add_transaction(matrix_traj, indx)
def add_transaction(self, matrix_traj, indx): def add_transaction(self, matrix_traj, indx):
"""
Aggiunge la transizione dal nodo current_state al nodo next_state e aggiorna lo state residence time del nodo
con chiave current_state.
Parameters:
matrix_traj: la traiettoria con cui si sta costruendo il grafo graph
indx: la posizione nella visita
Returns:
void
"""
current_state = matrix_traj[indx][1] current_state = matrix_traj[indx][1]
next_state = matrix_traj[indx + 1][1] next_state = matrix_traj[indx + 1][1]
self.graph[current_state]["Time"] += matrix_traj[indx + 1][0] - matrix_traj[indx][0] self.graph[current_state]["Time"] += matrix_traj[indx + 1][0] - matrix_traj[indx][0]
next_node = self.graph[next_state]["Node"] next_node = self.graph[next_state]["Node"] #Punta all'oggeto Node con node_id precedentemente settato
if next_node not in self.graph[current_state]["Arcs"].keys(): if next_node not in self.graph[current_state]["Arcs"].keys(): #Se non hai ancora incontrato next_node inizializza il numero di archi entranti
self.graph[current_state]["Arcs"][next_node] = 1 self.graph[current_state]["Arcs"][next_node] = 1
else: else:
self.graph[current_state]["Arcs"][next_node] += 1 self.graph[current_state]["Arcs"][next_node] += 1
def append_new_trajectory(self, trajectory): def append_new_trajectory(self, trajectory):
"""
Aggiunge i risultati di una nuova esplorazione trajectory al grafo graph.
Parameters:
trajectory: la traiettoria da aggiungere
Returns:
void
"""
matrix_traj = trajectory.get_trajectory_as_matrix() matrix_traj = trajectory.get_trajectory_as_matrix()
for indx in range(len(matrix_traj) - 1):
current_state = matrix_traj[0][1] #Aggiungi se necessario i primi due stati
next_state = matrix_traj[1][1]
self.add_node_if_not_present(current_state)
self.add_node_if_not_present(next_state)
self.add_transaction(matrix_traj, 0)
for indx in range(1, (len(matrix_traj) - 1)):
current_state = matrix_traj[indx][1] current_state = matrix_traj[indx][1]
next_state = matrix_traj[indx + 1][1] next_state = matrix_traj[indx + 1][1]
if current_state not in self.graph.keys(): self.add_node_if_not_present(next_state)
current_node = node.Node(current_state, self.states_number)
self.graph[current_state] = {"Arcs":{}, "Time":0.0, "Node":current_node}
self.states_number += 1
if next_state not in self.graph.keys():
next_node = node.Node(next_state, self.states_number)
self.graph[next_state] = {"Arcs":{}, "Time":0.0, "Node":next_node}
self.states_number += 1
self.add_transaction(matrix_traj, indx) self.add_transaction(matrix_traj, indx)
def add_node_if_not_present(self, current_state):
if current_state not in self.graph.keys(): #Se non hai ancora incontrato il lo state current_state
current_node = node.Node(current_state, self.states_number) #Crea il l'oggetto con opportuno node_id
self.graph[current_state] = {"Arcs":{}, "Time":0.0, "Node":current_node} #Aggiungilo al dizionario graph
self.states_number += 1
def build_graph(self): def build_graph(self):
for indx, trajectory in enumerate(self.sample_path.trajectories): for indx, trajectory in enumerate(self.sample_path.trajectories):
if indx == 0: if indx == 0:

@ -7,37 +7,44 @@ import numpy as np
class Importer(): class Importer():
"""Importer forisce tutti i metodi per importare i dataset in input in pandas data_frame ed effettuare operazioni """
volte ad ottenere i valori contenuti in tali frame nel formato utile alle computazioni sui dati. Fornisce tutti i metodi per importare i dataset contenuti nella directory files_path
in pandas data_frame.
Permette di effettuare operazioni
volte ad ottenere i valori contenuti in tali frame nel formato utile alle computazioni successive.
:files_path: il path alla cartella contenente i dataset da utilizzare :files_path: il path alla cartella contenente i dataset da utilizzare
:df_list: lista contentente tutti i padas_data_frame che saranno importati :df_list: lista contentente tutti i padas_data_frame contenuti nella directory files_path
""" """
def __init__(self, files_path): def __init__(self, files_path):
self.files_path = files_path self.files_path = files_path
self.df_list = [] self.df_list = []
#self.trajectories = []
def import_data_from_csv(self): def import_data_from_csv(self):
"""Importa tutti i file csv presenti nel path files_path in data_frame distinti. """
Aggiunge ogni data_frame alla lista df_list. Importa tutti i file csv presenti nel path files_path in data_frame distinti.
Aggiunge ogni data_frame alla lista df_list.
Parameters: Parameters:
void void
Returns:
Returns: void
void """
try:
read_files = glob.glob(os.path.join(self.files_path, "*.csv"))
for file in read_files:
my_df = pd.read_csv(file)
self.check_types_validity(my_df)
self.df_list.append(my_df)
except ValueError as err:
print(err.args)
"""
read_files = glob.glob(os.path.join(self.files_path, "*.csv"))
for file in read_files:
my_df = pd.read_csv(file) #TODO:Aggiungere try-catch controllo correttezza dei tipi di dato presenti nel dataset e.g. i tipi di dato della seconda colonna devono essere float
self.df_list.append(my_df)
def merge_value_columns(self, df): def merge_value_columns(self, df):
""" Effettua il merging di tutte le colonne che contengono i valori delle variabili in un unica colonna chiamata State. """
Effettua il merging di tutte le colonne che contengono i valori delle variabili
in un unica colonna chiamata State.
Parameters: Parameters:
df: il data_frame su cui effettuare il merging delle colonne df: il data_frame su cui effettuare il merging delle colonne
Returns: Returns:
@ -45,27 +52,75 @@ class Importer():
""" """
df['State'] = df[df.columns[2:]].apply(lambda row: ''.join(row.values.astype(str)), axis=1) df['State'] = df[df.columns[2:]].apply(lambda row: ''.join(row.values.astype(str)), axis=1)
def merge_value_columns_in_all_frames(self):
"""
Richiama il metodo merge_value_columns su tutti i data_frame contenuti nella df_list
Parameters:
void
Returns:
void
"""
for data_frame in self.df_list:
self.merge_value_columns(data_frame)
def drop_unneccessary_columns(self, df): def drop_unneccessary_columns(self, df):
"""
Rimuove le colonne contenenti i valori delle variabili dal data_frame df.
Parameters:
df: il data_frame su cui rimuovere le colonne
Returns:
void
"""
cols = df.columns.values[2:-1] cols = df.columns.values[2:-1]
print(cols) print(cols)
df.drop(cols, axis=1, inplace=True) df.drop(cols, axis=1, inplace=True)
def drop_unneccessary_columns_in_all_frames(self): def drop_unneccessary_columns_in_all_frames(self):
"""
Richiama il metodo drop_unneccessary_columns su tutti i data_frame contenuti nella df_list
Parameters:
void
Returns:
void
"""
for data_frame in self.df_list: for data_frame in self.df_list:
self.drop_unneccessary_columns(data_frame) self.drop_unneccessary_columns(data_frame)
def merge_value_columns_in_all_frames(self):
for data_frame in self.df_list:
self.merge_value_columns(data_frame)
def get_data_frames(self): def get_data_frames(self):
"""
Restituisce la lista contenente tutti i data_frames caricati in df_list.
Parameters:
void
Returns:
data_frames list
"""
return self.df_list return self.df_list
def clear_data_frames(self): def clear_data_frames(self):
"""
Rimuove tutti i valori contenuti nei data_frames presenti in df_list
Parameters:
void
Returns:
void
"""
for data_frame in self.df_list: for data_frame in self.df_list:
data_frame = data_frame.iloc[0:0] data_frame = data_frame.iloc[0:0]
def check_types_validity(self, data_frame): #Solo un esempio di controllo sui valori contenuti nel dataset
"""
Controlla la correttezza dei tipi contenuti nei dati caricati nel data_frame (in questo caso solo che nella seconda colonna siano contenuti dei float)
"""
if data_frame.iloc[:,1].dtype != np.float64:
raise ValueError("The Dataset is Not in the correct format")
#TODO Integrare i controlli di correttezza sul dataset e capire quali assunzioni vanno fatte

@ -1,6 +1,13 @@
class Node(): class Node():
"""
Astrae il concetto di nodo appartenente ad un grafo G.
Un nodo viene univocamente identificato dal suo state_id, il tag node_id è utilizzato per stabilire la posizione
del nodo stesso nel grafo rappresentato attraverso la matrice di adiacenza.
:state_id: UID del nodo
:node_id: int
"""
def __init__(self, state_id, node_id=-1): def __init__(self, state_id, node_id=-1):
self.state_id = state_id self.state_id = state_id
@ -12,7 +19,16 @@ class Node():
def __hash__(self): def __hash__(self):
return hash(self.__key()) return hash(self.__key())
def __eq__(self, other): def __eq__(self, other):
"""
Controlla l'uguaglianza di due oggetti Node.
Due nodi sono uguali sse hanno lo stesso state_id
Parameters:
other: oggetto nodo con cui effettuare il confronto
Returns:
boolean
"""
if isinstance(other, Node): if isinstance(other, Node):
return self.__key() == other.__key() return self.__key() == other.__key()
return NotImplemented return NotImplemented

@ -6,6 +6,14 @@ import trajectory as tr
class SamplePath(): class SamplePath():
"""
Rappresenta l'aggregazione di una o più traiettorie.
Ha il compito dato di costruire tutte gli oggetti Trajectory a partire
dai dataset contenuti nella directory files_path.
:importer: l'oggetto Importer che ha il compito di caricare i dataset
:trajectories: lista contenente le traiettorie create
"""
def __init__(self, files_path=os.getcwd() + "/main_package/data"): def __init__(self, files_path=os.getcwd() + "/main_package/data"):
self.importer = imp.Importer(files_path) self.importer = imp.Importer(files_path)
@ -26,11 +34,4 @@ class SamplePath():
######Veloci Tests#######
s1 = SamplePath()
s1.build_trajectories()
print(s1.get_number_trajectories())
#print(s1.trajectories[0].get_trajectory())

@ -3,15 +3,35 @@ import numpy as np
class Trajectory(): class Trajectory():
"""
Rappresenta una traiettoria come un data_frame contenente coppie (T_k,S_i) => (numpy.float64, string)
Offre i metodi utili alla computazione sulla struttura stessa.
:actual_trajectory: il data_frame contenente la successione di coppie (T_k,S_i)
"""
def __init__(self, data_frame): def __init__(self, data_frame):
self.actual_trajectory = data_frame self.actual_trajectory = data_frame
def get_trajectory(self): def get_trajectory(self):
return self.actual_trajectory return self.actual_trajectory
def get_trajectory_as_matrix(self): def get_trajectory_as_matrix(self):
"""
Converte il data_frame actual_trajectory in formato numpy.array
Parameters:
void
Returns:
numpy.array
"""
return self.actual_trajectory[['Time','State']].to_numpy() return self.actual_trajectory[['Time','State']].to_numpy()
def get_states(self): def get_states(self):
"""
Identifica gli stati visitati nella traiettoria.
Parameters:
void
Returns:
una lista contenente gli stati visitati nella traiettoria
"""
return self.actual_trajectory['State'].unique() return self.actual_trajectory['State'].unique()