From 5e958c50a217f6aba27513894363984d5e100414 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Fri, 6 Sep 2024 19:34:01 +0200 Subject: [PATCH 1/6] =?UTF-8?q?=F0=9F=94=A7=20update=20CMake=20compatibili?= =?UTF-8?q?ty?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d384fa03..6b7b299a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # set required cmake version -cmake_minimum_required(VERSION 3.19...3.28) +cmake_minimum_required(VERSION 3.19...3.30) project( mqt-qmap From f712cdfcb78199bd53daa88c68e33ff5d3218859 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Fri, 6 Sep 2024 21:53:08 +0200 Subject: [PATCH 2/6] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20improved=20CMake=20and?= =?UTF-8?q?=20library=20structure?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- CMakeLists.txt | 31 +- include/cliffordsynthesis/Results.hpp | 46 +- include/{ => sc}/Architecture.hpp | 0 include/{ => sc}/DataLogger.hpp | 0 include/{ => sc}/Mapper.hpp | 0 include/{ => sc}/MappingResults.hpp | 0 .../configuration/AvailableArchitecture.hpp | 0 .../configuration/CommanderGrouping.hpp | 0 .../{ => sc}/configuration/Configuration.hpp | 0 .../configuration/EarlyTermination.hpp | 0 include/{ => sc}/configuration/Encoding.hpp | 0 include/{ => sc}/configuration/Heuristic.hpp | 0 .../{ => sc}/configuration/InitialLayout.hpp | 0 include/{ => sc}/configuration/Layering.hpp | 0 .../configuration/LookaheadHeuristic.hpp | 0 include/{ => sc}/configuration/Method.hpp | 0 .../{ => sc}/configuration/SwapReduction.hpp | 0 include/{ => sc}/exact/ExactMapper.hpp | 8 +- .../{ => sc}/heuristic/HeuristicMapper.hpp | 12 +- .../heuristic/UniquePriorityQueue.hpp | 0 include/{ => sc}/utils.hpp | 0 src/CMakeLists.txt | 125 +- src/cliffordsynthesis/CMakeLists.txt | 30 + src/cliffordsynthesis/Results.cpp | 60 + src/cliffordsynthesis/Tableau.cpp | 54 +- src/hybridmap/CMakeLists.txt | 28 + src/hybridmap/HybridAnimation.cpp | 27 +- src/hybridmap/HybridNeutralAtomMapper.cpp | 3 +- src/hybridmap/MoveToAodConverter.cpp | 4 +- src/hybridmap/NeutralAtomArchitecture.cpp | 3 +- src/na/Architecture.cpp | 11 +- src/na/CMakeLists.txt | 5 +- src/na/Configuration.cpp | 2 +- src/na/NAGraphAlgorithms.cpp | 2 +- src/na/NAMapper.cpp | 8 +- src/python/CMakeLists.txt | 6 +- src/python/bindings.cpp | 15 +- src/{ => sc}/Architecture.cpp | 6 +- src/sc/CMakeLists.txt | 34 + src/{configuration => sc}/Configuration.cpp | 18 +- src/{ => sc}/DataLogger.cpp | 8 +- src/{ => sc}/Mapper.cpp | 12 +- src/sc/exact/CMakeLists.txt | 28 + src/{ => sc}/exact/ExactMapper.cpp | 14 +- src/sc/heuristic/CMakeLists.txt | 28 + src/{ => sc}/heuristic/HeuristicMapper.cpp | 22 +- src/{ => sc}/utils.cpp | 2 +- test/CMakeLists.txt | 38 +- test/cliffordsynthesis/CMakeLists.txt | 10 + test/cliffordsynthesis/test_synthesis.cpp | 6 +- test/{ => cliffordsynthesis}/test_tableau.cpp | 17 +- test/hybridmap/CMakeLists.txt | 9 + test/logicblocks/CMakeLists.txt | 4 + test/{ => logicblocks}/test_logicblocks.cpp | 0 test/na/test_architecture.cpp | 4 +- test/na/test_configuration.cpp | 2 +- test/na/test_nagraphalgorithms.cpp | 2 +- test/na/test_namapper.cpp | 6 +- test/sc/CMakeLists.txt | 7 + test/sc/exact/CMakeLists.txt | 4 + test/{ => sc/exact}/test_encodings.cpp | 14 +- test/{ => sc/exact}/test_exact.cpp | 1256 ++++++++--------- test/sc/heuristic/CMakeLists.txt | 4 + test/{ => sc/heuristic}/test_heuristic.cpp | 52 +- test/{ => sc}/test_architecture.cpp | 8 +- test/{ => sc}/test_general.cpp | 4 +- 66 files changed, 1105 insertions(+), 994 deletions(-) rename include/{ => sc}/Architecture.hpp (100%) rename include/{ => sc}/DataLogger.hpp (100%) rename include/{ => sc}/Mapper.hpp (100%) rename include/{ => sc}/MappingResults.hpp (100%) rename include/{ => sc}/configuration/AvailableArchitecture.hpp (100%) rename include/{ => sc}/configuration/CommanderGrouping.hpp (100%) rename include/{ => sc}/configuration/Configuration.hpp (100%) rename include/{ => sc}/configuration/EarlyTermination.hpp (100%) rename include/{ => sc}/configuration/Encoding.hpp (100%) rename include/{ => sc}/configuration/Heuristic.hpp (100%) rename include/{ => sc}/configuration/InitialLayout.hpp (100%) rename include/{ => sc}/configuration/Layering.hpp (100%) rename include/{ => sc}/configuration/LookaheadHeuristic.hpp (100%) rename include/{ => sc}/configuration/Method.hpp (100%) rename include/{ => sc}/configuration/SwapReduction.hpp (100%) rename include/{ => sc}/exact/ExactMapper.hpp (88%) rename include/{ => sc}/heuristic/HeuristicMapper.hpp (98%) rename include/{ => sc}/heuristic/UniquePriorityQueue.hpp (100%) rename include/{ => sc}/utils.hpp (100%) create mode 100644 src/cliffordsynthesis/CMakeLists.txt create mode 100644 src/cliffordsynthesis/Results.cpp create mode 100644 src/hybridmap/CMakeLists.txt rename src/{ => sc}/Architecture.cpp (99%) create mode 100644 src/sc/CMakeLists.txt rename src/{configuration => sc}/Configuration.cpp (87%) rename src/{ => sc}/DataLogger.cpp (98%) rename src/{ => sc}/Mapper.cpp (98%) create mode 100644 src/sc/exact/CMakeLists.txt rename src/{ => sc}/exact/ExactMapper.cpp (99%) create mode 100644 src/sc/heuristic/CMakeLists.txt rename src/{ => sc}/heuristic/HeuristicMapper.cpp (99%) rename src/{ => sc}/utils.cpp (99%) create mode 100644 test/cliffordsynthesis/CMakeLists.txt rename test/{ => cliffordsynthesis}/test_tableau.cpp (97%) create mode 100644 test/hybridmap/CMakeLists.txt create mode 100644 test/logicblocks/CMakeLists.txt rename test/{ => logicblocks}/test_logicblocks.cpp (100%) create mode 100644 test/sc/CMakeLists.txt create mode 100644 test/sc/exact/CMakeLists.txt rename test/{ => sc/exact}/test_encodings.cpp (89%) rename test/{ => sc/exact}/test_exact.cpp (94%) create mode 100644 test/sc/heuristic/CMakeLists.txt rename test/{ => sc/heuristic}/test_heuristic.cpp (98%) rename test/{ => sc}/test_architecture.cpp (99%) rename test/{ => sc}/test_general.cpp (99%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b7b299a4..6a6d8b05b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,9 +6,10 @@ project( LANGUAGES CXX DESCRIPTION "MQT QMAP - A library for mapping of quantum circuits to quantum architectures") -option(BUILD_MQT_QMAP_TESTS "Also build tests for the MQT QMAP project" ON) -option(BUILD_MQT_QMAP_BINDINGS "Build the MQT QMAP Python bindings" OFF) +# Add path for custom modules +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +option(BUILD_MQT_QMAP_BINDINGS "Build the MQT QMAP Python bindings" OFF) if(BUILD_MQT_QMAP_BINDINGS) # ensure that the BINDINGS option is set set(BINDINGS @@ -37,8 +38,14 @@ if(BUILD_MQT_QMAP_BINDINGS) OPTIONAL_COMPONENTS Development.SABIModule) endif() -# Add path for custom modules -list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +# check if this is the master project or used via add_subdirectory +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) + set(MQT_QMAP_MASTER_PROJECT ON) +else() + set(MQT_QMAP_MASTER_PROJECT OFF) +endif() + +option(BUILD_MQT_QMAP_TESTS "Also build tests for the MQT QMAP project" ${MQT_QMAP_MASTER_PROJECT}) include(cmake/ExternalDependencies.cmake) @@ -55,9 +62,15 @@ if(BUILD_MQT_QMAP_TESTS) add_subdirectory(test) endif() -if(NOT TARGET mqt-qmap-uninstall) - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake IMMEDIATE @ONLY) - add_custom_target(mqt-qmap-uninstall COMMAND ${CMAKE_COMMAND} -P - ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) +if(MQT_QMAP_MASTER_PROJECT) + if(NOT TARGET mqt-qmap-uninstall) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake IMMEDIATE @ONLY) + add_custom_target(mqt-qmap-uninstall COMMAND ${CMAKE_COMMAND} -P + ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) + endif() +else() + set(mqt-qmap_FOUND + TRUE + CACHE INTERNAL "True if mqt-qmap is found on the system") endif() diff --git a/include/cliffordsynthesis/Results.hpp b/include/cliffordsynthesis/Results.hpp index 78809ea07..ed7a6b9f4 100644 --- a/include/cliffordsynthesis/Results.hpp +++ b/include/cliffordsynthesis/Results.hpp @@ -5,34 +5,21 @@ #pragma once -#include "circuit_optimizer/CircuitOptimizer.hpp" #include "cliffordsynthesis/Tableau.hpp" #include "ir/QuantumComputation.hpp" #include "logicblocks/Logic.hpp" #include #include -#include +#include #include -#include #include namespace cs { class Results { public: Results() = default; - Results(qc::QuantumComputation& qc, const Tableau& tableau) { - // SWAP gates are not natively supported in the encoding, so we need to - // decompose them into sequences of three CNOTs. - qc::CircuitOptimizer::decomposeSWAP(qc, false); - - setResultCircuit(qc); - setResultTableau(tableau); - setDepth(qc.getDepth()); - setSingleQubitGates(qc.getNsingleQubitOps()); - setTwoQubitGates(qc.getNindividualOps() - singleQubitGates); - setSolverResult(logicbase::Result::SAT); - } + Results(qc::QuantumComputation& qc, const Tableau& tableau); virtual ~Results() = default; @@ -60,16 +47,8 @@ class Results { void setSolverResult(const logicbase::Result r) { solverResult = r; } void setSolverCalls(const std::size_t c) { solverCalls = c; } - void setResultCircuit(qc::QuantumComputation& qc) { - std::stringstream ss; - qc.dumpOpenQASM3(ss); - resultCircuit = ss.str(); - } - void setResultTableau(const Tableau& tableau) { - std::stringstream ss; - ss << tableau; - resultTableau = ss.str(); - } + void setResultCircuit(qc::QuantumComputation& qc); + void setResultTableau(const Tableau& tableau); [[nodiscard]] bool sat() const { return getSolverResult() == logicbase::Result::SAT; @@ -78,22 +57,9 @@ class Results { return getSolverResult() == logicbase::Result::UNSAT; } - [[nodiscard]] virtual nlohmann::basic_json<> json() const { - nlohmann::basic_json resultJSON{}; - resultJSON["solver_result"] = toString(solverResult); - resultJSON["single_qubit_gates"] = singleQubitGates; - resultJSON["two_qubit_gates"] = twoQubitGates; - resultJSON["depth"] = depth; - resultJSON["runtime"] = runtime; - resultJSON["solver_calls"] = solverCalls; + [[nodiscard]] virtual nlohmann::basic_json<> json() const; - return resultJSON; - } - - friend std::ostream& operator<<(std::ostream& os, const Results& config) { - os << config.json().dump(2); - return os; - } + friend std::ostream& operator<<(std::ostream& os, const Results& config); protected: logicbase::Result solverResult = logicbase::Result::NDEF; diff --git a/include/Architecture.hpp b/include/sc/Architecture.hpp similarity index 100% rename from include/Architecture.hpp rename to include/sc/Architecture.hpp diff --git a/include/DataLogger.hpp b/include/sc/DataLogger.hpp similarity index 100% rename from include/DataLogger.hpp rename to include/sc/DataLogger.hpp diff --git a/include/Mapper.hpp b/include/sc/Mapper.hpp similarity index 100% rename from include/Mapper.hpp rename to include/sc/Mapper.hpp diff --git a/include/MappingResults.hpp b/include/sc/MappingResults.hpp similarity index 100% rename from include/MappingResults.hpp rename to include/sc/MappingResults.hpp diff --git a/include/configuration/AvailableArchitecture.hpp b/include/sc/configuration/AvailableArchitecture.hpp similarity index 100% rename from include/configuration/AvailableArchitecture.hpp rename to include/sc/configuration/AvailableArchitecture.hpp diff --git a/include/configuration/CommanderGrouping.hpp b/include/sc/configuration/CommanderGrouping.hpp similarity index 100% rename from include/configuration/CommanderGrouping.hpp rename to include/sc/configuration/CommanderGrouping.hpp diff --git a/include/configuration/Configuration.hpp b/include/sc/configuration/Configuration.hpp similarity index 100% rename from include/configuration/Configuration.hpp rename to include/sc/configuration/Configuration.hpp diff --git a/include/configuration/EarlyTermination.hpp b/include/sc/configuration/EarlyTermination.hpp similarity index 100% rename from include/configuration/EarlyTermination.hpp rename to include/sc/configuration/EarlyTermination.hpp diff --git a/include/configuration/Encoding.hpp b/include/sc/configuration/Encoding.hpp similarity index 100% rename from include/configuration/Encoding.hpp rename to include/sc/configuration/Encoding.hpp diff --git a/include/configuration/Heuristic.hpp b/include/sc/configuration/Heuristic.hpp similarity index 100% rename from include/configuration/Heuristic.hpp rename to include/sc/configuration/Heuristic.hpp diff --git a/include/configuration/InitialLayout.hpp b/include/sc/configuration/InitialLayout.hpp similarity index 100% rename from include/configuration/InitialLayout.hpp rename to include/sc/configuration/InitialLayout.hpp diff --git a/include/configuration/Layering.hpp b/include/sc/configuration/Layering.hpp similarity index 100% rename from include/configuration/Layering.hpp rename to include/sc/configuration/Layering.hpp diff --git a/include/configuration/LookaheadHeuristic.hpp b/include/sc/configuration/LookaheadHeuristic.hpp similarity index 100% rename from include/configuration/LookaheadHeuristic.hpp rename to include/sc/configuration/LookaheadHeuristic.hpp diff --git a/include/configuration/Method.hpp b/include/sc/configuration/Method.hpp similarity index 100% rename from include/configuration/Method.hpp rename to include/sc/configuration/Method.hpp diff --git a/include/configuration/SwapReduction.hpp b/include/sc/configuration/SwapReduction.hpp similarity index 100% rename from include/configuration/SwapReduction.hpp rename to include/sc/configuration/SwapReduction.hpp diff --git a/include/exact/ExactMapper.hpp b/include/sc/exact/ExactMapper.hpp similarity index 88% rename from include/exact/ExactMapper.hpp rename to include/sc/exact/ExactMapper.hpp index 9946461d0..266593688 100644 --- a/include/exact/ExactMapper.hpp +++ b/include/sc/exact/ExactMapper.hpp @@ -5,10 +5,10 @@ #pragma once -#include "Mapper.hpp" -#include "MappingResults.hpp" -#include "configuration/Configuration.hpp" -#include "utils.hpp" +#include "sc/Mapper.hpp" +#include "sc/MappingResults.hpp" +#include "sc/configuration/Configuration.hpp" +#include "sc/utils.hpp" #include #include diff --git a/include/heuristic/HeuristicMapper.hpp b/include/sc/heuristic/HeuristicMapper.hpp similarity index 98% rename from include/heuristic/HeuristicMapper.hpp rename to include/sc/heuristic/HeuristicMapper.hpp index 4182022c6..88d9a8142 100644 --- a/include/heuristic/HeuristicMapper.hpp +++ b/include/sc/heuristic/HeuristicMapper.hpp @@ -3,12 +3,12 @@ // See README.md or go to https://github.com/cda-tum/qmap for more information. // -#include "Architecture.hpp" -#include "DataLogger.hpp" -#include "Mapper.hpp" -#include "configuration/Configuration.hpp" -#include "heuristic/UniquePriorityQueue.hpp" -#include "utils.hpp" +#include "sc/Architecture.hpp" +#include "sc/DataLogger.hpp" +#include "sc/Mapper.hpp" +#include "sc/configuration/Configuration.hpp" +#include "sc/heuristic/UniquePriorityQueue.hpp" +#include "sc/utils.hpp" #include #include diff --git a/include/heuristic/UniquePriorityQueue.hpp b/include/sc/heuristic/UniquePriorityQueue.hpp similarity index 100% rename from include/heuristic/UniquePriorityQueue.hpp rename to include/sc/heuristic/UniquePriorityQueue.hpp diff --git a/include/utils.hpp b/include/sc/utils.hpp similarity index 100% rename from include/utils.hpp rename to include/sc/utils.hpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5c5f65389..07c87258b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,135 +1,16 @@ set(MQT_QMAP_TARGET_NAME mqt-qmap) -# macro to add core libraries -macro(ADD_INTERNAL_LIBRARY libname) - set(lib ${libname}) - - # set include directories - target_include_directories(${lib} PUBLIC $) - - # add MQT::qfr library - target_link_libraries( - ${lib} - PUBLIC MQT::CoreIR MQT::CoreCircuitOptimizer nlohmann_json::nlohmann_json - PRIVATE MQT::ProjectOptions MQT::ProjectWarnings) -endmacro() - -# macro to add mapping libraries -macro(ADD_QMAP_LIBRARY libname srcfile) - set(lib ${MQT_QMAP_TARGET_NAME}-${libname}) - - # main project library - add_library( - ${lib} - ${libname}/${srcfile}.cpp - ${MQT_QMAP_INCLUDE_BUILD_DIR}/${libname}/${srcfile}.hpp - ${MQT_QMAP_INCLUDE_BUILD_DIR}/Architecture.hpp - ${MQT_QMAP_INCLUDE_BUILD_DIR}/configuration - ${MQT_QMAP_INCLUDE_BUILD_DIR}/DataLogger.hpp - ${MQT_QMAP_INCLUDE_BUILD_DIR}/heuristic/UniquePriorityQueue.hpp - ${MQT_QMAP_INCLUDE_BUILD_DIR}/Mapper.hpp - ${MQT_QMAP_INCLUDE_BUILD_DIR}/MappingResults.hpp - ${MQT_QMAP_INCLUDE_BUILD_DIR}/utils.hpp - Architecture.cpp - configuration/Configuration.cpp - DataLogger.cpp - Mapper.cpp - utils.cpp) - - add_internal_library(${lib}) -endmacro() - -# macro to add synthesis libraries -macro(ADD_SYNTHESIS_LIBRARY libname srcfile) - set(lib ${MQT_QMAP_TARGET_NAME}-${libname}) - - # main project library - add_library( - ${lib} - ${libname}/${srcfile}.cpp - ${MQT_QMAP_INCLUDE_BUILD_DIR}/${libname}/${srcfile}.hpp - ${MQT_QMAP_INCLUDE_BUILD_DIR}/cliffordsynthesis/Configuration.hpp - ${MQT_QMAP_INCLUDE_BUILD_DIR}/cliffordsynthesis/encoding/GateEncoder.hpp - ${MQT_QMAP_INCLUDE_BUILD_DIR}/cliffordsynthesis/encoding/MultiGateEncoder.hpp - ${MQT_QMAP_INCLUDE_BUILD_DIR}/cliffordsynthesis/encoding/ObjectiveEncoder.hpp - ${MQT_QMAP_INCLUDE_BUILD_DIR}/cliffordsynthesis/encoding/SATEncoder.hpp - ${MQT_QMAP_INCLUDE_BUILD_DIR}/cliffordsynthesis/encoding/SingleGateEncoder.hpp - ${MQT_QMAP_INCLUDE_BUILD_DIR}/cliffordsynthesis/encoding/TableauEncoder.hpp - ${MQT_QMAP_INCLUDE_BUILD_DIR}/cliffordsynthesis/Results.hpp - ${MQT_QMAP_INCLUDE_BUILD_DIR}/cliffordsynthesis/Tableau.hpp - ${MQT_QMAP_INCLUDE_BUILD_DIR}/cliffordsynthesis/TargetMetric.hpp - ${MQT_QMAP_INCLUDE_BUILD_DIR}/utils.hpp - cliffordsynthesis/encoding/GateEncoder.cpp - cliffordsynthesis/encoding/MultiGateEncoder.cpp - cliffordsynthesis/encoding/ObjectiveEncoder.cpp - cliffordsynthesis/encoding/SATEncoder.cpp - cliffordsynthesis/encoding/SingleGateEncoder.cpp - cliffordsynthesis/encoding/TableauEncoder.cpp - cliffordsynthesis/Tableau.cpp - utils.cpp) - - add_internal_library(${lib}) - target_link_libraries(${lib} PUBLIC MQT::CoreNA) -endmacro() - -# macro to add hybrid neutral atom mapping libraries -macro(ADD_HYBRIDMAP_LIBRARY libname srcfile) - set(lib ${MQT_QMAP_TARGET_NAME}-${libname}) - - # main project library - add_library( - ${lib} - ${libname}/${srcfile}.cpp - ${PROJECT_SOURCE_DIR}/include/${libname}/${srcfile}.hpp - ${PROJECT_SOURCE_DIR}/include/${libname}/NeutralAtomUtils.hpp - ${PROJECT_SOURCE_DIR}/include/${libname}/NeutralAtomScheduler.hpp - ${PROJECT_SOURCE_DIR}/include/${libname}/NeutralAtomArchitecture.hpp - ${PROJECT_SOURCE_DIR}/include/${libname}/HardwareQubits.hpp - ${PROJECT_SOURCE_DIR}/include/${libname}/Mapping.hpp - ${PROJECT_SOURCE_DIR}/include/${libname}/NeutralAtomDefinitions.hpp - ${PROJECT_SOURCE_DIR}/include/${libname}/MoveToAodConverter.hpp - ${PROJECT_SOURCE_DIR}/include/${libname}/NeutralAtomLayer.hpp - ${PROJECT_SOURCE_DIR}/include/${libname}/HybridAnimation.hpp - hybridmap/NeutralAtomUtils.cpp - hybridmap/NeutralAtomScheduler.cpp - hybridmap/NeutralAtomArchitecture.cpp - hybridmap/HardwareQubits.cpp - hybridmap/Mapping.cpp - hybridmap/MoveToAodConverter.cpp - hybridmap/HybridAnimation.cpp - hybridmap/NeutralAtomLayer.cpp) - - add_internal_library(${lib}) -endmacro() - # exact mapper project library if(Z3_FOUND) # add LogicBlocks library add_subdirectory(logicblocks) - add_qmap_library(exact ExactMapper) - target_link_libraries(${MQT_QMAP_TARGET_NAME}-exact PRIVATE MQT::LogicBlocks) - - add_synthesis_library(cliffordsynthesis CliffordSynthesizer) - target_link_libraries( - ${MQT_QMAP_TARGET_NAME}-cliffordsynthesis - PUBLIC plog::plog - PRIVATE MQT::LogicBlocks) - - # add MQT alias targets - add_library(MQT::QMapExact ALIAS ${MQT_QMAP_TARGET_NAME}-exact) - add_library(MQT::QMapCliffordSynthesis ALIAS ${MQT_QMAP_TARGET_NAME}-cliffordsynthesis) + add_subdirectory(cliffordsynthesis) endif() -# heuristic mapper project library -add_qmap_library(heuristic HeuristicMapper) - -# hybrid neutral atom mapper project library -add_hybridmap_library(hybridmap HybridNeutralAtomMapper) +add_subdirectory(sc) -# add MQT alias targets -add_library(MQT::QMapHeuristic ALIAS ${MQT_QMAP_TARGET_NAME}-heuristic) -add_library(MQT::QMapHybrid ALIAS ${MQT_QMAP_TARGET_NAME}-hybridmap) +add_subdirectory(hybridmap) add_subdirectory(na) diff --git a/src/cliffordsynthesis/CMakeLists.txt b/src/cliffordsynthesis/CMakeLists.txt new file mode 100644 index 000000000..832ec3f11 --- /dev/null +++ b/src/cliffordsynthesis/CMakeLists.txt @@ -0,0 +1,30 @@ +# +# 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/mqt-qmap for more information. +# + +set(MQT_QMAP_CLIFFORD_SYNTHESIS_TARGET_NAME ${MQT_QMAP_TARGET_NAME}-cliffordsynthesis) + +if(NOT TARGET ${MQT_QMAP_CLIFFORD_SYNTHESIS_TARGET_NAME}) + # collect headers and source files + file(GLOB_RECURSE CLIFFORD_SYNTHESIS_HEADERS + ${MQT_QMAP_INCLUDE_BUILD_DIR}/cliffordsynthesis/*.hpp) + file(GLOB_RECURSE CLIFFORD_SYNTHESIS_SOURCES **.cpp) + + # add CliffordSynthesis Package library + add_library(${MQT_QMAP_CLIFFORD_SYNTHESIS_TARGET_NAME} ${CLIFFORD_SYNTHESIS_HEADERS} + ${CLIFFORD_SYNTHESIS_SOURCES}) + + # set include directories + target_include_directories(${MQT_QMAP_CLIFFORD_SYNTHESIS_TARGET_NAME} + PUBLIC $) + + # link to the MQT::Core libraries + target_link_libraries( + ${MQT_QMAP_CLIFFORD_SYNTHESIS_TARGET_NAME} + PUBLIC MQT::CoreIR plog::plog nlohmann_json::nlohmann_json + PRIVATE MQT::LogicBlocks MQT::ProjectWarnings MQT::ProjectOptions MQT::CoreCircuitOptimizer) + + # add MQT alias + add_library(MQT::QMapCliffordSynthesis ALIAS ${MQT_QMAP_CLIFFORD_SYNTHESIS_TARGET_NAME}) +endif() diff --git a/src/cliffordsynthesis/Results.cpp b/src/cliffordsynthesis/Results.cpp new file mode 100644 index 000000000..c229e49e9 --- /dev/null +++ b/src/cliffordsynthesis/Results.cpp @@ -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. +// + +#include "cliffordsynthesis/Results.hpp" + +#include "Logic.hpp" +#include "circuit_optimizer/CircuitOptimizer.hpp" +#include "cliffordsynthesis/Tableau.hpp" +#include "ir/QuantumComputation.hpp" + +#include +#include +#include + +namespace cs { + +Results::Results(qc::QuantumComputation& qc, const Tableau& tableau) { + // SWAP gates are not natively supported in the encoding, so we need to + // decompose them into sequences of three CNOTs. + qc::CircuitOptimizer::decomposeSWAP(qc, false); + + setResultCircuit(qc); + setResultTableau(tableau); + setDepth(qc.getDepth()); + setSingleQubitGates(qc.getNsingleQubitOps()); + setTwoQubitGates(qc.getNindividualOps() - singleQubitGates); + setSolverResult(logicbase::Result::SAT); +} + +void Results::setResultCircuit(qc::QuantumComputation& qc) { + std::stringstream ss; + qc.dumpOpenQASM3(ss); + resultCircuit = ss.str(); +} + +void Results::setResultTableau(const Tableau& tableau) { + std::stringstream ss; + ss << tableau; + resultTableau = ss.str(); +} + +nlohmann::basic_json<> Results::json() const { + nlohmann::basic_json resultJSON{}; + resultJSON["solver_result"] = toString(solverResult); + resultJSON["single_qubit_gates"] = singleQubitGates; + resultJSON["two_qubit_gates"] = twoQubitGates; + resultJSON["depth"] = depth; + resultJSON["runtime"] = runtime; + resultJSON["solver_calls"] = solverCalls; + + return resultJSON; +} + +std::ostream& operator<<(std::ostream& os, const Results& config) { + os << config.json().dump(2); + return os; +} +} // namespace cs diff --git a/src/cliffordsynthesis/Tableau.cpp b/src/cliffordsynthesis/Tableau.cpp index e02415d95..074da87f3 100644 --- a/src/cliffordsynthesis/Tableau.cpp +++ b/src/cliffordsynthesis/Tableau.cpp @@ -9,7 +9,6 @@ #include "ir/operations/CompoundOperation.hpp" #include "ir/operations/OpType.hpp" #include "ir/operations/Operation.hpp" -#include "utils.hpp" #include #include @@ -50,6 +49,37 @@ void Tableau::import(const std::string& filename) { import(is); } +void parseLine(const std::string& line, char separator, + const std::set& escapeChars, + const std::set& ignoredChars, + std::vector& result) { + result.clear(); + std::string word; + bool inEscape = false; + for (const char c : line) { + if (ignoredChars.find(c) != ignoredChars.end()) { + continue; + } + if (inEscape) { + if (escapeChars.find(c) != escapeChars.end()) { + inEscape = false; + } else { + word += c; + } + } else { + if (escapeChars.find(c) != escapeChars.end()) { + inEscape = true; + } else if (c == separator) { + result.push_back(word); + word = ""; + } else { + word += c; + } + } + } + result.push_back(word); +} + void Tableau::import(std::istream& is) { tableau.clear(); @@ -62,7 +92,7 @@ void Tableau::import(std::istream& is) { delimiter = ';'; } tableau.emplace_back(); - ::parseLine(line, delimiter, {'\"'}, {'\\', '\r', '\n', '\t'}, data); + parseLine(line, delimiter, {'\"'}, {'\\', '\r', '\n', '\t'}, data); for (const auto& datum : data) { if (datum.empty()) { continue; @@ -399,7 +429,7 @@ Tableau::RowType Tableau::parseStabilizer(const std::string& stab) { if (stabCopy[stabCopy.size() - 1] == '\'') { stabCopy = stabCopy.substr(1, stabCopy.size() - 2); } else { - throw QMAPException("Unmatched \"'\" in stabilizer string"); + throw std::invalid_argument("Unmatched \"'\" in stabilizer string"); } } if (stabCopy[0] == '+' || stabCopy[0] == '-') { @@ -413,9 +443,10 @@ Tableau::RowType Tableau::parseStabilizer(const std::string& stab) { } else if (c == 'X' || c == 'Y') { row.push_back(1); } else { - throw QMAPException("Invalid stabilizer " + stab + - ". Stabilizers must be given as a list of stabilizer " - "like [XYZI, ZIXZ]"); + throw std::invalid_argument( + "Invalid stabilizer " + stab + + ". Stabilizers must be given as a list of stabilizer " + "like [XYZI, ZIXZ]"); } } for (const auto c : stabCopy) { @@ -424,9 +455,10 @@ Tableau::RowType Tableau::parseStabilizer(const std::string& stab) { } else if (c == 'Y' || c == 'Z') { row.push_back(1); } else { - throw QMAPException("Invalid stabilizer" + stab + - ". Stabilizers must be given as a list of stabilizer " - "like [XYZI, ZIXZ]"); + throw std::invalid_argument( + "Invalid stabilizer" + stab + + ". Stabilizers must be given as a list of stabilizer " + "like [XYZI, ZIXZ]"); } } if (stab[0U] == '-' || (stab[0U] == '\'' && stab[1U] == '-')) { @@ -453,7 +485,7 @@ void Tableau::loadStabilizerDestabilizerString(const std::string& string) { if (stabilizers[stabilizers.size() - 1] == ']') { stabilizers = stabilizers.substr(1, stabilizers.size() - 2); } else { - throw QMAPException("Unmatched \"[\" in stabilizer string"); + throw std::invalid_argument("Unmatched \"[\" in stabilizer string"); } } @@ -463,7 +495,7 @@ void Tableau::loadStabilizerDestabilizerString(const std::string& string) { stabLength = row.size(); } if (stabLength.value() != row.size()) { - throw QMAPException("All Stabilizers muts have the same length"); + throw std::invalid_argument("All Stabilizers muts have the same length"); } }; diff --git a/src/hybridmap/CMakeLists.txt b/src/hybridmap/CMakeLists.txt new file mode 100644 index 000000000..3d0a7d23c --- /dev/null +++ b/src/hybridmap/CMakeLists.txt @@ -0,0 +1,28 @@ +# +# 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/mqt-qmap for more information. +# + +set(MQT_QMAP_HYBRIDMAP_TARGET_NAME ${MQT_QMAP_TARGET_NAME}-hybridmap) + +if(NOT TARGET ${MQT_QMAP_HYBRIDMAP_TARGET_NAME}) + # collect headers and source files + file(GLOB_RECURSE HYBRIDMAP_HEADERS ${MQT_QMAP_INCLUDE_BUILD_DIR}/hybridmap/*.hpp) + file(GLOB_RECURSE HYBRIDMAP_SOURCES **.cpp) + + # add HybridMap Package library + add_library(${MQT_QMAP_HYBRIDMAP_TARGET_NAME} ${HYBRIDMAP_HEADERS} ${HYBRIDMAP_SOURCES}) + + # set include directories + target_include_directories(${MQT_QMAP_HYBRIDMAP_TARGET_NAME} + PUBLIC $) + + # link to the MQT::Core libraries + target_link_libraries( + ${MQT_QMAP_HYBRIDMAP_TARGET_NAME} + PUBLIC MQT::CoreIR nlohmann_json::nlohmann_json + PRIVATE MQT::ProjectWarnings MQT::ProjectOptions MQT::CoreCircuitOptimizer) + + # add MQT alias + add_library(MQT::QMapHybrid ALIAS ${MQT_QMAP_HYBRIDMAP_TARGET_NAME}) +endif() diff --git a/src/hybridmap/HybridAnimation.cpp b/src/hybridmap/HybridAnimation.cpp index f6257a22d..1de1bc863 100644 --- a/src/hybridmap/HybridAnimation.cpp +++ b/src/hybridmap/HybridAnimation.cpp @@ -10,13 +10,13 @@ #include "hybridmap/NeutralAtomDefinitions.hpp" #include "ir/operations/AodOperation.hpp" #include "ir/operations/OpType.hpp" -#include "utils.hpp" #include #include #include #include #include +#include #include namespace na { @@ -60,8 +60,9 @@ AnimationAtoms::axesId AnimationAtoms::addAxis(HwQubit id) { axesIdCounter++; axesIds[id] = axesIdCounter; } else { - throw QMAPException("Tried to add axis but axis already exists for qubit " + - std::to_string(id)); + throw std::invalid_argument( + "Tried to add axis but axis already exists for qubit " + + std::to_string(id)); } return axesIds[id]; } @@ -70,7 +71,7 @@ AnimationAtoms::marginId AnimationAtoms::addMargin(HwQubit id) { marginIdCounter++; marginIds[id] = marginIdCounter; } else { - throw QMAPException( + throw std::invalid_argument( "Tried to add margin but margin already exists for qubit " + std::to_string(id)); } @@ -117,16 +118,16 @@ AnimationAtoms::createCsvOp(const std::unique_ptr& op, } if (coordIdxToId.find(coordIdx) == coordIdxToId.end() || idToCoord.find(coordIdxToId.at(coordIdx)) == idToCoord.end()) { - throw QMAPException("Tried to create csv line for qubit at coordIdx " + - std::to_string(coordIdx) + - " but there is no qubit at this coordIdx"); + throw std::invalid_argument( + "Tried to create csv line for qubit at coordIdx " + + std::to_string(coordIdx) + " but there is no qubit at this coordIdx"); } auto id = coordIdxToId.at(coordIdx); auto coord = idToCoord.at(id); if (op->getType() == qc::OpType::AodActivate) { addAxis(id); if (axesIds.find(id) == axesIds.end()) { - throw QMAPException( + throw std::invalid_argument( "Tried to activate qubit at coordIdx " + std::to_string(coordIdx) + " but there is no axis for qubit " + std::to_string(id)); } @@ -136,10 +137,10 @@ AnimationAtoms::createCsvOp(const std::unique_ptr& op, colorAod, true, axesIds.at(id)); } else if (op->getType() == qc::OpType::AodDeactivate) { if (axesIds.find(id) == axesIds.end()) { - throw QMAPException("Tried to deactivate qubit at coordIdx " + - std::to_string(coordIdx) + - " but there is no axis for qubit " + - std::to_string(id)); + throw std::invalid_argument("Tried to deactivate qubit at coordIdx " + + std::to_string(coordIdx) + + " but there is no axis for qubit " + + std::to_string(id)); } csvLine += createCsvLine(startTime, id, coord.first, coord.second, 1, colorAod, true, axesIds.at(id)); @@ -149,7 +150,7 @@ AnimationAtoms::createCsvOp(const std::unique_ptr& op, } else if (op->getType() == qc::OpType::AodMove) { if (axesIds.find(id) == axesIds.end()) { - throw QMAPException( + throw std::invalid_argument( "Tried to move qubit at coordIdx " + std::to_string(coordIdx) + " but there is no axis for qubit " + std::to_string(id)); } diff --git a/src/hybridmap/HybridNeutralAtomMapper.cpp b/src/hybridmap/HybridNeutralAtomMapper.cpp index 9c6026818..3acb425a0 100644 --- a/src/hybridmap/HybridNeutralAtomMapper.cpp +++ b/src/hybridmap/HybridNeutralAtomMapper.cpp @@ -14,7 +14,6 @@ #include "ir/QuantumComputation.hpp" #include "ir/operations/OpType.hpp" #include "ir/operations/Operation.hpp" -#include "utils.hpp" #include #include @@ -1171,7 +1170,7 @@ NeutralAtomMapper::getMoveAwayCombinations(CoordIndex startCoord, moveCombinations.addMoveComb(MoveComb({moveAway, move})); } if (moveCombinations.empty()) { - throw QMAPException("No move away target found"); + throw std::runtime_error("No move away target found"); } return moveCombinations; } diff --git a/src/hybridmap/MoveToAodConverter.cpp b/src/hybridmap/MoveToAodConverter.cpp index ffd00fb82..ad71c8a1f 100644 --- a/src/hybridmap/MoveToAodConverter.cpp +++ b/src/hybridmap/MoveToAodConverter.cpp @@ -13,7 +13,6 @@ #include "ir/operations/AodOperation.hpp" #include "ir/operations/OpType.hpp" #include "na/NADefinitions.hpp" -#include "utils.hpp" #include #include @@ -21,6 +20,7 @@ #include #include #include +#include #include #include @@ -176,7 +176,7 @@ void MoveToAodConverter::AodActivationHelper::addActivation( reAssignOffsets(aodMovesX, signX); break; case ActivationMergeType::Merge: - throw QMAPException("Merge in both dimensions should never happen."); + throw std::runtime_error("Merge in both dimensions should never happen."); case ActivationMergeType::Append: mergeActivationDim(Dimension::X, AodActivation{Dimension::X, {x, deltaX, signX}, move}, diff --git a/src/hybridmap/NeutralAtomArchitecture.cpp b/src/hybridmap/NeutralAtomArchitecture.cpp index 2db6b6464..43bb885f3 100644 --- a/src/hybridmap/NeutralAtomArchitecture.cpp +++ b/src/hybridmap/NeutralAtomArchitecture.cpp @@ -11,7 +11,6 @@ #include "ir/operations/AodOperation.hpp" #include "ir/operations/OpType.hpp" #include "ir/operations/Operation.hpp" -#include "nlohmann/json.hpp" #include #include @@ -19,7 +18,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/na/Architecture.cpp b/src/na/Architecture.cpp index 4f9b6222a..70650b642 100644 --- a/src/na/Architecture.cpp +++ b/src/na/Architecture.cpp @@ -4,10 +4,11 @@ // information. // -#include "Architecture.hpp" +#include "na/Architecture.hpp" -#include "Configuration.hpp" +#include "Definitions.hpp" #include "ir/operations/OpType.hpp" +#include "na/Configuration.hpp" #include "na/NADefinitions.hpp" #include @@ -157,6 +158,9 @@ auto Architecture::isAllowedLocally(const FullOpType& t, return false; // gate not supported at all } const auto it = gateSet.find(t); + if (it == gateSet.end()) { + qc::unreachable(); // please the clang-tidy null dereference checker + } const auto& gateZones = it->second.zones; // zone exists in gateZones return gateZones.find(zone) != gateZones.end(); @@ -189,6 +193,9 @@ auto Architecture::isAllowedGlobally(const FullOpType& t, return false; // gate not supported at all } const auto it = gateSet.find(t); + if (it == gateSet.end()) { + qc::unreachable(); // please the clang-tidy null dereference checker + } const auto& gateZones = it->second.zones; // zone exists in gateZones return gateZones.find(zone) != gateZones.end(); diff --git a/src/na/CMakeLists.txt b/src/na/CMakeLists.txt index 04e3fca59..216ebe548 100644 --- a/src/na/CMakeLists.txt +++ b/src/na/CMakeLists.txt @@ -6,14 +6,13 @@ set(MQT_QMAP_NA_TARGET_NAME ${MQT_QMAP_TARGET_NAME}-na) if(NOT TARGET ${MQT_QMAP_NA_TARGET_NAME}) - file(GLOB_RECURSE NA_HEADERS ${MQT_QMAP_INCLUDE_BUILD_DIR}/na/*.hpp - ${MQT_QMAP_INCLUDE_BUILD_DIR}/na/operations/*.hpp) + file(GLOB_RECURSE NA_HEADERS ${MQT_QMAP_INCLUDE_BUILD_DIR}/na/*.hpp) file(GLOB_RECURSE NA_SOURCES *.cpp) add_library(${MQT_QMAP_NA_TARGET_NAME} ${NA_HEADERS} ${NA_SOURCES}) target_include_directories(${MQT_QMAP_NA_TARGET_NAME} - PUBLIC $) + PUBLIC $) target_link_libraries(${MQT_QMAP_NA_TARGET_NAME} PUBLIC MQT::CoreIR MQT::CoreNA nlohmann_json::nlohmann_json) diff --git a/src/na/Configuration.cpp b/src/na/Configuration.cpp index ad5bdf07f..8204f3b1e 100644 --- a/src/na/Configuration.cpp +++ b/src/na/Configuration.cpp @@ -4,7 +4,7 @@ // information. // -#include "Configuration.hpp" +#include "na/Configuration.hpp" #include #include diff --git a/src/na/NAGraphAlgorithms.cpp b/src/na/NAGraphAlgorithms.cpp index fee700e12..262582952 100644 --- a/src/na/NAGraphAlgorithms.cpp +++ b/src/na/NAGraphAlgorithms.cpp @@ -4,7 +4,7 @@ // information. // -#include "NAGraphAlgorithms.hpp" +#include "na/NAGraphAlgorithms.hpp" #include "Definitions.hpp" #include "datastructures/DirectedAcyclicGraph.hpp" diff --git a/src/na/NAMapper.cpp b/src/na/NAMapper.cpp index 867bac27f..a4d6b935c 100644 --- a/src/na/NAMapper.cpp +++ b/src/na/NAMapper.cpp @@ -4,18 +4,18 @@ // information. // -#include "NAMapper.hpp" +#include "na/NAMapper.hpp" -#include "Architecture.hpp" -#include "Configuration.hpp" #include "Definitions.hpp" -#include "NAGraphAlgorithms.hpp" #include "datastructures/Layer.hpp" #include "ir/QuantumComputation.hpp" #include "ir/operations/CompoundOperation.hpp" #include "ir/operations/OpType.hpp" #include "ir/operations/Operation.hpp" +#include "na/Architecture.hpp" +#include "na/Configuration.hpp" #include "na/NADefinitions.hpp" +#include "na/NAGraphAlgorithms.hpp" #include "na/operations/NAGlobalOperation.hpp" #include "na/operations/NALocalOperation.hpp" #include "na/operations/NAShuttlingOperation.hpp" diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index dcf182660..d58073426 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -18,13 +18,13 @@ pybind11_add_module( target_compile_definitions(pyqmap PRIVATE Z3_FOUND) target_link_libraries( pyqmap - PRIVATE MQT::QMapExact - MQT::QMapHeuristic + PRIVATE MQT::QMapSCExact + MQT::QMapSCHeuristic MQT::QMapCliffordSynthesis + MQT::QMapHybrid MQT::CorePython MQT::ProjectOptions MQT::ProjectWarnings - MQT::QMapHybrid pybind11_json) # Install directive for scikit-build-core diff --git a/src/python/bindings.cpp b/src/python/bindings.cpp index 7b12a6ca1..dc87016d4 100644 --- a/src/python/bindings.cpp +++ b/src/python/bindings.cpp @@ -4,16 +4,17 @@ // #include "cliffordsynthesis/CliffordSynthesizer.hpp" -#include "exact/ExactMapper.hpp" -#include "heuristic/HeuristicMapper.hpp" #include "hybridmap/HybridNeutralAtomMapper.hpp" #include "hybridmap/NeutralAtomScheduler.hpp" -#include "nlohmann/json.hpp" -#include "pybind11/pybind11.h" -#include "pybind11/stl.h" -#include "pybind11_json/pybind11_json.hpp" #include "python/qiskit/QuantumCircuit.hpp" -#include "string" +#include "sc/exact/ExactMapper.hpp" +#include "sc/heuristic/HeuristicMapper.hpp" + +#include +#include +#include +#include +#include namespace py = pybind11; using namespace pybind11::literals; diff --git a/src/Architecture.cpp b/src/sc/Architecture.cpp similarity index 99% rename from src/Architecture.cpp rename to src/sc/Architecture.cpp index 726cdd44a..b50b13720 100644 --- a/src/Architecture.cpp +++ b/src/sc/Architecture.cpp @@ -3,10 +3,10 @@ // See README.md or go to https://github.com/cda-tum/qmap for more information. // -#include "Architecture.hpp" +#include "sc/Architecture.hpp" -#include "configuration/AvailableArchitecture.hpp" -#include "utils.hpp" +#include "sc/configuration/AvailableArchitecture.hpp" +#include "sc/utils.hpp" #include #include diff --git a/src/sc/CMakeLists.txt b/src/sc/CMakeLists.txt new file mode 100644 index 000000000..7943c2f06 --- /dev/null +++ b/src/sc/CMakeLists.txt @@ -0,0 +1,34 @@ +# +# 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/mqt-qmap for more information. +# + +set(MQT_QMAP_SC_TARGET_NAME ${MQT_QMAP_TARGET_NAME}-sc) + +if(NOT TARGET ${MQT_QMAP_SC_TARGET_NAME}) + # collect headers and source files + file(GLOB SC_HEADERS ${MQT_QMAP_INCLUDE_BUILD_DIR}/sc/*.hpp + ${MQT_QMAP_INCLUDE_BUILD_DIR}/sc/configuration/*.hpp) + file(GLOB SC_SOURCES **.cpp) + + # add SC Package library + add_library(${MQT_QMAP_SC_TARGET_NAME} ${SC_HEADERS} ${SC_SOURCES}) + + # set include directories + target_include_directories(${MQT_QMAP_SC_TARGET_NAME} + PUBLIC $) + + # link to the MQT::Core libraries + target_link_libraries( + ${MQT_QMAP_SC_TARGET_NAME} + PUBLIC MQT::CoreIR nlohmann_json::nlohmann_json + PRIVATE MQT::CoreCircuitOptimizer MQT::ProjectWarnings MQT::ProjectOptions) + + # add MQT alias + add_library(MQT::QMapSC ALIAS ${MQT_QMAP_SC_TARGET_NAME}) +endif() + +add_subdirectory(heuristic) +if(Z3_FOUND) + add_subdirectory(exact) +endif() diff --git a/src/configuration/Configuration.cpp b/src/sc/Configuration.cpp similarity index 87% rename from src/configuration/Configuration.cpp rename to src/sc/Configuration.cpp index 6bfb28697..cddbcaae2 100644 --- a/src/configuration/Configuration.cpp +++ b/src/sc/Configuration.cpp @@ -3,16 +3,16 @@ // See README.md or go to https://github.com/cda-tum/qmap for more information. // -#include "configuration/Configuration.hpp" +#include "sc/configuration/Configuration.hpp" -#include "configuration/CommanderGrouping.hpp" -#include "configuration/Encoding.hpp" -#include "configuration/Heuristic.hpp" -#include "configuration/InitialLayout.hpp" -#include "configuration/Layering.hpp" -#include "configuration/LookaheadHeuristic.hpp" -#include "configuration/Method.hpp" -#include "configuration/SwapReduction.hpp" +#include "sc/configuration/CommanderGrouping.hpp" +#include "sc/configuration/Encoding.hpp" +#include "sc/configuration/Heuristic.hpp" +#include "sc/configuration/InitialLayout.hpp" +#include "sc/configuration/Layering.hpp" +#include "sc/configuration/LookaheadHeuristic.hpp" +#include "sc/configuration/Method.hpp" +#include "sc/configuration/SwapReduction.hpp" #include diff --git a/src/DataLogger.cpp b/src/sc/DataLogger.cpp similarity index 98% rename from src/DataLogger.cpp rename to src/sc/DataLogger.cpp index cb990cc0f..0375a7784 100644 --- a/src/DataLogger.cpp +++ b/src/sc/DataLogger.cpp @@ -3,13 +3,13 @@ // See README.md or go to https://github.com/cda-tum/qmap for more information. // -#include "DataLogger.hpp" +#include "sc/DataLogger.hpp" -#include "Architecture.hpp" -#include "MappingResults.hpp" #include "ir/operations/CompoundOperation.hpp" #include "ir/operations/OpType.hpp" -#include "utils.hpp" +#include "sc/Architecture.hpp" +#include "sc/MappingResults.hpp" +#include "sc/utils.hpp" #include #include diff --git a/src/Mapper.cpp b/src/sc/Mapper.cpp similarity index 98% rename from src/Mapper.cpp rename to src/sc/Mapper.cpp index aece4ae32..8dce3fbc5 100644 --- a/src/Mapper.cpp +++ b/src/sc/Mapper.cpp @@ -3,15 +3,15 @@ // See README.md or go to https://github.com/cda-tum/qmap for more information. // -#include "Mapper.hpp" +#include "sc/Mapper.hpp" -#include "Architecture.hpp" #include "Definitions.hpp" #include "circuit_optimizer/CircuitOptimizer.hpp" -#include "configuration/Layering.hpp" #include "ir/operations/CompoundOperation.hpp" #include "ir/operations/OpType.hpp" -#include "utils.hpp" +#include "sc/Architecture.hpp" +#include "sc/configuration/Layering.hpp" +#include "sc/utils.hpp" #include #include @@ -582,8 +582,8 @@ void Mapper::countGates(decltype(qcMapped.cbegin()) it, continue; } - if (g->isCompoundOperation()) { - const auto& cg = dynamic_cast(g.get()); + if (const auto& cg = dynamic_cast(g.get()); + cg != nullptr) { countGates(cg->cbegin(), cg->cend(), info); } } diff --git a/src/sc/exact/CMakeLists.txt b/src/sc/exact/CMakeLists.txt new file mode 100644 index 000000000..30f2f72f4 --- /dev/null +++ b/src/sc/exact/CMakeLists.txt @@ -0,0 +1,28 @@ +# +# 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/mqt-qmap for more information. +# + +set(MQT_QMAP_SC_EXACT_TARGET_NAME ${MQT_QMAP_TARGET_NAME}-sc-exact) + +if(NOT TARGET ${MQT_QMAP_SC_EXACT_TARGET_NAME}) + # collect headers and source files + file(GLOB SC_EXACT_HEADERS ${MQT_QMAP_INCLUDE_BUILD_DIR}/sc/exact/*.hpp) + file(GLOB SC_EXACT_SOURCES **.cpp) + + # add SC Exact Package library + add_library(${MQT_QMAP_SC_EXACT_TARGET_NAME} ${SC_EXACT_HEADERS} ${SC_EXACT_SOURCES}) + + # set include directories + target_include_directories(${MQT_QMAP_SC_EXACT_TARGET_NAME} + PUBLIC $) + + # link to the MQT::Core libraries + target_link_libraries( + ${MQT_QMAP_SC_EXACT_TARGET_NAME} + PUBLIC MQT::QMapSC + PRIVATE MQT::LogicBlocks MQT::ProjectWarnings MQT::ProjectOptions) + + # add MQT alias + add_library(MQT::QMapSCExact ALIAS ${MQT_QMAP_SC_EXACT_TARGET_NAME}) +endif() diff --git a/src/exact/ExactMapper.cpp b/src/sc/exact/ExactMapper.cpp similarity index 99% rename from src/exact/ExactMapper.cpp rename to src/sc/exact/ExactMapper.cpp index 9bb3408ec..a622921dc 100644 --- a/src/exact/ExactMapper.cpp +++ b/src/sc/exact/ExactMapper.cpp @@ -3,22 +3,22 @@ // See README.md or go to https://github.com/cda-tum/qmap for more information. // -#include "exact/ExactMapper.hpp" +#include "sc/exact/ExactMapper.hpp" -#include "Architecture.hpp" #include "Definitions.hpp" #include "Logic.hpp" #include "LogicTerm.hpp" -#include "configuration/CommanderGrouping.hpp" -#include "configuration/Configuration.hpp" -#include "configuration/Encoding.hpp" -#include "configuration/SwapReduction.hpp" #include "ir/operations/StandardOperation.hpp" #include "logicblocks/Encodings.hpp" #include "logicblocks/LogicBlock.hpp" #include "logicblocks/Model.hpp" #include "logicblocks/util_logicblock.hpp" -#include "utils.hpp" +#include "sc/Architecture.hpp" +#include "sc/configuration/CommanderGrouping.hpp" +#include "sc/configuration/Configuration.hpp" +#include "sc/configuration/Encoding.hpp" +#include "sc/configuration/SwapReduction.hpp" +#include "sc/utils.hpp" #include #include diff --git a/src/sc/heuristic/CMakeLists.txt b/src/sc/heuristic/CMakeLists.txt new file mode 100644 index 000000000..12909975b --- /dev/null +++ b/src/sc/heuristic/CMakeLists.txt @@ -0,0 +1,28 @@ +# +# 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/mqt-qmap for more information. +# + +set(MQT_QMAP_SC_HEURISTIC_TARGET_NAME ${MQT_QMAP_TARGET_NAME}-sc-heuristic) + +if(NOT TARGET ${MQT_QMAP_SC_HEURISTIC_TARGET_NAME}) + # collect headers and source files + file(GLOB SC_HEURISTIC_HEADERS ${MQT_QMAP_INCLUDE_BUILD_DIR}/sc/heuristic/*.hpp) + file(GLOB SC_HEURISTIC_SOURCES **.cpp) + + # add SC Heuristic Package library + add_library(${MQT_QMAP_SC_HEURISTIC_TARGET_NAME} ${SC_HEURISTIC_HEADERS} ${SC_HEURISTIC_SOURCES}) + + # set include directories + target_include_directories(${MQT_QMAP_SC_HEURISTIC_TARGET_NAME} + PUBLIC $) + + # link to the MQT::Core libraries + target_link_libraries( + ${MQT_QMAP_SC_HEURISTIC_TARGET_NAME} + PUBLIC MQT::QMapSC + PRIVATE MQT::ProjectWarnings MQT::ProjectOptions) + + # add MQT alias + add_library(MQT::QMapSCHeuristic ALIAS ${MQT_QMAP_SC_HEURISTIC_TARGET_NAME}) +endif() diff --git a/src/heuristic/HeuristicMapper.cpp b/src/sc/heuristic/HeuristicMapper.cpp similarity index 99% rename from src/heuristic/HeuristicMapper.cpp rename to src/sc/heuristic/HeuristicMapper.cpp index 48cdb234a..f81515b52 100644 --- a/src/heuristic/HeuristicMapper.cpp +++ b/src/sc/heuristic/HeuristicMapper.cpp @@ -3,22 +3,22 @@ // See README.md or go to https://github.com/cda-tum/qmap for more information. // -#include "heuristic/HeuristicMapper.hpp" +#include "sc/heuristic/HeuristicMapper.hpp" -#include "Architecture.hpp" -#include "DataLogger.hpp" #include "Definitions.hpp" -#include "Mapper.hpp" -#include "configuration/Configuration.hpp" -#include "configuration/EarlyTermination.hpp" -#include "configuration/Heuristic.hpp" -#include "configuration/InitialLayout.hpp" -#include "configuration/Layering.hpp" -#include "configuration/LookaheadHeuristic.hpp" #include "ir/operations/CompoundOperation.hpp" #include "ir/operations/OpType.hpp" #include "ir/operations/StandardOperation.hpp" -#include "utils.hpp" +#include "sc/Architecture.hpp" +#include "sc/DataLogger.hpp" +#include "sc/Mapper.hpp" +#include "sc/configuration/Configuration.hpp" +#include "sc/configuration/EarlyTermination.hpp" +#include "sc/configuration/Heuristic.hpp" +#include "sc/configuration/InitialLayout.hpp" +#include "sc/configuration/Layering.hpp" +#include "sc/configuration/LookaheadHeuristic.hpp" +#include "sc/utils.hpp" #include #include diff --git a/src/utils.cpp b/src/sc/utils.cpp similarity index 99% rename from src/utils.cpp rename to src/sc/utils.cpp index 0f7c393e4..3205f3f67 100644 --- a/src/utils.cpp +++ b/src/sc/utils.cpp @@ -3,7 +3,7 @@ // See README.md or go to https://github.com/cda-tum/qmap for more information. // -#include "utils.hpp" +#include "sc/utils.hpp" #include #include diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5c16c6d2c..6777ebedf 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,35 +1,5 @@ -package_add_test( - mqt-qmap-heuristic-test MQT::QMapHeuristic ${CMAKE_CURRENT_SOURCE_DIR}/test_heuristic.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/test_general.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_architecture.cpp) - -if(TARGET MQT::QMapExact) - package_add_test(mqt-qmap-exact-test MQT::QMapExact ${CMAKE_CURRENT_SOURCE_DIR}/test_exact.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/test_encodings.cpp) -endif() - +add_subdirectory(sc) +add_subdirectory(hybridmap) add_subdirectory(na) - -if(TARGET MQT::QMapCliffordSynthesis) - configure_file(${PROJECT_SOURCE_DIR}/test/cliffordsynthesis/tableaus.json - ${CMAKE_CURRENT_BINARY_DIR}/cliffordsynthesis/tableaus.json COPYONLY) - configure_file(${PROJECT_SOURCE_DIR}/test/cliffordsynthesis/circuits.json - ${CMAKE_CURRENT_BINARY_DIR}/cliffordsynthesis/circuits.json COPYONLY) - package_add_test( - mqt-qmap-cliffordsynthesis-test MQT::QMapCliffordSynthesis - ${CMAKE_CURRENT_SOURCE_DIR}/test_tableau.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/cliffordsynthesis/test_synthesis.cpp) -endif() - -if(TARGET MQT::LogicBlocks) - package_add_test(mqt-logic-blocks-test MQT::LogicBlocks - ${CMAKE_CURRENT_SOURCE_DIR}/test_logicblocks.cpp) -endif() - -if(TARGET MQT::QMapHybrid) - file(COPY ${PROJECT_SOURCE_DIR}/test/hybridmap/architectures - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) - file(COPY ${PROJECT_SOURCE_DIR}/test/hybridmap/circuits DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) - package_add_test_with_working_dir( - ${PROJECT_NAME}-hybridmap-test MQT::QMapHybrid ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/hybridmap/test_hybridmap.cpp) -endif() +add_subdirectory(logicblocks) +add_subdirectory(cliffordsynthesis) diff --git a/test/cliffordsynthesis/CMakeLists.txt b/test/cliffordsynthesis/CMakeLists.txt new file mode 100644 index 000000000..43f206e9e --- /dev/null +++ b/test/cliffordsynthesis/CMakeLists.txt @@ -0,0 +1,10 @@ +if(TARGET MQT::QMapCliffordSynthesis) + configure_file(${PROJECT_SOURCE_DIR}/test/cliffordsynthesis/tableaus.json + ${CMAKE_CURRENT_BINARY_DIR}/tableaus.json COPYONLY) + configure_file(${PROJECT_SOURCE_DIR}/test/cliffordsynthesis/circuits.json + ${CMAKE_CURRENT_BINARY_DIR}/circuits.json COPYONLY) + + file(GLOB_RECURSE CLIFFORDSYNTHESIS_TEST_SOURCES *.cpp) + package_add_test(mqt-qmap-cliffordsynthesis-test MQT::QMapCliffordSynthesis + ${CLIFFORDSYNTHESIS_TEST_SOURCES}) +endif() diff --git a/test/cliffordsynthesis/test_synthesis.cpp b/test/cliffordsynthesis/test_synthesis.cpp index 5449caa9d..45b7c8c6c 100644 --- a/test/cliffordsynthesis/test_synthesis.cpp +++ b/test/cliffordsynthesis/test_synthesis.cpp @@ -149,15 +149,13 @@ class SynthesisTest : public ::testing::TestWithParam { }; INSTANTIATE_TEST_SUITE_P( - Tableaus, SynthesisTest, - testing::ValuesIn(getTests("cliffordsynthesis/tableaus.json")), + Tableaus, SynthesisTest, testing::ValuesIn(getTests("tableaus.json")), [](const testing::TestParamInfo& inf) { return inf.param.description; }); INSTANTIATE_TEST_SUITE_P( - Circuits, SynthesisTest, - testing::ValuesIn(getTests("cliffordsynthesis/circuits.json")), + Circuits, SynthesisTest, testing::ValuesIn(getTests("circuits.json")), [](const testing::TestParamInfo& inf) { return inf.param.description; }); diff --git a/test/test_tableau.cpp b/test/cliffordsynthesis/test_tableau.cpp similarity index 97% rename from test/test_tableau.cpp rename to test/cliffordsynthesis/test_tableau.cpp index b960593f2..d1307b450 100644 --- a/test/test_tableau.cpp +++ b/test/cliffordsynthesis/test_tableau.cpp @@ -9,7 +9,6 @@ #include "ir/operations/Control.hpp" #include "ir/operations/OpType.hpp" #include "ir/operations/StandardOperation.hpp" -#include "utils.hpp" #include #include @@ -647,14 +646,14 @@ TEST_F(TestTableau, TableauIO) { } TEST_F(TestTableau, InvalidInput) { - EXPECT_THROW(tableau = Tableau("[ZZX, aXy]"), QMAPException); - EXPECT_THROW(tableau = Tableau("[ZZ__I, XXY]"), QMAPException); - EXPECT_THROW(tableau = Tableau("[ZZI, -XY]"), QMAPException); - EXPECT_THROW(tableau = Tableau("XY, XY]"), QMAPException); - EXPECT_THROW(tableau = Tableau("[XY, XY"), QMAPException); - EXPECT_THROW(tableau = Tableau("[XY, XY"), QMAPException); - EXPECT_THROW(tableau = Tableau("[XY; XY"), QMAPException); - EXPECT_THROW(tableau = Tableau("['XY, XY]"), QMAPException); + EXPECT_THROW(tableau = Tableau("[ZZX, aXy]"), std::invalid_argument); + EXPECT_THROW(tableau = Tableau("[ZZ__I, XXY]"), std::invalid_argument); + EXPECT_THROW(tableau = Tableau("[ZZI, -XY]"), std::invalid_argument); + EXPECT_THROW(tableau = Tableau("XY, XY]"), std::invalid_argument); + EXPECT_THROW(tableau = Tableau("[XY, XY"), std::invalid_argument); + EXPECT_THROW(tableau = Tableau("[XY, XY"), std::invalid_argument); + EXPECT_THROW(tableau = Tableau("[XY; XY"), std::invalid_argument); + EXPECT_THROW(tableau = Tableau("['XY, XY]"), std::invalid_argument); } TEST_F(TestTableau, ApplyCXH) { diff --git a/test/hybridmap/CMakeLists.txt b/test/hybridmap/CMakeLists.txt new file mode 100644 index 000000000..d3b0c3ae1 --- /dev/null +++ b/test/hybridmap/CMakeLists.txt @@ -0,0 +1,9 @@ +if(TARGET MQT::QMapHybrid) + file(COPY ${PROJECT_SOURCE_DIR}/test/hybridmap/architectures + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + file(COPY ${PROJECT_SOURCE_DIR}/test/hybridmap/circuits DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + + file(GLOB_RECURSE HYBRIDMAP_TEST_SOURCES *.cpp) + package_add_test_with_working_dir(${PROJECT_NAME}-hybridmap-test MQT::QMapHybrid + ${CMAKE_CURRENT_BINARY_DIR} ${HYBRIDMAP_TEST_SOURCES}) +endif() diff --git a/test/logicblocks/CMakeLists.txt b/test/logicblocks/CMakeLists.txt new file mode 100644 index 000000000..0215036a3 --- /dev/null +++ b/test/logicblocks/CMakeLists.txt @@ -0,0 +1,4 @@ +if(TARGET MQT::LogicBlocks) + file(GLOB_RECURSE LOGICBLOCKS_TEST_SOURCES *.cpp) + package_add_test(mqt-logic-blocks-test MQT::LogicBlocks ${LOGICBLOCKS_TEST_SOURCES}) +endif() diff --git a/test/test_logicblocks.cpp b/test/logicblocks/test_logicblocks.cpp similarity index 100% rename from test/test_logicblocks.cpp rename to test/logicblocks/test_logicblocks.cpp diff --git a/test/na/test_architecture.cpp b/test/na/test_architecture.cpp index b679535fa..2d00c456a 100644 --- a/test/na/test_architecture.cpp +++ b/test/na/test_architecture.cpp @@ -3,9 +3,9 @@ // See README.md or go to https://github.com/cda-tum/qmap for more information. // -#include "Architecture.hpp" -#include "Configuration.hpp" #include "ir/operations/OpType.hpp" +#include "na/Architecture.hpp" +#include "na/Configuration.hpp" #include #include diff --git a/test/na/test_configuration.cpp b/test/na/test_configuration.cpp index c61f454d8..22b988484 100644 --- a/test/na/test_configuration.cpp +++ b/test/na/test_configuration.cpp @@ -3,7 +3,7 @@ // See README.md or go to https://github.com/cda-tum/qmap for more information. // -#include "Configuration.hpp" +#include "na/Configuration.hpp" #include #include diff --git a/test/na/test_nagraphalgorithms.cpp b/test/na/test_nagraphalgorithms.cpp index 21e274b1a..55bbee33c 100644 --- a/test/na/test_nagraphalgorithms.cpp +++ b/test/na/test_nagraphalgorithms.cpp @@ -4,10 +4,10 @@ // #include "Definitions.hpp" -#include "NAGraphAlgorithms.hpp" #include "datastructures/Layer.hpp" #include "ir/QuantumComputation.hpp" #include "ir/operations/OpType.hpp" +#include "na/NAGraphAlgorithms.hpp" #include "gtest/gtest.h" #include diff --git a/test/na/test_namapper.cpp b/test/na/test_namapper.cpp index 6c6f7e8a1..1f3855a8b 100644 --- a/test/na/test_namapper.cpp +++ b/test/na/test_namapper.cpp @@ -3,16 +3,16 @@ // See README.md or go to https://github.com/cda-tum/qmap for more information. // -#include "Architecture.hpp" -#include "Configuration.hpp" #include "Definitions.hpp" -#include "NAMapper.hpp" #include "datastructures/Layer.hpp" #include "ir/QuantumComputation.hpp" #include "ir/operations/CompoundOperation.hpp" #include "ir/operations/OpType.hpp" #include "ir/operations/StandardOperation.hpp" +#include "na/Architecture.hpp" +#include "na/Configuration.hpp" #include "na/NAComputation.hpp" +#include "na/NAMapper.hpp" #include "na/operations/NAGlobalOperation.hpp" #include "na/operations/NALocalOperation.hpp" #include "na/operations/NAShuttlingOperation.hpp" diff --git a/test/sc/CMakeLists.txt b/test/sc/CMakeLists.txt new file mode 100644 index 000000000..d75901839 --- /dev/null +++ b/test/sc/CMakeLists.txt @@ -0,0 +1,7 @@ +if(TARGET MQT::QMapSC) + file(GLOB SC_TEST_SOURCES *.cpp) + package_add_test(mqt-qmap-sc-test MQT::QMapSC ${SC_TEST_SOURCES}) +endif() + +add_subdirectory(heuristic) +add_subdirectory(exact) diff --git a/test/sc/exact/CMakeLists.txt b/test/sc/exact/CMakeLists.txt new file mode 100644 index 000000000..7daff465b --- /dev/null +++ b/test/sc/exact/CMakeLists.txt @@ -0,0 +1,4 @@ +if(TARGET MQT::QMapSCExact) + file(GLOB_RECURSE SC_EXACT_TEST_SOURCES *.cpp) + package_add_test(mqt-qmap-sc-exact-test MQT::QMapSCExact ${SC_EXACT_TEST_SOURCES}) +endif() diff --git a/test/test_encodings.cpp b/test/sc/exact/test_encodings.cpp similarity index 89% rename from test/test_encodings.cpp rename to test/sc/exact/test_encodings.cpp index 8a156e740..335c98cdc 100644 --- a/test/test_encodings.cpp +++ b/test/sc/exact/test_encodings.cpp @@ -3,15 +3,15 @@ // See README.md or go to https://github.com/cda-tum/qmap for more information. // -#include "Architecture.hpp" -#include "configuration/AvailableArchitecture.hpp" -#include "configuration/CommanderGrouping.hpp" -#include "configuration/Configuration.hpp" -#include "configuration/Encoding.hpp" -#include "configuration/Method.hpp" -#include "exact/ExactMapper.hpp" #include "ir/QuantumComputation.hpp" #include "ir/operations/Control.hpp" +#include "sc/Architecture.hpp" +#include "sc/configuration/AvailableArchitecture.hpp" +#include "sc/configuration/CommanderGrouping.hpp" +#include "sc/configuration/Configuration.hpp" +#include "sc/configuration/Encoding.hpp" +#include "sc/configuration/Method.hpp" +#include "sc/exact/ExactMapper.hpp" #include #include diff --git a/test/test_exact.cpp b/test/sc/exact/test_exact.cpp similarity index 94% rename from test/test_exact.cpp rename to test/sc/exact/test_exact.cpp index 9d1a08d97..2ec977b2f 100644 --- a/test/test_exact.cpp +++ b/test/sc/exact/test_exact.cpp @@ -1,628 +1,628 @@ -// -// 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. -// - -#include "Architecture.hpp" -#include "Definitions.hpp" -#include "configuration/AvailableArchitecture.hpp" -#include "configuration/CommanderGrouping.hpp" -#include "configuration/Configuration.hpp" -#include "configuration/Encoding.hpp" -#include "configuration/InitialLayout.hpp" -#include "configuration/Layering.hpp" -#include "configuration/Method.hpp" -#include "configuration/SwapReduction.hpp" -#include "exact/ExactMapper.hpp" -#include "ir/QuantumComputation.hpp" -#include "ir/operations/Control.hpp" -#include "ir/operations/OpType.hpp" -#include "utils.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include - -class ExactTest : public testing::TestWithParam { -protected: - std::string testExampleDir = "../examples/"; - std::string testArchitectureDir = "../extern/architectures/"; - std::string testCalibrationDir = "../extern/calibration/"; - - qc::QuantumComputation qc; - Configuration settings{}; - Architecture ibmqYorktown; - Architecture ibmqLondon; - Architecture ibmQX4; - std::unique_ptr ibmqYorktownMapper; - std::unique_ptr ibmqLondonMapper; - std::unique_ptr ibmQX4Mapper; - - void SetUp() override { - using namespace qc::literals; - - if (::testing::UnitTest::GetInstance() - ->current_test_info() - ->value_param() != nullptr) { - qc.import(testExampleDir + GetParam() + ".qasm"); - } else { - qc.addQubitRegister(3U); - qc.cx(1_pc, 0); - qc.cx(2_pc, 1); - qc.cx(0_pc, 2); - } - ibmqYorktown.loadCouplingMap(AvailableArchitecture::IbmqYorktown); - ibmqLondon.loadCouplingMap(testArchitectureDir + "ibmq_london.arch"); - ibmqLondon.loadProperties(testCalibrationDir + "ibmq_london.csv"); - ibmQX4.loadCouplingMap(AvailableArchitecture::IbmQx4); - - ibmqYorktownMapper = std::make_unique(qc, ibmqYorktown); - ibmqLondonMapper = std::make_unique(qc, ibmqLondon); - ibmQX4Mapper = std::make_unique(qc, ibmQX4); - - settings.verbose = true; - settings.method = Method::Exact; - } -}; - -INSTANTIATE_TEST_SUITE_P( - Exact, ExactTest, - testing::Values("3_17_13", "ex-1_166", "ham3_102", "miller_11", "4gt11_84"), - [](const testing::TestParamInfo& inf) { - std::string name = inf.param; - std::replace(name.begin(), name.end(), '-', '_'); - return name; - }); - -TEST_P(ExactTest, IndividualGates) { - settings.layering = Layering::IndividualGates; - ibmqYorktownMapper->map(settings); - ibmqYorktownMapper->dumpResult(GetParam() + - "_exact_yorktown_individual.qasm"); - ibmqYorktownMapper->printResult(std::cout); - - ibmqLondonMapper->map(settings); - ibmqLondonMapper->dumpResult(GetParam() + "_exact_london_individual.qasm"); - ibmqLondonMapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} - -TEST_P(ExactTest, DisjointQubits) { - settings.layering = Layering::DisjointQubits; - ibmqYorktownMapper->map(settings); - ibmqYorktownMapper->dumpResult(GetParam() + "_exact_yorktown_disjoint.qasm"); - ibmqYorktownMapper->printResult(std::cout); - - ibmqLondonMapper->map(settings); - ibmqLondonMapper->dumpResult(GetParam() + "_exact_london_disjoint.qasm"); - ibmqLondonMapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} - -TEST_P(ExactTest, Disjoint2qBlocks) { - settings.layering = Layering::Disjoint2qBlocks; - ibmqYorktownMapper->map(settings); - ibmqYorktownMapper->dumpResult(GetParam() + - "_exact_yorktown_disjoint_2q.qasm"); - ibmqYorktownMapper->printResult(std::cout); - - ibmqLondonMapper->map(settings); - ibmqLondonMapper->dumpResult(GetParam() + "_exact_london_disjoint_2q.qasm"); - ibmqLondonMapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} - -TEST_P(ExactTest, OddGates) { - settings.layering = Layering::OddGates; - ibmqYorktownMapper->map(settings); - ibmqYorktownMapper->dumpResult(GetParam() + "_exact_yorktown_odd.qasm"); - ibmqYorktownMapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} - -TEST_P(ExactTest, QubitTriangle) { - settings.layering = Layering::QubitTriangle; - ibmqYorktownMapper->map(settings); - ibmqYorktownMapper->dumpResult(GetParam() + "_exact_yorktown_triangle.qasm"); - ibmqYorktownMapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} - -TEST_P(ExactTest, CommanderEncodingfixed3) { - settings.encoding = Encoding::Commander; - settings.commanderGrouping = CommanderGrouping::Fixed3; - ibmqYorktownMapper->map(settings); - ibmqYorktownMapper->dumpResult(GetParam() + - "_exact_yorktown_commander_fixed3.qasm"); - ibmqYorktownMapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} -TEST_P(ExactTest, CommanderEncodingfixed2) { - settings.encoding = Encoding::Commander; - settings.commanderGrouping = CommanderGrouping::Fixed2; - ibmqYorktownMapper->map(settings); - ibmqYorktownMapper->dumpResult(GetParam() + - "_exact_yorktown_commander_fixed2.qasm"); - ibmqYorktownMapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} -TEST_P(ExactTest, CommanderEncodinghalves) { - settings.encoding = Encoding::Commander; - settings.commanderGrouping = CommanderGrouping::Halves; - ibmqYorktownMapper->map(settings); - ibmqYorktownMapper->dumpResult(GetParam() + - "_exact_yorktown_commander_halves.qasm"); - ibmqYorktownMapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} -TEST_P(ExactTest, CommanderEncodinglogarithm) { - settings.encoding = Encoding::Commander; - settings.commanderGrouping = CommanderGrouping::Logarithm; - ibmqYorktownMapper->map(settings); - ibmqYorktownMapper->dumpResult(GetParam() + - "_exact_yorktown_commander_log.qasm"); - ibmqYorktownMapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} - -TEST_P(ExactTest, CommanderEncodingUnidirectionalfixed3) { - settings.encoding = Encoding::Commander; - settings.commanderGrouping = CommanderGrouping::Fixed3; - ibmQX4Mapper->map(settings); - ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_commander_fixed3.qasm"); - ibmQX4Mapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} -TEST_P(ExactTest, CommanderEncodingUnidirectionalfixed2) { - settings.encoding = Encoding::Commander; - settings.commanderGrouping = CommanderGrouping::Fixed2; - ibmQX4Mapper->map(settings); - ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_commander_fixed2.qasm"); - ibmQX4Mapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} -TEST_P(ExactTest, CommanderEncodingUnidirectionalhalves) { - settings.encoding = Encoding::Commander; - settings.commanderGrouping = CommanderGrouping::Halves; - ibmQX4Mapper->map(settings); - ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_commander_halves.qasm"); - ibmQX4Mapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} -TEST_P(ExactTest, CommanderEncodingUnidirectionallogarithm) { - settings.encoding = Encoding::Commander; - settings.commanderGrouping = CommanderGrouping::Logarithm; - ibmQX4Mapper->map(settings); - ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_commander_log.qasm"); - ibmQX4Mapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} - -TEST_P(ExactTest, BimanderEncodingfixed3) { - settings.encoding = Encoding::Bimander; - settings.commanderGrouping = CommanderGrouping::Fixed3; - ibmqYorktownMapper->map(settings); - ibmqYorktownMapper->dumpResult(GetParam() + "_exact_yorktown_bimander.qasm"); - ibmqYorktownMapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} -TEST_P(ExactTest, BimanderEncodingfixed2) { - settings.encoding = Encoding::Bimander; - settings.commanderGrouping = CommanderGrouping::Fixed2; - ibmqYorktownMapper->map(settings); - ibmqYorktownMapper->dumpResult(GetParam() + "_exact_yorktown_bimander.qasm"); - ibmqYorktownMapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} -TEST_P(ExactTest, BimanderEncodinghalves) { - settings.encoding = Encoding::Bimander; - settings.commanderGrouping = CommanderGrouping::Halves; - ibmqYorktownMapper->map(settings); - ibmqYorktownMapper->dumpResult(GetParam() + "_exact_yorktown_bimander.qasm"); - ibmqYorktownMapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} -TEST_P(ExactTest, BimanderEncodinglogaritm) { - settings.encoding = Encoding::Bimander; - settings.commanderGrouping = CommanderGrouping::Logarithm; - ibmqYorktownMapper->map(settings); - ibmqYorktownMapper->dumpResult(GetParam() + "_exact_yorktown_bimander.qasm"); - ibmqYorktownMapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} - -TEST_P(ExactTest, BimanderEncodingUnidirectionalfixed3) { - settings.encoding = Encoding::Bimander; - settings.commanderGrouping = CommanderGrouping::Fixed3; - ibmQX4Mapper->map(settings); - ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_bimander.qasm"); - ibmQX4Mapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} -TEST_P(ExactTest, BimanderEncodingUnidirectionalfixed2) { - settings.encoding = Encoding::Bimander; - settings.commanderGrouping = CommanderGrouping::Fixed2; - ibmQX4Mapper->map(settings); - ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_bimander.qasm"); - ibmQX4Mapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} -TEST_P(ExactTest, BimanderEncodingUnidirectionalhalves) { - settings.encoding = Encoding::Bimander; - settings.commanderGrouping = CommanderGrouping::Halves; - ibmQX4Mapper->map(settings); - ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_bimander.qasm"); - ibmQX4Mapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} -TEST_P(ExactTest, BimanderEncodingUnidirectionallogarithm) { - settings.encoding = Encoding::Bimander; - settings.commanderGrouping = CommanderGrouping::Logarithm; - ibmQX4Mapper->map(settings); - ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_bimander.qasm"); - ibmQX4Mapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} - -TEST_P(ExactTest, LimitsBidirectional) { - settings.enableSwapLimits = true; - settings.useSubsets = false; - settings.swapReduction = SwapReduction::CouplingLimit; - ibmqYorktownMapper->map(settings); - ibmqYorktownMapper->dumpResult(GetParam() + - "_exact_yorktown_swapreduct.qasm"); - ibmqYorktownMapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} -TEST_P(ExactTest, LimitsBidirectionalSubsetSwaps) { - settings.enableSwapLimits = true; - settings.useSubsets = true; - settings.swapReduction = SwapReduction::CouplingLimit; - ibmqYorktownMapper->map(settings); - ibmqYorktownMapper->dumpResult(GetParam() + - "_exact_yorktown_swapreduct.qasm"); - ibmqYorktownMapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} -TEST_P(ExactTest, LimitsBidirectionalCustomLimit) { - settings.enableSwapLimits = true; - settings.swapReduction = SwapReduction::Custom; - settings.swapLimit = 10; - ibmqYorktownMapper->map(settings); - ibmqYorktownMapper->dumpResult(GetParam() + - "_exact_yorktown_swapreduct.qasm"); - ibmqYorktownMapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} - -TEST_P(ExactTest, LimitsUnidirectional) { - settings.enableSwapLimits = true; - settings.useSubsets = false; - settings.swapReduction = SwapReduction::CouplingLimit; - ibmQX4Mapper->map(settings); - ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_swapreduct.qasm"); - ibmQX4Mapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} -TEST_P(ExactTest, LimitsUnidirectionalSubsetSwaps) { - settings.enableSwapLimits = true; - settings.useSubsets = true; - settings.swapReduction = SwapReduction::CouplingLimit; - ibmQX4Mapper->map(settings); - ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_swapreduct.qasm"); - ibmQX4Mapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} -TEST_P(ExactTest, LimitsUnidirectionalCustomLimit) { - settings.enableSwapLimits = true; - settings.swapReduction = SwapReduction::Custom; - settings.swapLimit = 10; - ibmQX4Mapper->map(settings); - ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_swapreduct.qasm"); - ibmQX4Mapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} -TEST_P(ExactTest, IncreasingCustomLimitUnidirectional) { - settings.enableSwapLimits = true; - settings.swapReduction = SwapReduction::Increasing; - settings.swapLimit = 3; - ibmQX4Mapper->map(settings); - ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_swapreduct_inccustom.qasm"); - ibmQX4Mapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} -TEST_P(ExactTest, IncreasingUnidirectional) { - settings.enableSwapLimits = true; - settings.swapReduction = SwapReduction::Increasing; - settings.swapLimit = 0; - ibmQX4Mapper->map(settings); - ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_swapreduct_inc.qasm"); - ibmQX4Mapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} - -TEST_P(ExactTest, NoSubsets) { - settings.useSubsets = false; - settings.enableSwapLimits = false; - ibmQX4Mapper->map(settings); - ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_nosubsets.qasm"); - ibmQX4Mapper->printResult(std::cout); - SUCCEED() << "Mapping successful"; -} - -TEST_P(ExactTest, toStringMethods) { - EXPECT_EQ(toString(InitialLayout::Identity), "identity"); - EXPECT_EQ(toString(InitialLayout::Static), "static"); - EXPECT_EQ(toString(InitialLayout::Dynamic), "dynamic"); - - EXPECT_EQ(toString(Layering::IndividualGates), "individual_gates"); - EXPECT_EQ(toString(Layering::DisjointQubits), "disjoint_qubits"); - EXPECT_EQ(toString(Layering::Disjoint2qBlocks), "disjoint_2q_blocks"); - EXPECT_EQ(toString(Layering::OddGates), "odd_gates"); - EXPECT_EQ(toString(Layering::QubitTriangle), "qubit_triangle"); - - EXPECT_EQ(toString(Encoding::Naive), "naive"); - EXPECT_EQ(toString(Encoding::Commander), "commander"); - EXPECT_EQ(toString(Encoding::Bimander), "bimander"); - - EXPECT_EQ(toString(CommanderGrouping::Fixed2), "fixed2"); - EXPECT_EQ(toString(CommanderGrouping::Fixed3), "fixed3"); - EXPECT_EQ(toString(CommanderGrouping::Logarithm), "logarithm"); - EXPECT_EQ(toString(CommanderGrouping::Halves), "halves"); - - EXPECT_EQ(toString(SwapReduction::CouplingLimit), "coupling_limit"); - EXPECT_EQ(toString(SwapReduction::Custom), "custom"); - EXPECT_EQ(toString(SwapReduction::None), "none"); - EXPECT_EQ(toString(SwapReduction::Increasing), "increasing"); - - SUCCEED() << "ToStringMethods working"; -} - -TEST_F(ExactTest, CircuitWithOnlySingleQubitGates) { - qc.clear(); - qc.x(0); - qc.x(1); - ibmQX4Mapper = std::make_unique(qc, ibmQX4); - ibmQX4Mapper->map(settings); - ibmQX4Mapper->dumpResult(std::cout, qc::Format::OpenQASM3); - SUCCEED() << "Mapping successful"; -} - -TEST_F(ExactTest, MapToSubsetNotIncludingQ0) { - const CouplingMap cm{{0, 1}, {1, 0}, {1, 2}, {2, 1}, - {2, 3}, {3, 2}, {1, 3}, {3, 1}}; - Architecture arch(4U, cm); - - auto mapper = ExactMapper(qc, arch); - settings.useSubsets = false; - mapper.map(settings); - - std::ostringstream oss{}; - mapper.dumpResult(oss, qc::Format::OpenQASM3); - auto qcMapped = qc::QuantumComputation(); - std::istringstream iss{oss.str()}; - qcMapped.import(iss, qc::Format::OpenQASM3); - std::cout << qcMapped << '\n'; - EXPECT_EQ(qcMapped.initialLayout.size(), 4U); - EXPECT_EQ(qcMapped.initialLayout[0], 3); - EXPECT_EQ(qcMapped.outputPermutation.size(), 3U); - EXPECT_TRUE(qcMapped.garbage.at(3)); -} - -TEST_F(ExactTest, WCNF) { - settings.verbose = false; - settings.includeWCNF = true; - ibmqLondonMapper->map(settings); - ibmqLondonMapper->printResult(std::cout); - const auto& wcnf = ibmqLondonMapper->getResults().wcnf; - EXPECT_TRUE(!wcnf.empty()); -} - -TEST_F(ExactTest, WCNFNotAvailable) { - using namespace qc::literals; - - settings.verbose = false; - settings.encoding = Encoding::Naive; - settings.includeWCNF = true; - - auto circ = qc::QuantumComputation(5U); - circ.h(0); - circ.cx(0_pc, 1); - circ.cx(0_pc, 2); - circ.cx(0_pc, 3); - circ.cx(0_pc, 4); - - auto mapper = ExactMapper(circ, ibmqLondon); - - mapper.map(settings); - EXPECT_TRUE(mapper.getResults().wcnf.empty()); - - auto mapper2 = ExactMapper(circ, ibmqLondon); - settings.encoding = Encoding::Commander; - mapper2.map(settings); - EXPECT_FALSE(mapper2.getResults().wcnf.empty()); -} - -TEST_F(ExactTest, MapToSubgraph) { - const auto connectedSubset = std::set{0U, 1U, 2U}; - - settings.subgraph = connectedSubset; - ibmqLondonMapper->map(settings); - const auto& results = ibmqLondonMapper->getResults(); - EXPECT_FALSE(results.timeout); -} - -TEST_F(ExactTest, MapToSubgraphTooSmall) { - const auto tooSmallSubset = std::set{0U, 1U}; - - settings.subgraph = tooSmallSubset; - ibmqLondonMapper->map(settings); - const auto& results = ibmqLondonMapper->getResults(); - EXPECT_TRUE(results.timeout); -} - -TEST_F(ExactTest, MapToSubgraphNotConnected) { - const auto nonConnectedSubset = std::set{0U, 2U, 3U}; - - settings.subgraph = nonConnectedSubset; - ibmqLondonMapper->map(settings); - const auto& results = ibmqLondonMapper->getResults(); - EXPECT_TRUE(results.timeout); -} -TEST_F(ExactTest, CommanderEncodingRigettiArch) { - Architecture aspen; - aspen.loadCouplingMap(AvailableArchitecture::RigettiAspen); - Architecture agave; - agave.loadCouplingMap(AvailableArchitecture::RigettiAgave); - - auto aspenMapper = ExactMapper(qc, aspen); - auto agaveMapper = ExactMapper(qc, agave); - aspenMapper.map(settings); - agaveMapper.map(settings); - aspenMapper.printResult(std::cout); - agaveMapper.printResult(std::cout); - - SUCCEED() << "Mapping successful"; -} - -TEST_F(ExactTest, NoMeasurementsAdded) { - // configure to not include measurements after mapping - settings.addMeasurementsToMappedCircuit = false; - - // perform the mapping - ibmqLondonMapper->map(settings); - - // get the resulting circuit - auto qcMapped = qc::QuantumComputation(); - std::stringstream qasm{}; - ibmqLondonMapper->dumpResult(qasm, qc::Format::OpenQASM3); - qcMapped.import(qasm, qc::Format::OpenQASM3); - - // check no measurements were added - EXPECT_EQ(qcMapped.getNops(), 4U); - EXPECT_NE(qcMapped.back()->getType(), qc::Measure); -} - -TEST_F(ExactTest, Test4QCircuitThatUsesAll5Q) { - Architecture arch; - const CouplingMap cm = {{0, 1}, {1, 0}, {1, 2}, {2, 1}, {2, 3}, - {3, 2}, {3, 4}, {4, 3}, {4, 0}, {0, 4}}; - arch.loadCouplingMap(5, cm); - - std::stringstream ss{"OPENQASM 2.0;\ninclude \"qelib1.inc\";\n" - "qreg q[4];\n" - "cx q[0],q[1];\n" - "cx q[1],q[2];\n" - "cx q[2],q[3];\n" - "cx q[3],q[0];\n"}; - qc.import(ss, qc::Format::OpenQASM3); - - auto mapper = ExactMapper(qc, arch); - // explicitly do not use subsets, but the full architecture - settings.useSubsets = false; - - ASSERT_NO_THROW(mapper.map(settings);); - const auto& results = mapper.getResults(); - EXPECT_EQ(results.output.swaps, 1); -} - -TEST_F(ExactTest, RegressionTestDirectionReverseCost) { - // Regression test for https://github.com/cda-tum/qmap/issues/251 - using namespace qc::literals; - - Architecture arch; - const CouplingMap cm = {{1, 0}, {2, 0}, {2, 1}, {4, 2}, {3, 2}, {3, 4}}; - arch.loadCouplingMap(5, cm); - - Architecture::printCouplingMap(cm, std::cout); - - qc = qc::QuantumComputation(4); - qc.cx(1_pc, 0); - qc.cx(0_pc, 1); - qc.cx(2_pc, 1); - qc.cx(1_pc, 2); - qc.cx(3_pc, 2); - - auto mapper = ExactMapper(qc, arch); - mapper.map(settings); - EXPECT_EQ(mapper.getResults().output.swaps, 0); - EXPECT_EQ(mapper.getResults().output.directionReverse, 2); -} - -TEST_F(ExactTest, RegressionTestExactMapperPerformance) { - // Regression test for https://github.com/cda-tum/qmap/issues/256 - std::stringstream ss{"OPENQASM 2.0;\n" - "include \"qelib1.inc\";\n" - "qreg q[3];\n" - "cx q[0],q[2];\n" - "cx q[2],q[1];\n" - "cx q[2],q[1];\n" - "cx q[0],q[2];\n" - "cx q[1],q[0];\n" - "cx q[1],q[2];\n" - "cx q[0],q[2];\n" - "cx q[1],q[0];\n" - "cx q[2],q[1];\n" - "cx q[1],q[0];\n" - "cx q[2],q[1];\n" - "cx q[0],q[2];\n" - "cx q[0],q[1];\n" - "cx q[2],q[1];\n" - "cx q[0],q[2];\n" - "cx q[1],q[0];\n" - "cx q[1],q[2];\n"}; - - Architecture arch; - const CouplingMap cm = {{1, 0}, {2, 0}, {2, 1}, {3, 2}, {3, 4}, {4, 2}}; - arch.loadCouplingMap(5, cm); - qc.import(ss, qc::Format::OpenQASM3); - - auto mapper = ExactMapper(qc, arch); - settings.swapReduction = SwapReduction::CouplingLimit; - mapper.map(settings); - EXPECT_EQ(mapper.getResults().output.swaps, 1); - EXPECT_EQ(mapper.getResults().output.directionReverse, 4); - - auto mapper2 = ExactMapper(qc, arch); - settings.swapReduction = SwapReduction::None; - mapper2.map(settings); - EXPECT_EQ(mapper2.getResults().output.swaps, 1); - EXPECT_EQ(mapper2.getResults().output.directionReverse, 4); -} - -TEST_F(ExactTest, RegressionTestExactMapperPerformance2) { - // Regression test for https://github.com/cda-tum/qmap/issues/256 - std::stringstream ss{"OPENQASM 2.0;\n" - "include \"qelib1.inc\";\n" - "qreg q[4];\n" - "cx q[0],q[1];\n" - "cx q[3],q[0];\n" - "cx q[1],q[3];\n" - "cx q[1],q[0];\n" - "cx q[3],q[0];\n" - "cx q[1],q[3];\n" - "cx q[0],q[1];\n" - "cx q[1],q[2];\n"}; - - Architecture arch; - const CouplingMap cm = {{1, 0}, {2, 0}, {2, 1}, {3, 2}, {3, 4}, {4, 2}}; - arch.loadCouplingMap(5, cm); - qc.import(ss, qc::Format::OpenQASM3); - - auto mapper = ExactMapper(qc, arch); - settings.swapReduction = SwapReduction::CouplingLimit; - mapper.map(settings); - EXPECT_EQ(mapper.getResults().output.swaps, 1); - EXPECT_EQ(mapper.getResults().output.directionReverse, 1); - - auto mapper2 = ExactMapper(qc, arch); - settings.swapReduction = SwapReduction::None; - mapper2.map(settings); - EXPECT_EQ(mapper2.getResults().output.swaps, 1); - EXPECT_EQ(mapper2.getResults().output.directionReverse, 1); -} +// +// 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. +// + +#include "Definitions.hpp" +#include "ir/QuantumComputation.hpp" +#include "ir/operations/Control.hpp" +#include "ir/operations/OpType.hpp" +#include "sc/Architecture.hpp" +#include "sc/configuration/AvailableArchitecture.hpp" +#include "sc/configuration/CommanderGrouping.hpp" +#include "sc/configuration/Configuration.hpp" +#include "sc/configuration/Encoding.hpp" +#include "sc/configuration/InitialLayout.hpp" +#include "sc/configuration/Layering.hpp" +#include "sc/configuration/Method.hpp" +#include "sc/configuration/SwapReduction.hpp" +#include "sc/exact/ExactMapper.hpp" +#include "sc/utils.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +class ExactTest : public testing::TestWithParam { +protected: + std::string testExampleDir = "../../../examples/"; + std::string testArchitectureDir = "../../../extern/architectures/"; + std::string testCalibrationDir = "../../../extern/calibration/"; + + qc::QuantumComputation qc; + Configuration settings{}; + Architecture ibmqYorktown; + Architecture ibmqLondon; + Architecture ibmQX4; + std::unique_ptr ibmqYorktownMapper; + std::unique_ptr ibmqLondonMapper; + std::unique_ptr ibmQX4Mapper; + + void SetUp() override { + using namespace qc::literals; + + if (::testing::UnitTest::GetInstance() + ->current_test_info() + ->value_param() != nullptr) { + qc.import(testExampleDir + GetParam() + ".qasm"); + } else { + qc.addQubitRegister(3U); + qc.cx(1_pc, 0); + qc.cx(2_pc, 1); + qc.cx(0_pc, 2); + } + ibmqYorktown.loadCouplingMap(AvailableArchitecture::IbmqYorktown); + ibmqLondon.loadCouplingMap(testArchitectureDir + "ibmq_london.arch"); + ibmqLondon.loadProperties(testCalibrationDir + "ibmq_london.csv"); + ibmQX4.loadCouplingMap(AvailableArchitecture::IbmQx4); + + ibmqYorktownMapper = std::make_unique(qc, ibmqYorktown); + ibmqLondonMapper = std::make_unique(qc, ibmqLondon); + ibmQX4Mapper = std::make_unique(qc, ibmQX4); + + settings.verbose = true; + settings.method = Method::Exact; + } +}; + +INSTANTIATE_TEST_SUITE_P( + Exact, ExactTest, + testing::Values("3_17_13", "ex-1_166", "ham3_102", "miller_11", "4gt11_84"), + [](const testing::TestParamInfo& inf) { + std::string name = inf.param; + std::replace(name.begin(), name.end(), '-', '_'); + return name; + }); + +TEST_P(ExactTest, IndividualGates) { + settings.layering = Layering::IndividualGates; + ibmqYorktownMapper->map(settings); + ibmqYorktownMapper->dumpResult(GetParam() + + "_exact_yorktown_individual.qasm"); + ibmqYorktownMapper->printResult(std::cout); + + ibmqLondonMapper->map(settings); + ibmqLondonMapper->dumpResult(GetParam() + "_exact_london_individual.qasm"); + ibmqLondonMapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} + +TEST_P(ExactTest, DisjointQubits) { + settings.layering = Layering::DisjointQubits; + ibmqYorktownMapper->map(settings); + ibmqYorktownMapper->dumpResult(GetParam() + "_exact_yorktown_disjoint.qasm"); + ibmqYorktownMapper->printResult(std::cout); + + ibmqLondonMapper->map(settings); + ibmqLondonMapper->dumpResult(GetParam() + "_exact_london_disjoint.qasm"); + ibmqLondonMapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} + +TEST_P(ExactTest, Disjoint2qBlocks) { + settings.layering = Layering::Disjoint2qBlocks; + ibmqYorktownMapper->map(settings); + ibmqYorktownMapper->dumpResult(GetParam() + + "_exact_yorktown_disjoint_2q.qasm"); + ibmqYorktownMapper->printResult(std::cout); + + ibmqLondonMapper->map(settings); + ibmqLondonMapper->dumpResult(GetParam() + "_exact_london_disjoint_2q.qasm"); + ibmqLondonMapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} + +TEST_P(ExactTest, OddGates) { + settings.layering = Layering::OddGates; + ibmqYorktownMapper->map(settings); + ibmqYorktownMapper->dumpResult(GetParam() + "_exact_yorktown_odd.qasm"); + ibmqYorktownMapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} + +TEST_P(ExactTest, QubitTriangle) { + settings.layering = Layering::QubitTriangle; + ibmqYorktownMapper->map(settings); + ibmqYorktownMapper->dumpResult(GetParam() + "_exact_yorktown_triangle.qasm"); + ibmqYorktownMapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} + +TEST_P(ExactTest, CommanderEncodingfixed3) { + settings.encoding = Encoding::Commander; + settings.commanderGrouping = CommanderGrouping::Fixed3; + ibmqYorktownMapper->map(settings); + ibmqYorktownMapper->dumpResult(GetParam() + + "_exact_yorktown_commander_fixed3.qasm"); + ibmqYorktownMapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} +TEST_P(ExactTest, CommanderEncodingfixed2) { + settings.encoding = Encoding::Commander; + settings.commanderGrouping = CommanderGrouping::Fixed2; + ibmqYorktownMapper->map(settings); + ibmqYorktownMapper->dumpResult(GetParam() + + "_exact_yorktown_commander_fixed2.qasm"); + ibmqYorktownMapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} +TEST_P(ExactTest, CommanderEncodinghalves) { + settings.encoding = Encoding::Commander; + settings.commanderGrouping = CommanderGrouping::Halves; + ibmqYorktownMapper->map(settings); + ibmqYorktownMapper->dumpResult(GetParam() + + "_exact_yorktown_commander_halves.qasm"); + ibmqYorktownMapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} +TEST_P(ExactTest, CommanderEncodinglogarithm) { + settings.encoding = Encoding::Commander; + settings.commanderGrouping = CommanderGrouping::Logarithm; + ibmqYorktownMapper->map(settings); + ibmqYorktownMapper->dumpResult(GetParam() + + "_exact_yorktown_commander_log.qasm"); + ibmqYorktownMapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} + +TEST_P(ExactTest, CommanderEncodingUnidirectionalfixed3) { + settings.encoding = Encoding::Commander; + settings.commanderGrouping = CommanderGrouping::Fixed3; + ibmQX4Mapper->map(settings); + ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_commander_fixed3.qasm"); + ibmQX4Mapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} +TEST_P(ExactTest, CommanderEncodingUnidirectionalfixed2) { + settings.encoding = Encoding::Commander; + settings.commanderGrouping = CommanderGrouping::Fixed2; + ibmQX4Mapper->map(settings); + ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_commander_fixed2.qasm"); + ibmQX4Mapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} +TEST_P(ExactTest, CommanderEncodingUnidirectionalhalves) { + settings.encoding = Encoding::Commander; + settings.commanderGrouping = CommanderGrouping::Halves; + ibmQX4Mapper->map(settings); + ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_commander_halves.qasm"); + ibmQX4Mapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} +TEST_P(ExactTest, CommanderEncodingUnidirectionallogarithm) { + settings.encoding = Encoding::Commander; + settings.commanderGrouping = CommanderGrouping::Logarithm; + ibmQX4Mapper->map(settings); + ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_commander_log.qasm"); + ibmQX4Mapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} + +TEST_P(ExactTest, BimanderEncodingfixed3) { + settings.encoding = Encoding::Bimander; + settings.commanderGrouping = CommanderGrouping::Fixed3; + ibmqYorktownMapper->map(settings); + ibmqYorktownMapper->dumpResult(GetParam() + "_exact_yorktown_bimander.qasm"); + ibmqYorktownMapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} +TEST_P(ExactTest, BimanderEncodingfixed2) { + settings.encoding = Encoding::Bimander; + settings.commanderGrouping = CommanderGrouping::Fixed2; + ibmqYorktownMapper->map(settings); + ibmqYorktownMapper->dumpResult(GetParam() + "_exact_yorktown_bimander.qasm"); + ibmqYorktownMapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} +TEST_P(ExactTest, BimanderEncodinghalves) { + settings.encoding = Encoding::Bimander; + settings.commanderGrouping = CommanderGrouping::Halves; + ibmqYorktownMapper->map(settings); + ibmqYorktownMapper->dumpResult(GetParam() + "_exact_yorktown_bimander.qasm"); + ibmqYorktownMapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} +TEST_P(ExactTest, BimanderEncodinglogaritm) { + settings.encoding = Encoding::Bimander; + settings.commanderGrouping = CommanderGrouping::Logarithm; + ibmqYorktownMapper->map(settings); + ibmqYorktownMapper->dumpResult(GetParam() + "_exact_yorktown_bimander.qasm"); + ibmqYorktownMapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} + +TEST_P(ExactTest, BimanderEncodingUnidirectionalfixed3) { + settings.encoding = Encoding::Bimander; + settings.commanderGrouping = CommanderGrouping::Fixed3; + ibmQX4Mapper->map(settings); + ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_bimander.qasm"); + ibmQX4Mapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} +TEST_P(ExactTest, BimanderEncodingUnidirectionalfixed2) { + settings.encoding = Encoding::Bimander; + settings.commanderGrouping = CommanderGrouping::Fixed2; + ibmQX4Mapper->map(settings); + ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_bimander.qasm"); + ibmQX4Mapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} +TEST_P(ExactTest, BimanderEncodingUnidirectionalhalves) { + settings.encoding = Encoding::Bimander; + settings.commanderGrouping = CommanderGrouping::Halves; + ibmQX4Mapper->map(settings); + ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_bimander.qasm"); + ibmQX4Mapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} +TEST_P(ExactTest, BimanderEncodingUnidirectionallogarithm) { + settings.encoding = Encoding::Bimander; + settings.commanderGrouping = CommanderGrouping::Logarithm; + ibmQX4Mapper->map(settings); + ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_bimander.qasm"); + ibmQX4Mapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} + +TEST_P(ExactTest, LimitsBidirectional) { + settings.enableSwapLimits = true; + settings.useSubsets = false; + settings.swapReduction = SwapReduction::CouplingLimit; + ibmqYorktownMapper->map(settings); + ibmqYorktownMapper->dumpResult(GetParam() + + "_exact_yorktown_swapreduct.qasm"); + ibmqYorktownMapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} +TEST_P(ExactTest, LimitsBidirectionalSubsetSwaps) { + settings.enableSwapLimits = true; + settings.useSubsets = true; + settings.swapReduction = SwapReduction::CouplingLimit; + ibmqYorktownMapper->map(settings); + ibmqYorktownMapper->dumpResult(GetParam() + + "_exact_yorktown_swapreduct.qasm"); + ibmqYorktownMapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} +TEST_P(ExactTest, LimitsBidirectionalCustomLimit) { + settings.enableSwapLimits = true; + settings.swapReduction = SwapReduction::Custom; + settings.swapLimit = 10; + ibmqYorktownMapper->map(settings); + ibmqYorktownMapper->dumpResult(GetParam() + + "_exact_yorktown_swapreduct.qasm"); + ibmqYorktownMapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} + +TEST_P(ExactTest, LimitsUnidirectional) { + settings.enableSwapLimits = true; + settings.useSubsets = false; + settings.swapReduction = SwapReduction::CouplingLimit; + ibmQX4Mapper->map(settings); + ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_swapreduct.qasm"); + ibmQX4Mapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} +TEST_P(ExactTest, LimitsUnidirectionalSubsetSwaps) { + settings.enableSwapLimits = true; + settings.useSubsets = true; + settings.swapReduction = SwapReduction::CouplingLimit; + ibmQX4Mapper->map(settings); + ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_swapreduct.qasm"); + ibmQX4Mapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} +TEST_P(ExactTest, LimitsUnidirectionalCustomLimit) { + settings.enableSwapLimits = true; + settings.swapReduction = SwapReduction::Custom; + settings.swapLimit = 10; + ibmQX4Mapper->map(settings); + ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_swapreduct.qasm"); + ibmQX4Mapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} +TEST_P(ExactTest, IncreasingCustomLimitUnidirectional) { + settings.enableSwapLimits = true; + settings.swapReduction = SwapReduction::Increasing; + settings.swapLimit = 3; + ibmQX4Mapper->map(settings); + ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_swapreduct_inccustom.qasm"); + ibmQX4Mapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} +TEST_P(ExactTest, IncreasingUnidirectional) { + settings.enableSwapLimits = true; + settings.swapReduction = SwapReduction::Increasing; + settings.swapLimit = 0; + ibmQX4Mapper->map(settings); + ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_swapreduct_inc.qasm"); + ibmQX4Mapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} + +TEST_P(ExactTest, NoSubsets) { + settings.useSubsets = false; + settings.enableSwapLimits = false; + ibmQX4Mapper->map(settings); + ibmQX4Mapper->dumpResult(GetParam() + "_exact_QX4_nosubsets.qasm"); + ibmQX4Mapper->printResult(std::cout); + SUCCEED() << "Mapping successful"; +} + +TEST_P(ExactTest, toStringMethods) { + EXPECT_EQ(toString(InitialLayout::Identity), "identity"); + EXPECT_EQ(toString(InitialLayout::Static), "static"); + EXPECT_EQ(toString(InitialLayout::Dynamic), "dynamic"); + + EXPECT_EQ(toString(Layering::IndividualGates), "individual_gates"); + EXPECT_EQ(toString(Layering::DisjointQubits), "disjoint_qubits"); + EXPECT_EQ(toString(Layering::Disjoint2qBlocks), "disjoint_2q_blocks"); + EXPECT_EQ(toString(Layering::OddGates), "odd_gates"); + EXPECT_EQ(toString(Layering::QubitTriangle), "qubit_triangle"); + + EXPECT_EQ(toString(Encoding::Naive), "naive"); + EXPECT_EQ(toString(Encoding::Commander), "commander"); + EXPECT_EQ(toString(Encoding::Bimander), "bimander"); + + EXPECT_EQ(toString(CommanderGrouping::Fixed2), "fixed2"); + EXPECT_EQ(toString(CommanderGrouping::Fixed3), "fixed3"); + EXPECT_EQ(toString(CommanderGrouping::Logarithm), "logarithm"); + EXPECT_EQ(toString(CommanderGrouping::Halves), "halves"); + + EXPECT_EQ(toString(SwapReduction::CouplingLimit), "coupling_limit"); + EXPECT_EQ(toString(SwapReduction::Custom), "custom"); + EXPECT_EQ(toString(SwapReduction::None), "none"); + EXPECT_EQ(toString(SwapReduction::Increasing), "increasing"); + + SUCCEED() << "ToStringMethods working"; +} + +TEST_F(ExactTest, CircuitWithOnlySingleQubitGates) { + qc.clear(); + qc.x(0); + qc.x(1); + ibmQX4Mapper = std::make_unique(qc, ibmQX4); + ibmQX4Mapper->map(settings); + ibmQX4Mapper->dumpResult(std::cout, qc::Format::OpenQASM3); + SUCCEED() << "Mapping successful"; +} + +TEST_F(ExactTest, MapToSubsetNotIncludingQ0) { + const CouplingMap cm{{0, 1}, {1, 0}, {1, 2}, {2, 1}, + {2, 3}, {3, 2}, {1, 3}, {3, 1}}; + Architecture arch(4U, cm); + + auto mapper = ExactMapper(qc, arch); + settings.useSubsets = false; + mapper.map(settings); + + std::ostringstream oss{}; + mapper.dumpResult(oss, qc::Format::OpenQASM3); + auto qcMapped = qc::QuantumComputation(); + std::istringstream iss{oss.str()}; + qcMapped.import(iss, qc::Format::OpenQASM3); + std::cout << qcMapped << '\n'; + EXPECT_EQ(qcMapped.initialLayout.size(), 4U); + EXPECT_EQ(qcMapped.initialLayout[0], 3); + EXPECT_EQ(qcMapped.outputPermutation.size(), 3U); + EXPECT_TRUE(qcMapped.garbage.at(3)); +} + +TEST_F(ExactTest, WCNF) { + settings.verbose = false; + settings.includeWCNF = true; + ibmqLondonMapper->map(settings); + ibmqLondonMapper->printResult(std::cout); + const auto& wcnf = ibmqLondonMapper->getResults().wcnf; + EXPECT_TRUE(!wcnf.empty()); +} + +TEST_F(ExactTest, WCNFNotAvailable) { + using namespace qc::literals; + + settings.verbose = false; + settings.encoding = Encoding::Naive; + settings.includeWCNF = true; + + auto circ = qc::QuantumComputation(5U); + circ.h(0); + circ.cx(0_pc, 1); + circ.cx(0_pc, 2); + circ.cx(0_pc, 3); + circ.cx(0_pc, 4); + + auto mapper = ExactMapper(circ, ibmqLondon); + + mapper.map(settings); + EXPECT_TRUE(mapper.getResults().wcnf.empty()); + + auto mapper2 = ExactMapper(circ, ibmqLondon); + settings.encoding = Encoding::Commander; + mapper2.map(settings); + EXPECT_FALSE(mapper2.getResults().wcnf.empty()); +} + +TEST_F(ExactTest, MapToSubgraph) { + const auto connectedSubset = std::set{0U, 1U, 2U}; + + settings.subgraph = connectedSubset; + ibmqLondonMapper->map(settings); + const auto& results = ibmqLondonMapper->getResults(); + EXPECT_FALSE(results.timeout); +} + +TEST_F(ExactTest, MapToSubgraphTooSmall) { + const auto tooSmallSubset = std::set{0U, 1U}; + + settings.subgraph = tooSmallSubset; + ibmqLondonMapper->map(settings); + const auto& results = ibmqLondonMapper->getResults(); + EXPECT_TRUE(results.timeout); +} + +TEST_F(ExactTest, MapToSubgraphNotConnected) { + const auto nonConnectedSubset = std::set{0U, 2U, 3U}; + + settings.subgraph = nonConnectedSubset; + ibmqLondonMapper->map(settings); + const auto& results = ibmqLondonMapper->getResults(); + EXPECT_TRUE(results.timeout); +} +TEST_F(ExactTest, CommanderEncodingRigettiArch) { + Architecture aspen; + aspen.loadCouplingMap(AvailableArchitecture::RigettiAspen); + Architecture agave; + agave.loadCouplingMap(AvailableArchitecture::RigettiAgave); + + auto aspenMapper = ExactMapper(qc, aspen); + auto agaveMapper = ExactMapper(qc, agave); + aspenMapper.map(settings); + agaveMapper.map(settings); + aspenMapper.printResult(std::cout); + agaveMapper.printResult(std::cout); + + SUCCEED() << "Mapping successful"; +} + +TEST_F(ExactTest, NoMeasurementsAdded) { + // configure to not include measurements after mapping + settings.addMeasurementsToMappedCircuit = false; + + // perform the mapping + ibmqLondonMapper->map(settings); + + // get the resulting circuit + auto qcMapped = qc::QuantumComputation(); + std::stringstream qasm{}; + ibmqLondonMapper->dumpResult(qasm, qc::Format::OpenQASM3); + qcMapped.import(qasm, qc::Format::OpenQASM3); + + // check no measurements were added + EXPECT_EQ(qcMapped.getNops(), 4U); + EXPECT_NE(qcMapped.back()->getType(), qc::Measure); +} + +TEST_F(ExactTest, Test4QCircuitThatUsesAll5Q) { + Architecture arch; + const CouplingMap cm = {{0, 1}, {1, 0}, {1, 2}, {2, 1}, {2, 3}, + {3, 2}, {3, 4}, {4, 3}, {4, 0}, {0, 4}}; + arch.loadCouplingMap(5, cm); + + std::stringstream ss{"OPENQASM 2.0;\ninclude \"qelib1.inc\";\n" + "qreg q[4];\n" + "cx q[0],q[1];\n" + "cx q[1],q[2];\n" + "cx q[2],q[3];\n" + "cx q[3],q[0];\n"}; + qc.import(ss, qc::Format::OpenQASM3); + + auto mapper = ExactMapper(qc, arch); + // explicitly do not use subsets, but the full architecture + settings.useSubsets = false; + + ASSERT_NO_THROW(mapper.map(settings);); + const auto& results = mapper.getResults(); + EXPECT_EQ(results.output.swaps, 1); +} + +TEST_F(ExactTest, RegressionTestDirectionReverseCost) { + // Regression test for https://github.com/cda-tum/qmap/issues/251 + using namespace qc::literals; + + Architecture arch; + const CouplingMap cm = {{1, 0}, {2, 0}, {2, 1}, {4, 2}, {3, 2}, {3, 4}}; + arch.loadCouplingMap(5, cm); + + Architecture::printCouplingMap(cm, std::cout); + + qc = qc::QuantumComputation(4); + qc.cx(1_pc, 0); + qc.cx(0_pc, 1); + qc.cx(2_pc, 1); + qc.cx(1_pc, 2); + qc.cx(3_pc, 2); + + auto mapper = ExactMapper(qc, arch); + mapper.map(settings); + EXPECT_EQ(mapper.getResults().output.swaps, 0); + EXPECT_EQ(mapper.getResults().output.directionReverse, 2); +} + +TEST_F(ExactTest, RegressionTestExactMapperPerformance) { + // Regression test for https://github.com/cda-tum/qmap/issues/256 + std::stringstream ss{"OPENQASM 2.0;\n" + "include \"qelib1.inc\";\n" + "qreg q[3];\n" + "cx q[0],q[2];\n" + "cx q[2],q[1];\n" + "cx q[2],q[1];\n" + "cx q[0],q[2];\n" + "cx q[1],q[0];\n" + "cx q[1],q[2];\n" + "cx q[0],q[2];\n" + "cx q[1],q[0];\n" + "cx q[2],q[1];\n" + "cx q[1],q[0];\n" + "cx q[2],q[1];\n" + "cx q[0],q[2];\n" + "cx q[0],q[1];\n" + "cx q[2],q[1];\n" + "cx q[0],q[2];\n" + "cx q[1],q[0];\n" + "cx q[1],q[2];\n"}; + + Architecture arch; + const CouplingMap cm = {{1, 0}, {2, 0}, {2, 1}, {3, 2}, {3, 4}, {4, 2}}; + arch.loadCouplingMap(5, cm); + qc.import(ss, qc::Format::OpenQASM3); + + auto mapper = ExactMapper(qc, arch); + settings.swapReduction = SwapReduction::CouplingLimit; + mapper.map(settings); + EXPECT_EQ(mapper.getResults().output.swaps, 1); + EXPECT_EQ(mapper.getResults().output.directionReverse, 4); + + auto mapper2 = ExactMapper(qc, arch); + settings.swapReduction = SwapReduction::None; + mapper2.map(settings); + EXPECT_EQ(mapper2.getResults().output.swaps, 1); + EXPECT_EQ(mapper2.getResults().output.directionReverse, 4); +} + +TEST_F(ExactTest, RegressionTestExactMapperPerformance2) { + // Regression test for https://github.com/cda-tum/qmap/issues/256 + std::stringstream ss{"OPENQASM 2.0;\n" + "include \"qelib1.inc\";\n" + "qreg q[4];\n" + "cx q[0],q[1];\n" + "cx q[3],q[0];\n" + "cx q[1],q[3];\n" + "cx q[1],q[0];\n" + "cx q[3],q[0];\n" + "cx q[1],q[3];\n" + "cx q[0],q[1];\n" + "cx q[1],q[2];\n"}; + + Architecture arch; + const CouplingMap cm = {{1, 0}, {2, 0}, {2, 1}, {3, 2}, {3, 4}, {4, 2}}; + arch.loadCouplingMap(5, cm); + qc.import(ss, qc::Format::OpenQASM3); + + auto mapper = ExactMapper(qc, arch); + settings.swapReduction = SwapReduction::CouplingLimit; + mapper.map(settings); + EXPECT_EQ(mapper.getResults().output.swaps, 1); + EXPECT_EQ(mapper.getResults().output.directionReverse, 1); + + auto mapper2 = ExactMapper(qc, arch); + settings.swapReduction = SwapReduction::None; + mapper2.map(settings); + EXPECT_EQ(mapper2.getResults().output.swaps, 1); + EXPECT_EQ(mapper2.getResults().output.directionReverse, 1); +} diff --git a/test/sc/heuristic/CMakeLists.txt b/test/sc/heuristic/CMakeLists.txt new file mode 100644 index 000000000..080568235 --- /dev/null +++ b/test/sc/heuristic/CMakeLists.txt @@ -0,0 +1,4 @@ +if(TARGET MQT::QMapSCHeuristic) + file(GLOB_RECURSE SC_HEURISTIC_TEST_SOURCES *.cpp) + package_add_test(mqt-qmap-sc-heuristic-test MQT::QMapSCHeuristic ${SC_HEURISTIC_TEST_SOURCES}) +endif() diff --git a/test/test_heuristic.cpp b/test/sc/heuristic/test_heuristic.cpp similarity index 98% rename from test/test_heuristic.cpp rename to test/sc/heuristic/test_heuristic.cpp index c6565cc4b..7127fac26 100644 --- a/test/test_heuristic.cpp +++ b/test/sc/heuristic/test_heuristic.cpp @@ -3,21 +3,21 @@ // See README.md or go to https://github.com/cda-tum/qmap for more information. // -#include "Architecture.hpp" -#include "DataLogger.hpp" #include "Definitions.hpp" -#include "configuration/AvailableArchitecture.hpp" -#include "configuration/EarlyTermination.hpp" -#include "configuration/Heuristic.hpp" -#include "configuration/InitialLayout.hpp" -#include "configuration/Layering.hpp" -#include "configuration/LookaheadHeuristic.hpp" -#include "configuration/Method.hpp" -#include "heuristic/HeuristicMapper.hpp" #include "ir/operations/CompoundOperation.hpp" #include "ir/operations/Control.hpp" #include "ir/operations/OpType.hpp" -#include "utils.hpp" +#include "sc/Architecture.hpp" +#include "sc/DataLogger.hpp" +#include "sc/configuration/AvailableArchitecture.hpp" +#include "sc/configuration/EarlyTermination.hpp" +#include "sc/configuration/Heuristic.hpp" +#include "sc/configuration/InitialLayout.hpp" +#include "sc/configuration/Layering.hpp" +#include "sc/configuration/LookaheadHeuristic.hpp" +#include "sc/configuration/Method.hpp" +#include "sc/heuristic/HeuristicMapper.hpp" +#include "sc/utils.hpp" #include #include @@ -435,9 +435,9 @@ TEST_F(InternalsTest, NodeLookaheadCalculation) { class TestHeuristics : public testing::TestWithParam> { protected: - std::string testExampleDir = "../examples/"; - std::string testArchitectureDir = "../extern/architectures/"; - std::string testCalibrationDir = "../extern/calibration/"; + std::string testExampleDir = "../../../examples/"; + std::string testArchitectureDir = "../../../extern/architectures/"; + std::string testCalibrationDir = "../../../extern/calibration/"; qc::QuantumComputation qc; std::string circuitName; @@ -1804,9 +1804,9 @@ TEST_F(LayeringTest, IndividualGates) { class HeuristicTest5Q : public testing::TestWithParam { protected: - std::string testExampleDir = "../examples/"; - std::string testArchitectureDir = "../extern/architectures/"; - std::string testCalibrationDir = "../extern/calibration/"; + std::string testExampleDir = "../../../examples/"; + std::string testArchitectureDir = "../../../extern/architectures/"; + std::string testCalibrationDir = "../../../extern/calibration/"; qc::QuantumComputation qc; Architecture ibmqYorktown; @@ -1878,8 +1878,8 @@ TEST_P(HeuristicTest5Q, Dynamic) { class HeuristicTest16Q : public testing::TestWithParam { protected: - std::string testExampleDir = "../examples/"; - std::string testArchitectureDir = "../extern/architectures/"; + std::string testExampleDir = "../../../examples/"; + std::string testArchitectureDir = "../../../extern/architectures/"; qc::QuantumComputation qc; Architecture ibmQX5; @@ -1929,8 +1929,8 @@ TEST_P(HeuristicTest16Q, Disjoint2qBlocks) { class HeuristicTest20Q : public testing::TestWithParam { protected: - std::string testExampleDir = "../examples/"; - std::string testArchitectureDir = "../extern/architectures/"; + std::string testExampleDir = "../../../examples/"; + std::string testArchitectureDir = "../../../extern/architectures/"; qc::QuantumComputation qc; Architecture arch; @@ -1966,8 +1966,8 @@ TEST_P(HeuristicTest20Q, Dynamic) { class HeuristicTest20QTeleport : public testing::TestWithParam> { protected: - std::string testExampleDir = "../examples/"; - std::string testArchitectureDir = "../extern/architectures/"; + std::string testExampleDir = "../../../examples/"; + std::string testArchitectureDir = "../../../extern/architectures/"; qc::QuantumComputation qc; Architecture arch; @@ -2009,9 +2009,9 @@ TEST_P(HeuristicTest20QTeleport, Teleportation) { class HeuristicTestFidelity : public testing::TestWithParam { protected: - std::string testExampleDir = "../examples/"; - std::string testArchitectureDir = "../extern/architectures/"; - std::string testCalibrationDir = "../extern/calibration/"; + std::string testExampleDir = "../../../examples/"; + std::string testArchitectureDir = "../../../extern/architectures/"; + std::string testCalibrationDir = "../../../extern/calibration/"; qc::QuantumComputation qc; Architecture arch; diff --git a/test/test_architecture.cpp b/test/sc/test_architecture.cpp similarity index 99% rename from test/test_architecture.cpp rename to test/sc/test_architecture.cpp index 82032670b..bb7f8fcf5 100644 --- a/test/test_architecture.cpp +++ b/test/sc/test_architecture.cpp @@ -3,9 +3,9 @@ // See README.md or go to https://github.com/cda-tum/qmap for more information. // -#include "Architecture.hpp" #include "ir/operations/OpType.hpp" -#include "utils.hpp" +#include "sc/Architecture.hpp" +#include "sc/utils.hpp" #include #include @@ -46,8 +46,8 @@ ::testing::AssertionResult matrixNear(const Matrix& a, const Matrix& b, class TestArchitecture : public testing::TestWithParam { protected: - std::string testArchitectureDir = "../extern/architectures/"; - std::string testCalibrationDir = "../extern/calibration/"; + std::string testArchitectureDir = "../../extern/architectures/"; + std::string testCalibrationDir = "../../extern/calibration/"; }; INSTANTIATE_TEST_SUITE_P(Architecture, TestArchitecture, diff --git a/test/test_general.cpp b/test/sc/test_general.cpp similarity index 99% rename from test/test_general.cpp rename to test/sc/test_general.cpp index 33bf86c26..7055d2d8a 100644 --- a/test/test_general.cpp +++ b/test/sc/test_general.cpp @@ -3,8 +3,8 @@ // See README.md or go to https://github.com/cda-tum/qmap for more information. // -#include "Architecture.hpp" -#include "utils.hpp" +#include "sc/Architecture.hpp" +#include "sc/utils.hpp" #include #include From b86aeb39500ae9a46eb0fe1b43109a8a8cd4e9d8 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Fri, 6 Sep 2024 21:55:08 +0200 Subject: [PATCH 3/6] =?UTF-8?q?=F0=9F=9A=B8=20nox=20session=20improvements?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- noxfile.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/noxfile.py b/noxfile.py index 91549cb13..f80b682b2 100644 --- a/noxfile.py +++ b/noxfile.py @@ -16,7 +16,7 @@ nox.needs_version = ">=2024.3.2" nox.options.default_venv_backend = "uv|virtualenv" -nox.options.sessions = ["lint", "tests"] +nox.options.sessions = ["lint", "tests", "minimums"] PYTHON_ALL_VERSIONS = ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] @@ -39,8 +39,10 @@ @nox.session(reuse_venv=True) def lint(session: nox.Session) -> None: """Run the linter.""" - session.install("pre-commit") - session.run("pre-commit", "run", "--all-files", *session.posargs) + if shutil.which("pre-commit") is None: + session.install("pre-commit") + + session.run("pre-commit", "run", "--all-files", *session.posargs, external=True) def _run_tests( @@ -51,8 +53,7 @@ def _run_tests( extras: Sequence[str] = (), ) -> None: posargs = list(session.posargs) - env = {"PIP_DISABLE_PIP_VERSION_CHECK": "1"} - + env = {} if os.environ.get("CI", None) and sys.platform == "win32": env["SKBUILD_CMAKE_ARGS"] = "-T ClangCL" From d7440c626e9efd1ca504a8234f8d8ee6868d3065 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Fri, 6 Sep 2024 22:00:12 +0200 Subject: [PATCH 4/6] =?UTF-8?q?=F0=9F=94=A7=20updated=20mypy=20config?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- .pre-commit-config.yaml | 3 ++- pyproject.toml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 948ea6469..aaca48a98 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -76,10 +76,11 @@ repos: rev: v1.11.2 hooks: - id: mypy - files: ^(src/mqt|test/python) + files: ^(src/mqt|test/python|noxfile.py) args: [] additional_dependencies: - importlib_resources + - nox - numpy - pytest - rustworkx diff --git a/pyproject.toml b/pyproject.toml index 05131428d..091455b9c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -174,7 +174,7 @@ report.exclude_also = [ ] [tool.mypy] -files = ["src/mqt", "test/python"] +files = ["src/mqt", "test/python", "noxfile.py"] mypy_path = ["$MYPY_CONFIG_FILE_DIR/src"] python_version = "3.8" warn_unused_configs = true From 788cac453a52945918fbbb22f927ec6a03db6c12 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Fri, 6 Sep 2024 22:08:25 +0200 Subject: [PATCH 5/6] =?UTF-8?q?=E2=AC=86=EF=B8=8F=F0=9F=AA=9D=20update=20p?= =?UTF-8?q?re-commit=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index aaca48a98..ba810c133 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -56,7 +56,7 @@ repos: # Python linting using ruff - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.6.3 + rev: v0.6.4 hooks: - id: ruff args: ["--fix", "--show-fixes"] @@ -88,7 +88,7 @@ repos: # Check for spelling - repo: https://github.com/crate-ci/typos - rev: v1.24.1 + rev: v1.24.5 hooks: - id: typos From a94f48f6a98f5bd0499c3e0d9f0007b794a926e8 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Fri, 6 Sep 2024 22:40:31 +0200 Subject: [PATCH 6/6] =?UTF-8?q?=F0=9F=9A=A8=20fix=20clang-tidy=20warnings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- src/cliffordsynthesis/Tableau.cpp | 1 + src/hybridmap/NeutralAtomArchitecture.cpp | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/cliffordsynthesis/Tableau.cpp b/src/cliffordsynthesis/Tableau.cpp index 074da87f3..0f4b83537 100644 --- a/src/cliffordsynthesis/Tableau.cpp +++ b/src/cliffordsynthesis/Tableau.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include diff --git a/src/hybridmap/NeutralAtomArchitecture.cpp b/src/hybridmap/NeutralAtomArchitecture.cpp index 43bb885f3..3d2346d9d 100644 --- a/src/hybridmap/NeutralAtomArchitecture.cpp +++ b/src/hybridmap/NeutralAtomArchitecture.cpp @@ -27,7 +27,7 @@ namespace na { void NeutralAtomArchitecture::loadJson(const std::string& filename) { - nlohmann::json jsonData; + nlohmann::basic_json<> jsonData; std::ifstream architectureFile(filename); if (!architectureFile.is_open()) { @@ -38,7 +38,7 @@ void NeutralAtomArchitecture::loadJson(const std::string& filename) { architectureFile.close(); // Load properties - nlohmann::json jsonDataProperties = jsonData["properties"]; + nlohmann::basic_json<> jsonDataProperties = jsonData["properties"]; this->properties = Properties( jsonDataProperties["nRows"], jsonDataProperties["nColumns"], jsonDataProperties["nAods"], jsonDataProperties["nAodCoordinates"], @@ -48,7 +48,7 @@ void NeutralAtomArchitecture::loadJson(const std::string& filename) { jsonDataProperties["minimalAodDistance"]); // Load parameters - const nlohmann::json jsonDataParameters = jsonData["parameters"]; + const nlohmann::basic_json<> jsonDataParameters = jsonData["parameters"]; this->parameters = Parameters(); this->parameters.nQubits = jsonDataParameters["nQubits"];