Skip to content

Commit

Permalink
👽 Update to latest mqt-core version (#390)
Browse files Browse the repository at this point in the history
## Description

This PR adjusts QMAP to the latest interface changes in `mqt-core`.
In a follow-up PR, the newly introduced `mqt.core` Python package that
include Python bindings for the `QuantumComputation` class will be
introduced.

## 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.
- [x] 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.

---------

Signed-off-by: burgholzer <burgholzer@me.com>
Co-authored-by: burgholzer <burgholzer@me.com>
  • Loading branch information
pehamTom and burgholzer authored Nov 9, 2023
1 parent 1b74685 commit 5d8795e
Show file tree
Hide file tree
Showing 20 changed files with 178 additions and 174 deletions.
2 changes: 2 additions & 0 deletions .clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ Checks: |
boost-*,
bugprone-*,
-bugprone-easily-swappable-parameters,
-bugprone-unchecked-optional-access,
clang-analyzer-*,
cppcoreguidelines-*,
-cppcoreguidelines-avoid-do-while,
-cppcoreguidelines-non-private-member-variables-in-classes,
-cppcoreguidelines-special-member-functions,
-cppcoreguidelines-avoid-magic-numbers,
Expand Down
2 changes: 1 addition & 1 deletion extern/mqt-core
Submodule mqt-core updated 153 files
25 changes: 11 additions & 14 deletions include/Mapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class Mapper {
/**
* @brief The quantum architecture on which to map the circuit
*/
Architecture& architecture;
Architecture* architecture;

/**
* @brief The resulting quantum circuit after mapping
Expand Down Expand Up @@ -183,8 +183,7 @@ class Mapper {
virtual void postMappingOptimizations(const Configuration& config);

public:
Mapper(const qc::QuantumComputation& quantumComputation,
Architecture& architecture);
Mapper(qc::QuantumComputation quantumComputation, Architecture& architecture);
virtual ~Mapper() = default;

/**
Expand Down Expand Up @@ -239,7 +238,7 @@ class Mapper {
virtual std::string csv() { return results.csv(); }

std::ostream& printLayering(std::ostream& out) {
out << "---------------- Layering -------------------" << std::endl;
out << "---------------- Layering -------------------\n";
for (auto& layer : layers) {
for (auto& gate : layer) {
if (gate.singleQubit()) {
Expand All @@ -248,33 +247,31 @@ class Mapper {
out << "(" << gate.control << " " << gate.target << ") ";
}
}
out << std::endl;
out << "\n";
}
out << "---------------------------------------------" << std::endl;
out << "---------------------------------------------\n";
return out;
}

std::ostream& printLocations(std::ostream& out) {
out << "---------------- Locations -------------------" << std::endl;
out << "---------------- Locations -------------------\n";
for (std::size_t i = 0; i < qc.getNqubits(); ++i) {
out << locations.at(i) << " ";
}
out << std::endl;
out << "---------------------------------------------" << std::endl;
out << "\n---------------------------------------------\n";
return out;
}
std::ostream& printQubits(std::ostream& out) {
out << "---------------- Qubits -------------------" << std::endl;
for (std::size_t i = 0; i < architecture.getNqubits(); ++i) {
out << "---------------- Qubits -------------------\n";
for (std::size_t i = 0; i < architecture->getNqubits(); ++i) {
out << qubits.at(i) << " ";
}
out << std::endl;
out << "---------------------------------------------" << std::endl;
out << "\n---------------------------------------------\n";
return out;
}

virtual void reset() {
architecture.reset();
architecture->reset();
qc.reset();
layers.clear();
qubits.fill(DEFAULT_POSITION);
Expand Down
4 changes: 2 additions & 2 deletions include/cliffordsynthesis/CliffordSynthesizer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@ class CliffordSynthesizer {
: initialTableau(std::move(initial)),
targetTableau(qc, 0, std::numeric_limits<std::size_t>::max(),
initialTableau.hasDestabilizers()),
initialCircuit(std::make_shared<qc::QuantumComputation>(qc.clone())),
initialCircuit(std::make_shared<qc::QuantumComputation>(qc)),
results(qc, targetTableau) {}
explicit CliffordSynthesizer(qc::QuantumComputation& qc,
const bool useDestabilizers = false)
: initialTableau(qc.getNqubits(), useDestabilizers),
targetTableau(qc, 0, std::numeric_limits<std::size_t>::max(),
useDestabilizers),
initialCircuit(std::make_shared<qc::QuantumComputation>(qc.clone())),
initialCircuit(std::make_shared<qc::QuantumComputation>(qc)),
results(qc, targetTableau) {}

virtual ~CliffordSynthesizer() = default;
Expand Down
6 changes: 3 additions & 3 deletions include/cliffordsynthesis/encoding/GateEncoder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ class GateEncoder {
[[nodiscard]] auto* getVariables() { return &vars; }

static constexpr std::array<qc::OpType, 7> SINGLE_QUBIT_GATES = {
qc::OpType::None, qc::OpType::X, qc::OpType::Y, qc::OpType::Z,
qc::OpType::H, qc::OpType::S, qc::OpType::Sdag};
qc::OpType::None, qc::OpType::X, qc::OpType::Y, qc::OpType::Z,
qc::OpType::H, qc::OpType::S, qc::OpType::Sdg};

[[nodiscard]] static constexpr std::size_t
gateToIndex(const qc::OpType type) {
Expand Down Expand Up @@ -97,7 +97,7 @@ class GateEncoder {
return containsGate<qc::OpType::S>();
}
[[nodiscard]] static constexpr bool containsSdag() {
return containsGate<qc::OpType::Sdag>();
return containsGate<qc::OpType::Sdg>();
}

protected:
Expand Down
4 changes: 2 additions & 2 deletions include/heuristic/HeuristicMapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ class HeuristicMapper : public Mapper {
*/
double distanceOnArchitectureOfLogicalQubits(std::uint16_t control,
std::uint16_t target) {
return architecture.distance(
return architecture->distance(
static_cast<std::uint16_t>(locations.at(control)),
static_cast<std::uint16_t>(locations.at(target)));
}
Expand All @@ -189,7 +189,7 @@ class HeuristicMapper : public Mapper {
*/
double distanceOnArchitectureOfPhysicalQubits(std::uint16_t control,
std::uint16_t target) {
return architecture.distance(control, target);
return architecture->distance(control, target);
}

/**
Expand Down
1 change: 1 addition & 0 deletions include/utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <algorithm>
#include <functional>
#include <iostream>
#include <limits>
#include <optional>
#include <queue>
#include <set>
Expand Down
27 changes: 14 additions & 13 deletions src/Mapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,21 @@

#include "CircuitOptimizer.hpp"

#include <utility>

void Mapper::initResults() {
countGates(qc, results.input);
results.input.name = qc.getName();
results.input.qubits = static_cast<std::uint16_t>(qc.getNqubits());
results.architecture = architecture.getName();
results.architecture = architecture->getName();
results.output.name = qc.getName() + "_mapped";
results.output.qubits = architecture.getNqubits();
results.output.qubits = architecture->getNqubits();
results.output.gates = std::numeric_limits<std::size_t>::max();
qcMapped.addQubitRegister(architecture.getNqubits());
qcMapped.addQubitRegister(architecture->getNqubits());
}

Mapper::Mapper(const qc::QuantumComputation& quantumComputation,
Architecture& arch)
: qc(quantumComputation.clone()), architecture(arch) {
Mapper::Mapper(qc::QuantumComputation quantumComputation, Architecture& arch)
: qc(std::move(quantumComputation)), architecture(&arch) {
qubits.fill(DEFAULT_POSITION);
locations.fill(DEFAULT_POSITION);
fidelities.fill(INITIAL_FIDELITY);
Expand Down Expand Up @@ -201,16 +202,16 @@ std::size_t Mapper::getNextLayer(std::size_t idx) {
void Mapper::finalizeMappedCircuit() {
// add additional qubits if the architecture contains more qubits than the
// circuit
if (architecture.getNqubits() > qcMapped.getNqubits()) {
if (architecture->getNqubits() > qcMapped.getNqubits()) {
for (auto logicalQubit = qcMapped.getNqubits();
logicalQubit < architecture.getNqubits(); ++logicalQubit) {
logicalQubit < architecture->getNqubits(); ++logicalQubit) {
std::optional<qc::Qubit> physicalQubit = std::nullopt;

// check if the corresponding physical qubit is already in use
if (qcMapped.initialLayout.find(static_cast<qc::Qubit>(logicalQubit)) !=
qcMapped.initialLayout.end()) {
// get the next unused physical qubit
for (physicalQubit = 0; *physicalQubit < architecture.getNqubits();
for (physicalQubit = 0; *physicalQubit < architecture->getNqubits();
++(*physicalQubit)) {
if (qcMapped.initialLayout.find(*physicalQubit) ==
qcMapped.initialLayout.end()) {
Expand Down Expand Up @@ -238,16 +239,16 @@ void Mapper::finalizeMappedCircuit() {
}

void Mapper::placeRemainingArchitectureQubits() {
if (qc.getNqubits() < architecture.getNqubits()) {
for (auto logical = qc.getNqubits(); logical < architecture.getNqubits();
if (qc.getNqubits() < architecture->getNqubits()) {
for (auto logical = qc.getNqubits(); logical < architecture->getNqubits();
++logical) {
std::optional<qc::Qubit> physical = std::nullopt;

// check if the corresponding physical qubit is already in use
if (qcMapped.initialLayout.find(static_cast<qc::Qubit>(logical)) !=
qcMapped.initialLayout.end()) {
// get the next unused physical qubit
for (physical = 0; *physical < architecture.getNqubits();
for (physical = 0; *physical < architecture->getNqubits();
++(*physical)) {
if (qcMapped.initialLayout.find(*physical) ==
qcMapped.initialLayout.end()) {
Expand Down Expand Up @@ -299,7 +300,7 @@ void Mapper::countGates(decltype(qcMapped.cbegin()) it,

if (g->isStandardOperation()) {
if (g->getType() == qc::SWAP) {
if (architecture.bidirectional()) {
if (architecture->bidirectional()) {
info.gates += GATES_OF_BIDIRECTIONAL_SWAP;
info.cnots += GATES_OF_BIDIRECTIONAL_SWAP;
} else {
Expand Down
7 changes: 3 additions & 4 deletions src/cliffordsynthesis/Tableau.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,13 @@ void Tableau::applyGate(const qc::Operation* const gate) {
case qc::OpType::S:
applyS(target);
break;
case qc::OpType::Sdag:
case qc::OpType::Sdg:
applySdag(target);
break;
case qc::OpType::SX:
applySx(target);
break;
case qc::OpType::SXdag:
case qc::OpType::SXdg:
applySxdag(target);
break;
case qc::OpType::X:
Expand Down Expand Up @@ -180,8 +180,7 @@ void Tableau::fromString(const std::string& str) {
if (line.empty()) {
return;
}
const auto rStabilizer = std::regex("([\\+-]?)([IYZX]+)");
std::smatch m;
const auto rStabilizer = std::regex("([\\+-]?)([IYZX]+)");
if (std::regex_search(line, rStabilizer)) {
// string is a list of stabilizers
loadStabilizerDestabilizerString(str);
Expand Down
6 changes: 3 additions & 3 deletions src/cliffordsynthesis/encoding/GateEncoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ void GateEncoder::assertSingleQubitGateCancellationConstraints(

if constexpr (containsS() && containsSdag()) {
const auto gateIndexS = gateToIndex(qc::OpType::S);
const auto gateIndexSdg = gateToIndex(qc::OpType::Sdag);
const auto gateIndexSdg = gateToIndex(qc::OpType::Sdg);

// -X-(S|Sd)- ~= -(Sd|S)-X-
// -Y-(S|Sd)- ~= -(Sd|S)-Y-
Expand Down Expand Up @@ -293,7 +293,7 @@ void GateEncoder::assertSingleQubitGateCancellationConstraints(
auto disallowed = !gSNext[gateIndexS][qubit];

if constexpr (containsSdag()) {
constexpr auto gateIndexSdag = gateToIndex(qc::OpType::Sdag);
constexpr auto gateIndexSdag = gateToIndex(qc::OpType::Sdg);

// -Sd-Sd- = -Z-
// -Sd-S- = -I-
Expand All @@ -308,7 +308,7 @@ void GateEncoder::assertSingleQubitGateCancellationConstraints(
lb->assertFormula(LogicTerm::implies(gates, disallowed));
} else {
if constexpr (containsSdag()) {
constexpr auto gateIndexSdag = gateToIndex(qc::OpType::Sdag);
constexpr auto gateIndexSdag = gateToIndex(qc::OpType::Sdg);

// -S-Sd- = -I-
// -Sd-S- = -I-
Expand Down
2 changes: 1 addition & 1 deletion src/cliffordsynthesis/encoding/SingleGateEncoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ void SingleGateEncoder::assertTwoQubitGateOrderConstraints(
// commute.
disallowed = disallowed && !gSNext[gateToIndex(qc::OpType::Z)][control] &&
!gSNext[gateToIndex(qc::OpType::S)][control] &&
!gSNext[gateToIndex(qc::OpType::Sdag)][control];
!gSNext[gateToIndex(qc::OpType::Sdg)][control];

// no CNOT with the same control and a lower target qubit may be placed.
for (std::size_t t = 0U; t < target; ++t) {
Expand Down
6 changes: 3 additions & 3 deletions src/cliffordsynthesis/encoding/TableauEncoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ TableauEncoder::Variables::singleQubitXChange(const std::size_t pos,
case qc::OpType::Y:
case qc::OpType::Z:
case qc::OpType::S:
case qc::OpType::Sdag:
case qc::OpType::Sdg:
return x[pos][qubit];
case qc::OpType::H:
return z[pos][qubit];
Expand All @@ -106,7 +106,7 @@ TableauEncoder::Variables::singleQubitZChange(const std::size_t pos,
case qc::OpType::H:
return x[pos][qubit];
case qc::OpType::S:
case qc::OpType::Sdag:
case qc::OpType::Sdg:
return (z[pos][qubit] ^ x[pos][qubit]);
default:
FATAL() << "Unsupported single-qubit gate: " << toString(gate);
Expand All @@ -126,7 +126,7 @@ TableauEncoder::Variables::singleQubitRChange(const std::size_t pos,
case qc::OpType::H:
case qc::OpType::S:
return x[pos][qubit] & z[pos][qubit];
case qc::OpType::Sdag:
case qc::OpType::Sdg:
return x[pos][qubit] & (x[pos][qubit] ^ z[pos][qubit]);
case qc::OpType::X:
return z[pos][qubit];
Expand Down
Loading

0 comments on commit 5d8795e

Please sign in to comment.