def test_convert_to_sycamore_gates_fsim(): q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit( cirq.FSimGate(theta=np.pi / 2, phi=np.pi / 6)(q0, q1)) compiled_circuit = cirq.optimize_for_target_gateset( circuit, gateset=cirq_google.SycamoreTargetGateset()) cirq.testing.assert_same_circuits(circuit, compiled_circuit)
def test_sycamore_gateset_compiles_swap_zz(): qubits = cirq.LineQubit.range(3) gamma = np.random.randn() circuit1 = cirq.Circuit( cirq.SWAP(qubits[0], qubits[1]), cirq.Z(qubits[2]), cirq.ZZ(qubits[0], qubits[1])**gamma, strategy=cirq.InsertStrategy.NEW, ) circuit2 = cirq.Circuit( cirq.ZZ(qubits[0], qubits[1])**gamma, cirq.Z(qubits[2]), cirq.SWAP(qubits[0], qubits[1]), strategy=cirq.InsertStrategy.NEW, ) gateset = cirq_google.SycamoreTargetGateset() compiled_circuit1 = cirq.optimize_for_target_gateset(circuit1, gateset=gateset) compiled_circuit2 = cirq.optimize_for_target_gateset(circuit2, gateset=gateset) cirq.testing.assert_same_circuits(compiled_circuit1, compiled_circuit2) assert (len( list( compiled_circuit1.findall_operations_with_gate_type( cirq_google.SycamoreGate))) == 3) cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent( circuit1, compiled_circuit1, atol=1e-7)
def test_convert_to_sycamore_equivalent_unitaries(gate): circuit = cirq.Circuit(gate.on(*cirq.LineQubit.range(2))) converted_circuit = cirq.optimize_for_target_gateset( circuit, gateset=cirq_google.SycamoreTargetGateset() ) cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent( circuit, converted_circuit, atol=1e-8 )
def test_grid_device_from_proto(): grid_qubits, spec = _create_device_spec_with_horizontal_couplings() device = cirq_google.GridDevice.from_proto(spec) assert len(device.metadata.qubit_set) == len(grid_qubits) assert device.metadata.qubit_set == frozenset(grid_qubits) assert all( frozenset((cirq.GridQubit(row, 0), cirq.GridQubit(row, 1))) in device.metadata.qubit_pairs for row in range(GRID_HEIGHT) ) assert device.metadata.gateset == cirq.Gateset( cirq_google.FSimGateFamily(gates_to_accept=[cirq_google.SYC]), cirq_google.FSimGateFamily(gates_to_accept=[cirq.SQRT_ISWAP]), cirq_google.FSimGateFamily(gates_to_accept=[cirq.SQRT_ISWAP_INV]), cirq_google.FSimGateFamily(gates_to_accept=[cirq.CZ]), cirq.ops.phased_x_z_gate.PhasedXZGate, cirq.ops.common_gates.XPowGate, cirq.ops.common_gates.YPowGate, cirq.ops.phased_x_gate.PhasedXPowGate, cirq.GateFamily( cirq.ops.common_gates.ZPowGate, tags_to_ignore=[cirq_google.PhysicalZTag()] ), cirq.GateFamily( cirq.ops.common_gates.ZPowGate, tags_to_accept=[cirq_google.PhysicalZTag()] ), cirq_google.experimental.ops.coupler_pulse.CouplerPulse, cirq.ops.measurement_gate.MeasurementGate, cirq.ops.wait_gate.WaitGate, ) assert tuple(device.metadata.compilation_target_gatesets) == ( cirq.CZTargetGateset(), cirq_google.SycamoreTargetGateset(), cirq.SqrtIswapTargetGateset(use_sqrt_iswap_inv=True), ) base_duration = cirq.Duration(picos=1_000) assert device.metadata.gate_durations == { cirq_google.FSimGateFamily(gates_to_accept=[cirq_google.SYC]): base_duration * 0, cirq_google.FSimGateFamily(gates_to_accept=[cirq.SQRT_ISWAP]): base_duration * 1, cirq_google.FSimGateFamily(gates_to_accept=[cirq.SQRT_ISWAP_INV]): base_duration * 2, cirq_google.FSimGateFamily(gates_to_accept=[cirq.CZ]): base_duration * 3, cirq.GateFamily(cirq.ops.phased_x_z_gate.PhasedXZGate): base_duration * 4, cirq.GateFamily(cirq.ops.common_gates.XPowGate): base_duration * 4, cirq.GateFamily(cirq.ops.common_gates.YPowGate): base_duration * 4, cirq.GateFamily(cirq.ops.phased_x_gate.PhasedXPowGate): base_duration * 4, cirq.GateFamily( cirq.ops.common_gates.ZPowGate, tags_to_ignore=[cirq_google.PhysicalZTag()] ): base_duration * 5, cirq.GateFamily( cirq.ops.common_gates.ZPowGate, tags_to_accept=[cirq_google.PhysicalZTag()] ): base_duration * 6, cirq.GateFamily(cirq_google.experimental.ops.coupler_pulse.CouplerPulse): base_duration * 7, cirq.GateFamily(cirq.ops.measurement_gate.MeasurementGate): base_duration * 8, cirq.GateFamily(cirq.ops.wait_gate.WaitGate): base_duration * 9, }
def test_zztheta_zzpow_unsorted_qubits(): qubits = cirq.LineQubit(1), cirq.LineQubit(0) exponent = 0.06366197723675814 circuit = cirq.Circuit( cirq.ZZPowGate(exponent=exponent, global_shift=-0.5).on(qubits[0], qubits[1]), ) converted_circuit = cirq.optimize_for_target_gateset( circuit, gateset=cirq_google.SycamoreTargetGateset()) cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent( circuit, converted_circuit, atol=1e-8)
def test_supported_operation(op): circuit = cirq.Circuit(op) converted_circuit = cirq.optimize_for_target_gateset( circuit, gateset=cirq_google.SycamoreTargetGateset() ) cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent( circuit, converted_circuit, atol=1e-8 ) multi_qubit_ops = [e for e in converted_circuit.all_operations() if len(e.qubits) > 1] assert all(isinstance(e.gate, cirq_google.SycamoreGate) for e in multi_qubit_ops)
def test_unsupported_gate(): class UnknownGate(cirq.testing.TwoQubitGate): pass q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit(UnknownGate()(q0, q1)) with pytest.raises(ValueError, match='Unable to convert'): cirq.optimize_for_target_gateset( circuit, gateset=cirq_google.SycamoreTargetGateset(), ignore_failures=False )
def test_single_qubit_gate_phased_xz(): q = cirq.LineQubit(0) gate = cirq.PhasedXZGate(axis_phase_exponent=0.2, x_exponent=0.3, z_exponent=0.4) circuit = cirq.Circuit(gate(q)) compiled_circuit = cirq.optimize_for_target_gateset( circuit, gateset=cirq_google.SycamoreTargetGateset() ) ops = list(compiled_circuit.all_operations()) assert len(ops) == 1 assert ops[0].gate == gate
def test_swap_zztheta(): qubits = cirq.LineQubit.range(2) a, b = qubits for theta in np.linspace(0, 2 * np.pi, 10): circuit = cirq.Circuit( cirq.SWAP(a, b), cirq.ZZPowGate(exponent=2 * theta / np.pi, global_shift=-0.5).on(a, b)) converted_circuit = cirq.optimize_for_target_gateset( circuit, gateset=cirq_google.SycamoreTargetGateset()) cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent( circuit, converted_circuit, atol=1e-8)
def test_single_qubit_gate(): q = cirq.LineQubit(0) mat = cirq.testing.random_unitary(2) gate = cirq.MatrixGate(mat, qid_shape=(2, )) circuit = cirq.Circuit(gate(q)) compiled_circuit = cirq.optimize_for_target_gateset( circuit, gateset=cirq_google.SycamoreTargetGateset()) ops = list(compiled_circuit.all_operations()) assert len(ops) == 1 assert isinstance(ops[0].gate, cirq.PhasedXZGate) cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent( circuit, compiled_circuit, atol=1e-8)
def test_zztheta_qaoa_like(): qubits = cirq.LineQubit.range(4) for exponent in np.linspace(-1, 1, 10): circuit = cirq.Circuit([ cirq.H.on_each(qubits), cirq.ZZPowGate(exponent=exponent)(qubits[0], qubits[1]), cirq.ZZPowGate(exponent=exponent)(qubits[2], qubits[3]), cirq.rx(0.123).on_each(qubits), ]) converted_circuit = cirq.optimize_for_target_gateset( circuit, gateset=cirq_google.SycamoreTargetGateset()) cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent( circuit, converted_circuit, atol=1e-8)
def test_convert_to_sycamore_tabulation(): # A tabulation for the sycamore gate with an infidelity of .1. sycamore_tabulation = cirq.two_qubit_gate_product_tabulation( cirq.unitary(cirq_google.SYC), 0.1, random_state=cirq.value.parse_random_state(11) ) circuit = cirq.Circuit(cirq.MatrixGate(cirq.unitary(cirq.CX)).on(*cirq.LineQubit.range(2))) converted_circuit = cirq.optimize_for_target_gateset( circuit, gateset=cirq_google.SycamoreTargetGateset(tabulation=sycamore_tabulation) ) u1 = cirq.unitary(circuit) u2 = cirq.unitary(converted_circuit) overlap = abs(np.trace(u1.conj().T @ u2)) assert np.isclose(overlap, 4.0, 0.1)
def test_known_two_q_operations_to_sycamore_operations_cnot(): a, b = cirq.LineQubit.range(2) circuit = cirq.Circuit(cirq.CNOT(a, b)) converted_circuit = cirq.optimize_for_target_gateset( circuit, gateset=cirq_google.SycamoreTargetGateset() ) # Should be equivalent. cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent( circuit, converted_circuit, atol=1e-8 ) # Should have decomposed into two Sycamores. multi_qubit_ops = [e for e in converted_circuit.all_operations() if len(e.qubits) > 1] assert len(multi_qubit_ops) == 2 assert all(isinstance(e.gate, cirq_google.SycamoreGate) for e in multi_qubit_ops)
def test_unsupported_gate_ignoring_failures(): class UnknownOperation(cirq.Operation): def __init__(self, qubits): self._qubits = qubits @property def qubits(self): return self._qubits def with_qubits(self, *new_qubits): # coverage: ignore return UnknownOperation(self._qubits) q0 = cirq.LineQubit(0) circuit = cirq.Circuit(UnknownOperation([q0])) converted_circuit = cirq.optimize_for_target_gateset( circuit, gateset=cirq_google.SycamoreTargetGateset()) assert circuit == converted_circuit
def _create_device_spec_with_horizontal_couplings(): # Qubit layout: # x -- x # x -- x # x -- x # x -- x # x -- x grid_qubits = [ cirq.GridQubit(i, j) for i in range(GRID_HEIGHT) for j in range(2) ] spec = v2.device_pb2.DeviceSpecification() spec.valid_qubits.extend([v2.qubit_to_proto_id(q) for q in grid_qubits]) qubit_pairs = [] grid_targets = spec.valid_targets.add() grid_targets.name = '2_qubit_targets' grid_targets.target_ordering = v2.device_pb2.TargetSet.SYMMETRIC for row in range(int(GRID_HEIGHT / 2)): qubit_pairs.append((cirq.GridQubit(row, 0), cirq.GridQubit(row, 1))) for row in range(int(GRID_HEIGHT / 2), GRID_HEIGHT): # Flip the qubit pair order for the second half of qubits # to verify GridDevice properly handles pair symmetry. qubit_pairs.append((cirq.GridQubit(row, 1), cirq.GridQubit(row, 0))) for pair in qubit_pairs: new_target = grid_targets.targets.add() new_target.ids.extend([v2.qubit_to_proto_id(q) for q in pair]) gate_names = [ 'syc', 'sqrt_iswap', 'sqrt_iswap_inv', 'cz', 'phased_xz', 'virtual_zpow', 'physical_zpow', 'coupler_pulse', 'meas', 'wait', ] gate_durations = [(n, i * 1000) for i, n in enumerate(gate_names)] for gate_name, duration in sorted(gate_durations): gate = spec.valid_gates.add() getattr(gate, gate_name).SetInParent() gate.gate_duration_picos = duration expected_gateset = cirq.Gateset( cirq_google.FSimGateFamily(gates_to_accept=[cirq_google.SYC]), cirq_google.FSimGateFamily(gates_to_accept=[cirq.SQRT_ISWAP]), cirq_google.FSimGateFamily(gates_to_accept=[cirq.SQRT_ISWAP_INV]), cirq_google.FSimGateFamily(gates_to_accept=[cirq.CZ]), cirq.ops.phased_x_z_gate.PhasedXZGate, cirq.ops.common_gates.XPowGate, cirq.ops.common_gates.YPowGate, cirq.ops.phased_x_gate.PhasedXPowGate, cirq.GateFamily(cirq.ops.common_gates.ZPowGate, tags_to_ignore=[cirq_google.PhysicalZTag()]), cirq.GateFamily(cirq.ops.common_gates.ZPowGate, tags_to_accept=[cirq_google.PhysicalZTag()]), cirq_google.experimental.ops.coupler_pulse.CouplerPulse, cirq.ops.measurement_gate.MeasurementGate, cirq.ops.wait_gate.WaitGate, ) base_duration = cirq.Duration(picos=1_000) expected_gate_durations = { cirq_google.FSimGateFamily(gates_to_accept=[cirq_google.SYC]): base_duration * 0, cirq_google.FSimGateFamily(gates_to_accept=[cirq.SQRT_ISWAP]): base_duration * 1, cirq_google.FSimGateFamily(gates_to_accept=[cirq.SQRT_ISWAP_INV]): base_duration * 2, cirq_google.FSimGateFamily(gates_to_accept=[cirq.CZ]): base_duration * 3, cirq.GateFamily(cirq.ops.phased_x_z_gate.PhasedXZGate): base_duration * 4, cirq.GateFamily(cirq.ops.common_gates.XPowGate): base_duration * 4, cirq.GateFamily(cirq.ops.common_gates.YPowGate): base_duration * 4, cirq.GateFamily(cirq.ops.phased_x_gate.PhasedXPowGate): base_duration * 4, cirq.GateFamily(cirq.ops.common_gates.ZPowGate, tags_to_ignore=[cirq_google.PhysicalZTag()]): base_duration * 5, cirq.GateFamily(cirq.ops.common_gates.ZPowGate, tags_to_accept=[cirq_google.PhysicalZTag()]): base_duration * 6, cirq.GateFamily(cirq_google.experimental.ops.coupler_pulse.CouplerPulse): base_duration * 7, cirq.GateFamily(cirq.ops.measurement_gate.MeasurementGate): base_duration * 8, cirq.GateFamily(cirq.ops.wait_gate.WaitGate): base_duration * 9, } expected_target_gatesets = ( cirq.CZTargetGateset(), cirq_google.SycamoreTargetGateset(), cirq.SqrtIswapTargetGateset(use_sqrt_iswap_inv=True), ) return ( _DeviceInfo( grid_qubits, qubit_pairs, expected_gateset, expected_gate_durations, expected_target_gatesets, ), spec, )
matrix_gate(q[0]).controlled_by(q[1]).with_tags('test_tags'), matrix_gate(q[0]).with_tags('test_tags').controlled_by(q[1]), ], ) def test_supported_operation(op): circuit = cirq.Circuit(op) converted_circuit = cirq.optimize_for_target_gateset( circuit, gateset=cirq_google.SycamoreTargetGateset() ) cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent( circuit, converted_circuit, atol=1e-8 ) multi_qubit_ops = [e for e in converted_circuit.all_operations() if len(e.qubits) > 1] assert all(isinstance(e.gate, cirq_google.SycamoreGate) for e in multi_qubit_ops) @pytest.mark.parametrize( 'gateset', [ cirq_google.SycamoreTargetGateset(), cirq_google.SycamoreTargetGateset( tabulation=cirq.two_qubit_gate_product_tabulation( cirq.unitary(cirq_google.SYC), 0.1, random_state=cirq.value.parse_random_state(11) ) ), ], ) def test_repr_json(gateset): assert eval(repr(gateset)) == gateset assert cirq.read_json(json_text=cirq.to_json(gateset)) == gateset