示例#1
0
    def optimize_circuit(self, circuit: Circuit):
        frontier = defaultdict(lambda: 0)  # type: Dict[QubitId, int]
        i = 0
        while i < len(circuit):  # Note: circuit may mutate as we go.
            for op in circuit[i].operations:
                # Don't touch stuff inserted by previous optimizations.
                if any(frontier[q] > i for q in op.qubits):
                    continue

                # Skip if an optimization removed the circuit underneath us.
                if i >= len(circuit):
                    continue
                # Skip if an optimization removed the op we're considering.
                if op not in circuit[i].operations:
                    continue
                opt = self.optimization_at(circuit, i, op)
                # Skip if the optimization did nothing.
                if opt is None:
                    continue

                # Clear target area, and insert new operations.
                circuit.clear_operations_touching(
                    opt.clear_qubits,
                    [e for e in range(i, i + opt.clear_span)])
                new_operations = self.post_clean_up(opt.new_operations)
                circuit.insert_at_frontier(new_operations, i, frontier)

            i += 1
 def optimize_circuit(self, circuit: _circuit.Circuit) -> None:
     deletions: List[Tuple[int, ops.Operation]] = []
     for moment_index, moment in enumerate(circuit):
         for op in moment.operations:
             if op is not None and protocols.trace_distance_bound(op) <= self.tolerance:
                 deletions.append((moment_index, op))
     circuit.batch_remove(deletions)
示例#3
0
    def optimize_circuit(self, circuit: Circuit):
        frontier = defaultdict(lambda: 0)  # type: Dict[QubitId, int]
        i = 0
        while i < len(circuit):  # Note: circuit may mutate as we go.
            for op in circuit[i].operations:
                # Don't touch stuff inserted by previous optimizations.
                if any(frontier[q] > i for q in op.qubits):
                    continue

                # Skip if an optimization removed the circuit underneath us.
                if i >= len(circuit):
                    continue
                # Skip if an optimization removed the op we're considering.
                if op not in circuit[i].operations:
                    continue
                opt = self.optimization_at(circuit, i, op)
                # Skip if the optimization did nothing.
                if opt is None:
                    continue

                # Clear target area, and insert new operations.
                circuit.clear_operations_touching(
                    opt.clear_qubits,
                    [e for e in range(i, i + opt.clear_span)])
                circuit.insert_at_frontier(opt.new_operations, i, frontier)

            i += 1
示例#4
0
def test_simple_circuits_to_unitary_matrix():
    a = cirq.NamedQubit('a')
    b = cirq.NamedQubit('b')

    # Phase parity.
    c = Circuit.from_ops(cirq.CNOT(a, b), cirq.Z(b), cirq.CNOT(a, b))
    m = c.to_unitary_matrix()
    cirq.testing.assert_allclose_up_to_global_phase(m,
                                                    np.array([
                                                        [1, 0, 0, 0],
                                                        [0, -1, 0, 0],
                                                        [0, 0, -1, 0],
                                                        [0, 0, 0, 1],
                                                    ]),
                                                    atol=1e-8)

    # 2-qubit matrix matches when qubits in order.
    for expected in [np.diag([1, 1j, -1, -1j]), cirq.CNOT.matrix()]:

        class Passthrough(cirq.KnownMatrixGate):
            def matrix(self):
                return expected

        c = Circuit.from_ops(Passthrough()(a, b))
        m = c.to_unitary_matrix()
        cirq.testing.assert_allclose_up_to_global_phase(m, expected)
示例#5
0
    def optimize_circuit(self, circuit: Circuit):
        walls = defaultdict(lambda: 0)  # type: Dict[QubitId, int]
        i = 0
        while i < len(circuit.moments):  # Note: circuit may mutate as we go.
            for op in circuit.moments[i].operations:
                # Don't touch stuff inserted by previous optimizations.
                if any(walls[q] > i for q in op.qubits):
                    continue

                # Skip if an optimization removed the circuit underneath us.
                if i >= len(circuit.moments):
                    continue
                # Skip if an optimization removed the op we're considering.
                if op not in circuit.moments[i].operations:
                    continue
                opt = self.optimization_at(circuit, i, op)
                # Skip if the optimization did nothing.
                if opt is None:
                    continue

                # Clear target area, and insert new operations.
                circuit.clear_operations_touching(
                    opt.clear_qubits,
                    [e for e in range(i, i + opt.clear_span)])
                next_insert_index = circuit.insert_into_range(
                    opt.new_operations, i, i + opt.clear_span)

                # Prevent redundant optimizations.
                for q in opt.clear_qubits:
                    walls[q] = max(walls[q], next_insert_index)

            i += 1
