Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🚸 Support for adding tests to NALAC #629

Merged
merged 24 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
07d7610
🚸 Make changes required for NA mapper tests
ystade Jun 7, 2024
e50e692
Merge remote-tracking branch 'origin/main' into wip-test-na-map
ystade Jun 7, 2024
461778c
🎨 pre-commit fixes
pre-commit-ci[bot] Jun 7, 2024
0ef9568
💚 Satisfy Linter
ystade Jun 7, 2024
63a7640
✅ Increase test coverage
ystade Jun 7, 2024
b358327
🎨 pre-commit fixes
pre-commit-ci[bot] Jun 7, 2024
d3f3978
🐛 Fix tests
ystade Jun 7, 2024
7f66b97
🎨 Apply suggested changes
ystade Jun 7, 2024
f0dfa71
🎨 pre-commit fixes
pre-commit-ci[bot] Jun 7, 2024
2d5d332
🎨 Satisfy Linter
ystade Jun 7, 2024
6da1a45
✅ Increse test coverage
ystade Jun 7, 2024
9c757ed
🎨 Apply suggested changes
ystade Jun 7, 2024
569f5e1
🎨 Apply suggested changes
ystade Jun 7, 2024
aa55400
🎨 pre-commit fixes
pre-commit-ci[bot] Jun 7, 2024
89a0177
🎨 Apply suggested changes
ystade Jun 7, 2024
9ee159b
🐛 Finally get this to work
ystade Jun 7, 2024
9213a0a
🎨 pre-commit fixes
pre-commit-ci[bot] Jun 7, 2024
7de26d6
🔥 remove redundant override for `getUsedQubits`
burgholzer Jun 7, 2024
85e300e
🚸 new `getControls` and `getTargets` methods with permutations
burgholzer Jun 7, 2024
d4008d7
⏪ revert unnecessary change
burgholzer Jun 7, 2024
21bbab7
♻️ adjusted `getUsedQubits` to `getUsedQubitsPermuted`
burgholzer Jun 7, 2024
41da4ba
♻️ optimize the `equals` method
burgholzer Jun 7, 2024
01b4870
🚨 include missing header
burgholzer Jun 7, 2024
5ebe377
♻️ even simpler implementation
burgholzer Jun 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion include/mqt-core/na/NAComputation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ class NAComputation {
}
auto clear(const bool clearInitialPositions = true) -> void {
operations.clear();
initialPositions.clear();
if (clearInitialPositions) {
initialPositions.clear();
}
Expand Down
9 changes: 9 additions & 0 deletions include/mqt-core/na/NADefinitions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,12 @@ template <> struct std::hash<na::FullOpType> {
return qc::combineHash(h1, h2);
}
};

