Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

option(BUILD_MQT_CORE_TESTS "Build tests for the MQT Core project" ${PROJECT_IS_TOP_LEVEL})

include(AddMQTPythonBinding)
include(StandardProjectSettings)
include(PreventInSourceBuilds)
include(PackageAddTest)
Expand Down Expand Up @@ -158,16 +157,12 @@ if(BUILD_MQT_CORE_DOCUMENTATION)
VERBATIM)
endif()
if(BUILD_MQT_CORE_BINDINGS)
foreach(binding dd qdmi)
add_dependencies(${MQT_CORE_TARGET_NAME}-${binding}-bindings mqt-core-docs)
endforeach()
add_dependencies(${MQT_CORE_TARGET_NAME}-bindings mqt-core-docs)
endif()
endif()

if(BUILD_MQT_CORE_BINDINGS)
set(MQT_CORE_WHEEL_TARGETS
mqt-core-bench-bindings mqt-core-dd-bindings mqt-core-qdmi-bindings mqt-cc mqt-core-bench
mqt-core-mlir-bindings)
set(MQT_CORE_WHEEL_TARGETS mqt-core-bindings mqt-cc mqt-core-bench)
if(BUILD_MQT_CORE_QDMI_DDSIM_DEVICE)
list(APPEND MQT_CORE_WHEEL_TARGETS mqt-core-qdmi-ddsim-device)
endif()
Expand Down
22 changes: 22 additions & 0 deletions bindings/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,28 @@
#
# Licensed under the MIT License

set(TARGET_NAME ${MQT_CORE_TARGET_NAME}-bindings)
nanobind_add_module(
${TARGET_NAME}
FREE_THREADED
NOMINSIZE
NB_SUPPRESS_WARNINGS
BACKEND_MODULE
nanobind_backend
register_core.cpp)
set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME _core)
target_compile_features(${TARGET_NAME} PRIVATE cxx_std_20)
target_link_libraries(${TARGET_NAME} PRIVATE MQT::ProjectOptions MQT::ProjectWarnings)

# Hide archive symbols without hiding C++ exception type information on Mach-O.
if(UNIX AND NOT APPLE)
target_link_options(${TARGET_NAME} PRIVATE "LINKER:--exclude-libs,ALL")
endif()

if(MQT_CORE_INSTALL)
install(TARGETS ${TARGET_NAME} DESTINATION . COMPONENT ${MQT_CORE_TARGET_NAME}_Python)
endif()

add_subdirectory(bench)
add_subdirectory(dd)
add_subdirectory(qdmi)
Expand Down
58 changes: 24 additions & 34 deletions bindings/bench/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,30 @@
#
# Licensed under the MIT License

if(NOT TARGET ${MQT_CORE_TARGET_NAME}-bench-bindings)
set(BENCH_SOURCES
register_bench.cpp
register_bv.cpp
register_fan_out.cpp
register_ghz.cpp
register_grover.cpp
register_grover_weak_measurement.cpp
register_magic_state_distillation.cpp
register_modular_multiplier.cpp
register_multiplexer.cpp
register_qaoa.cpp
register_qft.cpp
register_qft_adder.cpp
register_qpe.cpp
register_repeat_until_success.cpp
register_shor.cpp
register_teleportation.cpp
register_w_state.cpp)
set(BENCH_SOURCES
register_bench.cpp
register_bv.cpp
register_fan_out.cpp
register_ghz.cpp
register_grover.cpp
register_grover_weak_measurement.cpp
register_magic_state_distillation.cpp
register_modular_multiplier.cpp
register_multiplexer.cpp
register_qaoa.cpp
register_qft.cpp
register_qft_adder.cpp
register_qpe.cpp
register_repeat_until_success.cpp
register_shor.cpp
register_teleportation.cpp
register_w_state.cpp)

