コード例 #1
0
ファイル: recombine.py プロジェクト: google2013/Cirq
def move_non_clifford_into_clifford(circuit_left: Union[circuits.Circuit,
                                                        circuits.CircuitDag],
                                    circuit_right: circuits.Circuit
                                    ) -> circuits.Circuit:
    if isinstance(circuit_left, circuits.CircuitDag):
        string_dag = cast(circuits.CircuitDag, circuit_left)
    else:
        string_dag = pauli_string_dag_from_circuit(
                        cast(circuits.Circuit, circuit_left))
    output_ops = list(circuit_right.all_operations())

    rightmost_nodes = (set(string_dag.nodes)
                       - set(before for before, _ in string_dag.edges))

    def possible_string_placements(
            ) -> Iterator[Tuple[PauliStringGateOperation, int,
                                circuits.Unique[PauliStringGateOperation]]]:
        for right_node in rightmost_nodes:
            string_op = right_node.val
            # Try moving the Pauli string through, stop at measurements
            yield string_op, 0, right_node
            for i, out_op in enumerate(output_ops):
                if not set(out_op.qubits) & set(string_op.qubits):
                    # Skip if operations don't share qubits
                    continue
                if not (isinstance(out_op, ops.GateOperation) and
                        isinstance(out_op.gate, (ops.CliffordGate,
                                                 ops.PauliInteractionGate))):
                    # This is as far through as this Pauli string can move
                    break
                string_op = string_op.pass_operations_over([out_op],
                                                           after_to_before=True)
                yield string_op, i+1, right_node

    while rightmost_nodes:
        # Pick the Pauli string that can be moved furthest through the Clifford
        # circuit
        best_string_op, best_index, best_node = max(
            possible_string_placements(),
            key=lambda placement: (-len(placement[0].pauli_string),
                                   placement[1]))

        # Place the best one into the output circuit
        output_ops.insert(best_index, best_string_op)
        # Remove the best one from the dag and update rightmost_nodes
        rightmost_nodes.remove(best_node)
        rightmost_nodes.update(
            pred_node
            for pred_node in string_dag.predecessors(best_node)
            if len(string_dag.succ[pred_node]) <= 1)
        string_dag.remove_node(best_node)

    assert not string_dag.nodes, 'There was a cycle in the CircuitDag'

    return circuits.Circuit.from_ops(
            output_ops,
            strategy=circuits.InsertStrategy.EARLIEST,
            device=circuit_right.device)
コード例 #2
0
def move_non_clifford_into_clifford(
        circuit_left: Union[circuits.Circuit, circuits.CircuitDag],
        circuit_right: circuits.Circuit) -> circuits.Circuit:
    if isinstance(circuit_left, circuits.CircuitDag):
        string_dag = cast(circuits.CircuitDag, circuit_left)
    else:
        string_dag = pauli_string_dag_from_circuit(
            cast(circuits.Circuit, circuit_left))
    output_ops = list(circuit_right.all_operations())

    rightmost_nodes = (set(string_dag.nodes) -
                       set(before for before, _ in string_dag.edges))

    def possible_string_placements(
    ) -> Iterator[Tuple[PauliStringGateOperation, int,
                        circuits.Unique[PauliStringGateOperation]]]:
        for right_node in rightmost_nodes:
            string_op = right_node.val
            # Try moving the Pauli string through, stop at measurements
            yield string_op, 0, right_node
            for i, out_op in enumerate(output_ops):
                if not set(out_op.qubits) & set(string_op.qubits):
                    # Skip if operations don't share qubits
                    continue
                if not (isinstance(out_op, ops.GateOperation) and isinstance(
                        out_op.gate,
                    (ops.CliffordGate, ops.PauliInteractionGate))):
                    # This is as far through as this Pauli string can move
                    break
                string_op = string_op.pass_operations_over(
                    [out_op], after_to_before=True)
                yield string_op, i + 1, right_node

    while rightmost_nodes:
        # Pick the Pauli string that can be moved furthest through the Clifford
        # circuit
        best_string_op, best_index, best_node = max(
            possible_string_placements(),
            key=lambda placement:
            (-len(placement[0].pauli_string), placement[1]))

        # Place the best one into the output circuit
        output_ops.insert(best_index, best_string_op)
        # Remove the best one from the dag and update rightmost_nodes
        rightmost_nodes.remove(best_node)
        rightmost_nodes.update(
            pred_node for pred_node in string_dag.predecessors(best_node)
            if len(string_dag.succ[pred_node]) <= 1)
        string_dag.remove_node(best_node)

    assert not string_dag.nodes, 'There was a cycle in the CircuitDag'

    return circuits.Circuit.from_ops(output_ops,
                                     strategy=circuits.InsertStrategy.EARLIEST,
                                     device=circuit_right.device)
