diff --git a/src/braket/circuits/gates.py b/src/braket/circuits/gates.py index df17c03c3..d1bfbb214 100644 --- a/src/braket/circuits/gates.py +++ b/src/braket/circuits/gates.py @@ -24,6 +24,7 @@ from braket.circuits import circuit from braket.circuits.angled_gate import ( AngledGate, + DoubleAngledGate, TripleAngledGate, _get_angles, _multi_angled_ascii_characters, @@ -3296,6 +3297,123 @@ def gpi( Gate.register_gate(GPi) +class PhaseRx(DoubleAngledGate): + r"""Phase Rx gate. + + Unitary matrix: + + .. math:: \mathtt{PhaseRx}(\theta,\phi) = \begin{bmatrix} + cos(\theta / 2) & -i e^{-i \phi} sin(\theta / 2) \\ + -i e^{i \phi} sin(\theta / 2) & cos(\theta / 2) + \end{bmatrix}. + + Args: + angle_1 (Union[FreeParameterExpression, float]): The first angle of the gate in + radians or expression representation. + angle_2 (Union[FreeParameterExpression, float]): The second angle of the gate in + radians or expression representation. + """ + + def __init__( + self, + angle_1: Union[FreeParameterExpression, float], + angle_2: Union[FreeParameterExpression, float], + ): + super().__init__( + angle_1=angle_1, + angle_2=angle_2, + qubit_count=None, + ascii_symbols=[_multi_angled_ascii_characters("PhaseRx", angle_1, angle_2)], + ) + + def to_matrix(self) -> np.ndarray: + r"""Returns a matrix representation of this gate. + + Returns: + np.ndarray: The matrix representation of this gate. + """ + _theta = self.angle_1 + _phi = self.angle_2 + return np.array( + [ + [ + np.cos(_theta / 2), + -1j * np.exp(-1j * _phi) * np.sin(_theta / 2), + ], + [ + -1j * np.exp(1j * _phi) * np.sin(_theta / 2), + np.cos(_theta / 2), + ], + ] + ) + + def _qasm_name(self) -> str: + return "phaserx" + + def adjoint(self) -> list[Gate]: + return [PhaseRx(-self.angle_1, -self.angle_2)] + + @staticmethod + def fixed_qubit_count() -> int: + return 1 + + def bind_values(self, **kwargs) -> PhaseRx: + return get_angle(self, **kwargs) + + @staticmethod + @circuit.subroutine(register=True) + def phaserx( + target: QubitSetInput, + angle_1: Union[FreeParameterExpression, float], + angle_2: Union[FreeParameterExpression, float], + *, + control: Optional[QubitSetInput] = None, + control_state: Optional[BasisStateInput] = None, + power: float = 1, + ) -> Iterable[Instruction]: + r"""PhaseRx gate. + + .. math:: \mathtt{PRx}(\theta,\phi) = \begin{bmatrix} + cos(\theta) & -i e^{-i \phi} sin(\theta / 2) \\ + -i e^{i \phi} sin(\theta / 2) & cos(\theta / 2) + \end{bmatrix}. + + Args: + target (QubitSetInput): Target qubit(s). + angle_1 (Union[FreeParameterExpression, float]): First angle in radians. + angle_2 (Union[FreeParameterExpression, float]): Second angle in radians. + control (Optional[QubitSetInput]): Control qubit(s). Default None. + control_state (Optional[BasisStateInput]): Quantum state on which to control the + operation. Must be a binary sequence of same length as number of qubits in + `control`. Will be ignored if `control` is not present. May be represented as a + string, list, or int. For example "0101", [0, 1, 0, 1], 5 all represent + controlling on qubits 0 and 2 being in the \\|0⟩ state and qubits 1 and 3 being + in the \\|1⟩ state. Default "1" * len(control). + power (float): Integer or fractional power to raise the gate to. Negative + powers will be split into an inverse, accompanied by the positive power. + Default 1. + + Returns: + Iterable[Instruction]: PhaseRx instruction. + + Examples: + >>> circ = Circuit().phaserx(0, 0.15, 0.25) + """ + return [ + Instruction( + PhaseRx(angle_1, angle_2), + target=qubit, + control=control, + control_state=control_state, + power=power, + ) + for qubit in QubitSet(target) + ] + + +Gate.register_gate(PhaseRx) + + class GPi2(AngledGate): r"""IonQ GPi2 gate. diff --git a/test/unit_tests/braket/circuits/test_circuit.py b/test/unit_tests/braket/circuits/test_circuit.py index ecaad12bf..50c46c735 100644 --- a/test/unit_tests/braket/circuits/test_circuit.py +++ b/test/unit_tests/braket/circuits/test_circuit.py @@ -2196,6 +2196,7 @@ def test_to_unitary_with_global_phase(): (Circuit().cphaseshift00(0, 1, 0.15), gates.CPhaseShift00(0.15).to_matrix()), (Circuit().cphaseshift01(0, 1, 0.15), gates.CPhaseShift01(0.15).to_matrix()), (Circuit().cphaseshift10(0, 1, 0.15), gates.CPhaseShift10(0.15).to_matrix()), + (Circuit().phaserx(0, 1, 0.15), gates.PhaseRx(1, 0.15).to_matrix()), (Circuit().cy(0, 1), gates.CY().to_matrix()), (Circuit().cz(0, 1), gates.CZ().to_matrix()), (Circuit().xx(0, 1, 0.15), gates.XX(0.15).to_matrix()),