Skip to content

Commit

Permalink
Rename "m" to "rec" in qasm output
Browse files Browse the repository at this point in the history
Fix decomp check handling resets wrong
  • Loading branch information
Strilanc committed Nov 19, 2023
1 parent a6eb117 commit 24f978f
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 69 deletions.
6 changes: 3 additions & 3 deletions src/stim/circuit/circuit.pybind.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1432,14 +1432,14 @@ void stim_pybind::pybind_circuit_methods(pybind11::module &, pybind11::class_<Ci
OPENQASM 3.0;
include "stdgates.inc";
qubit q[2];
bit m[2];
bit rec[2];
bit dets[1];
reset q[0];
reset q[1];
h q[0];
cx q[0], q[1];
measure q[0] -> m[0];
measure q[1] -> m[1];
measure q[0] -> rec[0];
measure q[1] -> rec[1];
dets[0] = rec[1] ^ rec[0] ^ 0;
)DOC")
.data());
Expand Down
10 changes: 5 additions & 5 deletions src/stim/circuit/export_qasm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ static void do_qasm_decompose_mpp(
out << "cx q[" << t1.qubit_value() << "],q[" << t2.qubit_value() << "];";
}
for (auto t : meas.targets) {
out << "measure q[" << t.qubit_value() << "] -> m[" << measurement_offset << "];";
out << "measure q[" << t.qubit_value() << "] -> rec[" << measurement_offset << "];";
measurement_offset++;
}
for (size_t k = 0; k < cnot.targets.size(); k += 2) {
Expand Down Expand Up @@ -141,15 +141,15 @@ static void qasm_output_decomposed_inline(
q1 << "q[" << t1.qubit_value() << "]";
if (f & GATE_PRODUCES_RESULTS) {
m.str("");
m << "m[" << measurement_offset << "]";
m << "rec[" << measurement_offset << "]";
measurement_offset++;
}
do_decomposed(
instruction.gate_type, q0.str().data(), q1.str().data(), m.str().data(), out);
out << " // decomposed " << GATE_DATA[instruction.gate_type].name << "\n";
} else {
if (f & GATE_PRODUCES_RESULTS) {
out << "m[" << measurement_offset << "] = ";
out << "rec[" << measurement_offset << "] = ";
measurement_offset++;
}
out << qasm_names[(int)instruction.gate_type] << "(";
Expand Down Expand Up @@ -404,7 +404,7 @@ void stim::export_open_qasm(const Circuit &circuit, std::ostream &out, int open_
out << qubit_decl << " q[" << stats.num_qubits << "];\n";
}
if (stats.num_measurements > 0) {
out << bit_decl << " m[" << stats.num_measurements << "];\n";
out << bit_decl << " rec[" << stats.num_measurements << "];\n";
}
if (stats.num_detectors > 0 && !skip_dets_and_obs) {
out << bit_decl << " dets[" << stats.num_detectors << "];\n";
Expand Down Expand Up @@ -444,7 +444,7 @@ void stim::export_open_qasm(const Circuit &circuit, std::ostream &out, int open_

case GateType::M:
for (const auto &t : instruction.targets) {
out << "measure q[" << t.qubit_value() << "] -> m[" << measurement_offset << "];\n";
out << "measure q[" << t.qubit_value() << "] -> rec[" << measurement_offset << "];\n";
measurement_offset++;
}
return;
Expand Down
114 changes: 57 additions & 57 deletions src/stim/circuit/export_qasm.test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ include "stdgates.inc";
gate cxyz q0 { U(pi/2, 0, pi/2) q0; }
qubit q[2];
bit m[1];
bit rec[1];
bit sweep[6];
h q[0];
cx q[0], q[1];
cxyz q[1];
measure q[0] -> m[0];
measure q[0] -> rec[0];
if (ms[0]) {
X q[1];
}
Expand Down Expand Up @@ -77,7 +77,7 @@ TEST(export_circuit, export_open_qasm_qec) {
include "stdgates.inc";
qubit q[3];
bit m[4];
bit rec[4];
bit dets[3];
bit obs[1];
Expand All @@ -95,7 +95,7 @@ barrier q;
cx q[2], q[1];
barrier q;
measure q[1] -> m[0];
measure q[1] -> rec[0];
dets[0] = rec[0] ^ 1;
barrier q;
Expand All @@ -108,9 +108,9 @@ barrier q;
cx q[2], q[1];
barrier q;
measure q[0] -> m[1];
measure q[1] -> m[2];
measure q[2] -> m[3];
measure q[0] -> rec[1];
measure q[1] -> rec[2];
measure q[2] -> rec[3];
dets[1] = rec[2] ^ rec[0] ^ 0;
dets[2] = rec[3] ^ rec[2] ^ rec[1] ^ 0;
obs[0] = obs[0] ^ rec[3] ^ 0;
Expand All @@ -123,7 +123,7 @@ obs[0] = obs[0] ^ rec[3] ^ 0;
include "qelib1.inc";
qreg q[3];
creg m[4];
creg rec[4];
reset q[0];
reset q[1];
Expand All @@ -139,7 +139,7 @@ barrier q;
cx q[2], q[1];
barrier q;
measure q[1] -> m[0];
measure q[1] -> rec[0];
barrier q;
reset q[1];
Expand All @@ -151,9 +151,9 @@ barrier q;
cx q[2], q[1];
barrier q;
measure q[0] -> m[1];
measure q[1] -> m[2];
measure q[2] -> m[3];
measure q[0] -> rec[1];
measure q[1] -> rec[2];
measure q[2] -> rec[3];
)QASM");
}

Expand Down Expand Up @@ -185,22 +185,22 @@ def rx(qubit q0) { reset q0; h q0; }
def mxx(qubit q0, qubit q1) -> bit { bit b; cx q0, q1; h q0; measure q0 -> b; h q0; cx q0, q1; return b; }
qubit q[5];
bit m[5];
bit rec[5];
bit dets[1];
reset q[3];
rx(q[0]);
rx(q[1]);
m[0] = mx(q[2]);
rec[0] = mx(q[2]);
barrier q;
m[1] = mxx(q[0], q[1]);
rec[1] = mxx(q[0], q[1]);
dets[0] = rec[1] ^ 0;
barrier q;
measure q[2] -> m[2];
m[3] = mr(q[3]);
m[4] = mrx(q[4]);
measure q[2] -> rec[2];
rec[3] = mr(q[3]);
rec[4] = mrx(q[4]);
)QASM");

out.str("");
Expand All @@ -210,27 +210,26 @@ m[4] = mrx(q[4]);
include "qelib1.inc";
qreg q[5];
creg m[5];
creg rec[5];
reset q[3];
reset q[0]; h q[0]; // decomposed RX
reset q[1]; h q[1]; // decomposed RX
h q[2]; measure q[2] -> m[0]; h q[2]; // decomposed MX
h q[2]; measure q[2] -> rec[0]; h q[2]; // decomposed MX
barrier q;
cx q[0], q[1]; h q[0]; measure q[0] -> m[1]; h q[0]; cx q[0], q[1]; // decomposed MXX
cx q[0], q[1]; h q[0]; measure q[0] -> rec[1]; h q[0]; cx q[0], q[1]; // decomposed MXX
barrier q;
measure q[2] -> m[2];
measure q[3] -> m[3]; reset q[3]; // decomposed MR
h q[4]; measure q[4] -> m[4]; reset q[4]; h q[4]; // decomposed MRX
measure q[2] -> rec[2];
measure q[3] -> rec[3]; reset q[3]; // decomposed MR
h q[4]; measure q[4] -> rec[4]; reset q[4]; h q[4]; // decomposed MRX
)QASM");
}

