Skip to content

Commit b00f293

Browse files
committed
Add project sources
1 parent ad52c11 commit b00f293

53 files changed

Lines changed: 17395 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# .gitignore
2+
3+
# Ignore compiled files
4+
*.o
5+
*.so
6+
*.dylib
7+
8+
# Ignore executables
9+
*.exe
10+
*.out
11+
12+
# Ignore build directories
13+
/build/
14+
/debug/
15+
/release/
16+
17+
# Ignore temporary files created by macOS
18+
.DS_Store
19+
20+
# Ignore Python temporary files
21+
*.pyc
22+
*.pyo
23+
*.pyd
24+
__pycache__/
25+
26+
# Ignore Jupyter Notebook checkpoints
27+
.ipynb_checkpoints
28+
29+
# Ignore files related to Python virtual environments
30+
/venv/
31+
/.venv/
32+
/env/
33+
/.env/
34+
/bin/
35+
/lib/
36+
/lib64/
37+
/share/
38+
/pyvenv.cfg
39+
40+
# Ignore Visual Studio Code settings
41+
.vscode/
42+
43+
# Ignore CMake generated files
44+
CMakeFiles/
45+
CMakeCache.txt
46+
*.cmake
47+
# Makefile
48+
49+
# Ignore other IDE and editor files
50+
*.sln
51+
*.suo
52+
*.user
53+
*.userosscache
54+
*.sdf
55+
*.opensdf
56+
*.opendb
57+
58+
# Ignore CLion files
59+
.idea/
60+
*.iml
61+
62+
# Ignore large circuit files and QSVT circuits
63+
*_transpiled.qasm
64+
circuits/qsvt_circuits/
65+
taco_bench/vqe_n24_transpiled.qasm
66+
67+
# Ignore other large files (>10MB)
68+
*.qasm.large
69+
70+
.claude/
71+
72+
# Python build artifacts
73+
dist/
74+
skbuild/
75+
_skbuild/
76+
*.egg-info/
77+
*.egg
78+
79+
# Test/coverage artifacts
80+
.pytest_cache/
81+
.coverage
82+
coverage.xml
83+
htmlcov/
84+
85+
# Local install/test prefix
86+
/_inst/
87+
88+
# CLion CMake out-of-source builds
89+
cmake-build-*/

CMakeLists.txt

