from extensions.list import CoreList from itertools import repeat class AllSequencesModel: """ A class that processes information from the assembly and creates the objects necessary to create the assembly sequence """ all_sequences = None adj_matrix = None topologyIds = None adj_matrix_names = None def __init__(self, adj_matrix, restrictions: list[str]) -> None: self.adj_matrix = adj_matrix self.all_possible_sequences(self.adj_matrix) self.matrix_by_name() if restrictions.__len__() != 0: self.restrictionsValidate(restrictions) pass def restrictionsValidate(self, restrictions: CoreList[str]): """_summary_ Args: restrictions (CoreList[str]): _description_ """ filterMatrix = CoreList() for el in self.adj_matrix_names: result = False for restraint in restrictions: result = CoreList(el).indexedPriorities(restraint[0], restraint[1]) if result: filterMatrix.onlyUniqueElementAppend(el) self.adj_matrix_names = filterMatrix pass def matrix_by_name(self): result = self.all_sequences inc = 0 for matrix in self.all_sequences: for index in range(len(matrix)): result[inc][index] = CoreList( filter( lambda el: el.get("number") == matrix[index] + 1, self.topologyIds, ) )[0].get("name") inc += 1 self.adj_matrix_names = result pass def find_all_sequences(self, adj_matrix): """Find all assembly sequences with dfs Args: adj_matrix (dict): Assembly ajacency matrix """ sequences = [] num_vertices = len(adj_matrix) def dfs(vertex, sequence): sequence.append(vertex) if len(sequence) == num_vertices: sequences.append(sequence) return for i in range(num_vertices): if adj_matrix[vertex][i] == 1 and i not in sequence: dfs(i, sequence.copy()) for i in range(num_vertices): dfs(i, []) self.all_sequences = sequences def findId(self, listMatrix, id): def filter_odd_num(in_num): if in_num["name"] == id: return True else: return False return list(filter(filter_odd_num, listMatrix))[0]["number"] def iter_paths(self, adj, min_length=6, path=None): if not path: for start_node in range(len(adj)): yield from self.iter_paths(adj, min_length, [start_node]) else: if len(path) >= min_length: yield path if path[-1] in path[:-1]: return current_node = path[-1] for next_node in range(len(adj[current_node])): if adj[current_node][next_node] == 1: yield from self.iter_paths(adj, min_length, path + [next_node]) def allUnique(self, x): seen = set() return not any(i in seen or seen.add(i) for i in x) def all_possible_sequences(self, matrix): topologyIds = [] topologyMatrixNumber = {} inc = 0 for k, v in matrix.items(): inc += 1 topologyIds.append({"name": k, "number": inc}) inc = 0 for k, v in matrix.items(): inc += 1 topologyMatrixNumber[inc] = list( map(lambda el: self.findId(topologyIds, el), v) ) self.topologyIds = topologyIds adj = [] matrixSize = matrix.keys().__len__() inc = 0 for k, v in topologyMatrixNumber.items(): adj.append(list(repeat(0, matrixSize))) for el in v: adj[inc][el - 1] = 1 inc += 1 return self.find_all_sequences(adj)