def compute_periodicity_cycle_basis(self): """ Returns: """ my_simple_graph = nx.Graph(self._connected_subgraph) cycles = nx.cycle_basis(my_simple_graph) all_deltas = [] for cyc in cycles: mycyc = list(cyc) mycyc.append(cyc[0]) this_cycle_deltas = [np.zeros(3, np.int)] for (node1, node2) in [(node1, mycyc[inode1 + 1]) for inode1, node1 in enumerate(mycyc[:-1])]: this_cycle_deltas_new = [] for key, edge_data in self._connected_subgraph[node1][ node2].items(): delta = get_delta(node1, node2, edge_data) for current_delta in this_cycle_deltas: this_cycle_deltas_new.append(current_delta + delta) this_cycle_deltas = this_cycle_deltas_new all_deltas.extend(this_cycle_deltas) all_deltas = get_linearly_independent_vectors(all_deltas) if len(all_deltas) == 3: self._periodicity_vectors = all_deltas return # One has to consider pairs of nodes with parallel edges (these are not considered in the simple graph cycles) edges = my_simple_graph.edges() for n1, n2 in edges: if n1 == n2: continue if len(self._connected_subgraph[n1][n2]) == 1: continue elif len(self._connected_subgraph[n1][n2]) > 1: for iedge1, iedge2 in itertools.combinations( self._connected_subgraph[n1][n2], 2): e1data = self._connected_subgraph[n1][n2][iedge1] e2data = self._connected_subgraph[n1][n2][iedge2] current_delta = get_delta(n1, n2, e1data) delta = get_delta(n2, n1, e2data) current_delta += delta all_deltas.append(current_delta) else: raise ValueError('Should not be here ...') all_deltas = get_linearly_independent_vectors(all_deltas) if len(all_deltas) == 3: self._periodicity_vectors = all_deltas return self._periodicity_vectors = all_deltas
def test_linearly_independent_vectors(self): v1 = np.array([1, 0, 0]) v2 = np.array([0, 1, 0]) v3 = np.array([0, 0, 1]) v4 = np.array([-1, 0, 0]) v5 = np.array([1, 1, 0]) independent_vectors = get_linearly_independent_vectors([v1, v2, v3]) self.assertEqual(len(independent_vectors), 3) independent_vectors = get_linearly_independent_vectors([v1, v2, v4]) self.assertEqual(len(independent_vectors), 2) independent_vectors = get_linearly_independent_vectors([v1, v2, v5]) self.assertEqual(len(independent_vectors), 2) independent_vectors = get_linearly_independent_vectors([v1, v2, v3, v4, v5]) self.assertEqual(len(independent_vectors), 3)
def test_linearly_independent_vectors(self): v1 = np.array([1, 0, 0]) v2 = np.array([0, 1, 0]) v3 = np.array([0, 0, 1]) v4 = np.array([-1, 0, 0]) v5 = np.array([1, 1, 0]) independent_vectors = get_linearly_independent_vectors([v1, v2, v3]) self.assertEqual(len(independent_vectors), 3) independent_vectors = get_linearly_independent_vectors([v1, v2, v4]) self.assertEqual(len(independent_vectors), 2) independent_vectors = get_linearly_independent_vectors([v1, v2, v5]) self.assertEqual(len(independent_vectors), 2) independent_vectors = get_linearly_independent_vectors( [v1, v2, v3, v4, v5]) self.assertEqual(len(independent_vectors), 3)
def compute_periodicity_all_simple_paths_algorithm(self): """ Returns: """ self_loop_nodes = list(nx.nodes_with_selfloops(self._connected_subgraph)) all_nodes_independent_cell_image_vectors = [] my_simple_graph = nx.Graph(self._connected_subgraph) for test_node in self._connected_subgraph.nodes(): # TODO: do we need to go through all test nodes ? this_node_cell_img_vectors = [] if test_node in self_loop_nodes: for key, edge_data in self._connected_subgraph[test_node][test_node].items(): if edge_data["delta"] == (0, 0, 0): raise ValueError("There should not be self loops with delta image = (0, 0, 0).") this_node_cell_img_vectors.append(edge_data["delta"]) for d1, d2 in itertools.combinations(this_node_cell_img_vectors, 2): if d1 == d2 or d1 == tuple(-ii for ii in d2): raise ValueError("There should not be self loops with the same (or opposite) delta image.") this_node_cell_img_vectors = get_linearly_independent_vectors(this_node_cell_img_vectors) # Here, we adopt a cutoff equal to the size of the graph, contrary to the default of networkX (size - 1), # because otherwise, the all_simple_paths algorithm fail when the source node is equal to the target node. paths = [] # TODO: its probably possible to do just a dfs or bfs traversal instead of taking all simple paths! test_node_neighbors = my_simple_graph.neighbors(test_node) breaknodeloop = False for test_node_neighbor in test_node_neighbors: # Special case for two nodes if len(self._connected_subgraph[test_node][test_node_neighbor]) > 1: this_path_deltas = [] node_node_neighbor_edges_data = list( self._connected_subgraph[test_node][test_node_neighbor].values() ) for edge1_data, edge2_data in itertools.combinations(node_node_neighbor_edges_data, 2): delta1 = get_delta(test_node, test_node_neighbor, edge1_data) delta2 = get_delta(test_node_neighbor, test_node, edge2_data) this_path_deltas.append(delta1 + delta2) this_node_cell_img_vectors.extend(this_path_deltas) this_node_cell_img_vectors = get_linearly_independent_vectors(this_node_cell_img_vectors) if len(this_node_cell_img_vectors) == 3: break for path in nx.all_simple_paths( my_simple_graph, test_node, test_node_neighbor, cutoff=len(self._connected_subgraph), ): path_indices = [nodepath.isite for nodepath in path] if path_indices == [test_node.isite, test_node_neighbor.isite]: continue path_indices.append(test_node.isite) path_indices = tuple(path_indices) if path_indices not in paths: paths.append(path_indices) else: continue path.append(test_node) # TODO: there are some paths that appears twice for cycles, and there are some paths that should # probably not be considered this_path_deltas = [np.zeros(3, np.int_)] for (node1, node2) in [(node1, path[inode1 + 1]) for inode1, node1 in enumerate(path[:-1])]: this_path_deltas_new = [] for key, edge_data in self._connected_subgraph[node1][node2].items(): delta = get_delta(node1, node2, edge_data) for current_delta in this_path_deltas: this_path_deltas_new.append(current_delta + delta) this_path_deltas = this_path_deltas_new this_node_cell_img_vectors.extend(this_path_deltas) this_node_cell_img_vectors = get_linearly_independent_vectors(this_node_cell_img_vectors) if len(this_node_cell_img_vectors) == 3: breaknodeloop = True break if breaknodeloop: break this_node_cell_img_vectors = get_linearly_independent_vectors(this_node_cell_img_vectors) independent_cell_img_vectors = this_node_cell_img_vectors all_nodes_independent_cell_image_vectors.append(independent_cell_img_vectors) # If we have found that the sub structure network is 3D-connected, we can stop ... if len(independent_cell_img_vectors) == 3: break self._periodicity_vectors = [] if len(all_nodes_independent_cell_image_vectors) != 0: for independent_cell_img_vectors in all_nodes_independent_cell_image_vectors: if len(independent_cell_img_vectors) > len(self._periodicity_vectors): self._periodicity_vectors = independent_cell_img_vectors if len(self._periodicity_vectors) == 3: break