コード例 #3
0
def move_pauli_strings_into_circuit(
        circuit_left: Union[circuits.Circuit, circuits.CircuitDag],
        circuit_right: circuits.Circuit) -> circuits.Circuit:
    if isinstance(circuit_left, circuits.CircuitDag):
        string_dag = circuits.CircuitDag(pauli_string_reorder_pred,
                                         circuit_left)
    else:
        string_dag = pauli_string_dag_from_circuit(
            cast(circuits.Circuit, circuit_left))
    output_ops = list(circuit_right.all_operations())

    rightmost_nodes = (set(string_dag.nodes()) -
                       set(before for before, _ in string_dag.edges()))

    while rightmost_nodes:
        # Sort the pauli string placements based on paulistring length and
        # furthest possible distance in circuit_right
        placements = _sorted_best_string_placements(rightmost_nodes,
                                                    output_ops)
        last_index = len(output_ops)

        # Pick the Pauli string that can be moved furthest through
        # the Clifford circuit
        for best_string_op, best_index, best_node in placements:

            assert best_index <= last_index, (
                "Unexpected insertion index order,"
                " {} >= {}, len: {}".format(best_index, last_index,
                                            len(output_ops)))

            last_index = best_index
            output_ops.insert(best_index, best_string_op)
            # Remove the best one from the dag and update rightmost_nodes
            rightmost_nodes.remove(best_node)
            rightmost_nodes.update(
                pred_node for pred_node in string_dag.predecessors(best_node)
                if len(string_dag.succ[pred_node]) <= 1)
            string_dag.remove_node(best_node)

    assert not string_dag.nodes(), 'There was a cycle in the CircuitDag'

    return circuits.Circuit(output_ops,
                            strategy=circuits.InsertStrategy.EARLIEST,
                            device=circuit_right.device)
コード例 #4
0
def pauli_string_optimized_circuit(circuit: circuits.Circuit,
                                   move_cliffords: bool = True,
                                   atol: float = 1e-8) -> circuits.Circuit:
    cl, cr = convert_and_separate_circuit(circuit,
                                          leave_cliffords=not move_cliffords,
                                          atol=atol)
    string_dag = pauli_string_dag_from_circuit(cl)

    # Merge and remove Pauli string phasors
    while True:
        before_len = len(string_dag.nodes())
        merge_equal_strings(string_dag)
        remove_negligible_strings(string_dag)
        if len(string_dag.nodes()) >= before_len:
            break

    c_all = move_pauli_strings_into_circuit(string_dag, cr)

    assert_no_multi_qubit_pauli_strings(c_all)

    return c_all
コード例 #5
0
def move_pauli_strings_into_circuit(
        circuit_left: Union[circuits.Circuit, circuits.CircuitDag],
        circuit_right: circuits.Circuit) -> circuits.Circuit:
    if isinstance(circuit_left, circuits.CircuitDag):
        string_dag = circuits.CircuitDag(pauli_string_reorder_pred,
                                         circuit_left)
    else:
        string_dag = pauli_string_dag_from_circuit(
            cast(circuits.Circuit, circuit_left))
    output_ops = list(circuit_right.all_operations())

    rightmost_nodes = (set(string_dag.nodes) -
                       set(before for before, _ in string_dag.edges))

    while rightmost_nodes:
        # Pick the Pauli string that can be moved furthest through the Clifford
        # circuit
        best_string_op, best_index, best_node = max(
            _possible_string_placements(rightmost_nodes, output_ops),
            key=lambda placement:
            (-len(placement[0].pauli_string), placement[1]))

        # Place the best one into the output circuit
        output_ops.insert(best_index, best_string_op)
        # Remove the best one from the dag and update rightmost_nodes
        rightmost_nodes.remove(best_node)
        rightmost_nodes.update(
            pred_node for pred_node in string_dag.predecessors(best_node)
            if len(string_dag.succ[pred_node]) <= 1)
        string_dag.remove_node(best_node)

    assert not string_dag.nodes, 'There was a cycle in the CircuitDag'

    return circuits.Circuit.from_ops(output_ops,
                                     strategy=circuits.InsertStrategy.EARLIEST,
                                     device=circuit_right.device)