#[derive(Debug, Clone, PartialEq)]
pub(crate) enum QasmInstruction {
BitRegisterDeclaration(usize),
GateDeclaration(String),
MeasurementDeclaration(String),
RawQASM(String),
StartMeasurementGroup,
}
pub(crate) struct QasmCircuit {
pub(crate) instructions: Vec<QasmInstruction>,
pub(crate) num_qubits: usize,
}
impl QasmCircuit {
pub(crate) fn new(instructions: Vec<QasmInstruction>, num_qubits: usize) -> Self {
QasmCircuit {
instructions,
num_qubits,
}
}
pub(crate) fn to_qasm_string(&self) -> String {
let mut header = String::new();
let mut body = String::new();
header.push_str("OPENQASM 3.0;\n");
header.push_str("include \"stdgates.inc\";\n");
header.push_str("def xmeasure(qubit q) -> bit { h q; return measure q; } // Defines x-basis measurement\n");
header.push_str("def ymeasure(qubit q) -> bit { h q; s q; return measure q; } // Defines y-basis measurement\n");
header.push_str("// Generated by QuantIron's QASM Compiler\n\n");
header.push_str(&format!("qubit[{}] q; // Main register\n\n", self.num_qubits));
let mut measurement_register_idx = -1;
let mut measurement_bit_idx = 0;
let mut measurement_idx = 0;
for instruction in self.instructions.iter() {
match instruction {
QasmInstruction::BitRegisterDeclaration(len) => {
header.push_str(&format!("bit[{}] m{}; // Measurement result for measurement {}\n", len, measurement_idx, measurement_idx));
measurement_idx += 1;
}
QasmInstruction::GateDeclaration(gate) => {
if !body.is_empty() && !body.ends_with('\n') {
body.push('\n');
}
body.push_str(gate.trim());
body.push('\n');
}
QasmInstruction::MeasurementDeclaration(measurement_str) => {
body.push_str(&format!(
"m{}[{}] = {};\n",
measurement_register_idx, measurement_bit_idx, measurement_str
));
measurement_bit_idx += 1;
}
QasmInstruction::RawQASM(raw) => {
body.push_str(&format!("\n{}", raw.trim()));
}
QasmInstruction::StartMeasurementGroup => {
measurement_register_idx += 1;
measurement_bit_idx = 0;
if !body.is_empty() && !body.ends_with("\n\n") {
body.push('\n');
}
body.push_str(&format!("// Measurement {}\n", measurement_register_idx));
}
}
}
let mut final_header = header.trim_end().to_string();
if !body.is_empty() {
final_header.push_str("\n\n");
}
format!("{}{}", final_header, body.trim_start()).trim().to_string()
}
}