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

Hybrid Neutral Atom Mapper #458

Merged
merged 116 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
116 commits
Select commit Hold shift + click to select a range
ddc76c1
Created Hybrid NA MQT Core branch
lsschmid May 7, 2024
8f1c790
:sparkles: added AODOperation without parsing.
lsschmid May 8, 2024
59bf00d
✨ updated MQT Core to Version with AodOperation.
lsschmid May 8, 2024
a5aae37
✨ added Hybrid Neutral Atom Mapper.
lsschmid May 8, 2024
a3338db
✅ added Tests for Hybrid Neutral Atom Mapper.
lsschmid May 8, 2024
3fd52a6
🎨 preparation for python bindings
lsschmid May 24, 2024
2b1f52a
✨ Added Python bindings.
lsschmid May 24, 2024
0b77dad
🎨 Simplified HybridNeutralAtomMapper constructors.
lsschmid May 24, 2024
81bcf9c
🐛 Fixed verbosity.
lsschmid May 24, 2024
a6ff02b
✅ Updated C++ tests.
lsschmid May 24, 2024
eef0ab0
✨ Added Python mapping directly from file to prevent qasm problems wi…
lsschmid May 24, 2024
2c70adc
✅ Added Python Tests.
lsschmid May 24, 2024
d08340f
Merge branch 'refs/heads/main' into hybrid-na-mapper
lsschmid May 24, 2024
1382e44
⬆️ Updated mqt-core
lsschmid May 24, 2024
0691349
🎨 pre-commit fixes
pre-commit-ci[bot] May 24, 2024
db4c669
✅ Updated test files
lsschmid May 24, 2024
e61b49c
Merge remote-tracking branch 'origin/hybrid-na-mapper' into hybrid-na…
lsschmid May 24, 2024
6df309e
🎨 updated file headers
lsschmid May 24, 2024
afb3985
🔥 Removed unused test files
lsschmid May 24, 2024
1c45b92
🔥 Removed unused NeutralAtomMappingResults
lsschmid May 24, 2024
238f2d5
⬆️ updated mqt-core
lsschmid May 24, 2024
99e6db3
🎨 removed comment
lsschmid May 24, 2024
b77e82c
🎨 fixed floating point comparison
lsschmid May 24, 2024
e6d7917
🎨 fixed clang warnings
lsschmid May 24, 2024
026aa95
✅ fixed path in Python test
lsschmid May 24, 2024
392e8c8
✅ added create csv to test
lsschmid May 24, 2024
7d5a375
⬆️ updated mqt-core
lsschmid May 24, 2024
b8ea9de
✅ Tried fixing python test paths
lsschmid May 25, 2024
b962572
✨ added random seed to mapper parameters
lsschmid May 25, 2024
3b1dff8
✅ Updated tests to include random atom placement
lsschmid May 25, 2024
ef3592e
🎨 Fixed clang-tidy warnings
lsschmid May 25, 2024
adaf2f5
🎨 Fixed clang-tidy warnings in test file
lsschmid May 25, 2024
809645c
🐛 Fixed signbit problem on windows.
lsschmid May 25, 2024
16c7553
✅ Updated test architectures
lsschmid May 25, 2024
16e0bbc
✅ test verbosity of test
lsschmid May 25, 2024
4fed939
✅ Removed additional files for python test
lsschmid May 25, 2024
d3fdb57
✅ updated test architectures
lsschmid May 25, 2024
856e4c8
🎨 Added additional checks regarding qubit number and coord number
lsschmid May 25, 2024
f541c4e
✅ Increased int radius to make multi qubit gates executable
lsschmid May 25, 2024
144523a
✅ removed use of signbit to fix windows compilation
lsschmid May 25, 2024
fb1f81d
🐛 Fixed error introduced with clang-tidy fixes
lsschmid May 25, 2024
5eb28e8
🐛 Fixed error while tracking atoms to create animation
lsschmid May 25, 2024
8b403d1
🐛 Fixed error in offset calculation introduced by clang-tidy fixes
lsschmid May 25, 2024
8c34537
✅ Add animation csv creation to tests
lsschmid May 25, 2024
d889c2a
✅ Removed unnecessary test code
lsschmid May 25, 2024
e952354
🐛 Fixed float comparison
lsschmid May 25, 2024
a9f783c
⬆️ updated mqt-core
lsschmid May 25, 2024
11d6fec
⬆️ updated mqt-core
lsschmid May 30, 2024
66f712f
Merge branch 'refs/heads/main' into hybrid-na-mapper
lsschmid May 30, 2024
8ac0134
🎨 Substituted pointer with shared pointer.
lsschmid May 30, 2024
8b67d37
🎨 Pass architecture by reference in constructors.
lsschmid May 30, 2024
793a1f5
✅ Fixed test for random initial coord mapping.
lsschmid May 30, 2024
5ab915a
✨ Added support for non-unitary operations (measurements)
lsschmid May 30, 2024
4bd139e
🎨 Renamed AodScheduler to MoveToAodConverter
lsschmid May 31, 2024
c331554
🎨 Avoid copying of architecture.
lsschmid May 31, 2024
d560561
Fixed imports
lsschmid May 31, 2024
47044d8
🎨 pre-commit fixes
pre-commit-ci[bot] May 31, 2024
221bc59
🎨 Added default to trivial switch statement.
lsschmid May 31, 2024
a1e5991
🎨 Substitute push_back with emplace_back.
lsschmid May 31, 2024
dc08e82
🎨 Substitute push_back/insert with emplace_back/emplace.
lsschmid May 31, 2024
92c75b4
🎨 Put verbosity into mapper parameters.
lsschmid May 31, 2024
b06920f
🎨 added documentation to printLayers()
lsschmid May 31, 2024
1487cde
🎨 renamed mapPy
lsschmid May 31, 2024
1f10017
🎨 Moved Animations into separate file.
lsschmid May 31, 2024
99c0026
🎨 Changed namespace to na
lsschmid May 31, 2024
26d33b7
Merge remote-tracking branch 'origin/hybrid-na-mapper' into hybrid-na…
lsschmid May 31, 2024
e0ad602
Nicer test output
lsschmid May 31, 2024
60d7353
🎨 Print test output to std::out
lsschmid May 31, 2024
0fac4fe
🎨 Directly copy only test circuits and architectures not whole directory
lsschmid May 31, 2024
882da3f
🎨 Add assertions to python test
lsschmid May 31, 2024
310413f
Improved vector initalization
lsschmid May 31, 2024
bb1053d
Improved SymmetricMatrix methods
lsschmid May 31, 2024
f151eef
🎨 Removed NaN for uninitialized cost
lsschmid May 31, 2024
0d6527c
Use fron/back instead of begin/rbegin
lsschmid May 31, 2024
f9b8a3b
🎨 Merged
lsschmid May 31, 2024
b5e1aca
begin -> cbegin
lsschmid May 31, 2024
57eb3b8
🔥 Removed old na readme file
lsschmid May 31, 2024
3f40e1d
Merge remote-tracking branch 'origin/hybrid-na-mapper' into hybrid-na…
lsschmid May 31, 2024
4dafe4b
Use pre-allocation of vector size
lsschmid May 31, 2024
7edb5d6
Merge remote-tracking branch 'origin/hybrid-na-mapper' into hybrid-na…
lsschmid May 31, 2024
c32e06e
🐛 Fixed iterator naming
lsschmid May 31, 2024
1a3bea9
🎨 Changed Coordinate to Point structure
lsschmid May 31, 2024
5dde522
🎨 Moved MultiQubitPos to Utils
lsschmid May 31, 2024
7f921d7
🎨 Renamed getInitialHwPos -> getInitHwPos to be consistent
lsschmid May 31, 2024
82496a4
🎨 Removed delete default constructor
lsschmid May 31, 2024
82140ef
🎨 removed TODO
lsschmid May 31, 2024
8048dbc
🎨 remove barrier and measurements
lsschmid May 31, 2024
43575de
🎨 moved InitCoord to mapper parameters
lsschmid May 31, 2024
d8c477a
🎨 Updated Python bindings
lsschmid May 31, 2024
26732a6
🎨 fixed imports
lsschmid May 31, 2024
f8628ea
⬆️ updated mqt-core
lsschmid May 31, 2024
209af35
🎨 removed unused header
lsschmid May 31, 2024
7b560e6
Revert "🎨 Directly copy only test circuits and architectures not whol…
lsschmid May 31, 2024
f61e237
🐛 Fixed error during move group initialization
lsschmid Jun 1, 2024
b920101
⬆️ updated mqt-core
lsschmid Jun 1, 2024
33e6f09
🐛 Fixed bug when merging Aod activations/deactivations
lsschmid Jun 1, 2024
266e42a
🐛 prevent endless loops in symmetric situations
lsschmid Jun 1, 2024
e586d27
Merge branch 'refs/heads/main' into hybrid-na-mapper
lsschmid Jun 1, 2024
c9163a4
🎨 Changed numeric limits infinity to max
lsschmid Jun 2, 2024
98c3564
🎨 Changed Swap distance from fp to int
lsschmid Jun 2, 2024
7e262dc
🎨 Changed also in unused function
lsschmid Jun 2, 2024
2041406
🎨 Changed also in Python bindings
lsschmid Jun 2, 2024
03fcd2e
🎨 Moved Symmetric Matrix to MQT Core
lsschmid Jun 2, 2024
feedfd3
🎨 Update to fix new symmetric matrix signature
lsschmid Jun 3, 2024
084220c
🐛 Fixed assignment problem
lsschmid Jun 3, 2024
a662ae4
⬆️ updated MQT Core
lsschmid Jun 3, 2024
b6c1921
✅ Added another test circuit.
lsschmid Jun 3, 2024
0e47ade
✅ Changed random seed
lsschmid Jun 3, 2024
ff06f46
♻️ copy the `na::Architecture::DecoherenceTimes` class for now
burgholzer Jun 3, 2024
772d9b2
🚨 fix shadowing variables compiler warnings
burgholzer Jun 3, 2024
b52c53b
🩹 fix test target name
burgholzer Jun 3, 2024
4392a5e
⚗️ only copy relevant directories for C++ tests
burgholzer Jun 3, 2024
38c4311
🩹 fix example circuit to be QASM 2 compliant
burgholzer Jun 3, 2024
c6fea2d
♻️ parametrize Python tests
burgholzer Jun 3, 2024
0aa69e9
⬆️ update mqt-core
burgholzer Jun 3, 2024
289cb03
🩹 properly set working directory for tests
burgholzer Jun 3, 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
292 changes: 292 additions & 0 deletions include/hybridmap/HardwareQubits.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,292 @@
//
// This file is part of the MQT QMAP library released under the MIT license.
// See README.md or go to https://github.com/cda-tum/qmap for more information.
//

