Skip to content

Commit cd15b3e

Browse files
authored
Separate DD package functionality (#75)
* ♻️ 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
1 parent 1a8da60 commit cd15b3e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+1321
-1346
lines changed

.clang-format

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ ObjCSpaceAfterProperty: false
5656
ObjCSpaceBeforeProtocolList: true
5757
PointerAlignment: Left
5858
ReflowComments: false
59-
SortIncludes: true
59+
SortIncludes: CaseSensitive
6060
SpaceAfterCStyleCast: false
6161
SpaceAfterLogicalNot: false
6262
SpaceAfterTemplateKeyword: false

.github/workflows/ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,4 +96,4 @@ jobs:
9696
with:
9797
source: 'apps include src test mqt/qfr'
9898
extensions: 'h,hpp,c,cpp'
99-
clangFormatVersion: 12
99+
clangFormatVersion: 13

CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.14...3.22)
22

33
project(qfr
44
LANGUAGES CXX
5-
VERSION 1.9.0
5+
VERSION 1.10.0
66
DESCRIPTION "MQT QFR - A library for Quantum Functionality Representation"
77
)
88

apps/app.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* This file is part of MQT QCEC library which is released under the MIT license.
3-
* See file README.md or go to http://iic.jku.at/eda/research/quantum/ for more information.
3+
* See file README.md or go to https://www.cda.cit.tum.de//research/quantum/ for more information.
44
*/
55

66
#include "QuantumComputation.hpp"

include/CircuitOptimizer.hpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
/*
22
* This file is part of MQT QFR library which is released under the MIT license.
3-
* See file README.md or go to http://iic.jku.at/eda/research/quantum/ for more information.
3+
* See file README.md or go to https://www.cda.cit.tum.de/research/quantum/ for more information.
44
*/
55

6-
#ifndef QFR_CIRCUITOPTIMIZER_HPP
7-
#define QFR_CIRCUITOPTIMIZER_HPP
6+
#pragma once
87

98
#include "Definitions.hpp"
109
#include "QuantumComputation.hpp"
@@ -66,4 +65,3 @@ namespace qc {
6665
static Iterator flattenCompoundOperation(std::vector<std::unique_ptr<Operation>>& ops, Iterator it);
6766
};
6867
} // namespace qc
69-
#endif //QFR_CIRCUITOPTIMIZER_HPP

include/Definitions.hpp

+5-9
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
/*
22
* This file is part of MQT QFR library which is released under the MIT license.
3-
* See file README.md or go to http://iic.jku.at/eda/research/quantum/ for more information.
3+
* See file README.md or go to https://www.cda.cit.tum.de/research/quantum/ for more information.
44
*/
55

6-
#ifndef QFR_DEFINITIONS_HPP
7-
#define QFR_DEFINITIONS_HPP
6+
#pragma once
87

9-
#include "dd/Package.hpp"
8+
#include "dd/Control.hpp"
9+
#include "dd/Definitions.hpp"
1010