/// Hash function for Point, e.g., for use in unordered_map
template <> struct std::hash<na::Point> {
std::size_t operator()(const na::Point& p) const noexcept {
const std::size_t h1 = std::hash<decltype(p.x)>{}(p.x);
const std::size_t h2 = std::hash<decltype(p.y)>{}(p.y);
return qc::combineHash(h1, h2);
}
};
1 change: 1 addition & 0 deletions include/mqt-core/na/operations/NAGlobalOperation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class NAGlobalOperation : public NAOperation {
[[nodiscard]] auto getParams() const -> const std::vector<qc::fp>& {
return params;
}
[[nodiscard]] auto getType() const -> FullOpType { return type; }
[[nodiscard]] auto isGlobalOperation() const -> bool override { return true; }
[[nodiscard]] auto toString() const -> std::string override;
[[nodiscard]] auto clone() const -> std::unique_ptr<NAOperation> override {
Expand Down
5 changes: 4 additions & 1 deletion include/mqt-core/operations/CompoundOperation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@

std::vector<std::unique_ptr<Operation>>& getOps() { return ops; }

[[nodiscard]] std::set<Qubit> getUsedQubits() const override;
[[nodiscard]] std::set<Qubit>
getUsedQubits(const std::function<Qubit(Qubit)>& perm = [](Qubit q) {

Check warning on line 66 in include/mqt-core/operations/CompoundOperation.hpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

include/mqt-core/operations/CompoundOperation.hpp:66:3 [google-default-arguments]

default arguments on virtual or override methods are prohibited
ystade marked this conversation as resolved.
Show resolved Hide resolved
return q;
}) const override;

[[nodiscard]] auto commutesAtQubit(const Operation& other,
const Qubit& qubit) const -> bool override;
Expand Down
11 changes: 9 additions & 2 deletions include/mqt-core/operations/NonUnitaryOperation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,16 @@
std::vector<Bit>& getClassics() { return classics; }
[[nodiscard]] std::size_t getNclassics() const { return classics.size(); }

[[nodiscard]] std::set<Qubit> getUsedQubits() const override {
[[nodiscard]] std::set<Qubit>
getUsedQubits(const std::function<Qubit(Qubit)>& perm = [](Qubit q) {

Check warning on line 51 in include/mqt-core/operations/NonUnitaryOperation.hpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

include/mqt-core/operations/NonUnitaryOperation.hpp:51:3 [google-default-arguments]

default arguments on virtual or override methods are prohibited
return q;
}) const override {
const auto& opTargets = getTargets();
return {opTargets.begin(), opTargets.end()};
std::set<Qubit> usedQubits;
for (const auto& target : opTargets) {
usedQubits.emplace(perm(target));
}
return usedQubits;
}

[[nodiscard]] const Controls& getControls() const override {
Expand Down
12 changes: 9 additions & 3 deletions include/mqt-core/operations/Operation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,18 @@
[[nodiscard]] const std::string& getName() const { return name; }
[[nodiscard]] virtual OpType getType() const { return type; }

[[nodiscard]] virtual std::set<Qubit> getUsedQubits() const {
[[nodiscard]] virtual auto
getUsedQubits(const std::function<Qubit(Qubit)>& perm = [](Qubit q) {

Check warning on line 72 in include/mqt-core/operations/Operation.hpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

include/mqt-core/operations/Operation.hpp:72:3 [google-default-arguments]

default arguments on virtual or override methods are prohibited
return q;
}) const -> std::set<Qubit> {
const auto& opTargets = getTargets();
const auto& opControls = getControls();
std::set<Qubit> usedQubits = {opTargets.begin(), opTargets.end()};
std::set<Qubit> usedQubits;
for (const auto& target : opTargets) {
usedQubits.emplace(perm(target));
}
for (const auto& control : opControls) {
usedQubits.insert(control.qubit);
usedQubits.emplace(perm(control.qubit));
}
return usedQubits;
}
Expand Down
11 changes: 7 additions & 4 deletions src/na/NAComputation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@ auto NAComputation::toString() const -> std::string {
std::stringstream ss;
ss << "init at ";
for (const auto& p : initialPositions) {
ss << "(" << p->x << ", " << p->y << ")"
<< ", ";
ss << *p << ", ";
}
if (ss.tellp() == 8) {
ss.seekp(-1, std::ios_base::end);
ystade marked this conversation as resolved.
Show resolved Hide resolved
} else {
ss.seekp(-2, std::ios_base::end);
}
ss.seekp(-2, std::ios_base::end);
ss << ";\n";
for (const auto& op : operations) {
ss << op->toString();
ss << *op;
}
return ss.str();
}
Expand Down
10 changes: 7 additions & 3 deletions src/na/operations/NALocalOperation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@ auto NALocalOperation::toString() const -> std::string {
ss << ")";
}
ss << " at ";
for (const auto& p : positions) {
ss << *p << ", ";
if (positions.empty()) {
ss.seekp(-1, std::ios_base::end);
ystade marked this conversation as resolved.
Show resolved Hide resolved
} else {
for (const auto& p : positions) {
ss << *p << ", ";
}
ss.seekp(-2, std::ios_base::end);
}
ss.seekp(-2, std::ios_base::end);
ss << ";\n";
return ss.str();
}
Expand Down
5 changes: 3 additions & 2 deletions src/operations/CompoundOperation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,11 @@
}
}

std::set<Qubit> CompoundOperation::getUsedQubits() const {
std::set<Qubit> CompoundOperation::getUsedQubits(

Check warning on line 163 in src/operations/CompoundOperation.cpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

src/operations/CompoundOperation.cpp:163:36 [google-default-arguments]

default arguments on virtual or override methods are prohibited
const std::function<Qubit(Qubit)>& perm) const {
std::set<Qubit> usedQubits{};
for (const auto& op : ops) {
usedQubits.merge(op->getUsedQubits());
usedQubits.merge(op->getUsedQubits(perm));
}
return usedQubits;
}
Expand Down Expand Up @@ -194,14 +195,14 @@
assert(!thisUsedQubits.empty());
const auto thisMaxQubit =
*std::max_element(thisUsedQubits.cbegin(), thisUsedQubits.cend());
QuantumComputation thisQc(thisMaxQubit + 1);

Check warning on line 198 in src/operations/CompoundOperation.cpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

src/operations/CompoundOperation.cpp:198:5 [misc-const-correctness]

variable 'thisQc' of type 'QuantumComputation' can be declared 'const'
std::for_each(cbegin(), cend(),
[&](const auto& op) { thisQc.emplace_back(op->clone()); });
const auto& otherUsedQubits = co.getUsedQubits();
assert(!otherUsedQubits.empty());
const auto otherMaxQubit =
*std::max_element(otherUsedQubits.cbegin(), otherUsedQubits.cend());
QuantumComputation otherQc(otherMaxQubit + 1);

Check warning on line 205 in src/operations/CompoundOperation.cpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

src/operations/CompoundOperation.cpp:205:5 [misc-const-correctness]

variable 'otherQc' of type 'QuantumComputation' can be declared 'const'
std::for_each(co.cbegin(), co.cend(),
[&](const auto& op) { otherQc.emplace_back(op->clone()); });
CircuitOptimizer::reorderOperations(thisQc);
Expand Down
40 changes: 40 additions & 0 deletions src/operations/Operation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,46 @@
return false;
}

if (isDiagonalGate()) {
// check pos. controls and targets together
std::set<Qubit> usedQubits1 =

Check warning on line 126 in src/operations/Operation.cpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

src/operations/Operation.cpp:126:5 [misc-const-correctness]

variable 'usedQubits1' of type 'std::set<Qubit>' (aka 'set<unsigned int>') can be declared 'const'
perm1.empty()
? getUsedQubits()
: getUsedQubits([&perm1](const auto& q) { return perm1.at(q); });

std::set<Qubit> usedQubits2 =

Check warning on line 131 in src/operations/Operation.cpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

src/operations/Operation.cpp:131:5 [misc-const-correctness]

variable 'usedQubits2' of type 'std::set<Qubit>' (aka 'set<unsigned int>') can be declared 'const'
perm2.empty()
? getUsedQubits()
: getUsedQubits([&perm2](const auto& q) { return perm2.at(q); });

if (usedQubits1 != usedQubits2) {
return false;
}

std::set<Qubit> negControls1{};

Check warning on line 140 in src/operations/Operation.cpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

src/operations/Operation.cpp:140:5 [misc-const-correctness]

variable 'negControls1' of type 'std::set<Qubit>' (aka 'set<unsigned int>') can be declared 'const'
for (const auto& control : getControls()) {
if (control.type == Control::Type::Neg) {
if (perm1.empty()) {
negControls1.emplace(control.qubit);
} else {
negControls1.emplace(perm1.at(control.qubit));
}
}
}

std::set<Qubit> negControls2{};

Check warning on line 151 in src/operations/Operation.cpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

src/operations/Operation.cpp:151:5 [misc-const-correctness]

variable 'negControls2' of type 'std::set<Qubit>' (aka 'set<unsigned int>') can be declared 'const'
for (const auto& control : op.getControls()) {
if (control.type == Control::Type::Neg) {
if (perm2.empty()) {
negControls2.emplace(control.qubit);
} else {
negControls2.emplace(perm2.at(control.qubit));
}
}
}

return negControls1 == negControls2;
ystade marked this conversation as resolved.
Show resolved Hide resolved
}
// check controls
if (nc1 != 0U) {
Controls controls1{};
Expand Down
7 changes: 7 additions & 0 deletions test/na/test_nacomputation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,11 @@ TEST(NAComputation, General) {
"move (0, 1), (1, 1) to (4, 1), (5, 1);\n"
"store (4, 1), (5, 1) to (4, 0), (5, 0);\n");
}

TEST(NAComputation, EmptyPrint) {
const NAComputation qc;
std::stringstream ss;
ss << qc;
EXPECT_EQ(ss.str(), "init at;\n");
}
} // namespace na
9 changes: 9 additions & 0 deletions test/na/test_naoperation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <gtest/gtest.h>
#include <memory>
#include <sstream>
#include <vector>

namespace na {
Expand Down Expand Up @@ -49,4 +50,12 @@ TEST(NAOperation, LocalOperation) {
EXPECT_ANY_THROW(
NALocalOperation(FullOpType{qc::RY, 1}, std::make_shared<Point>(0, 0)));
}

TEST(NAOperation, EmptyPrint) {
const NALocalOperation op(FullOpType{qc::RY, 0}, std::vector{qc::PI_2},
std::vector<std::shared_ptr<Point>>{});
std::stringstream ss;
ss << op;
EXPECT_EQ(ss.str(), "ry(1.5708) at;\n");
}
} // namespace na
19 changes: 19 additions & 0 deletions test/test_operation.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "Definitions.hpp"
#include "Permutation.hpp"
#include "operations/AodOperation.hpp"
#include "operations/CompoundOperation.hpp"
#include "operations/Expression.hpp"
Expand Down Expand Up @@ -139,6 +140,24 @@ TEST(Operation, IsDiagonalGate) {
EXPECT_TRUE(op2.isDiagonalGate());
}

TEST(Operation, Equality) {
const qc::StandardOperation op1(0, qc::Z);
const qc::StandardOperation op2(1, 0, qc::Z);
const qc::StandardOperation op3(0, 1, qc::Z);
const qc::StandardOperation op4({0, qc::Control::Type::Neg}, 1, qc::Z);
EXPECT_FALSE(op1 == op2);
EXPECT_TRUE(op2 == op3);
EXPECT_TRUE(op3 == op2);
EXPECT_FALSE(op2 == op4);

EXPECT_TRUE(op2.equals(op3, qc::Permutation{{{0, 0}, {1, 2}}},
qc::Permutation{{{0, 2}, {1, 0}}}));
EXPECT_FALSE(
op2.equals(op3, qc::Permutation{{{0, 0}, {1, 2}}}, qc::Permutation{}));
EXPECT_FALSE(op2.equals(op4, qc::Permutation{{{0, 0}, {1, 2}}},
qc::Permutation{{{0, 2}, {1, 0}}}));
}

TEST(StandardOperation, Move) {
const qc::StandardOperation moveOp({0, 1}, qc::OpType::Move);
EXPECT_EQ(moveOp.getTargets().size(), 2);
Expand Down
Loading