#pragma once

#include "Definitions.hpp"
#include "Permutation.hpp"
#include "datastructures/SymmetricMatrix.hpp"
#include "hybridmap/NeutralAtomArchitecture.hpp"
#include "hybridmap/NeutralAtomDefinitions.hpp"
#include "hybridmap/NeutralAtomUtils.hpp"
#include "operations/Operation.hpp"

#include <algorithm>
#include <cstdint>
#include <map>
#include <numeric>
#include <random>
#include <set>
#include <stdexcept>
#include <string>
#include <vector>

namespace na {

/**
* @brief Class that represents the hardware qubits of a neutral atom quantum
* @details Class that represents the hardware qubits of a neutral atom quantum
* computer. It stores the mapping from the circuit qubits to the hardware
* qubits and the mapping from the hardware qubits to the coordinates of the
* neutral atoms. It also stores the swap distances between the hardware
* qubits.
*/
class HardwareQubits {
protected:
const NeutralAtomArchitecture* arch;
qc::Permutation hwToCoordIdx;
SymmetricMatrix<SwapDistance> swapDistances;
std::map<HwQubit, HwQubits> nearbyQubits;
qc::Permutation initialHwPos;

/**
* @brief Initializes the swap distances between the hardware qubits for the
* trivial initial layout.
* @details Initializes the swap distances between the hardware qubits. This
* is only valid for the trivial initial layout.
*/
void initTrivialSwapDistances();
/**
* @brief Initializes the nearby qubits for each hardware qubit.
* @details Nearby qubits are the qubits that are closer than the interaction
* radius. Therefore they can be swapped with a single swap operation.
*/
void initNearbyQubits();
/**
* @brief Computes the nearby qubits for a single hardware qubit.
* @details Computes the nearby qubits for a single hardware qubit. This
* function is called by initNearbyQubits(). It uses the nearby coordinates
* of the neutral atom architecture to compute the nearby qubits.
* @param qubit The hardware qubit for which the nearby qubits are computed.
*/
void computeNearbyQubits(HwQubit qubit);

/**
* @brief Computes the swap distance between two hardware qubits.
* @details Computes the swap distance between two hardware qubits. This
* function is called by getSwapDistance(). It uses a breadth-first search
* to find the shortest path between the two qubits.
* @param q1 The first hardware qubit.
* @param q2 The second hardware qubit.
*/
void computeSwapDistance(HwQubit q1, HwQubit q2);

/**
* @brief Resets the swap distances between the hardware qubits.
* @details Used after each shuttling operation to reset the swap distances.
*/
void resetSwapDistances();

public:
// Constructors
HardwareQubits(const NeutralAtomArchitecture& architecture,
InitialCoordinateMapping initialCoordinateMapping,
uint32_t seed)
: arch(&architecture), swapDistances(architecture.getNqubits()) {
switch (initialCoordinateMapping) {
case Trivial:
for (uint32_t i = 0; i < architecture.getNqubits(); ++i) {
hwToCoordIdx.emplace(i, i);
}
initTrivialSwapDistances();
break;
case Random:
std::vector<CoordIndex> indices(architecture.getNpositions());
std::iota(indices.begin(), indices.end(), 0);
if (seed == 0) {
seed = std::random_device()();
}
std::mt19937 g(seed);
std::shuffle(indices.begin(), indices.end(), g);
for (uint32_t i = 0; i < architecture.getNqubits(); ++i) {
hwToCoordIdx.emplace(i, indices[i]);
}

swapDistances = SymmetricMatrix(architecture.getNqubits(), -1);
}
initNearbyQubits();
initialHwPos = hwToCoordIdx;
}

// Mapping

/**
* @brief Checks if a hardware qubit is mapped to a coordinate.
* @param idx The coordinate index.
* @return Boolean indicating if the hardware qubit is mapped to a coordinate.
*/
[[nodiscard]] bool isMapped(CoordIndex idx) const {
return !std::none_of(
hwToCoordIdx.begin(), hwToCoordIdx.end(),
[idx](const auto& pair) { return pair.second == idx; });
}
/**
* @brief Updates mapping after moving a hardware qubit to a coordinate.
* @details Checks if the coordinate is valid and free. If yes, the mapping is
* updated.
* @param hwQubit The hardware qubit to be moved.
* @param newCoord The new coordinate of the hardware qubit.
*/
void move(HwQubit hwQubit, CoordIndex newCoord);

/**
* @brief Converts gate qubits from hardware qubits to coordinate indices.
* @param op The operation.
*/
void mapToCoordIdx(qc::Operation* op) const {
op->setTargets(hwToCoordIdx.apply(op->getTargets()));
if (op->isControlled()) {
op->setControls(hwToCoordIdx.apply(op->getControls()));
}
}

/**
* @brief Returns the coordinate index of a hardware qubit.
* @param qubit The hardware qubit.
* @return The coordinate index of the hardware qubit.
*/
[[nodiscard]] CoordIndex getCoordIndex(HwQubit qubit) const {
return hwToCoordIdx.at(qubit);
}
/**
* @brief Returns the coordinate indices of a set of hardware qubits.
* @param hwQubits The set of hardware qubits.
* @return The coordinate indices of the hardware qubits.
*/
[[nodiscard]] std::set<CoordIndex>
getCoordIndices(std::set<HwQubit>& hwQubits) const {
std::set<CoordIndex> coordIndices;
for (auto const& hwQubit : hwQubits) {
coordIndices.emplace(this->getCoordIndex(hwQubit));
}
return coordIndices;
}
/**
* @brief Returns the hardware qubit at a coordinate.
* @details Returns the hardware qubit at a coordinate. Throws an exception if
* there is no hardware qubit at the coordinate.
* @param coordIndex The coordinate index.
* @return The hardware qubit at the coordinate.
*/
[[nodiscard]] HwQubit getHwQubit(CoordIndex coordIndex) const {
for (auto const& [hwQubit, index] : hwToCoordIdx) {
if (index == coordIndex) {
return hwQubit;
}
}
throw std::runtime_error("There is no qubit at this coordinate " +
std::to_string(coordIndex));
}

// Forwards from architecture class

/**
* @brief Returns the nearby coordinates of a hardware qubit.
* @param q The hardware qubit.
* @return The nearby coordinates of the hardware qubit.
*/
[[nodiscard]] [[maybe_unused]] std::set<CoordIndex>
getNearbyCoordinates(HwQubit q) const {
return this->arch->getNearbyCoordinates(this->getCoordIndex(q));
}

// Swap Distances and Nearby qc::Qubits

/**
* @brief Returns the swap distance between two hardware qubits.
* @details Returns the swap distance between two hardware qubits. If the
* swap distance is not yet computed, it is computed using a breadth-first
* search.
* @param q1 The first hardware qubit.
* @param q2 The second hardware qubit.
* @param closeBy If the swap should be performed to the exact position of q2
* or just to its vicinity.
* @return The swap distance between the two hardware qubits.
*/
[[nodiscard]] SwapDistance getSwapDistance(HwQubit q1, HwQubit q2,
bool closeBy = true) {
if (q1 == q2) {
return 0;
}
if (swapDistances(q1, q2) < 0) {
computeSwapDistance(q1, q2);
}
if (closeBy) {
return swapDistances(q1, q2);
}
return swapDistances(q1, q2) + 1;
}

/**
* @brief Returns the nearby hardware qubits of a hardware qubit.
* @param q The hardware qubit.
* @return The nearby hardware qubits of the hardware qubit.
*/
[[nodiscard]] HwQubits getNearbyQubits(HwQubit q) const {
return nearbyQubits.at(q);
}

/**
* @brief Returns vector of all possible swaps for a hardware qubit.
* @param q The hardware qubit.
* @return The vector of all possible swaps for the hardware qubit.
*/
[[nodiscard]] std::vector<Swap> getNearbySwaps(HwQubit q) const;

/**
* @brief Returns the unoccupied coordinates in the vicinity of a coordinate.
* @param idx The coordinate index.
* @return The unoccupied coordinates in the vicinity of the coordinate.
*/
std::set<CoordIndex> getNearbyFreeCoordinatesByCoord(CoordIndex idx);

/**
* @brief Returns the occupied coordinates in the vicinity of a coordinate.
* @param idx The coordinate index.
* @return The occupied coordinates in the vicinity of the coordinate.
*/
[[nodiscard]] std::set<CoordIndex>
getNearbyOccupiedCoordinatesByCoord(CoordIndex idx) const;

/**
* @brief Computes the summed swap distance between all hardware qubits in a
* set.
* @param qubits The set of hardware qubits.
* @return The summed swap distance between all hardware qubits in the set.
*/
qc::fp getAllToAllSwapDistance(std::set<HwQubit>& qubits);

/**
* @brief Computes the closest free coordinate in a given direction.
* @details Uses a breadth-first search to find the closest free coordinate in
* a given direction.
* @param qubit The hardware qubit to start the search from.
* @param direction The direction in which the search is performed
* (Left/Right, Down/Up)
* @param excludedCoords Coordinates to be ignored in the search.
* @return The closest free coordinate in the given direction.
*/
std::vector<CoordIndex>
findClosestFreeCoord(HwQubit qubit, Direction direction,
const CoordIndices& excludedCoords = {});

// Blocking
/**
* @brief Computes all hardware qubits that are blocked by a set of hardware
* qubits.
* @param qubits The input hardware qubits.
* @return The blocked hardware qubits.
*/
std::set<HwQubit> getBlockedQubits(const std::set<HwQubit>& qubits);

[[nodiscard]] std::map<HwQubit, HwQubit> getInitHwPos() const {
std::map<HwQubit, HwQubit> initialHwPosMap;
for (auto const& pair : initialHwPos) {
initialHwPosMap[pair.first] = pair.second;
}
return initialHwPosMap;
}
};
} // namespace na
60 changes: 60 additions & 0 deletions include/hybridmap/HybridAnimation.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//
// This file is part of the MQT QMAP library released under the MIT license.
// See README.md or go to https://github.com/cda-tum/qmap for more information.
//