示例#6
0
def test_diagram_custom_precision():
    qa = cirq.NamedQubit('a')
    c = Circuit([Moment([cirq.X(qa)**0.12341234])])
    diagram = c.to_text_diagram(use_unicode_characters=False, precision=5)
    assert diagram.strip() == """
a: ---X^0.12341---
    """.strip()
示例#7
0
def test_to_text_diagram_teleportation_to_diagram():
    ali = cirq.NamedQubit('(0, 0)')
    bob = cirq.NamedQubit('(0, 1)')
    msg = cirq.NamedQubit('(1, 0)')
    tmp = cirq.NamedQubit('(1, 1)')

    c = Circuit([
        Moment([cirq.H(ali)]),
        Moment([cirq.CNOT(ali, bob)]),
        Moment([cirq.X(msg)**0.5]),
        Moment([cirq.CNOT(msg, ali)]),
        Moment([cirq.H(msg)]),
        Moment([cirq.measure(msg), cirq.measure(ali)]),
        Moment([cirq.CNOT(ali, bob)]),
        Moment([cirq.CNOT(msg, tmp)]),
        Moment([cirq.CZ(bob, tmp)]),
    ])

    assert c.to_text_diagram().strip() == """
(0, 0): ───H───@───────────X───────M───@───────────
               │           │           │
(0, 1): ───────X───────────┼───────────X───────@───
                           │                   │
(1, 0): ───────────X^0.5───@───H───M───────@───┼───
                                           │   │
(1, 1): ───────────────────────────────────X───@───
    """.strip()
    assert c.to_text_diagram(use_unicode_characters=False).strip() == """
(0, 0): ---H---@-----------X-------M---@-----------
               |           |           |
(0, 1): -------X-----------|-----------X-------@---
                           |                   |
(1, 0): -----------X^0.5---@---H---M-------@---|---
                                           |   |
(1, 1): -----------------------------------X---@---
        """.strip()

    assert c.to_text_diagram(transpose=True,
                             use_unicode_characters=False).strip() == """
(0, 0) (0, 1) (1, 0) (1, 1)
|      |      |      |
H      |      |      |
|      |      |      |
@------X      |      |
|      |      |      |
|      |      X^0.5  |
|      |      |      |
X-------------@      |
|      |      |      |
|      |      H      |
|      |      |      |
M      |      M      |
|      |      |      |
@------X      |      |
|      |      |      |
|      |      @------X
|      |      |      |
|      @-------------@
|      |      |      |
        """.strip()
示例#8
0
def test_diagram_wgate_none_precision():
    qa = cirq.NamedQubit('a')
    test_wgate = ExpWGate(half_turns=0.12341234, axis_half_turns=0.43214321)
    c = Circuit([Moment([test_wgate.on(qa)])])
    diagram = c.to_text_diagram(use_unicode_characters=False, precision=None)
    assert diagram.strip() == """
a: ---W(0.43214321)^0.12341234---
    """.strip()
示例#9
0
def test_overly_precise_diagram():
    # Test default precision of 3
    qa = cirq.NamedQubit('a')
    c = Circuit([Moment([cirq.X(qa)**0.12345678])])
    diagram = c.to_text_diagram(use_unicode_characters=False)
    assert diagram.strip() == """
a: ---X^0.123---
    """.strip()
示例#10
0
def test_none_precision_diagram():
    # Test default precision of 3
    qa = cirq.NamedQubit('a')
    c = Circuit([Moment([cirq.X(qa)**0.4921875])])
    diagram = c.to_text_diagram(use_unicode_characters=False, precision=None)
    assert diagram.strip() == """
a: ---X^0.4921875---
    """.strip()
