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
12 changes: 12 additions & 0 deletions crates/pecos-core/src/gate_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ pub enum GateType {
// MZ = 104
Measure = 104,
// MnZ = 105
MeasureLeaked = 105,
// TODO: MPauli instead of the other variants?

// PX = 130
Expand Down Expand Up @@ -104,6 +105,7 @@ impl From<u8> for GateType {
58 => GateType::SZZdg,
82 => GateType::RZZ,
104 => GateType::Measure,
105 => GateType::MeasureLeaked,
134 => GateType::Prep,
200 => GateType::Idle,
_ => panic!("Invalid gate type ID: {value}"),
Expand Down Expand Up @@ -134,6 +136,7 @@ impl GateType {
| GateType::SZZ
| GateType::SZZdg
| GateType::Measure
| GateType::MeasureLeaked
| GateType::Prep => 0,

// Gates with one parameter
Expand Down Expand Up @@ -170,6 +173,7 @@ impl GateType {
| GateType::R1XY
| GateType::U
| GateType::Measure
| GateType::MeasureLeaked
| GateType::Prep
| GateType::Idle => 1,

Expand Down Expand Up @@ -217,6 +221,7 @@ impl fmt::Display for GateType {
GateType::SZZdg => write!(f, "SZZdg"),
GateType::RZZ => write!(f, "RZZ"),
GateType::Measure => write!(f, "Measure"),
GateType::MeasureLeaked => write!(f, "MeasureLeaked"),
GateType::Prep => write!(f, "Prep"),
GateType::Idle => write!(f, "Idle"),
}
Expand All @@ -239,6 +244,7 @@ mod tests {
assert_eq!(GateType::RZ as u8, 32);
assert_eq!(GateType::R1XY as u8, 36);
assert_eq!(GateType::Measure as u8, 104);
assert_eq!(GateType::MeasureLeaked as u8, 105);

assert_eq!(GateType::from(0u8), GateType::I);
assert_eq!(GateType::from(1u8), GateType::X);
Expand All @@ -250,6 +256,7 @@ mod tests {
assert_eq!(GateType::from(32u8), GateType::RZ);
assert_eq!(GateType::from(36u8), GateType::R1XY);
assert_eq!(GateType::from(104u8), GateType::Measure);
assert_eq!(GateType::from(105u8), GateType::MeasureLeaked);
}

#[test]
Expand All @@ -264,6 +271,7 @@ mod tests {
assert_eq!(GateType::SZZ.classical_arity(), 0);
assert_eq!(GateType::SZZdg.classical_arity(), 0);
assert_eq!(GateType::Measure.classical_arity(), 0);
assert_eq!(GateType::MeasureLeaked.classical_arity(), 0);
assert_eq!(GateType::Prep.classical_arity(), 0);

// Gates with one parameter
Expand All @@ -290,6 +298,7 @@ mod tests {
assert_eq!(GateType::R1XY.quantum_arity(), 1);
assert_eq!(GateType::U.quantum_arity(), 1);
assert_eq!(GateType::Measure.quantum_arity(), 1);
assert_eq!(GateType::MeasureLeaked.quantum_arity(), 1);
assert_eq!(GateType::Prep.quantum_arity(), 1);
assert_eq!(GateType::Idle.quantum_arity(), 1);

Expand All @@ -312,6 +321,7 @@ mod tests {
assert!(!GateType::SZZ.is_parameterized());
assert!(!GateType::SZZdg.is_parameterized());
assert!(!GateType::Measure.is_parameterized());
assert!(!GateType::MeasureLeaked.is_parameterized());
assert!(!GateType::Prep.is_parameterized());

// Parameterized gates
Expand All @@ -334,6 +344,7 @@ mod tests {
assert!(GateType::R1XY.is_single_qubit());
assert!(GateType::U.is_single_qubit());
assert!(GateType::Measure.is_single_qubit());
assert!(GateType::MeasureLeaked.is_single_qubit());
assert!(GateType::Prep.is_single_qubit());
assert!(GateType::Idle.is_single_qubit());

Expand All @@ -356,6 +367,7 @@ mod tests {
assert!(!GateType::R1XY.is_two_qubit());
assert!(!GateType::U.is_two_qubit());
assert!(!GateType::Measure.is_two_qubit());
assert!(!GateType::MeasureLeaked.is_two_qubit());
assert!(!GateType::Prep.is_two_qubit());
assert!(!GateType::Idle.is_two_qubit());

Expand Down
10 changes: 10 additions & 0 deletions crates/pecos-core/src/gates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,16 @@ impl Gate {
)
}

/// Create `MeasureLeaked` gate on multiple qubits
#[must_use]
pub fn measure_leaked(qubits: &[impl Into<QubitId> + Copy]) -> Self {
Self::new(
GateType::MeasureLeaked,
vec![],
qubits.iter().map(|&q| q.into()).collect(),
)
}

/// Create Prep gate on multiple qubits
#[must_use]
pub fn prep(qubits: &[impl Into<QubitId> + Copy]) -> Self {
Expand Down
42 changes: 42 additions & 0 deletions crates/pecos-engines/src/byte_message/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,24 @@ impl ByteMessageBuilder {
self
}

/// Add measure leakage operations for multiple qubits
///
/// This behaves like `add_measurements()` but is intended for measuring qubits
/// that may be in a leaked state. In the future, this will output 0, 1, or 2
/// (where 2 indicates the qubit is leaked).
///
/// # Panics
///
/// Panics if any qubit ID is too large to fit in a u32.
pub fn add_measure_leakages(&mut self, qubit_ids: &[usize]) -> &mut Self {
for &qubit in qubit_ids {
// Add a measure_leaked as a regular gate command
let gate = Gate::measure_leaked(&[qubit]);
self.add_gate_command(&gate);
}
self
}

/// Add a Prep gate
pub fn add_prep(&mut self, qubits: &[usize]) -> &mut Self {
let gate = Gate::prep(qubits);
Expand Down Expand Up @@ -732,6 +750,30 @@ mod tests {
}
}

#[test]
fn test_add_measure_leakages() {
// Create a builder
let mut builder = ByteMessageBuilder::new();
let _ = builder.for_quantum_operations();

// Add measure_leakages for multiple qubits
let qubits = vec![0, 1, 2];
builder.add_measure_leakages(&qubits);

// Build the message
let message = builder.build();

// Parse the message
let commands = message.quantum_ops().unwrap();

// Verify the commands
assert_eq!(commands.len(), 3);
for i in 0..3 {
assert_eq!(commands[i].gate_type, GateType::MeasureLeaked);
assert_eq!(commands[i].qubits, vec![QubitId(qubits[i])]);
}
}

#[test]
fn test_batch_structure() {
// Create a builder
Expand Down
2 changes: 1 addition & 1 deletion crates/pecos-engines/src/noise/biased_depolarizing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ impl BiasedDepolarizingNoiseModel {
trace!("Applying two-qubit gate with possible fault");
self.apply_tq_faults(&mut builder, gate);
}
GateType::Measure => {
GateType::Measure | GateType::MeasureLeaked => {
trace!("Applying measurement. Will apply bias after engine returns results.");
// we apply biased measurement after the engine
// returns the results, rather than before measurement
Expand Down
2 changes: 1 addition & 1 deletion crates/pecos-engines/src/noise/depolarizing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ impl DepolarizingNoiseModel {
GateType::RZ => {
NoiseUtils::add_gate_to_builder(&mut builder, gate);
}
GateType::Measure => {
GateType::Measure | GateType::MeasureLeaked => {
trace!("Applying measurement with possible fault");
self.apply_meas_faults(&mut builder, gate);
NoiseUtils::add_gate_to_builder(&mut builder, gate);
Expand Down
Loading
Loading