#pragma once

#include "Definitions.hpp"
#include "NeutralAtomArchitecture.hpp"
#include "NeutralAtomDefinitions.hpp"
#include "operations/Operation.hpp"

#include <cstdint>
#include <map>
#include <memory>
#include <string>
#include <utility>

namespace na {
class AnimationAtoms {
using axesId = std::uint32_t;
using marginId = std::uint32_t;

protected:
uint32_t colorSlm = 0;
uint32_t colorAod = 1;
uint32_t colorLocal = 2;
[[maybe_unused]] uint32_t colorGlobal = 3;
uint32_t colorCz = 4;

std::map<CoordIndex, HwQubit> coordIdxToId;
std::map<HwQubit, std::pair<qc::fp, qc::fp>> idToCoord;
std::map<HwQubit, uint32_t> axesIds;
std::map<HwQubit, uint32_t> marginIds;
uint32_t axesIdCounter = 0;
uint32_t marginIdCounter = 0;

axesId addAxis(HwQubit id);
void removeAxis(HwQubit id) { axesIds.erase(id); }
marginId addMargin(HwQubit id);
void removeMargin(HwQubit id) { marginIds.erase(id); }

public:
AnimationAtoms(const std::map<HwQubit, HwQubit>& initHwPos,
const NeutralAtomArchitecture& arch);

std::string getInitString();
std::string getEndString(qc::fp endTime);
static std::string createCsvLine(qc::fp startTime, HwQubit id, qc::fp x,
qc::fp y, uint32_t size = 1,
uint32_t color = 0, bool axes = false,
axesId axId = 0, bool margin = false,
marginId marginId = 0,
qc::fp marginSize = 0);
std::string createCsvOp(const std::unique_ptr<qc::Operation>& op,
qc::fp startTime, qc::fp endTime,
const NeutralAtomArchitecture& arch);
};

} // namespace na
Loading
Loading