Esempio n. 1
0
def assert_optimizes(
    before: cirq.Circuit,
    expected: cirq.Circuit,
    compare_unitaries: bool = True,
    eject_parameterized: bool = False,
    *,
    with_context: bool = False,
):
    context = cirq.TransformerContext(tags_to_ignore=("nocompile",)) if with_context else None
    circuit = cirq.eject_phased_paulis(
        before, eject_parameterized=eject_parameterized, context=context
    )

    # They should have equivalent effects.
    if compare_unitaries:
        if cirq.is_parameterized(circuit):
            for a in (0, 0.1, 0.5, -1.0, np.pi, np.pi / 2):
                params = {'x': a, 'y': a / 2, 'z': -2 * a}
                (
                    cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent(
                        cirq.resolve_parameters(circuit, params),
                        cirq.resolve_parameters(expected, params),
                        1e-8,
                    )
                )
        else:
            (
                cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent(
                    circuit, expected, 1e-8
                )
            )

    # And match the expected circuit.
    assert circuit == expected, (
        "Circuit wasn't optimized as expected.\n"
        "INPUT:\n"
        "{}\n"
        "\n"
        "EXPECTED OUTPUT:\n"
        "{}\n"
        "\n"
        "ACTUAL OUTPUT:\n"
        "{}\n"
        "\n"
        "EXPECTED OUTPUT (detailed):\n"
        "{!r}\n"
        "\n"
        "ACTUAL OUTPUT (detailed):\n"
        "{!r}"
    ).format(before, expected, circuit, expected, circuit)

    # And it should be idempotent.
    circuit = cirq.eject_phased_paulis(
        circuit, eject_parameterized=eject_parameterized, context=context
    )
    assert circuit == expected
Esempio n. 2
0
def optimized_for_sycamore(
    circuit: cirq.Circuit,
    *,
    qubit_map: Callable[[cirq.Qid], cirq.GridQubit] = lambda e: cast(cirq.GridQubit, e),
    optimizer_type: str = 'sqrt_iswap',
    tolerance: float = 1e-5,
    tabulation_resolution: Optional[float] = None,
) -> cirq.Circuit:
    """Optimizes a circuit for Google devices.

    Uses a set of optimizers that will compile to the proper gateset for the
    device (xmon, sqrt_iswap, or sycamore gates) and then use optimizers to
    compress the gate depth down as much as is easily algorithmically possible
    by merging rotations, ejecting Z gates, etc.

    Args:
        circuit: The circuit to optimize.
        qubit_map: Transforms the qubits (e.g. so that they are GridQubits).
        optimizer_type: A string defining the optimizations to apply.
            Possible values are  'xmon', 'xmon_partial_cz', 'sqrt_iswap',
            'sycamore'
        tolerance: The tolerance passed to the various circuit optimization
            passes.
        tabulation_resolution: If provided, compute a gateset tabulation
            with the specified resolution and use it to approximately
            compile arbitrary two-qubit gates for which an analytic compilation
            is not known.
    Returns:
        The optimized circuit.

    Raises:
        ValueError: If the `optimizer_type` is not a supported type.
    """
    copy = circuit.copy()
    if optimizer_type not in _TARGET_GATESETS:
        raise ValueError(
            f'{optimizer_type} is not an allowed type.  Allowed '
            f'types are: {_TARGET_GATESETS.keys()}'
        )

    tabulation: Optional[cirq.TwoQubitGateTabulation] = None
    if tabulation_resolution is not None:
        tabulation = _gate_product_tabulation_cached(optimizer_type, tabulation_resolution)

    if optimizer_type in _TARGET_GATESETS:
        copy = cirq.optimize_for_target_gateset(
            circuit,
            gateset=_TARGET_GATESETS[optimizer_type](tolerance, tabulation),
            context=cirq.TransformerContext(deep=True),
        )
    copy = cirq.merge_single_qubit_gates_to_phxz(copy, atol=tolerance)
    copy = cirq.eject_phased_paulis(copy, atol=tolerance)
    copy = cirq.eject_z(copy, atol=tolerance)
    copy = cirq.drop_negligible_operations(copy, atol=tolerance)

    ret = cirq.Circuit(
        (op.transform_qubits(qubit_map) for op in copy.all_operations()),
        strategy=cirq.InsertStrategy.EARLIEST,
    )
    return ret