示例#11
0
 def optimize_circuit(self, circuit: _circuit.Circuit) -> None:
     deletions = []  # type: List[Tuple[int, ops.Operation]]
     for moment_index, moment in enumerate(circuit):
         for op in moment.operations:
             bounded = self.extensions.try_cast(ops.BoundedEffect, op)
             if (bounded is not None
                     and bounded.trace_distance_bound() <= self.tolerance):
                 deletions.append((moment_index, op))
     circuit.batch_remove(deletions)
示例#12
0
 def optimize_circuit(self, circuit: _circuit.Circuit) -> None:
     deletions = []  # type: List[Tuple[int, ops.Operation]]
     for moment_index, moment in enumerate(circuit):
         for op in moment.operations:
             bounded = self.extensions.try_cast(ops.BoundedEffect, op)
             if (bounded is not None and
                     bounded.trace_distance_bound() <= self.tolerance):
                 deletions.append((moment_index, op))
     circuit.batch_remove(deletions)
示例#13
0
def test_concatenate():
    a = cirq.QubitId()
    b = cirq.QubitId()

    c = Circuit()
    d = Circuit([Moment([cirq.X(b)])])
    e = Circuit([Moment([cirq.X(a), cirq.X(b)])])

    assert c + d == Circuit([Moment([cirq.X(b)])])
    assert d + c == Circuit([Moment([cirq.X(b)])])
    assert e + d == Circuit(
        [Moment([cirq.X(a), cirq.X(b)]),
         Moment([cirq.X(b)])])

    d += c
    assert d == Circuit([Moment([cirq.X(b)])])

    c += d
    assert c == Circuit([Moment([cirq.X(b)])])

    f = e + d
    f += e
    assert f == Circuit([
        Moment([cirq.X(a), cirq.X(b)]),
        Moment([cirq.X(b)]),
        Moment([cirq.X(a), cirq.X(b)])
    ])

    with pytest.raises(TypeError):
        _ = c + 'a'
    with pytest.raises(TypeError):
        c += 'a'
示例#14
0
def test_multiply():
    a = cirq.QubitId()

    c = Circuit()
    d = Circuit([Moment([cirq.X(a)])])

    assert c * 0 == Circuit()
    assert d * 0 == Circuit()
    assert d * 2 == Circuit([Moment([cirq.X(a)]), Moment([cirq.X(a)])])
    assert 1 * c == Circuit()
    assert -1 * d == Circuit()
    assert 1 * d == Circuit([Moment([cirq.X(a)])])

    d *= 3
    assert d == Circuit(
        [Moment([cirq.X(a)]),
         Moment([cirq.X(a)]),
         Moment([cirq.X(a)])])

    with pytest.raises(TypeError):
        _ = c * 'a'
    with pytest.raises(TypeError):
        _ = 'a' * c
    with pytest.raises(TypeError):
        c *= 'a'
示例#15
0
def test_to_text_diagram_extended_gate():
    q = cirq.NamedQubit('(0, 0)')
    q2 = cirq.NamedQubit('(0, 1)')
    q3 = cirq.NamedQubit('(0, 2)')

    class FGate(cirq.Gate):
        def __repr__(self):
            return 'python-object-FGate:arbitrary-digits'

    f = FGate()
    c = Circuit([
        Moment([f.on(q)]),
    ])

    # Fallback to repr without extension.
    diagram = Circuit([
        Moment([f.on(q)]),
    ]).to_text_diagram(use_unicode_characters=False)
    assert diagram.strip() == """
(0, 0): ---python-object-FGate:arbitrary-digits---
        """.strip()

    # When used on multiple qubits, show the qubit order as a digit suffix.
    diagram = Circuit([
        Moment([f.on(q, q3, q2)]),
    ]).to_text_diagram(use_unicode_characters=False)
    assert diagram.strip() == """
(0, 0): ---python-object-FGate:arbitrary-digits:0---
           |
(0, 1): ---python-object-FGate:arbitrary-digits:2---
           |
(0, 2): ---python-object-FGate:arbitrary-digits:1---
            """.strip()

    # Succeeds with extension.
    class FGateAsText(cirq.TextDiagrammableGate):
        def __init__(self, f_gate):
            self.f_gate = f_gate

        def text_diagram_wire_symbols(self,
                                      qubit_count=None,
                                      use_unicode_characters=True,
                                      precision=3):
            return 'F'

    diagram = c.to_text_diagram(Extensions(
        {cirq.TextDiagrammableGate: {
            FGate: FGateAsText
        }}),
                                use_unicode_characters=False)

    assert diagram.strip() == """
(0, 0): ---F---
        """.strip()