11+
#include <bitset>
1112
#include <deque>
1213
#include <map>
1314
#include <memory>
@@ -37,9 +38,6 @@ namespace qc {
3738
using ClassicalRegisterMap = RegisterMap<ClassicalRegister>;
3839
using RegisterNames = std::vector<std::pair<std::string, std::string>>;
3940

40-
using VectorDD = dd::Package::vEdge;
41-
using MatrixDD = dd::Package::mEdge;
42-
4341
using Targets = std::vector<dd::Qubit>;
4442

4543
using BitString = std::bitset<std::numeric_limits<dd::Qubit>::max() + 1>;
@@ -83,5 +81,3 @@ namespace qc {
8381
using DAGIterators = std::vector<DAGIterator>;
8482
using DAGReverseIterators = std::vector<DAGReverseIterator>;
8583
} // namespace qc
86-
87-
#endif //QFR_DEFINITIONS_HPP

include/QuantumComputation.hpp

+20-74
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
/*
22
* This file is part of MQT QFR library which is released under the MIT license.
3-
* See file README.md or go to http://iic.jku.at/eda/research/quantum/ for more information.
3+
* See file README.md or go to https://www.cda.cit.tum.de/research/quantum/ for more information.
44
*/
55

6-
#ifndef QFR_QUANTUMCOMPUTATION_H
7-
#define QFR_QUANTUMCOMPUTATION_H
6+
#pragma once
87

98
#include "Definitions.hpp"
9+
#include "dd/Operations.hpp"
1010
#include "operations/ClassicControlledOperation.hpp"
1111
#include "operations/NonUnitaryOperation.hpp"
1212
#include "operations/StandardOperation.hpp"
@@ -176,10 +176,10 @@ namespace qc {
176176
mt.seed(seeds);
177177
}
178178
}
179-
explicit QuantumComputation(const std::string& filename, std::size_t seed = 0):
179+
explicit QuantumComputation(const std::string& filename, std::size_t seed = 0U):
180180
seed(seed) {
181181
import(filename);
182-
if (seed != 0) {
182+
if (seed != 0U) {
183183
mt.seed(seed);
184184
} else {
185185
// create and properly seed rng
@@ -192,9 +192,11 @@ namespace qc {
192192
}
193193
QuantumComputation(const QuantumComputation& qc) = delete;
194194
QuantumComputation(QuantumComputation&& qc) noexcept = default;
195+
195196
QuantumComputation& operator=(const QuantumComputation& qc) = delete;
196197
QuantumComputation& operator=(QuantumComputation&& qc) noexcept = default;
197-
virtual ~QuantumComputation() = default;
198+
199+
virtual ~QuantumComputation() = default;
198200

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

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

261264
void i(dd::Qubit target) { emplace_back<StandardOperation>(getNqubits(), target, qc::I); }
262265
void i(dd::Qubit target, const dd::Control& control) { emplace_back<StandardOperation>(getNqubits(), control, target, qc::I); }
@@ -362,55 +365,6 @@ namespace qc {
362365
/// strip away qubits with no operations applied to them and which do not pop up in the output permutation
363366
/// \param force if true, also strip away idle qubits occurring in the output permutation
364367
void stripIdleQubits(bool force = false, bool reduceIOpermutations = true);
365-
// apply swaps 'on' DD in order to change 'from' to 'to'
366-
// where |from| >= |to|
367-
template<class DDType>
368-
static void changePermutation(DDType& on, Permutation& from, const Permutation& to, std::unique_ptr<dd::Package>& dd, bool regular = true) {
369-
assert(from.size() >= to.size());
370-
371-
// iterate over (k,v) pairs of second permutation
372-
for (const auto& [i, goal]: to) {
373-
// search for key in the first map
374-
auto it = from.find(i);
375-
if (it == from.end()) {
376-
throw QFRException("[changePermutation] Key " + std::to_string(it->first) + " was not found in first permutation. This should never happen.");
377-
}
378-
auto current = it->second;
379-
380-
// permutations agree for this key value
381-
if (current == goal) continue;
382-
383-
// search for goal value in first permutation
384-
dd::Qubit j = 0;
385-
for (const auto& [key, value]: from) {
386-
if (value == goal) {
387-
j = key;
388-
break;
389-
}
390-
}
391-
392-
// swap i and j
393-
auto saved = on;
394-
if constexpr (std::is_same_v<DDType, VectorDD>) {
395-
on = dd->multiply(dd->makeSWAPDD(on.p->v + 1, {}, from.at(i), from.at(j)), on);
396-
} else {
397-
// the regular flag only has an effect on matrix DDs
398-
if (regular) {
399-
on = dd->multiply(dd->makeSWAPDD(on.p->v + 1, {}, from.at(i), from.at(j)), on);
400-
} else {
401-
on = dd->multiply(on, dd->makeSWAPDD(on.p->v + 1, {}, from.at(i), from.at(j)));
402-
}
403-
}
404-
405-
dd->incRef(on);
406-
dd->decRef(saved);
407-
dd->garbageCollect();
408-
409-
// update permutation
410-
from.at(i) = goal;
411-
from.at(j) = current;
412-
}
413-
}
414368

415369
void import(const std::string& filename);
416370
void import(const std::string& filename, Format format);
@@ -448,14 +402,6 @@ namespace qc {
448402
max_controls = std::max(ncontrols, max_controls);
449403
}
450404

451-
virtual VectorDD simulate(const VectorDD& in, std::unique_ptr<dd::Package>& dd) const;
452-
virtual std::map<std::string, std::size_t> simulate(const VectorDD& in, std::unique_ptr<dd::Package>& dd, std::size_t shots);
453-
virtual MatrixDD buildFunctionality(std::unique_ptr<dd::Package>& dd) const;
454-
virtual MatrixDD buildFunctionalityRecursive(std::unique_ptr<dd::Package>& dd) const;
455-
virtual bool buildFunctionalityRecursive(std::size_t depth, std::size_t opIdx, std::stack<MatrixDD>& s, Permutation& permutation, std::unique_ptr<dd::Package>& dd) const;
456-
457-
virtual void extractProbabilityVector(const VectorDD& in, dd::ProbabilityVector& probVector, std::unique_ptr<dd::Package>& dd);
458-
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);
459405
/**
460406
* printing
461407
*/
@@ -549,6 +495,6 @@ namespace qc {
549495
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)); }
550496

551497
[[nodiscard]] const auto& at(std::size_t i) const { return ops.at(i); }
498+
[[nodiscard]] const auto& front() const { return ops.front(); }
552499
};
553500
} // namespace qc
554-
#endif //QFR_QUANTUMCOMPUTATION_H

include/algorithms/BernsteinVazirani.hpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
/*
22
* This file is part of MQT QFR library which is released under the MIT license.
3-
* See file README.md or go to http://iic.jku.at/eda/research/quantum/ for more information.
3+
* See file README.md or go to https://www.cda.cit.tum.de/research/quantum/ for more information.
44
*/
55

6-
#ifndef QFR_BV_H
7-
#define QFR_BV_H
6+
#pragma once
87

98
#include <QuantumComputation.hpp>
109
#include <bitset>
@@ -29,4 +28,3 @@ namespace qc {
2928
void createCircuit();
3029
};
3130
} // namespace qc
32-
#endif //QFR_BV_H

