Exemplo n.º 1
0
def merge_equal_strings(string_dag: circuits.CircuitDag) -> None:
    for node in tuple(string_dag.nodes()):
        if node not in string_dag.nodes():
            # Node was removed
            continue
        commuting_nodes = (set(string_dag.nodes()) -
                           set(networkx.dag.ancestors(string_dag, node)) -
                           set(networkx.dag.descendants(string_dag, node)) -
                           set([node]))
        for other_node in commuting_nodes:
            if node.val.pauli_string.equal_up_to_sign(
                    other_node.val.pauli_string):
                string_dag.remove_node(other_node)
                node.val = node.val.merged_with(other_node.val)
Exemplo n.º 2
0
def get_time_slices(dag: circuits.CircuitDag) -> List[nx.Graph]:
    """Slices the DAG into logical graphs.

    Each time slice is a graph whose vertices are qubits and whose edges
    correspond to two-qubit gates. Single-qubit gates are ignored (and
    more-than-two-qubit gates are not supported).

    The edges of the first time slice correspond to the nodes of the DAG without
    predecessors. (Again, single-qubit gates are ignored.) The edges of the
    second slice correspond to the nodes of the DAG whose only predecessors are
    in the first time slice, and so on.
    """
    circuit = circuits.Circuit(op for op in dag.all_operations()
                               if len(op.qubits) > 1)
    return [
        nx.Graph(op.qubits for op in moment.operations) for moment in circuit
    ]
Exemplo n.º 3
0
def is_topologically_sorted(dag: circuits.CircuitDag,
                            operations: ops.OP_TREE) -> bool:
    """Whether a given order of operations is consistent with the DAG.

    For example, suppose the (transitive reduction of the) circuit DAG is

         ╭─> Op2 ─╮
    Op1 ─┤        ├─> Op4
         ╰─> Op3 ─╯

    Then [Op1, Op2, Op3, Op4] and [Op1, Op3, Op2, Op4] (and any operations
    tree that flattens to one of them) are topologically sorted according
    to the DAG, and any other ordering of the four operations is not.

    Evaluates to False when the set of operations is different from those
    in the nodes of the DAG, regardless of the ordering.

    Args:
        dag: The circuit DAG.
        operations: The ordered operations.

    Returns:
        Whether or not the operations given are topologically sorted
        according to the DAG.
    """

    remaining_dag = dag.copy()
    frontier = [
        node for node in remaining_dag.nodes() if not remaining_dag.pred[node]
    ]
    for operation in ops.flatten_op_tree(operations):
        for i, node in enumerate(frontier):
            if node.val == operation:
                frontier.pop(i)
                succ = remaining_dag.succ[node]
                remaining_dag.remove_node(node)
                frontier.extend(new_node for new_node in succ
                                if not remaining_dag.pred[new_node])
                break
        else:
            return False
    return not bool(frontier)
Exemplo n.º 4
0
def remove_negligible_strings(string_dag: circuits.CircuitDag,
                              tolerance=linalg.Tolerance.DEFAULT) -> None:
    for node in tuple(string_dag.nodes()):
        if tolerance.all_near_zero_mod(node.val.half_turns, 2):
            string_dag.remove_node(node)
Exemplo n.º 5
0
def remove_negligible_strings(string_dag: circuits.CircuitDag,
                              atol=1e-8) -> None:
    for node in tuple(string_dag.nodes()):
        if linalg.all_near_zero_mod(node.val.exponent_relative, 2, atol=atol):
            string_dag.remove_node(node)
Exemplo n.º 6
0
def remove_negligible_strings(string_dag: circuits.CircuitDag,
                              atol=DEFAULT_ATOL) -> None:
    for node in tuple(string_dag.nodes()):
        if all_near_zero_mod(node.val.half_turns, 2, atol=atol):
            string_dag.remove_node(node)