def _remove_trace_edge(self, edge: network_components.Edge, new_node: network_components.BaseNode) -> None: """Collapse a trace edge. Collapses a trace edge and updates the network. Args: edge: The edge to contract. new_node: The new node created after contraction. Returns: The node that had the contracted edge. Raises: ValueError: If edge is not a trace edge. """ if edge.is_dangling(): raise ValueError("Attempted to remove dangling edge '{}'.".format(edge)) if edge.node1 is not edge.node2: raise ValueError("Edge '{}' is not a trace edge.".format(edge)) axes = sorted([edge.axis1, edge.axis2]) node_edges = edge.node1.edges[:] node_edges.pop(axes[0]) node_edges.pop(axes[1] - 1) seen_edges = set() for tmp_edge in node_edges: if tmp_edge in seen_edges: continue else: seen_edges.add(tmp_edge) if tmp_edge.node1 is edge.node1: to_reduce = 0 to_reduce += 1 if tmp_edge.axis1 > axes[0] else 0 to_reduce += 1 if tmp_edge.axis1 > axes[1] else 0 tmp_edge.axis1 -= to_reduce tmp_edge.node1 = new_node if tmp_edge.node2 is edge.node1: to_reduce = 0 to_reduce += 1 if tmp_edge.axis2 > axes[0] else 0 to_reduce += 1 if tmp_edge.axis2 > axes[1] else 0 tmp_edge.axis2 -= to_reduce tmp_edge.node2 = new_node # Update edges for the new node. for i, e in enumerate(node_edges): new_node.add_edge(e, i) self.nodes_set.remove(edge.node1)
def _remove_edges(self, edges: Set[network_components.Edge], node1: network_components.BaseNode, node2: network_components.BaseNode, new_node: network_components.BaseNode) -> None: """Collapse a list of edges shared by two nodes in the network. Collapses the edges and updates the rest of the network. The nodes that currently share the edges in `edges` must be supplied as `node1` and `node2`. The ordering of `node1` and `node2` must match the axis ordering of `new_node` (as determined by the contraction procedure). Args: edges: The edges to contract. node1: The old node that supplies the first edges of `new_node`. node2: The old node that supplies the last edges of `new_node`. new_node: The new node that represents the contraction of the two old nodes. Raises: Value Error: If edge isn't in the network. """ if node1 is node2: raise ValueError( "node1 and node2 are the same ('{}' == '{}'), but trace edges cannot " "be removed by _remove_edges.".format(node1, node2)) node1_edges = node1.edges[:] node2_edges = node2.edges[:] nodes_set = set([node1, node2]) for edge in edges: if edge.is_dangling(): raise ValueError("Attempted to remove dangling edge '{}'.".format(edge)) if set([edge.node1, edge.node2]) != nodes_set: raise ValueError( "Attempted to remove edges belonging to different node pairs: " "'{}' != '{}'.".format(nodes_set, set([edge.node1, edge.node2]))) remaining_edges = [] for (i, edge) in enumerate(node1_edges): if edge not in edges: # NOTE: Makes the cost quadratic in # edges edge.update_axis( old_node=node1, old_axis=i, new_axis=len(remaining_edges), new_node=new_node) remaining_edges.append(edge) for (i, edge) in enumerate(node2_edges): if edge not in edges: edge.update_axis( old_node=node2, old_axis=i, new_axis=len(remaining_edges), new_node=new_node) remaining_edges.append(edge) for (i, edge) in enumerate(remaining_edges): new_node.add_edge(edge, i) # Remove nodes self.nodes_set.remove(node1) self.nodes_set.remove(node2)