diff --git a/include/mqt-core/dd/Package.hpp b/include/mqt-core/dd/Package.hpp index 0488f4dac..249c8ab85 100644 --- a/include/mqt-core/dd/Package.hpp +++ b/include/mqt-core/dd/Package.hpp @@ -303,6 +303,7 @@ template class Package { static_cast(p), std::array{f, dEdge::zero(), dEdge::zero(), dEdge::zero()}); } + incRef(f); return f; } @@ -319,6 +320,7 @@ template class Package { for (std::size_t p = start; p < n + start; p++) { f = makeDDNode(static_cast(p), std::array{f, vEdge::zero()}); } + incRef(f); return f; } // generate computational basis state |i> with n qubits @@ -339,6 +341,7 @@ template class Package { f = makeDDNode(static_cast(p), std::array{vEdge::zero(), f}); } } + incRef(f); return f; } // generate general basis state with n qubits @@ -391,7 +394,9 @@ template class Package { break; } } - return {f.p, cn.lookup(f.w)}; + vEdge e{f.p, cn.lookup(f.w)}; + incRef(e); + return e; } // generate general GHZ state with n qubits @@ -418,11 +423,13 @@ template class Package { std::array{vEdge::zero(), rightSubtree}); } - return makeDDNode( + vEdge e = makeDDNode( static_cast(n - 1), std::array{ {{leftSubtree.p, {&constants::sqrt2over2, &constants::zero}}, {rightSubtree.p, {&constants::sqrt2over2, &constants::zero}}}}); + incRef(e); + return e; } // generate general W state with n qubits @@ -459,6 +466,7 @@ template class Package { std::array{rightSubtree, vEdge::zero()}); } } + incRef(leftSubtree); return leftSubtree; } @@ -480,7 +488,9 @@ template class Package { const auto level = static_cast(std::log2(length) - 1); const auto state = makeStateFromVector(stateVector.begin(), stateVector.end(), level); - return {state.p, cn.lookup(state.w)}; + vEdge e{state.p, cn.lookup(state.w)}; + incRef(e); + return e; } /** diff --git a/include/mqt-core/dd/Simulation.hpp b/include/mqt-core/dd/Simulation.hpp index afdccebbe..946a8013c 100644 --- a/include/mqt-core/dd/Simulation.hpp +++ b/include/mqt-core/dd/Simulation.hpp @@ -18,7 +18,6 @@ VectorDD simulate(const QuantumComputation* qc, const VectorDD& in, // measurements are currently not supported here auto permutation = qc->initialLayout; auto e = in; - dd.incRef(e); for (const auto& op : *qc) { e = applyUnitaryOperation(op.get(), e, dd, permutation); diff --git a/src/dd/Simulation.cpp b/src/dd/Simulation.cpp index 69eac09c2..e54f433ca 100644 --- a/src/dd/Simulation.cpp +++ b/src/dd/Simulation.cpp @@ -81,7 +81,6 @@ simulate(const QuantumComputation* qc, const VectorDD& in, Package& dd, // simulate once and measure all qubits repeatedly auto permutation = qc->initialLayout; auto e = in; - dd.incRef(e); for (const auto& op : *qc) { // simply skip any non-unitary @@ -135,11 +134,13 @@ simulate(const QuantumComputation* qc, const VectorDD& in, Package& dd, std::map counts{}; for (std::size_t i = 0U; i < shots; i++) { + // increase reference count of input state so that it is collected + dd.incRef(in); + std::vector measurements(qc->getNcbits(), false); auto permutation = qc->initialLayout; auto e = in; - dd.incRef(e); for (const auto& op : *qc) { if (op->getType() == Measure) { @@ -171,6 +172,9 @@ simulate(const QuantumComputation* qc, const VectorDD& in, Package& dd, counts[shot]++; } + // decrease reference count of input state so that it can be garbage collected + dd.decRef(in); + return counts; } diff --git a/test/dd/test_dd_noise_functionality.cpp b/test/dd/test_dd_noise_functionality.cpp index 6d27fadd0..2cd0f8b3f 100644 --- a/test/dd/test_dd_noise_functionality.cpp +++ b/test/dd/test_dd_noise_functionality.cpp @@ -77,7 +77,6 @@ TEST_F(DDNoiseFunctionalityTest, DetSimulateAdder4TrackAPD) { auto dd = std::make_unique(qc.getNqubits()); auto rootEdge = dd->makeZeroDensityOperator(qc.getNqubits()); - dd->incRef(rootEdge); const auto* const noiseEffects = "APDI"; @@ -109,7 +108,6 @@ TEST_F(DDNoiseFunctionalityTest, DetSimulateAdder4TrackD) { auto dd = std::make_unique(qc.getNqubits()); auto rootEdge = dd->makeZeroDensityOperator(qc.getNqubits()); - dd->incRef(rootEdge); const auto* const noiseEffects = "D"; @@ -141,7 +139,6 @@ TEST_F(DDNoiseFunctionalityTest, testingMeasure) { auto dd = std::make_unique(qcOp.getNqubits()); auto rootEdge = dd->makeZeroDensityOperator(qcOp.getNqubits()); - dd->incRef(rootEdge); auto deterministicNoiseFunctionality = dd::DeterministicNoiseFunctionality( dd, qcOp.getNqubits(), 0.01, 0.02, 0.02, 0.04, {}); diff --git a/test/dd/test_edge_functionality.cpp b/test/dd/test_edge_functionality.cpp index fb2096fde..ea2808efa 100644 --- a/test/dd/test_edge_functionality.cpp +++ b/test/dd/test_edge_functionality.cpp @@ -364,7 +364,6 @@ TEST(DensityMatrixFunctionality, GetValueByIndexProperDensityMatrix) { const auto nqubits = 1U; auto dd = std::make_unique>(nqubits); auto zero = dd->makeZeroDensityOperator(nqubits); - dd->incRef(zero); const auto op1 = dd->makeGateDD(dd::H_MAT, 0U); const auto op2 = dd->makeGateDD(dd::rzMat(dd::PI_4), 0U); auto state = dd->applyOperationToDensity(zero, op1); @@ -399,7 +398,6 @@ TEST(DensityMatrixFunctionality, GetSparseMatrixConsistency) { const auto nqubits = 1U; auto dd = std::make_unique>(nqubits); auto zero = dd->makeZeroDensityOperator(nqubits); - dd->incRef(zero); const auto op1 = dd->makeGateDD(dd::H_MAT, 0U); const auto op2 = dd->makeGateDD(dd::rzMat(dd::PI_4), 0U); auto state = dd->applyOperationToDensity(zero, op1); @@ -430,7 +428,6 @@ TEST(DensityMatrixFunctionality, PrintMatrix) { const auto nqubits = 1U; auto dd = std::make_unique>(nqubits); auto zero = dd->makeZeroDensityOperator(nqubits); - dd->incRef(zero); const auto op1 = dd->makeGateDD(dd::H_MAT, 0U); const auto op2 = dd->makeGateDD(dd::rzMat(dd::PI_4), 0U); auto state = dd->applyOperationToDensity(zero, op1); diff --git a/test/dd/test_package.cpp b/test/dd/test_package.cpp index a5762e7d2..b7f0f93cb 100644 --- a/test/dd/test_package.cpp +++ b/test/dd/test_package.cpp @@ -428,8 +428,6 @@ TEST(DDPackageTest, StateGenerationManipulation) { {dd::BasisStates::zero, dd::BasisStates::one, dd::BasisStates::plus, dd::BasisStates::minus, dd::BasisStates::left, dd::BasisStates::right}); - dd->incRef(e); - dd->incRef(f); dd->vUniqueTable.print(); dd->decRef(e); dd->decRef(f); @@ -1497,7 +1495,6 @@ TEST(DDPackageTest, dNodeMultiply) { nrQubits); // Make zero density matrix auto state = dd->makeZeroDensityOperator(dd->qubits()); - dd->incRef(state); std::vector operations = {}; operations.emplace_back(dd->makeGateDD(dd::H_MAT, 0)); operations.emplace_back(dd->makeGateDD(dd::H_MAT, 1)); @@ -1546,7 +1543,6 @@ TEST(DDPackageTest, dNodeMultiply2) { nrQubits); // Make zero density matrix auto state = dd->makeZeroDensityOperator(dd->qubits()); - dd->incRef(state); std::vector operations = {}; operations.emplace_back(dd->makeGateDD(dd::H_MAT, 0)); operations.emplace_back(dd->makeGateDD(dd::H_MAT, 1)); @@ -1588,7 +1584,6 @@ TEST(DDPackageTest, dNodeMulCache1) { nrQubits); // Make zero density matrix auto state = dd->makeZeroDensityOperator(nrQubits); - dd->incRef(state); const auto operation = dd->makeGateDD(dd::H_MAT, 0); dd->applyOperationToDensity(state, operation); @@ -1635,7 +1630,6 @@ TEST(DDPackageTest, dNoiseCache) { auto dd = std::make_unique>(nrQubits); // Make zero density matrix const auto initialState = dd->makeZeroDensityOperator(nrQubits); - dd->incRef(initialState); // nothing pre-cached const std::vector target = {0};