Skip to content
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
3 changes: 3 additions & 0 deletions .typos.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ typ = "typ"
# These are operation names in HUGR/Guppy integer operations
ine = "ine" # Integer not equal operation
inot = "inot" # Integer bitwise NOT operation
# Float comparison operation (float less-than-or-equal)
fle = "fle"
Fle = "Fle"
# QuEST v4.1.0 uses "calcExpec" (not "calcExpect") in function names
Expec = "Expec"
# NumPy uses "arange" (array range), not "arrange"
Expand Down
41 changes: 38 additions & 3 deletions crates/pecos-core/src/gate_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,23 @@ pub enum GateType {
// SYYdg = 56
SZZ = 57,
SZZdg = 58,
// SWAP = 59
SWAP = 59,
// iSWAP = 60
// G = 61
/// Controlled-RZ gate (2 qubits, 1 angle parameter)
CRZ = 70,

// RXX = 80
// RYY = 81
RZZ = 82,
// RXXYYZZ
/// Toffoli gate (CCX, 3 qubits)
CCX = 90,

/// Square root of X gate (also known as V gate)
SX = 24,
/// Inverse of square root of X gate (also known as Vdg gate)
SXdg = 25,

// MX = 100
// MnX = 101
Expand Down Expand Up @@ -109,12 +118,17 @@ impl From<u8> for GateType {
34 => GateType::Tdg,
35 => GateType::U,
36 => GateType::R1XY,
24 => GateType::SX,
25 => GateType::SXdg,
50 => GateType::CX,
51 => GateType::CY,
52 => GateType::CZ,
57 => GateType::SZZ,
58 => GateType::SZZdg,
59 => GateType::SWAP,
70 => GateType::CRZ,
82 => GateType::RZZ,
90 => GateType::CCX,
104 => GateType::Measure,
105 => GateType::MeasureLeaked,
106 => GateType::MeasureFree,
Expand Down Expand Up @@ -148,11 +162,15 @@ impl GateType {
| GateType::H
| GateType::T
| GateType::Tdg
| GateType::SX
| GateType::SXdg
| GateType::CX
| GateType::CY
| GateType::CZ
| GateType::SZZ
| GateType::SZZdg
| GateType::SWAP
| GateType::CCX
| GateType::Measure
| GateType::MeasureLeaked
| GateType::MeasureFree
Expand All @@ -163,7 +181,12 @@ impl GateType {
| GateType::QFree => 0,

// Gates with one parameter
GateType::RX | GateType::RY | GateType::RZ | GateType::RZZ | GateType::Idle => 1,
GateType::RX
| GateType::RY
| GateType::RZ
| GateType::RZZ
| GateType::CRZ
| GateType::Idle => 1,

// Gates with two parameters
GateType::R1XY => 2,
Expand Down Expand Up @@ -195,6 +218,8 @@ impl GateType {
| GateType::RZ
| GateType::T
| GateType::Tdg
| GateType::SX
| GateType::SXdg
| GateType::R1XY
| GateType::U
| GateType::Measure
Expand All @@ -213,7 +238,12 @@ impl GateType {
| GateType::CZ
| GateType::SZZ
| GateType::SZZdg
| GateType::SWAP
| GateType::CRZ
| GateType::RZZ => 2,

// Three-qubit gates
GateType::CCX => 3,
}
}

Expand All @@ -225,7 +255,7 @@ impl GateType {
pub const fn angle_arity(self) -> usize {
match self {
// Rotation gates with angle parameters
GateType::RX | GateType::RY | GateType::RZ | GateType::RZZ => 1,
GateType::RX | GateType::RY | GateType::RZ | GateType::RZZ | GateType::CRZ => 1,
GateType::R1XY => 2,
GateType::U => 3,
// All other gates have no angle parameters
Expand Down Expand Up @@ -278,12 +308,17 @@ impl fmt::Display for GateType {
GateType::Tdg => write!(f, "Tdg"),
GateType::U => write!(f, "U"),
GateType::R1XY => write!(f, "R1XY"),
GateType::SX => write!(f, "SX"),
GateType::SXdg => write!(f, "SXdg"),
GateType::CX => write!(f, "CX"),
GateType::CY => write!(f, "CY"),
GateType::CZ => write!(f, "CZ"),
GateType::SZZ => write!(f, "SZZ"),
GateType::SZZdg => write!(f, "SZZdg"),
GateType::SWAP => write!(f, "SWAP"),
GateType::CRZ => write!(f, "CRZ"),
GateType::RZZ => write!(f, "RZZ"),
GateType::CCX => write!(f, "CCX"),
GateType::Measure => write!(f, "Measure"),
GateType::MeasureLeaked => write!(f, "MeasureLeaked"),
GateType::MeasureFree => write!(f, "MeasureFree"),
Expand Down
12 changes: 11 additions & 1 deletion crates/pecos-engines/src/noise/biased_depolarizing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ impl BiasedDepolarizingNoiseModel {
| GateType::Z
| GateType::SZ
| GateType::SZdg
| GateType::SX
| GateType::SXdg
| GateType::H
| GateType::T
| GateType::Tdg
Expand All @@ -178,11 +180,19 @@ impl BiasedDepolarizingNoiseModel {
| GateType::CZ
| GateType::RZZ
| GateType::SZZ
| GateType::SZZdg => {
| GateType::SZZdg
| GateType::SWAP
| GateType::CRZ => {
NoiseUtils::add_gate_to_builder(&mut builder, gate);
trace!("Applying two-qubit gate with possible fault");
self.apply_tq_faults(&mut builder, gate);
}
GateType::CCX => {
NoiseUtils::add_gate_to_builder(&mut builder, gate);
trace!("Applying three-qubit gate with possible fault");
// Apply fault to each qubit pair (treat as three two-qubit interactions)
self.apply_tq_faults(&mut builder, gate);
}
GateType::Measure | GateType::MeasureLeaked | GateType::MeasureFree => {
trace!("Applying measurement. Will apply bias after engine returns results.");
// we apply biased measurement after the engine
Expand Down
12 changes: 11 additions & 1 deletion crates/pecos-engines/src/noise/depolarizing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ impl DepolarizingNoiseModel {
| GateType::Z
| GateType::SZ
| GateType::SZdg
| GateType::SX
| GateType::SXdg
| GateType::H
| GateType::T
| GateType::Tdg
Expand All @@ -183,11 +185,19 @@ impl DepolarizingNoiseModel {
| GateType::CZ
| GateType::RZZ
| GateType::SZZ
| GateType::SZZdg => {
| GateType::SZZdg
| GateType::SWAP
| GateType::CRZ => {
NoiseUtils::add_gate_to_builder(&mut builder, gate);
trace!("Applying two-qubit gate with possible fault");
self.apply_tq_faults(&mut builder, gate);
}
GateType::CCX => {
NoiseUtils::add_gate_to_builder(&mut builder, gate);
trace!("Applying three-qubit gate with possible fault");
// Apply fault to each qubit pair
self.apply_tq_faults(&mut builder, gate);
}
GateType::RZ => {
NoiseUtils::add_gate_to_builder(&mut builder, gate);
}
Expand Down
92 changes: 92 additions & 0 deletions crates/pecos-engines/src/quantum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,18 @@ impl Engine for StateVecEngine {
self.simulator.szdg(usize::from(*q));
}
}
GateType::SX => {
for q in &cmd.qubits {
debug!("Processing SX gate on qubit {q:?}");
self.simulator.sx(usize::from(*q));
}
}
GateType::SXdg => {
for q in &cmd.qubits {
debug!("Processing SXdg gate on qubit {q:?}");
self.simulator.sxdg(usize::from(*q));
}
}
GateType::T => {
for q in &cmd.qubits {
debug!("Processing T gate on qubit {q:?}");
Expand Down Expand Up @@ -276,6 +288,86 @@ impl Engine for StateVecEngine {
.szzdg(usize::from(qubits[0]), usize::from(qubits[1]));
}
}
GateType::SWAP => {
if cmd.qubits.len() % 2 != 0 {
return Err(quantum_error(format!(
"SWAP gate requires even number of qubits, got {}",
cmd.qubits.len()
)));
}
for qubits in cmd.qubits.chunks_exact(2) {
debug!(
"Processing SWAP gate on qubits {:?} and {:?}",
qubits[0], qubits[1]
);
// SWAP = CX(0,1) CX(1,0) CX(0,1)
let q0 = usize::from(qubits[0]);
let q1 = usize::from(qubits[1]);
self.simulator.cx(q0, q1);
self.simulator.cx(q1, q0);
self.simulator.cx(q0, q1);
}
}
GateType::CRZ => {
if cmd.qubits.len() % 2 != 0 {
return Err(quantum_error(format!(
"CRZ gate requires even number of qubits, got {}",
cmd.qubits.len()
)));
}
if cmd.angles.is_empty() {
return Err(quantum_error("CRZ gate requires at least one angle"));
}
let angle = cmd.angles[0].to_radians();
let half_angle = angle / 2.0;
for qubits in cmd.qubits.chunks_exact(2) {
debug!(
"Processing CRZ gate on qubits {:?} and {:?} with angle {:?}",
qubits[0], qubits[1], angle
);
// CRZ(θ) = Rz(θ/2) on target, CX, Rz(-θ/2) on target, CX
let control = usize::from(qubits[0]);
let target = usize::from(qubits[1]);
self.simulator.rz(half_angle, target);
self.simulator.cx(control, target);
self.simulator.rz(-half_angle, target);
self.simulator.cx(control, target);
}
}
GateType::CCX => {
if cmd.qubits.len() % 3 != 0 {
return Err(quantum_error(format!(
"CCX gate requires a multiple of 3 qubits, got {}",
cmd.qubits.len()
)));
}
for qubits in cmd.qubits.chunks_exact(3) {
debug!(
"Processing CCX gate with controls {:?}, {:?} and target {:?}",
qubits[0], qubits[1], qubits[2]
);
// Toffoli decomposition into Clifford+T gates
let c0 = usize::from(qubits[0]);
let c1 = usize::from(qubits[1]);
let target = usize::from(qubits[2]);
// Standard decomposition (15 gates)
self.simulator.h(target);
self.simulator.cx(c1, target);
self.simulator.tdg(target);
self.simulator.cx(c0, target);
self.simulator.t(target);
self.simulator.cx(c1, target);
self.simulator.tdg(target);
self.simulator.cx(c0, target);
self.simulator.t(c1);
self.simulator.t(target);
self.simulator.cx(c0, c1);
self.simulator.h(target);
self.simulator.t(c0);
self.simulator.tdg(c1);
self.simulator.cx(c0, c1);
}
}
GateType::RX => {
if !cmd.angles.is_empty() {
let angle = cmd.angles[0].to_radians();
Expand Down
7 changes: 6 additions & 1 deletion crates/pecos-experimental/src/hugr_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,12 @@ where
| GateType::R1XY
| GateType::SZZ
| GateType::SZZdg
| GateType::RZZ => {
| GateType::RZZ
| GateType::SWAP
| GateType::CRZ
| GateType::CCX
| GateType::SX
| GateType::SXdg => {
return Err(HugrExecutionError::UnsupportedGate {
gate_type: gate.gate_type,
gate_index: gate_idx,
Expand Down
Loading
Loading