Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement RGate in Rust #12662

Merged
merged 7 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions crates/circuit/src/gate_matrix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,19 @@ const fn c64(re: f64, im: f64) -> Complex64 {
pub static ONE_QUBIT_IDENTITY: [[Complex64; 2]; 2] =
[[c64(1., 0.), c64(0., 0.)], [c64(0., 0.), c64(1., 0.)]];

#[inline]
pub fn r_gate(theta: f64, phi: f64) -> [[Complex64; 2]; 2] {
let half_theta = theta / 2.;
let cost = c64(half_theta.cos(), 0.);
let sint = half_theta.sin();
let cosphi = phi.cos();
let sinphi = phi.sin();
[
[cost, c64(-sint * sinphi, -sint * cosphi)],
[c64(sint * sinphi, -sint * cosphi), cost],
]
}

#[inline]
pub fn rx_gate(theta: f64) -> [[Complex64; 2]; 2] {
let half_theta = theta / 2.;
Expand Down
2 changes: 1 addition & 1 deletion crates/circuit/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ static STDGATE_IMPORT_PATHS: [[&str; 2]; STANDARD_GATE_SIZE] = [
// CRZGate = 31
["placeholder", "placeholder"],
// RGate 32
["placeholder", "placeholder"],
["qiskit.circuit.library.standard_gates.r", "RGate"],
// CHGate = 33
["qiskit.circuit.library.standard_gates.h", "CHGate"],
// CPhaseGate = 34
Expand Down
52 changes: 47 additions & 5 deletions crates/circuit/src/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ static STANDARD_GATE_NUM_QUBITS: [u32; STANDARD_GATE_SIZE] = [
1, 1, 1, 2, 2, 2, 3, 1, 1, 1, // 0-9
2, 2, 1, 0, 1, 1, 1, 1, 1, 1, // 10-19
1, 1, 1, 2, 2, 2, 1, 1, 1, 34, // 20-29
34, 34, 34, 2, 2, 2, 2, 2, 3, 2, // 30-39
34, 34, 1, 2, 2, 2, 2, 2, 3, 2, // 30-39
2, 2, 34, 34, 34, 2, 34, 34, 34, 34, // 40-49
34, 34, 34, // 50-52
];
Expand All @@ -249,7 +249,7 @@ static STANDARD_GATE_NUM_PARAMS: [u32; STANDARD_GATE_SIZE] = [
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, // 0-9
0, 0, 0, 1, 0, 0, 1, 3, 0, 0, // 10-19
0, 0, 0, 0, 2, 2, 1, 2, 3, 34, // 20-29
34, 34, 34, 0, 1, 0, 0, 0, 0, 3, // 30-39
34, 34, 2, 0, 1, 0, 0, 0, 0, 3, // 30-39
1, 3, 34, 34, 34, 0, 34, 34, 34, 34, // 40-49
34, 34, 34, // 50-52
];
Expand Down Expand Up @@ -514,7 +514,12 @@ impl Operation for StandardGate {
_ => None,
},
Self::CRXGate | Self::CRYGate | Self::CRZGate => todo!(),
Self::RGate => todo!(),
Self::RGate => match params {
[Param::Float(theta), Param::Float(phi)] => {
Some(aview2(&gate_matrix::r_gate(*theta, *phi)).to_owned())
}
_ => None,
},
Self::CHGate => todo!(),
Self::CPhaseGate => todo!(),
Self::CSGate => todo!(),
Expand Down Expand Up @@ -957,7 +962,21 @@ impl Operation for StandardGate {
)
}),
Self::CRXGate | Self::CRYGate | Self::CRZGate => todo!(),
Self::RGate => todo!(),
Self::RGate => Python::with_gil(|py| -> Option<CircuitData> {
let theta_expr = clone_param(&params[0], py);
let phi_expr1 = add_param(&params[1], -PI2, py);
let phi_expr2 = multiply_param(&phi_expr1, -1.0, py);
let defparams = smallvec![theta_expr, phi_expr1, phi_expr2];
Some(
CircuitData::from_standard_gates(
py,
1,
[(Self::UGate, defparams, smallvec![Qubit(0)])],
FLOAT_ZERO,
)
.expect("Unexpected Qiskit python bug"),
)
}),
Self::CHGate => todo!(),
Self::CPhaseGate => todo!(),
Self::CSGate => todo!(),
Expand Down Expand Up @@ -997,14 +1016,37 @@ impl Operation for StandardGate {

const FLOAT_ZERO: Param = Param::Float(0.0);

// Return explictly requested copy of `param`, handling
// each variant separately.
fn clone_param(param: &Param, py: Python) -> Param {
match param {
Param::Float(theta) => Param::Float(*theta),
Param::ParameterExpression(theta) => Param::ParameterExpression(theta.clone_ref(py)),
Param::Obj(_) => unreachable!(),
}
}

fn multiply_param(param: &Param, mult: f64, py: Python) -> Param {
match param {
Param::Float(theta) => Param::Float(*theta * mult),
Param::ParameterExpression(theta) => Param::ParameterExpression(
theta
.clone_ref(py)
.call_method1(py, intern!(py, "__rmul__"), (mult,))
.expect("Parameter expression for global phase failed"),
.expect("Multiplication of Parameter expression by float failed."),
),
Param::Obj(_) => unreachable!(),
}
}

fn add_param(param: &Param, summand: f64, py: Python) -> Param {
match param {
Param::Float(theta) => Param::Float(*theta + summand),
Param::ParameterExpression(theta) => Param::ParameterExpression(
theta
.clone_ref(py)
.call_method1(py, intern!(py, "__add__"), (summand,))
.expect("Sum of Parameter expression and float failed."),
),
Param::Obj(_) => unreachable!(),
}
Expand Down
3 changes: 3 additions & 0 deletions qiskit/circuit/library/standard_gates/r.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from qiskit.circuit.gate import Gate
from qiskit.circuit.quantumregister import QuantumRegister
from qiskit.circuit.parameterexpression import ParameterValueType
from qiskit._accelerate.circuit import StandardGate


class RGate(Gate):
Expand Down Expand Up @@ -49,6 +50,8 @@ class RGate(Gate):
\end{pmatrix}
"""

_standard_gate = StandardGate.RGate

def __init__(
self,
theta: ParameterValueType,
Expand Down
4 changes: 1 addition & 3 deletions qiskit/circuit/quantumcircuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -4649,9 +4649,7 @@ def r(
Returns:
A handle to the instructions created.
"""
from .library.standard_gates.r import RGate

return self.append(RGate(theta, phi), [qubit], [], copy=False)
return self._append_standard_gate(StandardGate.RGate, [theta, phi], qargs=[qubit])

def rv(
self,
Expand Down
Loading