add_mqt_python_binding(
CORE
${MQT_CORE_TARGET_NAME}-bench-bindings
${BENCH_SOURCES}
MODULE_NAME
bench
INSTALL_DIR
.
LINK_LIBS
MQT::CoreBench)
target_sources(${MQT_CORE_TARGET_NAME}-bindings PRIVATE ${BENCH_SOURCES})
target_link_libraries(${MQT_CORE_TARGET_NAME}-bindings PRIVATE MQT::CoreBench)

# install the Python stub files in editable mode for better IDE support
if(MQT_CORE_INSTALL AND SKBUILD_STATE STREQUAL "editable")
file(GLOB_RECURSE BENCH_PYI_FILES ${PROJECT_SOURCE_DIR}/python/mqt/core/bench/*.pyi)
install(FILES ${BENCH_PYI_FILES} DESTINATION ./bench COMPONENT ${MQT_CORE_TARGET_NAME}_Python)
endif()
# install the Python stub files in editable mode for better IDE support
if(MQT_CORE_INSTALL AND SKBUILD_STATE STREQUAL "editable")
file(GLOB_RECURSE BENCH_PYI_FILES ${PROJECT_SOURCE_DIR}/python/mqt/core/bench/*.pyi)
install(FILES ${BENCH_PYI_FILES} DESTINATION ./bench COMPONENT ${MQT_CORE_TARGET_NAME}_Python)
endif()
5 changes: 2 additions & 3 deletions bindings/bench/register_bench.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,8 @@ void registerShor(nb::module_& m);
void registerTeleportation(const nb::module_& m);
void registerWState(const nb::module_& m);

// The nanobind module macro requires its module handle by value.
// NOLINTNEXTLINE(performance-unnecessary-value-param)
NB_MODULE(MQT_CORE_MODULE_NAME, m) {
// NOLINTNEXTLINE(misc-use-internal-linkage): module entry point.
void registerBench(nb::module_& m) {
m.doc() = "Typed benchmark instances and references.";

nb::class_<bench::Output>(m, "Output",
Expand Down
28 changes: 9 additions & 19 deletions bindings/dd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,15 @@
#
# Licensed under the MIT License

if(NOT TARGET ${MQT_CORE_TARGET_NAME}-dd-bindings)
file(GLOB_RECURSE DD_SOURCES **.cpp)
file(GLOB_RECURSE DD_SOURCES **.cpp)

add_mqt_python_binding(
CORE
${MQT_CORE_TARGET_NAME}-dd-bindings
${DD_SOURCES}
MODULE_NAME
dd
INSTALL_DIR
.
LINK_LIBS
MQT::CoreDDPython)
target_sources(${MQT_CORE_TARGET_NAME}-bindings PRIVATE ${DD_SOURCES})
target_link_libraries(${MQT_CORE_TARGET_NAME}-bindings PRIVATE MQT::CoreDD)

# install the Python stub file in editable mode for better IDE support
if(MQT_CORE_INSTALL AND SKBUILD_STATE STREQUAL "editable")
install(
FILES ${PROJECT_SOURCE_DIR}/python/mqt/core/dd.pyi
DESTINATION .
COMPONENT ${MQT_CORE_TARGET_NAME}_Python)
endif()
# install the Python stub file in editable mode for better IDE support
if(MQT_CORE_INSTALL AND SKBUILD_STATE STREQUAL "editable")
install(
FILES ${PROJECT_SOURCE_DIR}/python/mqt/core/dd.pyi
DESTINATION .
COMPONENT ${MQT_CORE_TARGET_NAME}_Python)
endif()
4 changes: 2 additions & 2 deletions bindings/dd/register_dd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ void registerControl(const nb::module_& m) {
}
} // namespace

// NOLINTNEXTLINE(performance-unnecessary-value-param)
NB_MODULE(MQT_CORE_MODULE_NAME, m) {
// NOLINTNEXTLINE(misc-use-internal-linkage): module entry point.
void registerDD(const nb::module_& m) {
m.doc() = "MQT Core decision diagram module.";

// Controls for raw matrix DD construction.
Expand Down
138 changes: 66 additions & 72 deletions bindings/mlir/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,90 +6,84 @@
#
# Licensed under the MIT License

set(TARGET_NAME "${MQT_CORE_TARGET_NAME}-mlir-bindings")
set(TARGET_NAME "${MQT_CORE_TARGET_NAME}-bindings")

if(NOT TARGET ${TARGET_NAME})
file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS *.cpp)
file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS *.cpp)

# Qiskit's extension C API tables are translation-unit local. Each supported minor therefore gets
# one source file with a private header snapshot.
file(
STRINGS Target/Qiskit/SupportedVersions.inc qiskit_version_registrations
REGEX "^MQT_QISKIT_VERSION\\(")
foreach(registration IN LISTS qiskit_version_registrations)
string(REGEX MATCH
"^MQT_QISKIT_VERSION\\(([0-9]+), *([0-9]+), *(2\\.[0-9]+\\.[0-9]+), *\"[^\"]+\"\\)$"
registration_match "${registration}")
if(NOT registration_match)
message(FATAL_ERROR "Invalid Qiskit version registration: ${registration}")
endif()
set(version_minor "${CMAKE_MATCH_1}")
set(version_release "${CMAKE_MATCH_3}")
set(translation_source "${CMAKE_CURRENT_SOURCE_DIR}/Target/Qiskit/Qiskit2_${version_minor}.cpp")
if(NOT EXISTS "${translation_source}")
message(
FATAL_ERROR "Missing Qiskit ${version_release} translation source: ${translation_source}")
endif()
set(version_include "${PROJECT_SOURCE_DIR}/vendor/qiskit-c-api/${version_release}/include")
if(NOT IS_DIRECTORY "${version_include}")
message(FATAL_ERROR "Missing Qiskit ${version_release} C API headers: ${version_include}")
endif()
set_source_files_properties(
${translation_source}
PROPERTIES
COMPILE_DEFINITIONS QISKIT_PYTHON_EXTENSION INCLUDE_DIRECTORIES "${version_include}")
endforeach()
# Qiskit's extension C API tables are translation-unit local. Each supported minor therefore gets
# one source file with a private header snapshot.
file(
STRINGS Target/Qiskit/SupportedVersions.inc qiskit_version_registrations
REGEX "^MQT_QISKIT_VERSION\\(")
foreach(registration IN LISTS qiskit_version_registrations)
string(REGEX MATCH
"^MQT_QISKIT_VERSION\\(([0-9]+), *([0-9]+), *(2\\.[0-9]+\\.[0-9]+), *\"[^\"]+\"\\)$"
registration_match "${registration}")
if(NOT registration_match)
message(FATAL_ERROR "Invalid Qiskit version registration: ${registration}")
endif()
set(version_minor "${CMAKE_MATCH_1}")
set(version_release "${CMAKE_MATCH_3}")
set(translation_source "${CMAKE_CURRENT_SOURCE_DIR}/Target/Qiskit/Qiskit2_${version_minor}.cpp")
if(NOT EXISTS "${translation_source}")
message(
FATAL_ERROR "Missing Qiskit ${version_release} translation source: ${translation_source}")
endif()
set(version_include "${PROJECT_SOURCE_DIR}/vendor/qiskit-c-api/${version_release}/include")
if(NOT IS_DIRECTORY "${version_include}")
message(FATAL_ERROR "Missing Qiskit ${version_release} C API headers: ${version_include}")
endif()
set_source_files_properties(
${translation_source}
TARGET_DIRECTORY ${TARGET_NAME}
PROPERTIES COMPILE_DEFINITIONS QISKIT_PYTHON_EXTENSION INCLUDE_DIRECTORIES "${version_include}")
endforeach()

set(MQT_QISKIT_CAPI_CANDIDATE_INCLUDE ""
CACHE PATH "CI-only include directory for an exact non-shipping Qiskit version")
set(MQT_QISKIT_CAPI_CANDIDATE_VERSION "" CACHE STRING "CI-only exact Qiskit development version")
if(MQT_QISKIT_CAPI_CANDIDATE_INCLUDE OR MQT_QISKIT_CAPI_CANDIDATE_VERSION)
if(NOT IS_DIRECTORY "${MQT_QISKIT_CAPI_CANDIDATE_INCLUDE}")
message(FATAL_ERROR "MQT_QISKIT_CAPI_CANDIDATE_INCLUDE must be a directory")
endif()
if(NOT MQT_QISKIT_CAPI_CANDIDATE_VERSION MATCHES "^2\\.[0-9]+\\.[0-9]+[^;\"]*$")
message(FATAL_ERROR "MQT_QISKIT_CAPI_CANDIDATE_VERSION must be one exact Qiskit 2 version")
endif()
set(QISKIT_FACTORY createCandidateTranslation)
set(candidate_source "${CMAKE_CURRENT_BINARY_DIR}/QiskitCandidate.cpp")
configure_file(Target/Qiskit/QiskitMinor.cpp.in ${candidate_source} @ONLY)
list(APPEND SOURCES ${candidate_source})
set_source_files_properties(
${candidate_source}
PROPERTIES
COMPILE_DEFINITIONS QISKIT_PYTHON_EXTENSION INCLUDE_DIRECTORIES
"${MQT_QISKIT_CAPI_CANDIDATE_INCLUDE};${CMAKE_CURRENT_SOURCE_DIR}/Target/Qiskit")
set(MQT_QISKIT_CAPI_CANDIDATE_INCLUDE ""
CACHE PATH "CI-only include directory for an exact non-shipping Qiskit version")
set(MQT_QISKIT_CAPI_CANDIDATE_VERSION "" CACHE STRING "CI-only exact Qiskit development version")
if(MQT_QISKIT_CAPI_CANDIDATE_INCLUDE OR MQT_QISKIT_CAPI_CANDIDATE_VERSION)
if(NOT IS_DIRECTORY "${MQT_QISKIT_CAPI_CANDIDATE_INCLUDE}")
message(FATAL_ERROR "MQT_QISKIT_CAPI_CANDIDATE_INCLUDE must be a directory")
endif()
if(NOT MQT_QISKIT_CAPI_CANDIDATE_VERSION MATCHES "^2\\.[0-9]+\\.[0-9]+[^;\"]*$")
message(FATAL_ERROR "MQT_QISKIT_CAPI_CANDIDATE_VERSION must be one exact Qiskit 2 version")
endif()
set(QISKIT_FACTORY createCandidateTranslation)
set(candidate_source "${CMAKE_CURRENT_BINARY_DIR}/QiskitCandidate.cpp")
configure_file(Target/Qiskit/QiskitMinor.cpp.in ${candidate_source} @ONLY)
list(APPEND SOURCES ${candidate_source})
set_source_files_properties(
${candidate_source}
TARGET_DIRECTORY ${TARGET_NAME}
PROPERTIES
COMPILE_DEFINITIONS QISKIT_PYTHON_EXTENSION INCLUDE_DIRECTORIES
"${MQT_QISKIT_CAPI_CANDIDATE_INCLUDE};${CMAKE_CURRENT_SOURCE_DIR}/Target/Qiskit")
endif()

add_mqt_python_binding(
CORE
${TARGET_NAME}
${SOURCES}
MODULE_NAME
mlir
INSTALL_DIR
.
LINK_LIBS
target_sources(${TARGET_NAME} PRIVATE ${SOURCES})
target_link_libraries(
${TARGET_NAME}
PRIVATE
MQT::CoreBenchGenerate
MQTCompilerQDMIAdapter
MQTCompilerPipeline
MLIRAnalysis
MLIRMQTDialect
MLIRMQTUtils
MLIRQCTranslationSupport
MLIRQCODDFunctionalityPython)
MLIRQCODDFunctionality)

if(MQT_QISKIT_CAPI_CANDIDATE_VERSION)
target_compile_definitions(
${TARGET_NAME}
PRIVATE MQT_QISKIT_CAPI_CANDIDATE_VERSION="${MQT_QISKIT_CAPI_CANDIDATE_VERSION}")
endif()
if(MQT_QISKIT_CAPI_CANDIDATE_VERSION)
target_compile_definitions(
${TARGET_NAME}
PRIVATE MQT_QISKIT_CAPI_CANDIDATE_VERSION="${MQT_QISKIT_CAPI_CANDIDATE_VERSION}")
endif()

# install the Python stub file in editable mode for better IDE support
if(MQT_CORE_INSTALL AND SKBUILD_STATE STREQUAL "editable")
install(
FILES ${PROJECT_SOURCE_DIR}/python/mqt/core/mlir.pyi
DESTINATION .
COMPONENT ${MQT_CORE_TARGET_NAME}_Python)
endif()
# install the Python stub file in editable mode for better IDE support
if(MQT_CORE_INSTALL AND SKBUILD_STATE STREQUAL "editable")
install(
FILES ${PROJECT_SOURCE_DIR}/python/mqt/core/mlir.pyi
DESTINATION .
COMPONENT ${MQT_CORE_TARGET_NAME}_Python)
endif()
30 changes: 2 additions & 28 deletions bindings/mlir/register_mlir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <exception>
#include <filesystem>
#include <limits>
#include <map>
Expand All @@ -95,26 +94,6 @@ namespace mqt {
namespace nb = nanobind;
using namespace nb::literals;

#ifdef __APPLE__
/// Translate standard exceptions that nanobind's split-mode backend can miss
/// on Darwin.
static void translateRuntimeError(const std::exception_ptr& error,
void* /*unused*/) {
try {
std::rethrow_exception(error);
} catch (const std::range_error& exception) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg): nanobind's error API.
nb::chain_error(nb::handle(PyExc_ValueError), "%s", exception.what());
} catch (const std::overflow_error& exception) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg): nanobind's error API.
nb::chain_error(nb::handle(PyExc_OverflowError), "%s", exception.what());
} catch (const std::runtime_error& exception) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg): nanobind's error API.
nb::chain_error(nb::handle(PyExc_RuntimeError), "%s", exception.what());
}
}
#endif

