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

✨ Gate Extensions and better QASM parser #268

Merged
merged 10 commits into from
Mar 19, 2023
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