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
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
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)