Skip to content

Commit

Permalink
♻️ streamline makeGateDD method (#571)
Browse files Browse the repository at this point in the history
## Description

This is the first of probably many follow-up PRs to #358, which tries to
simplify the underlying functions and methods for representing
operations.
This PR specifically streamlines the `makeGateDD` method in the DD
package and eliminates the `nqubits` and `start` parameters, which are
no longer necessary.

## 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 committed Mar 25, 2024
1 parent af3eb94 commit c40d5a1
Show file tree
Hide file tree
Showing 6 changed files with 256 additions and 305 deletions.
4 changes: 1 addition & 3 deletions include/mqt-core/dd/Operations.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ getStandardOperationDD(const qc::StandardOperation* op, Package<Config>& dd,
GateMatrix gm;

const auto type = op->getType();
const auto nqubits = op->getNqubits();
const auto startQubit = op->getStartingQubit();
const auto& parameter = op->getParameter();

switch (type) {
Expand Down Expand Up @@ -88,7 +86,7 @@ getStandardOperationDD(const qc::StandardOperation* op, Package<Config>& dd,
oss << "DD for gate" << op->getName() << " not available!";
throw qc::QFRException(oss.str());
}
return dd.makeGateDD(gm, nqubits, controls, target, startQubit);
return dd.makeGateDD(gm, controls, target);
}

// two-target Operations
Expand Down
95 changes: 42 additions & 53 deletions include/mqt-core/dd/Package.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -512,27 +512,28 @@ template <class Config> class Package {
/// Matrix nodes, edges and quantum gates
///
// build matrix representation for a single gate on an n-qubit circuit
mEdge makeGateDD(const GateMatrix& mat, const std::size_t n,
const qc::Qubit target, const std::size_t start = 0) {
return makeGateDD(mat, n, qc::Controls{}, target, start);
}
mEdge makeGateDD(const GateMatrix& mat, const std::size_t n,
const qc::Control& control, const qc::Qubit target,
const std::size_t start = 0) {
return makeGateDD(mat, n, qc::Controls{control}, target, start);
}
mEdge makeGateDD(const GateMatrix& mat, const std::size_t n,
const qc::Controls& controls, const qc::Qubit target,
const std::size_t start = 0) {
if (n + start > nqubits) {
mEdge makeGateDD(const GateMatrix& mat, const qc::Qubit target) {
return makeGateDD(mat, qc::Controls{}, target);
}
mEdge makeGateDD(const GateMatrix& mat, const qc::Control& control,
const qc::Qubit target) {
return makeGateDD(mat, qc::Controls{control}, target);
}
mEdge makeGateDD(const GateMatrix& mat, const qc::Controls& controls,
const qc::Qubit target) {
if (std::any_of(controls.begin(), controls.end(),
[this](const auto& c) {
return c.qubit > static_cast<Qubit>(nqubits - 1U);
}) ||
target > static_cast<Qubit>(nqubits - 1U)) {
throw std::runtime_error{
"Requested gate with " + std::to_string(n + start) +
" qubits, but current package configuration only supports up to " +
"Requested gate acting on qubit(s) with index larger than " +
std::to_string(nqubits - 1U) +
" while the package configuration only supports up to " +
std::to_string(nqubits) +
" qubits. Please allocate a larger package instance."};
}
std::array<mCachedEdge, NEDGE> em{};
auto it = controls.begin();
for (auto i = 0U; i < NEDGE; ++i) {
em[i] = mCachedEdge::terminal(mat[i]);
}
Expand All @@ -543,51 +544,40 @@ template <class Config> class Package {
return {e.p, cn.lookup(e.w)};
}

auto it = controls.begin();
auto edges = std::array{mCachedEdge::zero(), mCachedEdge::zero(),
mCachedEdge::zero(), mCachedEdge::zero()};

// process lines below target
auto z = static_cast<Qubit>(start);
for (; z < static_cast<Qubit>(target); ++z) {
for (; it != controls.end() && it->qubit < target; ++it) {
for (auto i1 = 0U; i1 < RADIX; ++i1) {
for (auto i2 = 0U; i2 < RADIX; ++i2) {
auto i = i1 * RADIX + i2;
if (it != controls.end() && it->qubit == z) {
auto edges = std::array{mCachedEdge::zero(), mCachedEdge::zero(),
mCachedEdge::zero(), mCachedEdge::zero()};
if (it->type == qc::Control::Type::Neg) { // neg. control
edges[0] = em[i];
if (i1 == i2) {
edges[3] = mCachedEdge::one();
}
} else { // pos. control
edges[3] = em[i];
if (i1 == i2) {
edges[0] = mCachedEdge::one();
}
}
em[i] = makeDDNode(z, edges);
if (it->type == qc::Control::Type::Neg) { // neg. control
edges[0] = em[i];
edges[3] = (i1 == i2) ? mCachedEdge::one() : mCachedEdge::zero();
} else { // pos. control
edges[0] = (i1 == i2) ? mCachedEdge::one() : mCachedEdge::zero();
edges[3] = em[i];
}
em[i] = makeDDNode(static_cast<Qubit>(it->qubit), edges);
}
}
if (it != controls.end() && it->qubit == z) {
++it;
}
}

// target line
auto e = makeDDNode(z, em);
auto e = makeDDNode(static_cast<Qubit>(target), em);

// process lines above target
for (; z < static_cast<Qubit>(n - 1 + start); z++) {
auto q = static_cast<Qubit>(z + 1);
if (it != controls.end() && it->qubit == static_cast<qc::Qubit>(q)) {
if (it->type == qc::Control::Type::Neg) { // neg. control
e = makeDDNode(q,
std::array{e, mCachedEdge::zero(), mCachedEdge::zero(),
mCachedEdge::one()});
} else { // pos. control
e = makeDDNode(q, std::array{mCachedEdge::one(), mCachedEdge::zero(),
mCachedEdge::zero(), e});
}
++it;
for (; it != controls.end(); ++it) {
if (it->type == qc::Control::Type::Neg) { // neg. control
edges[0] = e;
edges[3] = mCachedEdge::one();
e = makeDDNode(static_cast<Qubit>(it->qubit), edges);
} else { // pos. control
edges[0] = mCachedEdge::one();
edges[3] = e;
e = makeDDNode(static_cast<Qubit>(it->qubit), edges);
}
}
return {e.p, cn.lookup(e.w)};
Expand Down Expand Up @@ -1135,7 +1125,7 @@ template <class Config> class Package {
const auto nrQubits = e.p->v + 1U;
dEdge::setDensityMatrixTrue(e);

auto const measZeroDd = makeGateDD(MEAS_ZERO_MAT, nrQubits, index);
auto const measZeroDd = makeGateDD(MEAS_ZERO_MAT, index);

auto tmp0 = conjugateTranspose(measZeroDd);
auto tmp1 = multiply(e, densityFromMatrixEdge(tmp0), 0, false);
Expand All @@ -1144,7 +1134,7 @@ template <class Config> class Package {

std::uniform_real_distribution<fp> dist(0., 1.);
if (const auto threshold = dist(mt); threshold > densityMatrixTrace.r) {
auto const measOneDd = makeGateDD(MEAS_ONE_MAT, nrQubits, index);
auto const measOneDd = makeGateDD(MEAS_ONE_MAT, index);
tmp0 = conjugateTranspose(measOneDd);
tmp1 = multiply(e, densityFromMatrixEdge(tmp0), 0, false);
tmp2 = multiply(densityFromMatrixEdge(measOneDd), tmp1, 0, true);
Expand Down Expand Up @@ -1181,8 +1171,7 @@ template <class Config> class Package {
const bool measureZero) {
GateMatrix measurementMatrix = measureZero ? MEAS_ZERO_MAT : MEAS_ONE_MAT;

const auto measurementGate =
makeGateDD(measurementMatrix, rootEdge.p->v + 1U, index);
const auto measurementGate = makeGateDD(measurementMatrix, index);

vEdge e = multiply(measurementGate, rootEdge);

Expand Down
2 changes: 1 addition & 1 deletion src/dd/NoiseFunctionality.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ mEdge StochasticNoiseFunctionality::stackOperation(
op != nullptr) {
return package->multiply(*op, operation);
}
const auto gateDD = package->makeGateDD(matrix, getNumberOfQubits(), target);
const auto gateDD = package->makeGateDD(matrix, target);
package->stochasticNoiseOperationCache.insert(noiseOperation, target, gateDD);
return package->multiply(gateDD, operation);
}
Expand Down
3 changes: 1 addition & 2 deletions src/dd/Simulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,8 +270,7 @@ void extractProbabilityVectorRecursive(const QuantumComputation* qc,

if (RealNumber::approximatelyEquals(pone, 1.)) {
const qc::MatrixDD xGate =
dd.makeGateDD(X_MAT, static_cast<std::size_t>(state.p->v) + 1U,
static_cast<Qubit>(permutation.at(target)));
dd.makeGateDD(X_MAT, static_cast<Qubit>(permutation.at(target)));
const qc::VectorDD resetState = dd.multiply(xGate, state);
dd.incRef(resetState);
dd.decRef(state);
Expand Down
12 changes: 6 additions & 6 deletions test/dd/test_edge_functionality.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,8 +356,8 @@ TEST(DensityMatrixFunctionality, GetValueByIndexProperDensityMatrix) {
auto dd = std::make_unique<dd::Package<>>(nqubits);
auto zero = dd->makeZeroDensityOperator(nqubits);
dd->incRef(zero);
const auto op1 = dd->makeGateDD(dd::H_MAT, nqubits, 0U);
const auto op2 = dd->makeGateDD(dd::rzMat(dd::PI_4), nqubits, 0U);
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);
state = dd->applyOperationToDensity(state, op2);

Expand Down Expand Up @@ -391,8 +391,8 @@ TEST(DensityMatrixFunctionality, GetSparseMatrixConsistency) {
auto dd = std::make_unique<dd::Package<>>(nqubits);
auto zero = dd->makeZeroDensityOperator(nqubits);
dd->incRef(zero);
const auto op1 = dd->makeGateDD(dd::H_MAT, nqubits, 0U);
const auto op2 = dd->makeGateDD(dd::rzMat(dd::PI_4), nqubits, 0U);
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);
state = dd->applyOperationToDensity(state, op2);

Expand Down Expand Up @@ -422,8 +422,8 @@ TEST(DensityMatrixFunctionality, PrintMatrix) {
auto dd = std::make_unique<dd::Package<>>(nqubits);
auto zero = dd->makeZeroDensityOperator(nqubits);
dd->incRef(zero);
const auto op1 = dd->makeGateDD(dd::H_MAT, nqubits, 0U);
const auto op2 = dd->makeGateDD(dd::rzMat(dd::PI_4), nqubits, 0U);
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);
state = dd->applyOperationToDensity(state, op2);

Expand Down

0 comments on commit c40d5a1

Please sign in to comment.