Skip to content

Commit 923ac7f

Browse files
Handle X gates in QTensorNetwork::ForceM()
1 parent d3843b7 commit 923ac7f

File tree

2 files changed

+49
-11
lines changed

2 files changed

+49
-11
lines changed

include/qcircuit.hpp

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -735,12 +735,39 @@ class QCircuit {
735735
void Run(QInterfacePtr qsim);
736736

737737
/**
738-
* Check if an index is any target qubit of this circuit.
738+
* Check if an index is any target qubit of a nonclassical gate in this circuit.
739739
*/
740-
bool IsNonPhaseTarget(bitLenInt qubit)
740+
bool IsNonClassicalTarget(bitLenInt qubit)
741741
{
742742
for (const QCircuitGatePtr& gate : gates) {
743-
if ((gate->target == qubit) && !(gate->IsPhase())) {
743+
if (gate->target != qubit) {
744+
continue;
745+
}
746+
if (gate->IsInvert() && gate->controls.empty()) {
747+
continue;
748+
}
749+
if (!(gate->IsPhase())) {
750+
return true;
751+
}
752+
}
753+
754+
return false;
755+
}
756+
757+
/**
758+
* Check if an index is any target qubit of a nonclassical gate in this circuit.
759+
*/
760+
bool IsNonClassicalTarget(bitLenInt qubit, bool* eigen)
761+
{
762+
for (const QCircuitGatePtr& gate : gates) {
763+
if (gate->target != qubit) {
764+
continue;
765+
}
766+
if (gate->IsInvert() && gate->controls.empty()) {
767+
*eigen = !*eigen;
768+
continue;
769+
}
770+
if (!(gate->IsPhase())) {
744771
return true;
745772
}
746773
}
@@ -749,21 +776,27 @@ class QCircuit {
749776
}
750777

751778
/**
752-
* (If the qubit is not a target of a non-phase gate...) Delete this qubits' controls and phase targets.
779+
* (If the qubit is not a target of a non-classical gate...) Delete this qubits' controls and phase targets.
753780
*/
754-
void DeletePhaseTarget(bitLenInt qubit, bool eigen)
781+
bool DeleteClassicalTarget(bitLenInt qubit, bool eigen)
755782
{
756783
std::list<QCircuitGatePtr> nGates;
757784
gates.reverse();
758785
for (const QCircuitGatePtr& gate : gates) {
759786
if (gate->target == qubit) {
787+
if (gate->IsInvert()) {
788+
eigen = !eigen;
789+
QCircuitGatePtr nGate = gate->Clone();
790+
nGates.insert(nGates.begin(), nGate);
791+
}
760792
continue;
761793
}
762794
QCircuitGatePtr nGate = gate->Clone();
763795
nGate->PostSelectControl(qubit, eigen);
764796
nGates.insert(nGates.begin(), nGate);
765797
}
766798
gates = nGates;
799+
return eigen;
767800
}
768801

769802
/**

src/qtensornetwork.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -236,11 +236,12 @@ bool QTensorNetwork::ForceM(bitLenInt qubit, bool result, bool doForce, bool doA
236236
return toRet;
237237
}
238238

239+
bool eigen = toRet;
239240
size_t layerId = circuit.size() - 1U;
240241
// Starting from latest circuit layer, if measurement commutes...
241-
while (!(circuit[layerId]->IsNonPhaseTarget(qubit))) {
242+
while (!(circuit[layerId]->IsNonClassicalTarget(qubit))) {
242243
const QCircuitPtr& c = circuit[layerId];
243-
c->DeletePhaseTarget(qubit, toRet);
244+
eigen = c->DeleteClassicalTarget(qubit, eigen);
244245

245246
if (!layerId) {
246247
// The qubit has been simplified to |0> with no gates.
@@ -274,25 +275,30 @@ bool QTensorNetwork::ForceM(bitLenInt qubit, bool result, bool doForce, bool doA
274275
}
275276

276277
// Insert terminal measurement.
277-
measurements[layerId][qubit] = toRet;
278+
measurements[layerId][qubit] = eigen;
278279

279280
// If no qubit in this layer is unmeasured, we can completely telescope into classical state preparation.
280281
std::vector<bitLenInt> nonMeasuredQubits;
281282
nonMeasuredQubits.reserve(qubitCount);
282283
for (size_t i = 0U; i < qubitCount; ++i) {
283284
nonMeasuredQubits.push_back(i);
284285
}
286+
std::map<bitLenInt, bool> m = measurements[layerId];
285287
for (const bitLenInt& q : nonMeasuredQubits) {
286288
size_t layer = layerId;
289+
eigen = false;
287290
while (true) {
288-
if (measurements[layer].find(q) != measurements[layer].end()) {
291+
std::map<bitLenInt, bool>& ml = measurements[layer];
292+
if (ml.find(q) != ml.end()) {
293+
m[q] = ml[q] ^ eigen;
289294
break;
290295
}
291-
if (circuit[layer]->IsNonPhaseTarget(q)) {
296+
if (circuit[layer]->IsNonClassicalTarget(q, &eigen)) {
292297
// Nothing more to do; tell the user the result.
293298
return toRet;
294299
}
295300
if (!layer) {
301+
m[q] = eigen;
296302
break;
297303
}
298304
--layer;
@@ -302,7 +308,6 @@ bool QTensorNetwork::ForceM(bitLenInt qubit, bool result, bool doForce, bool doA
302308

303309
// All bits have been measured in this layer.
304310
// None of the previous layers matter.
305-
const std::map<bitLenInt, bool>& m = measurements[layerId];
306311

307312
// Erase all of the previous layers.
308313
for (size_t i = 0U; i < layerId; ++i) {

0 commit comments

Comments
 (0)