def _scan_single_qubit_ops(
        circuit: Circuit, index: Optional[int],
        qubit: ops.QubitId) -> Tuple[List[int], List[ops.Operation]]:
    operations = []  # type: List[ops.Operation]
    indices = []  # type: List[int]
    while index is not None:
        op = cast(ops.Operation, circuit.operation_at(qubit, index))
        if len(op.qubits) != 1 or protocols.unitary(op, None) is None:
            break
        indices.append(index)
        operations.append(op)
        index = circuit.next_moment_operating_on([qubit], index + 1)
    return indices, operations
示例#17
0
def test_to_text_diagram_many_qubits_gate_but_multiple_wire_symbols():
    class BadGate(cirq.TextDiagrammableGate):
        def text_diagram_wire_symbols(self,
                                      qubit_count=None,
                                      use_unicode_characters=True,
                                      precision=3):
            return 'a', 'a'

    q1 = cirq.NamedQubit('(0, 0)')
    q2 = cirq.NamedQubit('(0, 1)')
    q3 = cirq.NamedQubit('(0, 2)')
    c = Circuit([Moment([BadGate().on(q1, q2, q3)])])
    with pytest.raises(ValueError, match='BadGate'):
        c.to_text_diagram()
示例#18
0
    def _scan_two_qubit_ops_into_matrix(
            self,
            circuit: Circuit,
            index: Optional[int],
            qubits: Tuple[ops.QubitId, ...]
    ) -> Tuple[List[ops.Operation], List[int], np.ndarray]:
        """Accumulates operations affecting the given pair of qubits.

        The scan terminates when it hits the end of the circuit, finds an
        operation without a known matrix, or finds an operation that interacts
        the given qubits with other qubits.

        Args:
            circuit: The circuit to scan for operations.
            index: The index to start scanning forward from.
            qubits: The pair of qubits we care about.

        Returns:
            A tuple containing:
                0. The operations.
                1. The moment indices those operations were on.
                2. A matrix equivalent to the effect of the scanned operations.
        """

        product = np.eye(4, dtype=np.complex128)
        all_operations = []
        touched_indices = []

        while index is not None:
            operations = list({circuit.operation_at(q, index) for q in qubits})
            op_data = [
                self._op_to_matrix(op, qubits)
                for op in operations
                if op is not None
            ]

            # Stop at any non-constant or non-local interaction.
            if any(e is None for e in op_data):
                break
            present_ops = [op for op in operations if op]
            present_op_data = cast(List[np.ndarray], op_data)

            for op_mat in present_op_data:
                product = np.dot(op_mat, product)
            all_operations.extend(present_ops)

            touched_indices.append(index)
            index = circuit.next_moment_operating_on(qubits, index + 1)

        return all_operations, touched_indices, product
示例#19
0
def test_iter_ops():
    a = cirq.NamedQubit('a')
    b = cirq.NamedQubit('b')
    c = Circuit([
        Moment([]),
        Moment([cirq.X(a), cirq.Y(b)]),
        Moment([]),
        Moment([cirq.CNOT(a, b)]),
        Moment([cirq.Z(b), cirq.H(a)]),  # Different qubit order
        Moment([])
    ])

    expected = [cirq.X(a), cirq.Y(b), cirq.CNOT(a, b), cirq.Z(b), cirq.H(a)]

    assert list(c.iter_ops()) == expected
示例#20
0
def test_to_text_diagram_custom_order():
    qa = cirq.NamedQubit('2')
    qb = cirq.NamedQubit('3')
    qc = cirq.NamedQubit('4')

    c = Circuit([Moment([cirq.X(qa), cirq.X(qb), cirq.X(qc)])])
    diagram = c.to_text_diagram(
        qubit_order=cirq.QubitOrder.sorted_by(lambda e: int(str(e)) % 3),
        use_unicode_characters=False)
    assert diagram.strip() == """
3: ---X---

4: ---X---

2: ---X---
    """.strip()
