示例#1
0
  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)
示例#2
0
  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)