Add Rust representation for CHGate, CPhaseGate, CSGate, CSdgGate, CSXGate, CSwapGate (#12639)

* Add CHGate, CPhaseGate, CSGate, CSdgGate, CSXGate, CSwapGate

* Fix tests, add labels

* Fix oversights in gate definitions

* Fix test

* Add ctrl_state 1 to rust building path.
This commit is contained in:
Elena Peña Tapia 2024-07-01 14:49:06 +02:00 committed by GitHub
parent c452694d70
commit a7fc2daf4c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 465 additions and 176 deletions

View File

@ -53,43 +53,6 @@ pub fn rz_gate(theta: f64) -> GateArray1Q {
[[(-ilam2).exp(), C_ZERO], [C_ZERO, ilam2.exp()]]
}
#[inline]
pub fn crx_gate(theta: f64) -> GateArray2Q {
let half_theta = theta / 2.;
let cos = c64(half_theta.cos(), 0.);
let isin = c64(0., half_theta.sin());
[
[C_ONE, C_ZERO, C_ZERO, C_ZERO],
[C_ZERO, cos, C_ZERO, -isin],
[C_ZERO, C_ZERO, C_ONE, C_ZERO],
[C_ZERO, -isin, C_ZERO, cos],
]
}
#[inline]
pub fn cry_gate(theta: f64) -> GateArray2Q {
let half_theta = theta / 2.;
let cos = c64(half_theta.cos(), 0.);
let sin = c64(half_theta.sin(), 0.);
[
[C_ONE, C_ZERO, C_ZERO, C_ZERO],
[C_ZERO, cos, C_ZERO, -sin],
[C_ZERO, C_ZERO, C_ONE, C_ZERO],
[C_ZERO, sin, C_ZERO, cos],
]
}
#[inline]
pub fn crz_gate(theta: f64) -> GateArray2Q {
let i_half_theta = c64(0., theta / 2.);
[
[C_ONE, C_ZERO, C_ZERO, C_ZERO],
[C_ZERO, (-i_half_theta).exp(), C_ZERO, C_ZERO],
[C_ZERO, C_ZERO, C_ONE, C_ZERO],
[C_ZERO, C_ZERO, C_ZERO, i_half_theta.exp()],
]
}
pub static H_GATE: GateArray1Q = [
[c64(FRAC_1_SQRT_2, 0.), c64(FRAC_1_SQRT_2, 0.)],
[c64(FRAC_1_SQRT_2, 0.), c64(-FRAC_1_SQRT_2, 0.)],
@ -210,6 +173,71 @@ pub static TDG_GATE: GateArray1Q = [
[C_ZERO, c64(FRAC_1_SQRT_2, -FRAC_1_SQRT_2)],
];
pub static CH_GATE: GateArray2Q = [
[C_ONE, C_ZERO, C_ZERO, C_ZERO],
[
C_ZERO,
c64(FRAC_1_SQRT_2, 0.),
C_ZERO,
c64(FRAC_1_SQRT_2, 0.),
],
[C_ZERO, C_ZERO, C_ONE, C_ZERO],
[
C_ZERO,
c64(FRAC_1_SQRT_2, 0.),
C_ZERO,
c64(-FRAC_1_SQRT_2, 0.),
],
];
pub static CS_GATE: GateArray2Q = [
[C_ONE, C_ZERO, C_ZERO, C_ZERO],
[C_ZERO, C_ONE, C_ZERO, C_ZERO],
[C_ZERO, C_ZERO, C_ONE, C_ZERO],
[C_ZERO, C_ZERO, C_ZERO, IM],
];
pub static CSDG_GATE: GateArray2Q = [
[C_ONE, C_ZERO, C_ZERO, C_ZERO],
[C_ZERO, C_ONE, C_ZERO, C_ZERO],
[C_ZERO, C_ZERO, C_ONE, C_ZERO],
[C_ZERO, C_ZERO, C_ZERO, M_IM],
];
pub static CSX_GATE: GateArray2Q = [
[C_ONE, C_ZERO, C_ZERO, C_ZERO],
[C_ZERO, c64(0.5, 0.5), C_ZERO, c64(0.5, -0.5)],
[C_ZERO, C_ZERO, C_ONE, C_ZERO],
[C_ZERO, c64(0.5, -0.5), C_ZERO, c64(0.5, 0.5)],
];
pub static CSWAP_GATE: GateArray3Q = [
[
C_ONE, C_ZERO, C_ZERO, C_ZERO, C_ZERO, C_ZERO, C_ZERO, C_ZERO,
],
[
C_ZERO, C_ONE, C_ZERO, C_ZERO, C_ZERO, C_ZERO, C_ZERO, C_ZERO,
],
[
C_ZERO, C_ZERO, C_ONE, C_ZERO, C_ZERO, C_ZERO, C_ZERO, C_ZERO,
],
[
C_ZERO, C_ZERO, C_ZERO, C_ZERO, C_ZERO, C_ONE, C_ZERO, C_ZERO,
],
[
C_ZERO, C_ZERO, C_ZERO, C_ZERO, C_ONE, C_ZERO, C_ZERO, C_ZERO,
],
[
C_ZERO, C_ZERO, C_ZERO, C_ONE, C_ZERO, C_ZERO, C_ZERO, C_ZERO,
],
[
C_ZERO, C_ZERO, C_ZERO, C_ZERO, C_ZERO, C_ZERO, C_ONE, C_ZERO,
],
[
C_ZERO, C_ZERO, C_ZERO, C_ZERO, C_ZERO, C_ZERO, C_ZERO, C_ONE,
],
];
pub static DCX_GATE: GateArray2Q = [
[C_ONE, C_ZERO, C_ZERO, C_ZERO],
[C_ZERO, C_ZERO, C_ZERO, C_ONE],
@ -217,6 +245,43 @@ pub static DCX_GATE: GateArray2Q = [
[C_ZERO, C_ZERO, C_ONE, C_ZERO],
];
#[inline]
pub fn crx_gate(theta: f64) -> GateArray2Q {
let half_theta = theta / 2.;
let cos = c64(half_theta.cos(), 0.);
let isin = c64(0., half_theta.sin());
[
[C_ONE, C_ZERO, C_ZERO, C_ZERO],
[C_ZERO, cos, C_ZERO, -isin],
[C_ZERO, C_ZERO, C_ONE, C_ZERO],
[C_ZERO, -isin, C_ZERO, cos],
]
}
#[inline]
pub fn cry_gate(theta: f64) -> GateArray2Q {
let half_theta = theta / 2.;
let cos = c64(half_theta.cos(), 0.);
let sin = c64(half_theta.sin(), 0.);
[
[C_ONE, C_ZERO, C_ZERO, C_ZERO],
[C_ZERO, cos, C_ZERO, -sin],
[C_ZERO, C_ZERO, C_ONE, C_ZERO],
[C_ZERO, sin, C_ZERO, cos],
]
}
#[inline]
pub fn crz_gate(theta: f64) -> GateArray2Q {
let i_half_theta = c64(0., theta / 2.);
[
[C_ONE, C_ZERO, C_ZERO, C_ZERO],
[C_ZERO, (-i_half_theta).exp(), C_ZERO, C_ZERO],
[C_ZERO, C_ZERO, C_ONE, C_ZERO],
[C_ZERO, C_ZERO, C_ZERO, i_half_theta.exp()],
]
}
#[inline]
pub fn global_phase_gate(theta: f64) -> GateArray0Q {
[[c64(0., theta).exp()]]
@ -310,18 +375,27 @@ pub fn xx_plus_yy_gate(theta: f64, beta: f64) -> GateArray2Q {
]
}
#[inline]
pub fn cp_gate(lam: f64) -> GateArray2Q {
[
[C_ONE, C_ZERO, C_ZERO, C_ZERO],
[C_ZERO, C_ONE, C_ZERO, C_ZERO],
[C_ZERO, C_ZERO, C_ONE, C_ZERO],
[C_ZERO, C_ZERO, C_ZERO, c64(0., lam).exp()],
]
}
#[inline]
pub fn rxx_gate(theta: f64) -> GateArray2Q {
let (sint, cost) = (theta / 2.0).sin_cos();
let ccos = c64(cost, 0.);
let csinm = c64(0., -sint);
let c0 = c64(0., 0.);
[
[ccos, c0, c0, csinm],
[c0, ccos, csinm, c0],
[c0, csinm, ccos, c0],
[csinm, c0, c0, ccos],
[ccos, C_ZERO, C_ZERO, csinm],
[C_ZERO, ccos, csinm, C_ZERO],
[C_ZERO, csinm, ccos, C_ZERO],
[csinm, C_ZERO, C_ZERO, ccos],
]
}
@ -330,28 +404,26 @@ pub fn ryy_gate(theta: f64) -> GateArray2Q {
let (sint, cost) = (theta / 2.0).sin_cos();
let ccos = c64(cost, 0.);
let csin = c64(0., sint);
let c0 = c64(0., 0.);
[
[ccos, c0, c0, csin],
[c0, ccos, -csin, c0],
[c0, -csin, ccos, c0],
[csin, c0, c0, ccos],
[ccos, C_ZERO, C_ZERO, csin],
[C_ZERO, ccos, -csin, C_ZERO],
[C_ZERO, -csin, ccos, C_ZERO],
[csin, C_ZERO, C_ZERO, ccos],
]
}
#[inline]
pub fn rzz_gate(theta: f64) -> GateArray2Q {
let (sint, cost) = (theta / 2.0).sin_cos();
let c0 = c64(0., 0.);
let exp_it2 = c64(cost, sint);
let exp_mit2 = c64(cost, -sint);
[
[exp_mit2, c0, c0, c0],
[c0, exp_it2, c0, c0],
[c0, c0, exp_it2, c0],
[c0, c0, c0, exp_mit2],
[exp_mit2, C_ZERO, C_ZERO, C_ZERO],
[C_ZERO, exp_it2, C_ZERO, C_ZERO],
[C_ZERO, C_ZERO, exp_it2, C_ZERO],
[C_ZERO, C_ZERO, C_ZERO, exp_mit2],
]
}
@ -360,12 +432,11 @@ pub fn rzx_gate(theta: f64) -> GateArray2Q {
let (sint, cost) = (theta / 2.0).sin_cos();
let ccos = c64(cost, 0.);
let csin = c64(0., sint);
let c0 = c64(0., 0.);
[
[ccos, c0, -csin, c0],
[c0, ccos, c0, csin],
[-csin, c0, ccos, c0],
[c0, csin, c0, ccos],
[ccos, C_ZERO, -csin, C_ZERO],
[C_ZERO, ccos, C_ZERO, csin],
[-csin, C_ZERO, ccos, C_ZERO],
[C_ZERO, csin, C_ZERO, ccos],
]
}

View File

@ -522,20 +522,38 @@ impl Operation for StandardGate {
}
_ => None,
},
Self::CHGate => match params {
[] => Some(aview2(&gate_matrix::CH_GATE).to_owned()),
_ => None,
},
Self::CPhaseGate => match params {
[Param::Float(lam)] => Some(aview2(&gate_matrix::cp_gate(*lam)).to_owned()),
_ => None,
},
Self::CSGate => match params {
[] => Some(aview2(&gate_matrix::CS_GATE).to_owned()),
_ => None,
},
Self::CSdgGate => match params {
[] => Some(aview2(&gate_matrix::CSDG_GATE).to_owned()),
_ => None,
},
Self::CSXGate => match params {
[] => Some(aview2(&gate_matrix::CSX_GATE).to_owned()),
_ => None,
},
Self::CSwapGate => match params {
[] => Some(aview2(&gate_matrix::CSWAP_GATE).to_owned()),
_ => None,
},
Self::CUGate | Self::CU1Gate | Self::CU3Gate => todo!(),
Self::C3XGate | Self::C3SXGate | Self::C4XGate => 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!(),
Self::CSdgGate => todo!(),
Self::CSXGate => todo!(),
Self::CSwapGate => todo!(),
Self::CUGate | Self::CU1Gate | Self::CU3Gate => todo!(),
Self::C3XGate | Self::C3SXGate | Self::C4XGate => todo!(),
Self::DCXGate => match params {
[] => Some(aview2(&gate_matrix::DCX_GATE).to_owned()),
_ => None,
@ -870,21 +888,6 @@ impl Operation for StandardGate {
)
}),
Self::UGate => None,
Self::SGate => Python::with_gil(|py| -> Option<CircuitData> {
Some(
CircuitData::from_standard_gates(
py,
1,
[(
Self::PhaseGate,
smallvec![Param::Float(PI / 2.)],
smallvec![Qubit(0)],
)],
FLOAT_ZERO,
)
.expect("Unexpected Qiskit python bug"),
)
}),
Self::U1Gate => Python::with_gil(|py| -> Option<CircuitData> {
Some(
CircuitData::from_standard_gates(
@ -900,21 +903,6 @@ impl Operation for StandardGate {
.expect("Unexpected Qiskit python bug"),
)
}),
Self::SdgGate => Python::with_gil(|py| -> Option<CircuitData> {
Some(
CircuitData::from_standard_gates(
py,
1,
[(
Self::PhaseGate,
smallvec![Param::Float(-PI / 2.)],
smallvec![Qubit(0)],
)],
FLOAT_ZERO,
)
.expect("Unexpected Qiskit python bug"),
)
}),
Self::U2Gate => Python::with_gil(|py| -> Option<CircuitData> {
Some(
CircuitData::from_standard_gates(
@ -930,21 +918,6 @@ impl Operation for StandardGate {
.expect("Unexpected Qiskit python bug"),
)
}),
Self::TGate => Python::with_gil(|py| -> Option<CircuitData> {
Some(
CircuitData::from_standard_gates(
py,
1,
[(
Self::PhaseGate,
smallvec![Param::Float(PI / 4.)],
smallvec![Qubit(0)],
)],
FLOAT_ZERO,
)
.expect("Unexpected Qiskit python bug"),
)
}),
Self::U3Gate => Python::with_gil(|py| -> Option<CircuitData> {
Some(
CircuitData::from_standard_gates(
@ -960,6 +933,51 @@ impl Operation for StandardGate {
.expect("Unexpected Qiskit python bug"),
)
}),
Self::SGate => Python::with_gil(|py| -> Option<CircuitData> {
Some(
CircuitData::from_standard_gates(
py,
1,
[(
Self::PhaseGate,
smallvec![Param::Float(PI / 2.)],
smallvec![Qubit(0)],
)],
FLOAT_ZERO,
)
.expect("Unexpected Qiskit python bug"),
)
}),
Self::SdgGate => Python::with_gil(|py| -> Option<CircuitData> {
Some(
CircuitData::from_standard_gates(
py,
1,
[(
Self::PhaseGate,
smallvec![Param::Float(-PI / 2.)],
smallvec![Qubit(0)],
)],
FLOAT_ZERO,
)
.expect("Unexpected Qiskit python bug"),
)
}),
Self::TGate => Python::with_gil(|py| -> Option<CircuitData> {
Some(
CircuitData::from_standard_gates(
py,
1,
[(
Self::PhaseGate,
smallvec![Param::Float(PI / 4.)],
smallvec![Qubit(0)],
)],
FLOAT_ZERO,
)
.expect("Unexpected Qiskit python bug"),
)
}),
Self::TdgGate => Python::with_gil(|py| -> Option<CircuitData> {
Some(
CircuitData::from_standard_gates(
@ -1075,6 +1093,143 @@ impl Operation for StandardGate {
.expect("Unexpected Qiskit python bug"),
)
}),
Self::CHGate => Python::with_gil(|py| -> Option<CircuitData> {
let q1 = smallvec![Qubit(1)];
let q0_1 = smallvec![Qubit(0), Qubit(1)];
Some(
CircuitData::from_standard_gates(
py,
2,
[
(Self::SGate, smallvec![], q1.clone()),
(Self::HGate, smallvec![], q1.clone()),
(Self::TGate, smallvec![], q1.clone()),
(Self::CXGate, smallvec![], q0_1),
(Self::TdgGate, smallvec![], q1.clone()),
(Self::HGate, smallvec![], q1.clone()),
(Self::SdgGate, smallvec![], q1),
],
FLOAT_ZERO,
)
.expect("Unexpected Qiskit python bug"),
)
}),
Self::CPhaseGate => Python::with_gil(|py| -> Option<CircuitData> {
let q0 = smallvec![Qubit(0)];
let q1 = smallvec![Qubit(1)];
let q0_1 = smallvec![Qubit(0), Qubit(1)];
Some(
CircuitData::from_standard_gates(
py,
2,
[
(
Self::PhaseGate,
smallvec![multiply_param(&params[0], 0.5, py)],
q0,
),
(Self::CXGate, smallvec![], q0_1.clone()),
(
Self::PhaseGate,
smallvec![multiply_param(&params[0], -0.5, py)],
q1.clone(),
),
(Self::CXGate, smallvec![], q0_1),
(
Self::PhaseGate,
smallvec![multiply_param(&params[0], 0.5, py)],
q1,
),
],
FLOAT_ZERO,
)
.expect("Unexpected Qiskit python bug"),
)
}),
Self::CSGate => Python::with_gil(|py| -> Option<CircuitData> {
let q0 = smallvec![Qubit(0)];
let q1 = smallvec![Qubit(1)];
let q0_1 = smallvec![Qubit(0), Qubit(1)];
Some(
CircuitData::from_standard_gates(
py,
2,
[
(Self::PhaseGate, smallvec![Param::Float(PI / 4.)], q0),
(Self::CXGate, smallvec![], q0_1.clone()),
(
Self::PhaseGate,
smallvec![Param::Float(-PI / 4.)],
q1.clone(),
),
(Self::CXGate, smallvec![], q0_1),
(Self::PhaseGate, smallvec![Param::Float(PI / 4.)], q1),
],
FLOAT_ZERO,
)
.expect("Unexpected Qiskit python bug"),
)
}),
Self::CSdgGate => Python::with_gil(|py| -> Option<CircuitData> {
let q0 = smallvec![Qubit(0)];
let q1 = smallvec![Qubit(1)];
let q0_1 = smallvec![Qubit(0), Qubit(1)];
Some(
CircuitData::from_standard_gates(
py,
2,
[
(Self::PhaseGate, smallvec![Param::Float(-PI / 4.)], q0),
(Self::CXGate, smallvec![], q0_1.clone()),
(
Self::PhaseGate,
smallvec![Param::Float(PI / 4.)],
q1.clone(),
),
(Self::CXGate, smallvec![], q0_1),
(Self::PhaseGate, smallvec![Param::Float(-PI / 4.)], q1),
],
FLOAT_ZERO,
)
.expect("Unexpected Qiskit python bug"),
)
}),
Self::CSXGate => Python::with_gil(|py| -> Option<CircuitData> {
let q1 = smallvec![Qubit(1)];
let q0_1 = smallvec![Qubit(0), Qubit(1)];
Some(
CircuitData::from_standard_gates(
py,
2,
[
(Self::HGate, smallvec![], q1.clone()),
(Self::CPhaseGate, smallvec![Param::Float(PI / 2.)], q0_1),
(Self::HGate, smallvec![], q1),
],
FLOAT_ZERO,
)
.expect("Unexpected Qiskit python bug"),
)
}),
Self::CSwapGate => Python::with_gil(|py| -> Option<CircuitData> {
Some(
CircuitData::from_standard_gates(
py,
3,
[
(Self::CXGate, smallvec![], smallvec![Qubit(2), Qubit(1)]),
(
Self::CCXGate,
smallvec![],
smallvec![Qubit(0), Qubit(1), Qubit(2)],
),
(Self::CXGate, smallvec![], smallvec![Qubit(2), Qubit(1)]),
],
FLOAT_ZERO,
)
.expect("Unexpected Qiskit python bug"),
)
}),
Self::RGate => Python::with_gil(|py| -> Option<CircuitData> {
let theta_expr = clone_param(&params[0], py);
let phi_expr1 = add_param(&params[1], -PI / 2., py);
@ -1090,12 +1245,6 @@ impl Operation for StandardGate {
.expect("Unexpected Qiskit python bug"),
)
}),
Self::CHGate => todo!(),
Self::CPhaseGate => todo!(),
Self::CSGate => todo!(),
Self::CSdgGate => todo!(),
Self::CSXGate => todo!(),
Self::CSwapGate => todo!(),
Self::CUGate => todo!(),
Self::CU1Gate => todo!(),
Self::CU3Gate => todo!(),
@ -1114,7 +1263,6 @@ impl Operation for StandardGate {
.expect("Unexpected Qiskit python bug"),
)
}),
Self::CCZGate => todo!(),
Self::RCCXGate | Self::RC3XGate => todo!(),
Self::RXXGate => Python::with_gil(|py| -> Option<CircuitData> {

View File

@ -185,6 +185,8 @@ class CHGate(SingletonControlledGate):
\end{pmatrix}
"""
_standard_gate = StandardGate.CHGate
def __init__(
self,
label: Optional[str] = None,

View File

@ -200,6 +200,8 @@ class CPhaseGate(ControlledGate):
phase difference.
"""
_standard_gate = StandardGate.CPhaseGate
def __init__(
self,
theta: ParameterValueType,

View File

@ -215,6 +215,8 @@ class CSGate(SingletonControlledGate):
\end{pmatrix}
"""
_standard_gate = StandardGate.CSGate
def __init__(
self,
label: Optional[str] = None,
@ -301,6 +303,8 @@ class CSdgGate(SingletonControlledGate):
\end{pmatrix}
"""
_standard_gate = StandardGate.CSdgGate
def __init__(
self,
label: Optional[str] = None,

View File

@ -216,6 +216,8 @@ class CSwapGate(SingletonControlledGate):
|1, b, c\rangle \rightarrow |1, c, b\rangle
"""
_standard_gate = StandardGate.CSwapGate
def __init__(
self,
label: Optional[str] = None,

View File

@ -266,6 +266,8 @@ class CSXGate(SingletonControlledGate):
"""
_standard_gate = StandardGate.CSXGate
def __init__(
self,
label: Optional[str] = None,

View File

@ -4516,6 +4516,12 @@ class QuantumCircuit:
Returns:
A handle to the instructions created.
"""
# if the control state is |1> use the fast Rust version of the gate
if ctrl_state is None or ctrl_state in ["1", 1]:
return self._append_standard_gate(
StandardGate.CHGate, [], qargs=[control_qubit, target_qubit], label=label
)
from .library.standard_gates.h import CHGate
return self.append(
@ -4593,6 +4599,12 @@ class QuantumCircuit:
Returns:
A handle to the instructions created.
"""
# if the control state is |1> use the fast Rust version of the gate
if ctrl_state is None or ctrl_state in ["1", 1]:
return self._append_standard_gate(
StandardGate.CPhaseGate, [theta], qargs=[control_qubit, target_qubit], label=label
)
from .library.standard_gates.p import CPhaseGate
return self.append(
@ -4772,14 +4784,14 @@ class QuantumCircuit:
Returns:
A handle to the instructions created.
"""
from .library.standard_gates.rx import CRXGate
# if the control state is |1> use the fast Rust version of the gate
if ctrl_state is None or ctrl_state in ["1", 1]:
return self._append_standard_gate(
StandardGate.CRXGate, [theta], [control_qubit, target_qubit], None, label=label
)
from .library.standard_gates.rx import CRXGate
return self.append(
CRXGate(theta, label=label, ctrl_state=ctrl_state),
[control_qubit, target_qubit],
@ -4845,14 +4857,14 @@ class QuantumCircuit:
Returns:
A handle to the instructions created.
"""
from .library.standard_gates.ry import CRYGate
# if the control state is |1> use the fast Rust version of the gate
if ctrl_state is None or ctrl_state in ["1", 1]:
return self._append_standard_gate(
StandardGate.CRYGate, [theta], [control_qubit, target_qubit], None, label=label
)
from .library.standard_gates.ry import CRYGate
return self.append(
CRYGate(theta, label=label, ctrl_state=ctrl_state),
[control_qubit, target_qubit],
@ -4915,14 +4927,14 @@ class QuantumCircuit:
Returns:
A handle to the instructions created.
"""
from .library.standard_gates.rz import CRZGate
# if the control state is |1> use the fast Rust version of the gate
if ctrl_state is None or ctrl_state in ["1", 1]:
return self._append_standard_gate(
StandardGate.CRZGate, [theta], [control_qubit, target_qubit], None, label=label
)
from .library.standard_gates.rz import CRZGate
return self.append(
CRZGate(theta, label=label, ctrl_state=ctrl_state),
[control_qubit, target_qubit],
@ -4975,9 +4987,7 @@ class QuantumCircuit:
Returns:
A handle to the instructions created.
"""
return self._append_standard_gate(
StandardGate.ECRGate, [], qargs=[qubit1, qubit2], cargs=None
)
return self._append_standard_gate(StandardGate.ECRGate, [], qargs=[qubit1, qubit2])
def s(self, qubit: QubitSpecifier) -> InstructionSet:
"""Apply :class:`~qiskit.circuit.library.SGate`.
@ -4990,7 +5000,7 @@ class QuantumCircuit:
Returns:
A handle to the instructions created.
"""
return self._append_standard_gate(StandardGate.SGate, [], [qubit], cargs=None)
return self._append_standard_gate(StandardGate.SGate, [], qargs=[qubit])
def sdg(self, qubit: QubitSpecifier) -> InstructionSet:
"""Apply :class:`~qiskit.circuit.library.SdgGate`.
@ -5003,7 +5013,7 @@ class QuantumCircuit:
Returns:
A handle to the instructions created.
"""
return self._append_standard_gate(StandardGate.SdgGate, [], [qubit], cargs=None)
return self._append_standard_gate(StandardGate.SdgGate, [], qargs=[qubit])
def cs(
self,
@ -5027,6 +5037,12 @@ class QuantumCircuit:
Returns:
A handle to the instructions created.
"""
# if the control state is |1> use the fast Rust version of the gate
if ctrl_state is None or ctrl_state in ["1", 1]:
return self._append_standard_gate(
StandardGate.CSGate, [], qargs=[control_qubit, target_qubit], label=label
)
from .library.standard_gates.s import CSGate
return self.append(
@ -5058,6 +5074,12 @@ class QuantumCircuit:
Returns:
A handle to the instructions created.
"""
# if the control state is |1> use the fast Rust version of the gate
if ctrl_state is None or ctrl_state in ["1", 1]:
return self._append_standard_gate(
StandardGate.CSdgGate, [], qargs=[control_qubit, target_qubit], label=label
)
from .library.standard_gates.s import CSdgGate
return self.append(
@ -5082,7 +5104,6 @@ class QuantumCircuit:
StandardGate.SwapGate,
[],
qargs=[qubit1, qubit2],
cargs=None,
)
def iswap(self, qubit1: QubitSpecifier, qubit2: QubitSpecifier) -> InstructionSet:
@ -5096,7 +5117,7 @@ class QuantumCircuit:
Returns:
A handle to the instructions created.
"""
return self._append_standard_gate(StandardGate.ISwapGate, [], [qubit1, qubit2], cargs=None)
return self._append_standard_gate(StandardGate.ISwapGate, [], qargs=[qubit1, qubit2])
def cswap(
self,
@ -5122,6 +5143,15 @@ class QuantumCircuit:
Returns:
A handle to the instructions created.
"""
# if the control state is |1> use the fast Rust version of the gate
if ctrl_state is None or ctrl_state in ["1", 1]:
return self._append_standard_gate(
StandardGate.CSwapGate,
[],
qargs=[control_qubit, target_qubit1, target_qubit2],
label=label,
)
from .library.standard_gates.swap import CSwapGate
return self.append(
@ -5142,7 +5172,7 @@ class QuantumCircuit:
Returns:
A handle to the instructions created.
"""
return self._append_standard_gate(StandardGate.SXGate, None, qargs=[qubit])
return self._append_standard_gate(StandardGate.SXGate, [], qargs=[qubit])
def sxdg(self, qubit: QubitSpecifier) -> InstructionSet:
"""Apply :class:`~qiskit.circuit.library.SXdgGate`.
@ -5155,7 +5185,7 @@ class QuantumCircuit:
Returns:
A handle to the instructions created.
"""
return self._append_standard_gate(StandardGate.SXdgGate, None, qargs=[qubit])
return self._append_standard_gate(StandardGate.SXdgGate, [], qargs=[qubit])
def csx(
self,
@ -5179,6 +5209,12 @@ class QuantumCircuit:
Returns:
A handle to the instructions created.
"""
# if the control state is |1> use the fast Rust version of the gate
if ctrl_state is None or ctrl_state in ["1", 1]:
return self._append_standard_gate(
StandardGate.CSXGate, [], qargs=[control_qubit, target_qubit], label=label
)
from .library.standard_gates.sx import CSXGate
return self.append(
@ -5199,7 +5235,7 @@ class QuantumCircuit:
Returns:
A handle to the instructions created.
"""
return self._append_standard_gate(StandardGate.TGate, [], [qubit], cargs=None)
return self._append_standard_gate(StandardGate.TGate, [], qargs=[qubit])
def tdg(self, qubit: QubitSpecifier) -> InstructionSet:
"""Apply :class:`~qiskit.circuit.library.TdgGate`.
@ -5212,7 +5248,7 @@ class QuantumCircuit:
Returns:
A handle to the instructions created.
"""
return self._append_standard_gate(StandardGate.TdgGate, [], [qubit], cargs=None)
return self._append_standard_gate(StandardGate.TdgGate, [], qargs=[qubit])
def u(
self,
@ -5311,17 +5347,23 @@ class QuantumCircuit:
Returns:
A handle to the instructions created.
"""
if ctrl_state is not None:
from .library.standard_gates.x import CXGate
return self.append(
CXGate(label=label, ctrl_state=ctrl_state),
[control_qubit, target_qubit],
# if the control state is |1> use the fast Rust version of the gate
if ctrl_state is None or ctrl_state in ["1", 1]:
return self._append_standard_gate(
StandardGate.CXGate,
[],
copy=False,
qargs=[control_qubit, target_qubit],
cargs=None,
label=label,
)
return self._append_standard_gate(
StandardGate.CXGate, [], qargs=[control_qubit, target_qubit], cargs=None, label=label
from .library.standard_gates.x import CXGate
return self.append(
CXGate(label=label, ctrl_state=ctrl_state),
[control_qubit, target_qubit],
[],
copy=False,
)
def dcx(self, qubit1: QubitSpecifier, qubit2: QubitSpecifier) -> InstructionSet:
@ -5360,20 +5402,22 @@ class QuantumCircuit:
Returns:
A handle to the instructions created.
"""
if ctrl_state is not None:
from .library.standard_gates.x import CCXGate
return self.append(
CCXGate(ctrl_state=ctrl_state),
[control_qubit1, control_qubit2, target_qubit],
# if the control state is |1> use the fast Rust version of the gate
if ctrl_state is None or ctrl_state in ["1", 1]:
return self._append_standard_gate(
StandardGate.CCXGate,
[],
copy=False,
qargs=[control_qubit1, control_qubit2, target_qubit],
cargs=None,
)
return self._append_standard_gate(
StandardGate.CCXGate,
from .library.standard_gates.x import CCXGate
return self.append(
CCXGate(ctrl_state=ctrl_state),
[control_qubit1, control_qubit2, target_qubit],
[],
qargs=[control_qubit1, control_qubit2, target_qubit],
cargs=None,
copy=False,
)
def mcx(
@ -5495,18 +5539,23 @@ class QuantumCircuit:
Returns:
A handle to the instructions created.
"""
if ctrl_state is not None:
from .library.standard_gates.y import CYGate
return self.append(
CYGate(label=label, ctrl_state=ctrl_state),
[control_qubit, target_qubit],
# if the control state is |1> use the fast Rust version of the gate
if ctrl_state is None or ctrl_state in ["1", 1]:
return self._append_standard_gate(
StandardGate.CYGate,
[],
copy=False,
qargs=[control_qubit, target_qubit],
cargs=None,
label=label,
)
return self._append_standard_gate(
StandardGate.CYGate, [], qargs=[control_qubit, target_qubit], cargs=None, label=label
from .library.standard_gates.y import CYGate
return self.append(
CYGate(label=label, ctrl_state=ctrl_state),
[control_qubit, target_qubit],
[],
copy=False,
)
def z(self, qubit: QubitSpecifier) -> InstructionSet:
@ -5544,18 +5593,19 @@ class QuantumCircuit:
Returns:
A handle to the instructions created.
"""
if ctrl_state is not None:
from .library.standard_gates.z import CZGate
return self.append(
CZGate(label=label, ctrl_state=ctrl_state),
[control_qubit, target_qubit],
[],
copy=False,
# if the control state is |1> use the fast Rust version of the gate
if ctrl_state is None or ctrl_state in ["1", 1]:
return self._append_standard_gate(
StandardGate.CZGate, [], qargs=[control_qubit, target_qubit], label=label
)
return self._append_standard_gate(
StandardGate.CZGate, [], qargs=[control_qubit, target_qubit], cargs=None, label=label
from .library.standard_gates.z import CZGate
return self.append(
CZGate(label=label, ctrl_state=ctrl_state),
[control_qubit, target_qubit],
[],
copy=False,
)
def ccz(

View File

@ -73,6 +73,7 @@ class TestRustGateEquivalence(QiskitTestCase):
self.assertIsNone(rs_def)
else:
rs_def = QuantumCircuit._from_circuit_data(rs_def)
for rs_inst, py_inst in zip(rs_def._data, py_def._data):
# Rust uses U but python still uses U3 and u2
if rs_inst.operation.name == "u":
@ -92,8 +93,8 @@ class TestRustGateEquivalence(QiskitTestCase):
[py_def.find_bit(x).index for x in py_inst.qubits],
[rs_def.find_bit(x).index for x in rs_inst.qubits],
)
# Rust uses P but python still uses u1
elif rs_inst.operation.name == "p":
# Rust uses p but python still uses u1/u3 in some cases
elif rs_inst.operation.name == "p" and not name in ["cp", "cs", "csdg"]:
if py_inst.operation.name == "u1":
self.assertEqual(py_inst.operation.name, "u1")
self.assertEqual(rs_inst.operation.params, py_inst.operation.params)
@ -110,7 +111,14 @@ class TestRustGateEquivalence(QiskitTestCase):
[py_def.find_bit(x).index for x in py_inst.qubits],
[rs_def.find_bit(x).index for x in rs_inst.qubits],
)
# Rust uses cp but python still uses cu1 in some cases
elif rs_inst.operation.name == "cp":
self.assertEqual(py_inst.operation.name, "cu1")
self.assertEqual(rs_inst.operation.params, py_inst.operation.params)
self.assertEqual(
[py_def.find_bit(x).index for x in py_inst.qubits],
[rs_def.find_bit(x).index for x in rs_inst.qubits],
)
else:
self.assertEqual(py_inst.operation.name, rs_inst.operation.name)
self.assertEqual(rs_inst.operation.params, py_inst.operation.params)