diff --git a/.github/compiler_setup.py b/.github/compiler_setup.py index 038bb47..7bd7d3d 100644 --- a/.github/compiler_setup.py +++ b/.github/compiler_setup.py @@ -2,7 +2,6 @@ import sys if __name__ == "__main__": - # TODO only for ubuntu compiler = sys.argv[1] diff --git a/.github/workflows/all_push.yml b/.github/workflows/all_push.yml index 4e8ec41..2d30e74 100644 --- a/.github/workflows/all_push.yml +++ b/.github/workflows/all_push.yml @@ -1,7 +1,5 @@ name: All push - on: [push] - jobs: build: runs-on: ${{ matrix.os }} @@ -12,42 +10,36 @@ jobs: compiler: [g++-12, clang++-17] python-version: ["3.10"] steps: - - uses: actions/checkout@v2 - with: - submodules: recursive - - - name: Setup compiler - run: python3 ./.github/compiler_setup.py ${{ matrix.compiler }} - - - name: Setup Python - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - - name: Install Python dependencies - run: python -m pip install numpy pytest cmake - - - name: Configure CMake - env: - CXX: ${{ matrix.compiler }} - run: cmake -B ${{github.workspace}}/build -DCMAKE_CXX_COMPILER=${CXX} - - - name: Build - # Build your program with the given configuration - run: | - cmake --build ${{github.workspace}}/build --verbose --parallel - du build/tests/test_pauli_op - - - name: Test C++ - env: - OMP_NUM_THREADS: 2 - run: | - # ctest --test-dir build --verbose # TODO not using bc of PauliOp problems on CI - ./build/tests/test_factory - ./build/tests/test_pauli - ./build/tests/test_pauli_op --test-case-exclude="*multistring*" - ./build/tests/test_pauli_string - ./build/tests/test_summed_pauli_op - - # - name: Test Python - # run: PYTHONPATH=build:$PYTHONPATH pytest -v test + - uses: actions/checkout@v2 + with: + submodules: recursive + - name: Setup compiler + run: python3 ./.github/compiler_setup.py ${{ matrix.compiler }} + - name: Setup Python + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install Python dependencies + run: python -m pip install numpy pytest cmake + - name: Configure CMake + env: + CXX: ${{ matrix.compiler }} + run: cmake -B ${{github.workspace}}/build -DCMAKE_CXX_COMPILER=${CXX} + - name: Build + # Build your program with the given configuration + run: | + cmake --build ${{github.workspace}}/build --verbose --parallel + du build/tests/test_pauli_op + - name: Test C++ + env: + OMP_NUM_THREADS: 2 + run: | + # ctest --test-dir build --verbose # TODO not using bc of PauliOp problems on CI + ./build/tests/test_factory + ./build/tests/test_pauli + ./build/tests/test_pauli_op --test-case-exclude="*multistring*" + ./build/tests/test_pauli_string + ./build/tests/test_summed_pauli_op + +# - name: Test Python +# run: PYTHONPATH=build:$PYTHONPATH pytest -v test diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 0000000..2a1d73c --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,12 @@ +name: pre-commit +on: + pull_request: + push: + branches: [main] +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v3 + - uses: pre-commit/action@v3.0.1 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..901f2e9 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,24 @@ +repos: + # Config files (CMake, YAML) + - repo: https://github.com/cheshirekow/cmake-format-precommit + rev: v0.6.10 + hooks: + - id: cmake-format + - repo: https://github.com/google/yamlfmt + rev: v0.10.0 + hooks: + - id: yamlfmt + # C/C++ + - repo: https://github.com/pre-commit/mirrors-clang-format + rev: v18.1.8 + hooks: + - id: clang-format + # Python + - repo: https://github.com/astral-sh/ruff-pre-commit + # Ruff version. + rev: v0.5.1 + hooks: + # Run the linter. + - id: ruff + # Run the formatter. + - id: ruff-format diff --git a/README.md b/README.md index f95d1b9..15a5b51 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,20 @@ - Tested Compilers GCC@12, LLVM@17, LLVM@18 - Python >= 3.10 +## Developer Setup + +### Dev Requirements + +- C/C++: `clang-format` defaults +- Python: `ruff` lint/format, [`pre-commit`](https://pre-commit.com/) +- CMake: `cmake-format` + +> **You need to install the `pre-commit` hooks to ensure they run before you commit code.** + +```shell +# From root project dir +pre-commit install # installs the checks as pre-commit hooks +``` ## Build and Test diff --git a/cmake/CPM.cmake b/cmake/CPM.cmake index d0fd0e8..e847861 100644 --- a/cmake/CPM.cmake +++ b/cmake/CPM.cmake @@ -3,22 +3,28 @@ # SPDX-FileCopyrightText: Copyright (c) 2019-2023 Lars Melchior and contributors set(CPM_DOWNLOAD_VERSION 0.39.0) -set(CPM_HASH_SUM "66639bcac9dd2907b2918de466783554c1334446b9874e90d38e3778d404c2ef") +set(CPM_HASH_SUM + "66639bcac9dd2907b2918de466783554c1334446b9874e90d38e3778d404c2ef") if(CPM_SOURCE_CACHE) - set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") + set(CPM_DOWNLOAD_LOCATION + "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") elseif(DEFINED ENV{CPM_SOURCE_CACHE}) - set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") + set(CPM_DOWNLOAD_LOCATION + "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") else() - set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake") + set(CPM_DOWNLOAD_LOCATION + "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake") endif() -# Expand relative path. This is important if the provided path contains a tilde (~) +# Expand relative path. This is important if the provided path contains a tilde +# (~) get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE) -file(DOWNLOAD - https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake - ${CPM_DOWNLOAD_LOCATION} EXPECTED_HASH SHA256=${CPM_HASH_SUM} -) +file( + DOWNLOAD + https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake + ${CPM_DOWNLOAD_LOCATION} + EXPECTED_HASH SHA256=${CPM_HASH_SUM}) include(${CPM_DOWNLOAD_LOCATION}) diff --git a/examples/make_strings.py b/examples/make_strings.py deleted file mode 100644 index 903637f..0000000 --- a/examples/make_strings.py +++ /dev/null @@ -1,22 +0,0 @@ -from itertools import combinations, product - -qubits = 5 -weight = 2 - -strings = [] -nontrivial_matrix_elements = list(product(["X", "Y", "Z"], repeat=weight)) -for indices in combinations(range(qubits), weight): # n(n-1)/2 terms - for elements in nontrivial_matrix_elements: - pauli_string = [] - for qbit in range(qubits): - for el_position, i in enumerate(indices): - if i == qbit: - pauli_string.append(elements[el_position]) - break - else: - pauli_string.append("I") - strings.append("".join(pauli_string)) - -print(strings) - -"XXIII", "XYIII", "XZIII", "YXIII", "YYIII", "YZIII", "ZXIII", "ZYIII", "ZZIII", "XIXII", "XIYII", "XIZII", "YIXII", "YIYII", "YIZII" diff --git a/include/__factory.hpp b/include/__factory.hpp index 1b969ea..f0ccbae 100644 --- a/include/__factory.hpp +++ b/include/__factory.hpp @@ -86,9 +86,8 @@ auto rand(std::vector &blob, std::array extents) { if constexpr (is_complex::value) { std::uniform_real_distribution dis(0, 1.0); - std::generate(blob.begin(), blob.end(), [&]() { - return T{dis(gen), dis(gen)}; - }); + std::generate(blob.begin(), blob.end(), + [&]() { return T{dis(gen), dis(gen)}; }); } else { std::uniform_real_distribution dis(0, 1.0); diff --git a/include/__pauli.hpp b/include/__pauli.hpp index ba13686..b071529 100644 --- a/include/__pauli.hpp +++ b/include/__pauli.hpp @@ -15,7 +15,7 @@ using namespace std::literals; namespace fast_pauli { /** - * @brief A class for efficient representation of a + * @brief A class for efficient representation of a * 2x2 Pauli matrix \f$ \sigma_i \in \{ I,X,Y,Z \} \f$ * */ diff --git a/include/__pauli_string.hpp b/include/__pauli_string.hpp index cb66223..ec51d3f 100644 --- a/include/__pauli_string.hpp +++ b/include/__pauli_string.hpp @@ -84,7 +84,7 @@ struct PauliString { PauliString(char const *str) : PauliString(std::string(str)) {} PauliString(PauliString const &other) - : weight(other.weight), paulis(other.paulis){}; + : weight(other.weight), paulis(other.paulis) {}; PauliString &operator=(PauliString const &other) { this->weight = other.weight; this->paulis = other.paulis; @@ -111,9 +111,9 @@ struct PauliString { /** * @brief Get the sparse representation of the pauli string matrix. - * - * PauliStrings are always sparse and have only single non-zero element per row. - * It's N non-zero elements for NxN matrix where N is 2^n_qubits. + * + * PauliStrings are always sparse and have only single non-zero element per + * row. It's N non-zero elements for NxN matrix where N is 2^n_qubits. * Therefore j, k, and m will always have N elements. * * TODO remove j because it's unused (and redundant). @@ -181,8 +181,9 @@ struct PauliString { /** * @brief Apply the PauliString (using the sparse representation) to a vector. - * This performs following matrix-vector multiplication \f$ \mathcal{\hat{P}} \ket{\psi} \f$ - * + * This performs following matrix-vector multiplication \f$ \mathcal{\hat{P}} + * \ket{\psi} \f$ + * * @tparam T The floating point base to use for all the complex numbers * @param v The input vector to apply the PauliString to. Must be the same * size as PauliString.dims(). @@ -245,9 +246,10 @@ struct PauliString { * different shape of the states than the other apply functions. here all the * states (new and old) are transposed so their shape is (n_dims x n_states). * All the new_stats are overwritten, no need to initialize. - * - * This performs following matrix-matrix multiplication \f$ \mathcal{\hat{P}} \hat{\Psi} \f$ - * where matrix \f$ \hat{\Psi} \f$ has \f$ \ket{\psi_t} \f$ as columns + * + * This performs following matrix-matrix multiplication \f$ \mathcal{\hat{P}} + * \hat{\Psi} \f$ where matrix \f$ \hat{\Psi} \f$ has \f$ \ket{\psi_t} \f$ as + * columns * * @tparam T The floating point base to use for all the complex numbers * @param new_states_T The outpus states after applying the PauliString