Skip to content

Commit

Permalink
✨ Gate Extensions and better QASM parser (#268)
Browse files Browse the repository at this point in the history
## Description

This PR updates the internal QFR library and brings along support for
many new (two-qubit) gates. Until #235 is in, the mapper in QMAP can't
really take advantage of that, but it's good to be prepared for that.
Some breaking changes in the QFR required changes here to make the
project compile again.

The Clifford Tableau simulation algorithm now also supports `iSWAP`,
`DCX`, and `ECR` gates.

Finally, the internal QASM parser has been improved by quite a bit;
adding support for all new gates and direct parsing for natively
supported gates without requiring definitions. The version specifier
(`OPENQASM 2.0`) is now optional and the parser supports all standard
quantum gates and controlled versions without requiring the `qelib1.inc`
include.

## 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.
- [ ] 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.
  • Loading branch information
burgholzer authored Mar 19, 2023
2 parents 3ab50ae + 27bb1c8 commit 6e8ab7a
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 14 deletions.
2 changes: 1 addition & 1 deletion extern/qfr
Submodule qfr updated from 6fc052 to 9dbdeb
3 changes: 3 additions & 0 deletions include/cliffordsynthesis/Tableau.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ class Tableau {
void applyCY(std::size_t control, std::size_t target);
void applyCZ(std::size_t control, std::size_t target);
void applySwap(std::size_t q1, std::size_t q2);
void applyISwap(std::size_t q1, std::size_t q2);
void applyDCX(std::size_t q1, std::size_t q2);
void applyECR(std::size_t q1, std::size_t q2);

[[gnu::pure]] friend bool operator==(const Tableau& lhs, const Tableau& rhs) {
return lhs.tableau == rhs.tableau;
Expand Down
20 changes: 16 additions & 4 deletions include/configuration/CommanderGrouping.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@

enum class CommanderGrouping { Halves, Fixed2, Fixed3, Logarithm };

[[maybe_unused]] static inline std::string
toString(const CommanderGrouping grouping) {
static inline std::string toString(const CommanderGrouping grouping) {
switch (grouping) {
case CommanderGrouping::Fixed2:
return "fixed2";
Expand All @@ -25,8 +24,7 @@ toString(const CommanderGrouping grouping) {
return " ";
}

[[maybe_unused]] static CommanderGrouping
groupingFromString(const std::string& grouping) {
static CommanderGrouping groupingFromString(const std::string& grouping) {
if (grouping == "halves" || grouping == "0") {
return CommanderGrouping::Halves;
}
Expand All @@ -41,3 +39,17 @@ groupingFromString(const std::string& grouping) {
}
throw std::invalid_argument("Invalid grouping value: " + grouping);
}

[[maybe_unused]] static inline std::ostream&
operator<<(std::ostream& os, const CommanderGrouping& grouping) {
os << toString(grouping);
return os;
}

[[maybe_unused]] static inline std::istream&
operator>>(std::istream& is, CommanderGrouping& grouping) {
std::string s;
is >> s;
grouping = groupingFromString(s);
return is;
}
19 changes: 16 additions & 3 deletions include/configuration/Encoding.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

enum class Encoding { Naive, Commander, Bimander };

[[maybe_unused]] static inline std::string toString(const Encoding encoding) {
static inline std::string toString(const Encoding encoding) {
switch (encoding) {
case Encoding::Naive:
return "naive";
Expand All @@ -22,8 +22,7 @@ enum class Encoding { Naive, Commander, Bimander };
return " ";
}

[[maybe_unused]] static Encoding
encodingFromString(const std::string& encoding) {
static Encoding encodingFromString(const std::string& encoding) {
if (encoding == "naive" || encoding == "0") {
return Encoding::Naive;
}
Expand All @@ -35,3 +34,17 @@ encodingFromString(const std::string& encoding) {
}
throw std::invalid_argument("Invalid encoding value: " + encoding);
}

[[maybe_unused]] static inline std::ostream&
operator<<(std::ostream& os, const Encoding& encoding) {
os << toString(encoding);
return os;
}

[[maybe_unused]] static inline std::istream& operator>>(std::istream& is,
Encoding& encoding) {
std::string s;
is >> s;
encoding = encodingFromString(s);
return is;
}
44 changes: 44 additions & 0 deletions src/cliffordsynthesis/Tableau.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,21 @@ void Tableau::applyGate(const qc::Operation* const gate) {
applySwap(target, target2);
break;
}
case qc::OpType::iSWAP: {
const auto target2 = static_cast<std::size_t>(gate->getTargets().at(1U));
applyISwap(target, target2);
break;
}
case qc::OpType::DCX: {
const auto target2 = static_cast<std::size_t>(gate->getTargets().at(1U));
applyDCX(target, target2);
break;
}
case qc::OpType::ECR: {
const auto target2 = static_cast<std::size_t>(gate->getTargets().at(1U));
applyECR(target, target2);
break;
}
default:
// unsupported non-controlled gate type
util::fatal("Tableau::applyGate: Unsupported non-controlled gate type " +
Expand Down Expand Up @@ -295,6 +310,35 @@ void Tableau::applySwap(const std::size_t q1, const std::size_t q2) {
applyCX(q1, q2);
}

void Tableau::applyISwap(const std::size_t q1, const std::size_t q2) {
assert(q1 < nQubits);
assert(q2 < nQubits);
assert(q1 != q2);
applyS(q2);
applyS(q1);
applyH(q1);
applyDCX(q1, q2);
applyH(q2);
}

void Tableau::applyDCX(const std::size_t q1, const std::size_t q2) {
assert(q1 < nQubits);
assert(q2 < nQubits);
assert(q1 != q2);
applyCX(q1, q2);
applyCX(q2, q1);
}

void Tableau::applyECR(const std::size_t q1, const std::size_t q2) {
assert(q1 < nQubits);
assert(q2 < nQubits);
assert(q1 != q2);
applyS(q1);
applySx(q2);
applyCX(q1, q2);
applyX(q1);
}

Tableau::Tableau(const qc::QuantumComputation& qc, const std::size_t begin,
const std::size_t end)
: Tableau(qc.getNqubits()) {
Expand Down
3 changes: 1 addition & 2 deletions src/exact/ExactMapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,7 @@ void ExactMapper::map(const Configuration& settings) {

qcMapped.emplace_back<qc::StandardOperation>(
qcMapped.getNqubits(), locations.at(gate.target), op->getType(),
op->getParameter().at(0), op->getParameter().at(1),
op->getParameter().at(2));
op->getParameter());
} else {
const Edge cnot = {locations.at(static_cast<std::size_t>(gate.control)),
locations.at(gate.target)};
Expand Down
6 changes: 2 additions & 4 deletions src/heuristic/HeuristicMapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,13 @@ void HeuristicMapper::map(const Configuration& configuration) {
if (locations.at(gate.target) == DEFAULT_POSITION) {
qcMapped.emplace_back<qc::StandardOperation>(
qcMapped.getNqubits(), gate.target, op->getType(),
op->getParameter().at(0), op->getParameter().at(1),
op->getParameter().at(2));
op->getParameter());
gatesToAdjust.push_back(gateidx);
gateidx++;
} else {
qcMapped.emplace_back<qc::StandardOperation>(
qcMapped.getNqubits(), locations.at(gate.target), op->getType(),
op->getParameter().at(0), op->getParameter().at(1),
op->getParameter().at(2));
op->getParameter());
gateidx++;
}
} else {
Expand Down
67 changes: 67 additions & 0 deletions test/test_architecture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "Architecture.hpp"

#include "gtest/gtest.h"
#include <random>

class TestArchitecture : public testing::TestWithParam<std::string> {
protected:
Expand Down Expand Up @@ -160,3 +161,69 @@ TEST(TestArchitecture, TestCouplingLimitRing) {
architecture.loadCouplingMap(5, cm);
EXPECT_EQ(architecture.getCouplingLimit(), 2);
}

TEST(TestArchitecture, opTypeFromString) {
Architecture arch{2, {{0, 1}}};
auto& props = arch.getProperties();

std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<> dis(0., 1.);

const std::vector<std::pair<std::string, qc::OpType>> singleQubitGates = {
{"i", qc::OpType::I},
{"x", qc::OpType::X},
{"y", qc::OpType::Y},
{"z", qc::OpType::Z},
{"sx", qc::OpType::SX},
{"sxdg", qc::OpType::SXdag},
{"h", qc::OpType::H},
{"s", qc::OpType::S},
{"sdg", qc::OpType::Sdag},
{"t", qc::OpType::T},
{"tdg", qc::OpType::Tdag},
{"rx", qc::OpType::RX},
{"ry", qc::OpType::RY},
{"rz", qc::OpType::RZ},
{"u1", qc::OpType::Phase},
{"u2", qc::OpType::U2},
{"u3", qc::OpType::U3},
{"reset", qc::OpType::Reset},
{"measure", qc::OpType::Measure}};

for (const auto& [opName, opType] : singleQubitGates) {
const auto errorRate = dis(gen);

props.setSingleQubitErrorRate(0, opName, errorRate);
EXPECT_EQ(props.getSingleQubitErrorRate(0, opName), errorRate);
}

const std::vector<std::pair<std::string, qc::OpType>> twoQubitGates = {
{"cx", qc::OpType::X},
{"cz", qc::OpType::Z},
{"cy", qc::OpType::Y},
{"ch", qc::OpType::H},
{"swap", qc::OpType::SWAP},
{"crx", qc::OpType::RX},
{"ry", qc::OpType::RY},
{"crz", qc::OpType::RZ},
{"cu1", qc::OpType::Phase},
{"cu2", qc::OpType::U2},
{"cu3", qc::OpType::U3},
{"iswap", qc::OpType::iSWAP},
{"ecr", qc::OpType::ECR},
{"dcx", qc::OpType::DCX},
{"rxx", qc::OpType::RXX},
{"rzz", qc::OpType::RZZ},
{"ryy", qc::OpType::RYY},
{"rzx", qc::OpType::RZX},
{"xx_minus_yy", qc::OpType::XXminusYY},
{"xx_plus_yy", qc::OpType::XXplusYY}};

for (const auto& [opName, opType] : twoQubitGates) {
const auto errorRate = dis(gen);

props.setTwoQubitErrorRate(0, 1, errorRate, opName);
EXPECT_EQ(props.getTwoQubitErrorRate(0, 1, opName), errorRate);
}
}
3 changes: 3 additions & 0 deletions test/test_tableau.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,9 @@ TEST_F(TestTableau, CircuitTranslation) {
qc.y(1, 0_pc);
qc.z(1, 0_pc);
qc.swap(0, 1);
qc.iswap(0, 1);
qc.dcx(0, 1);
qc.ecr(0, 1);

auto compOP = std::make_unique<qc::CompoundOperation>(2U);
compOP->emplace_back<qc::StandardOperation>(2U, 0, qc::H);
Expand Down

0 comments on commit 6e8ab7a

Please sign in to comment.