include/algorithms/Entanglement.hpp

+2-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
/*
22
* This file is part of MQT QFR library which is released under the MIT license.
3-
* See file README.md or go to http://iic.jku.at/eda/research/quantum/ for more information.
3+
* See file README.md or go to https://www.cda.cit.tum.de/research/quantum/ for more information.
44
*/
55

6-
#ifndef QFR_ENTANGLEMENT_H
7-
#define QFR_ENTANGLEMENT_H
6+
#pragma once
87

98
#include <QuantumComputation.hpp>
109

@@ -14,5 +13,3 @@ namespace qc {
1413
explicit Entanglement(dd::QubitCount nq);
1514
};
1615
} // namespace qc
17-
18-
#endif //QFR_ENTANGLEMENT_H

include/algorithms/GoogleRandomCircuitSampling.hpp

+2-21
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
/*
22
* This file is part of MQT QFR library which is released under the MIT license.
3-
* See file README.md or go to http://iic.jku.at/eda/research/quantum/ for more information.
3+
* See file README.md or go to https://www.cda.cit.tum.de/research/quantum/ for more information.
44
*/
55

6-
#ifndef QFR_GRCS_H
7-
#define QFR_GRCS_H
6+
#pragma once
87

98
#include <QuantumComputation.hpp>
109
#include <chrono>
@@ -33,22 +32,6 @@ namespace qc {
3332

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

36-
MatrixDD buildFunctionality(std::unique_ptr<dd::Package>& dd) const override;
37-
MatrixDD buildFunctionality(std::unique_ptr<dd::Package>& dd, unsigned short ncycles) {
38-
if (ncycles < cycles.size() - 2) {
39-
removeCycles(cycles.size() - 2 - ncycles);
40-
}
41-
return buildFunctionality(dd);
42-
}
43-
VectorDD simulate(const VectorDD& in, std::unique_ptr<dd::Package>& dd) const override;
44-
using QuantumComputation::simulate;
45-
VectorDD simulate(unsigned short ncycles, const VectorDD& in, std::unique_ptr<dd::Package>& dd) {
46-
if (ncycles < cycles.size() - 2) {
47-
removeCycles(cycles.size() - 2 - ncycles);
48-
}
49-
return simulate(in, dd);
50-
}
51-
5235
void removeCycles(unsigned short ncycles) {
5336
if (ncycles > cycles.size() - 2) {
5437
std::stringstream ss{};
@@ -64,5 +47,3 @@ namespace qc {
6447
}
6548
};
6649
} // namespace qc
67-
68-
#endif //QFR_GRCS_H

include/algorithms/Grover.hpp

+11-17
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,18 @@
11
/*
22
* This file is part of MQT QFR library which is released under the MIT license.
3-
* See file README.md or go to http://iic.jku.at/eda/research/quantum/ for more information.
3+
* See file README.md or go to https://www.cda.cit.tum.de/research/quantum/ for more information.
44
*/
55

6-
#ifndef QFR_GROVER_H
7-
#define QFR_GROVER_H
6+
#pragma once
7+
8+
#include "QuantumComputation.hpp"
89

9-
#include <QuantumComputation.hpp>
1010
#include <bitset>
1111
#include <functional>
1212
#include <random>
1313

1414
namespace qc {
1515
class Grover: public QuantumComputation {
16-
protected:
17-
void setup(QuantumComputation& qc) const;
18-
19-
void oracle(QuantumComputation& qc) const;
20-
21-
void diffusion(QuantumComputation& qc) const;
22-
23-
void full_grover(QuantumComputation& qc) const;
24-
2516
public:
2617
std::size_t seed = 0;
2718
BitString targetValue = 0;
@@ -31,11 +22,14 @@ namespace qc {
3122

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

34-
MatrixDD buildFunctionality(std::unique_ptr<dd::Package>& dd) const override;
35-
MatrixDD buildFunctionalityRecursive(std::unique_ptr<dd::Package>& dd) const override;
25+
void setup(QuantumComputation& qc) const;
26+
27+
void oracle(QuantumComputation& qc) const;
28+
29+
void diffusion(QuantumComputation& qc) const;
30+
31+
void full_grover(QuantumComputation& qc) const;
3632

3733
std::ostream& printStatistics(std::ostream& os) const override;
3834
};
3935
} // namespace qc
40-
41-
#endif //QFR_GROVER_H

include/algorithms/QFT.hpp

+2-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
/*
22
* This file is part of MQT QFR library which is released under the MIT license.
3-
* See file README.md or go to http://iic.jku.at/eda/research/quantum/ for more information.
3+
* See file README.md or go to https://www.cda.cit.tum.de/research/quantum/ for more information.
44
*/
55

6-
#ifndef QFR_QFT_H
7-
#define QFR_QFT_H
6+
#pragma once
87

98
#include "QuantumComputation.hpp"
109

@@ -23,5 +22,3 @@ namespace qc {
2322
void createCircuit();
2423
};
2524
} // namespace qc
26-
27-
#endif //QFR_QFT_H

0 commit comments

Comments
 (0)