using DenseVector = nb::ndarray<nb::numpy, std::complex<dd::fp>, nb::ndim<1>,
nb::c_contig, nb::device::cpu>;
using DenseMatrix = nb::ndarray<nb::numpy, std::complex<dd::fp>, nb::ndim<2>,
Expand Down Expand Up @@ -1031,15 +1010,12 @@ generateBenchmark(const Benchmark& benchmark) {
return std::move(*generated);
}

NB_MODULE(MQT_CORE_MODULE_NAME, m) {
#ifdef __APPLE__
nb::register_exception_translator(&translateRuntimeError);
#endif
// NOLINTNEXTLINE(misc-use-internal-linkage): module entry point.
void registerMLIR(nb::module_& m) {

m.doc() = "MQT Core MLIR compiler bindings.";

nb::module_::import_("typing");
nb::module_::import_("mqt.core.qdmi");
const auto inputTypes = std::make_shared<PythonInputTypes>();
[[maybe_unused]] const auto initialQiskitType = inputTypes->quantumCircuit();

Expand Down Expand Up @@ -2292,8 +2268,6 @@ The source is consumed even on failure. Set ``copy=True`` to preserve it.
path: Destination file.
copy: Preserve the source program by exporting a copy.)pb");

nb::module_::import_("mqt.core.dd");

qcoProgram.def(
"build_functionality", &buildQCOFunctionality, "dd_package"_a,
// Keep the DD package alive while the returned matrix DD is alive.
Expand Down
Loading
Loading