Skip to content

Commit

Permalink
🩹 disentangle mqt-core-dd and mqt-core-algo (#670)
Browse files Browse the repository at this point in the history
## Description

This PR is a follow-up to #668 and fixes an overlooked dependency of the
`mqt-core-dd` library on the `mqt-core-algo` library that somehow went
unnoticed in the original PR.
To this end, this PR reverts parts of #452 and moves the respective
benchmarking code to the evaluation target.

## 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 <[email protected]>
  • Loading branch information
burgholzer authored Aug 14, 2024
1 parent 2662795 commit 21da251
Show file tree
Hide file tree
Showing 11 changed files with 325 additions and 303 deletions.
172 changes: 171 additions & 1 deletion eval/eval_dd_package.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
#include "algorithms/RandomCliffordCircuit.hpp"
#include "algorithms/WState.hpp"
#include "circuit_optimizer/CircuitOptimizer.hpp"
#include "dd/Benchmark.hpp"
#include "dd/FunctionalityConstruction.hpp"
#include "dd/Package.hpp"
#include "dd/Simulation.hpp"
#include "dd/statistics/PackageStatistics.hpp"
#include "ir/QuantumComputation.hpp"

#include <array>
#include <bitset>
Expand All @@ -20,13 +21,182 @@
#include <fstream>
#include <ios>
#include <iostream>
#include <map>
#include <memory>
#include <nlohmann/json.hpp>
#include <string>
#include <utility>

namespace dd {

struct Experiment {
std::unique_ptr<Package<>> dd;
nlohmann::basic_json<> stats = nlohmann::basic_json<>::object();
std::chrono::duration<double> runtime{};

Experiment() = default;
Experiment(const Experiment&) = delete;
Experiment(Experiment&&) = default;
Experiment& operator=(const Experiment&) = delete;
Experiment& operator=(Experiment&&) = default;
virtual ~Experiment() = default;

[[nodiscard]] virtual bool success() const noexcept { return false; }
};

struct SimulationExperiment : public Experiment {
SimulationExperiment() = default;
qc::VectorDD sim{};

[[nodiscard]] bool success() const noexcept override {
return sim.p != nullptr;
}
};

struct FunctionalityConstructionExperiment : public Experiment {
qc::MatrixDD func{};

[[nodiscard]] bool success() const noexcept override {
return func.p != nullptr;
}
};

template <class Config>
MatrixDD buildFunctionality(const qc::Grover* qc, Package<Config>& dd) {
QuantumComputation groverIteration(qc->getNqubits());
qc->oracle(groverIteration);
qc->diffusion(groverIteration);

auto iteration = buildFunctionality(&groverIteration, 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();
}

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

dd.decRef(iteration);
return e;
}

template <class Config>
MatrixDD buildFunctionalityRecursive(const qc::Grover* qc,
Package<Config>& dd) {
QuantumComputation groverIteration(qc->getNqubits());
qc->oracle(groverIteration);
qc->diffusion(groverIteration);

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)));
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;
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();
}
}
}
dd.decRef(f);

// 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;
}

std::unique_ptr<SimulationExperiment>
benchmarkSimulate(const QuantumComputation& qc) {
std::unique_ptr<SimulationExperiment> exp =
std::make_unique<SimulationExperiment>();
const auto nq = qc.getNqubits();
exp->dd = std::make_unique<Package<>>(nq);
const auto start = std::chrono::high_resolution_clock::now();
const auto in = exp->dd->makeZeroState(nq);
exp->sim = simulate(&qc, in, *(exp->dd));
const auto end = std::chrono::high_resolution_clock::now();
exp->runtime =
std::chrono::duration_cast<std::chrono::duration<double>>(end - start);
exp->stats = dd::getStatistics(exp->dd.get());
return exp;
}

std::unique_ptr<FunctionalityConstructionExperiment>
benchmarkFunctionalityConstruction(const QuantumComputation& qc,
const bool recursive = false) {
std::unique_ptr<FunctionalityConstructionExperiment> exp =
std::make_unique<FunctionalityConstructionExperiment>();
const auto nq = qc.getNqubits();
exp->dd = std::make_unique<Package<>>(nq);
const auto start = std::chrono::high_resolution_clock::now();

if (const auto* grover = dynamic_cast<const Grover*>(&qc)) {
if (recursive) {
exp->func = buildFunctionalityRecursive(grover, *(exp->dd));
} else {
exp->func = buildFunctionality(grover, *(exp->dd));
}
} else {
if (recursive) {
exp->func = buildFunctionalityRecursive(&qc, *(exp->dd));
} else {
exp->func = buildFunctionality(&qc, *(exp->dd));
}
}
const auto end = std::chrono::high_resolution_clock::now();
exp->runtime =
std::chrono::duration_cast<std::chrono::duration<double>>(end - start);
exp->stats = dd::getStatistics(exp->dd.get());
return exp;
}

std::map<std::string, std::size_t>
benchmarkSimulateWithShots(const qc::QuantumComputation& qc,
const std::size_t shots) {
auto nq = qc.getNqubits();
auto dd = std::make_unique<dd::Package<>>(nq);
auto in = dd->makeZeroState(nq);
auto measurements = simulate(&qc, in, *dd, shots);
return measurements;
}

static constexpr std::size_t SEED = 42U;

class BenchmarkDDPackage {
Expand Down
59 changes: 0 additions & 59 deletions include/mqt-core/dd/Benchmark.hpp

This file was deleted.

Loading

0 comments on commit 21da251

Please sign in to comment.