Esempio n. 3
0
def test_eject_phased_xz():
    a = cirq.NamedQubit('a')
    b = cirq.NamedQubit('b')
    c = cirq.Circuit(
        cirq.PhasedXZGate(x_exponent=1, z_exponent=0.5, axis_phase_exponent=0.5).on(a),
        cirq.CZ(a, b) ** 0.25,
    )
    c_expected = cirq.Circuit(
        cirq.CZ(a, b) ** -0.25, cirq.PhasedXPowGate(phase_exponent=0.75).on(a), cirq.T(b)
    )
    cirq.testing.assert_same_circuits(
        cirq.eject_z(cirq.eject_phased_paulis(cirq.eject_z(c))), c_expected
    )
    cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent(c, c_expected, 1e-8)
def assert_optimizes(
    before: cirq.Circuit,
    expected: cirq.Circuit,
    compare_unitaries: bool = True,
    eject_parameterized: bool = False,
    *,
    with_context: bool = False,
):
    context = cirq.TransformerContext(
        tags_to_ignore=("nocompile", )) if with_context else None
    circuit = cirq.eject_phased_paulis(before,
                                       eject_parameterized=eject_parameterized,
                                       context=context)

    # They should have equivalent effects.
    if compare_unitaries:
        if cirq.is_parameterized(circuit):
            for a in (0, 0.1, 0.5, -1.0, np.pi, np.pi / 2):
                params: cirq.ParamDictType = {'x': a, 'y': a / 2, 'z': -2 * a}
                (cirq.testing.
                 assert_circuits_with_terminal_measurements_are_equivalent(
                     cirq.resolve_parameters(circuit, params),
                     cirq.resolve_parameters(expected, params),
                     1e-8,
                 ))
        else:
            (cirq.testing.
             assert_circuits_with_terminal_measurements_are_equivalent(
                 circuit, expected, 1e-8))

    # And match the expected circuit.
    cirq.testing.assert_same_circuits(circuit, expected)

    # And it should be idempotent.
    circuit = cirq.eject_phased_paulis(circuit,
                                       eject_parameterized=eject_parameterized,
                                       context=context)
    cirq.testing.assert_same_circuits(circuit, expected)

    # Nested sub-circuits should also get optimized.
    q = before.all_qubits()
    c_nested = cirq.Circuit(
        [
            cirq.PhasedXPowGate(phase_exponent=0.5).on_each(*q),
            (cirq.Z**0.5).on_each(*q)
        ],
        cirq.CircuitOperation(before.freeze()).repeat(2).with_tags("ignore"),
        [cirq.Y.on_each(*q), cirq.X.on_each(*q)],
        cirq.CircuitOperation(
            before.freeze()).repeat(3).with_tags("preserve_tag"),
    )
    c_expected = cirq.Circuit(
        cirq.PhasedXPowGate(phase_exponent=0.75).on_each(*q),
        cirq.Moment(
            cirq.CircuitOperation(
                before.freeze()).repeat(2).with_tags("ignore")),
        cirq.Z.on_each(*q),
        cirq.Moment(
            cirq.CircuitOperation(
                expected.freeze()).repeat(3).with_tags("preserve_tag")),
    )
    if context is None:
        context = cirq.TransformerContext(tags_to_ignore=("ignore", ),
                                          deep=True)
    else:
        context = dataclasses.replace(context,
                                      tags_to_ignore=context.tags_to_ignore +
                                      ("ignore", ),
                                      deep=True)
    c_nested = cirq.eject_phased_paulis(
        c_nested, context=context, eject_parameterized=eject_parameterized)
    cirq.testing.assert_same_circuits(c_nested, c_expected)
    c_nested = cirq.eject_phased_paulis(
        c_nested, context=context, eject_parameterized=eject_parameterized)
    cirq.testing.assert_same_circuits(c_nested, c_expected)