diff --git a/.gitignore b/.gitignore index 69c11f92d705..bd73f4508758 100644 --- a/.gitignore +++ b/.gitignore @@ -20,7 +20,7 @@ __pycache__/ *.so # The C API header is generated automatically, therefore we do not upload it. -qiskit.h +qiskit.h # Distribution / packaging .Python @@ -145,6 +145,7 @@ qiskit/quantum_info/states/cython/*.cpp /docs/stubs /docs/locale /executed_tutorials +/docs/xml # Notebook testing images test/visual/mpl/circuit/circuit_results/*.png diff --git a/Makefile b/Makefile index 38585310f324..4922bd151ba7 100644 --- a/Makefile +++ b/Makefile @@ -89,7 +89,7 @@ cformat: # Build C API crate and header cbuild: cargo build --release --no-default-features --features cbinding - cbindgen --crate qiskit-c-ext --output test/c/qiskit.h --lang C + cbindgen --crate qiskit-c-ext --output qiskit.h --lang C # Use ctest to run C API tests ctest: cbuild diff --git a/crates/c_ext/cbindgen.toml b/crates/c_ext/cbindgen.toml index 6673cbb3bcf6..5d7971faadac 100644 --- a/crates/c_ext/cbindgen.toml +++ b/crates/c_ext/cbindgen.toml @@ -10,4 +10,4 @@ parse_deps = true include = ["qiskit-accelerate"] [enum] -prefix_with_name = true \ No newline at end of file +prefix_with_name = true diff --git a/crates/c_ext/src/sparse_observable.rs b/crates/c_ext/src/sparse_observable.rs index 25d59017018d..8b3015034d5c 100644 --- a/crates/c_ext/src/sparse_observable.rs +++ b/crates/c_ext/src/sparse_observable.rs @@ -13,6 +13,7 @@ use num_complex::Complex64; use qiskit_accelerate::sparse_observable::{BitTerm, SparseObservable, SparseTerm}; +/// @ingroup PauliTermVec /// A Pauli term vector, containing ``(index, bit_term)`` tuples. #[derive(Debug, Clone)] pub struct PauliTermVec { @@ -22,6 +23,7 @@ pub struct PauliTermVec { bit_terms: Vec, } +/// @ingroup PauliTerm /// A struct representing a (Pauli, qubit index) tuple. #[repr(C)] pub struct PauliTerm { @@ -29,17 +31,18 @@ pub struct PauliTerm { index: u32, } +/// @ingroup PauliTerm /// Free the Pauli term. /// /// @param A pointer to the Pauli term struct. /// /// Example: -/// +/// /// SparseObservable *obs = obs_zero(100); /// PauliTermVec *paulis = paulis_new(); /// paulis_push(paulis, BitTerm_X, 99); // push X_99 onto the vector /// obs_push_consume(obs, paulis, 2.0); // add the Pauli term 2 * X_99 to the observable -/// +/// /// SparseTerm *term = obs_term(obs, 0); // get the 0th Pauli term in the observable /// PauliTerm *pauli = obsterm_pauli(term, 0); // get the 0th Pauli in the Pauli term /// printf("Bit term: %i, Index: %i", pauli->bit_term, pauli->index); @@ -54,6 +57,7 @@ pub extern "C" fn pauli_free(pauli: &mut PauliTerm) { } } +/// @ingroup PauliTermVec /// Create a new Pauli term vector. /// /// @return A pointer to an empty Pauli term vector. @@ -72,6 +76,7 @@ pub extern "C" fn paulis_new() -> *mut PauliTermVec { Box::into_raw(Box::new(paulis)) } +/// @ingroup PauliTermVec /// Create a new Pauli term vector, with a given capacity. /// /// @param capacity The capacity to allocate for the vector. @@ -93,6 +98,7 @@ pub extern "C" fn paulis_with_capacity(capacity: u64) -> *mut PauliTermVec { Box::into_raw(Box::new(paulis)) } +/// @ingroup PauliTermVec /// Free the Pauli term vector. /// /// @param paulis A pointer to the index vector to be freed. @@ -111,6 +117,7 @@ pub extern "C" fn paulis_free(paulis: &mut PauliTermVec) { } } +/// @ingroup PauliTermVec /// Push a new ``(bit_term, index)`` tuple onto the Pauli term vector. /// /// @param paulis A pointer to the Pauli term vector. @@ -129,6 +136,7 @@ pub extern "C" fn paulis_push(paulis: &mut PauliTermVec, bit_term: BitTerm, inde paulis.indices.push(index); } +/// @ingroup SparseObservable /// Construct the zero observable (without any terms). /// /// @param num_qubits The number of qubits the observable is defined on. @@ -146,6 +154,7 @@ pub extern "C" fn obs_zero(num_qubits: u32) -> *mut SparseObservable { Box::into_raw(Box::new(obs)) } +/// @ingroup SparseObservable /// Construct the identity observable. /// /// @param num_qubits The number of qubits the observable is defined on. @@ -163,6 +172,7 @@ pub extern "C" fn obs_identity(num_qubits: u32) -> *mut SparseObservable { Box::into_raw(Box::new(obs)) } +/// @ingroup SparseObservable /// Deallocate the observable. /// /// Memory deallocation is user responsibility. Every constructed observable @@ -183,13 +193,14 @@ pub extern "C" fn obs_free(obs: &mut SparseObservable) { } } +/// @ingroup SparseObservable /// @brief Add a term to the observable by copy. /// /// @param obs A pointer to the observable to which the term is added. /// @param paulis The Pauli term vector to add to the observable. /// @param coeff The coefficient of the term. /// -/// Example: +/// Example: /// /// u_int32_t num_qubits = 100; /// SparseObservable *obs = obs_zero(num_qubits); @@ -223,6 +234,7 @@ pub extern "C" fn obs_push_copy( obs.add_term(term.view()).unwrap(); } +/// @ingroup SparseObservable /// @brief Add a term to the observable and deallocate the memory for the indices and bit terms. /// /// @param obs A pointer to the observable to which the term is added. @@ -231,7 +243,7 @@ pub extern "C" fn obs_push_copy( /// /// @warning Panics if an index in the Pauli term is greater equal than the number of qubits. /// -/// Example: +/// Example: /// /// u_int32_t num_qubits = 100; /// SparseObservable *obs = obs_zero(num_qubits); @@ -267,6 +279,7 @@ pub extern "C" fn obs_push_consume( obs.add_term(term.view()).unwrap(); // TODO handle error } +/// @ingroup SparseObservable /// Get an observable term. /// /// @param obs A pointer to the observable. @@ -279,7 +292,7 @@ pub extern "C" fn obs_push_consume( /// SparseObservable *obs = obs_identity(100); /// SparseTerm *term = obs_term(obs, 0); /// // out-of-bounds indices will fail -/// // SparseTerm *will_fail = obs_term(obs, 1); +/// // SparseTerm *will_fail = obs_term(obs, 1); /// #[no_mangle] #[cfg(feature = "cbinding")] @@ -291,13 +304,14 @@ pub extern "C" fn obs_term(obs: &SparseObservable, index: u64) -> *mut SparseTer Box::into_raw(Box::new(term)) } +/// @ingroup SparseObservable /// Multiply the observable by a complex coefficient. /// /// @param obs A pointer to the observable. /// @param coeff The coefficient to multiply the observable with. /// /// Example: -/// +/// /// SparseObservable *obs = obs_identity(100); /// SparseObservable *result = obs_multiply(obs, 2); #[no_mangle] @@ -307,6 +321,7 @@ pub extern "C" fn obs_multiply(obs: &SparseObservable, coeff: Complex64) -> *mut Box::into_raw(Box::new(result)) } +/// @ingroup SparseObservable /// Add two observables. /// /// @param left A pointer to the left observable. @@ -315,7 +330,7 @@ pub extern "C" fn obs_multiply(obs: &SparseObservable, coeff: Complex64) -> *mut /// @return A pointer to the result ``left + right``. /// /// Example: -/// +/// /// SparseObservable *left = obs_identity(100); /// SparseObservable *right = obs_zero(100); /// SparseObservable *result = obs_add(left, right); @@ -330,6 +345,7 @@ pub extern "C" fn obs_add( Box::into_raw(Box::new(result)) } +/// @ingroup SparseObservable /// Calculate the canonical representation of the observable. /// /// @param obs A pointer to the observable. @@ -355,6 +371,7 @@ pub extern "C" fn obs_canonicalize( Box::into_raw(Box::new(result)) } +/// @ingroup SparseObservable /// Copy the observable. /// /// @param obs A pointer to the observable. @@ -373,6 +390,7 @@ pub extern "C" fn obs_copy(obs: &SparseObservable) -> *mut SparseObservable { Box::into_raw(Box::new(copied)) } +/// @ingroup SparseObservable /// Compare two observables for equality. /// /// Note that this does not compare mathematical equality, but data equality. This means @@ -394,6 +412,8 @@ pub extern "C" fn obs_copy(obs: &SparseObservable) -> *mut SparseObservable { pub extern "C" fn obs_equal(observable: &SparseObservable, other: &SparseObservable) -> bool { observable.eq(other) } + +/// @ingroup SparseObservable /// Get the number of terms in the observable. /// /// @param observable A pointer to the observable. @@ -411,6 +431,7 @@ pub extern "C" fn obs_num_terms(observable: &SparseObservable) -> u64 { observable.num_terms() as u64 } +/// @ingroup SparseObservable /// Get the number of qubits the observable is defined on. /// /// @param observable A pointer to the observable. @@ -428,6 +449,7 @@ pub extern "C" fn obs_num_qubits(observable: &SparseObservable) -> u32 { observable.num_qubits() } +/// @ingroup SparseObservable /// Print the observable. /// /// @param term A pointer to the ``SparseObservable`` to print. @@ -443,6 +465,7 @@ pub extern "C" fn obs_print(observable: &SparseObservable) { println!("{:?}", observable); } +/// @ingroup SparseTerm /// Deallocate the term. /// /// The term is **not** automatically deallocated if the observable it @@ -466,12 +489,13 @@ pub extern "C" fn obsterm_free(term: &mut SparseTerm) { } } +/// @ingroup SparseTerm /// Print a sparse term. /// /// @param term A pointer to the ``SparseTerm`` to print. /// /// Example: -/// +/// /// SparseObservable *obs = obs_identity(100); /// SparseTerm *term = obs_term(obs, 0); /// obsterm_print(term); @@ -482,6 +506,7 @@ pub extern "C" fn obsterm_print(term: &SparseTerm) { println!("{:?}", term); } +/// @ingroup SparseTerm /// Get the coefficient of a sparse term. /// /// @param term A pointer to the ``SparseTerm`` whose coefficient is returned. @@ -489,7 +514,7 @@ pub extern "C" fn obsterm_print(term: &SparseTerm) { /// @return The complex coefficient of the sparse term. /// /// Example: -/// +/// /// SparseObservable *obs = obs_identity(100); /// SparseTerm *term = obs_term(obs, 0); /// complex double coeff = obsterm_coeff(term); @@ -500,6 +525,7 @@ pub extern "C" fn obsterm_coeff(term: &SparseTerm) -> Complex64 { term.coeff() } +/// @ingroup SparseTerm /// Get the number of qubits the sparse term is defined on. /// /// @param term A pointer to the ``SparseTerm`` whose number of qubits is returned. @@ -507,7 +533,7 @@ pub extern "C" fn obsterm_coeff(term: &SparseTerm) -> Complex64 { /// @return The number of qubits the sparse term is defined on. /// /// Example: -/// +/// /// SparseObservable *obs = obs_identity(100); /// SparseTerm *term = obs_term(obs, 0); /// uint32_t num_qubits = obsterm_num_qubits(term); @@ -518,6 +544,7 @@ pub extern "C" fn obsterm_num_qubits(term: &SparseTerm) -> u32 { term.num_qubits() } +/// @ingroup SparseTerm /// Get the number of non-identity (nni) Paulis in the sparse term. /// /// @param term A pointer to the ``SparseTerm``. @@ -525,7 +552,7 @@ pub extern "C" fn obsterm_num_qubits(term: &SparseTerm) -> u32 { /// @return The number of non-identity Paulis. /// /// Example: -/// +/// /// SparseObservable *obs = obs_identity(100); /// SparseTerm *term = obs_term(obs, 0); /// uint32_t nni = obsterm_nni(term); @@ -537,6 +564,7 @@ pub extern "C" fn obsterm_nni(term: &SparseTerm) -> u32 { term.indices().len() as u32 } +/// @ingroup SparseTerm /// Get the (Pauli, qubit index) tuple inside term. /// /// @param term A pointer to the ``SparseTerm``. @@ -545,7 +573,7 @@ pub extern "C" fn obsterm_nni(term: &SparseTerm) -> u32 { /// @return The Pauli and qubit index it acts on as struct. /// /// Example: -/// +/// /// SparseObservable *obs = obs_identity(100); /// SparseTerm *term = obs_term(obs, 0); /// uint32_t nni = obsterm_nni(term); diff --git a/docs/Doxyfile b/docs/Doxyfile new file mode 100644 index 000000000000..a37630dc0a84 --- /dev/null +++ b/docs/Doxyfile @@ -0,0 +1,9 @@ +INPUT = docs/cdoc/ qiskit.h + +EXTRACT_ALL = YES + +GENERATE_XML = YES +XML_OUTPUT = docs/xml + +GENERATE_HTML = NO +GENERATE_LATEX = NO diff --git a/docs/apidoc/index.rst b/docs/apidoc/index.rst index 8581d56ace77..9bec3563a412 100644 --- a/docs/apidoc/index.rst +++ b/docs/apidoc/index.rst @@ -3,9 +3,9 @@ Within each section, the modules should be ordered alphabetically by module name (not RST filename). -============= -API Reference -============= +==================== +Python API Reference +==================== Circuit construction: diff --git a/docs/cdoc/index.rst b/docs/cdoc/index.rst new file mode 100644 index 000000000000..ce28556214ba --- /dev/null +++ b/docs/cdoc/index.rst @@ -0,0 +1,10 @@ +=========================== +Qiskit C API (``qiskit.h``) +=========================== + +Quantum information: + +.. toctree:: + :maxdepth: 1 + + sparse_observable diff --git a/docs/cdoc/sparse_observable.h b/docs/cdoc/sparse_observable.h new file mode 100644 index 000000000000..ff74578547a7 --- /dev/null +++ b/docs/cdoc/sparse_observable.h @@ -0,0 +1,19 @@ +/** + * @defgroup SparseObservable SparseObservable + * This is a group of functions for interacting with an opaque (Rust-space) SparseObservable + * instance. + */ + +/** + * @defgroup SparseTerm SparseTerm + * This is a group of functions for interacting with an opaque (Rust-space) SparseTerm + * instance. + */ + +/** + * @defgroup PauliTerm PauliTerm + */ + +/** + * @defgroup PauliTermVec PauliTermVec + */ diff --git a/docs/cdoc/sparse_observable.rst b/docs/cdoc/sparse_observable.rst new file mode 100644 index 000000000000..5208dc949154 --- /dev/null +++ b/docs/cdoc/sparse_observable.rst @@ -0,0 +1,11 @@ +================= +Sparse Observable +================= + +.. doxygengroup:: SparseObservable + +.. doxygengroup:: SparseTerm + +.. doxygengroup:: PauliTerm + +.. doxygengroup:: PauliTermVec diff --git a/docs/conf.py b/docs/conf.py index 3bd1fd6516de..aaa87e1e2f18 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -49,8 +49,13 @@ "matplotlib.sphinxext.plot_directive", "reno.sphinxext", "sphinxcontrib.katex", + "breathe", ] +breathe_projects = {"qiskit": "xml/"} + +breathe_default_project = "qiskit" + templates_path = ["_templates"] # Number figures, tables and code-blocks if they have a caption. diff --git a/docs/index.rst b/docs/index.rst index 5105a1b6d7a9..60f14b0c5d20 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -11,5 +11,6 @@ https://github.com/Qiskit/documentation. :hidden: Documentation Home - API Reference + C API Reference + Python API Reference Release Notes diff --git a/requirements-dev.txt b/requirements-dev.txt index 7c5a909bd395..22e0910f24c6 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -47,3 +47,4 @@ threadpoolctl Sphinx>=6.0,<7.2 reno >= 4.1.0 sphinxcontrib-katex==0.9.9 +breathe>=4.35.0 diff --git a/test/c/CMakeLists.txt b/test/c/CMakeLists.txt index a72a6c569058..b28ef1fa1e19 100644 --- a/test/c/CMakeLists.txt +++ b/test/c/CMakeLists.txt @@ -20,6 +20,8 @@ create_test_sourcelist (source_files test_driver.c ${discovered_tests}) # Actually define the test driver program executable to be built... add_executable (test_driver ${source_files}) +# ...include the location of the header file... +target_include_directories (test_driver PRIVATE ${CMAKE_SOURCE_DIR}) # ...and linked with the qiskit library. target_link_libraries (test_driver ${qiskit}) diff --git a/tox.ini b/tox.ini index d4d822766675..0cb4f1ba6861 100644 --- a/tox.ini +++ b/tox.ini @@ -88,6 +88,7 @@ setenv = commands_pre = {[testenv]install_command} -r{toxinidir}/requirements-optional.txt commands = + doxygen docs/Doxyfile sphinx-build -W -j auto -T --keep-going -b html docs/ docs/_build/html {posargs} [testenv:docs-clean] @@ -96,4 +97,4 @@ deps = allowlist_externals = rm commands = - rm -rf {toxinidir}/docs/stubs/ {toxinidir}/docs/_build {toxinidir}/docs/locale + rm -rf {toxinidir}/docs/stubs/ {toxinidir}/docs/_build {toxinidir}/docs/locale {toxinidir}/docs/xml/