Skip to content

Commit

Permalink
🎨 further DD usability improvements (#764)
Browse files Browse the repository at this point in the history
## Description

This is a direct follow-up to #674 and adds one more convenience routine
that avoids users having to perform reference counting on their own.

## Checklist:

<!---
This checklist serves as a reminder of a couple of things that ensure
your pull request will be merged swiftly.
-->

- [x] The pull request only contains commits that are related to it.
- [x] I have added appropriate tests and documentation.
- [x] I have made sure that all CI jobs on GitHub pass.
- [x] The pull request introduces no new warnings and follows the
project's style guidelines.

Signed-off-by: burgholzer <burgholzer@me.com>
  • Loading branch information
burgholzer authored Nov 28, 2024
1 parent 6733f78 commit 13f33d7
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 53 deletions.
56 changes: 13 additions & 43 deletions eval/eval_dd_package.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,25 +71,16 @@ MatrixDD buildFunctionality(const qc::Grover* qc, Package<Config>& dd) {

auto e = iteration;
dd.incRef(e);

for (std::size_t i = 0U; i < qc->iterations - 1U; ++i) {
auto f = dd.multiply(iteration, e);
dd.incRef(f);
dd.decRef(e);
e = f;
dd.garbageCollect();
e = dd.applyOperation(iteration, e);
}
dd.decRef(iteration);

QuantumComputation setup(qc->getNqubits());
qc->setup(setup);
auto g = buildFunctionality(&setup, dd);
auto f = dd.multiply(e, g);
dd.incRef(f);
dd.decRef(e);
const auto g = buildFunctionality(&setup, dd);
e = dd.applyOperation(e, g);
dd.decRef(g);
e = f;

dd.decRef(iteration);
return e;
}

Expand All @@ -103,27 +94,21 @@ MatrixDD buildFunctionalityRecursive(const qc::Grover* qc,
auto iter = buildFunctionalityRecursive(&groverIteration, dd);
auto e = iter;
std::bitset<128U> iterBits(qc->iterations);
auto msb = static_cast<std::size_t>(std::floor(std::log2(qc->iterations)));
const auto msb =
static_cast<std::size_t>(std::floor(std::log2(qc->iterations)));
auto f = iter;
dd.incRef(f);
bool zero = !iterBits[0U];
for (std::size_t j = 1U; j <= msb; ++j) {
auto tmp = dd.multiply(f, f);
dd.incRef(tmp);
dd.decRef(f);
f = tmp;
f = dd.applyOperation(f, f);
if (iterBits[j]) {
if (zero) {
dd.incRef(f);
dd.decRef(e);
e = f;
zero = false;
} else {
auto g = dd.multiply(e, f);
dd.incRef(g);
dd.decRef(e);
e = g;
dd.garbageCollect();
e = dd.applyOperation(e, f);
}
}
}
Expand All @@ -132,14 +117,8 @@ MatrixDD buildFunctionalityRecursive(const qc::Grover* qc,
// apply state preparation setup
qc::QuantumComputation statePrep(qc->getNqubits());
qc->setup(statePrep);
auto s = buildFunctionality(&statePrep, dd);
auto tmp = dd.multiply(e, s);
dd.incRef(tmp);
dd.decRef(s);
dd.decRef(e);
e = tmp;

return e;
const auto s = buildFunctionality(&statePrep, dd);
return dd.applyOperation(e, s);
}

std::unique_ptr<SimulationExperiment>
Expand Down Expand Up @@ -302,9 +281,7 @@ class BenchmarkDDPackage {
qc::QuantumComputation statePrep(qc->getNqubits());
qc->setup(statePrep);
auto s = buildFunctionality(&statePrep, *dd);
auto e = dd->multiply(s, dd->makeZeroState(qc->getNqubits()));
dd->incRef(e);
dd->decRef(s);
auto e = dd->applyOperation(s, dd->makeZeroState(qc->getNqubits()));

qc::QuantumComputation groverIteration(qc->getNqubits());
qc->oracle(groverIteration);
Expand All @@ -318,17 +295,10 @@ class BenchmarkDDPackage {
dd->incRef(f);
for (std::size_t j = 0U; j <= msb; ++j) {
if (iterBits[j]) {
auto g = dd->multiply(f, e);
dd->incRef(g);
dd->decRef(e);
e = g;
dd->garbageCollect();
e = dd->applyOperation(f, e);
}
if (j < msb) {
auto tmp = dd->multiply(f, f);
dd->incRef(tmp);
dd->decRef(f);
f = tmp;
f = dd->applyOperation(f, f);
}
}
dd->decRef(f);
Expand Down
6 changes: 1 addition & 5 deletions include/mqt-core/dd/Operations.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,11 +248,7 @@ Edge<Node> applyUnitaryOperation(const qc::Operation* op, const Edge<Node>& in,
const qc::Permutation& permutation = {}) {
static_assert(std::is_same_v<Node, dd::vNode> ||
std::is_same_v<Node, dd::mNode>);
auto tmp = dd.multiply(getDD(op, dd, permutation), in);
dd.incRef(tmp);
dd.decRef(in);
dd.garbageCollect();
return tmp;
return dd.applyOperation(getDD(op, dd, permutation), in);
}

template <class Config>
Expand Down
26 changes: 25 additions & 1 deletion include/mqt-core/dd/Package.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1476,6 +1476,30 @@ template <class Config> class Package {
}
}

/**
* @brief Applies a matrix operation to a matrix or vector.
*
* @details The reference count of the input matrix or vector is decreased,
* while the reference count of the result is increased. After the operation,
* garbage collection is triggered.
*
* @tparam Node Node type
* @param operation Matrix operation to apply
* @param e Matrix or vector to apply the operation to
* @return The appropriately reference-counted result.
*/
template <class Node>
Edge<Node> applyOperation(const mEdge& operation, const Edge<Node>& e) {
static_assert(std::disjunction_v<std::is_same<Node, vNode>,
std::is_same<Node, mNode>>,
"Node must be a vector or matrix node.");
const auto tmp = multiply(operation, e);
incRef(tmp);
decRef(e);
garbageCollect();
return tmp;
}

dEdge applyOperationToDensity(dEdge& e, const mEdge& operation) {
const auto tmp0 = conjugateTranspose(operation);
const auto tmp1 = multiply(e, densityFromMatrixEdge(tmp0), false);
Expand Down Expand Up @@ -1827,7 +1851,7 @@ template <class Config> class Package {
"expectation value.");
}

auto yPrime = multiply(x, y);
const auto yPrime = multiply(x, y);
const ComplexValue expValue = innerProduct(y, yPrime);

assert(RealNumber::approximatelyZero(expValue.i));
Expand Down
5 changes: 1 addition & 4 deletions src/dd/Simulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,10 +285,7 @@ void extractProbabilityVectorRecursive(const QuantumComputation* qc,
if (RealNumber::approximatelyEquals(pone, 1.)) {
const qc::MatrixDD xGate =
dd.makeGateDD(X_MAT, static_cast<Qubit>(permutation.at(target)));
const qc::VectorDD resetState = dd.multiply(xGate, state);
dd.incRef(resetState);
dd.decRef(state);
state = resetState;
state = dd.applyOperation(xGate, state);
continue;
}

Expand Down

0 comments on commit 13f33d7

Please sign in to comment.