diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt
index dc696d77..735cf6f1 100644
--- a/docs/CMakeLists.txt
+++ b/docs/CMakeLists.txt
@@ -1,5 +1,5 @@
# ============================================================================ #
-# Copyright (c) 2024 NVIDIA Corporation & Affiliates. #
+# Copyright (c) 2024 - 2025 NVIDIA Corporation & Affiliates. #
# All rights reserved. #
# #
# This source code and the accompanying materials are made available under #
@@ -25,13 +25,6 @@ foreach(lib ${CUDAQX_ALL_LIBS})
list(APPEND CUDAQX_PUBLIC_PYTHON ${LIB_PUBLIC_PYTHON})
endforeach()
-# Find all the rst files
-set(CUDAQX_PUBLIC_RST)
-foreach(lib ${CUDAQX_ALL_LIBS})
- file(GLOB_RECURSE RST_FILES "*.rst")
- list(APPEND CUDAQX_PUBLIC_RST ${RST_FILES})
-endforeach()
-
# ==============================================================================
# Doxygen
# ==============================================================================
@@ -58,69 +51,6 @@ add_custom_command(
add_custom_target(doxygen_docs DEPENDS ${DOXYGEN_INDEX_FILE})
-# ==============================================================================
-# Sphinx
-# ==============================================================================
-
-find_package(Python COMPONENTS Interpreter REQUIRED)
-
-function(require_python_module module_name)
- execute_process(
- COMMAND ${Python_EXECUTABLE} -c "import ${module_name}"
- RESULT_VARIABLE result
- OUTPUT_QUIET
- ERROR_QUIET
- )
- if(NOT result EQUAL 0)
- message(FATAL_ERROR "Python module '${module_name}' not found")
- endif()
-endfunction()
-
-require_python_module(IPython)
-require_python_module(breathe)
-require_python_module(enum_tools)
-require_python_module(myst_parser)
-require_python_module(nbsphinx)
-require_python_module(sphinx_copybutton)
-require_python_module(sphinx_inline_tabs)
-require_python_module(sphinx_gallery)
-require_python_module(sphinx_rtd_theme)
-require_python_module(sphinx_reredirects)
-require_python_module(sphinx_toolbox)
-
-set(SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/sphinx)
-set(SPHINX_BUILD ${CMAKE_CURRENT_BINARY_DIR}/build)
-set(SPHINX_INDEX_FILE ${SPHINX_BUILD}/index.html)
-
-set(SPHINX_CONF_IN ${SPHINX_SOURCE}/conf.py.in)
-set(SPHINX_CONF ${CMAKE_CURRENT_BINARY_DIR}/conf.py)
-
-configure_file(${SPHINX_CONF_IN} ${SPHINX_CONF} @ONLY)
-
-# Only regenerate Sphinx when:
-# - Doxygen has rerun
-# - Our doc files have been updated
-# - The Sphinx config has been updated
-# TODO: set warning as error (-W flag)
-add_custom_command(
- OUTPUT ${SPHINX_INDEX_FILE}
- COMMAND ${SPHINX_EXECUTABLE} -v -n --keep-going -b html
- -c ${CMAKE_CURRENT_BINARY_DIR}
- -Dbreathe_projects.cudaqx=${DOXYGEN_OUTPUT_DIR}/xml
- ${SPHINX_SOURCE} ${SPHINX_BUILD}
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- DEPENDS
- ${SPHINX_SOURCE}/index.rst
- ${DOXYGEN_INDEX_FILE}
- cudaqx-pymodules
- ${CUDAQX_PUBLIC_PYTHON}
- ${CUDAQX_PUBLIC_RST}
- MAIN_DEPENDENCY ${SPHINX_CONF_IN} ${SPHINX_CONF}
- COMMENT "Generating documentation with Sphinx"
-)
-
-add_custom_target(sphinx_docs DEPENDS ${SPHINX_INDEX_FILE})
-
# ==============================================================================
-add_custom_target(docs DEPENDS doxygen_docs sphinx_docs)
+add_custom_target(docs DEPENDS doxygen_docs)
diff --git a/docs/Doxyfile.in b/docs/Doxyfile.in
index 29b697c8..defee60a 100644
--- a/docs/Doxyfile.in
+++ b/docs/Doxyfile.in
@@ -16,9 +16,18 @@ ALIASES += "pure_device_kernel=\par This function is a pure-device CUDA-Q quantu
# Build related configuration options
#---------------------------------------------------------------------------
-EXTRACT_ALL = YES
-EXTRACT_PRIVATE = YES
+EXTRACT_ALL = NO
+EXTRACT_PRIVATE = NO
EXTRACT_STATIC = YES
+WARN_AS_ERROR = FAIL_ON_WARNINGS
+WARN_IF_INCOMPLETE_DOC = NO
+WARN_IF_UNDOCUMENTED = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+EXCLUDE_SYMBOLS = "classcudaqx_1_1*"
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
diff --git a/docs/sphinx/_static/cuda_quantum_icon.svg b/docs/sphinx/_static/cuda_quantum_icon.svg
deleted file mode 100644
index e7f2901f..00000000
--- a/docs/sphinx/_static/cuda_quantum_icon.svg
+++ /dev/null
@@ -1,553 +0,0 @@
-
diff --git a/docs/sphinx/_static/cudaq_override.css b/docs/sphinx/_static/cudaq_override.css
deleted file mode 100644
index 4ab0ac17..00000000
--- a/docs/sphinx/_static/cudaq_override.css
+++ /dev/null
@@ -1,27 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2022 - 2024 NVIDIA Corporation & Affiliates. *
- * All rights reserved. *
- * *
- * This source code and the accompanying materials are made available under *
- * the terms of the Apache License 2.0 which accompanies this distribution. *
- * *
- * File: cudaq_override.css *
- * Created Date: 16 Feb 2023 *
- * Last Modified: 16 Feb 2023 *
- ******************************************************************************/
-
-.wy-nav-content {
-max-width: 1240px !important;
-}
-
-.wy-menu-vertical a {
- font-size: 92%;
-}
-
-.wy-menu-vertical li code, .wy-menu-vertical li .rst-content tt, .rst-content .wy-menu-vertical li tt {
- font-size: 100%;
-}
-
-code.code span.pre, code.cpp span.pre, code.docutils span.pre{
- color: darkgreen;
-}
diff --git a/docs/sphinx/_templates/autosummary/class.rst b/docs/sphinx/_templates/autosummary/class.rst
deleted file mode 100644
index b45a3fd5..00000000
--- a/docs/sphinx/_templates/autosummary/class.rst
+++ /dev/null
@@ -1,26 +0,0 @@
-{{ fullname | escape | underline}}
-
-.. currentmodule:: {{ module }}
-
-.. autoclass:: {{ objname }}
-
- {% block methods %}
- {% if methods %}
- .. rubric:: {{ _('Methods') }}
-
- {% for item in methods %}
- .. automethod:: {{ item }}
- {%- endfor %}
-
- {% endif %}
- {% endblock %}
-
- {% block attributes %}
- {% if attributes %}
- .. rubric:: {{ _('Attributes') }}
-
- {% for item in attributes %}
- .. autoattribute:: {{ item }}
- {%- endfor %}
- {% endif %}
- {% endblock %}
diff --git a/docs/sphinx/_templates/autosummary/dataclass.rst b/docs/sphinx/_templates/autosummary/dataclass.rst
deleted file mode 100644
index b8c35324..00000000
--- a/docs/sphinx/_templates/autosummary/dataclass.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-{{ fullname | escape | underline}}
-
-.. currentmodule:: {{ module }}
-
-.. autoclass:: {{ objname }}
-
- {% block methods %}
- .. automethod:: __init__
- {% endblock %}
-
diff --git a/docs/sphinx/_templates/layout.html b/docs/sphinx/_templates/layout.html
deleted file mode 100644
index c0f02f29..00000000
--- a/docs/sphinx/_templates/layout.html
+++ /dev/null
@@ -1,62 +0,0 @@
-{% extends "!layout.html" %}
- {% block sidebartitle %} {{ super() }}
-
-
- {% endblock %}
-
- {% block footer %} {{ super() }}
-
-
- {% endblock %}
diff --git a/docs/sphinx/_templates/openapi.html b/docs/sphinx/_templates/openapi.html
deleted file mode 100644
index d50627fd..00000000
--- a/docs/sphinx/_templates/openapi.html
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/docs/sphinx/api/core/cpp_api.rst b/docs/sphinx/api/core/cpp_api.rst
deleted file mode 100644
index 6d323af3..00000000
--- a/docs/sphinx/api/core/cpp_api.rst
+++ /dev/null
@@ -1,46 +0,0 @@
-CUDA-QX Namespaces and Core Library C++ API
-********************************************
-
-Namespaces
-==========
-.. doxygennamespace:: cudaqx
- :desc-only:
-.. doxygennamespace:: cudaq
- :desc-only:
-.. doxygennamespace:: cudaq::qec
- :desc-only:
-.. doxygennamespace:: cudaq::qec::steane
- :desc-only:
-.. doxygennamespace:: cudaq::qec::surface_code
- :desc-only:
-.. doxygennamespace:: cudaq::qec::repetition
- :desc-only:
-.. doxygennamespace:: cudaq::solvers
- :desc-only:
-.. doxygennamespace:: cudaq::solvers::stateprep
- :desc-only:
-.. doxygennamespace:: cudaq::solvers::adapt
- :desc-only:
-.. doxygennamespace:: cudaq::optim
- :desc-only:
-
-Core
-=============
-
-.. doxygenclass:: cudaqx::extension_point
- :members:
-
-.. doxygenclass:: cudaqx::heterogeneous_map
- :members:
-
-.. doxygenclass:: cudaqx::tear_down
- :members:
-
-.. doxygenclass:: cudaqx::details::tensor_impl
- :members:
-
-.. doxygenclass:: cudaqx::tensor
- :members:
-
-.. doxygenclass:: cudaqx::graph
- :members:
diff --git a/docs/sphinx/api/qec/cpp_api.rst b/docs/sphinx/api/qec/cpp_api.rst
deleted file mode 100644
index 6df1f6c5..00000000
--- a/docs/sphinx/api/qec/cpp_api.rst
+++ /dev/null
@@ -1,60 +0,0 @@
-CUDA-Q QEC C++ API
-******************************
-
-Code
-=============
-
-.. doxygenclass:: cudaq::qec::code
- :members:
-
-.. doxygenstruct:: cudaq::qec::patch
- :members:
-
-.. doxygenclass:: cudaq::qec::repetition::repetition
- :members:
-
-.. doxygenclass:: cudaq::qec::steane::steane
- :members:
-
-.. doxygenclass:: cudaq::qec::surface_code::stabilizer_grid
- :members:
-
-.. doxygenclass:: cudaq::qec::surface_code::surface_code
- :members:
-
-
-Decoder Interfaces
-==================
-
-.. doxygenclass:: cudaq::qec::decoder
- :members:
-
-.. doxygenstruct:: cudaq::qec::decoder_result
- :members:
-
-Built-in Decoders
-=================
-
-.. _nv_qldpc_decoder_api_cpp:
-
-NVIDIA QLDPC Decoder
---------------------
-
-.. include:: nv_qldpc_decoder_api.rst
-
-Common
-=============
-
-.. doxygentypedef:: cudaq::qec::float_t
-
-.. doxygenenum:: cudaq::qec::operation
-
-.. doxygenfunction:: cudaq::qec::sample_code_capacity(const cudaqx::tensor &, std::size_t, double)
-.. doxygenfunction:: cudaq::qec::sample_code_capacity(const cudaqx::tensor &, std::size_t, double, unsigned)
-.. doxygenfunction:: cudaq::qec::sample_code_capacity(const code &, std::size_t, double)
-.. doxygenfunction:: cudaq::qec::sample_code_capacity(const code &, std::size_t, double, unsigned)
-
-.. doxygenfunction:: cudaq::qec::sample_memory_circuit(const code &, std::size_t, std::size_t)
-.. doxygenfunction:: cudaq::qec::sample_memory_circuit(const code &, std::size_t, std::size_t, cudaq::noise_model &)
-.. doxygenfunction:: cudaq::qec::sample_memory_circuit(const code &, operation, std::size_t, std::size_t)
-.. doxygenfunction:: cudaq::qec::sample_memory_circuit(const code &, operation, std::size_t, std::size_t, cudaq::noise_model &)
diff --git a/docs/sphinx/api/qec/nv_qldpc_decoder_api.rst b/docs/sphinx/api/qec/nv_qldpc_decoder_api.rst
deleted file mode 100644
index 7f8bb7e5..00000000
--- a/docs/sphinx/api/qec/nv_qldpc_decoder_api.rst
+++ /dev/null
@@ -1,97 +0,0 @@
-.. class:: nv_qldpc_decoder
-
- A general purpose Quantum Low-Density Parity-Check Decoder (QLDPC)
- decoder based on GPU accelerated belief propagation (BP). Since belief
- propagation is an iterative method, decoding can be improved with a
- second-stage post-processing step. Optionally, ordered statistics decoding
- (OSD) can be chosen to perform the second stage of decoding.
-
- An [[n,k,d]] quantum error correction (QEC) code encodes k logical qubits
- into an n qubit data block, with a code distance d. Quantum low-density
- parity-check (QLDPC) codes are characterized by sparse parity-check matrices
- (or Tanner graphs), corresponding to a bounded number of parity checks per
- data qubit.
-
- Requires a CUDA-Q compatible GPU. See the `CUDA-Q GPU Compatibility
- List `_
- for a list of valid GPU configurations.
-
- References:
- `Decoding Across the Quantum LDPC Code Landscape `_
-
- .. note::
- It is required to create decoders with the `get_decoder` API from the CUDA-QX
- extension points API, such as
-
- .. tab:: Python
-
- .. code-block:: python
-
- import cudaq_qec as qec
- import numpy as np
- H = np.array([[1, 0, 0, 1, 0, 1, 1],
- [0, 1, 0, 1, 1, 0, 1],
- [0, 0, 1, 0, 1, 1, 1]], dtype=np.uint8) # sample 3x7 PCM
- opts = dict() # see below for options
- # Note: H must be in row-major order. If you use
- # `scipy.sparse.csr_matrix.todense()` to get the parity check
- # matrix, you must specify todense(order='C') to get a row-major
- # matrix.
- nvdec = qec.get_decoder('nv-qldpc-decoder', H, **opts)
-
- .. tab:: C++
-
- .. code-block:: cpp
-
- std::size_t block_size = 7;
- std::size_t syndrome_size = 3;
- cudaqx::tensor H;
-
- std::vector H_vec = {1, 0, 0, 1, 0, 1, 1,
- 0, 1, 0, 1, 1, 0, 1,
- 0, 0, 1, 0, 1, 1, 1};
- H.copy(H_vec.data(), {syndrome_size, block_size});
-
- cudaqx::heterogeneous_map nv_custom_args;
- nv_custom_args.insert("use_osd", true);
- // See below for options
-
- auto nvdec = cudaq::qec::get_decoder("nv-qldpc-decoder", H, nv_custom_args);
-
- .. note::
- The `"nv-qldpc-decoder"` implements the :class:`cudaq_qec.Decoder`
- interface for Python and the :cpp:class:`cudaq::qec::decoder` interface
- for C++, so it supports all the methods in those respective classes.
-
- :param H: Parity check matrix (tensor format)
- :param params: Heterogeneous map of parameters:
-
- - `use_sparsity` (bool): Whether or not to use a sparse matrix solver
- - `error_rate` (double): Probability of an error (in 0-1 range) on a
- block data bit (defaults to 0.001)
- - `error_rate_vec` (double): Vector of length "block size" containing
- the probability of an error (in 0-1 range) on a block data bit (defaults
- to 0.001). This overrides `error_rate`.
- - `max_iterations` (int): Maximum number of BP iterations to perform
- (defaults to 30)
- - `n_threads` (int): Number of CUDA threads to use for the GPU decoder
- (defaults to smart selection based on parity matrix size)
- - `use_osd` (bool): Whether or not to use an OSD post processor if the
- initial BP algorithm fails to converge on a solution
- - `osd_method` (int): 1=OSD-0, 2=Exhaustive, 3=Combination Sweep
- (defaults to 1). Ignored unless `use_osd` is true.
- - `osd_order` (int): OSD postprocessor order (defaults to 0). Ref:
- `Decoding Across the Quantum LDPC Code Landscape `_
- - For `osd_method=2` (Exhaustive), the number of possible
- permutations searched after OSD-0 grows by 2^osd_order.
- - For `osd_method=3` (Combination Sweep), this is the λ parameter. All
- weight 1 permutations and the first λ bits worth of weight 2
- permutations are searched after OSD-0. This is (syndrome_length -
- block_size + λ * (λ - 1) / 2) additional permutations.
- - For other `osd_method` values, this is ignored.
- - `bp_batch_size` (int): Number of syndromes that will be decoded in
- parallel for the BP decoder (defaults to 1)
- - `osd_batch_size` (int): Number of syndromes that will be decoded in
- parallel for OSD (defaults to the number of concurrent threads supported
- by the hardware)
-
diff --git a/docs/sphinx/api/qec/python_api.rst b/docs/sphinx/api/qec/python_api.rst
deleted file mode 100644
index 2c6df892..00000000
--- a/docs/sphinx/api/qec/python_api.rst
+++ /dev/null
@@ -1,37 +0,0 @@
-CUDA-Q QEC Python API
-******************************
-
-.. automodule:: cudaq_qec
- :members:
-
-Code
-=============
-
-.. autoclass:: cudaq_qec.Code
- :members:
-
-Decoder Interfaces
-==================
-
-.. autoclass:: cudaq_qec.Decoder
- :members:
-
-.. autoclass:: cudaq_qec.DecoderResult
- :members:
-
-Built-in Decoders
-=================
-
-.. _nv_qldpc_decoder_api_python:
-
-NVIDIA QLDPC Decoder
---------------------
-
-.. include:: nv_qldpc_decoder_api.rst
-
-Common
-=============
-
-.. autofunction:: cudaq_qec.sample_memory_circuit
-
-.. autofunction:: cudaq_qec.sample_code_capacity
diff --git a/docs/sphinx/api/solvers/cpp_api.rst b/docs/sphinx/api/solvers/cpp_api.rst
deleted file mode 100644
index e363f396..00000000
--- a/docs/sphinx/api/solvers/cpp_api.rst
+++ /dev/null
@@ -1,79 +0,0 @@
-CUDA-Q Solvers C++ API
-******************************
-
-.. doxygenclass:: cudaq::solvers::operator_pool
- :members:
-
-.. doxygenclass:: cudaq::solvers::spin_complement_gsd
-.. doxygenclass:: cudaq::solvers::uccsd
-.. doxygenclass:: cudaq::solvers::qaoa_pool
-
-.. doxygenfunction:: cudaq::solvers::get_operator_pool
-
-.. doxygenstruct:: cudaq::solvers::atom
- :members:
-
-.. doxygenclass:: cudaq::solvers::molecular_geometry
- :members:
-
-.. doxygenstruct:: cudaq::solvers::molecular_hamiltonian
- :members:
-
-.. doxygenstruct:: cudaq::solvers::molecule_options
- :members:
-
-.. doxygenfunction:: cudaq::solvers::create_molecule
-
-.. doxygenfunction:: cudaq::solvers::get_maxcut_hamiltonian
-
-.. doxygenfunction:: cudaq::solvers::get_clique_hamiltonian
-
-.. doxygenfunction:: cudaq::solvers::one_particle_op
-
-.. doxygentypedef:: cudaq::ParameterizedKernel
-.. doxygentypedef:: cudaq::optim::optimization_result
-.. doxygenclass:: cudaq::optim::optimizable_function
-.. doxygenclass:: cudaq::optim::optimizer
- :members:
-.. doxygenclass:: cudaq::optim::cobyla
-.. doxygenclass:: cudaq::optim::lbfgs
-.. doxygenclass:: cudaq::observe_gradient
- :members:
-.. doxygenstruct:: cudaq::observe_iteration
- :members:
-.. doxygenclass:: cudaq::central_difference
-.. doxygenclass:: cudaq::forward_difference
-.. doxygenclass:: cudaq::parameter_shift
-
-.. doxygenenum:: cudaq::observe_execution_type
-
-.. doxygenstruct:: cudaq::solvers::vqe_result
-.. doxygenfunction:: cudaq::solvers::vqe(QuantumKernel &&, const spin_op &, const std::string &, const std::string &, const std::vector &, heterogeneous_map)
-.. doxygenfunction:: cudaq::solvers::vqe(QuantumKernel &&, const spin_op &, const std::string &, const std::vector &, heterogeneous_map)
-.. doxygenfunction:: cudaq::solvers::vqe(QuantumKernel &&, const spin_op &, const std::string &, observe_gradient &, const std::vector &, heterogeneous_map)
-.. doxygenfunction:: cudaq::solvers::vqe(QuantumKernel &&, const spin_op &, optim::optimizer &, const std::string &, const std::vector &, heterogeneous_map)
-.. doxygenfunction:: cudaq::solvers::vqe(QuantumKernel &&, const spin_op &, optim::optimizer &, const std::vector &, heterogeneous_map)
-.. doxygenfunction:: cudaq::solvers::vqe(QuantumKernel &&, const spin_op &, optim::optimizer &, observe_gradient &, const std::vector &, heterogeneous_map)
-
-.. doxygentypedef:: cudaq::solvers::adapt::result
-.. doxygenfunction:: cudaq::solvers::adapt_vqe(const cudaq::qkernel&)> &, const spin_op &, const std::vector &, const heterogeneous_map)
-.. doxygenfunction:: cudaq::solvers::adapt_vqe(const cudaq::qkernel&)> &, const spin_op &, const std::vector &, const optim::optimizer&, const heterogeneous_map)
-.. doxygenfunction:: cudaq::solvers::adapt_vqe(const cudaq::qkernel&)> &, const spin_op &, const std::vector &, const optim::optimizer&, const std::string&, const heterogeneous_map)
-
-.. doxygentypedef:: cudaq::solvers::stateprep::excitation_list
-.. doxygenfunction:: cudaq::solvers::stateprep::get_uccsd_excitations
-.. doxygenfunction:: cudaq::solvers::stateprep::get_num_uccsd_parameters
-.. doxygenfunction:: cudaq::solvers::stateprep::single_excitation
-.. doxygenfunction:: cudaq::solvers::stateprep::double_excitation
-.. doxygenfunction:: cudaq::solvers::stateprep::uccsd(cudaq::qview<>, const std::vector&, std::size_t, std::size_t)
-.. doxygenfunction:: cudaq::solvers::stateprep::uccsd(cudaq::qview<>, const std::vector&, std::size_t)
-
-
-.. doxygenstruct:: cudaq::solvers::qaoa_result
- :members:
-.. doxygenfunction:: cudaq::solvers::qaoa(const cudaq::spin_op &, const cudaq::spin_op &, const optim::optimizer &, std::size_t, const std::vector &, const heterogeneous_map)
-.. doxygenfunction:: cudaq::solvers::qaoa(const cudaq::spin_op &, const optim::optimizer &, std::size_t, const std::vector &, const heterogeneous_map)
-.. doxygenfunction:: cudaq::solvers::qaoa(const cudaq::spin_op &, std::size_t, const std::vector &, const heterogeneous_map)
-.. doxygenfunction:: cudaq::solvers::qaoa(const cudaq::spin_op &, const cudaq::spin_op &, std::size_t, const std::vector &, const heterogeneous_map)
-.. doxygenfunction:: cudaq::solvers::get_num_qaoa_parameters(const cudaq::spin_op &, const cudaq::spin_op &, std::size_t, const heterogeneous_map)
-.. doxygenfunction:: cudaq::solvers::get_num_qaoa_parameters(const cudaq::spin_op &, std::size_t, const heterogeneous_map)
diff --git a/docs/sphinx/api/solvers/python_api.rst b/docs/sphinx/api/solvers/python_api.rst
deleted file mode 100644
index 150935b8..00000000
--- a/docs/sphinx/api/solvers/python_api.rst
+++ /dev/null
@@ -1,32 +0,0 @@
-CUDA-Q Solvers Python API
-******************************
-
-.. automodule:: cudaq_solvers
- :members:
-
-.. autofunction:: cudaq_solvers.jordan_wigner
-
-.. autofunction:: cudaq_solvers.bravyi_kitaev
-
-.. autoclass:: cudaq_solvers.MolecularHamiltonian
- :members:
-
-.. autofunction:: cudaq_solvers.get_operator_pool
-
-.. autofunction:: cudaq_solvers.optim.optimize
-.. autoclass:: cudaq_solvers.ObserveExecutionType
- :members:
- :undoc-members:
-.. autoclass:: cudaq_solvers.ObserveIteration
- :members:
-.. autofunction:: cudaq_solvers.vqe
-.. autofunction:: cudaq_solvers.adapt_vqe
-
-.. autofunction:: cudaq_solvers.stateprep.uccsd
-.. autofunction:: cudaq_solvers.stateprep.single_excitation
-.. autofunction:: cudaq_solvers.stateprep.double_excitation
-.. autofunction:: cudaq_solvers.stateprep.get_num_uccsd_parameters
-.. autofunction:: cudaq_solvers.stateprep.get_uccsd_excitations
-
-.. autofunction:: cudaq_solvers.get_num_qaoa_parameters
-
diff --git a/docs/sphinx/components/qec/introduction.rst b/docs/sphinx/components/qec/introduction.rst
deleted file mode 100644
index 41f2588f..00000000
--- a/docs/sphinx/components/qec/introduction.rst
+++ /dev/null
@@ -1,1050 +0,0 @@
-CUDA-Q QEC - Quantum Error Correction Library
-=============================================
-
-Overview
---------
-The ``cudaq-qec`` library provides a comprehensive framework for quantum
-error correction research and development. It leverages GPU acceleration
-for efficient syndrome decoding and error correction simulations (coming soon).
-
-Core Components
-----------------
-``cudaq-qec`` is composed of two main interfaces - the :code:`cudaq::qec::code` and
-:code:`cudaq::qec::decoder` types. These types are meant to be extended by developers
-to provide new error correcting codes and new decoding strategies.
-
-QEC Code Framework :code:`cudaq::qec::code`
--------------------------------------------
-
-The :code:`cudaq::qec::code` class serves as the base class for all quantum error correcting codes in CUDA-Q QEC. It provides
-a flexible extension point for implementing new codes and defines the core interface that all QEC codes must support.
-
-The core abstraction here is that of a mapping or dictionary of logical operations to their
-corresponding physical implementation in the error correcting code as CUDA-Q quantum kernels.
-
-Class Structure
-^^^^^^^^^^^^^^^
-
-The code base class provides:
-
-1. **Operation Enumeration**: Defines supported logical operations
-
- .. code-block:: cpp
-
- enum class operation {
- x, // Logical X gate
- y, // Logical Y gate
- z, // Logical Z gate
- h, // Logical Hadamard gate
- s, // Logical S gate
- cx, // Logical CNOT gate
- cy, // Logical CY gate
- cz, // Logical CZ gate
- stabilizer_round, // Stabilizer measurement round
- prep0, // Prepare |0⟩ state
- prep1, // Prepare |1⟩ state
- prepp, // Prepare |+⟩ state
- prepm // Prepare |-⟩ state
- };
-
-
-2. **Patch Type**: Defines the structure of a logical qubit patch
-
- .. code-block:: cpp
-
- struct patch {
- cudaq::qview<> data; // View of data qubits
- cudaq::qview<> ancx; // View of X stabilizer ancilla qubits
- cudaq::qview<> ancz; // View of Z stabilizer ancilla qubits
- };
-
- The `patch` type represents a logical qubit in quantum error correction codes. It contains:
- - `data`: A view of the data qubits in the patch
- - `ancx`: A view of the ancilla qubits used for X stabilizer measurements
- - `ancz`: A view of the ancilla qubits used for Z stabilizer measurements
-
- This structure is designed for use within CUDA-Q kernel code and provides a
- convenient way to access different qubit subsets within a logical qubit patch.
-
-
-3. **Kernel Type Aliases**: Defines quantum kernel signatures
-
- .. code-block:: cpp
-
- using one_qubit_encoding = cudaq::qkernel;
- using two_qubit_encoding = cudaq::qkernel;
- using stabilizer_round = cudaq::qkernel(
- patch, const std::vector&, const std::vector&)>;
-
-4. **Protected Members**:
-
- - :code:`operation_encodings`: Maps operations to their quantum kernel implementations. The key is the ``operation`` enum and the value is a variant on the above kernel type aliases.
- - :code:`m_stabilizers`: Stores the code's stabilizer generators
-
-Implementing a New Code
-^^^^^^^^^^^^^^^^^^^^^^^
-
-To implement a new quantum error correcting code:
-
-1. **Create a New Class**:
-
- .. code-block:: cpp
-
- class my_code : public qec::code {
- protected:
- // Implement required virtual methods
- public:
- my_code(const heterogeneous_map& options);
- };
-
-2. **Implement Required Virtual Methods**:
-
- .. code-block:: cpp
-
- // Number of physical data qubits
- std::size_t get_num_data_qubits() const override;
-
- // Total number of ancilla qubits
- std::size_t get_num_ancilla_qubits() const override;
-
- // Number of X-type ancilla qubits
- std::size_t get_num_ancilla_x_qubits() const override;
-
- // Number of Z-type ancilla qubits
- std::size_t get_num_ancilla_z_qubits() const override;
-
-3. **Define Quantum Kernels**:
-
- Create CUDA-Q kernels for each logical operation:
-
- .. code-block:: cpp
-
- __qpu__ void x(patch p) {
- // Implement logical X
- }
-
- __qpu__ std::vector stabilizer(patch p,
- const std::vector& x_stabs,
- const std::vector& z_stabs) {
- // Implement stabilizer measurements
- }
-
-4. **Register Operations**:
-
- In the constructor, register quantum kernels for each operation:
-
- .. code-block:: cpp
-
- my_code::my_code(const heterogeneous_map& options) : code() {
- // Register operations
- operation_encodings.insert(
- std::make_pair(operation::x, x));
- operation_encodings.insert(
- std::make_pair(operation::stabilizer_round, stabilizer));
-
- // Define stabilizer generators
- m_stabilizers = qec::stabilizers({"XXXX", "ZZZZ"});
- }
-
-
- Note that in your constructor, you have access to user-provided ``options``. For
- example, if your code depends on an integer parameter called ``distance``, you can
- retrieve that from the user via
-
- .. code-block:: cpp
-
- my_code::my_code(const heterogeneous_map& options) : code() {
- // ... fill the map and stabilizers ...
-
- // Get the user-provided distance, or just
- // set to 3 if user did not provide one
- this->distance = options.get("distance", /*defaultValue*/ 3);
- }
-
-5. **Register Extension Point**:
-
- Add extension point registration:
-
- .. code-block:: cpp
-
- CUDAQ_EXTENSION_CUSTOM_CREATOR_FUNCTION(
- my_code,
- static std::unique_ptr create(
- const heterogeneous_map &options) {
- return std::make_unique(options);
- }
- )
-
- CUDAQ_REGISTER_TYPE(my_code)
-
-Example: Steane Code
-^^^^^^^^^^^^^^^^^^^^^
-
-The Steane [[7,1,3]] code provides a complete example implementation:
-
-1. **Header Definition**:
-
- - Declares quantum kernels for all logical operations
- - Defines the code class with required virtual methods
- - Specifies 7 data qubits and 6 ancilla qubits (3 X-type, 3 Z-type)
-
-2. **Implementation**:
-
- .. code-block:: cpp
-
- steane::steane(const heterogeneous_map &options) : code() {
- // Register all logical operations
- operation_encodings.insert(
- std::make_pair(operation::x, x));
- // ... register other operations ...
-
- // Define stabilizer generators
- m_stabilizers = qec::stabilizers({
- "XXXXIII", "IXXIXXI", "IIXXIXX",
- "ZZZZIII", "IZZIZZI", "IIZZIZZ"
- });
- }
-
-3. **Quantum Kernels**:
-
- Implements fault-tolerant logical operations:
-
- .. code-block:: cpp
-
- __qpu__ void x(patch logicalQubit) {
- // Apply logical X to specific data qubits
- x(logicalQubit.data[4], logicalQubit.data[5],
- logicalQubit.data[6]);
- }
-
- __qpu__ std::vector stabilizer(patch logicalQubit,
- const std::vector& x_stabilizers,
- const std::vector& z_stabilizers) {
- // Measure X stabilizers
- h(logicalQubit.ancx);
- // ... apply controlled-X gates ...
- h(logicalQubit.ancx);
-
- // Measure Z stabilizers
- // ... apply controlled-X gates ...
-
- // Return measurement results
- return mz(logicalQubit.ancz, logicalQubit.ancx);
- }
-
-Implementing a New Code in Python
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-CUDA-Q QEC supports implementing quantum error correction codes in Python
-using the :code:`@qec.code` decorator. This provides a more accessible way
-to prototype and develop new codes.
-
-1. **Create a New Python File**:
-
- Create a new file (e.g., :code:`my_steane.py`) with your code implementation:
-
- .. code-block:: python
-
- import cudaq
- import cudaq_qec as qec
- from cudaq_qec import patch
-
-2. **Define Quantum Kernels**:
-
- Implement the required quantum kernels using the :code:`@cudaq.kernel` decorator:
-
- .. code-block:: python
-
- @cudaq.kernel
- def prep0(logicalQubit: patch):
- h(logicalQubit.data[0], logicalQubit.data[4], logicalQubit.data[6])
- x.ctrl(logicalQubit.data[0], logicalQubit.data[1])
- x.ctrl(logicalQubit.data[4], logicalQubit.data[5])
- # ... additional initialization gates ...
-
- @cudaq.kernel
- def stabilizer(logicalQubit: patch,
- x_stabilizers: list[int],
- z_stabilizers: list[int]) -> list[bool]:
- # Measure X stabilizers
- h(logicalQubit.ancx)
- for xi in range(len(logicalQubit.ancx)):
- for di in range(len(logicalQubit.data)):
- if x_stabilizers[xi * len(logicalQubit.data) + di] == 1:
- x.ctrl(logicalQubit.ancx[xi], logicalQubit.data[di])
- h(logicalQubit.ancx)
-
- # Measure Z stabilizers
- for zi in range(len(logicalQubit.ancx)):
- for di in range(len(logicalQubit.data)):
- if z_stabilizers[zi * len(logicalQubit.data) + di] == 1:
- x.ctrl(logicalQubit.data[di], logicalQubit.ancz[zi])
-
- # Get and reset ancillas
- results = mz(logicalQubit.ancz, logicalQubit.ancx)
- reset(logicalQubit.ancx)
- reset(logicalQubit.ancz)
- return results
-
-3. **Implement the Code Class**:
-
- Create a class decorated with :code:`@qec.code` that implements the required interface:
-
- .. code-block:: python
-
- @qec.code('py-steane-example')
- class MySteaneCodeImpl:
- def __init__(self, **kwargs):
- qec.Code.__init__(self, **kwargs)
-
- # Define stabilizer generators
- self.stabilizers = qec.Stabilizers([
- "XXXXIII", "IXXIXXI", "IIXXIXX",
- "ZZZZIII", "IZZIZZI", "IIZZIZZ"
- ])
-
- # Register quantum kernels
- self.operation_encodings = {
- qec.operation.prep0: prep0,
- qec.operation.stabilizer_round: stabilizer
- }
-
- def get_num_data_qubits(self):
- return 7
-
- def get_num_ancilla_x_qubits(self):
- return 3
-
- def get_num_ancilla_z_qubits(self):
- return 3
-
- def get_num_ancilla_qubits(self):
- return 6
-
-4. **Install the Code**:
-
- Install your Python-implemented code using :code:`cudaqx-config`:
-
- .. code-block:: bash
-
- cudaqx-config --install-code my_steane.py
-
-5. **Using the Code**:
-
- The code can now be used like any other CUDA-Q QEC code:
-
- .. code-block:: python
-
- import cudaq_qec as qec
-
- # Create instance of your code
- code = qec.get_code('py-steane-example')
-
- # Use the code for various numerical experiments
-
-Key Points
-^^^^^^^^^^^
-
-* The :code:`@qec.code` decorator takes the name of the code as an argument
-* Operation encodings are registered via the :code:`operation_encodings` dictionary
-* Stabilizer generators are defined using the :code:`qec.Stabilizers` class
-* The code must implement all required methods from the base class interface
-
-
-Using the Code Framework
-^^^^^^^^^^^^^^^^^^^^^^^^^
-
-To use an implemented code:
-
-.. tab:: Python
-
- .. code-block:: python
-
- # Create a code instance
- code = qec.get_code("steane")
-
- # Access stabilizer information
- stabilizers = code.get_stabilizers()
- parity = code.get_parity()
-
- # The code can now be used for various numerical
- # experiments - see section below.
-
-.. tab:: C++
-
- .. code-block:: cpp
-
- // Create a code instance
- auto code = cudaq::qec::get_code("steane");
-
- // Access stabilizer information
- auto stabilizers = code->get_stabilizers();
- auto parity = code->get_parity();
-
- // The code can now be used for various numerical
- // experiments - see section below.
-
-
-Pre-built QEC Codes
--------------------
-
-CUDA-Q QEC provides several well-studied quantum error correction codes out of the box. Here's a detailed overview of each:
-
-Steane Code
-^^^^^^^^^^^
-
-The Steane code is a ``[[7,1,3]]`` CSS (Calderbank-Shor-Steane) code that encodes
-one logical qubit into seven physical qubits with a code distance of 3.
-
-**Key Properties**:
-
-* Data qubits: 7
-* Encoded qubits: 1
-* Code distance: 3
-* Ancilla qubits: 6 (3 for X stabilizers, 3 for Z stabilizers)
-
-**Stabilizer Generators**:
-
-* X-type: ``["XXXXIII", "IXXIXXI", "IIXXIXX"]``
-* Z-type: ``["ZZZZIII", "IZZIZZI", "IIZZIZZ"]``
-
-The Steane code can correct any single-qubit error and detect up to two errors.
-It is particularly notable for being the smallest CSS code that can implement a universal set of transversal gates.
-
-Usage:
-
-.. tab:: Python
-
- .. code-block:: python
-
- import cudaq_qec as qec
-
- # Create Steane code instance
- steane = qec.get_code("steane")
-
-.. tab:: C++
-
- .. code-block:: cpp
-
- auto steane = cudaq::qec::get_code("steane");
-
-Repetition Code
-^^^^^^^^^^^^^^^
-The repetition code is a simple [[n,1,n]] code that protects against
-bit-flip (X) errors by encoding one logical qubit into n physical qubits, where n is the code distance.
-
-**Key Properties**:
-
-* Data qubits: n (distance)
-* Encoded qubits: 1
-* Code distance: n
-* Ancilla qubits: n-1 (all for Z stabilizers)
-
-**Stabilizer Generators**:
-
-* For distance 3: ``["ZZI", "IZZ"]``
-* For distance 5: ``["ZZIII", "IZZII", "IIZZI", "IIIZZ"]``
-
-The repetition code is primarily educational as it can only correct
-X errors. However, it serves as an excellent introduction to QEC concepts.
-
-Usage:
-
-.. tab:: Python
-
- .. code-block:: python
-
- import cudaq_qec as qec
-
- # Create distance-3 repetition code
- code = qec.get_code('repetition', distance=3)
-
- # Access stabilizers
- stabilizers = code.get_stabilizers() # Returns ["ZZI", "IZZ"]
-
-.. tab:: C++
-
- .. code-block:: cpp
-
- auto code = qec::get_code("repetition", {{"distance", 3}});
-
- // Access stabilizers
- auto stabilizers = code->get_stabilizers();
-
-
-Decoder Framework :code:`cudaq::qec::decoder`
-----------------------------------------------
-
-The CUDA-Q QEC decoder framework provides an extensible system for implementing
-quantum error correction decoders through the :code:`cudaq::qec::decoder` base class.
-
-Class Structure
-^^^^^^^^^^^^^^^
-
-The decoder base class defines the core interface for syndrome decoding:
-
-.. code-block:: cpp
-
- class decoder {
- protected:
- std::size_t block_size; // For [n,k] code, this is n
- std::size_t syndrome_size; // For [n,k] code, this is n-k
- tensor H; // Parity check matrix
-
- public:
- struct decoder_result {
- bool converged; // Decoder convergence status
- std::vector result; // Soft error probabilities
- };
-
- virtual decoder_result decode(
- const std::vector& syndrome) = 0;
-
- virtual std::vector decode_batch(
- const std::vector>& syndrome);
- };
-
-Key Components:
-
-* **Parity Check Matrix**: Defines the code structure via :code:`H`
-* **Block Size**: Number of physical qubits in the code
-* **Syndrome Size**: Number of stabilizer measurements
-* **Decoder Result**: Contains convergence status and error probabilities
-* **Multiple Decoding Modes**: Single syndrome or batch processing
-
-Implementing a New Decoder in C++
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-To implement a new decoder:
-
-1. **Create Decoder Class**:
-
-.. code-block:: cpp
-
- class my_decoder : public qec::decoder {
- private:
- // Decoder-specific members
-
- public:
- my_decoder(const tensor& H,
- const heterogeneous_map& params)
- : decoder(H) {
- // Initialize decoder
- }
-
- decoder_result decode(
- const std::vector& syndrome) override {
- // Implement decoding logic
- }
- };
-
-2. **Register Extension Point**:
-
-.. code-block:: cpp
-
- CUDAQ_EXTENSION_CUSTOM_CREATOR_FUNCTION(
- my_decoder,
- static std::unique_ptr create(
- const tensor& H,
- const heterogeneous_map& params) {
- return std::make_unique(H, params);
- }
- )
-
- CUDAQ_REGISTER_TYPE(my_decoder)
-
-Example: Lookup Table Decoder
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Here's a simple lookup table decoder for the Steane code:
-
-.. code-block:: cpp
-
- class single_error_lut : public decoder {
- private:
- std::map single_qubit_err_signatures;
-
- public:
- single_error_lut(const tensor& H,
- const heterogeneous_map& params)
- : decoder(H) {
- // Build lookup table for single-qubit errors
- for (std::size_t qErr = 0; qErr < block_size; qErr++) {
- std::string err_sig(syndrome_size, '0');
- for (std::size_t r = 0; r < syndrome_size; r++) {
- bool syndrome = 0;
- for (std::size_t c = 0; c < block_size; c++)
- syndrome ^= (c != qErr) && H.at({r, c});
- err_sig[r] = syndrome ? '1' : '0';
- }
- single_qubit_err_signatures.insert({err_sig, qErr});
- }
- }
-
- decoder_result decode(
- const std::vector& syndrome) override {
- decoder_result result{false,
- std::vector(block_size, 0.0)};
-
- // Convert syndrome to string
- std::string syndrome_str(syndrome_size, '0');
- for (std::size_t i = 0; i < syndrome_size; i++)
- syndrome_str[i] = (syndrome[i] >= 0.5) ? '1' : '0';
-
- // Lookup error location
- auto it = single_qubit_err_signatures.find(syndrome_str);
- if (it != single_qubit_err_signatures.end()) {
- result.converged = true;
- result.result[it->second] = 1.0;
- }
-
- return result;
- }
- };
-
-Implementing a Decoder in Python
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-CUDA-Q QEC supports implementing decoders in Python using the :code:`@qec.decoder` decorator:
-
-1. **Create Decoder Class**:
-
-.. code-block:: python
-
- @qec.decoder("my_decoder")
- class MyDecoder:
- def __init__(self, H, **kwargs):
- qec.Decoder.__init__(self, H)
- self.H = H
- # Initialize with optional kwargs
-
- def decode(self, syndrome):
- # Create result object
- result = qec.DecoderResult()
-
- # Implement decoding logic
- # ...
-
- # Set results
- result.converged = True
- result.result = [0.0] * self.block_size
-
- return result
-
-2. **Using Custom Parameters**:
-
-.. code-block:: python
-
- # Create decoder with custom parameters
- decoder = qec.get_decoder("my_decoder",
- H=parity_check_matrix,
- custom_param=42)
-
-Key Features
-^^^^^^^^^^^^^
-
-* **Soft Decision Decoding**: Results are probabilities in [0,1]
-* **Batch Processing**: Support for decoding multiple syndromes
-* **Asynchronous Decoding**: Optional async interface for parallel processing
-* **Custom Parameters**: Flexible configuration via heterogeneous_map
-* **Python Integration**: First-class support for Python implementations
-
-Usage Example
-^^^^^^^^^^^^^^
-
-.. tab:: Python
-
- .. code-block:: python
-
- import cudaq_qec as qec
-
- # Get a code instance
- steane = qec.get_code("steane")
-
- # Create decoder with code's parity matrix
- decoder = qec.get_decoder('single_error_lut', steane.get_parity())
-
- # Run stabilizer measurements
- syndromes, dataQubitResults = qec.sample_memory_circuit(steane, numShots=1, numRounds=1)
-
- # Decode a syndrome
- result = decoder.decode(syndromes[0])
- if result.converged:
- print("Error locations:",
- [i for i,p in enumerate(result.result) if p > 0.5])
- # No errors as we did not include a noise model and
- # thus prints:
- # Error locations: []
-
-.. tab:: C++
-
- .. code-block:: cpp
-
- using namespace cudaq;
-
- // Get a code instance
- auto code = qec::get_code("steane");
-
- // Create decoder with code's parity matrix
- auto decoder = qec::get_decoder("single_error_lut",
- code->get_parity());
-
- // Run stabilizer measurements
- auto [syndromes, dataQubitResults] = qec::sample_memory_circuit(*code, /*numShots*/numShots, /*numRounds*/ 1);
-
- // Decode syndrome
- auto result = decoder->decode(syndromes[0]);
-
-
-Pre-built QEC Decoders
-----------------------
-
-CUDA-Q QEC provides pre-built decoders. Here's a detailed overview of each:
-
-Quantum Low-Density Parity-Check Decoder
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The Quantum Low-Density Parity-Check (QLDPC) decoder leverages GPU-accelerated belief propagation (BP) for efficient error correction.
-Since belief propagation is an iterative method which may not converge, decoding can be improved with a second-stage post-processing step. The `nv-qldpc-decoder`
-API provides various post-processing options, which can be selected through its parameters.
-
-The QLDPC decoder `nv-qldpc-decoder` requires a CUDA-Q compatible GPU. See the list below for dependencies and compatibility:
-https://nvidia.github.io/cuda-quantum/latest/using/install/local_installation.html#dependencies-and-compatibility
-
-The decoder is based on the following references:
-
-* https://arxiv.org/pdf/2005.07016
-* https://github.com/quantumgizmos/ldpc
-
-
-Usage:
-
-.. tab:: Python
-
- .. code-block:: python
-
- import cudaq_qec as qec
-
- H_list = [
- [1, 0, 0, 1, 0, 1, 1],
- [0, 1, 0, 1, 1, 0, 1],
- [0, 0, 1, 0, 1, 1, 1]
- ]
-
- H_np = np.array(H_list, dtype=np.uint8)
-
- decoder = qec.get_decoder("nv-qldpc-decoder", H_np)
-
-.. tab:: C++
-
- .. code-block:: cpp
-
- std::size_t block_size = 7;
- std::size_t syndrome_size = 3;
- cudaqx::tensor H;
-
- std::vector H_vec = {1, 0, 0, 1, 0, 1, 1,
- 0, 1, 0, 1, 1, 0, 1,
- 0, 0, 1, 0, 1, 1, 1};
- H.copy(H_vec.data(), {syndrome_size, block_size});
-
- cudaqx::heterogeneous_map nv_custom_args;
- nv_custom_args.insert("use_osd", true);
-
- auto d1 = cudaq::qec::get_decoder("nv-qldpc-decoder", H, nv_custom_args);
-
- // Alternatively, configure the decoder without instantiating a heterogeneous_map
- auto d2 = cudaq::qec::get_decoder("nv-qldpc-decoder", H, {{"use_osd", true}, {"bp_batch_size", 100}});
-
-
-Numerical Experiments
----------------------
-
-CUDA-Q QEC provides utilities for running numerical experiments with quantum error correction codes.
-
-Conventions
-^^^^^^^^^^^
-
-To address vectors of qubits (`cudaq::qvector`), CUDAQ indexing starts from 0, and 0 corresponds
-to the leftmost position when working with pauli strings (`cudaq::spin_op`). For example, applying a pauli X operator
-to qubit 1 out of 7 would be `X_1 = IXIIIII`.
-
-While implementing your own codes and decoders, you are free to follow any convention that is convenient to you. However,
-to interact with the pre-built QEC codes and decoders within this library, the following conventions are used. All of these codes
-are CSS codes, and so we separate :math:`X`-type and :math:`Z`-type errors. For example, an error vector for 3 qubits will
-have 6 entries, 3 bits representing the presence of a bit-flip on each qubit, and 3 bits representing a phase-flip on each qubit.
-An error vector representing a bit-flip on qubit 0, and a phase-flip on qubit 1 would look like `E = 100010`. This means that this
-error vector is just two error vectors (`E_X, E_Z`) concatenated together (`E = E_X | E_Z`).
-
-These errors are detected by stabilizers. :math:`Z`-stabilizers detect :math:`X`-type errors and vice versa. Thus we write our
-CSS parity check matrices as
-
-.. math::
- H_{CSS} = \begin{pmatrix}
- H_Z & 0 \\
- 0 & H_X
- \end{pmatrix},
-
-so that when we generate a syndrome vector by multiplying the parity check matrix by an error vector we get
-
-.. math::
- \begin{align}
- S &= H \cdot E\\
- S_X &= H_Z \cdot E_x\\
- S_Z &= H_X \cdot E_Z.
- \end{align}
-
-This means that for the concatenated syndrome vector `S = S_X | S_Z`, the first part, `S_X`, are syndrome bits triggered by `Z`
-stabilizers detecting `X` errors. This is because the `Z` stabilizers like `ZZI` and `IZZ` anti-commute with `X` errors like
-`IXI`.
-
-The decoder prediction as to what error happened is `D = D_X | D_Z`. A successful error decoding does not require that `D = E`,
-but that `D + E` is not a logical operator. There are a couple ways to check this.
-For bitflip errors, we check that the residual error `R = D_X + E_X` is not `L_X`. Since `X` anticommutes
-with `Z`, we can check that `L_Z(D_X + E_X) = 0`. This is because we just need to check if they have mutual support on an even
-or odd number of qubits. We could also check that `R` is not a stabilizer.
-
-Similar to the parity check matrix, the logical observables are also stored in a matrix as
-
-.. math::
- L = \begin{pmatrix}
- L_Z & 0 \\
- 0 & L_X
- \end{pmatrix},
-
-so that when determining logical errors, we can do matrix multiplication
-
-.. math::
- \begin{align}
- P &= L \cdot R\\
- P_X &= L_Z \cdot R_x\\
- P_Z &= L_X \cdot R_Z.
- \end{align}
-
-Here we're using `P` as this can be stored in a Pauli frame tracker to track observable flips.
-
-Each logical qubit has logical observables associated with it. Depending on what basis the data qubits are measured in, either the
-`X` or `Z` logical observables can be measured. The data qubits which support the logical observable is contained the `qec::code` class as well.
-
-To do a logical `Z(X)` measurement, measure out all of the data qubits in the `Z(X)` basis. Then check support on the appropriate
-`Z(x)` observable.
-
-
-Memory Circuit Experiments
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Memory circuit experiments test a QEC code's ability to preserve quantum information over time by:
-
-1. Preparing an initial logical state
-2. Performing multiple rounds of stabilizer measurements
-3. Measuring data qubits to verify state preservation
-4. Optionally applying noise during the process
-
-Function Variants
-~~~~~~~~~~~~~~~~~
-
-.. tab:: Python
-
- .. code-block:: python
-
- import cudaq
- import cudaq_qec as qec
-
- # Use the stim backend for performance in QEC settings
- cudaq.set_target("stim")
-
- # Get a code instance
- code = qec.get_code("steane")
-
- # Basic memory circuit with |0⟩ state
- syndromes, measurements = qec.sample_memory_circuit(
- code, # QEC code instance
- numShots=1000, # Number of circuit executions
- numRounds=1 # Number of stabilizer rounds
- )
-
- # Memory circuit with custom initial state
- syndromes, measurements = qec.sample_memory_circuit(
- code, # QEC code instance
- op=qec.operation.prep1, # Initial state
- numShots=1000, # Number of shots
- numRounds=1 # Number of rounds
- )
-
- # Memory circuit with noise model
- noise = cudaq.NoiseModel()
- # Configure noise
- noise.add_all_qubit_channel("x", cudaq.Depolarization2(0.01), 1)
- syndromes, measurements = qec.sample_memory_circuit(
- code, # QEC code instance
- numShots=1000, # Number of shots
- numRounds=1, # Number of rounds
- noise=noise # Noise model
- )
-
-.. tab:: C++
-
- .. code-block:: cpp
-
- // Basic memory circuit with |0⟩ state
- auto [syndromes, measurements] = qec::sample_memory_circuit(
- code, // QEC code instance
- numShots, // Number of circuit executions
- numRounds // Number of stabilizer rounds
- );
-
- // Memory circuit with custom initial state
- auto [syndromes, measurements] = qec::sample_memory_circuit(
- code, // QEC code instance
- operation::prep1, // Initial state preparation
- numShots, // Number of circuit executions
- numRounds // Number of stabilizer rounds
- );
-
- // Memory circuit with noise model
- auto noise_model = cudaq::noise_model();
- noise_model.add_channel(...); // Configure noise
- auto [syndromes, measurements] = qec::sample_memory_circuit(
- code, // QEC code instance
- numShots, // Number of circuit executions
- numRounds, // Number of stabilizer rounds
- noise_model // Noise model to apply
- );
-
-Return Values
-~~~~~~~~~~~~~
-
-The functions return a tuple containing:
-
-1. **Syndrome Measurements** (:code:`tensor`):
-
- * Shape: :code:`(num_shots, num_rounds * syndrome_size)`
- * Contains stabilizer measurement results
- * Values are 0 or 1 representing measurement outcomes
-
-2. **Data Measurements** (:code:`tensor`):
-
- * Shape: :code:`(num_shots, block_size)`
- * Contains final data qubit measurements
- * Used to verify logical state preservation
-
-Example Usage
-~~~~~~~~~~~~~
-
-Example of running a memory experiment:
-
-.. tab:: Python
-
- .. code-block:: python
-
- import cudaq
- import cudaq_qec as qec
-
- # Use the stim backend for performance in QEC settings
- cudaq.set_target("stim")
-
- # Create code and decoder
- code = qec.get_code('steane')
- decoder = qec.get_decoder('single_error_lut',
- code.get_parity())
-
- # Configure noise
- noise = cudaq.NoiseModel()
- noise.add_all_qubit_channel("x", cudaq.Depolarization2(0.01), 1)
-
- # Run memory experiment
- syndromes, measurements = qec.sample_memory_circuit(
- code,
- op=qec.operation.prep0,
- numShots=1000,
- numRounds=10,
- noise=noise
- )
-
- # Analyze results
- for shot in range(1000):
- # Get syndrome for this shot
- syndrome = syndromes[shot].tolist()
-
- # Decode syndrome
- result = decoder.decode(syndrome)
- if result.converged:
- # Process correction
- pass
-
-.. tab:: C++
-
- .. code-block:: cpp
-
- // Compile and run with:
- // nvq++ --enable-mlir --target=stim -lcudaq-qec example.cpp
- // ./a.out
-
- #include "cudaq.h"
- #include "cudaq/qec/decoder.h"
- #include "cudaq/qec/experiments.h"
- #include "cudaq/qec/noise_model.h"
-
- int main(){
- // Create a Steane code instance
- auto code = cudaq::qec::get_code("steane");
-
- // Configure noise model
- cudaq::noise_model noise;
- noise.add_all_qubit_channel("x", cudaq::depolarization2(0.1),
- /*num_controls=*/1);
-
- // Run memory experiment
- auto [syndromes, data] = cudaq::qec::sample_memory_circuit(
- *code, // Code instance
- cudaq::qec::operation::prep0, // Prepare |0⟩ state
- 1000, // 1000 shots
- 1, // 1 rounds
- noise // Apply noise
- );
-
- // Analyze results
- auto decoder = cudaq::qec::get_decoder("single_error_lut", code->get_parity());
- for (std::size_t shot = 0; shot < 1000; shot++) {
- // Get syndrome for this shot
- std::vector syndrome(syndromes.shape()[1]);
- for (std::size_t i = 0; i < syndrome.size(); i++)
- syndrome[i] = syndromes.at({shot, i});
-
- // Decode syndrome
- auto [converged, v_result] = decoder->decode(syndrome);
- // Process correction
- // ...
- }
- }
-
-Additional Noise Models
-~~~~~~~~~~~~~~~~~~~~~~~
-
-.. tab:: Python
-
- .. code-block:: python
-
- noise = cudaq.NoiseModel()
-
- # Add multiple error channels
- noise.add_all_qubit_channel('h', cudaq.BitFlipChannel(0.001))
-
- # Specify two qubit errors
- noise.add_all_qubit_channel("x", cudaq.Depolarization2(p), 1)
-
-.. tab:: C++
-
- .. code-block:: cpp
-
- cudaq::noise_model noise;
-
- // Add multiple error channels
- noise.add_all_qubit_channel(
- "x", cudaq::bit_flip_channel(/*probability*/ 0.01));
-
- // Specify two qubit errors
- noise.add_all_qubit_channel(
- "x", cudaq::depolarization2(/*probability*/ 0.01),
- /*numControls*/ 1);
-
diff --git a/docs/sphinx/components/solvers/introduction.rst b/docs/sphinx/components/solvers/introduction.rst
deleted file mode 100644
index 3bd0c869..00000000
--- a/docs/sphinx/components/solvers/introduction.rst
+++ /dev/null
@@ -1,553 +0,0 @@
-CUDA-Q Solvers Library
-=======================
-
-Overview
---------
-The CUDA-Q Solvers library provides high-level quantum-classical hybrid
-algorithms and supporting infrastructure for quantum chemistry and
-optimization problems. It features implementations of VQE, ADAPT-VQE,
-and supporting utilities for Hamiltonian generation and operator pool management.
-
-Core Components
------------------
-
-1. **Variational Algorithms**:
-
- * Variational Quantum Eigensolver (VQE)
- * Adaptive Derivative-Assembled Pseudo-Trotter VQE (ADAPT-VQE)
-
-2. **Quantum Chemistry Tools**:
-
- * Molecular Hamiltonian Generation
- * One-Particle Operator Creation
- * Geometry Management
-
-3. **Operator Infrastructure**:
-
- * Operator Pool Generation
- * Fermion-to-Qubit Mappings
- * Gradient Computation
-
-Operator Infrastructure
-------------------------
-
-Molecular Hamiltonian Options
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The :code:`molecule_options` structure provides extensive configuration for molecular calculations in CUDA-QX.
-
-+---------------------+---------------+------------------+------------------------------------------+
-| Option | Type | Default | Description |
-+=====================+===============+==================+==========================================+
-| driver | string | "RESTPySCFDriver"| Quantum chemistry driver backend |
-+---------------------+---------------+------------------+------------------------------------------+
-| fermion_to_spin | string | "jordan_wigner" | Fermionic to qubit operator mapping |
-+---------------------+---------------+------------------+------------------------------------------+
-| type | string | "gas_phase" | Type of molecular system |
-+---------------------+---------------+------------------+------------------------------------------+
-| symmetry | bool | false | Use molecular symmetry |
-+---------------------+---------------+------------------+------------------------------------------+
-| memory | double | 4000.0 | Memory allocation (MB) |
-+---------------------+---------------+------------------+------------------------------------------+
-| cycles | size_t | 100 | Maximum SCF cycles |
-+---------------------+---------------+------------------+------------------------------------------+
-| initguess | string | "minao" | Initial SCF guess method |
-+---------------------+---------------+------------------+------------------------------------------+
-| UR | bool | false | Enable unrestricted calculations |
-+---------------------+---------------+------------------+------------------------------------------+
-| nele_cas | optional | nullopt | Number of electrons in active space |
-| | | | |
-+---------------------+---------------+------------------+------------------------------------------+
-| norb_cas | optional | nullopt | Number of spatial orbitals in |
-| | | | in active space |
-+---------------------+---------------+------------------+------------------------------------------+
-| MP2 | bool | false | Enable MP2 calculations |
-+---------------------+---------------+------------------+------------------------------------------+
-| natorb | bool | false | Use natural orbitals |
-+---------------------+---------------+------------------+------------------------------------------+
-| casci | bool | false | Perform CASCI calculations |
-+---------------------+---------------+------------------+------------------------------------------+
-| ccsd | bool | false | Perform CCSD calculations |
-+---------------------+---------------+------------------+------------------------------------------+
-| casscf | bool | false | Perform CASSCF calculations |
-+---------------------+---------------+------------------+------------------------------------------+
-| integrals_natorb | bool | false | Use natural orbitals for integrals |
-+---------------------+---------------+------------------+------------------------------------------+
-| integrals_casscf | bool | false | Use CASSCF orbitals for integrals |
-+---------------------+---------------+------------------+------------------------------------------+
-| potfile | optional | nullopt | Path to external potential file |
-| | | | |
-+---------------------+---------------+------------------+------------------------------------------+
-| verbose | bool | false | Enable detailed output logging |
-+---------------------+---------------+------------------+------------------------------------------+
-
-Example Usage
-^^^^^^^^^^^^^
-
-.. tab:: Python
-
- .. code-block:: python
-
- import cudaq_solvers as solvers
-
- # Configure molecular options
- options = {
- 'fermion_to_spin': 'jordan_wigner',
- 'casci': True,
- 'memory': 8000.0,
- 'verbose': True
- }
-
- # Create molecular Hamiltonian
- molecule = solvers.create_molecule(
- geometry=[('H', (0., 0., 0.)),
- ('H', (0., 0., 0.7474))],
- basis='sto-3g',
- spin=0,
- charge=0,
- **options
- )
-
-.. tab:: C++
-
- .. code-block:: cpp
-
- using namespace cudaq::solvers;
-
- // Configure molecular options
- molecule_options options;
- options.fermion_to_spin = "jordan_wigner";
- options.casci = true;
- options.memory = 8000.0;
- options.verbose = true;
-
- // Create molecular geometry
- auto geometry = molecular_geometry({
- atom{"H", {0.0, 0.0, 0.0}},
- atom{"H", {0.0, 0.0, 0.7474}}
- });
-
- // Create molecular Hamiltonian
- auto molecule = create_molecule(
- geometry,
- "sto-3g",
- 0, // spin
- 0, // charge
- options
- );
-
-Variational Quantum Eigensolver (VQE)
---------------------------------------
-
-The VQE algorithm finds the minimum eigenvalue of a
-Hamiltonian using a hybrid quantum-classical approach.
-
-VQE Examples
--------------
-
-The VQE implementation supports multiple usage patterns with different levels of customization.
-
-Basic Usage
-^^^^^^^^^^^
-
-.. tab:: Python
-
- .. code-block:: python
-
- import cudaq
- from cudaq import spin
- import cudaq_solvers as solvers
-
- # Define quantum kernel (ansatz)
- @cudaq.kernel
- def ansatz(theta: float):
- q = cudaq.qvector(2)
- x(q[0])
- ry(theta, q[1])
- x.ctrl(q[1], q[0])
-
- # Define Hamiltonian
- H = 5.907 - 2.1433 * spin.x(0) * spin.x(1) - \
- 2.1433 * spin.y(0) * spin.y(1) + \
- 0.21829 * spin.z(0) - 6.125 * spin.z(1)
-
- # Run VQE with defaults (cobyla optimizer)
- energy, parameters, data = solvers.vqe(
- lambda thetas: ansatz(thetas[0]),
- H,
- initial_parameters=[0.0],
- verbose=True
- )
- print(f"Ground state energy: {energy}")
-
-.. tab:: C++
-
- .. code-block:: cpp
-
- #include "cudaq.h"
-
- #include "cudaq/solvers/operators.h"
- #include "cudaq/solvers/vqe.h"
-
- // Define quantum kernel
- struct ansatz {
- void operator()(std::vector theta) __qpu__ {
- cudaq::qvector q(2);
- x(q[0]);
- ry(theta[0], q[1]);
- x(q[1], q[0]);
- }
- };
-
- // Create Hamiltonian
- auto H = 5.907 - 2.1433 * x(0) * x(1) -
- 2.1433 * y(0) * y(1) +
- 0.21829 * z(0) - 6.125 * z(1);
-
- // Run VQE with default optimizer
- auto result = cudaq::solvers::vqe(
- ansatz{},
- H,
- {0.0}, // Initial parameters
- {{"verbose", true}}
- );
- printf("Ground state energy: %lf\n", result.energy);
-
-Custom Optimization
-^^^^^^^^^^^^^^^^^^^
-
-.. tab:: Python
-
- .. code-block:: python
-
- # Using L-BFGS-B optimizer with parameter-shift gradients
- energy, parameters, data = solvers.vqe(
- lambda thetas: ansatz(thetas[0]),
- H,
- initial_parameters=[0.0],
- optimizer='lbfgs',
- gradient='parameter_shift',
- verbose=True
- )
-
- # Using SciPy optimizer directly
- from scipy.optimize import minimize
-
- def callback(xk):
- exp_val = cudaq.observe(ansatz, H, xk[0]).expectation()
- print(f"Energy at iteration: {exp_val}")
-
- energy, parameters, data = solvers.vqe(
- lambda thetas: ansatz(thetas[0]),
- H,
- initial_parameters=[0.0],
- optimizer=minimize,
- callback=callback,
- method='L-BFGS-B',
- jac='3-point',
- tol=1e-4,
- options={'disp': True}
- )
-
-.. tab:: C++
-
- .. code-block:: cpp
-
- // Using L-BFGS optimizer with central difference gradients
- auto optimizer = cudaq::optim::optimizer::get("lbfgs");
- auto gradient = cudaq::observe_gradient::get(
- "central_difference",
- ansatz{},
- H
- );
-
- auto result = cudaq::solvers::vqe(
- ansatz{},
- H,
- *optimizer,
- *gradient,
- {0.0}, // Initial parameters
- {{"verbose", true}}
- );
-
-Shot-based Simulation
-^^^^^^^^^^^^^^^^^^^^^
-
-.. tab:: Python
-
- .. code-block:: python
-
- # Run VQE with finite shots
- energy, parameters, data = solvers.vqe(
- lambda thetas: ansatz(thetas[0]),
- H,
- initial_parameters=[0.0],
- shots=10000,
- max_iterations=10,
- verbose=True
- )
-
- # Analyze measurement data
- for iteration in data:
- counts = iteration.result.counts()
- print("\nMeasurement counts:")
- print("XX basis:", counts.get_register_counts('XX'))
- print("YY basis:", counts.get_register_counts('YY'))
- print("ZI basis:", counts.get_register_counts('ZI'))
- print("IZ basis:", counts.get_register_counts('IZ'))
-
-.. tab:: C++
-
- .. code-block:: cpp
-
- // Run VQE with finite shots
- auto optimizer = cudaq::optim::optimizer::get("lbfgs");
- auto gradient = cudaq::observe_gradient::get(
- "parameter_shift",
- ansatz{},
- H
- );
-
- auto result = cudaq::solvers::vqe(
- ansatz{},
- H,
- *optimizer,
- *gradient,
- {0.0},
- {
- {"shots", 10000},
- {"verbose", true}
- }
- );
-
- // Analyze measurement data
- for (auto& iteration : result.iteration_data) {
- std::cout << "Iteration type: "
- << (iteration.type == observe_execution_type::gradient
- ? "gradient" : "function")
- << "\n";
- iteration.result.dump();
- }
-
-ADAPT-VQE
----------
-
-The Adaptive Derivative-Assembled Pseudo-Trotter Variational Quantum Eigensolver (ADAPT-VQE)
-is an advanced quantum algorithm that dynamically builds a problem-tailored ansatz
-based on operator gradients.
-
-Key Features
-^^^^^^^^^^^^
-
-* Dynamic ansatz construction
-* Gradient-based operator selection
-* Automatic termination criteria
-* Support for various operator pools
-* Compatible with multiple optimizers
-
-Basic Usage
-^^^^^^^^^^^^
-
-.. tab:: Python
-
- .. code-block:: python
-
- import cudaq
- import cudaq_solvers as solvers
-
- # Define molecular geometry
- geometry = [
- ('H', (0., 0., 0.)),
- ('H', (0., 0., 0.7474))
- ]
-
- # Create molecular Hamiltonian
- molecule = solvers.create_molecule(
- geometry,
- 'sto-3g',
- spin=0,
- charge=0,
- casci=True
- )
-
- # Generate operator pool
- operators = solvers.get_operator_pool(
- "spin_complement_gsd",
- num_orbitals=molecule.n_orbitals
- )
-
- numElectrons = molecule.n_electrons
-
- # Define initial state preparation
- @cudaq.kernel
- def initial_state(q: cudaq.qview):
- for i in range(numElectrons):
- x(q[i])
-
- # Run ADAPT-VQE
- energy, parameters, operators = solvers.adapt_vqe(
- initial_state,
- molecule.hamiltonian,
- operators,
- verbose=True
- )
- print(f"Ground state energy: {energy}")
-
-.. tab:: C++
-
- .. code-block:: cpp
-
- #include "cudaq/solvers/adapt.h"
- #include "cudaq/solvers/operators.h"
-
- // compile with
- // nvq++ adaptEx.cpp --enable-mlir -lcudaq-solvers
- // ./a.out
-
- int main() {
- // Define initial state preparation
- auto initial_state = [](cudaq::qvector<>& q) __qpu__ {
- for (std::size_t i = 0; i < 2; ++i)
- x(q[i]);
- };
-
- // Create Hamiltonian (H2 molecule example)
- cudaq::solvers::molecular_geometry geometry{{"H", {0., 0., 0.}},
- {"H", {0., 0., .7474}}};
- auto molecule = cudaq::solvers::create_molecule(
- geometry, "sto-3g", 0, 0, {.casci = true, .verbose = true});
-
- auto h = molecule.hamiltonian;
-
- // Generate operator pool
- auto operators = cudaq::solvers::get_operator_pool(
- "spin_complement_gsd", {
- {"num-orbitals", h.num_qubits() / 2}
- });
-
- // Run ADAPT-VQE
- auto [energy, parameters, selected_ops] =
- cudaq::solvers::adapt_vqe(
- initial_state,
- h,
- operators,
- {
- {"grad_norm_tolerance", 1e-3},
- {"verbose", true}
- }
- );
- }
-
-Advanced Usage
-^^^^^^^^^^^^^^^
-
-Custom Optimization Settings
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. tab:: Python
-
- .. code-block:: python
-
- # Using L-BFGS-B optimizer with central difference gradients
- energy, parameters, operators = solvers.adapt_vqe(
- initial_state,
- molecule.hamiltonian,
- operators,
- optimizer='lbfgs',
- gradient='central_difference',
- verbose=True
- )
-
- # Using SciPy optimizer directly
- from scipy.optimize import minimize
- energy, parameters, operators = solvers.adapt_vqe(
- initial_state,
- molecule.hamiltonian,
- operators,
- optimizer=minimize,
- method='L-BFGS-B',
- jac='3-point',
- tol=1e-8,
- options={'disp': True}
- )
-
-.. tab:: C++
-
- .. code-block:: cpp
-
- // Using L-BFGS optimizer with central difference gradients
- auto optimizer = cudaq::optim::optimizer::get("lbfgs");
- auto [energy, parameters, operators] =
- cudaq::solvers::adapt_vqe(
- initial_state{},
- h,
- operators,
- *optimizer,
- "central_difference",
- {
- {"grad_norm_tolerance", 1e-3},
- {"verbose", true}
- }
- );
-
-Available Operator Pools
-^^^^^^^^^^^^^^^^^^^^^^^^^
-
-CUDA-QX provides several pre-built operator pools for ADAPT-VQE:
-
-* **spin_complement_gsd**: Spin-complemented generalized singles and doubles
-* **uccsd**: UCCSD operators
-* **qaoa**: QAOA mixer excitation operators
-
-.. code-block:: python
-
- # Generate different operator pools
- gsd_ops = solvers.get_operator_pool(
- "spin_complement_gsd",
- num_orbitals=molecule.n_orbitals
- )
-
- uccsd_ops = solvers.get_operator_pool(
- "uccsd",
- num_orbitals=molecule.n_orbitals,
- num_electrons=molecule.n_electrons
- )
-
-Algorithm Parameters
-^^^^^^^^^^^^^^^^^^^^^^
-
-ADAPT-VQE supports various configuration options:
-
-* **grad_norm_tolerance**: Convergence threshold for operator gradients
-* **max_iterations**: Maximum number of ADAPT iterations
-* **verbose**: Enable detailed output
-* **shots**: Number of measurements for shot-based simulation
-
-.. code-block:: python
-
- energy, parameters, operators = solvers.adapt_vqe(
- initial_state,
- hamiltonian,
- operators,
- grad_norm_tolerance=1e-3,
- max_iterations=20,
- verbose=True,
- shots=10000
- )
-
-Results Analysis
-^^^^^^^^^^^^^^^^^
-
-The algorithm returns three components:
-
-1. **energy**: Final ground state energy
-2. **parameters**: Optimized parameters for each selected operator
-3. **operators**: List of selected operators in order of application
-
-.. code-block:: python
-
- # Analyze results
- print(f"Final energy: {energy}")
- print("\nSelected operators and parameters:")
- for param, op in zip(parameters, operators):
- print(f"θ = {param:.6f} : {op}")
\ No newline at end of file
diff --git a/docs/sphinx/conf.py.in b/docs/sphinx/conf.py.in
deleted file mode 100644
index 71560a38..00000000
--- a/docs/sphinx/conf.py.in
+++ /dev/null
@@ -1,212 +0,0 @@
-# ============================================================================ #
-# Copyright (c) 2024 - 2025 NVIDIA Corporation & Affiliates. #
-# All rights reserved. #
-# #
-# This source code and the accompanying materials are made available under #
-# the terms of the Apache License 2.0 which accompanies this distribution. #
-# ============================================================================ #
-
-# Configuration file for the Sphinx documentation builder.
-#
-# This file only contains a selection of the most common options. For a full
-# list see the documentation:
-# https://www.sphinx-doc.org/en/master/usage/configuration.html
-
-# -- Path setup --------------------------------------------------------------
-
-# If extensions (or modules to document with autodoc) are in another directory,
-# add these directories to sys.path here. If the directory is relative to the
-# documentation root, use os.path.abspath to make it absolute, like shown here.
-
-import os
-import sys
-
-sys.path.insert(0, os.path.abspath('@CUDAQ_INSTALL_DIR@'))
-sys.path.insert(0, os.path.abspath('@CMAKE_BINARY_DIR@/python'))
-
-# -- Project information -----------------------------------------------------
-
-project = 'NVIDIA CUDA-QX'
-copyright = '2025, NVIDIA Corporation & Affiliates'
-author = 'NVIDIA Corporation & Affiliates'
-
-# The version info for the project you're documenting, acts as replacement for
-# |version| used in various places throughout the docs.
-
-# The short X.Y version.
-version = os.getenv("CUDAQX_VERSION", "latest")
-
-# -- General configuration ---------------------------------------------------
-
-# Add any Sphinx extension module names here, as strings. They can be
-# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
-# ones.
-extensions = [
- # 'sphinx.ext.imgmath',
- 'sphinx.ext.ifconfig',
- 'sphinx.ext.autodoc', # to get documentation from python doc comments
- 'sphinx.ext.autosummary',
- 'sphinx.ext.autosectionlabel',
- 'sphinx.ext.doctest', # test example codes in docs
- 'sphinx.ext.extlinks',
- 'sphinx.ext.intersphinx',
- 'sphinx.ext.mathjax',
- 'sphinx.ext.napoleon', # support google/numpy style docstrings
- #'sphinx.ext.linkcode',
- 'sphinx_reredirects',
- 'breathe',
- 'enum_tools.autoenum', # for pretty-print Python enums
- 'myst_parser', # for including markdown files
- 'sphinx_inline_tabs', # showing code blocks in multiple languages
- 'nbsphinx', # for supporting jupyter notebooks
- 'sphinx_copybutton', # allows for copy/paste of code cells
- "sphinx_gallery.load_style",
- "IPython.sphinxext.ipython_console_highlighting",
-]
-
-nbsphinx_allow_errors = False
-nbsphinx_thumbnails = {
- # Default thumbnail if the notebook does not define a cell tag to specify the thumbnail.
- # See also: https://nbsphinx.readthedocs.io/en/latest/subdir/gallery.html
- '**': '@SPHINX_SOURCE@/_static/cuda_quantum_icon.svg'
-}
-
-imgmath_latex_preamble = r'\usepackage{braket}'
-
-imgmath_image_format = 'svg'
-imgmath_font_size = 14
-#imgmath_dvipng_args = ['-gamma', '1.5', '-D', '110', '-bg', 'Transparent']
-
-# Add any paths that contain templates here, relative to this directory.
-templates_path = ['@SPHINX_SOURCE@/_templates']
-
-# The suffix(es) of source filenames.
-# You can specify multiple suffix as a list of string:
-source_suffix = {
- '.rst': 'restructuredtext',
- '.md': 'markdown',
-}
-
-# The master toctree document.
-master_doc = 'index'
-
-# List of patterns, relative to source directory, that match files and
-# directories to ignore when looking for source files.
-# This pattern also affects html_static_path and html_extra_path.
-exclude_patterns = ['_templates']
-
-# The reST default role (used for this markup: `text`) to use for all documents.
-default_role = 'code' # NOTE: the following may be a better choice to error on the side of flagging anything that is referenced but but not declared
-#default_role = 'cpp:any' # see https://www.sphinx-doc.org/en/master/usage/restructuredtext/domains.html#cross-referencing
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'lightbulb'
-
-# autosummary is buggy: this must be py instead of cpp so that the domain setting
-# can be propagated to the autogen'd rst files.
-# primary_domain = 'py'
-
-# -- Options for HTML output -------------------------------------------------
-
-# The theme to use for HTML and HTML Help pages. See the documentation for
-# a list of builtin themes.
-
-html_theme = 'sphinx_rtd_theme'
-
-# Theme options are theme-specific and customize the look and feel of a theme
-# further. For a list of options available for each theme, see the
-# documentation.
-html_theme_options = {
- "collapse_navigation": False,
- "sticky_navigation": False,
- "prev_next_buttons_location": "both",
- "style_nav_header_background":
- "#76b900" # Set upper left search bar to NVIDIA green
-}
-
-html_css_files = ['@SPHINX_SOURCE@/_static/cudaq_override.css']
-
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['@SPHINX_SOURCE@/_static']
-
-# Output file base name for HTML help builder.
-htmlhelp_basename = 'cudaqxDoc'
-
-# A table of string replacements to apply to docs. These strings are unnecessary
-# implementation details that add noise to the documentation.
-doc_replacements = (
- ('_pycudaqx_qec_the_suffix_matters_cudaq_qec.qecrt.', ''),
- ('mlir._mlir_libs._quakeDialects.cudaq_runtime.', ''),
-)
-
-def fix_string(input):
- """Fixes a string by applying the replacements in `doc_replacements`"""
- if not isinstance(input, str):
- return input
- for old, new in doc_replacements:
- input = input.replace(old, new)
- return input
-
-def process_signature(app, what, name, obj, options, signature, return_annotation):
- return (fix_string(signature), fix_string(return_annotation))
-
-def process_docstring(app, what, name, obj, options, lines):
- for i, line in enumerate(lines):
- lines[i] = fix_string(line)
-
-def setup(app):
- app.connect('autodoc-process-signature', process_signature)
- app.connect('autodoc-process-docstring', process_docstring)
- app.add_css_file('cudaq_override.css')
-
-
-# -- Options for BREATHE -------------------------------------------------
-
-breathe_default_project = "cudaqx"
-
-breathe_show_enumvalue_initializer = True
-
-# -- Other options -------------------------------------------------
-
-autosummary_generate = True
-
-intersphinx_mapping = {
- 'python': ('https://docs.python.org/3/', None),
- 'numpy': ('https://numpy.org/doc/stable/', None),
- 'cudaq': ('https://nvidia.github.io/cuda-quantum/latest', None)
-}
-
-redirects = {"versions": "../latest/releases.html"}
-
-nitpick_ignore = [
- ('cpp:identifier', 'pid_t'),
- ('cpp:identifier', 'uint8_t'),
- ('cpp:identifier', 'details::tensor_impl::scalar_type'),
- ('cpp:identifier', 'cudaqx'),
- ('cpp:identifier', 'size_t'),
- ('cpp:identifier', 'details'),
- ('cpp:identifier', 'spin_op'),
- ('cpp:identifier', 'heterogeneous_map'),
- ('cpp:identifier', 'cudaq::qkernel&)>'),
- ('cpp:identifier', 'cudaq::qkernel'),
- ('cpp:identifier', 'cudaq::qkernel'),
- ('cpp:identifier',
- 'cudaq::qkernel(patch, const std::vector&, const std::vector&)>'
- ),
- ('cpp:identifier', 'cudaq::qvector<>'),
- ('cpp:identifier', 'cudaq::qview<>'),
- ('cpp:identifier', 'cudaq::measure_result'),
- ('py:class', 'SpinOperator'),
- ('py:class', 'numpy.int32'),
- ('py:class', 'numpy.uint8'),
- ('py:class', 'cudaq.mlir._mlir_libs._quakeDialects.cudaq_runtime.qview')
-]
-
-napoleon_google_docstring = True
-napoleon_numpy_docstring = False
-autosectionlabel_prefix_document = True
-autosectionlabel_maxdepth = 2
-copybutton_copy_empty_lines = False
-pybind11_compatibility = True
diff --git a/docs/sphinx/examples/qec/cpp/circuit_level_noise.cpp b/docs/sphinx/examples/qec/cpp/circuit_level_noise.cpp
deleted file mode 100644
index bf79984c..00000000
--- a/docs/sphinx/examples/qec/cpp/circuit_level_noise.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2024 - 2025 NVIDIA Corporation & Affiliates. *
- * All rights reserved. *
- * *
- * This source code and the accompanying materials are made available under *
- * the terms of the Apache License 2.0 which accompanies this distribution. *
- ******************************************************************************/
-// [Begin Documentation]
-// Compile and run with:
-// nvq++ --enable-mlir --target=stim -lcudaq-qec circuit_level_noise.cpp
-// ./a.out
-
-#include "cudaq.h"
-#include "cudaq/qec/decoder.h"
-#include "cudaq/qec/experiments.h"
-#include "cudaq/qec/noise_model.h"
-
-int main() {
- // Choose a QEC code
- auto steane = cudaq::qec::get_code("steane");
-
- // Access the parity check matrix
- auto H = steane->get_parity();
- std::cout << "H:\n";
- H.dump();
-
- // Access the logical observables
- auto observables = steane->get_pauli_observables_matrix();
- auto Lz = steane->get_observables_z();
-
- // Data qubits the logical Z observable is supported on
- std::cout << "Lz:\n";
- Lz.dump();
-
- // Observables are stacked as Z over X for mat-vec multiplication
- std::cout << "Obs:\n";
- observables.dump();
-
- // How many shots to run the experiment
- int nShots = 3;
- // For each shot, how many rounds of stabilizer measurements
- int nRounds = 4;
-
- // can set seed for reproducibility
- // cudaq::set_random_seed(1337);
- cudaq::noise_model noise;
-
- // Add a depolarization noise channel after each cx gate
- noise.add_all_qubit_channel("x", cudaq::depolarization2(/*probability*/ 0.01),
- /*numControls*/ 1);
-
- // Perform a noisy z-basis memory circuit experiment
- auto [syndromes, data] = cudaq::qec::sample_memory_circuit(
- *steane, cudaq::qec::operation::prep0, nShots, nRounds, noise);
-
- // With noise, many syndromes will flip each QEC cycle, these are the
- // syndrome differences from the previous cycle.
- std::cout << "syndromes:\n";
- syndromes.dump();
-
- // With noise, Lz will sometimes be flipped
- std::cout << "data:\n";
- data.dump();
-
- // Use z-measurements on data qubits to determine the logical mz
- // In an x-basis experiment, use Lx.
- auto logical_mz = Lz.dot(data.transpose()) % 2;
- std::cout << "logical_mz each shot:\n";
- logical_mz.dump();
-
- // Select a decoder
- auto decoder = cudaq::qec::get_decoder("single_error_lut", H);
-
- // Initialize a pauli_frame to track the logical errors
- cudaqx::tensor pauli_frame({observables.shape()[0]});
-
- // Start a loop to count the number of logical errors
- size_t numLerrors = 0;
- for (size_t shot = 0; shot < nShots; ++shot) {
- std::cout << "shot: " << shot << "\n";
-
- for (size_t round = 0; round < nRounds; ++round) {
- std::cout << "round: " << round << "\n";
-
- // Access one row of the syndrome tensor
- size_t count = shot * nRounds + round;
- size_t stride = syndromes.shape()[1];
- cudaqx::tensor syndrome({stride});
- syndrome.borrow(syndromes.data() + stride * count);
- std::cout << "syndrome:\n";
- syndrome.dump();
-
- // Decode the syndrome
- auto [converged, v_result] = decoder->decode(syndrome);
- cudaqx::tensor result_tensor;
- cudaq::qec::convert_vec_soft_to_tensor_hard(v_result, result_tensor);
- std::cout << "decode result:\n";
- result_tensor.dump();
-
- // See if the decoded result anti-commutes with observables
- auto decoded_observables = observables.dot(result_tensor);
- std::cout << "decoded observable:\n";
- decoded_observables.dump();
-
- // update from previous stabilizer round
- pauli_frame = (pauli_frame + decoded_observables) % 2;
- std::cout << "pauli frame:\n";
- pauli_frame.dump();
- }
-
- // prep0 means we expected to measure out 0.
- uint8_t expected_mz = 0;
- // Apply the pauli frame correction to our logical measurement
- uint8_t corrected_mz = (logical_mz.at({0, shot}) + pauli_frame.at({0})) % 2;
-
- // Check if Logical_mz + pauli_frame_X = 0?
- std::cout << "Corrected readout: " << +corrected_mz << "\n";
- std::cout << "Expected readout: " << +expected_mz << "\n";
- if (corrected_mz != expected_mz)
- numLerrors++;
- std::cout << "\n";
- }
-
- std::cout << "numLogicalErrors: " << numLerrors << "\n";
-}
diff --git a/docs/sphinx/examples/qec/cpp/code_capacity_noise.cpp b/docs/sphinx/examples/qec/cpp/code_capacity_noise.cpp
deleted file mode 100644
index fbe89491..00000000
--- a/docs/sphinx/examples/qec/cpp/code_capacity_noise.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2024 NVIDIA Corporation & Affiliates. *
- * All rights reserved. *
- * *
- * This source code and the accompanying materials are made available under *
- * the terms of the Apache License 2.0 which accompanies this distribution. *
- ******************************************************************************/
-// [Begin Documentation]
-// This example shows the primary cudaq::qec types:
-// decoder, code
-//
-// Compile and run with
-// nvq++ --enable-mlir --target=stim -lcudaq-qec code_capacity_noise.cpp
-// ./a.out
-
-#include
-#include
-#include
-
-#include "cudaq.h"
-#include "cudaq/qec/decoder.h"
-#include "cudaq/qec/experiments.h"
-
-int main() {
- auto steane = cudaq::qec::get_code("steane");
- auto Hz = steane->get_parity_z();
- std::vector t_shape = Hz.shape();
-
- std::cout << "Hz.shape():\n";
- for (size_t elem : t_shape)
- std::cout << elem << " ";
- std::cout << "\n";
-
- std::cout << "Hz:\n";
- Hz.dump();
-
- auto Lz = steane->get_observables_x();
- std::cout << "Lz:\n";
- Lz.dump();
-
- double p = 0.2;
- size_t nShots = 5;
- auto lut_decoder = cudaq::qec::get_decoder("single_error_lut", Hz);
-
- std::cout << "nShots: " << nShots << "\n";
-
- // May want a order-2 tensor of syndromes
- // access tensor by stride to write in an entire syndrome
- cudaqx::tensor syndrome({Hz.shape()[0]});
-
- int nErrors = 0;
- for (size_t shot = 0; shot < nShots; ++shot) {
- std::cout << "shot: " << shot << "\n";
- auto shot_data = cudaq::qec::generate_random_bit_flips(Hz.shape()[1], p);
- std::cout << "shot data\n";
- shot_data.dump();
-
- auto observable_z_data = Lz.dot(shot_data);
- observable_z_data = observable_z_data % 2;
- std::cout << "Data Lz state:\n";
- observable_z_data.dump();
-
- auto syndrome = Hz.dot(shot_data);
- syndrome = syndrome % 2;
- std::cout << "syndrome:\n";
- syndrome.dump();
-
- auto [converged, v_result] = lut_decoder->decode(syndrome);
- cudaqx::tensor result_tensor;
- // v_result is a std::vector, of soft information. We'll convert
- // this to hard information and store as a tensor.
- cudaq::qec::convert_vec_soft_to_tensor_hard(v_result, result_tensor);
- std::cout << "decode result:\n";
- result_tensor.dump();
-
- // check observable result
- auto decoded_observable_z = Lz.dot(result_tensor);
- std::cout << "decoded observable:\n";
- decoded_observable_z.dump();
-
- // check how many observable operators were decoded correctly
- // observable_z_data == decoded_observable_z This maps onto element wise
- // addition (mod 2)
- auto observable_flips = decoded_observable_z + observable_z_data;
- observable_flips = observable_flips % 2;
- std::cout << "Logical errors:\n";
- observable_flips.dump();
- std::cout << "\n";
-
- // shot counts as a observable error unless all observables are correct
- if (observable_flips.any()) {
- nErrors++;
- }
- }
- std::cout << "Total logical errors: " << nErrors << "\n";
-
- // Full data gen in function call
- auto [syn, data] = cudaq::qec::sample_code_capacity(Hz, nShots, p);
- std::cout << "Numerical experiment:\n";
- std::cout << "Data:\n";
- data.dump();
- std::cout << "Syn:\n";
- syn.dump();
-}
diff --git a/docs/sphinx/examples/qec/python/circuit_level_noise.py b/docs/sphinx/examples/qec/python/circuit_level_noise.py
deleted file mode 100644
index a0202ac5..00000000
--- a/docs/sphinx/examples/qec/python/circuit_level_noise.py
+++ /dev/null
@@ -1,93 +0,0 @@
-# ============================================================================ #
-# Copyright (c) 2025 NVIDIA Corporation & Affiliates. #
-# All rights reserved. #
-# #
-# This source code and the accompanying materials are made available under #
-# the terms of the Apache License 2.0 which accompanies this distribution. #
-# ============================================================================ #
-# [Begin Documentation]
-import numpy as np
-import cudaq
-import cudaq_qec as qec
-
-# Get a QEC code
-cudaq.set_target("stim")
-steane = qec.get_code("steane")
-
-# Get the parity check matrix of a code
-# Can get the full code, or for CSS codes
-# just the X or Z component
-H = steane.get_parity()
-print(f"H:\n{H}")
-observables = steane.get_pauli_observables_matrix()
-Lz = steane.get_observables_z()
-print(f"observables:\n{observables}")
-print(f"Lz:\n{Lz}")
-
-nShots = 3
-nRounds = 4
-
-# error probabily
-p = 0.01
-noise = cudaq.NoiseModel()
-noise.add_all_qubit_channel("x", cudaq.Depolarization2(p), 1)
-
-# prepare logical |0> state, tells the sampler to do z-basis experiment
-statePrep = qec.operation.prep0
-# our expected measurement in this state is 0
-expected_value = 0
-
-# sample the steane memory circuit with noise on each cx gate
-# reading out the syndromes after each stabilizer round (xor'd against the previous)
-# and readout out the data qubits at the end of the experiment
-syndromes, data = qec.sample_memory_circuit(steane, statePrep, nShots, nRounds,
- noise)
-print("From sample function:\n")
-print("syndromes:\n", syndromes)
-print("data:\n", data)
-
-# Get a decoder
-decoder = qec.get_decoder("single_error_lut", H)
-nLogicalErrors = 0
-
-# Logical Mz each shot (use Lx if preparing in X-basis)
-logical_measurements = (Lz @ data.transpose()) % 2
-# only one logical qubit, so do not need the second axis
-logical_measurements = logical_measurements.flatten()
-print("LMz:\n", logical_measurements)
-
-# organize data by shot and round if desired
-syndromes = syndromes.reshape((nShots, nRounds, syndromes.shape[1]))
-
-# initialize a Pauli frame to track logical flips
-# through the stabilizer rounds
-pauli_frame = np.array([0, 0], dtype=np.uint8)
-for shot in range(0, nShots):
- print("shot:", shot)
- for syndrome in syndromes[shot]:
- print("syndrome:", syndrome)
- # decode the syndrome
- convergence, result = decoder.decode(syndrome)
- data_prediction = np.array(result, dtype=np.uint8)
-
- # see if the decoded result anti-commutes with the observables
- print("decode result:", data_prediction)
- decoded_observables = (observables @ data_prediction) % 2
- print("decoded_observables:", decoded_observables)
-
- # update pauli frame
- pauli_frame = (pauli_frame + decoded_observables) % 2
- print("pauli frame:", pauli_frame)
-
- # after pauli frame has tracked corrections through the rounds
- # apply the pauli frame correction to the measurement, and see
- # if this matches the state we intended to prepare
- # We prepared |0>, so we check if logical measurement Mz + Pf_X = 0
- corrected_mz = (logical_measurements[shot] + pauli_frame[0]) % 2
- print("Expected value:", expected_value)
- print("Corrected value:", corrected_mz)
- if (corrected_mz != expected_value):
- nLogicalErrors += 1
-
-# Count how many shots the decoder failed to correct the errors
-print("Number of logical errors:", nLogicalErrors)
diff --git a/docs/sphinx/examples/qec/python/code_capacity_noise.py b/docs/sphinx/examples/qec/python/code_capacity_noise.py
deleted file mode 100644
index e25be036..00000000
--- a/docs/sphinx/examples/qec/python/code_capacity_noise.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# ============================================================================ #
-# Copyright (c) 2025 NVIDIA Corporation & Affiliates. #
-# All rights reserved. #
-# #
-# This source code and the accompanying materials are made available under #
-# the terms of the Apache License 2.0 which accompanies this distribution. #
-# ============================================================================ #
-
-# [Begin Documentation]
-import numpy as np
-import cudaq_qec as qec
-
-# Get a QEC code
-steane = qec.get_code("steane")
-
-# Get the parity check matrix of a code
-# Can get the full code, or for CSS codes
-# just the X or Z component
-Hz = steane.get_parity_z()
-print(f"Hz:\n{Hz}")
-observable = steane.get_observables_z()
-print(f"observable:\n{observable}")
-
-# error probabily
-p = 0.1
-# Get a decoder
-decoder = qec.get_decoder("single_error_lut", Hz)
-
-# Perform a code capacity noise model numerical experiment
-nShots = 10
-nLogicalErrors = 0
-for i in range(nShots):
- print(f"shot: {i}")
-
- # Generate noisy data
- data = qec.generate_random_bit_flips(Hz.shape[1], p)
- print(f"data: {data}")
-
- # Calculate which syndromes are flagged.
- syndrome = Hz @ data % 2
- print(f"syndrome: {syndrome}")
-
- # Decode the syndrome to predict what happen to the data
- convergence, result = decoder.decode(syndrome)
- data_prediction = np.array(result, dtype=np.uint8)
- print(f"data_prediction: {data_prediction}")
-
- # See if this prediction flipped the observable
- predicted_observable = observable @ data_prediction % 2
- print(f"predicted_observable: {predicted_observable}")
-
- # See if the observable was actually flipped
- actual_observable = observable @ data % 2
- print(f"actual_observable: {actual_observable}")
- if (predicted_observable != actual_observable):
- nLogicalErrors += 1
-
-# Count how many shots the decoder failed to correct the errors
-print(f"{nLogicalErrors} logical errors in {nShots} shots\n")
-
-# Can also generate syndromes and data from a single line with:
-syndromes, data = qec.sample_code_capacity(Hz, nShots, p)
-print("From sample function:")
-print("syndromes:\n", syndromes)
-print("data:\n", data)
diff --git a/docs/sphinx/examples/qec/python/nv-qldpc-decoder.py b/docs/sphinx/examples/qec/python/nv-qldpc-decoder.py
deleted file mode 100644
index 42d4a1f0..00000000
--- a/docs/sphinx/examples/qec/python/nv-qldpc-decoder.py
+++ /dev/null
@@ -1,227 +0,0 @@
-# ============================================================================ #
-# Copyright (c) 2025 NVIDIA Corporation & Affiliates. #
-# All rights reserved. #
-# #
-# This source code and the accompanying materials are made available under #
-# the terms of the Apache License 2.0 which accompanies this distribution. #
-# ============================================================================ #
-# [Begin Documentation]
-
-import numpy as np
-from scipy.sparse import csr_matrix
-import cudaq_qec as qec
-import json
-import time
-
-# For fetching data
-import requests
-import bz2
-import os
-
-# Note: running this script will automatically download data if necessary.
-
-### Helper functions ###
-
-
-def parse_csr_mat(j, dims, mat_name):
- """
- Parse a CSR-style matrix from a JSON file using SciPy's sparse matrix utilities.
- """
- assert len(dims) == 2, "dims must be a tuple of two integers"
-
- # Extract indptr and indices from the JSON.
- indptr = np.array(j[f"{mat_name}_indptr"], dtype=int)
- indices = np.array(j[f"{mat_name}_indices"], dtype=int)
-
- # Check that the CSR structure is consistent.
- assert len(indptr) == dims[0] + 1, "indptr length must equal dims[0] + 1"
- assert np.all(
- indices < dims[1]), "All column indices must be less than dims[1]"
-
- # Create a data array of ones.
- data = np.ones(indptr[-1], dtype=np.uint8)
-
- # Build the CSR matrix and return it as a dense numpy array.
- csr = csr_matrix((data, indices, indptr), shape=dims, dtype=np.uint8)
- return csr.toarray()
-
-
-def parse_H_csr(j, dims):
- """
- Parse a CSR-style parity check matrix from an input file in JSON format"
- """
- return parse_csr_mat(j, dims, "H")
-
-
-def parse_obs_csr(j, dims):
- """
- Parse a CSR-style observable matrix from an input file in JSON format"
- """
- return parse_csr_mat(j, dims, "obs_mat")
-
-
-### Main decoder loop ###
-
-
-def run_decoder(filename, num_shots, run_as_batched):
- """
- Load a JSON file and decode "num_shots" syndromes.
- """
- t_load_begin = time.time()
- with open(filename, "r") as f:
- j = json.load(f)
-
- dims = j["shape"]
- assert len(dims) == 2
-
- # Read the Parity Check Matrix
- H = parse_H_csr(j, dims)
- syndrome_length, block_length = dims
- t_load_end = time.time()
-
- print(f"{filename} parsed in {1e3 * (t_load_end-t_load_begin)} ms")
-
- error_rate_vec = np.array(j["error_rate_vec"])
- assert len(error_rate_vec) == block_length
- obs_mat_dims = j["obs_mat_shape"]
- obs_mat = parse_obs_csr(j, obs_mat_dims)
- assert dims[1] == obs_mat_dims[0]
- file_num_trials = j["num_trials"]
- num_shots = min(num_shots, file_num_trials)
- print(
- f'Your JSON file has {file_num_trials} shots. Running {num_shots} now.')
-
- # osd_method: 0=Off, 1=OSD-0, 2=Exhaustive, 3=Combination Sweep
- osd_method = 1
-
- # When osd_method is:
- # 2) there are 2^osd_order additional error mechanisms checked.
- # 3) there are an additional k + osd_order*(osd_order-1)/2 error
- # mechanisms checked.
- # Ref: https://arxiv.org/pdf/2005.07016
- osd_order = 0
-
- # Maximum number of BP iterations before attempting OSD (if necessary)
- max_iter = 50
-
- nv_dec_args = {
- "max_iterations": max_iter,
- "error_rate_vec": error_rate_vec,
- "use_sparsity": True,
- "use_osd": osd_method > 0,
- "osd_order": osd_order,
- "osd_method": osd_method
- }
-
- if run_as_batched:
- # Perform BP processing for up to 1000 syndromes per batch. If there
- # are more than 1000 syndromes, the decoder will chunk them up and
- # process each batch sequentially under the hood.
- nv_dec_args['bp_batch_size'] = min(1000, num_shots)
-
- try:
- nv_dec_gpu_and_cpu = qec.get_decoder("nv-qldpc-decoder", H,
- **nv_dec_args)
- except Exception as e:
- print(
- 'The nv-qldpc-decoder is not available with your current CUDA-Q ' +
- 'QEC installation.')
- exit(0)
- decoding_time = 0
- bp_converged_flags = []
- num_logical_errors = 0
-
- # Batched API
- if run_as_batched:
- syndrome_list = []
- obs_truth_list = []
- for i in range(num_shots):
- syndrome = j["trials"][i]["syndrome_truth"]
- obs_truth = j["trials"][i]["obs_truth"]
- syndrome_list.append(syndrome)
- obs_truth_list.append(obs_truth)
- t0 = time.time()
- results = nv_dec_gpu_and_cpu.decode_batch(syndrome_list)
- t1 = time.time()
- decoding_time += t1 - t0
- for r, obs_truth in zip(results, obs_truth_list):
- bp_converged_flags.append(r.converged)
- dec_result = np.array(r.result, dtype=np.uint8)
-
- # See if this prediction flipped the observable
- predicted_observable = obs_mat.T @ dec_result % 2
- print(f"predicted_observable: {predicted_observable}")
-
- # See if the observable was actually flipped according to the truth
- # data
- actual_observable = np.array(obs_truth, dtype=np.uint8)
- print(f"actual_observable: {actual_observable}")
-
- if np.sum(predicted_observable != actual_observable) > 0:
- num_logical_errors += 1
-
- # Non-batched API
- else:
- for i in range(num_shots):
- syndrome = j["trials"][i]["syndrome_truth"]
- obs_truth = j["trials"][i]["obs_truth"]
-
- t0 = time.time()
- bp_converged, dec_result = nv_dec_gpu_and_cpu.decode(syndrome)
- t1 = time.time()
- trial_diff = t1 - t0
- decoding_time += trial_diff
-
- dec_result = np.array(dec_result, dtype=np.uint8)
- bp_converged_flags.append(bp_converged)
-
- # See if this prediction flipped the observable
- predicted_observable = obs_mat.T @ dec_result % 2
- print(f"predicted_observable: {predicted_observable}")
-
- # See if the observable was actually flipped according to the truth
- # data
- actual_observable = np.array(obs_truth, dtype=np.uint8)
- print(f"actual_observable: {actual_observable}")
-
- if np.sum(predicted_observable != actual_observable) > 0:
- num_logical_errors += 1
-
- # Count how many shots the decoder failed to correct the errors
- print(f"{num_logical_errors} logical errors in {num_shots} shots")
- print(
- f"Number of shots that converged with BP processing: {np.sum(np.array(bp_converged_flags))}"
- )
- print(
- f"Average decoding time for {num_shots} shots was {1e3 * decoding_time / num_shots} ms per shot"
- )
-
-
-if __name__ == "__main__":
- # See other test data options in https://github.com/NVIDIA/cudaqx/releases/tag/0.2.0
- filename = 'osd_1008_8785_0.001.json'
- bz2filename = filename + '.bz2'
- if not os.path.exists(filename):
- url = f"https://github.com/NVIDIA/cudaqx/releases/download/0.2.0/{bz2filename}"
-
- print(f'Downloading data from {url}')
-
- # Download the file
- response = requests.get(url, stream=True)
- response.raise_for_status() # Raise an error if download fails
- with open(bz2filename, "wb") as f:
- for chunk in response.iter_content(chunk_size=8192):
- f.write(chunk)
-
- print(f'Decompressing {bz2filename} into {filename}')
-
- # Decompress the file
- with bz2.BZ2File(bz2filename, "rb") as f_in, open(filename,
- "wb") as f_out:
- f_out.write(f_in.read())
-
- print(f"Decompressed file saved as {filename}")
-
- num_shots = 100
- run_as_batched = True
- run_decoder(filename, num_shots, run_as_batched)
diff --git a/docs/sphinx/examples/qec/python/pseudo_threshold.py b/docs/sphinx/examples/qec/python/pseudo_threshold.py
deleted file mode 100644
index fddf9ed5..00000000
--- a/docs/sphinx/examples/qec/python/pseudo_threshold.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# ============================================================================ #
-# Copyright (c) 2025 NVIDIA Corporation & Affiliates. #
-# All rights reserved. #
-# #
-# This source code and the accompanying materials are made available under #
-# the terms of the Apache License 2.0 which accompanies this distribution. #
-# ============================================================================ #
-
-# [Begin Documentation]
-import numpy as np
-import cudaq_qec as qec
-import matplotlib.pyplot as plt
-
-# Get a QEC code
-# steane = qec.get_code("repetition", distance=9)
-steane = qec.get_code("steane")
-
-# Get the parity check matrix of a code
-# Can get the full code, or for CSS codes
-# just the X or Z component
-Hz = steane.get_parity_z()
-observable = steane.get_observables_z()
-
-# Get a decoder
-decoder = qec.get_decoder("single_error_lut", Hz)
-
-# Perform a code capacity noise model numerical experiment
-nShots = 100000
-LERates = []
-# PERates = np.linspace(0.1, 0.50, num=20)
-PERates = np.logspace(-2.0, -0.5, num=25)
-
-for p in PERates:
- nLogicalErrors = 0
- for i in range(nShots):
- data = qec.generate_random_bit_flips(Hz.shape[1], p)
- # Calculate which syndromes are flagged.
- syndrome = Hz @ data % 2
-
- convergence, result = decoder.decode(syndrome)
- data_prediction = np.array(result)
-
- predicted_observable = observable @ data_prediction % 2
-
- actual_observable = observable @ data % 2
- if (predicted_observable != actual_observable):
- nLogicalErrors += 1
- LERates.append(nLogicalErrors / nShots)
-
-# Count how many shots the decoder failed to correct the errors
-print("PERates:", PERates)
-print("LERates:", LERates)
-
-# Create a figure and an axes object
-fig, ax = plt.subplots()
-
-# Plot the data
-ax.loglog(PERates, LERates)
-ax.loglog(PERates, PERates, 'r--', label='y=x')
-
-# Add a title and labels
-ax.set_title("Steane Code")
-ax.set_xlabel("Physical Error Rate")
-ax.set_ylabel("Logical Error Rate")
-
-# Show the plot
-# plt.show()
-# plt.savefig("myplot.png")
diff --git a/docs/sphinx/examples/qec/python/repetition_code_fine_grain_noise.py b/docs/sphinx/examples/qec/python/repetition_code_fine_grain_noise.py
deleted file mode 100644
index af06ce41..00000000
--- a/docs/sphinx/examples/qec/python/repetition_code_fine_grain_noise.py
+++ /dev/null
@@ -1,184 +0,0 @@
-# ============================================================================ #
-# Copyright (c) 2025 NVIDIA Corporation & Affiliates. #
-# All rights reserved. #
-# #
-# This source code and the accompanying materials are made available under #
-# the terms of the Apache License 2.0 which accompanies this distribution. #
-# ============================================================================ #
-
-# [Begin Documentation]
-import cudaq
-import cudaq_qec as qec
-import numpy as np
-
-nRounds = 3
-nShots = 500
-# Physical error rate
-p_per_round = 0.01
-p_per_mz = 0.01
-
-
-# Construct the measurement error syndrome matrix based on the distance and number of rounds
-def construct_measurement_error_syndrome(distance, nRounds):
- num_stabilizers = distance - 1
- num_mea_q = num_stabilizers * nRounds
-
- syndrome_rows = []
-
- # In this scheme, need two rounds for each measurement syndrome
- for i in range(nRounds - 1):
- for j in range(num_stabilizers):
- syndrome = np.zeros((num_mea_q,), dtype=np.uint8)
-
- # The error on ancilla (j) in round (i) affects stabilizer checks at two positions:
- # First occurrence in round i
- pos1 = i * num_stabilizers + j
- # Second occurrence in round i+1
- pos2 = (i + 1) * num_stabilizers + j
-
- # Mark the syndrome
- syndrome[pos1] = 1
- syndrome[pos2] = 1
-
- syndrome_rows.append(syndrome)
-
- return np.array(syndrome_rows).T
-
-
-# Generate the parity check matrix for n-rounds by duplicating the input parity check matrix Hz
-# and appending the measurement error syndrome matrix.
-def get_circuit_level_pcm(distance, nRounds, Hz):
- if nRounds < 2:
- raise ValueError("nRounds must be greater than or equal to 2")
- if distance < 3:
- raise ValueError("distance must be greater than or equal to 3")
-
- # Parity check matrix for a single round
- H = np.array(Hz)
-
- # Extends H to nRounds
- rows, cols = H.shape
- H_nrounds = np.zeros((rows * nRounds, cols * nRounds), dtype=np.uint8)
- for i in range(nRounds):
- H_nrounds[i * rows:(i + 1) * rows, i * cols:(i + 1) * cols] = H
- print("H_nrounds\n", H_nrounds)
-
- # Construct the measurement error syndrome matrix for Z errors
- H_mz = construct_measurement_error_syndrome(distance, nRounds)
- print("H_mz\n", H_mz)
- assert H_nrounds.shape[0] == H_mz.shape[
- 0], "Dimensions of H_nrounds and H_mz do not match"
-
- # Append columns for measurement errors to H
- H_pcm = np.concatenate((H_nrounds, H_mz), axis=1)
- print(f"H_pcm:\n{H_pcm}")
-
- return H_pcm
-
-
-# Example of how to construct a repetition code with a distance of 3 and random
-# bit flip errors applied to the data qubits
-@cudaq.kernel
-def three_qubit_repetition_code():
- data_qubits = cudaq.qvector(3)
- ancilla_qubits = cudaq.qvector(2)
-
- # Initialize the logical |1> state as |111>
- x(data_qubits)
-
- for i in range(nRounds):
- # Random Bit Flip Errors
- for j in range(3):
- cudaq.apply_noise(cudaq.XError, p_per_round, data_qubits[j])
-
- # Extract Syndromes
- h(ancilla_qubits)
-
- # First Parity Check
- z.ctrl(ancilla_qubits[0], data_qubits[0])
- z.ctrl(ancilla_qubits[0], data_qubits[1])
-
- # Second Parity Check
- z.ctrl(ancilla_qubits[1], data_qubits[1])
- z.ctrl(ancilla_qubits[1], data_qubits[2])
-
- h(ancilla_qubits)
-
- # Measure the ancilla qubits
- s0 = mz(ancilla_qubits[0])
- s1 = mz(ancilla_qubits[1])
- reset(ancilla_qubits[0])
- reset(ancilla_qubits[1])
-
- # Final measurement to get the data qubits
- mz(data_qubits)
-
-
-# Create a noise model
-noise_model = cudaq.NoiseModel()
-# Add measurement noise
-noise_model.add_all_qubit_channel("mz", cudaq.BitFlipChannel(p_per_mz))
-
-# Run the kernel and observe results
-# The percent of samples that are 000 corresponds to the logical error rate
-cudaq.set_target("stim")
-result = cudaq.sample(three_qubit_repetition_code,
- shots_count=nShots,
- noise_model=noise_model,
- explicit_measurements=True)
-
-# The following section will demonstrate how to decode the results
-# Get the parity check matrix for n-rounds of the repetition code
-Hz = [[1, 1, 0], [0, 1, 1]] # Parity check matrix for 1 round
-H_pcm = get_circuit_level_pcm(3, nRounds, Hz)
-
-# Get observables
-observables = np.array([1, 0, 0, 0, 0, 0], dtype=np.uint8)
-Lz = np.array([1, 0, 0], dtype=np.uint8)
-print(f"observables:\n{observables}")
-print(f"Lz:\n{Lz}")
-# Pad the observables to be the same dimension as the decoded observable
-Lz_nrounds = np.tile(Lz, nRounds)
-pad_size = max(0, H_pcm.shape[1] - Lz_nrounds.shape[0])
-Lz_nround_mz = np.pad(Lz_nrounds, (0, pad_size), mode='constant')
-print(f"Lz_nround_mz\n{Lz_nround_mz}")
-
-# Get a decoder
-decoder = qec.get_decoder("single_error_lut", H_pcm)
-nLogicalErrors = 0
-
-# initialize a Pauli frame to track logical flips
-# through the stabilizer rounds. Only need the Z component for the repetition code.
-pauli_frame = np.array([0, 0], dtype=np.uint8)
-expected_value = 1
-for shot, outcome in enumerate(result.get_sequential_data()):
- outcome_array = np.array([int(bit) for bit in outcome], dtype=np.uint8)
- syndrome = outcome_array[:len(outcome_array) - 3]
- data = outcome_array[len(outcome_array) - 3:]
- print("\nshot:", shot)
- print("syndrome:", syndrome)
-
- # Decode the syndrome
- convergence, result = decoder.decode(syndrome)
- data_prediction = np.array(result, dtype=np.uint8)
-
- # See if the decoded result anti-commutes with the observables
- print("decode result:", data_prediction)
- decoded_observables = (Lz_nround_mz @ data_prediction) % 2
- print("decoded_observables:", decoded_observables)
-
- # update pauli frame
- pauli_frame[0] = (pauli_frame[0] + decoded_observables) % 2
- print("pauli frame:", pauli_frame)
-
- logical_measurements = (Lz @ data.transpose()) % 2
- print("LMz:", logical_measurements)
-
- corrected_mz = (logical_measurements + pauli_frame[0]) % 2
- print("Expected value:", expected_value)
- print("Corrected value:", corrected_mz)
- if (corrected_mz != expected_value):
- nLogicalErrors += 1
-
-# Count how many shots the decoder failed to correct the errors
-print("\nNumber of logical errors:", nLogicalErrors)
diff --git a/docs/sphinx/examples/solvers/cpp/adapt_h2.cpp b/docs/sphinx/examples/solvers/cpp/adapt_h2.cpp
deleted file mode 100644
index 527bb4f5..00000000
--- a/docs/sphinx/examples/solvers/cpp/adapt_h2.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2024 NVIDIA Corporation & Affiliates. *
- * All rights reserved. *
- * *
- * This source code and the accompanying materials are made available under *
- * the terms of the Apache License 2.0 which accompanies this distribution. *
- ******************************************************************************/
-// [Begin Documentation]
-#include "cudaq.h"
-#include "cudaq/solvers/adapt.h"
-#include "cudaq/solvers/operators.h"
-
-// Compile and run with
-// nvq++ --enable-mlir -lcudaq-solvers adapt_h2.cpp -o adapt_ex
-// ./adapt_ex
-
-int main() {
- // Create the molecular hamiltonian
- cudaq::solvers::molecular_geometry geometry{{"H", {0., 0., 0.}},
- {"H", {0., 0., .7474}}};
- auto molecule = cudaq::solvers::create_molecule(
- geometry, "sto-3g", 0, 0, {.casci = true, .verbose = true});
-
- // Get the spin operator
- auto h = molecule.hamiltonian;
-
- // Create the operator pool
- std::vector opPool = cudaq::solvers::get_operator_pool(
- "spin_complement_gsd", {{"num-orbitals", h.num_qubits() / 2}});
-
- // Run ADAPT
- auto [energy, thetas, ops] = cudaq::solvers::adapt_vqe(
- [](cudaq::qvector<> &q) __qpu__ {
- x(q[0]);
- x(q[1]);
- },
- h, opPool, {{"grad_norm_tolerance", 1e-3}});
-
- printf("Final = %.12lf\n", energy);
-}
diff --git a/docs/sphinx/examples/solvers/cpp/molecular_docking_qaoa.cpp b/docs/sphinx/examples/solvers/cpp/molecular_docking_qaoa.cpp
deleted file mode 100644
index 3b115cfe..00000000
--- a/docs/sphinx/examples/solvers/cpp/molecular_docking_qaoa.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2024 NVIDIA Corporation & Affiliates. *
- * All rights reserved. *
- * *
- * This source code and the accompanying materials are made available under *
- * the terms of the Apache License 2.0 which accompanies this distribution. *
- ******************************************************************************/
-// [Begin Documentation]
-#include "cudaq.h"
-#include "cudaq/solvers/operators.h"
-#include "cudaq/solvers/qaoa.h"
-
-// Compile and run with
-// nvq++ --enable-mlir -lcudaq-solvers molecular_docking_qaoa.cpp
-// ./a.out
-
-int main() {
-
- // Create the ligand-configuration graph
- cudaqx::graph g;
- std::vector weights{0.6686, 0.6686, 0.6686, 0.1453, 0.1453, 0.1453};
- std::vector> edges{{0, 1}, {0, 2}, {0, 4}, {0, 5},
- {1, 2}, {1, 3}, {1, 5}, {2, 3},
- {2, 4}, {3, 4}, {3, 5}, {4, 5}};
- for (std::size_t node = 0; auto weight : weights)
- g.add_node(node++, weight);
-
- for (auto &edge : edges)
- g.add_edge(edge.first, edge.second);
-
- // Set some parameters we'll need
- double penalty = 6.0;
- std::size_t numLayers = 3;
-
- // Create the Clique Hamiltonian
- auto H = cudaq::solvers::get_clique_hamiltonian(g, penalty);
-
- // Get the number of required variational parameters
- auto numParams = cudaq::solvers::get_num_qaoa_parameters(
- H, numLayers,
- {{"full_parameterization", true}, {"counterdiabatic", true}});
-
- // Create the initial parameters to begin optimization
- auto initParams = cudaq::random_vector(-M_PI / 8., M_PI / 8., numParams);
-
- // Run QAOA, specify full parameterization and counterdiabatic
- // Full parameterization uses an optimization parameter for
- // every term in the clique Hamiltonian and the mixer hamiltonian.
- // Specifying counterdiabatic adds extra Ry rotations at the
- // end of each layer.
- auto [opt_value, opt_params, opt_config] = cudaq::solvers::qaoa(
- H, numLayers, initParams,
- {{"full_parameterization", true}, {"counterdiabatic", true}});
-
- // Print out the results
- std::cout << "Optimal energy: " << opt_value << "\n";
- std::cout << "Sampled states: ";
- opt_config.dump();
- std::cout << "Optimal configuraiton: " << opt_config.most_probable() << "\n";
-}
diff --git a/docs/sphinx/examples/solvers/cpp/uccsd_vqe.cpp b/docs/sphinx/examples/solvers/cpp/uccsd_vqe.cpp
deleted file mode 100644
index 513b6996..00000000
--- a/docs/sphinx/examples/solvers/cpp/uccsd_vqe.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2024 NVIDIA Corporation & Affiliates. *
- * All rights reserved. *
- * *
- * This source code and the accompanying materials are made available under *
- * the terms of the Apache License 2.0 which accompanies this distribution. *
- ******************************************************************************/
-// [Begin Documentation]
-#include "cudaq.h"
-#include "cudaq/solvers/operators.h"
-#include "cudaq/solvers/stateprep/uccsd.h"
-#include "cudaq/solvers/vqe.h"
-
-// Compile and run with
-// nvq++ --enable-mlir -lcudaq-solvers uccsd_vqe.cpp -o uccsd_vqe
-// ./uccsd_vqe
-
-int main() {
- // Create the molecular hamiltonian
- cudaq::solvers::molecular_geometry geometry{{"H", {0., 0., 0.}},
- {"H", {0., 0., .7474}}};
- auto molecule = cudaq::solvers::create_molecule(
- geometry, "sto-3g", 0, 0, {.casci = true, .verbose = true});
-
- // Get the spin operator
- auto h = molecule.hamiltonian;
-
- // Get the number of electrons and qubits
- auto numElectrons = molecule.n_electrons;
- auto numQubits = molecule.n_orbitals * 2;
-
- // Create an initial set of parameters for the optimization
- auto numParams = cudaq::solvers::stateprep::get_num_uccsd_parameters(
- numElectrons, numQubits);
- std::vector init(numParams, -2.);
-
- // Run VQE
- auto [energy, thetas, ops] = cudaq::solvers::vqe(
- [&](std::vector params, std::size_t numQubits,
- std::size_t numElectrons) __qpu__ {
- cudaq::qvector q(numQubits);
- for (auto i : cudaq::range(numElectrons))
- x(q[i]);
-
- cudaq::solvers::stateprep::uccsd(q, params, numElectrons);
- },
- molecule.hamiltonian, init,
- [&](std::vector x) {
- return std::make_tuple(x, numQubits, numElectrons);
- },
- {{"verbose", true}});
-
- printf("Final = %.12lf\n", energy);
-}
diff --git a/docs/sphinx/examples/solvers/python/adapt_h2.py b/docs/sphinx/examples/solvers/python/adapt_h2.py
deleted file mode 100644
index f40bafa8..00000000
--- a/docs/sphinx/examples/solvers/python/adapt_h2.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# ============================================================================ #
-# Copyright (c) 2024 NVIDIA Corporation & Affiliates. #
-# All rights reserved. #
-# #
-# This source code and the accompanying materials are made available under #
-# the terms of the Apache License 2.0 which accompanies this distribution. #
-# ============================================================================ #
-
-# [Begin Documentation]
-import cudaq, cudaq_solvers as solvers
-
-# Run this script with
-# python3 adapt_h2.py
-#
-# In order to leverage CUDA-Q MQPU and distribute the work across
-# multiple QPUs (thereby observing a speed-up), set the target and
-# use MPI:
-#
-# cudaq.set_target('nvidia', mqpu=True)
-# cudaq.mpi.initialize()
-#
-# run with
-#
-# mpiexec -np N and vary N to see the speedup...
-# e.g. mpiexec -np 2 python3 adapt_h2_mqpu.py
-#
-# End the script with
-# cudaq.mpi.finalize()
-
-# Create the molecular hamiltonian
-geometry = [('H', (0., 0., 0.)), ('H', (0., 0., .7474))]
-molecule = solvers.create_molecule(geometry, 'sto-3g', 0, 0, casci=True)
-
-# Create the ADAPT operator pool
-operators = solvers.get_operator_pool("spin_complement_gsd",
- num_orbitals=molecule.n_orbitals)
-
-# Get the number of electrons so we can
-# capture it in the initial state kernel
-numElectrons = molecule.n_electrons
-
-
-# Define the initial Hartree Fock state
-@cudaq.kernel
-def initState(q: cudaq.qview):
- for i in range(numElectrons):
- x(q[i])
-
-
-# Run ADAPT-VQE
-energy, thetas, ops = solvers.adapt_vqe(initState, molecule.hamiltonian,
- operators)
-
-# Print the result.
-print(" = ", energy)
diff --git a/docs/sphinx/examples/solvers/python/generate_molecular_hamiltonians.py b/docs/sphinx/examples/solvers/python/generate_molecular_hamiltonians.py
deleted file mode 100644
index c5e719c2..00000000
--- a/docs/sphinx/examples/solvers/python/generate_molecular_hamiltonians.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# ============================================================================ #
-# Copyright (c) 2024 NVIDIA Corporation & Affiliates. #
-# All rights reserved. #
-# #
-# This source code and the accompanying materials are made available under #
-# the terms of the Apache License 2.0 which accompanies this distribution. #
-# ============================================================================ #
-
-# [Begin Documentation]
-import cudaq_solvers as solvers
-
-# Generate active space Hamiltonian using HF molecular orbitals
-
-geometry = [('N', (0.0, 0.0, 0.5600)), ('N', (0.0, 0.0, -0.5600))]
-molecule = solvers.create_molecule(geometry,
- 'sto-3g',
- 0,
- 0,
- nele_cas=2,
- norb_cas=3,
- verbose=True)
-
-print('N2 HF Hamiltonian')
-print('Energies : ', molecule.energies)
-print('No. of orbitals: ', molecule.n_orbitals)
-print('No. of electrons: ', molecule.n_electrons)
-
-# Generate active space Hamiltonian using natural orbitals from MP2
-
-geometry = [('N', (0.0, 0.0, 0.5600)), ('N', (0.0, 0.0, -0.5600))]
-molecule = solvers.create_molecule(geometry,
- 'sto-3g',
- 0,
- 0,
- nele_cas=2,
- norb_cas=3,
- MP2=True,
- integrals_natorb=True,
- verbose=True)
-
-print('N2 Natural Orbitals from MP2 Hamiltonian')
-print('Energies: ', molecule.energies)
-print('No. of orbitals: ', molecule.n_orbitals)
-print('No. of electrons: ', molecule.n_electrons)
-
-# Generate active space Hamiltonian using casscf orbitals,
-# where the active space of the casscf was defined from HF molecular orbitals
-
-geometry = [('N', (0.0, 0.0, 0.5600)), ('N', (0.0, 0.0, -0.5600))]
-molecule = solvers.create_molecule(geometry,
- 'sto-3g',
- 0,
- 0,
- nele_cas=2,
- norb_cas=3,
- casscf=True,
- integrals_casscf=True,
- verbose=True)
-
-print('N2 Active Space Hamiltonian Using CASSF Orbitals - HF orbitals')
-print('Energies: ', molecule.energies)
-print('No. of orbitals: ', molecule.n_orbitals)
-print('No. of electrons: ', molecule.n_electrons)
-
-# Generate active space Hamiltonian using casscf orbitals,
-# where the active space of the casscf was defined from the MP2 natural orbitals.
-
-geometry = [('N', (0.0, 0.0, 0.5600)), ('N', (0.0, 0.0, -0.5600))]
-molecule = solvers.create_molecule(geometry,
- 'sto-3g',
- 0,
- 0,
- nele_cas=2,
- norb_cas=3,
- MP2=True,
- natorb=True,
- casscf=True,
- integrals_casscf=True,
- verbose=True)
-
-print('N2 Active Space Hamiltonian Using CASSF Orbitals - MP2 natural orbitals')
-print('N2 HF Hamiltonian')
-print('Energies: ', molecule.energies)
-print('No. of orbitals: ', molecule.n_orbitals)
-print('No. of electrons: ', molecule.n_electrons)
diff --git a/docs/sphinx/examples/solvers/python/molecular_docking_qaoa.py b/docs/sphinx/examples/solvers/python/molecular_docking_qaoa.py
deleted file mode 100644
index a9784ec0..00000000
--- a/docs/sphinx/examples/solvers/python/molecular_docking_qaoa.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# ============================================================================ #
-# Copyright (c) 2024 NVIDIA Corporation & Affiliates. #
-# All rights reserved. #
-# #
-# This source code and the accompanying materials are made available under #
-# the terms of the Apache License 2.0 which accompanies this distribution. #
-# ============================================================================ #
-
-# [Begin Documentation]
-import cudaq, cudaq_solvers as solvers
-import networkx as nx, numpy as np
-
-# Create the ligand-configuration graph
-G = nx.Graph()
-edges = [[0, 1], [0, 2], [0, 4], [0, 5], [1, 2], [1, 3], [1, 5], [2, 3], [2, 4],
- [3, 4], [3, 5], [4, 5]]
-weights = [0.6686, 0.6686, 0.6686, 0.1453, 0.1453, 0.1453]
-for i, weight in enumerate(weights):
- G.add_node(i, weight=weight)
-G.add_edges_from(edges)
-
-# Set some parameters we'll need
-penalty = 6.0
-num_layers = 3
-
-# Create the Clique Hamiltonian
-H = solvers.get_clique_hamiltonian(G, penalty=penalty)
-
-# Get the number of parameters we'll need
-parameter_count = solvers.get_num_qaoa_parameters(H,
- num_layers,
- full_parameterization=True,
- counterdiabatic=True)
-
-# Create the initial parameters to begin optimization
-init_params = np.random.uniform(-np.pi / 8, np.pi / 8, parameter_count)
-
-# Run QAOA, specify full parameterization and counterdiabatic
-# Full parameterization uses an optimization parameter for
-# every term in the clique Hamiltonian and the mixer hamiltonian.
-# Specifying counterdiabatic adds extra Ry rotations at the
-# end of each layer.
-opt_value, opt_params, opt_config = solvers.qaoa(H,
- num_layers,
- init_params,
- full_parameterization=True,
- counterdiabatic=True)
-
-# Print the results
-print()
-print('Optimal energy: ', opt_value)
-print('Sampled states: ', opt_config)
-print('Optimal Configuration: ', opt_config.most_probable())
diff --git a/docs/sphinx/examples/solvers/python/uccsd_vqe.py b/docs/sphinx/examples/solvers/python/uccsd_vqe.py
deleted file mode 100644
index cf01de22..00000000
--- a/docs/sphinx/examples/solvers/python/uccsd_vqe.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# ============================================================================ #
-# Copyright (c) 2024 NVIDIA Corporation & Affiliates. #
-# All rights reserved. #
-# #
-# This source code and the accompanying materials are made available under #
-# the terms of the Apache License 2.0 which accompanies this distribution. #
-# ============================================================================ #
-
-# [Begin Documentation]
-import cudaq, cudaq_solvers as solvers
-from scipy.optimize import minimize
-
-# Create the molecular hamiltonian
-geometry = [('H', (0., 0., 0.)), ('H', (0., 0., .7474))]
-molecule = solvers.create_molecule(geometry, 'sto-3g', 0, 0, casci=True)
-
-# Get the number of qubits and electrons
-numQubits = molecule.n_orbitals * 2
-numElectrons = molecule.n_electrons
-spin = 0
-initialX = [-.2] * solvers.stateprep.get_num_uccsd_parameters(
- numElectrons, numQubits)
-
-
-# Define the UCCSD ansatz
-@cudaq.kernel
-def ansatz(thetas: list[float]):
- q = cudaq.qvector(numQubits)
- for i in range(numElectrons):
- x(q[i])
- solvers.stateprep.uccsd(q, thetas, numElectrons, spin)
-
-
-# Run VQE
-energy, params, all_data = solvers.vqe(ansatz,
- molecule.hamiltonian,
- initialX,
- optimizer=minimize,
- method='L-BFGS-B',
- jac='3-point',
- tol=1e-4,
- options={'disp': True})
-print(f'Final = {energy}')
diff --git a/docs/sphinx/examples_rst/qec/circuit_level_noise.rst b/docs/sphinx/examples_rst/qec/circuit_level_noise.rst
deleted file mode 100644
index 860ef424..00000000
--- a/docs/sphinx/examples_rst/qec/circuit_level_noise.rst
+++ /dev/null
@@ -1,148 +0,0 @@
-Quantum Error Correction with Circuit-level Noise Modeling
-----------------------------------------------------------
-This example builds upon the previous code-capacity noise model example.
-In the circuit-level noise modeling experiment, we have many of the same components from the CUDA-Q QEC library: QEC codes, decoders, and noisy data.
-The primary difference here, is that we can begin to run CUDA-Q kernels to generate noisy data, rather than just generating random bitstring to represent our errors.
-
-Along with the stabilizers, parity check matrices, and logical observables, the QEC code type also has an encoding map.
-This map allows codes to define logical gates in terms of gates on the underlying physical qubits.
-These encodings operate on the `qec.patch` type, which represents three registers of physical qubits making up a logical qubit.
-A data qubit register, an X-stabilizer ancilla register, and a Z-stabilizer ancilla register.
-
-The most notable encoding stored in the QEC map, is how the `qec.operation.stabilizer_round`, which encodes a `cudaq.kernel` which stores the gate-level information for how to do a stabilizer measurement.
-These stabilizer rounds are the gate-level way to encode the parity check matrix of a QEC code into quantum circuits.
-
-This example walks through how to use the CUDA-Q QEC library to perform a quantum memory experiment simulation.
-These experiments model how well QEC cycles, or rounds of stabilizer measuments, can protect the information encoded in a logical qubit.
-If noise is turned off, then the information is protected indefinitely.
-Here, we will model depolarization noise after each CX gate, and track how many logical errors occur.
-
-
-CUDA-Q QEC Implementation
-+++++++++++++++++++++++++++++
-Here's how to use CUDA-Q QEC to perform a circuit-level noise model experiment in both Python and C++:
-
-.. tab:: Python
-
- .. literalinclude:: ../../examples/qec/python/circuit_level_noise.py
- :language: python
- :start-after: [Begin Documentation]
-
-.. tab:: C++
-
- .. literalinclude:: ../../examples/qec/cpp/circuit_level_noise.cpp
- :language: cpp
- :start-after: [Begin Documentation]
-
- Compile and run with
-
- .. code-block:: bash
-
- nvq++ --enable-mlir --target=stim -lcudaq-qec circuit_level_noise.cpp -o circuit_level_noise
- ./circuit_level_noise
-
-
-1. QEC Code and Decoder types:
- - As in the code capacity example, our central objects are the `qec.code` and `qec.decoder` types.
-
-2. Clifford simulation backend:
- - As the size of QEC circuits can grow quite large, Clifford simulation is often the best tool for these simulations.
- - `cudaq.set_target("stim")` selects the highly performant Stim simulator as the simulation backend.
-
-3. Noise model:
- - To add noisy gates we use the `cudaq.NoiseModel` type.
- - CUDA-Q supports the generation of arbitrary noise channels. Here we use a `cudaq.Depolarization2` channel to add a depolarization channel.
- - This is added to the `CX` gate by adding it to the `X` gate with 1 control.
- - This noisy gate is added to every qubit via that `noise.add_all_qubit_channel` function.
-
-4. Getting circuit-level noisy data:
- - The `qec.code` is the first input parameter here, as the code's `stabilizer_round` determines the circuits executed.
- - Each memory circuit runs for an input number of `nRounds`, which specifies how many `stabilizer_round` kernels are ran.
- - After `nRounds` the data qubits are measured and the run is over.
- - This is performed `nShots` number of times.
- - During a shot, each stabilizer round's syndrome is `xor`'d against the preceding syndrome, so that we can track a sparser flow of data showing which round each parity check was violated.
- - The first round returns the syndrome as is, as there is nothing preceding to `xor` against.
-
-5. Data qubit measurements:
- - The data qubits are only read out after the end of each shot, so there are `nShots` worth of data readouts.
- - The basis of the data qubit measurements depends on the state preparation used.
- - Z-basis readout when preparing the logical `|0>` or logical `|1>` state with the `qec.operation.prep0` or `qec.operation.prep1` kernels.
- - X-basis readout when preparing the logical `|+>` or logical `|->` state with the `qec.operation.prepp` or `qec.operation.prepm` kernels.
-
-6. Logical Errors:
- - From here, the decoding procedure is again similar to the code capacity case, expect for we use a pauli frame to track errors that happen each QEC cycle.
- - The final values of the pauli frame tell us how our logical state flipped during the experiment, and what needs to be done to correct it.
- - We compare our known initial state (corrected by the Pauli frame), against our measured data qubits to determine if a logical error occurred.
-
-
-The CUDA-Q QEC library thus provides a platform for numerical QEC experiments. The `qec.code` can be used to analyze a variety of QEC codes (both library or user provided), with a variety of decoders (both library or user provided).
-The CUDA-Q QEC library also provides tools to speed up the automation of generating noisy data and syndromes.
-
-Addtionally, here's how to use CUDA-Q QEC to construct a multi-round parity check matrix and a custom error correction code for the circuit-level noise model experiment in Python:
-
-.. tab:: Python
-
- .. literalinclude:: ../../examples/qec/python/repetition_code_fine_grain_noise.py
- :language: python
- :start-after: [Begin Documentation]
-
-This example illustrates how to:
-
-1. Construct a multi-round parity check matrix – Users can extend a single-round parity check matrix across multiple rounds,
-incorporating measurement errors to track syndrome evolution over time. This enables more accurate circuit-level noise modeling for decoders.
-
-2. Define custom error correction circuits with precise noise injection – Using `cudaq.apply_noise`, users can introduce specific error channels
-at targeted locations within the QEC circuit. This fine-grained control allows for precise testing of how different noise sources affect logical error rates.
-
-In the previous example, we demonstrated how to introduce random X errors into each data qubit using `cudaq.apply_noise` during each round of syndrome extraction.
-CUDA-Q allows users to inject a variety of error channels at different locations within their circuits, enabling fine-grained noise modeling. The example below showcases
-additional ways to introduce errors into a quantum kernel:
-
- .. code-block:: python
-
- @cudaq.kernel
- def inject_noise_example():
- q = cudaq.qvector(3)
-
- # Apply depolarization noise to the first qubit
- cudaq.apply_noise(cudaq.DepolarizationChannel, 0.1, q[0])
-
- # Perform gate operations
- h(q[1])
- x.ctrl(q[1], q[2])
-
- # Inject a Y error into the second qubit
- cudaq.apply_noise(cudaq.YError, 0.1, q[1])
-
- # Apply a general Pauli noise channel to the third qubit, where the 3 values indicate the probability of X, Y, and Z errors.
- cudaq.apply_noise(cudaq.Pauli1, 0.1, 0.1, 0.1, q[2])
-
- # Define and apply a noise model
- noise = cudaq.NoiseModel()
- counts = cudaq.sample(inject_noise_example, noise_model=noise)
-
-For a full list of supported noise models and their parameters, refer to the `CUDA-Q documentation `_.
-
-Getting Started with the NVIDIA QLDPC Decoder
-+++++++++++++++++++++++++++++++++++++++++++++
-
-Starting with CUDA-Q QEC v0.2, a GPU-accelerated decoder is included with the
-CUDA-Q QEC library. The library follows the CUDA-Q decoder Python and C++ interfaces
-(namely :class:`cudaq_qec.Decoder` for Python and
-:cpp:class:`cudaq::qec::decoder` for C++), but as documented in the API sections
-(:ref:`nv_qldpc_decoder_api_python` for Python and
-:ref:`nv_qldpc_decoder_api_cpp` for C++), there are many configuration options
-that can be passed to the constructor. The following example shows how to
-exercise the decoder using non-trivial pre-generated test data. The test data
-was generated using scripts originating from the GitHub repo for
-`BivariateBicycleCodes
-`_ [#f1]_; it includes parity
-check matrices (PCMs) and test syndromes to exercise a decoder.
-
-.. literalinclude:: ../../examples/qec/python/nv-qldpc-decoder.py
- :language: python
- :start-after: [Begin Documentation]
-
-.. rubric:: Footnotes
-
-.. [#f1] [BCGMRY] Sergey Bravyi, Andrew Cross, Jay Gambetta, Dmitri Maslov, Patrick Rall, Theodore Yoder, High-threshold and low-overhead fault-tolerant quantum memory https://arxiv.org/abs/2308.07915
diff --git a/docs/sphinx/examples_rst/qec/code_capacity_noise.rst b/docs/sphinx/examples_rst/qec/code_capacity_noise.rst
deleted file mode 100644
index 03bbee2f..00000000
--- a/docs/sphinx/examples_rst/qec/code_capacity_noise.rst
+++ /dev/null
@@ -1,86 +0,0 @@
-Quantum Error Correction with Code-Capacity Noise Modeling
-----------------------------------------------------------
-
-Quantum error correction (QEC) describes a set of tools used to detect and correct errors which occur to qubits on quantum computers.
-This example will walk through how the CUDA-Q QEC library handles two of the most common objects in QEC: stabilizer codes, and decoders.
-A stabilizer code is the quantum generalization of linear codes in classical error correction, which use parity checks to detect errors on noise bits.
-In QEC, we'll perform stabilizer measurements on ancilla qubits to check the parity of our data qubits.
-These stabilizer measurements are non-destructive, and thus allow us to check the relative parity of qubits without destroying our quantum information.
-
-For example, if we prepare two qubits in the state `\Psi = a|00> + b|11>`, we maybe want to check if a bit-flip error happened.
-We can measure the stabilizer `ZZ`, which will return 0 if there are no errors or even number of errors, but will return 1 if either has flipped.
-This is how we can perform parity checks in quantum computing, without performing destructive measurements which collapse our superposition.
-How these measurements are physically performed can be seen in the circuit-level noise QEC example.
-
-We can specify a stabilizer code with either a list of stabilizer operators (like `ZZ` above), or equivalently, a parity check matrix.
-We can think of the columns of a parity check matrix as the types of errors that can occur. In this case, each qubit can experience a bit flip `X` or a phase flip `Z` error, so the parity check matrix will have 2N columns where N is the number of data qubits.
-Each row represents a stabilizer, or a parity check.
-The values are either 0 or 1, where a 1 means that the corresponding column does participate in the parity check, and a 0 means it does not.
-Therefore, if a single `X/Z` error happens to a qubit, the supported rows of the parity check matrix will trigger.
-This is called the syndrome, a string of 0's and 1's corresponding to which parity checks were violated.
-A special class of stabilizer codes are called CSS (Calderbank-Shor-Steane) codes, which means the `X` and `Z` components of their parity check matrix can be separated.
-
-This brings us to decoding. Decoding is the act of solving the problem: given a syndrome, which underlying errors are most likely?
-There are many decoding algorithms, but this example will use a simple single-error look-up table.
-This means that the decoder will enumerate for each single error bit string, what the resulting syndromes are.
-Then given a syndrome, it will look up the error string and return that as a result.
-
-The last thing we need, is a way to generate errors.
-This example will go through a code capacity noise model where we have an independent and identical chance that an `X` or `Z` error happens on each qubit with some probability `p`.
-
-CUDA-Q QEC Implementation
-+++++++++++++++++++++++++++++
-Here's how to use CUDA-Q QEC to perform a code capacity noise model experiment in both Python and C++:
-
-.. tab:: Python
-
- .. literalinclude:: ../../examples/qec/python/code_capacity_noise.py
- :language: python
- :start-after: [Begin Documentation]
-
-.. tab:: C++
-
- .. literalinclude:: ../../examples/qec/cpp/code_capacity_noise.cpp
- :language: cpp
- :start-after: [Begin Documentation]
-
- Compile and run with
-
- .. code-block:: bash
-
- nvq++ --enable-mlir --target=stim -lcudaq-qec code_capacity_noise.cpp -o code_capacity_noise
- ./code_capacity_noise
-
-
-Code Explanation
-++++++++++++++++
-
-1. QEC Code type:
- - CUDA-Q QEC centers around the `qec.code` type, which contains the data relevant for a given code.
- - In particular, this represents a collection of qubits which represent a single logical qubit.
- - Here we get one of the most well known QEC codes, the Steane code, with the `qec.get_code` function.
- - We can get the stabilizers from a code with the `code.get_stabilizers()` function.
- - In this example, we get the parity check matrix of the code. Because the Steane code is a CSS code, we can extract just the `Z` components of the parity check matrix.
- - Here, we see this matrix has 3 rows and 7 columns, which means there are 7 data qubits (7 possible single bit-flip errors) and 3 Z-stabilizers (parity checks). Note that `Z` stabilizers check for `X` type errors.
- - Lastly, we get the logical `Z` observable for the code. This will allow us to see if the `Z` observable of our logical qubit has flipped.
-
-2. Decoder type:
- - A single-error look-up table (LUT) decoder can be acquired with the `qec.get_decoder` call.
- - Passing in the parity check matrix gives the decoder the required information to associated syndromes with underlying error mechanisms.
- - Once the decode has been constructed, the `decoder.decode(syndrome)` member function is called, which returns a predicted error given the syndrome.
-
-3. Noise model:
- - To generate noisy data, we call `qec.generate_random_bit_flips(nBits, p)` which will return an array of bits, where each bit has probability `p` to have been flipped into 1, and a `1-p` chance to have remained 0.
- - Since we are using the `Z` parity check matrix `H_Z`, we want to simulate random `X` errors on our 7 data qubits.
-
-4. Logical Errors:
- - Once we have noisy data, we see what the resulting syndromes are by multiplying our noisy data vector with our parity check matrix (mod 2).
- - From this syndrome, we see what the decoder predicts what errors occurred in the data.
- - To classify as a logical error, the decoder does not need to exactly guess what happened to the data, but if there was a flip in the logical observable or not.
- - If the decoder guesses this successfully, we have corrected the quantum error. If not, we have incurred a logical error.
-
-5. Further automation:
- - While this workflow is nice for seeing things step by step, the `qec.sample_code_capacity` API is provided to generate a batch of noisy data and their corresponding syndromes.
-
-The CUDA-Q QEC library thus provides a platform for numerical QEC experiments. The `qec.code` can be used to analyze a variety of QEC codes (both library or user provided), with a variety of decoders (both library or user provided).
-The CUDA-Q QEC library also provides tools to speed up the automation of generating noisy data and syndromes.
diff --git a/docs/sphinx/examples_rst/qec/examples.rst b/docs/sphinx/examples_rst/qec/examples.rst
deleted file mode 100644
index 606f2fa6..00000000
--- a/docs/sphinx/examples_rst/qec/examples.rst
+++ /dev/null
@@ -1,11 +0,0 @@
-*************************
-CUDA-Q QEC by Example
-*************************
-
-Examples that illustrate how to use CUDA-QX for application development are available in C++ and Python.
-
-.. toctree::
- :maxdepth: 1
-
- Code-Capacity-QEC
- Circuit-Level-QEC
diff --git a/docs/sphinx/examples_rst/solvers/adapt.rst b/docs/sphinx/examples_rst/solvers/adapt.rst
deleted file mode 100644
index ba801c0f..00000000
--- a/docs/sphinx/examples_rst/solvers/adapt.rst
+++ /dev/null
@@ -1,41 +0,0 @@
-ADAPT-VQE
----------
-
-ADAPT-VQE is an advanced quantum algorithm designed to improve upon the
-standard Variational Quantum Eigensolver (VQE) approach for solving quantum
-chemistry problems. It addresses key challenges faced by traditional VQE
-methods by dynamically constructing a problem-specific ansatz, offering
-several advantages:
-
-- Faster convergence: Adaptively selects the most impactful operators, potentially achieving convergence more quickly than fixed-ansatz VQE methods.
-- Enhanced efficiency: Builds a compact ansatz tailored to the specific problem, potentially reducing overall circuit depth.
-- Increased accuracy: Has demonstrated the ability to outperform standard VQE approaches in terms of accuracy for certain molecular systems.
-- Adaptability: Automatically adjusts to different molecular systems without requiring significant user intervention or prior knowledge of the system's electronic structure.
-
-The ADAPT-VQE algorithm works by iteratively growing the quantum circuit
-ansatz, selecting operators from a predefined pool based on their gradient
-magnitudes. This adaptive approach allows the algorithm to focus
-computational resources on the most relevant aspects of the problem,
-potentially leading to more efficient and accurate simulations of molecular
-systems on quantum computers.
-
-Here we demonstrate how to use the CUDA-Q Solvers library to execute the ADAPT-VQE algorithm.
-
-.. tab:: Python
-
- .. literalinclude:: ../../examples/solvers/python/adapt_h2.py
- :language: python
- :start-after: [Begin Documentation]
-
-.. tab:: C++
-
- .. literalinclude:: ../../examples/solvers/cpp/adapt_h2.cpp
- :language: cpp
- :start-after: [Begin Documentation]
-
- Compile and run with
-
- .. code:: bash
-
- nvq++ --enable-mlir -lcudaq-solvers adapt_h2.cpp -o adapt_h2
- ./adapt_h2
diff --git a/docs/sphinx/examples_rst/solvers/examples.rst b/docs/sphinx/examples_rst/solvers/examples.rst
deleted file mode 100644
index 75ec8d71..00000000
--- a/docs/sphinx/examples_rst/solvers/examples.rst
+++ /dev/null
@@ -1,13 +0,0 @@
-*************************
-CUDA-Q Solvers by Example
-*************************
-
-Examples that illustrate how to use CUDA-QX for application development are available in C++ and Python.
-
-.. toctree::
- :maxdepth: 1
-
- Molecular-Hamiltonians
- ADAPT-VQE
- VQE
- QAOA
diff --git a/docs/sphinx/examples_rst/solvers/molecular_hamiltonians.rst b/docs/sphinx/examples_rst/solvers/molecular_hamiltonians.rst
deleted file mode 100644
index 8ba2d754..00000000
--- a/docs/sphinx/examples_rst/solvers/molecular_hamiltonians.rst
+++ /dev/null
@@ -1,103 +0,0 @@
-Generating Molecular Hamiltonians
-----------------------------------
-
-The CUDA-Q Solvers library accelerates a wide range of applications in the domain of quantum chemistry.
-To facilitate these calculations, CUDA-Q Solvers provides the `solver.create_molecule` function to allow users to generate basis sets and Hamiltonians for many systems of interest.
-The molecule class contains basis set informations, and the Hamiltonian (`molecule.hamiltonian`) for the target systems.
-These Hamiltonians can then be used as input into the hybrid quantum-classical solvers that the CUDA-Q Solvers API provides.
-
-
-Molecular Orbitals and Hamiltonians
-+++++++++++++++++++++++++++++++++++
-
-First we define the atomic geometry of the molecule by specifying a array of atomic symbols as strings, and coordinates in 3D space. We then get a molecule object from the `solvers.create_molecule` call.
-Here we create "default" Hamiltonian for the N2 system using complete active space molecular orbitals constructed from Hartree-Fock atomic orbitals.
-
-.. tab:: Python
-
- .. code-block:: python
-
- geometry = [('N', (0.0, 0.0, 0.5600)), ('N', (0.0, 0.0, -0.5600))]
- molecule = solvers.create_molecule(geometry,
- 'sto-3g',
- 0,
- 0,
- nele_cas=2,
- norb_cas=3,
- verbose=True)
-
-We specify:
- - The geometry previously created
- - The single particle basis set (here STO-3G)
- - The total spin
- - The total charge
- - The number of electrons in the complete active space
- - The number of orbitals in the complete activate space
- - A verbosity flag to help introspect on the data what was generated.
-
-Along with the orbitals and Hamiltonian, we can also view various properties like the Hartree-Fock energy, and the energy of the frozen core orbitals by printing `molecule.energies`.
-
-Natural Orbitals from MP2
-++++++++++++++++++++++++++
-Now we take our same N2 molecule, but generate natural orbitals from second order Møller–Plesset perturbation theory as the basis.
-
-.. tab:: Python
-
- .. code-block:: python
-
- geometry = [('N', (0.0, 0.0, 0.5600)), ('N', (0.0, 0.0, -0.5600))]
- molecule = solvers.create_molecule(geometry,
- 'sto-3g',
- 0,
- 0,
- nele_cas=2,
- norb_cas=3,
- MP2=True,
- integrals_natorb=True,
- verbose=True)
-
-Note that we use the same API but,toggle `MP2=True` and `integrals_natorb=True`.
-
-CASSCF Orbitals
-+++++++++++++++
-
-Next, we can start from either Hartree-Fock or perturbation theory atomic orbitals and build complete active space self-consistent field (CASSCF) molecular orbitals.
-
-.. tab:: Python
-
- .. code-block:: python
-
- geometry = [('N', (0.0, 0.0, 0.5600)), ('N', (0.0, 0.0, -0.5600))]
- molecule = solvers.create_molecule(geometry,
- 'sto-3g',
- 0,
- 0,
- nele_cas=2,
- norb_cas=3,
- casscf=True,
- integrals_casscf=True,
- verbose=True)
-
-For Hartree-Fock, or
-
-.. tab:: Python
-
- .. code-block:: python
-
- geometry = [('N', (0.0, 0.0, 0.5600)), ('N', (0.0, 0.0, -0.5600))]
- molecule = solvers.create_molecule(geometry,
- 'sto-3g',
- 0,
- 0,
- nele_cas=2,
- norb_cas=3,
- MP2=True,
- natorb=True,
- casscf=True,
- integrals_casscf=True,
- verbose=True)
-
-for MP2. In these cases, printing the `molecule.energies` also shows the `R-CASSCF` energy for the system.
-
-Now that we have seen how to generate basis sets and Hamiltonians for quantum chemistry systems, we can use these as inputs to hybrid quantum-classical methods like VQE or adapt VQE via the CUDA-Q Solvers API.
-
diff --git a/docs/sphinx/examples_rst/solvers/qaoa.rst b/docs/sphinx/examples_rst/solvers/qaoa.rst
deleted file mode 100644
index eb036228..00000000
--- a/docs/sphinx/examples_rst/solvers/qaoa.rst
+++ /dev/null
@@ -1,62 +0,0 @@
-Quantum Approximate Optimization Algorithm (QAOA)
--------------------------------------------------
-
-The Quantum Approximate Optimization Algorithm (QAOA) is a hybrid quantum-classical algorithm that solves combinatorial optimization problems.
-
-Key features of QAOA:
-
-- Hybrid approach: Utilizes both quantum and classical resources efficiently.
-- Iterative optimization: Classical optimizer adjusts circuit parameters to minimize energy.
-- NISQ compatibility: This algorithm is designed to run on the noisy quantum computers of today.
-- Flexibility: Can be applied to various problems in quantum chemistry and optimization problems broadly.
-
-.. tab:: Python
-
- .. literalinclude:: ../../examples/solvers/python/molecular_docking_qaoa.py
- :language: python
- :start-after: [Begin Documentation]
-
-.. tab:: C++
-
- .. literalinclude:: ../../examples/solvers/cpp/molecular_docking_qaoa.cpp
- :language: cpp
- :start-after: [Begin Documentation]
-
- Compile and run with
-
- .. code-block:: bash
-
- nvq++ --enable-mlir -lcudaq-solvers molecular_docking_qaoa.cpp -o molecular_docking_qaoa
- ./molecular_docking_qaoa
-
-CUDA-Q Solvers Implementation
-+++++++++++++++++++++++++++++
-Here's how to use CUDA-Q Solvers to solve the Maximum Clique Problem using QAOA:
-
-Code Explanation
-++++++++++++++++
-1. Graph Creation:
- - A NetworkX graph is created to represent the problem.
- - Nodes and edges are added with specific weights.
-
-2. Clique Hamiltonian Generation:
- - `solvers.get_clique_hamiltonian` is used to create the Hamiltonian for the Maximum Clique Problem.
- - The penalty term and number of QAOA layers are defined.
-
-3. QAOA Parameter Setup:
- - The number of required parameters is calculated using `solvers.get_num_qaoa_parameters`.
- - Randomly generate initial parameters.
-
-4. QAOA Execution with `solvers.qaoa`:
- - Call the solver with the Hamiltonian, number of QAOA layers, and whether you want full parametrization and counterdiabatic driving.
- - Full parameterization: Uses an optimization parameter for every term in the clique Hamiltonian and the mixer Hamiltonian.
- - Counterdiabatic driving: Adds extra Ry rotations at the end of each layer.
-
-5. Results Analysis:
- - The optimal energy, sampled states, and most probable configuration are printed.
-
-This implementation showcases the power of CUDA-Q Solvers in solving combinatorial optimization problems using hybrid quantum-classical algorithms.
-By using CUDA-Q Solvers with the networkx library, we very quickly set up and ran a QAOA application to compute optimal configurations for a molecular docking problem.
-
-
-
diff --git a/docs/sphinx/examples_rst/solvers/vqe.rst b/docs/sphinx/examples_rst/solvers/vqe.rst
deleted file mode 100644
index 767132be..00000000
--- a/docs/sphinx/examples_rst/solvers/vqe.rst
+++ /dev/null
@@ -1,68 +0,0 @@
-Variational Quantum Eigensolver (VQE)
--------------------------------------
-
-The Variational Quantum Eigensolver (VQE) is a hybrid quantum-classical algorithm designed to find the ground state energy of a quantum system. It combines quantum computation with classical optimization to iteratively improve an approximation of the ground state.
-
-Key features of VQE:
-
-- Hybrid approach: Utilizes both quantum and classical resources efficiently.
-- Variational method: Uses a parameterized quantum circuit (ansatz) to prepare trial states.
-- Iterative optimization: Classical optimizer adjusts circuit parameters to minimize energy.
-- Flexibility: Can be applied to various problems in quantum chemistry and materials science.
-
-VQE Algorithm Overview:
-
-1. Prepare an initial quantum state using a parameterized circuit (ansatz).
-2. Measure the expectation value of the Hamiltonian.
-3. Use a classical optimizer to adjust circuit parameters.
-4. Repeat steps 1-3 until convergence or a stopping criterion is met.
-
-CUDA-Q Solvers Implementation
-+++++++++++++++++++++++++++++
-
-CUDA-Q Solvers provides a high-level interface for running VQE simulations. Here's how to use it in both Python and C++:
-
-.. tab:: Python
-
- .. literalinclude:: ../../examples/solvers/python/uccsd_vqe.py
- :language: python
- :start-after: [Begin Documentation]
-
-.. tab:: C++
-
- .. literalinclude:: ../../examples/solvers/cpp/uccsd_vqe.cpp
- :language: cpp
- :start-after: [Begin Documentation]
-
- Compile and run with
-
- .. code-block:: bash
-
- nvq++ --enable-mlir -lcudaq-solvers uccsd_vqe.cpp -o uccsd_vqe
- ./uccsd_vqe
-
-Code Explanation
-++++++++++++++++
-
-1. Molecule Creation:
- - Both examples start by defining the molecular geometry (H2 molecule).
- - The `create_molecule` function generates the molecular Hamiltonian.
-
-2. Ansatz Definition:
- - The UCCSD (Unitary Coupled Cluster Singles and Doubles) ansatz is used.
- - In Python, it's defined as a `cudaq.kernel`.
- - In C++, it's defined as a lambda function within the VQE call.
-
-3. VQE Execution:
- - The `solvers.vqe` function (Python) or `solvers::vqe` (C++) is called.
- - It takes the ansatz, Hamiltonian, initial parameters, and optimization settings.
-
-4. Optimization:
- - Python uses SciPy's `minimize` function with L-BFGS-B method.
- - C++ uses CUDA-Q Solvers' built-in optimizer.
- - Either language can make use of CUDA-QX builtin optimizers.
-
-5. Results:
- - Both versions print the final ground state energy.
-
-The CUDA-Q Solvers implementation of VQE provides a high-level interface that handles the quantum-classical hybrid optimization loop, making it easy to apply VQE to molecular systems. Users can focus on defining the problem (molecule and ansatz) while CUDA-Q Solvers manages the complex interaction between quantum and classical resources.
diff --git a/docs/sphinx/index.rst b/docs/sphinx/index.rst
deleted file mode 100644
index 15153ebf..00000000
--- a/docs/sphinx/index.rst
+++ /dev/null
@@ -1,66 +0,0 @@
-CUDA-QX - The CUDA-Q Libraries Collection
-==========================================
-
-CUDA-QX is a collection of libraries that build upon the CUDA-Q programming model
-to enable the rapid development of hybrid quantum-classical application code leveraging
-state-of-the-art CPUs, GPUs, and QPUs. It provides a collection of C++
-libraries and Python packages that enable research, development, and application
-creation for use cases in quantum error correction and hybrid quantum-classical
-solvers.
-
-.. toctree::
- :maxdepth: 2
- :caption: Getting Started
-
- quickstart/installation
-
-.. toctree::
- :maxdepth: 1
- :caption: Libraries
-
- components/qec/introduction
- components/solvers/introduction
-
-.. toctree::
- :maxdepth: 2
- :caption: Examples
-
- examples_rst/qec/examples
- examples_rst/solvers/examples
-
-.. toctree::
- :maxdepth: 1
- :caption: API Reference
-
- api/core/cpp_api
- api/qec/cpp_api
- api/qec/python_api
- api/solvers/cpp_api
- api/solvers/python_api
-
-Key Features
--------------
-
-CUDA-QX is composed of two distinct libraries that build upon CUDA-Q programming model.
-The libraries provided are cudaq-qec, a library enabling performant research workflows
-for quantum error correction, and cudaq-solvers, a library that provides high-level
-APIs for common quantum-classical solver workflows.
-
-* **cudaq-qec**: Quantum Error Correction Library
- * Extensible framework describing quantum error correcting codes as a collection of CUDA-Q kernels.
- * Extensible framework for describing syndrome decoders
- * State-of-the-art, performant decoder implementations on NVIDIA GPUs (coming soon)
- * Pre-built numerical experiment APIs
-
-* **cudaq-solvers**: Performant Quantum-Classical Simulation Workflows
- * Variational Quantum Eigensolver (VQE)
- * ADAPT-VQE implementation that scales via CUDA-Q MQPU.
- * Quantum Approximate Optimization Algorithm (QAOA)
- * More to come...
-
-Indices and Tables
-------------------
-
-* :ref:`genindex`
-* :ref:`modindex`
-* :ref:`search`
diff --git a/docs/sphinx/quickstart/installation.rst b/docs/sphinx/quickstart/installation.rst
deleted file mode 100644
index ff68e262..00000000
--- a/docs/sphinx/quickstart/installation.rst
+++ /dev/null
@@ -1,151 +0,0 @@
-Installation Guide
-==================
-
-Installation Methods
---------------------
-
-CUDA-QX provides multiple installation methods to suit your needs:
-
-pip install
-^^^^^^^^^^^^
-
-The simplest way to install CUDA-QX is via pip. (If you're on Mac, your only
-option is to use the Docker container as described below.) For pip, you can
-install individual components:
-
-.. code-block:: bash
-
- # Install QEC library
- pip install cudaq-qec
-
- # Install Solvers library
- pip install cudaq-solvers
-
- # Install both libraries
- pip install cudaq-qec cudaq-solvers
-
-.. note::
-
- CUDA-Q Solvers will require the presence of :code:`libgfortran`, which is
- not distributed with the Python wheel, for provided classical optimizers. If
- :code:`libgfortran` is not installed, you will need to install it via your
- distribution's package manager. On Debian based systems, you can install
- this with :code:`apt-get install gfortran`.
-
-Docker Container
-^^^^^^^^^^^^^^^^
-
-CUDA-QX is available as a Docker container with all dependencies pre-installed:
-
-1. Pull the container:
-
-.. code-block:: bash
-
- docker pull ghcr.io/nvidia/cudaqx
-
-2. Run the container:
-
-.. code-block:: bash
-
- docker run --gpus all -it ghcr.io/nvidia/cudaqx
-
-.. note::
-
- If your system does not have local GPUs (eg. a MacBook), omit the `--gpus all`
- argument.
-
-The container includes:
- * CUDA-Q compiler and runtime
- * CUDA-QX libraries (QEC and Solvers)
- * All required dependencies
- * Example notebooks and tutorials
-
-Building from Source
-^^^^^^^^^^^^^^^^^^^^
-
-Prerequisites
-~~~~~~~~~~~~~
-
-Before building CUDA-QX from source, ensure your system meets the following requirements:
-
-* **CUDA-Q**: The NVIDIA quantum-classical programming model
-* **CMake**: Version 3.28 or higher (``pip install "cmake<4"``), less than 4.0
-* **GCC**: Version 11 or higher
-* **Python**: Version 3.10, 3.11, or 3.12
-* **NVIDIA GPU**: CUDA-capable GPU with compute capability 12.0 or higher
-* **Git**: For cloning the repository
-
-Build Instructions
-~~~~~~~~~~~~~~~~~~~
-
-1. Clone the repository:
-
-.. code-block:: bash
-
- git clone https://github.com/nvidia/cudaqx
- cd cudaqx
-
-2. Create and enter build directory:
-
-.. code-block:: bash
-
- mkdir build && cd build
-
-3. Configure with CMake:
-
-.. code-block:: bash
-
- cmake .. -G Ninja \
- -DCUDAQX_ENABLE_LIBS="all" \
- -DCUDAQX_INCLUDE_TESTS=ON \
- -DCUDAQX_BINDINGS_PYTHON=ON \
- -DCUDAQ_DIR=$HOME/.cudaq/lib/cmake/cudaq \
- -DCMAKE_CXX_FLAGS="-Wno-attributes" \
- -DCMAKE_BUILD_TYPE=Release \
- -DCMAKE_INSTALL_PREFIX=$HOME/.cudaqx
-
-4. Build and install:
-
-.. code-block:: bash
-
- ninja install
-
-CMake Build Options
-~~~~~~~~~~~~~~~~~~~~
-
-* ``CUDAQX_ENABLE_LIBS``: Specify which libraries to build (``all``, ``qec``, ``solvers``)
-* ``CUDAQX_INCLUDE_TESTS``: Enable building of tests
-* ``CUDAQX_BINDINGS_PYTHON``: Enable Python bindings
-* ``CUDAQ_DIR``: Path to CUDA-Q installation
-* ``CMAKE_INSTALL_PREFIX``: Installation directory
-
-Verifying Installation
------------------------
-
-To verify your installation, run the following Python code:
-
-.. code-block:: python
-
- import cudaq_qec as qec
- import cudaq_solvers as solvers
-
-
-Troubleshooting (Common Issues)
---------------------------------
-
-1. **CMake configuration fails**:
- * Ensure CUDA-Q is properly installed
- * Verify CMake version (``cmake --version``)
- * Check GCC version (``gcc --version``)
-
-2. **CUDA device not found**:
- * Verify NVIDIA driver installation
- * Check CUDA toolkit installation
- * Ensure GPU compute capability is supported
-
-3. **Python bindings not found**:
- * Confirm ``CUDAQX_BINDINGS_PYTHON=ON`` during build
- * Check Python environment activation
- * Verify installation path is in ``PYTHONPATH``
-
-For additional support, please visit our `GitHub Issues `_ page.
diff --git a/libs/qec/include/cudaq/qec/codes/surface_code.h b/libs/qec/include/cudaq/qec/codes/surface_code.h
index 2abeb408..c7096ad6 100644
--- a/libs/qec/include/cudaq/qec/codes/surface_code.h
+++ b/libs/qec/include/cudaq/qec/codes/surface_code.h
@@ -1,5 +1,5 @@
/****************************************************************-*- C++ -*-****
- * Copyright (c) 2024 NVIDIA Corporation & Affiliates. *
+ * Copyright (c) 2024 - 2025 NVIDIA Corporation & Affiliates. *
* All rights reserved. *
* *
* This source code and the accompanying materials are made available under *
@@ -251,6 +251,9 @@ class surface_code : public cudaq::qec::code {
std::size_t get_num_ancilla_z_qubits() const override;
public:
+ /// @brief Grid to keep track of topological arrangement of qubits.
+ stabilizer_grid grid;
+
/// @brief Constructor for the surface_code
surface_code(const heterogeneous_map &);
// Grid constructor would be useful
@@ -261,9 +264,6 @@ class surface_code : public cudaq::qec::code {
const cudaqx::heterogeneous_map &options) {
return std::make_unique(options);
})
-
- /// @brief Grid to keep track of topological arrangement of qubits.
- stabilizer_grid grid;
};
} // namespace cudaq::qec::surface_code
diff --git a/libs/qec/python/cudaq_qec/__init__.py b/libs/qec/python/cudaq_qec/__init__.py
index ca0e55b0..20ede4e7 100644
--- a/libs/qec/python/cudaq_qec/__init__.py
+++ b/libs/qec/python/cudaq_qec/__init__.py
@@ -21,6 +21,7 @@
get_available_codes = qecrt.get_available_codes
get_decoder = qecrt.get_decoder
DecoderResult = qecrt.DecoderResult
+AsyncDecoderResult = qecrt.AsyncDecoderResult
generate_random_bit_flips = qecrt.generate_random_bit_flips
sample_memory_circuit = qecrt.sample_memory_circuit
sample_code_capacity = qecrt.sample_code_capacity
diff --git a/scripts/build_docs.sh b/scripts/build_docs.sh
index ab3ff61e..02438ffb 100755
--- a/scripts/build_docs.sh
+++ b/scripts/build_docs.sh
@@ -1,7 +1,7 @@
#!/bin/bash
# ============================================================================ #
-# Copyright (c) 2024 NVIDIA Corporation & Affiliates. #
+# Copyright (c) 2024 - 2025 NVIDIA Corporation & Affiliates. #
# All rights reserved. #
# #
# This source code and the accompanying materials are made available under #
@@ -44,34 +44,10 @@ dialect_output_dir="$docs_build_output/Dialects"
rm -rf "$docs_build_output"
mkdir -p "$docs_build_output"
-doxygen_exe=doxygen
-
-# Create the conf.py file needed by Sphinx
-echo "Generating conf.py ..."
-sphinx_conf_in="$repo_root/docs/sphinx/conf.py.in"
-sphinx_conf="$repo_root/docs/sphinx/conf.py"
-
-# Verify that the input file exists before proceeding
-if [ ! -f "$sphinx_conf_in" ]; then
- echo "Error: Sphinx configuration template '$sphinx_conf_in' does not exist." >&2
- exit 1
-fi
-
-# Replace placeholders of the form @VAR@ in the template file with their variable values.
-CUDAQ_INSTALL_DIR=${CUDAQ_INSTALL_DIR:-"$HOME/.cudaq"}
-CMAKE_BINARY_DIR="$repo_root/build"
-SPHINX_SOURCE="$repo_root/docs/sphinx"
-
-sed -e "s|@CUDAQ_INSTALL_DIR@|${CUDAQ_INSTALL_DIR}|g" \
- -e "s|@CMAKE_BINARY_DIR@|${CMAKE_BINARY_DIR}|g" \
- -e "s|@SPHINX_SOURCE@|${SPHINX_SOURCE}|g" \
- "$sphinx_conf_in" > "$sphinx_conf"
-
-echo "Configuration file created at: $sphinx_conf"
-
# Generate API documentation using Doxygen
echo "Generating XML documentation using Doxygen..."
mkdir -p "${doxygen_output_dir}"
+doxygen_exe=doxygen
doxygen_input="$repo_root/docs/Doxyfile.in"
# Get all the headers
@@ -97,40 +73,10 @@ if [ ! "$doxygen_exit_code" -eq "0" ]; then
docs_exit_code=11
fi
-echo "Building CUDA-QX documentation using Sphinx..."
-cd "$repo_root/docs"
-# The docs build so far is fast such that we do not care about the cached outputs.
-# Revisit this when caching becomes necessary.
-
-rm -rf sphinx/_doxygen/
-rm -rf sphinx/_mdgen/
-cp -r "$doxygen_output_dir" sphinx/_doxygen/
-# cp -r "$dialect_output_dir" sphinx/_mdgen/ # uncomment once we use the content from those files
-
-rm -rf "$sphinx_output_dir"
-sphinx-build -v -n --keep-going -b html \
- -Dbreathe_projects.cudaqx="${doxygen_output_dir}/xml" \
- sphinx "$sphinx_output_dir" -j auto #2> "$logs_dir/sphinx_error.txt" 1> "$logs_dir/sphinx_output.txt"
-
-sphinx_exit_code=$?
-if [ ! "$sphinx_exit_code" -eq "0" ]; then
- echo "Failed to generate documentation using sphinx-build."
- echo "Sphinx exit code: $sphinx_exit_code"
- echo "======== logs ========"
- cat "$logs_dir/sphinx_output.txt" "$logs_dir/sphinx_error.txt"
- echo "======================"
- docs_exit_code=12
-fi
-
-rm -rf sphinx/_doxygen/
-rm -rf sphinx/_mdgen/
-
mkdir -p "$DOCS_INSTALL_PREFIX"
if [ "$docs_exit_code" -eq "0" ]; then
- cp -r "$sphinx_output_dir"/* "$DOCS_INSTALL_PREFIX"
- touch "$DOCS_INSTALL_PREFIX/.nojekyll"
+ cp -r "$doxygen_output_dir"/xml/* "$DOCS_INSTALL_PREFIX"
echo "Documentation was generated in $DOCS_INSTALL_PREFIX."
- echo "To browse it, open this url in a browser: file://$DOCS_INSTALL_PREFIX/index.html"
else
echo "Documentation generation failed with exit code $docs_exit_code."
echo "Check the logs in $logs_dir, and the documentation build output in $docs_build_output."