Skip to content

Commit e097c70

Browse files
Debug QTensorNetwork mid-circuit measurement
1 parent d132a9b commit e097c70

File tree

1 file changed

+26
-38
lines changed

1 file changed

+26
-38
lines changed

src/qtensornetwork.cpp

Lines changed: 26 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -276,50 +276,38 @@ bool QTensorNetwork::ForceM(bitLenInt qubit, bool result, bool doForce, bool doA
276276
// Insert terminal measurement.
277277
measurements[layerId][qubit] = toRet;
278278

279-
// If no qubit in this layer is target of a non-phase gate, it can be completely telescoped into classical state
280-
// preparation.
281-
while (layerId) {
282-
std::vector<bitLenInt> nonMeasuredQubits;
283-
nonMeasuredQubits.reserve(qubitCount);
284-
for (size_t i = 0U; i < qubitCount; ++i) {
285-
nonMeasuredQubits.push_back(i);
286-
}
287-
std::map<bitLenInt, bool>& m = measurements[layerId];
288-
for (const auto& b : m) {
289-
nonMeasuredQubits.erase(std::find(nonMeasuredQubits.begin(), nonMeasuredQubits.end(), b.first));
290-
}
279+
// If no qubit in this layer is unmeasured, we can completely telescope into classical state preparation.
280+
std::vector<bitLenInt> nonMeasuredQubits;
281+
nonMeasuredQubits.reserve(qubitCount);
282+
for (size_t i = 0U; i < qubitCount; ++i) {
283+
nonMeasuredQubits.push_back(i);
284+
}
285+
std::map<bitLenInt, bool>& m = measurements[layerId];
286+
for (const auto& b : m) {
287+
nonMeasuredQubits.erase(std::find(nonMeasuredQubits.begin(), nonMeasuredQubits.end(), b.first));
288+
}
291289

292-
const QCircuitPtr& c = circuit[layerId];
293-
for (const bitLenInt& q : nonMeasuredQubits) {
294-
if (c->IsNonPhaseTarget(q)) {
295-
// Nothing more to do; tell the user the result.
296-
return toRet;
297-
}
290+
if (nonMeasuredQubits.empty()) {
291+
// All bits have been measured in this layer.
292+
// None of the previous layers matter.
293+
294+
// Erase all of the previous layers.
295+
std::map<bitLenInt, bool> m = measurements[layerId];
296+
for (size_t i = 1U; i < layerId; ++i) {
297+
circuit.erase(circuit.end() - 1U);
298+
measurements.erase(measurements.end() - 1U);
298299
}
300+
circuit[0U] = std::make_shared<QCircuit>();
301+
measurements[0U] = m;
299302

300-
// If we did not return, this circuit layer is fully collapsed.
303+
// Sync layer 0U as state preparation for deterministic measurement.
304+
std::map<bitLenInt, bool> m0 = measurements[0U];
301305
QRACK_CONST complex pauliX[4U]{ ZERO_CMPLX, ONE_CMPLX, ONE_CMPLX, ZERO_CMPLX };
302-
303-
const size_t layerIdMin1 = layerId - 1U;
304-
std::map<bitLenInt, bool>& mMin1 = measurements[layerIdMin1];
305-
for (const auto& b : m) {
306-
const auto it = mMin1.find(b.first);
307-
if ((it != mMin1.end()) && (it->second != b.second)) {
308-
// If the last measurement and this measurement do not agree, insert an X gate between.
309-
circuit[layerIdMin1]->AppendGate(std::make_shared<QCircuitGate>(b.first, pauliX));
306+
for (const auto& b : m0) {
307+
if (b.second) {
308+
circuit[0U]->AppendGate(std::make_shared<QCircuitGate>(b.first, pauliX));
310309
}
311-
// Collapse the measurements into the previous layer.
312-
mMin1[b.first] = b.second;
313310
}
314-
// Combine any remaining gates into the previous layer
315-
circuit[layerIdMin1]->Combine(circuit[layerId]);
316-
// The circuit layer is effectively empty.
317-
circuit.erase(circuit.begin() + layerId);
318-
// The measurement layer is effectively empty.
319-
measurements.erase(measurements.begin() + layerId);
320-
321-
// ...Repeat until we reach the terminal layer.
322-
--layerId;
323311
}
324312

325313
// Tell the user the result.

0 commit comments

Comments
 (0)