Skip to content

Commit

Permalink
Separate DD package functionality (#75)
Browse files Browse the repository at this point in the history
* ♻️ factor out the DD operations
* ♻️ extract `Simulation` and `FunctionalityConstruction` for decision diagrams
* 🎨 add some `const` where appropriate
* 🎨 fix file header links
* 🎨 use `#pragma once`
* 🔖 v1.10.0
  • Loading branch information
burgholzer authored Mar 28, 2022
1 parent 1a8da60 commit cd15b3e
Show file tree
Hide file tree
Showing 66 changed files with 1,321 additions and 1,346 deletions.
2 changes: 1 addition & 1 deletion .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PointerAlignment: Left
ReflowComments: false
SortIncludes: true
SortIncludes: CaseSensitive
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,4 @@ jobs:
with:
source: 'apps include src test mqt/qfr'
extensions: 'h,hpp,c,cpp'
clangFormatVersion: 12
clangFormatVersion: 13
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.14...3.22)

project(qfr
LANGUAGES CXX
VERSION 1.9.0
VERSION 1.10.0
DESCRIPTION "MQT QFR - A library for Quantum Functionality Representation"
)

Expand Down
2 changes: 1 addition & 1 deletion apps/app.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* This file is part of MQT QCEC library which is released under the MIT license.
* See file README.md or go to http://iic.jku.at/eda/research/quantum/ for more information.
* See file README.md or go to https://www.cda.cit.tum.de//research/quantum/ for more information.
*/

#include "QuantumComputation.hpp"
Expand Down
2 changes: 1 addition & 1 deletion extern/json
Submodule json updated 40 files
+0 −57 .github/ISSUE_TEMPLATE/Bug_report.md
+93 −0 .github/ISSUE_TEMPLATE/bug.yaml
+1 −1 .github/workflows/macos.yml
+9 −2 CMakeLists.txt
+1 −1 benchmarks/CMakeLists.txt
+360 −343 cmake/ci.cmake
+204 −0 cmake/test.cmake
+2 −1 include/nlohmann/detail/conversions/from_json.hpp
+9 −0 include/nlohmann/detail/macro_scope.hpp
+12 −8 include/nlohmann/detail/macro_unscope.hpp
+6 −2 include/nlohmann/detail/meta/cpp_future.hpp
+29 −11 single_include/nlohmann/json.hpp
+100 −132 test/CMakeLists.txt
+1 −3 test/src/unit-algorithms.cpp
+3 −3 test/src/unit-alt-string.cpp
+16 −36 test/src/unit-bson.cpp
+36 −106 test/src/unit-cbor.cpp
+4 −8 test/src/unit-class_const_iterator.cpp
+4 −8 test/src/unit-class_iterator.cpp
+199 −323 test/src/unit-class_parser.cpp
+1 −5 test/src/unit-comparison.cpp
+34 −72 test/src/unit-constructor1.cpp
+2 −6 test/src/unit-convenience.cpp
+142 −269 test/src/unit-conversions.cpp
+16 −46 test/src/unit-deserialization.cpp
+96 −201 test/src/unit-element_access1.cpp
+115 −236 test/src/unit-element_access2.cpp
+0 −7 test/src/unit-items.cpp
+40 −80 test/src/unit-iterators1.cpp
+180 −296 test/src/unit-iterators2.cpp
+59 −106 test/src/unit-json_patch.cpp
+79 −119 test/src/unit-json_pointer.cpp
+37 −97 test/src/unit-modifiers.cpp
+45 −73 test/src/unit-msgpack.cpp
+77 −126 test/src/unit-reference_access.cpp
+37 −104 test/src/unit-regression1.cpp
+3 −64 test/src/unit-regression2.cpp
+4 −8 test/src/unit-serialization.cpp
+32 −64 test/src/unit-ubjson.cpp
+7 −21 test/src/unit-unicode1.cpp
6 changes: 2 additions & 4 deletions include/CircuitOptimizer.hpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
/*
* This file is part of MQT QFR library which is released under the MIT license.
* See file README.md or go to http://iic.jku.at/eda/research/quantum/ for more information.
* See file README.md or go to https://www.cda.cit.tum.de/research/quantum/ for more information.
*/