示例#21
0
def _final_clifford_tableau(
        circuit: Circuit,
        qubit_map) -> Optional[clifford_tableau.CliffordTableau]:
    """Evolves a default CliffordTableau through the input circuit.

    Initializes a CliffordTableau with default args for the given qubits and
    evolves it by having each operation act on the tableau.

    Args:
        circuit: An input circuit that acts on the zero state
        qubit_map: A map from qid to the qubit index for the above circuit

    Returns:
        None if any of the operations can not act on a CliffordTableau, returns
        the tableau otherwise."""

    tableau = clifford_tableau.CliffordTableau(len(qubit_map))
    args = clifford_tableau_simulation_state.CliffordTableauSimulationState(
        tableau=tableau,
        qubits=list(qubit_map.keys()),
        prng=np.random.RandomState())
    for op in circuit.all_operations():
        try:
            protocols.act_on(op, args, allow_decompose=True)
        except TypeError:
            return None
    return tableau
示例#22
0
def test_to_text_diagram_multi_qubit_gate():
    q1 = cirq.NamedQubit('(0, 0)')
    q2 = cirq.NamedQubit('(0, 1)')
    q3 = cirq.NamedQubit('(0, 2)')
    c = Circuit.from_ops(cirq.measure(q1, q2, q3, key='msg'))
    assert c.to_text_diagram().strip() == """
(0, 0): ───M───
           │
(0, 1): ───M───
           │
(0, 2): ───M───
    """.strip()
    assert c.to_text_diagram(use_unicode_characters=False).strip() == """
(0, 0): ---M---
           |
(0, 1): ---M---
           |
(0, 2): ---M---
    """.strip()
    assert c.to_text_diagram(transpose=True).strip() == """
(0, 0) (0, 1) (0, 2)
│      │      │
M──────M──────M
│      │      │
    """.strip()
示例#23
0
def _final_stabilizer_state_ch_form(
        circuit: Circuit,
        qubit_map) -> Optional[stabilizer_state_ch_form.StabilizerStateChForm]:
    """Evolves a default StabilizerStateChForm through the input circuit.

    Initializes a StabilizerStateChForm with default args for the given qubits
    and evolves it by having each operation act on the state.

    Args:
        circuit: An input circuit that acts on the zero state
        qubit_map: A map from qid to the qubit index for the above circuit

    Returns:
        None if any of the operations can not act on a StabilizerStateChForm,
        returns the StabilizerStateChForm otherwise."""

    stabilizer_ch_form = stabilizer_state_ch_form.StabilizerStateChForm(
        len(qubit_map))
    args = stabilizer_ch_form_simulation_state.StabilizerChFormSimulationState(
        qubits=list(qubit_map.keys()),
        prng=np.random.RandomState(),
        initial_state=stabilizer_ch_form,
    )
    for op in circuit.all_operations():
        try:
            protocols.act_on(op, args, allow_decompose=True)
        except TypeError:
            return None
    return stabilizer_ch_form
示例#24
0
def _final_stabilizer_state_ch_form(
        circuit: Circuit,
        qubit_map) -> Optional[stabilizer_state_ch_form.StabilizerStateChForm]:
    """Evolves a default StabilizerStateChForm through the input circuit.

    Initializes a StabilizerStateChForm with default args for the given qubits
    and evolves it by having each operation act on the state.

    Args:
        circuit: An input circuit that acts on the zero state
        qubit_map: A map from qid to the qubit index for the above circuit

    Returns:
        None if any of the operations can not act on a StabilizerStateChForm,
        returns the StabilizerStateChForm otherwise."""

    stabilizer_ch_form = stabilizer_state_ch_form.StabilizerStateChForm(
        len(qubit_map))
    for op in circuit.all_operations():
        try:
            args = act_on_stabilizer_ch_form_args.ActOnStabilizerCHFormArgs(
                state=stabilizer_ch_form,
                axes=[qubit_map[qid] for qid in op.qubits],
                prng=np.random.RandomState(),
                log_of_measurement_results={},
            )
            protocols.act_on(op, args, allow_decompose=True)
        except TypeError:
            return None
    return stabilizer_ch_form
