def test_rot_gates_eq(): eq = cirq.testing.EqualsTester() gates = [ lambda p: cirq.CZ**p, lambda p: cirq.X**p, lambda p: cirq.Y**p, lambda p: cirq.Z**p, lambda p: cirq.CNOT**p, ] for gate in gates: eq.add_equality_group(gate(3.5), gate(-0.5)) eq.make_equality_group(lambda: gate(0)) eq.make_equality_group(lambda: gate(0.5)) eq.add_equality_group(cirq.XPowGate(), cirq.XPowGate(exponent=1), cirq.X) eq.add_equality_group(cirq.YPowGate(), cirq.YPowGate(exponent=1), cirq.Y) eq.add_equality_group(cirq.ZPowGate(), cirq.ZPowGate(exponent=1), cirq.Z) eq.add_equality_group(cirq.ZPowGate(exponent=1, global_shift=-0.5), cirq.ZPowGate(exponent=5, global_shift=-0.5)) eq.add_equality_group(cirq.ZPowGate(exponent=3, global_shift=-0.5)) eq.add_equality_group(cirq.ZPowGate(exponent=1, global_shift=-0.1)) eq.add_equality_group(cirq.ZPowGate(exponent=5, global_shift=-0.1)) eq.add_equality_group(cirq.CNotPowGate(), cirq.CNotPowGate(exponent=1), cirq.CNOT) eq.add_equality_group(cirq.CZPowGate(), cirq.CZPowGate(exponent=1), cirq.CZ)
def test_is_pasqal_device_op(): d = generic_device(2) with pytest.raises(ValueError, match="Got unknown operation"): d.is_pasqal_device_op(cirq.NamedQubit('q0')) op = (cirq.ops.CZ).on(*(d.qubit_list())) bad_op = cirq.ops.CNotPowGate(exponent=0.5) assert d.is_pasqal_device_op(op) assert d.is_pasqal_device_op(cirq.ops.X(cirq.NamedQubit('q0'))) assert not d.is_pasqal_device_op( cirq.ops.CCX(cirq.NamedQubit('q0'), cirq.NamedQubit('q1'), cirq.NamedQubit('q2'))**0.2) assert not d.is_pasqal_device_op( bad_op(cirq.NamedQubit('q0'), cirq.NamedQubit('q1'))) for op1 in [ cirq.CNotPowGate(exponent=1.0), cirq.CNotPowGate(exponent=1.0, global_shift=-0.5) ]: assert d.is_pasqal_device_op( op1(cirq.NamedQubit('q0'), cirq.NamedQubit('q1'))) op2 = (cirq.ops.H**sympy.Symbol('exp')).on(d.qubit_list()[0]) assert not d.is_pasqal_device_op(op2) d2 = square_virtual_device(control_r=1.1, num_qubits=3) assert d.is_pasqal_device_op(cirq.ops.X(TwoDQubit(0, 0))) assert not d2.is_pasqal_device_op(op1(TwoDQubit(0, 0), TwoDQubit(0, 1)))
def controlled( self, num_controls: int = None, control_values: Optional[Sequence[Union[int, Collection[int]]]] = None, control_qid_shape: Optional[Tuple[int, ...]] = None) -> raw_types.Gate: """ Constructs CNotPowGate from controlled XPowGate when applicable. This method is a specialized controlled method for XPowGate. It overrides the default behavior of returning a ControlledGate by transforming the underlying controlled gate to a CNotPowGate and removing the last specified control qubit (which acts first semantically). If this is a gate with multiple control qubits, it will now be a ControlledGate with one less control. This behavior only occurs when the last control qubit is a default-type control qubit. A default-type control qubit is one with shape of 2 (not a generic qudit) and where the control is satisfied by the qubit being ON, as opposed to OFF. (Note that a CNotPowGate is, by definition, a controlled-XPowGate.) """ result = super().controlled(num_controls, control_values, control_qid_shape) if (isinstance(result, controlled_gate.ControlledGate) and result.control_values[-1] == (1, ) and result.control_qid_shape[-1] == 2): return cirq.CNotPowGate( exponent=self._exponent, global_shift=self._global_shift).controlled( result.num_controls() - 1, result.control_values[:-1], result.control_qid_shape[:-1]) return result
def test_validate_gate_errors(): d = square_device(1, 1) d.validate_gate(cirq.IdentityGate(4)) with pytest.raises(ValueError, match="controlled gates must have integer exponents"): d.validate_gate(cirq.CNotPowGate(exponent=0.5)) with pytest.raises(ValueError, match="Unsupported gate"): d.validate_gate(cirq.SingleQubitGate())
def get_default_noise_dict(self) -> Dict[str, Any]: """Returns the current noise parameters""" default_noise_dict = { str(cirq.YPowGate()): cirq.depolarize(1e-2), str(cirq.ZPowGate()): cirq.depolarize(1e-2), str(cirq.XPowGate()): cirq.depolarize(1e-2), str(cirq.PhasedXPowGate(phase_exponent=0)): cirq.depolarize(1e-2), str(cirq.HPowGate(exponent=1)): cirq.depolarize(1e-2), str(cirq.CNotPowGate(exponent=1)): cirq.depolarize(3e-2), str(cirq.CZPowGate(exponent=1)): cirq.depolarize(3e-2), str(cirq.CCXPowGate(exponent=1)): cirq.depolarize(8e-2), str(cirq.CCZPowGate(exponent=1)): cirq.depolarize(8e-2), } return default_noise_dict
def _decompose_(self, qubits): q = qubits π = np.pi θ, ϕ = self.params return [ cirq.ZPowGate(exponent=1 / 2 - ϕ / π).on(q[1]), cirq.X.on(q[0]), cirq.CNOT(q[0], q[1]), cirq.X.on(q[0]), cirq.CNotPowGate(exponent=2 * θ / π).on( q[1], q[0] ), # global_shift is needed to remove erronous complex numbers cirq.S.on(q[0]), cirq.ZPowGate(exponent=-θ / π).on(q[1]) ]
c_orig, gateset=cirq.SqrtIswapTargetGateset(use_sqrt_iswap_inv=True), ignore_failures=False ) cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent(c_orig, c_new, atol=1e-6) assert all( ( all_gates_of_type(m, cirq.Gateset(cirq.PhasedXZGate)) or all_gates_of_type(m, cirq.Gateset(cirq.SQRT_ISWAP_INV)) ) for m in c_new ) @pytest.mark.parametrize( 'gate', [ cirq.CNotPowGate(exponent=sympy.Symbol('t')), cirq.PhasedFSimGate(theta=sympy.Symbol('t'), chi=sympy.Symbol('t'), phi=sympy.Symbol('t')), ], ) @pytest.mark.parametrize('use_sqrt_iswap_inv', [True, False]) def test_two_qubit_gates_with_symbols(gate: cirq.Gate, use_sqrt_iswap_inv: bool): # Note that even though these gates are not natively supported by # `cirq.parameterized_2q_op_to_sqrt_iswap_operations`, the transformation succeeds because # `cirq.optimize_for_target_gateset` also relies on `cirq.decompose` as a fallback. c_orig = cirq.Circuit(gate(*cirq.LineQubit.range(2))) c_new = cirq.optimize_for_target_gateset( c_orig, gateset=cirq.SqrtIswapTargetGateset( use_sqrt_iswap_inv=use_sqrt_iswap_inv, additional_gates=[cirq.XPowGate, cirq.YPowGate, cirq.ZPowGate],
def _get_circuit_proto_pairs(): q0 = cirq.GridQubit(0, 0) q1 = cirq.GridQubit(0, 1) pairs = [ # HPOW and aliases. (cirq.Circuit(cirq.HPowGate(exponent=0.3)(q0)), _build_gate_proto("HP", ['exponent', 'exponent_scalar', 'global_shift'], [0.3, 1.0, 0.0], ['0_0'])), (cirq.Circuit(cirq.HPowGate(exponent=sympy.Symbol('alpha'))(q0)), _build_gate_proto("HP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 1.0, 0.0], ['0_0'])), (cirq.Circuit(cirq.HPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0)), _build_gate_proto("HP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 3.1, 0.0], ['0_0'])), (cirq.Circuit(cirq.H(q0)), _build_gate_proto("HP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, 0.0], ['0_0'])), # XPOW and aliases. (cirq.Circuit(cirq.XPowGate(exponent=0.3)(q0)), _build_gate_proto("XP", ['exponent', 'exponent_scalar', 'global_shift'], [0.3, 1.0, 0.0], ['0_0'])), (cirq.Circuit(cirq.XPowGate(exponent=sympy.Symbol('alpha'))(q0)), _build_gate_proto("XP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 1.0, 0.0], ['0_0'])), (cirq.Circuit(cirq.XPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0)), _build_gate_proto("XP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 3.1, 0.0], ['0_0'])), (cirq.Circuit(cirq.X(q0)), _build_gate_proto("XP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, 0.0], ['0_0'])), # YPOW and aliases (cirq.Circuit(cirq.YPowGate(exponent=0.3)(q0)), _build_gate_proto("YP", ['exponent', 'exponent_scalar', 'global_shift'], [0.3, 1.0, 0.0], ['0_0'])), (cirq.Circuit(cirq.YPowGate(exponent=sympy.Symbol('alpha'))(q0)), _build_gate_proto("YP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 1.0, 0.0], ['0_0'])), (cirq.Circuit(cirq.YPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0)), _build_gate_proto("YP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 3.1, 0.0], ['0_0'])), (cirq.Circuit(cirq.Y(q0)), _build_gate_proto("YP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, 0.0], ['0_0'])), # ZPOW and aliases. (cirq.Circuit(cirq.ZPowGate(exponent=0.3)(q0)), _build_gate_proto("ZP", ['exponent', 'exponent_scalar', 'global_shift'], [0.3, 1.0, 0.0], ['0_0'])), (cirq.Circuit(cirq.ZPowGate(exponent=sympy.Symbol('alpha'))(q0)), _build_gate_proto("ZP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 1.0, 0.0], ['0_0'])), (cirq.Circuit(cirq.ZPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0)), _build_gate_proto("ZP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 3.1, 0.0], ['0_0'])), (cirq.Circuit(cirq.Z(q0)), _build_gate_proto("ZP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, 0.0], ['0_0'])), # XXPow and aliases (cirq.Circuit(cirq.XXPowGate(exponent=0.3)(q0, q1)), _build_gate_proto("XXP", ['exponent', 'exponent_scalar', 'global_shift'], [0.3, 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit(cirq.XXPowGate(exponent=sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("XXP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit( cirq.XXPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("XXP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 3.1, 0.0], ['0_0', '0_1'])), (cirq.Circuit(cirq.XX(q0, q1)), _build_gate_proto("XXP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, 0.0], ['0_0', '0_1'])), # YYPow and aliases (cirq.Circuit(cirq.YYPowGate(exponent=0.3)(q0, q1)), _build_gate_proto("YYP", ['exponent', 'exponent_scalar', 'global_shift'], [0.3, 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit(cirq.YYPowGate(exponent=sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("YYP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit( cirq.YYPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("YYP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 3.1, 0.0], ['0_0', '0_1'])), (cirq.Circuit(cirq.YY(q0, q1)), _build_gate_proto("YYP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, 0.0], ['0_0', '0_1'])), # ZZPow and aliases (cirq.Circuit(cirq.ZZPowGate(exponent=0.3)(q0, q1)), _build_gate_proto("ZZP", ['exponent', 'exponent_scalar', 'global_shift'], [0.3, 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit(cirq.ZZPowGate(exponent=sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("ZZP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit( cirq.ZZPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("ZZP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 3.1, 0.0], ['0_0', '0_1'])), (cirq.Circuit(cirq.ZZ(q0, q1)), _build_gate_proto("ZZP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, 0.0], ['0_0', '0_1'])), # CZPow and aliases (cirq.Circuit(cirq.CZPowGate(exponent=0.3)(q0, q1)), _build_gate_proto("CZP", ['exponent', 'exponent_scalar', 'global_shift'], [0.3, 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit(cirq.CZPowGate(exponent=sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("CZP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit( cirq.CZPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("CZP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 3.1, 0.0], ['0_0', '0_1'])), (cirq.Circuit(cirq.CZ(q0, q1)), _build_gate_proto("CZP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, 0.0], ['0_0', '0_1'])), # CNOTPow and aliases (cirq.Circuit(cirq.CNotPowGate(exponent=0.3)(q0, q1)), _build_gate_proto("CNP", ['exponent', 'exponent_scalar', 'global_shift'], [0.3, 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit( cirq.CNotPowGate(exponent=sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("CNP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit( cirq.CNotPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("CNP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 3.1, 0.0], ['0_0', '0_1'])), (cirq.Circuit(cirq.CNOT(q0, q1)), _build_gate_proto("CNP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, 0.0], ['0_0', '0_1'])), # SWAPPow and aliases (cirq.Circuit(cirq.SwapPowGate(exponent=0.3)(q0, q1)), _build_gate_proto("SP", ['exponent', 'exponent_scalar', 'global_shift'], [0.3, 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit( cirq.SwapPowGate(exponent=sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("SP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit( cirq.SwapPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("SP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 3.1, 0.0], ['0_0', '0_1'])), (cirq.Circuit(cirq.SWAP(q0, q1)), _build_gate_proto("SP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, 0.0], ['0_0', '0_1'])), # ISWAPPow and aliases (cirq.Circuit(cirq.ISwapPowGate(exponent=0.3)(q0, q1)), _build_gate_proto("ISP", ['exponent', 'exponent_scalar', 'global_shift'], [0.3, 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit( cirq.ISwapPowGate(exponent=sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("ISP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit( cirq.ISwapPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("ISP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 3.1, 0.0], ['0_0', '0_1'])), (cirq.Circuit(cirq.ISWAP(q0, q1)), _build_gate_proto("ISP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, 0.0], ['0_0', '0_1'])), # PhasedXPow and aliases (cirq.Circuit( cirq.PhasedXPowGate(phase_exponent=0.9, exponent=0.3, global_shift=0.2)(q0)), _build_gate_proto("PXP", [ 'phase_exponent', 'phase_exponent_scalar', 'exponent', 'exponent_scalar', 'global_shift' ], [0.9, 1.0, 0.3, 1.0, 0.2], ['0_0'])), (cirq.Circuit( cirq.PhasedXPowGate(phase_exponent=sympy.Symbol('alpha'), exponent=0.3)(q0)), _build_gate_proto("PXP", [ 'phase_exponent', 'phase_exponent_scalar', 'exponent', 'exponent_scalar', 'global_shift' ], ['alpha', 1.0, 0.3, 1.0, 0.0], ['0_0'])), (cirq.Circuit( cirq.PhasedXPowGate(phase_exponent=3.1 * sympy.Symbol('alpha'), exponent=0.3)(q0)), _build_gate_proto("PXP", [ 'phase_exponent', 'phase_exponent_scalar', 'exponent', 'exponent_scalar', 'global_shift' ], ['alpha', 3.1, 0.3, 1.0, 0.0], ['0_0'])), (cirq.Circuit( cirq.PhasedXPowGate(phase_exponent=0.9, exponent=sympy.Symbol('beta'))(q0)), _build_gate_proto("PXP", [ 'phase_exponent', 'phase_exponent_scalar', 'exponent', 'exponent_scalar', 'global_shift' ], [0.9, 1.0, 'beta', 1.0, 0.0], ['0_0'])), (cirq.Circuit( cirq.PhasedXPowGate(phase_exponent=0.9, exponent=5.1 * sympy.Symbol('beta'))(q0)), _build_gate_proto("PXP", [ 'phase_exponent', 'phase_exponent_scalar', 'exponent', 'exponent_scalar', 'global_shift' ], [0.9, 1.0, 'beta', 5.1, 0.0], ['0_0'])), (cirq.Circuit( cirq.PhasedXPowGate(phase_exponent=3.1 * sympy.Symbol('alpha'), exponent=5.1 * sympy.Symbol('beta'))(q0)), _build_gate_proto("PXP", [ 'phase_exponent', 'phase_exponent_scalar', 'exponent', 'exponent_scalar', 'global_shift' ], ['alpha', 3.1, 'beta', 5.1, 0.0], ['0_0'])), # RX, RY, RZ with symbolization is tested in special cases as the # string comparison of the float converted sympy.pi does not happen # smoothly. See: test_serialize_deserialize_special_case_one_qubit (cirq.Circuit(cirq.rx(np.pi)(q0)), _build_gate_proto("XP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, -0.5], ['0_0'])), (cirq.Circuit(cirq.ry(np.pi)(q0)), _build_gate_proto("YP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, -0.5], ['0_0'])), (cirq.Circuit(cirq.rz(np.pi)(q0)), _build_gate_proto("ZP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, -0.5], ['0_0'])), # Identity (cirq.Circuit(cirq.I(q0)), _build_gate_proto("I", ['unused'], [True], ['0_0'])), # FSimGate (cirq.Circuit(cirq.FSimGate(theta=0.1, phi=0.2)(q0, q1)), _build_gate_proto("FSIM", ['theta', 'theta_scalar', 'phi', 'phi_scalar'], [0.1, 1.0, 0.2, 1.0], ['0_0', '0_1'])), (cirq.Circuit( cirq.FSimGate(theta=2.1 * sympy.Symbol("alpha"), phi=1.3 * sympy.Symbol("beta"))(q0, q1)), _build_gate_proto("FSIM", ['theta', 'theta_scalar', 'phi', 'phi_scalar'], ['alpha', 2.1, 'beta', 1.3], ['0_0', '0_1'])), ] return pairs
(cast(cirq.Gate, cirq.ISWAP), 7), # cast is for fixing mypy confusion (cirq.CZ, 8), (cirq.SWAP, 7), (cirq.CNOT, 9), (cirq.ISWAP**0.5, 1), (cirq.ISWAP**-0.5, 1), (cirq.ISwapPowGate(exponent=0.5), 1), (cirq.ISwapPowGate(exponent=-0.5), 1), (cirq.FSimGate(theta=np.pi / 4, phi=0), 1), *[(cirq.SwapPowGate(exponent=a), 13) for a in np.linspace(0, 2 * np.pi, 20)], *[(cirq.CZPowGate(exponent=a), 8) for a in np.linspace(0, 2 * np.pi, 20)], *[(cirq.ISwapPowGate(exponent=a), 5) for a in np.linspace(0, 2 * np.pi, 20)], *[(cirq.CNotPowGate(exponent=a), 9) for a in np.linspace(0, 2 * np.pi, 20)], *[(cirq.FSimGate(theta=a, phi=a), 13) for a in np.linspace(0, 2 * np.pi, 20)], ], ) def test_two_qubit_gates(gate: cirq.Gate, expected_length: int): """Tests that two qubit gates decompose to an equivalent and serializable circuit with the expected length (or less). """ q0 = cirq.GridQubit(5, 3) q1 = cirq.GridQubit(5, 4) original_circuit = cirq.Circuit(gate(q0, q1)) converted_circuit = original_circuit.copy() converted_circuit_iswap_inv = cirq.optimize_for_target_gateset( original_circuit,
z = cirq.ZPowGate(exponent=5) assert z.exponent == 5 # Canonicalizes exponent for equality, but keeps the inner details. assert cirq.Z**0.5 != cirq.Z**-0.5 assert (cirq.Z**-1)**0.5 == cirq.Z**-0.5 assert cirq.Z**-1 == cirq.Z @pytest.mark.parametrize( 'input_gate, specialized_output', [(cirq.Z, cirq.CZ), (cirq.CZ, cirq.CCZ), (cirq.X, cirq.CX), (cirq.CX, cirq.CCX), (cirq.ZPowGate(exponent=0.5), cirq.CZPowGate(exponent=0.5)), (cirq.CZPowGate(exponent=0.5), cirq.CCZPowGate(exponent=0.5)), (cirq.XPowGate(exponent=0.5), cirq.CNotPowGate(exponent=0.5)), (cirq.CNotPowGate(exponent=0.5), cirq.CCXPowGate(exponent=0.5))]) def test_specialized_control(input_gate, specialized_output): # Single qubit control on the input gate gives the specialized output assert input_gate.controlled() == specialized_output assert input_gate.controlled(num_controls=1) == specialized_output assert input_gate.controlled( control_values=((1, ), )) == specialized_output assert input_gate.controlled(control_qid_shape=(2, )) == specialized_output assert np.allclose( cirq.unitary(specialized_output), cirq.unitary(cirq.ControlledGate(input_gate, num_controls=1))) # For multi-qudit controls, if the last control is a qubit with control # value 1, construct the specialized output leaving the rest of the # controls as they are.
'Bristlecone': cirq.google.Bristlecone, 'CCNOT': cirq.CCNOT, 'CCX': cirq.CCX, 'CCXPowGate': cirq.CCXPowGate(exponent=0.123, global_shift=0.456), 'CCZ': cirq.CCZ, 'CCZPowGate': cirq.CCZPowGate(exponent=0.123, global_shift=0.456), 'CNOT': cirq.CNOT, 'CNotPowGate': cirq.CNotPowGate(exponent=0.123, global_shift=0.456), 'ControlledOperation': cirq.ControlledOperation(sub_operation=cirq.Y(cirq.NamedQubit('target')), controls=cirq.LineQubit.range(2), control_values=[0, 1]), 'ControlledGate': cirq.ControlledGate(sub_gate=cirq.Y, num_controls=2, control_values=[0, 1], control_qid_shape=(3, 2)), 'CX': cirq.CX, 'CSWAP': cirq.CSWAP, 'CSwapGate': cirq.CSwapGate(),
def test_CY(benchmark, nqubits): benchmark.group = "C-Rx(0.5)" run_bench(benchmark, nqubits, cirq.CNotPowGate(exponent=0.5), (2, 3))
class CirqDevice(QubitDevice, abc.ABC): """Abstract base device for PennyLane-Cirq. Args: wires (int or Iterable[Number, str]]): Number of subsystems represented by the device, or iterable that contains unique labels for the subsystems as numbers (i.e., ``[-1, 0, 2]``) or strings (``['ancilla', 'q1', 'q2']``). shots (int): Number of circuit evaluations/random samples used to estimate expectation values of observables. Shots need to be >= 1. qubits (List[cirq.Qubit]): A list of Cirq qubits that are used as wires. By default, an array of ``cirq.LineQubit`` instances is created. Wires are mapped to qubits using Cirq's internal mechanism for ordering qubits. For example, if ``wires=2`` and ``qubits=[q1, q2]``, with ``q1>q2``, then the wire indices 0 and 1 are mapped to q2 and q1, respectively. If the user provides their own wire labels, e.g., ``wires=["alice", "bob"]``, and the qubits are the same as the previous example, then "alice" would map to qubit q2 and "bob" would map to qubit q1. """ name = "Cirq Abstract PennyLane plugin base class" pennylane_requires = ">=0.11.0" version = __version__ author = "Xanadu Inc" _capabilities = { "model": "qubit", "tensor_observables": True, "inverse_operations": True, } short_name = "cirq.base_device" def __init__(self, wires, shots, analytic, qubits=None): if not isinstance(wires, Iterable): # interpret wires as the number of consecutive wires wires = range(wires) num_wires = len(wires) if qubits: if num_wires != len(qubits): raise qml.DeviceError( "The number of given qubits and the specified number of wires have to match. Got {} wires and {} qubits.".format( wires, len(qubits) ) ) else: qubits = [cirq.LineQubit(idx) for idx in range(num_wires)] # cirq orders the subsystems based on a total order defined on qubits. # For consistency, this plugin uses that same total order self._unsorted_qubits = qubits self.qubits = sorted(qubits) super().__init__(wires, shots, analytic) self.circuit = None self.cirq_device = None # Add inverse operations self._inverse_operation_map = {} for key in self._operation_map: if not self._operation_map[key]: continue # We have to use a new CirqOperation instance because .inv() acts in-place inverted_operation = CirqOperation(self._operation_map[key].parametrization) inverted_operation.inv() self._inverse_operation_map[key + Operation.string_for_inverse] = inverted_operation self._complete_operation_map = { **self._operation_map, **self._inverse_operation_map, } _operation_map = { "BasisState": None, "QubitStateVector": None, "QubitUnitary": CirqOperation(cirq.MatrixGate), "PauliX": CirqOperation(lambda: cirq.X), "PauliY": CirqOperation(lambda: cirq.Y), "PauliZ": CirqOperation(lambda: cirq.Z), "Hadamard": CirqOperation(lambda: cirq.H), "S": CirqOperation(lambda: cirq.S), "T": CirqOperation(lambda: cirq.T), "CNOT": CirqOperation(lambda: cirq.CNOT), "SWAP": CirqOperation(lambda: cirq.SWAP), "ISWAP": CirqOperation(lambda: cirq.ISWAP), "CZ": CirqOperation(lambda: cirq.CZ), "PhaseShift": CirqOperation(lambda phi: cirq.ZPowGate(exponent=phi / np.pi)), "CPhase": CirqOperation(lambda phi: cirq.CZPowGate(exponent=phi / np.pi)), "RX": CirqOperation(lambda phi: cirq.XPowGate(exponent=phi / np.pi, global_shift=0.5)), "RY": CirqOperation(lambda phi: cirq.YPowGate(exponent=phi / np.pi, global_shift=0.5)), "RZ": CirqOperation(lambda phi: cirq.ZPowGate(exponent=phi / np.pi, global_shift=0.5)), "Rot": CirqOperation( lambda a, b, c: [ cirq.ZPowGate(exponent=a / np.pi, global_shift=0.5), cirq.YPowGate(exponent=b / np.pi, global_shift=0.5), cirq.ZPowGate(exponent=c / np.pi, global_shift=0.5), ] ), "CRX": CirqOperation(lambda phi: cirq.CNotPowGate(exponent=phi / np.pi, global_shift=0.5)), # "CRY": CirqOperation(lambda phi: cirq.ControlledGate(cirq.YPowGate(exponent=phi / np.pi, global_shift=-0.5))), "CRZ": CirqOperation(lambda phi: cirq.CZPowGate(exponent=phi / np.pi, global_shift=0.5)), # "CRot": CirqOperation( # lambda a, b, c: [ # cirq.ControlledGate(cirq.rz(a)), # cirq.ControlledGate(cirq.ry(b)), # cirq.ControlledGate(cirq.rz(c)), # ] # ), "CSWAP": CirqOperation(lambda: cirq.CSWAP), "Toffoli": CirqOperation(lambda: cirq.TOFFOLI), } _observable_map = { "PauliX": CirqOperation(lambda: cirq.X), "PauliY": CirqOperation(lambda: cirq.Y), "PauliZ": CirqOperation(lambda: cirq.Z), "Hadamard": CirqOperation(lambda: cirq.H), # TODO(chase): Consider using qml.utils.decompose_hamiltonian() # to support this observable. "Hermitian": None, "Identity": CirqOperation(lambda: cirq.I), } def to_paulistring(self, observable): """Convert an observable to a cirq.PauliString""" if isinstance(observable, Tensor): obs = [self.to_paulistring(o) for o in observable.obs] return functools.reduce(operator.mul, obs) cirq_op = self._observable_map[observable.name] if cirq_op is None: raise NotImplementedError(f"{observable.name} is not currently supported.") cirq_op.parametrize(*observable.parameters) device_wires = self.map_wires(observable.wires) return functools.reduce( operator.mul, cirq_op.apply(*[self.qubits[w] for w in device_wires.labels]) ) def reset(self): # pylint: disable=missing-function-docstring super().reset() if self.cirq_device: self.circuit = cirq.Circuit(device=self.cirq_device) else: self.circuit = cirq.Circuit() @property def observables(self): # pylint: disable=missing-function-docstring return set(self._observable_map.keys()) @property def operations(self): # pylint: disable=missing-function-docstring return set(self._operation_map.keys()) @abc.abstractmethod def _apply_basis_state(self, basis_state_operation): """Apply a basis state preparation. Args: basis_state_operation (pennylane.BasisState): the BasisState operation instance that shall be applied Raises: NotImplementedError: when not implemented in the subclass """ raise NotImplementedError @abc.abstractmethod def _apply_qubit_state_vector(self, qubit_state_vector_operation): """Apply a state vector preparation. Args: qubit_state_vector_operation (pennylane.QubitStateVector): the QubitStateVector operation instance that shall be applied Raises: NotImplementedError: when not implemented in the subclass """ raise NotImplementedError def _apply_operation(self, operation): """Apply a single PennyLane Operation. Args: operation (pennylane.Operation): the operation that shall be applied """ cirq_operation = self._complete_operation_map[operation.name] # If command is None do nothing if cirq_operation: cirq_operation.parametrize(*operation.parameters) device_wires = self.map_wires(operation.wires) self.circuit.append( cirq_operation.apply(*[self.qubits[w] for w in device_wires.labels]) ) def apply(self, operations, **kwargs): # pylint: disable=missing-function-docstring rotations = kwargs.pop("rotations", []) for i, operation in enumerate(operations): if i > 0 and operation.name in {"BasisState", "QubitStateVector"}: raise qml.DeviceError( "The operation {} is only supported at the beginning of a circuit.".format( operation.name ) ) if operation.name == "BasisState": self._apply_basis_state(operation) elif operation.name == "QubitStateVector": self._apply_qubit_state_vector(operation) else: self._apply_operation(operation) # TODO: get pre rotated state here # Diagonalize the given observables for operation in rotations: self._apply_operation(operation) def define_wire_map(self, wires): # pylint: disable=missing-function-docstring cirq_order = np.argsort(self._unsorted_qubits) consecutive_wires = Wires(cirq_order) wire_map = zip(wires, consecutive_wires) return OrderedDict(wire_map)
@pytest.mark.parametrize( 'gate, expected_length', [ (cast(cirq.Gate, cirq.ISWAP), 7), # cast is for fixing mypy confusion (cirq.CZ, 8), (cirq.SWAP, 7), (cirq.CNOT, 9), (cirq.ISWAP ** 0.5, 1), (cirq.ISWAP ** -0.5, 1), (cirq.ISwapPowGate(exponent=0.5), 1), (cirq.ISwapPowGate(exponent=-0.5), 1), (cirq.FSimGate(theta=np.pi / 4, phi=0), 1), *[(cirq.SwapPowGate(exponent=a), 13) for a in np.linspace(0, 2 * np.pi, 20)], *[(cirq.CZPowGate(exponent=a), 8) for a in np.linspace(0, 2 * np.pi, 20)], *[(cirq.ISwapPowGate(exponent=a), 5) for a in np.linspace(0, 2 * np.pi, 20)], *[(cirq.CNotPowGate(exponent=a), 9) for a in np.linspace(0, 2 * np.pi, 20)], *[(cirq.FSimGate(theta=a, phi=a), 13) for a in np.linspace(0, 2 * np.pi, 20)], ], ) def test_two_qubit_gates(gate: cirq.Gate, expected_length: int): """Tests that two qubit gates decompose to an equivalent and serializable circuit with the expected length (or less). """ q0 = cirq.GridQubit(5, 3) q1 = cirq.GridQubit(5, 4) original_circuit = cirq.Circuit(gate(q0, q1)) converted_circuit = original_circuit.copy() cgoc.ConvertToSqrtIswapGates().optimize_circuit(converted_circuit) cig.SQRT_ISWAP_GATESET.serialize(converted_circuit) assert len(converted_circuit) <= expected_length assert _unitaries_allclose(original_circuit, converted_circuit)