#ifndef QFR_CIRCUITOPTIMIZER_HPP
#define QFR_CIRCUITOPTIMIZER_HPP
#pragma once

#include "Definitions.hpp"
#include "QuantumComputation.hpp"
Expand Down Expand Up @@ -66,4 +65,3 @@ namespace qc {
static Iterator flattenCompoundOperation(std::vector<std::unique_ptr<Operation>>& ops, Iterator it);
};
} // namespace qc
#endif //QFR_CIRCUITOPTIMIZER_HPP
14 changes: 5 additions & 9 deletions include/Definitions.hpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
/*
* This file is part of MQT QFR library which is released under the MIT license.
* See file README.md or go to http://iic.jku.at/eda/research/quantum/ for more information.
* See file README.md or go to https://www.cda.cit.tum.de/research/quantum/ for more information.
*/

#ifndef QFR_DEFINITIONS_HPP
#define QFR_DEFINITIONS_HPP
#pragma once

#include "dd/Package.hpp"
#include "dd/Control.hpp"
#include "dd/Definitions.hpp"

#include <bitset>
#include <deque>
#include <map>
#include <memory>
Expand Down Expand Up @@ -37,9 +38,6 @@ namespace qc {
using ClassicalRegisterMap = RegisterMap<ClassicalRegister>;
using RegisterNames = std::vector<std::pair<std::string, std::string>>;

using VectorDD = dd::Package::vEdge;
using MatrixDD = dd::Package::mEdge;

using Targets = std::vector<dd::Qubit>;

using BitString = std::bitset<std::numeric_limits<dd::Qubit>::max() + 1>;
Expand Down Expand Up @@ -83,5 +81,3 @@ namespace qc {
using DAGIterators = std::vector<DAGIterator>;
using DAGReverseIterators = std::vector<DAGReverseIterator>;
} // namespace qc

#endif //QFR_DEFINITIONS_HPP
94 changes: 20 additions & 74 deletions include/QuantumComputation.hpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/*
* This file is part of MQT QFR library which is released under the MIT license.
* See file README.md or go to http://iic.jku.at/eda/research/quantum/ for more information.
* See file README.md or go to https://www.cda.cit.tum.de/research/quantum/ for more information.
*/

#ifndef QFR_QUANTUMCOMPUTATION_H
#define QFR_QUANTUMCOMPUTATION_H
#pragma once

#include "Definitions.hpp"
#include "dd/Operations.hpp"
#include "operations/ClassicControlledOperation.hpp"
#include "operations/NonUnitaryOperation.hpp"
#include "operations/StandardOperation.hpp"
Expand Down Expand Up @@ -176,10 +176,10 @@ namespace qc {
mt.seed(seeds);
}
}
explicit QuantumComputation(const std::string& filename, std::size_t seed = 0):
explicit QuantumComputation(const std::string& filename, std::size_t seed = 0U):
seed(seed) {
import(filename);
if (seed != 0) {
if (seed != 0U) {
mt.seed(seed);
} else {
// create and properly seed rng
Expand All @@ -192,9 +192,11 @@ namespace qc {
}
QuantumComputation(const QuantumComputation& qc) = delete;
QuantumComputation(QuantumComputation&& qc) noexcept = default;

QuantumComputation& operator=(const QuantumComputation& qc) = delete;
QuantumComputation& operator=(QuantumComputation&& qc) noexcept = default;
virtual ~QuantumComputation() = default;

virtual ~QuantumComputation() = default;

[[nodiscard]] QuantumComputation clone() const {
auto qc = QuantumComputation(nqubits);
Expand Down Expand Up @@ -247,16 +249,17 @@ namespace qc {
[[nodiscard]] std::pair<std::string, dd::Qubit> getQubitRegisterAndIndex(dd::Qubit physicalQubitIndex) const;
[[nodiscard]] std::pair<std::string, std::size_t> getClassicalRegisterAndIndex(std::size_t classicalIndex) const;

[[nodiscard]] dd::Qubit getIndexFromQubitRegister(const std::pair<std::string, dd::Qubit>& qubit) const;
[[nodiscard]] std::size_t getIndexFromClassicalRegister(const std::pair<std::string, std::size_t>& clbit) const;
[[nodiscard]] bool isIdleQubit(dd::Qubit physicalQubit) const;
[[nodiscard]] bool isLastOperationOnQubit(const decltype(ops.cbegin())& opIt, const decltype(ops.cend())& end) const;
[[nodiscard]] bool physicalQubitIsAncillary(dd::Qubit physicalQubitIndex) const;
[[nodiscard]] bool logicalQubitIsAncillary(dd::Qubit logicalQubitIndex) const { return ancillary[logicalQubitIndex]; }
void setLogicalQubitAncillary(dd::Qubit logicalQubitIndex) { ancillary[logicalQubitIndex] = true; }
[[nodiscard]] bool logicalQubitIsGarbage(dd::Qubit logicalQubitIndex) const { return garbage[logicalQubitIndex]; }
void setLogicalQubitGarbage(dd::Qubit logicalQubitIndex);
MatrixDD createInitialMatrix(std::unique_ptr<dd::Package>& dd) const; // creates identity matrix, which is reduced with respect to the ancillary qubits
[[nodiscard]] dd::Qubit getIndexFromQubitRegister(const std::pair<std::string, dd::Qubit>& qubit) const;
[[nodiscard]] std::size_t getIndexFromClassicalRegister(const std::pair<std::string, std::size_t>& clbit) const;
[[nodiscard]] bool isIdleQubit(dd::Qubit physicalQubit) const;
[[nodiscard]] bool isLastOperationOnQubit(const decltype(ops.cbegin())& opIt, const decltype(ops.cend())& end) const;
[[nodiscard]] bool physicalQubitIsAncillary(dd::Qubit physicalQubitIndex) const;
[[nodiscard]] bool logicalQubitIsAncillary(dd::Qubit logicalQubitIndex) const { return ancillary[logicalQubitIndex]; }
void setLogicalQubitAncillary(dd::Qubit logicalQubitIndex) { ancillary[logicalQubitIndex] = true; }
[[nodiscard]] bool logicalQubitIsGarbage(dd::Qubit logicalQubitIndex) const { return garbage[logicalQubitIndex]; }
void setLogicalQubitGarbage(dd::Qubit logicalQubitIndex);
[[nodiscard]] const std::vector<bool>& getAncillary() const { return ancillary; }
[[nodiscard]] const std::vector<bool>& getGarbage() const { return garbage; }

void i(dd::Qubit target) { emplace_back<StandardOperation>(getNqubits(), target, qc::I); }
void i(dd::Qubit target, const dd::Control& control) { emplace_back<StandardOperation>(getNqubits(), control, target, qc::I); }
Expand Down Expand Up @@ -362,55 +365,6 @@ namespace qc {
/// strip away qubits with no operations applied to them and which do not pop up in the output permutation
/// \param force if true, also strip away idle qubits occurring in the output permutation
void stripIdleQubits(bool force = false, bool reduceIOpermutations = true);
// apply swaps 'on' DD in order to change 'from' to 'to'
// where |from| >= |to|
template<class DDType>
static void changePermutation(DDType& on, Permutation& from, const Permutation& to, std::unique_ptr<dd::Package>& dd, bool regular = true) {
assert(from.size() >= to.size());

// iterate over (k,v) pairs of second permutation
for (const auto& [i, goal]: to) {
// search for key in the first map
auto it = from.find(i);
if (it == from.end()) {
throw QFRException("[changePermutation] Key " + std::to_string(it->first) + " was not found in first permutation. This should never happen.");
}
auto current = it->second;

// permutations agree for this key value
if (current == goal) continue;

// search for goal value in first permutation
dd::Qubit j = 0;
for (const auto& [key, value]: from) {
if (value == goal) {
j = key;
break;
}
}

// swap i and j
auto saved = on;
if constexpr (std::is_same_v<DDType, VectorDD>) {
on = dd->multiply(dd->makeSWAPDD(on.p->v + 1, {}, from.at(i), from.at(j)), on);
} else {
// the regular flag only has an effect on matrix DDs
if (regular) {
on = dd->multiply(dd->makeSWAPDD(on.p->v + 1, {}, from.at(i), from.at(j)), on);
} else {
on = dd->multiply(on, dd->makeSWAPDD(on.p->v + 1, {}, from.at(i), from.at(j)));
}
}

dd->incRef(on);
dd->decRef(saved);
dd->garbageCollect();

// update permutation
from.at(i) = goal;
from.at(j) = current;
}
}

void import(const std::string& filename);
void import(const std::string& filename, Format format);
Expand Down Expand Up @@ -448,14 +402,6 @@ namespace qc {
max_controls = std::max(ncontrols, max_controls);
}

virtual VectorDD simulate(const VectorDD& in, std::unique_ptr<dd::Package>& dd) const;
virtual std::map<std::string, std::size_t> simulate(const VectorDD& in, std::unique_ptr<dd::Package>& dd, std::size_t shots);
virtual MatrixDD buildFunctionality(std::unique_ptr<dd::Package>& dd) const;
virtual MatrixDD buildFunctionalityRecursive(std::unique_ptr<dd::Package>& dd) const;
virtual bool buildFunctionalityRecursive(std::size_t depth, std::size_t opIdx, std::stack<MatrixDD>& s, Permutation& permutation, std::unique_ptr<dd::Package>& dd) const;

virtual void extractProbabilityVector(const VectorDD& in, dd::ProbabilityVector& probVector, std::unique_ptr<dd::Package>& dd);
virtual void extractProbabilityVectorRecursive(const VectorDD& currentState, decltype(ops.begin()) currentIt, std::map<std::size_t, char> measurements, dd::fp commonFactor, dd::ProbabilityVector& probVector, std::unique_ptr<dd::Package>& dd);
/**
* printing
*/
Expand Down Expand Up @@ -549,6 +495,6 @@ namespace qc {
std::vector<std::unique_ptr<Operation>>::iterator insert(std::vector<std::unique_ptr<Operation>>::const_iterator pos, T&& op) { return ops.insert(pos, std::forward<T>(op)); }

[[nodiscard]] const auto& at(std::size_t i) const { return ops.at(i); }
[[nodiscard]] const auto& front() const { return ops.front(); }
};
} // namespace qc
#endif //QFR_QUANTUMCOMPUTATION_H
6 changes: 2 additions & 4 deletions include/algorithms/BernsteinVazirani.hpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
/*
* This file is part of MQT QFR library which is released under the MIT license.
* See file README.md or go to http://iic.jku.at/eda/research/quantum/ for more information.
* See file README.md or go to https://www.cda.cit.tum.de/research/quantum/ for more information.
*/

#ifndef QFR_BV_H
#define QFR_BV_H
#pragma once

#include <QuantumComputation.hpp>
#include <bitset>
Expand All @@ -29,4 +28,3 @@ namespace qc {
void createCircuit();
};
} // namespace qc
#endif //QFR_BV_H
7 changes: 2 additions & 5 deletions include/algorithms/Entanglement.hpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
/*
* This file is part of MQT QFR library which is released under the MIT license.
* See file README.md or go to http://iic.jku.at/eda/research/quantum/ for more information.
* See file README.md or go to https://www.cda.cit.tum.de/research/quantum/ for more information.
*/

#ifndef QFR_ENTANGLEMENT_H
#define QFR_ENTANGLEMENT_H
#pragma once

#include <QuantumComputation.hpp>

Expand All @@ -14,5 +13,3 @@ namespace qc {
explicit Entanglement(dd::QubitCount nq);
};
} // namespace qc

#endif //QFR_ENTANGLEMENT_H
23 changes: 2 additions & 21 deletions include/algorithms/GoogleRandomCircuitSampling.hpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
/*
* This file is part of MQT QFR library which is released under the MIT license.
* See file README.md or go to http://iic.jku.at/eda/research/quantum/ for more information.
* See file README.md or go to https://www.cda.cit.tum.de/research/quantum/ for more information.
*/

#ifndef QFR_GRCS_H
#define QFR_GRCS_H
#pragma once

#include <QuantumComputation.hpp>
#include <chrono>
Expand Down Expand Up @@ -33,22 +32,6 @@ namespace qc {

std::ostream& printStatistics(std::ostream& os) const override;

MatrixDD buildFunctionality(std::unique_ptr<dd::Package>& dd) const override;
MatrixDD buildFunctionality(std::unique_ptr<dd::Package>& dd, unsigned short ncycles) {
if (ncycles < cycles.size() - 2) {
removeCycles(cycles.size() - 2 - ncycles);
}
return buildFunctionality(dd);
}
VectorDD simulate(const VectorDD& in, std::unique_ptr<dd::Package>& dd) const override;
using QuantumComputation::simulate;
VectorDD simulate(unsigned short ncycles, const VectorDD& in, std::unique_ptr<dd::Package>& dd) {
if (ncycles < cycles.size() - 2) {
removeCycles(cycles.size() - 2 - ncycles);
}
return simulate(in, dd);
}

void removeCycles(unsigned short ncycles) {
if (ncycles > cycles.size() - 2) {
std::stringstream ss{};
Expand All @@ -64,5 +47,3 @@ namespace qc {
}
};
} // namespace qc

#endif //QFR_GRCS_H
28 changes: 11 additions & 17 deletions include/algorithms/Grover.hpp
Original file line number Diff line number Diff line change
@@ -1,27 +1,18 @@
/*
* This file is part of MQT QFR library which is released under the MIT license.
* See file README.md or go to http://iic.jku.at/eda/research/quantum/ for more information.
* See file README.md or go to https://www.cda.cit.tum.de/research/quantum/ for more information.
*/

#ifndef QFR_GROVER_H
#define QFR_GROVER_H
#pragma once

#include "QuantumComputation.hpp"

#include <QuantumComputation.hpp>
#include <bitset>
#include <functional>
#include <random>

namespace qc {
class Grover: public QuantumComputation {
protected:
void setup(QuantumComputation& qc) const;

void oracle(QuantumComputation& qc) const;

void diffusion(QuantumComputation& qc) const;

void full_grover(QuantumComputation& qc) const;

public:
std::size_t seed = 0;
BitString targetValue = 0;
Expand All @@ -31,11 +22,14 @@ namespace qc {

explicit Grover(dd::QubitCount nq, std::size_t seed = 0);

MatrixDD buildFunctionality(std::unique_ptr<dd::Package>& dd) const override;
MatrixDD buildFunctionalityRecursive(std::unique_ptr<dd::Package>& dd) const override;
void setup(QuantumComputation& qc) const;

void oracle(QuantumComputation& qc) const;

void diffusion(QuantumComputation& qc) const;

void full_grover(QuantumComputation& qc) const;

std::ostream& printStatistics(std::ostream& os) const override;
};
} // namespace qc

#endif //QFR_GROVER_H
7 changes: 2 additions & 5 deletions include/algorithms/QFT.hpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
/*
* This file is part of MQT QFR library which is released under the MIT license.
* See file README.md or go to http://iic.jku.at/eda/research/quantum/ for more information.
* See file README.md or go to https://www.cda.cit.tum.de/research/quantum/ for more information.
*/

#ifndef QFR_QFT_H
#define QFR_QFT_H
#pragma once

#include "QuantumComputation.hpp"

Expand All @@ -23,5 +22,3 @@ namespace qc {
void createCircuit();
};
} // namespace qc

#endif //QFR_QFT_H
Loading

0 comments on commit cd15b3e

Please sign in to comment.