diff --git a/include/checker/dd/TaskManager.hpp b/include/checker/dd/TaskManager.hpp index 170a5270..83118115 100644 --- a/include/checker/dd/TaskManager.hpp +++ b/include/checker/dd/TaskManager.hpp @@ -13,8 +13,10 @@ #include "ir/operations/OpType.hpp" #include "ir/operations/Operation.hpp" +#include #include #include +#include namespace ec { enum class Direction : bool { Left = true, Right = false }; @@ -53,10 +55,10 @@ template class TaskManager { } [[nodiscard]] qc::MatrixDD getDD() { - return dd::getDD((*iterator).get(), *package, permutation); + return dd::getDD(iterator->get(), *package, permutation); } [[nodiscard]] qc::MatrixDD getInverseDD() { - return dd::getInverseDD((*iterator).get(), *package, permutation); + return dd::getInverseDD(iterator->get(), *package, permutation); } [[nodiscard]] const qc::QuantumComputation* getCircuit() const noexcept { @@ -85,17 +87,22 @@ template class TaskManager { ++iterator; } - void applySwapOperations(DDType& state) { - while (!finished() && (*iterator)->getType() == qc::SWAP) { - applyGate(state); + void applySwapOperations() { + while (!finished() && (*iterator)->getType() == qc::SWAP && + !(*iterator)->isControlled()) { + const auto& targets = (*iterator)->getTargets(); + assert(targets.size() == 2); + const auto t1 = targets[0]; + const auto t2 = targets[1]; + std::swap(permutation.at(t1), permutation.at(t2)); + ++iterator; } } - void applySwapOperations() { applySwapOperations(internalState); } void advance(DDType& state, const std::size_t steps) { for (std::size_t i = 0U; i < steps && !finished(); ++i) { applyGate(state); - applySwapOperations(state); + applySwapOperations(); } } void advance(DDType& state) { advance(state, 1U); } diff --git a/src/checker/dd/DDAlternatingChecker.cpp b/src/checker/dd/DDAlternatingChecker.cpp index 6ee0c313..32a700c1 100644 --- a/src/checker/dd/DDAlternatingChecker.cpp +++ b/src/checker/dd/DDAlternatingChecker.cpp @@ -52,8 +52,8 @@ void DDAlternatingChecker::initialize() { void DDAlternatingChecker::execute() { while (!taskManager1.finished() && !taskManager2.finished() && !isDone()) { // skip over any SWAP operations - taskManager1.applySwapOperations(functionality); - taskManager2.applySwapOperations(functionality); + taskManager1.applySwapOperations(); + taskManager2.applySwapOperations(); if (!taskManager1.finished() && !taskManager2.finished() && !isDone()) { // whenever the current functionality resembles the identity, identical diff --git a/src/checker/dd/DDSimulationChecker.cpp b/src/checker/dd/DDSimulationChecker.cpp index b2957768..2cf9af15 100644 --- a/src/checker/dd/DDSimulationChecker.cpp +++ b/src/checker/dd/DDSimulationChecker.cpp @@ -38,6 +38,7 @@ EquivalenceCriterion DDSimulationChecker::checkEquivalence() { // adjust reference counts to facilitate reuse of the simulation checker taskManager1.decRef(); taskManager2.decRef(); + dd->decRef(initialState); return equivalence; } diff --git a/src/checker/dd/simulation/StateGenerator.cpp b/src/checker/dd/simulation/StateGenerator.cpp index 0a326f1b..3ddc80eb 100644 --- a/src/checker/dd/simulation/StateGenerator.cpp +++ b/src/checker/dd/simulation/StateGenerator.cpp @@ -143,15 +143,15 @@ qc::VectorDD StateGenerator::generateRandomStabilizerState( // circuit auto stabilizer = simulate(&rcs, dd.makeZeroState(randomQubits), dd); - // decrease the ref count right after so that it stays correct later on - dd.decRef(stabilizer); - // add |0> edges for all the ancillary qubits auto initial = stabilizer; for (std::size_t p = randomQubits; p < totalQubits; ++p) { initial = dd.makeDDNode(static_cast(p), std::array{initial, qc::VectorDD::zero()}); } + // properly set the reference count for the state + dd.incRef(initial); + dd.decRef(stabilizer); // return the resulting decision diagram return initial;