示例#25
0
def test_text_diagram_jupyter():
    a = cirq.NamedQubit('a')
    b = cirq.NamedQubit('b')
    c = cirq.NamedQubit('c')
    circuit = Circuit.from_ops(
        (cirq.CNOT(a, b), cirq.CNOT(b, c), cirq.CNOT(c, a)) * 50)
    text_expected = circuit.to_text_diagram()

    # Test Jupyter console output from
    class FakePrinter:
        def __init__(self):
            self.text_pretty = ''

        def text(self, to_print):
            self.text_pretty += to_print

    p = FakePrinter()
    circuit._repr_pretty_(p, False)
    assert p.text_pretty == text_expected

    # Test cycle handling
    p = FakePrinter()
    circuit._repr_pretty_(p, True)
    assert p.text_pretty == 'Circuit(...)'

    # Test Jupyter notebook html output
    text_html = circuit._repr_html_()
    # Don't enforce specific html surrounding the diagram content
    assert text_expected in text_html
示例#26
0
    def transform_job(self, job):
        """Creates a new job object with depolarizing channel.

        This job will contain the existing Job's circuit with an error gate per
        qubit at every moment.  Creates the parameter sweep for each gate and
        populates with random values as per the specifications of the
        depolarizer channel.

        Args:
            job: Job object to transform

        Returns:
            A new Job object that contains a circuit with up to double the
            moments as the original job, with every other moment being a
            moment containing error gates.  It will also contain a Sweep
            containing values for each error gate.  Note that moments that
            contain no error gates for any repetition will be automatically
            omitted.
        """
        # A set for quick lookup of pre-existing qubits
        qubit_set = set()
        # A list with deterministic qubit order
        qubit_list = []
        circuit = job.circuit

        # Retrieve the set of qubits used in the circuit
        for moment in circuit:
            for op in moment.operations:
                for qubit in op.qubits:
                    if qubit not in qubit_set:
                        qubit_set.add(qubit)
                        qubit_list.append(qubit)

        # Add error circuits
        moments = []
        error_number = 0
        error_sweep = Zip()

        for moment in circuit:
            moments.append(moment)

            for gate in self.depolarizing_gates:
                error_gates = []
                for q in qubit_list:
                    errors = np.random.random(self.realizations) < self.p
                    if any(errors):
                        key = self._parameter_name + str(error_number)
                        new_error_gate = gate**Symbol(key)
                        error_gates.append(new_error_gate.on(q))
                        error_sweep += Points(key, list(errors * 1.0))
                        error_number += 1

                if error_gates:
                    moments.append(ops.Moment(error_gates))

        sweep = job.sweep
        if error_sweep:
            sweep *= error_sweep

        return Job(Circuit(moments), sweep, job.repetitions)
示例#27
0
def _final_clifford_tableau(
        circuit: Circuit,
        qubit_map) -> Optional[clifford_tableau.CliffordTableau]:
    """Evolves a default CliffordTableau through the input circuit.

    Initializes a CliffordTableau with default args for the given qubits and
    evolves it by having each operation act on the tableau.

    Args:
        circuit: An input circuit that acts on the zero state
        qubit_map: A map from qid to the qubit index for the above circuit

    Returns:
        None if any of the operations can not act on a CliffordTableau, returns
        the tableau otherwise."""

    tableau = clifford_tableau.CliffordTableau(len(qubit_map))
    for op in circuit.all_operations():
        try:
            args = act_on_clifford_tableau_args.ActOnCliffordTableauArgs(
                tableau=tableau,
                axes=[qubit_map[qid] for qid in op.qubits],  # type: ignore
                prng=np.random.RandomState(),
                log_of_measurement_results={},
            )
            protocols.act_on(op, args, allow_decompose=True)
        except TypeError:
            return None
    return tableau
示例#28
0
 def _scan_single_qubit_ops(
         self, circuit: Circuit, index: Optional[int],
         qubit: ops.QubitId) -> Tuple[List[int], List[ops.KnownMatrix]]:
     operations = []  # type: List[ops.KnownMatrix]
     indices = []  # type: List[int]
     while index is not None:
         op = cast(ops.Operation, circuit.operation_at(qubit, index))
         if len(op.qubits) != 1:
             break
         operation = self.extensions.try_cast(ops.KnownMatrix, op)
         if operation is None:
             break
         indices.append(index)
         operations.append(operation)
         index = circuit.next_moment_operating_on([qubit], index + 1)
     return indices, operations