Lines changed: 301 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,301 @@
1+
cmake_minimum_required(VERSION 3.16)
2+
project(NWQEC VERSION 1.0 LANGUAGES CXX)
3+
4+
# =============================================================================
5+
# Project Configuration
6+
# =============================================================================
7+
8+
# Enable C++17 features
9+
set(CMAKE_CXX_STANDARD 17)
10+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
11+
set(CMAKE_CXX_EXTENSIONS OFF)
12+
13+
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
14+
15+
# Display compiler information
16+
message(STATUS "Using C++ compiler: ${CMAKE_CXX_COMPILER}")
17+
18+
# Options
19+
option(NWQEC_ENABLE_LTO "Enable IPO/LTO in Release" ON)
20+
option(NWQEC_ENABLE_NATIVE "Enable -march=native in Release (GCC/Clang)" OFF)
21+
option(NWQEC_BUILD_PYTHON "Build Python bindings (pybind11)" ON)
22+
23+
option(NWQEC_ALLOW_NO_GMP "Allow building without GMP/MPFR (use Python gridsynth fallback)" OFF)
24+
25+
# =============================================================================
26+
# Compiler Options
27+
# =============================================================================
28+
29+
# Common compiler options
30+
set(COMMON_COMPILE_OPTIONS)
31+
if(MSVC)
32+
list(APPEND COMMON_COMPILE_OPTIONS /W4)
33+
else()
34+
list(APPEND COMMON_COMPILE_OPTIONS -Wall -Wextra -pedantic)
35+
endif()
36+
37+
# =============================================================================
38+
# Library Targets
39+
# =============================================================================
40+
41+
# Public interface for the project headers
42+
add_library(nwqec INTERFACE)
43+
target_include_directories(nwqec INTERFACE
44+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
45+
$<INSTALL_INTERFACE:include>
46+
)
47+
target_compile_features(nwqec INTERFACE cxx_std_17)
48+
49+
# =============================================================================
50+
# Gridsynth dependency (GMP/MPFR) and target
51+
# =============================================================================
52+
53+
# Try find_package first; if unavailable, create imported targets from paths
54+
find_package(GMP QUIET)
55+
find_package(MPFR QUIET)
56+
57+
if(NOT TARGET GMP::gmp OR NOT TARGET GMP::gmpxx)
58+
find_path(GMP_INCLUDE_DIR NAMES gmp.h)
59+
find_library(GMP_LIBRARY NAMES gmp)
60+
find_library(GMPXX_LIBRARY NAMES gmpxx)
61+
if(GMP_INCLUDE_DIR AND GMP_LIBRARY AND GMPXX_LIBRARY)
62+
add_library(GMP::gmp UNKNOWN IMPORTED)
63+
set_target_properties(GMP::gmp PROPERTIES
64+
IMPORTED_LOCATION ${GMP_LIBRARY}
65+
INTERFACE_INCLUDE_DIRECTORIES ${GMP_INCLUDE_DIR}
66+
)
67+
add_library(GMP::gmpxx UNKNOWN IMPORTED)
68+
set_target_properties(GMP::gmpxx PROPERTIES
69+
IMPORTED_LOCATION ${GMPXX_LIBRARY}
70+
INTERFACE_INCLUDE_DIRECTORIES ${GMP_INCLUDE_DIR}
71+
)
72+
endif()
73+
endif()
74+
75+
if(NOT TARGET MPFR::MPFR)
76+
find_path(MPFR_INCLUDE_DIR NAMES mpfr.h)
77+
find_library(MPFR_LIBRARY NAMES mpfr)
78+
if(MPFR_INCLUDE_DIR AND MPFR_LIBRARY)
79+
add_library(MPFR::MPFR UNKNOWN IMPORTED)
80+
set_target_properties(MPFR::MPFR PROPERTIES
81+
IMPORTED_LOCATION ${MPFR_LIBRARY}
82+
INTERFACE_INCLUDE_DIRECTORIES ${MPFR_INCLUDE_DIR}
83+
)
84+
endif()
85+
endif()
86+
87+
# Determine availability of gridsynth dependencies and prompt if missing
88+
set(NWQEC_MISSING_GRIDSYNTH_DEPS FALSE)
89+
if(NOT (TARGET GMP::gmp AND TARGET GMP::gmpxx AND TARGET MPFR::MPFR))
90+
set(NWQEC_MISSING_GRIDSYNTH_DEPS TRUE)
91+
endif()
92+
93+
if(NWQEC_MISSING_GRIDSYNTH_DEPS AND NOT NWQEC_ALLOW_NO_GMP)
94+
if(NOT Python3_Interpreter_FOUND)
95+
find_package(Python3 COMPONENTS Interpreter QUIET)
96+
endif()
97+
if(NOT Python3_Interpreter_FOUND)
98+
message(FATAL_ERROR "
99+
*** GMP/MPFR MISSING ***\nInstall the GMP and MPFR development libraries, then rerun CMake.\n macOS (Homebrew): brew install gmp mpfr\n Ubuntu/Debian: sudo apt-get install -y libgmp-dev libmpfr-dev\n Fedora: sudo dnf install gmp-devel mpfr-devel\n Windows (MSYS2): pacman -S mingw-w64-x86_64-gmp mingw-w64-x86_64-mpfr\n
100+
If you prefer to proceed without the C++ gridsynth backend, rerun with\n -DNWQEC_ALLOW_NO_GMP=ON\nor for pip:\n pip install . --config-settings=cmake.define.NWQEC_ALLOW_NO_GMP=ON\n
101+
")
102+
endif()
103+
104+
set(_NWQEC_PROMPT_SCRIPT [=[
105+
import sys
106+
prompt = """GMP and MPFR were not detected.
107+
108+
Install instructions:
109+
macOS (Homebrew): brew install gmp mpfr
110+
Ubuntu/Debian: sudo apt-get install -y libgmp-dev libmpfr-dev
111+
Fedora: sudo dnf install gmp-devel mpfr-devel
112+
Windows (MSYS2): pacman -S mingw-w64-x86_64-gmp mingw-w64-x86_64-mpfr
113+
114+
Install these libraries before continuing? [Y/n]: """
115+
try:
116+
answer = input(prompt)
117+
except EOFError:
118+
sys.exit(2)
119+
answer = answer.strip().lower()
120+
if not answer:
121+
answer = 'y'
122+
print(answer)
123+
]=])
124+
execute_process(COMMAND "${Python3_EXECUTABLE}" -c "${_NWQEC_PROMPT_SCRIPT}"
125+
RESULT_VARIABLE _NWQEC_PROMPT_RESULT
126+
OUTPUT_VARIABLE _NWQEC_PROMPT_OUTPUT)
127+
if(NOT _NWQEC_PROMPT_RESULT EQUAL 0)
128+
message(FATAL_ERROR "
129+
*** GMP/MPFR MISSING ***\nConfiguration cancelled at your request. Install the libraries above or rerun with\n -DNWQEC_ALLOW_NO_GMP=ON\n(pip: pip install . --config-settings=cmake.define.NWQEC_ALLOW_NO_GMP=ON)\n
130+
")
131+
endif()
132+
133+
string(STRIP "${_NWQEC_PROMPT_OUTPUT}" _NWQEC_PROMPT_OUTPUT)
134+
if(_NWQEC_PROMPT_OUTPUT STREQUAL "y" OR _NWQEC_PROMPT_OUTPUT STREQUAL "yes")
135+
message(FATAL_ERROR "Please install GMP and MPFR, then rerun configuration.")
136+
elseif(_NWQEC_PROMPT_OUTPUT STREQUAL "n" OR _NWQEC_PROMPT_OUTPUT STREQUAL "no")
137+
set(NWQEC_ALLOW_NO_GMP ON CACHE BOOL "Allow building without GMP/MPFR (use Python gridsynth fallback)" FORCE)
138+
message(WARNING "Proceeding without GMP/MPFR. Install python packages 'pygridsynth' and 'mpmath' to enable runtime RZ synthesis.")
139+
else()
140+
message(FATAL_ERROR "Unrecognized response: '${_NWQEC_PROMPT_OUTPUT}'. Aborting.")
141+
endif()
142+
endif()
143+
144+
# Interface target for gridsynth that carries MP deps
145+
add_library(nwqec_gridsynth INTERFACE)
146+
target_link_libraries(nwqec_gridsynth INTERFACE nwqec)
147+
148+
set(_NWQEC_GRIDSYNTH_CPP_FLAG 0)
149+
if(TARGET GMP::gmp AND TARGET GMP::gmpxx AND TARGET MPFR::MPFR)
150+
target_link_libraries(nwqec_gridsynth INTERFACE GMP::gmp GMP::gmpxx MPFR::MPFR)
151+
set(_NWQEC_GRIDSYNTH_CPP_FLAG 1)
152+
endif()
153+
154+
target_compile_definitions(nwqec_gridsynth INTERFACE NWQEC_WITH_GRIDSYNTH_CPP=${_NWQEC_GRIDSYNTH_CPP_FLAG})
155+
156+
# =============================================================================
157+
# Executables
158+
# =============================================================================
159+
160+
add_executable(transpiler tools/transpiler.cpp)
161+
set(_NWQEC_CLI_TARGETS transpiler)
162+
target_link_libraries(transpiler PRIVATE nwqec_gridsynth)
163+
target_compile_definitions(transpiler PRIVATE PROJECT_ROOT_DIR="${CMAKE_CURRENT_SOURCE_DIR}" NWQEC_WITH_GRIDSYNTH_CPP=${_NWQEC_GRIDSYNTH_CPP_FLAG})
164+
target_compile_options(transpiler PRIVATE ${COMMON_COMPILE_OPTIONS})
165+
166+
if(_NWQEC_GRIDSYNTH_CPP_FLAG)
167+
add_executable(gridsynth tools/gridsynth.cpp)
168+
target_link_libraries(gridsynth PRIVATE nwqec_gridsynth)
169+
target_compile_definitions(gridsynth PRIVATE PROJECT_ROOT_DIR="${CMAKE_CURRENT_SOURCE_DIR}" NWQEC_WITH_GRIDSYNTH_CPP=${_NWQEC_GRIDSYNTH_CPP_FLAG})
170+
target_compile_options(gridsynth PRIVATE ${COMMON_COMPILE_OPTIONS})
171+
list(APPEND _NWQEC_CLI_TARGETS gridsynth)
172+
endif()
173+
174+
# =============================================================================
175+
# Build type specific tweaks
176+
# =============================================================================
177+
178+
if(CMAKE_BUILD_TYPE STREQUAL "Release")
179+
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
180+
foreach(cli_target IN LISTS _NWQEC_CLI_TARGETS)
181+
if(NWQEC_ENABLE_NATIVE)
182+
target_compile_options(${cli_target} PRIVATE -O3 -march=native -funroll-loops)
183+
else()
184+
target_compile_options(${cli_target} PRIVATE -O3)
185+
endif()
186+
endforeach()
187+
else()
188+
foreach(cli_target IN LISTS _NWQEC_CLI_TARGETS)
189+
target_compile_options(${cli_target} PRIVATE -O2)
190+
endforeach()
191+
endif()
192+
193+
if(NWQEC_ENABLE_LTO)
194+
include(CheckIPOSupported)
195+
check_ipo_supported(RESULT _ipo_ok OUTPUT _ipo_err)
196+
if(_ipo_ok)
197+
foreach(cli_target IN LISTS _NWQEC_CLI_TARGETS)
198+
set_property(TARGET ${cli_target} PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
199+
endforeach()
200+
endif()
201+
endif()
202+
endif()
203+
204+
message(STATUS "Configured executable: transpiler")
205+
if(TARGET gridsynth)
206+
message(STATUS "Configured executable: gridsynth")
207+
else()
208+
message(STATUS "Skipping gridsynth CLI (GMP/MPFR not available)")
209+
endif()
210+
211+
# =============================================================================
212+
# Install rules (CLI binaries and headers)
213+
# =============================================================================
214+
include(GNUInstallDirs)
215+
install(TARGETS transpiler
216+
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
217+
if(TARGET gridsynth)
218+
install(TARGETS gridsynth RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
219+
endif()
220+
221+
# Install interface libraries and export targets
222+
install(TARGETS nwqec nwqec_gridsynth
223+
EXPORT NWQECTargets)
224+
225+
install(DIRECTORY include/
226+
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
227+
228+
install(EXPORT NWQECTargets
229+
NAMESPACE NWQEC::
230+
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/NWQEC)
231+
232+
# Package config files
233+
include(CMakePackageConfigHelpers)
234+
235+
# Record whether gridsynth deps were present at build
236+
set(NWQEC_WITH_GRIDSYNTH OFF)
237+
if(TARGET GMP::gmp AND TARGET GMP::gmpxx AND TARGET MPFR::MPFR)
238+
set(NWQEC_WITH_GRIDSYNTH ON)
239+
endif()
240+
241+
configure_package_config_file(
242+
${CMAKE_CURRENT_SOURCE_DIR}/cmake/NWQECConfig.cmake.in
243+
${CMAKE_CURRENT_BINARY_DIR}/NWQECConfig.cmake
244+
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/NWQEC
245+
)
246+
247+
write_basic_package_version_file(
248+
${CMAKE_CURRENT_BINARY_DIR}/NWQECConfigVersion.cmake
249+
VERSION ${PROJECT_VERSION}
250+
COMPATIBILITY SameMajorVersion
251+
)
252+
253+
install(FILES
254+
${CMAKE_CURRENT_BINARY_DIR}/NWQECConfig.cmake
255+
${CMAKE_CURRENT_BINARY_DIR}/NWQECConfigVersion.cmake
256+
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/NWQEC)
257+
258+
# =============================================================================
259+
# Tests (CLI)
260+
# =============================================================================
261+
include(CTest)
262+
if(BUILD_TESTING)
263+
add_test(NAME transpiler_help
264+
COMMAND $<TARGET_FILE:transpiler> --help)
265+
add_test(NAME transpiler_qft
266+
COMMAND $<TARGET_FILE:transpiler> --qft 4 --no-save)
267+
if(TARGET gridsynth)
268+
add_test(NAME gridsynth_basic
269+
COMMAND $<TARGET_FILE:gridsynth> pi/4 10)
270+
endif()
271+
endif()
272+
273+
# =============================================================================
274+
# Python bindings (pybind11)
275+
# =============================================================================
276+
if(NWQEC_BUILD_PYTHON)
277+
find_package(pybind11 CONFIG QUIET)
278+
if(pybind11_FOUND)
279+
# Use a different CMake target name to avoid clashing with the INTERFACE library 'nwqec'
280+
pybind11_add_module(nwqec_ext MODULE python/nwqec/_core.cpp)
281+
# Ensure the produced module is packaged as nwqec._core
282+
set_target_properties(nwqec_ext PROPERTIES OUTPUT_NAME "_core")
283+
284+
target_link_libraries(nwqec_ext PRIVATE nwqec)
285+
if(TARGET GMP::gmp AND TARGET GMP::gmpxx AND TARGET MPFR::MPFR)
286+
target_link_libraries(nwqec_ext PRIVATE GMP::gmp GMP::gmpxx MPFR::MPFR)
287+
target_compile_definitions(nwqec_ext PRIVATE NWQEC_WITH_GRIDSYNTH_CPP=1)
288+
else()
289+
target_compile_definitions(nwqec_ext PRIVATE NWQEC_WITH_GRIDSYNTH_CPP=0)
290+
endif()
291+
target_compile_definitions(nwqec_ext PRIVATE PROJECT_ROOT_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
292+
target_compile_options(nwqec_ext PRIVATE ${COMMON_COMPILE_OPTIONS})
293+
# Install extension into the correct Python platlib dir when building a wheel
294+
if(DEFINED SKBUILD_PLATLIB_DIR)
295+
install(TARGETS nwqec_ext LIBRARY DESTINATION ${SKBUILD_PLATLIB_DIR}/nwqec)
296+
endif()
297+
message(STATUS "Configured Python module target: nwqec_ext (module name: nwqec._core)")
298+
else()
299+
message(WARNING "pybind11 not found; skipping Python module. Install with 'pip install pybind11' and reconfigure, or set NWQEC_BUILD_PYTHON=OFF.")
300+
endif()
301+
endif()

0 commit comments

Comments
 (0)