TEST(export_circuit, export_qasm_all_operations) {
Circuit c = generate_test_circuit_with_all_operations();
c = c.without_noise();
c = circuit_with_inlined_feedback(c);

std::stringstream out;
export_open_qasm(c, out, 3, false);
Expand Down Expand Up @@ -271,7 +270,7 @@ def myy(qubit q0, qubit q1) -> bit { bit b; s q0; s q1; cx q0, q1; h q0; measure
def mzz(qubit q0, qubit q1) -> bit { bit b; cx q0, q1; measure q1 -> b; cx q0, q1; return b; }
qubit q[18];
bit m[20];
bit rec[20];
bit dets[1];
bit obs[1];
Expand Down Expand Up @@ -318,24 +317,24 @@ barrier q;
barrier q;
h q[0];sx q[1];cx q[1],q[0];cx q[2],q[0];measure q[0] -> m[2];cx q[1],q[0];cx q[2],q[0];sxdg q[1];h q[0]; // decomposed MPP
cx q[1],q[0];measure q[0] -> m[3];cx q[1],q[0]; // decomposed MPP
m[4] = mrx(q[0]);
m[5] = mry(q[1]);
m[6] = mr(q[2]);
m[7] = mx(q[3]);
m[8] = my(q[4]);
measure q[5] -> m[9];
measure q[6] -> m[10];
h q[0];sx q[1];cx q[1],q[0];cx q[2],q[0];measure q[0] -> rec[2];cx q[1],q[0];cx q[2],q[0];sxdg q[1];h q[0]; // decomposed MPP
cx q[1],q[0];measure q[0] -> rec[3];cx q[1],q[0]; // decomposed MPP
rec[4] = mrx(q[0]);
rec[5] = mry(q[1]);
rec[6] = mr(q[2]);
rec[7] = mx(q[3]);
rec[8] = my(q[4]);
measure q[5] -> rec[9];
measure q[6] -> rec[10];
rx(q[7]);
ry(q[8]);
reset q[9];
barrier q;
m[11] = mxx(q[0], q[1]);
m[12] = mxx(q[2], q[3]);
m[13] = myy(q[4], q[5]);
m[14] = mzz(q[6], q[7]);
rec[11] = mxx(q[0], q[1]);
rec[12] = mxx(q[2], q[3]);
rec[13] = myy(q[4], q[5]);
rec[14] = mzz(q[6], q[7]);
barrier q;
h q[0];
Expand All @@ -355,15 +354,16 @@ barrier q;
barrier q;
m[15] = mr(q[0]);
m[16] = mr(q[0]);
rec[15] = mr(q[0]);
rec[16] = mr(q[0]);
dets[0] = rec[16] ^ 0;
obs[0] = obs[0] ^ rec[16] ^ 0;
barrier q;
)QASM");

out.str("");
c = circuit_with_inlined_feedback(c);
export_open_qasm(c, out, 2, true);
ASSERT_EQ(out.str(), R"QASM(OPENQASM 2.0;
Expand Down Expand Up @@ -392,7 +392,7 @@ gate swapcx q0, q1 { cx q0, q1; cx q1, q0; }
gate iswapdg q0, q1 { s q0; s q0; s q0; s q1; s q1; s q1; h q1; cx q1, q0; cx q0, q1; h q0; }
qreg q[18];
creg m[20];
creg rec[20];
id q[0];
x q[1];
Expand Down Expand Up @@ -437,24 +437,24 @@ barrier q;
barrier q;
h q[0];sx q[1];cx q[1],q[0];cx q[2],q[0];measure q[0] -> m[2];cx q[1],q[0];cx q[2],q[0];sxdg q[1];h q[0]; // decomposed MPP
cx q[1],q[0];measure q[0] -> m[3];cx q[1],q[0]; // decomposed MPP
h q[0]; measure q[0] -> m[4]; reset q[0]; h q[0]; // decomposed MRX
s q[1]; s q[1]; s q[1]; h q[1]; measure q[1] -> m[5]; reset q[1]; h q[1]; s q[1]; // decomposed MRY
measure q[2] -> m[6]; reset q[2]; // decomposed MR
h q[3]; measure q[3] -> m[7]; h q[3]; // decomposed MX
s q[4]; s q[4]; s q[4]; h q[4]; measure q[4] -> m[8]; h q[4]; s q[4]; // decomposed MY
measure q[5] -> m[9];
measure q[6] -> m[10];
h q[0];sx q[1];cx q[1],q[0];cx q[2],q[0];measure q[0] -> rec[2];cx q[1],q[0];cx q[2],q[0];sxdg q[1];h q[0]; // decomposed MPP
cx q[1],q[0];measure q[0] -> rec[3];cx q[1],q[0]; // decomposed MPP
h q[0]; measure q[0] -> rec[4]; reset q[0]; h q[0]; // decomposed MRX
s q[1]; s q[1]; s q[1]; h q[1]; measure q[1] -> rec[5]; reset q[1]; h q[1]; s q[1]; // decomposed MRY
measure q[2] -> rec[6]; reset q[2]; // decomposed MR
h q[3]; measure q[3] -> rec[7]; h q[3]; // decomposed MX
s q[4]; s q[4]; s q[4]; h q[4]; measure q[4] -> rec[8]; h q[4]; s q[4]; // decomposed MY
measure q[5] -> rec[9];
measure q[6] -> rec[10];
reset q[7]; h q[7]; // decomposed RX
reset q[8]; h q[8]; s q[8]; // decomposed RY
reset q[9];
barrier q;
cx q[0], q[1]; h q[0]; measure q[0] -> m[11]; h q[0]; cx q[0], q[1]; // decomposed MXX
cx q[2], q[3]; h q[2]; measure q[2] -> m[12]; h q[2]; cx q[2], q[3]; // decomposed MXX
s q[4]; s q[5]; cx q[4], q[5]; h q[4]; measure q[4] -> m[13]; s q[5]; s q[5]; h q[4]; cx q[4], q[5]; s q[4]; s q[5]; // decomposed MYY
cx q[6], q[7]; measure q[7] -> m[14]; cx q[6], q[7]; // decomposed MZZ
cx q[0], q[1]; h q[0]; measure q[0] -> rec[11]; h q[0]; cx q[0], q[1]; // decomposed MXX
cx q[2], q[3]; h q[2]; measure q[2] -> rec[12]; h q[2]; cx q[2], q[3]; // decomposed MXX
s q[4]; s q[5]; cx q[4], q[5]; h q[4]; measure q[4] -> rec[13]; s q[5]; s q[5]; h q[4]; cx q[4], q[5]; s q[4]; s q[5]; // decomposed MYY
cx q[6], q[7]; measure q[7] -> rec[14]; cx q[6], q[7]; // decomposed MZZ
barrier q;
h q[0];
Expand All @@ -474,8 +474,8 @@ barrier q;
barrier q;
measure q[0] -> m[15]; reset q[0]; // decomposed MR
measure q[0] -> m[16]; reset q[0]; // decomposed MR
measure q[0] -> rec[15]; reset q[0]; // decomposed MR
measure q[0] -> rec[16]; reset q[0]; // decomposed MR
barrier q;
)QASM");
Expand Down
2 changes: 1 addition & 1 deletion src/stim/circuit/gate_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ enum GateFlags : uint16_t {

struct Gate {
/// The canonical name of the gate, used when printing it to a circuit file.
const char *name = nullptr;
const char *name;
/// The gate's type, such as stim::GateType::X or stim::GateType::MRZ.
GateType id;
/// The id of the gate inverse to this one, or at least the closest thing to an inverse.
Expand Down
17 changes: 14 additions & 3 deletions src/stim/circuit/gate_data.test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -104,17 +104,28 @@ bool is_decomposition_correct(const Gate &gate) {

Circuit circuit1 = epr;
circuit1.safe_append_u(gate.name, qs);
auto v1 = circuit_output_eq_val<W>(circuit1);

Circuit circuit2 = epr + Circuit(decomposition);
auto v2 = circuit_output_eq_val<W>(circuit2);

// Reset gates make the ancillary qubits irrelevant because the final value is unrelated to the initial value.
// So, for reset gates, discard the ancillary qubits.
// CAUTION: this could give false positives if "partial reset" gates are added in the future.
// (E.g. a two qubit gate that resets only one of the qubits.)
if ((gate.flags & GATE_IS_RESET) && !(gate.flags & GATE_PRODUCES_RESULTS)) {
for (auto q : qs) {
circuit1.safe_append_u("R", {q + 2});
circuit2.safe_append_u("R", {q + 2});
}
}

for (const auto &op : circuit2.operations) {
if (op.gate_type != GateType::CX && op.gate_type != GateType::H && op.gate_type != GateType::S &&
op.gate_type != GateType::M && op.gate_type != GateType::R) {
return false;
}
}

auto v1 = circuit_output_eq_val<W>(circuit1);
auto v2 = circuit_output_eq_val<W>(circuit2);
return v1 == v2;
}

Expand Down

0 comments on commit 24f978f

Please sign in to comment.