示例#29
0
def test_from_ops():
    a = cirq.QubitId()
    b = cirq.QubitId()

    actual = Circuit.from_ops(
        cirq.X(a),
        [cirq.Y(a), cirq.Z(b)],
        cirq.CZ(a, b),
        cirq.X(a),
        [cirq.Z(b), cirq.Y(a)],
    )

    assert actual == Circuit([
        Moment([cirq.X(a)]),
        Moment([cirq.Y(a), cirq.Z(b)]),
        Moment([cirq.CZ(a, b)]),
        Moment([cirq.X(a), cirq.Z(b)]),
        Moment([cirq.Y(a)]),
    ])
示例#30
0
    def optimize_circuit(self, circuit: Circuit):
        frontier: Dict['Qid', int] = defaultdict(lambda: 0)
        i = 0
        while i < len(circuit):  # Note: circuit may mutate as we go.
            for op in circuit[i].operations:
                # Don't touch stuff inserted by previous optimizations.
                if any(frontier[q] > i for q in op.qubits):
                    continue

                # Skip if an optimization removed the circuit underneath us.
                if i >= len(circuit):
                    continue
                # Skip if an optimization removed the op we're considering.
                if op not in circuit[i].operations:
                    continue
                opt = self.optimization_at(circuit, i, op)
                # Skip if the optimization did nothing.
                if opt is None:
                    continue

                # Clear target area, and insert new operations.
                circuit.clear_operations_touching(
                    opt.clear_qubits,
                    [e for e in range(i, i + opt.clear_span)])
                new_operations = self.post_clean_up(
                    cast(Tuple[ops.Operation], opt.new_operations))

                flat_new_operations = tuple(ops.flatten_to_ops(new_operations))

                new_qubits = set()
                for flat_op in flat_new_operations:
                    for q in flat_op.qubits:
                        new_qubits.add(q)

                if not new_qubits.issubset(set(opt.clear_qubits)):
                    raise ValueError(
                        'New operations in PointOptimizer should not act on new qubits.'
                    )

                circuit.insert_at_frontier(flat_new_operations, i, frontier)
            i += 1
示例#31
0
    def optimize_circuit(self, circuit: Circuit):
        moment_new_ops = defaultdict(
            list)  # type: Dict[int, List['cirq.Operation']]
        circuit_len = len(circuit)
        for i in range(circuit_len):
            moment_new_ops[i] = []
            for op in circuit[i].operations:
                opt = self.optimization_at(circuit, i, op)
                if opt is None:
                    # keep the old operation if the optimization did nothing.
                    moment_new_ops[i].append(op)
                    circuit.clear_operations_touching(op.qubits, [i])
                else:
                    # Clear target area, and insert new operations.
                    circuit.clear_operations_touching(
                        opt.clear_qubits,
                        [e for e in range(i, i + opt.clear_span)])
                    new_operations = self.post_clean_up(
                        cast(Tuple[ops.Operation], opt.new_operations))

                    flat_new_operations = tuple(
                        ops.flatten_to_ops(new_operations))

                    new_qubits = set()
                    for flat_op in flat_new_operations:
                        for q in flat_op.qubits:
                            new_qubits.add(q)

                    if not new_qubits.issubset(set(opt.clear_qubits)):
                        raise ValueError(
                            'New operations in PointOptimizer should not act on new'
                            ' qubits.')
                    moment_new_ops[i].extend(flat_new_operations)
        frontier = 0
        for i in range(circuit_len):
            new_frontier = circuit.insert(frontier, moment_new_ops[i],
                                          InsertStrategy.EARLIEST_AFTER)
            if frontier < new_frontier:
                frontier = new_frontier
示例#32
0
def test_composite_gate_to_unitary_matrix():
    class CNOT_composite(cirq.CompositeGate):
        def default_decompose(self, qubits):
            q0, q1 = qubits
            return cirq.Y(q1)**-0.5, cirq.CZ(q0, q1), cirq.Y(q1)**0.5

    a = cirq.NamedQubit('a')
    b = cirq.NamedQubit('b')
    c = Circuit.from_ops(cirq.X(a),
                         CNOT_composite()(a, b), cirq.X(a), cirq.measure(a),
                         cirq.X(b), cirq.measure(b))
    mat = c.to_unitary_matrix()
    mat_expected = cirq.CNOT.matrix()

    cirq.testing.assert_allclose_up_to_global_phase(mat, mat_expected)