diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml deleted file mode 100644 index a62f4a58..00000000 --- a/.github/workflows/python-app.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: Python application - -on: - push: - branches: [ "master", "development" ] - pull_request: - branches: [ "master", "development" ] - -permissions: - contents: read - -jobs: - build: - - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-latest, windows-latest, macOS-latest] - python-version: ["3.10", "3.11", "3.12"] - - steps: - - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - cache: 'pip' - - name: Install dependencies - run: | - python -m pip install --upgrade pip setuptools - pip install -r requirements.txt - - name: Pre-commit checks - run: | - python -m pip install pre-commit - pre-commit run --all-files --show-diff-on-failure - - name: Test with pytest - run: | - pip install pytest-cov - pip install . - pytest tests --doctest-modules --junitxml=junit/test-results.xml --cov=com --cov-report=xml --cov-report=html - - name: Test optional dependencies with pytest - run: | - pip install pytest-cov - pip install .[all] - pytest tests --doctest-modules --junitxml=junit/test-results.xml --cov=com --cov-report=xml --cov-report=html -m optional_dependency diff --git a/.github/workflows/python-release.yml b/.github/workflows/python-release.yml new file mode 100644 index 00000000..1eb4f4e0 --- /dev/null +++ b/.github/workflows/python-release.yml @@ -0,0 +1,269 @@ +name: Python Artifacts + +env: + TRIGGER_ON_PR_PUSH: false # Set to true to enable triggers on PR pushes + PYTHON_VERSION: '3.10' + +on: + push: + branches: + - development + - master + tags: + - 'py-*' + pull_request: + branches: + - development + - master + workflow_dispatch: + inputs: + sha: + description: Commit SHA + type: string + dry_run: + description: 'Dry run (build but not publish)' + type: boolean + default: true + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +defaults: + run: + shell: bash + +jobs: + check_pr_push: + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' && github.event.action != 'closed' + outputs: + run: ${{ steps.check.outputs.run }} + steps: + - name: Check if should run on PR push + id: check + run: | + if [ "${{ env.TRIGGER_ON_PR_PUSH }}" = "true" ]; then + echo "run=true" >> $GITHUB_OUTPUT + else + echo "run=false" >> $GITHUB_OUTPUT + fi + + build_sdist_pecos_rslib: + needs: check_pr_push + if: | + always() && + (needs.check_pr_push.result == 'success' && needs.check_pr_push.outputs.run == 'true' || needs.check_pr_push.result == 'skipped') && + (github.event_name != 'pull_request' || github.event.pull_request.merged == true || github.event.action == 'opened' || github.event.action == 'synchronize') + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ inputs.sha || github.sha }} + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{ env.PYTHON_VERSION }} + + - name: Remove conflicting README.md + run: | + if [ -f crates/pecos-python/README.md ]; then + mv crates/pecos-python/README.md crates/pecos-python/README.md.bak + echo "Moved conflicting README.md to README.md.bak" + else + echo "No conflicting README.md found" + fi + + - name: Build pecos-rslib SDist + uses: PyO3/maturin-action@v1 + with: + command: sdist + args: --out dist + working-directory: python/pecos-rslib + + - name: Restore README.md + if: always() + run: | + if [ -f crates/pecos-python/README.md.bak ]; then + mv crates/pecos-python/README.md.bak crates/pecos-python/README.md + echo "Restored README.md from backup" + else + echo "No README.md backup found" + fi + + - name: Test pecos-rslib SDist + run: | + pip install --force-reinstall --verbose python/pecos-rslib/dist/*.tar.gz + python -c 'import pecos_rslib; print(pecos_rslib.__version__)' + + - name: Upload pecos-rslib SDist + uses: actions/upload-artifact@v4 + with: + name: sdist-pecos-rslib + path: python/pecos-rslib/dist/*.tar.gz + + build_wheels_pecos_rslib: + needs: check_pr_push + if: | + always() && + (needs.check_pr_push.result == 'success' && needs.check_pr_push.outputs.run == 'true' || needs.check_pr_push.result == 'skipped') && + (github.event_name != 'pull_request' || github.event.pull_request.merged == true || github.event.action == 'opened' || github.event.action == 'synchronize') + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + python-version: ['3.10', '3.11', '3.12'] + architecture: [ x86_64, aarch64 ] + exclude: + - os: windows-latest + architecture: aarch64 + + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ inputs.sha || github.sha }} + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Remove conflicting README.md + run: | + if [ -f crates/pecos-python/README.md ]; then + mv crates/pecos-python/README.md crates/pecos-python/README.md.bak + echo "Moved conflicting README.md to README.md.bak" + else + echo "No conflicting README.md found" + fi + + - name: Build wheel + uses: PyO3/maturin-action@v1 + with: + command: build + args: --release --out dist --interpreter python${{ matrix.python-version }} + working-directory: python/pecos-rslib + target: ${{ matrix.architecture == 'aarch64' && (matrix.os == 'macos-latest' && 'aarch64-apple-darwin' || 'aarch64-unknown-linux-gnu') || '' }} + manylinux: auto + + - name: Restore README.md + if: always() + run: | + if [ -f crates/pecos-python/README.md.bak ]; then + mv crates/pecos-python/README.md.bak crates/pecos-python/README.md + echo "Restored README.md from backup" + else + echo "No README.md backup found" + fi + + - name: Test wheel + if: matrix.architecture == 'x86_64' + run: | + pip install --force-reinstall --verbose python/pecos-rslib/dist/*.whl + python -c 'import pecos_rslib; print(pecos_rslib.__version__)' + + - name: Upload wheel + uses: actions/upload-artifact@v4 + with: + name: wheel-pecos-rslib-${{ matrix.os }}-${{ matrix.architecture }}-py${{ matrix.python-version }} + path: python/pecos-rslib/dist/*.whl + + build_sdist_quantum_pecos: + needs: [check_pr_push, build_sdist_pecos_rslib, build_wheels_pecos_rslib] + if: | + always() && + (needs.check_pr_push.result == 'success' && needs.check_pr_push.outputs.run == 'true' || needs.check_pr_push.result == 'skipped') && + (github.event_name != 'pull_request' || github.event.pull_request.merged == true || github.event.action == 'opened' || github.event.action == 'synchronize') + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ inputs.sha || github.sha }} + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{ env.PYTHON_VERSION }} + + - name: Download pecos-rslib wheel + uses: actions/download-artifact@v4 + with: + name: wheel-pecos-rslib-ubuntu-latest-x86_64-py${{ env.PYTHON_VERSION }} + path: ./pecos-rslib-wheel + + - name: Install pecos-rslib + run: pip install ./pecos-rslib-wheel/*.whl + + - name: Install build dependencies + run: | + python -m pip install --upgrade pip + pip install build + + - name: Build quantum-pecos SDist + run: | + cd python/quantum-pecos + python -m build --sdist --outdir dist + + - name: Test quantum-pecos SDist + run: | + pip install python/quantum-pecos/dist/*.tar.gz + python -c 'import pecos; print(pecos.__version__)' + + - name: Upload quantum-pecos SDist + uses: actions/upload-artifact@v4 + with: + name: sdist-quantum-pecos + path: python/quantum-pecos/dist/*.tar.gz + + build_wheels_quantum_pecos: + needs: [check_pr_push, build_wheels_pecos_rslib, build_sdist_quantum_pecos] + if: | + always() && + (needs.check_pr_push.result == 'success' && needs.check_pr_push.outputs.run == 'true' || needs.check_pr_push.result == 'skipped') && + (github.event_name != 'pull_request' || github.event.pull_request.merged == true || github.event.action == 'opened' || github.event.action == 'synchronize') + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ['3.10', '3.11', '3.12'] + + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ inputs.sha || github.sha }} + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Download pecos-rslib wheel + uses: actions/download-artifact@v4 + with: + name: wheel-pecos-rslib-ubuntu-latest-x86_64-py${{ matrix.python-version }} + path: ./pecos-rslib-wheel + + - name: Install pecos-rslib + run: pip install ./pecos-rslib-wheel/*.whl + + - name: Install build dependencies + run: | + python -m pip install --upgrade pip + pip install build + + - name: Build quantum-pecos wheel + run: | + cd python/quantum-pecos + python -m build --wheel --outdir dist + + - name: Test quantum-pecos wheel + run: | + pip install python/quantum-pecos/dist/*.whl + python -c 'import pecos; print(pecos.__version__)' + + - name: Upload quantum-pecos wheel + uses: actions/upload-artifact@v4 + with: + name: wheel-quantum-pecos-py${{ matrix.python-version }} + path: python/quantum-pecos/dist/*.whl diff --git a/.github/workflows/python-test.yml b/.github/workflows/python-test.yml new file mode 100644 index 00000000..983c5ec5 --- /dev/null +++ b/.github/workflows/python-test.yml @@ -0,0 +1,102 @@ +name: Python test / linting + +on: + push: + branches: [ "master", "development" ] + paths: + - 'python/**' + - '.github/workflows/python-test.yml' + - '.typos.toml' + - 'ruff.toml' + - '.pre-commit-config.yaml' + pull_request: + branches: [ "master", "development" ] + paths: + - 'python/**' + - '.github/workflows/python-test.yml' + - '.typos.toml' + - 'ruff.toml' + - '.pre-commit-config.yaml' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + + +env: + RUSTFLAGS: -C debuginfo=0 + RUST_BACKTRACE: 1 + PYTHONUTF8: 1 + +defaults: + run: + shell: bash + +jobs: + python-test: + + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macOS-latest] + python-version: ["3.10", "3.11", "3.12"] + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Create and activate virtual environment + env: + BIN: ${{ matrix.os == 'windows-latest' && 'Scripts' || 'bin' }} + run: | + python -m venv .venv + source .venv/$BIN/activate + echo "$GITHUB_WORKSPACE/.venv/$BIN" >> $GITHUB_PATH + echo "VIRTUAL_ENV=$GITHUB_WORKSPACE/.venv" >> $GITHUB_ENV + + - name: Install Python dependencies + run: | + python -m pip install --upgrade pip setuptools + pip install maturin pytest pre-commit + echo "Temporarily removing pecos-rslib from requirements... because we need to build it" + grep -v "pecos-rslib" python/quantum-pecos/requirements.txt > temp_requirements.txt + echo "Installing project requirements (excluding pecos-rslib)..." + pip install -r temp_requirements.txt + echo "Cleaning up temporary files..." + rm temp_requirements.txt + + - name: Set up Rust + run: rustup show + + - name: Cache Rust + uses: Swatinem/rust-cache@v2 + with: + workspaces: python/pecos-rslib + + - name: Install pecos-rslib with maturin develop + run: | + cd python/pecos-rslib + maturin develop + + - name: Install pure Python PECOS + run: pip install ./python/quantum-pecos/ + + - name: Run pre-commit checks + run: | + pre-commit run --all-files --show-diff-on-failure + + - name: Run standard tests + run: | + pip install pytest-cov + pytest ./python/tests --doctest-modules --junitxml=junit/test-results.xml --cov=com --cov-report=xml --cov-report=html + + - name: Run tests with optional dependencies + run: | + pip install pytest-cov + pip install ./python/quantum-pecos/[all] + pytest ./python/tests --doctest-modules --junitxml=junit/test-results.xml --cov=com --cov-report=xml --cov-report=html -m optional_dependency diff --git a/.github/workflows/python-version-consistency.yml b/.github/workflows/python-version-consistency.yml new file mode 100644 index 00000000..58632323 --- /dev/null +++ b/.github/workflows/python-version-consistency.yml @@ -0,0 +1,48 @@ +name: Python Version Consistency Check + +on: + push: + paths: + - 'python/**/pyproject.toml' + pull_request: + paths: + - 'python/**/pyproject.toml' + +jobs: + check_versions: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Check version consistency + run: | + # Find all pyproject.toml files in the python/ directory + PYPROJECT_FILES=$(find python -name pyproject.toml) + + # Initialize variables + FIRST_VERSION="" + INCONSISTENT=false + + # Check each pyproject.toml file + for file in $PYPROJECT_FILES; do + VERSION=$(grep -oP 'version = "\K[^"]+' $file) + + if [ -z "$FIRST_VERSION" ]; then + FIRST_VERSION=$VERSION + echo "Reference version: $FIRST_VERSION (from $file)" + elif [ "$VERSION" != "$FIRST_VERSION" ]; then + echo "Inconsistent version found in $file: $VERSION" + INCONSISTENT=true + else + echo "Consistent version found in $file: $VERSION" + fi + done + + # Exit with error if versions are inconsistent + if [ "$INCONSISTENT" = true ]; then + echo "Error: Inconsistent versions found across pyproject.toml files" + exit 1 + else + echo "Success: All pyproject.toml files have consistent versions" + fi diff --git a/.github/workflows/rust-test.yml b/.github/workflows/rust-test.yml new file mode 100644 index 00000000..99f0ee04 --- /dev/null +++ b/.github/workflows/rust-test.yml @@ -0,0 +1,91 @@ +name: Rust test / linting + +on: + push: + branches: [ "master", "development" ] + paths: + - 'crates/**' + - 'examples/**' + - 'Cargo.toml' + - '.github/workflows/rust-test.yml' + - '.pre-commit-config.yaml' + pull_request: + branches: [ "master", "development" ] + paths: + - 'crates/**' + - 'examples/**' + - 'Cargo.toml' + - '.github/workflows/rust-test.yml' + - '.pre-commit-config.yaml' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + RUSTFLAGS: -C debuginfo=0 + RUST_BACKTRACE: 1 + +jobs: + rust-lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Rust + run: rustup override set stable && rustup update + + - name: Cache Rust + uses: Swatinem/rust-cache@v2 + with: + save-if: ${{ github.ref_name == 'master' || github.ref_name == 'development' }} + + - name: Install rustfmt + run: rustup component add rustfmt + + - name: Check formatting + run: cargo fmt --all -- --check + + - name: Install clippy + run: rustup component add clippy + + - name: Run clippy + run: cargo clippy --workspace --all-targets -- -D warnings + + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + - name: Install pre-commit + run: pip install pre-commit + - name: Run pre-commit + run: pre-commit run --all-files --show-diff-on-failure + + rust-test: + needs: [pre-commit, rust-lint] + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + + steps: + - uses: actions/checkout@v4 + + - name: Set up Rust + run: rustup show + + - name: Cache Rust + uses: Swatinem/rust-cache@v2 + with: + save-if: ${{ github.ref_name == 'master' || github.ref_name == 'development' }} + + - name: Compile tests + run: cargo test --no-run + + - name: Run tests + run: cargo test diff --git a/.github/workflows/rust-version-consistency.yml b/.github/workflows/rust-version-consistency.yml new file mode 100644 index 00000000..2e5fb052 --- /dev/null +++ b/.github/workflows/rust-version-consistency.yml @@ -0,0 +1,53 @@ +name: Rust Version Consistency Check + +on: + push: + paths: + - 'Cargo.toml' + - 'crates/**/Cargo.toml' + pull_request: + paths: + - 'Cargo.toml' + - 'crates/**/Cargo.toml' + +jobs: + check_rust_versions: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Check Rust crate configurations + run: | + # Check root Cargo.toml for workspace version + ROOT_VERSION=$(grep -oP 'version\s*=\s*"\K[^"]+' Cargo.toml) + if [ -z "$ROOT_VERSION" ]; then + echo "Error: No version specified in root Cargo.toml" + exit 1 + fi + echo "Workspace version: $ROOT_VERSION" + + # Check each Cargo.toml in crates/ + INCONSISTENT=false + for file in crates/*/Cargo.toml; do + echo "Checking $file" + + # Check if the crate is using workspace inheritance for version + if ! grep -q "version.workspace\s*=\s*true" "$file"; then + echo "Error: $file is not inheriting version from workspace" + INCONSISTENT=true + fi + + # Check if version is explicitly specified (it shouldn't be) + if grep -qP '^version\s*=\s*"[^"]+"' "$file"; then + echo "Error: $file specifies its own version, should inherit from workspace" + INCONSISTENT=true + fi + done + + if [ "$INCONSISTENT" = true ]; then + echo "Error: Inconsistencies found in Rust crate configurations" + exit 1 + else + echo "Success: All Rust crates are correctly configured in the workspace" + fi diff --git a/.gitignore b/.gitignore index 5298529c..7a51be5d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# pytest results +junit/ + # Cython *.pyc *.pyd diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fa848919..588f4a75 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,11 +1,15 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.6.0 + rev: v5.0.0 hooks: - id: trailing-whitespace - exclude: ^docs/reference/_autosummary/ + exclude: ^python/docs/reference/_autosummary/ - id: end-of-file-fixer - exclude: ^docs/reference/_autosummary/ + exclude: | + (?x)^( + python/docs/reference/_autosummary/| + .*\.rs$ + ) - id: check-toml - id: check-yaml - id: check-added-large-files @@ -15,33 +19,25 @@ repos: - id: debug-statements - repo: https://github.com/crate-ci/typos - rev: v1.21.0 + rev: v1.27.0 hooks: - id: typos args: [] - exclude: | - (?x)^( - python/pecos/simulators/cuquantum_old/.*| - )$ - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.4.3 + rev: v0.7.2 hooks: - id: ruff args: [--fix, --exit-non-zero-on-fix] - repo: https://github.com/psf/black - rev: 24.4.2 + rev: 24.10.0 hooks: - id: black - exclude: | - (?x)^( - python/pecos/simulators/cuquantum_old/custatevec/bindings.py| - )$ - repo: https://github.com/keewis/blackdoc rev: v0.3.9 hooks: - id: blackdoc additional_dependencies: - - black==24.1.1 + - black==24.8.0 diff --git a/.typos.toml b/.typos.toml index 7e061f4e..c241b054 100644 --- a/.typos.toml +++ b/.typos.toml @@ -5,3 +5,5 @@ ket = "ket" wqs = "wqs" thr = "thr" IY = "IY" +anc = "anc" +Pn = "Pn" diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 00000000..3e7b63b6 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,2414 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + +[[package]] +name = "anstream" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" + +[[package]] +name = "anstyle-parse" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "anyhow" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "async-compression" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fec134f64e2bc57411226dfc4e52dec859ddfc7e711fc5e07b612584f000e4aa" +dependencies = [ + "brotli", + "flate2", + "futures-core", + "memchr", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object 0.36.4", + "rustc-demangle", + "windows-targets 0.52.6", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "benchmarks" +version = "0.1.0" +dependencies = [ + "criterion", + "pecos", + "pecos-core", + "pecos-qec", + "pecos-qsims", +] + +[[package]] +name = "binary-merge" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597bb81c80a54b6a4381b23faba8d7774b144c94cbd1d6fe3f1329bd776554ab" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "blondie" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2ae5905939ba6bf68e566e6b8a280210923bb9afa5dcd4bc4c71fade8a9a7f" +dependencies = [ + "object 0.30.4", + "pdb-addr2line", + "rustc-hash", + "symsrv", + "tokio", + "windows", +] + +[[package]] +name = "brotli" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "bstr" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" +dependencies = [ + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "bytemuck" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" + +[[package]] +name = "cab" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae6b4de23c7d39c0631fd3cc952d87951c86c75a13812d7247cb7a896e7b3551" +dependencies = [ + "byteorder", + "flate2", + "lzxd", + "time", +] + +[[package]] +name = "camino" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[package]] +name = "cc" +version = "1.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45bcde016d64c21da4be18b655631e5ab6d3107607e71a73a9f53eb48aae23fb" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "clap" +version = "4.5.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_complete" +version = "4.5.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b378c786d3bde9442d2c6dd7e6080b2a818db2b96e30d6e7f1b6d224eb617d3" +dependencies = [ + "clap", +] + +[[package]] +name = "clap_derive" +version = "4.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" + +[[package]] +name = "colorchoice" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "criterion" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" +dependencies = [ + "anes", + "cast", + "ciborium", + "clap", + "criterion-plot", + "is-terminal", + "itertools", + "num-traits", + "once_cell", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "dashmap" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "elsa" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98e71ae4df57d214182a2e5cb90230c0192c6ddfcaa05c36453d46a54713e10" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "flamegraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3da1f6b64e11ddd0f00d7920382085230b3814eacf96132d29474f7693485b4f" +dependencies = [ + "anyhow", + "blondie", + "cargo_metadata", + "clap", + "clap_complete", + "inferno", + "opener", + "shlex", + "signal-hook", +] + +[[package]] +name = "flate2" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" + +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "half" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http", + "hyper", + "rustls", + "tokio", + "tokio-rustls", +] + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "indoc" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" + +[[package]] +name = "inferno" +version = "0.11.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "232929e1d75fe899576a3d5c7416ad0d88dbfbb3c3d6aa00873a7408a50ddb88" +dependencies = [ + "ahash", + "crossbeam-channel", + "crossbeam-utils", + "dashmap", + "indexmap", + "is-terminal", + "itoa", + "log", + "num-format", + "once_cell", + "quick-xml", + "rgb", + "str_stack", +] + +[[package]] +name = "inplace-vec-builder" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf64c2edc8226891a71f127587a2861b132d2b942310843814d5001d99a1d307" +dependencies = [ + "smallvec", +] + +[[package]] +name = "ipnet" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" + +[[package]] +name = "is-terminal" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +dependencies = [ + "hermit-abi 0.4.0", + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "lzxd" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784462f20dddd9dfdb45de963fa4ad4a288cb10a7889ac5d2c34fb6481c6b213" + +[[package]] +name = "maybe-owned" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "minicov" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c71e683cd655513b99affab7d317deb690528255a0d5f717f1024093c12b169" +dependencies = [ + "cc", + "walkdir", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "wasi", + "windows-sys 0.52.0", +] + +[[package]] +name = "normpath" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8911957c4b1549ac0dc74e30db9c8b0e66ddcd6d7acc33098f4c63a64a6d7ed" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-format" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" +dependencies = [ + "arrayvec", + "itoa", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "object" +version = "0.30.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" +dependencies = [ + "flate2", + "memchr", +] + +[[package]] +name = "object" +version = "0.36.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "oorandom" +version = "11.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" + +[[package]] +name = "opener" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c62dcb6174f9cb326eac248f07e955d5d559c272730b6c03e396b443b562788" +dependencies = [ + "bstr", + "normpath", + "winapi", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + +[[package]] +name = "pdb" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82040a392923abe6279c00ab4aff62d5250d1c8555dc780e4b02783a7aa74863" +dependencies = [ + "fallible-iterator", + "scroll", + "uuid", +] + +[[package]] +name = "pdb-addr2line" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4e89a9f2f40b2389ba6da0814c8044bf942bece03dffa1514f84e3b525f4f9a" +dependencies = [ + "bitflags 1.3.2", + "elsa", + "maybe-owned", + "pdb", + "range-collections", + "thiserror", +] + +[[package]] +name = "pecos" +version = "0.1.0" +dependencies = [ + "criterion", + "flamegraph", + "getrandom", + "pecos-core", + "pecos-qec", + "pecos-qsims", + "rand", + "rand_chacha", + "rand_xoshiro", + "wasm-bindgen-test", +] + +[[package]] +name = "pecos-core" +version = "0.1.0" +dependencies = [ + "rand", + "rand_chacha", + "rand_xoshiro", +] + +[[package]] +name = "pecos-python" +version = "0.1.0" +dependencies = [ + "pecos", + "pyo3", +] + +[[package]] +name = "pecos-qec" +version = "0.1.0" +dependencies = [ + "pecos-qsims", +] + +[[package]] +name = "pecos-qsims" +version = "0.1.0" +dependencies = [ + "pecos-core", + "rand_chacha", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "plotters" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" + +[[package]] +name = "plotters-svg" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" +dependencies = [ + "plotters-backend", +] + +[[package]] +name = "portable-atomic" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "pyo3" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15ee168e30649f7f234c3d49ef5a7a6cbf5134289bc46c29ff3155fa3221c225" +dependencies = [ + "cfg-if", + "indoc", + "libc", + "memoffset", + "once_cell", + "portable-atomic", + "pyo3-build-config", + "pyo3-ffi", + "pyo3-macros", + "unindent", +] + +[[package]] +name = "pyo3-build-config" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e61cef80755fe9e46bb8a0b8f20752ca7676dcc07a5277d8b7768c6172e529b3" +dependencies = [ + "once_cell", + "target-lexicon", +] + +[[package]] +name = "pyo3-ffi" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ce096073ec5405f5ee2b8b31f03a68e02aa10d5d4f565eca04acc41931fa1c" +dependencies = [ + "libc", + "pyo3-build-config", +] + +[[package]] +name = "pyo3-macros" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2440c6d12bc8f3ae39f1e775266fa5122fd0c8891ce7520fa6048e683ad3de28" +dependencies = [ + "proc-macro2", + "pyo3-macros-backend", + "quote", + "syn", +] + +[[package]] +name = "pyo3-macros-backend" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1be962f0e06da8f8465729ea2cb71a416d2257dff56cbe40a70d3e62a93ae5d1" +dependencies = [ + "heck", + "proc-macro2", + "pyo3-build-config", + "quote", + "syn", +] + +[[package]] +name = "quick-xml" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f50b1c63b38611e7d4d7f68b82d3ad0cc71a2ad2e7f61fc10f1328d917c93cd" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_xoshiro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +dependencies = [ + "rand_core", +] + +[[package]] +name = "range-collections" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61fdfd79629e2b44a1d34b4d227957174cb858e6b86ee45fad114edbcfc903ab" +dependencies = [ + "binary-merge", + "inplace-vec-builder", + "smallvec", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "reqwest" +version = "0.11.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +dependencies = [ + "async-compression", + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-rustls", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-rustls", + "tokio-util", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", + "winreg", +] + +[[package]] +name = "rgb" +version = "0.8.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring", + "rustls-webpki", + "sct", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "scroll" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da" + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +dependencies = [ + "serde", +] + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "str_stack" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "symsrv" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "328d40bbd6972015696ee86709ccc1327a2529816898f2844a62b71e449b1274" +dependencies = [ + "bytes", + "cab", + "dirs", + "memmap2", + "reqwest", + "thiserror", + "tokio", +] + +[[package]] +name = "syn" +version = "2.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + +[[package]] +name = "thiserror" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde", + "time-core", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unindent" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uuid" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[package]] +name = "wasm-bindgen-test" +version = "0.3.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68497a05fb21143a08a7d24fc81763384a3072ee43c44e86aad1744d6adef9d9" +dependencies = [ + "console_error_panic_hook", + "js-sys", + "minicov", + "scoped-tls", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test-macro", +] + +[[package]] +name = "wasm-bindgen-test-macro" +version = "0.3.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b8220be1fa9e4c889b30fd207d4906657e7e90b12e0e6b0c8b8d8709f5de021" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "web-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 00000000..cd3d18c3 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,41 @@ +[workspace] +resolver = "2" +members = [ + "crates/pecos*", + "crates/benchmarks", + # "examples/*", +] + +[workspace.package] +version = "0.1.0" +edition = "2021" +readme = "README.md" +authors = [ + "The PECOS Developers", + "Ciaran Ryan-Anderson", +] +homepage = "https://pecos.io" +repository = "https://github.com/PECOS-packages/PECOS" +license = "Apache-2.0" +keywords = ["scientific", "quantum", "QEC"] +categories = ["science", "simulation"] + +[workspace.dependencies] +pyo3 = "0.22" +rand = "0.8" +rand_chacha = "0.3" +rand_xoshiro = "0.6" + +[profile.release] +codegen-units = 1 +lto = "fat" + +[workspace.lints.clippy] +# For more details see: https://doc.rust-lang.org/clippy/lints.html +suspicious = "warn" +complexity = "warn" +perf = "warn" +style = "warn" +pedantic = "warn" +# restriction = "warn" +cargo = "warn" diff --git a/Makefile b/Makefile index ca13d66f..caf49737 100644 --- a/Makefile +++ b/Makefile @@ -1,102 +1,169 @@ -# A set of commands for development utilizing venv to develop, lint, test, document, and build the project. -# The goal is to concretely capture the development/build process for reproducibility of the development workflow. - .DEFAULT_GOAL := help -.PHONY: requirements updatereqs metadeps install install-all docs lint tests tests-dep doctests tests-all clean venv dev-all build build-full help upgrade-pip dev-setup - # Try to autodetect if python3 or python is the python executable used. -BASEPYTHON := $(shell which python3 2>/dev/null || which python 2>/dev/null) -VENV=.venv +PYTHONPATH := $(shell which python3 2>/dev/null || which python 2>/dev/null) +SHELL=bash + +# Get absolute path of venv directory +BASE_DIR := $(shell realpath .) +VENV=$(BASE_DIR)/.venv ifeq ($(OS),Windows_NT) - VENV_BIN=$(VENV)/Scripts + VENV_BIN := $(VENV)/Scriptsexit else - VENV_BIN=$(VENV)/bin + VENV_BIN := $(VENV)/bin endif -# Requirements -# ------------ - -requirements: upgrade-pip ## Install/refresh Python project requirements - $(VENV_BIN)/pip install --upgrade -r requirements.txt - $(VENV_BIN)/pip install --upgrade -r docs/requirements.txt +# Define the path to main Python pyproject.toml +PYPROJECT_PATH := python/quantum-pecos/pyproject.toml -updatereqs: upgrade-pip ## Autogenerate requirements.txt - $(VENV_BIN)/pip install -U pip-tools - -@rm requirements.txt - $(VENV_BIN)/pip-compile --extra=tests --no-annotate --no-emit-index-url --output-file=requirements.txt --strip-extras pyproject.toml +# Virtual environment +# ------------------- -metadeps: upgrade-pip ## Install extra dependencies used to develop/build this package - $(VENV_BIN)/pip install -U build pip-tools pre-commit wheel pytest hypothesis +.PHONY: venv +venv: ## Build Python virtual environment and install requirements + $(PYTHONPATH) -m venv $(VENV) + $(MAKE) requirements -# Installation +# Requirements # ------------ +.PHONY: requirements +requirements: metadeps installreqs ## Install/refresh Python project requirements including those needed for development -install: upgrade-pip ## Install PECOS - $(VENV_BIN)/pip install . - -install-all: upgrade-pip ## Install PECOS with all optional dependencies - $(VENV_BIN)/pip install .[all] +.PHONY: updatereqs +updatereqs: ## Auto update and generate requirements.txt + @echo "Upgrading pip..." + $(VENV_BIN)/python -m pip install --upgrade pip + $(VENV_BIN)/pip install -U pip-tools + -@rm python/quantum-pecos/requirements.txt + @echo "Using version: $(call get_version)" + @echo "Temporarily modifying pyproject.toml..." + @sed -i.bak '/pecos-rslib==/d' $(PYPROJECT_PATH) + $(VENV_BIN)/pip-compile --extra=tests --no-annotate --no-emit-index-url \ + --output-file=python/quantum-pecos/requirements.txt \ + --strip-extras $(PYPROJECT_PATH) + @echo "Restoring original pyproject.toml..." + @mv $(PYPROJECT_PATH).bak $(PYPROJECT_PATH) + @echo "Adding pecos-rslib back to requirements.txt..." + @echo "pecos-rslib==$(call get_version)" >> python/quantum-pecos/requirements.txt + +.PHONY: installreqs +installreqs: upgrade-pip ## Install Python project requirements + @echo "Temporarily removing pecos-rslib from requirements..." + @grep -v "pecos-rslib" python/quantum-pecos/requirements.txt > temp_requirements.txt + + @echo "Installing project requirements (excluding pecos-rslib)..." + $(VENV_BIN)/pip install -r temp_requirements.txt + + @echo "Cleaning up temporary files..." + @rm temp_requirements.txt + +.PHONY: metadeps +metadeps: upgrade-pip ## Install extra dependencies used to develop/build this package + $(VENV_BIN)/pip install -U setuptools pip-tools pre-commit pytest hypothesis maturin + +# Function to extract version from pyproject.toml +define get_version +$(shell grep -m 1 'version\s*=' $(PYPROJECT_PATH) | sed 's/.*version\s*=\s*"\(.*\)".*/\1/') +endef + +# Building development environments +# --------------------------------- +.PHONY: build +build: requirements ## Compile and install for development + @unset CONDA_PREFIX && cd python/pecos-rslib/ && $(VENV_BIN)/maturin develop + @unset CONDA_PREFIX && cd python/quantum-pecos && $(VENV_BIN)/pip install -e .[all] + +.PHONY: build-basic +build-basic: requirements ## Compile and install for development but do not include install extras + @unset CONDA_PREFIX && cd python/pecos-rslib/ && $(VENV_BIN)/maturin develop + @unset CONDA_PREFIX && cd python/quantum-pecos && $(VENV_BIN)/pip install -e . + +.PHONY: build-release +build-release: requirements ## Build a faster version of binaries + @unset CONDA_PREFIX && cd python/pecos-rslib/ && $(VENV_BIN)/maturin develop --release + @unset CONDA_PREFIX && cd python/quantum-pecos && $(VENV_BIN)/pip install -e .[all] + +.PHONY: build-native +build-native: requirements ## Build a faster version of binaries with native CPU optimization + @unset CONDA_PREFIX && cd python/pecos-rslib/ && RUSTFLAGS='-C target-cpu=native' \ + && $(VENV_BIN)/maturin develop --release + @unset CONDA_PREFIX && cd python/quantum-pecos && $(VENV_BIN)/pip install -e .[all] # Documentation # ------------- -docs: install-all ## Generate documentation - $(VENV_BIN)/pip install -r ./docs/requirements.txt - $(MAKE) -C docs SPHINXBUILD=../$(VENV_BIN)/sphinx-build clean html +# .PHONY: docs +# docs: ## Generate documentation +# #TODO: ... # Linting / formatting # -------------------- -lint: metadeps ## Run all quality checks / linting / reformatting +.PHONY: check +check: ## Run cargo check with all features + cargo check --workspace --all-targets --all-features + +.PHONY: clippy +clippy: ## Run cargo clippy with all features + cargo clippy --workspace --all-targets --all-features -- -D warnings + +.PHONY: fmt +fmt: ## Run autoformatting for cargo + cargo fmt --all -- --check + +.PHONY: pre-commit ## Run all quality checks / linting / reformatting +pre-commit: fmt clippy $(VENV_BIN)/pre-commit run --all-files # Testing # ------- -tests: install metadeps ## Run tests on the Python package (not including optional dependencies) - $(VENV_BIN)/pytest tests -m "not optional_dependency" +.PHONY: rstest +rstest: ## Run Rust tests + cargo test -tests-dep: install-all metadeps ## Run tests on the Python package only for optional dependencies - $(VENV_BIN)/pytest tests -m optional_dependency +.PHONY: pytest +pytest: ## Run tests on the Python package (not including optional dependencies). ASSUMES: previous build command + @cd python/tests/ && $(VENV_BIN)/pytest . -m "not optional_dependency" -doctests: ## Run doctests with pytest - $(VENV_BIN)/pytest ./docs --doctest-glob=*.rst --doctest-continue-on-failure +.PHONY: pytest-dep +pytest-dep: ## Run tests on the Python package only for optional dependencies. ASSUMES: previous build command + @cd python/ && $(VENV_BIN)/pytest tests -m optional_dependency -tests-all: tests tests-dep doctests ## Run all tests +# .PHONY: pytest-doc +# pydoctest: ## Run doctests with pytest. ASSUMES: A build command was ran previously. ASSUMES: previous build command +# # TODO: update and install docs requirements +# @cd python/ && $(VENV_BIN)/pytest docs --doctest-glob=*.rst --doctest-continue-on-failure -# Building / Developing -# --------------------- - -clean: ## Clean up caches and build artifacts - -rm -rf *.egg-info dist build docs/_build .pytest_cache/ .ruff_cache/ +.PHONY: test +test: rstest pytest pytest-dep ## Run all tests. ASSUMES: previous build command -venv: ## Build a new Python virtual environment from scratch - -rm -rf .venv/ - $(BASEPYTHON) -m venv $(VENV) - -dev-all: dev-setup ## Create a development environment from scratch with all optional dependencies and PECOS installed in editable mode - $(VENV_BIN)/pip install -e .[all] +# Utility +# ------- -build: dev-setup ## Clean, create new environment, and build PECOS for pypi - $(VENV_BIN)/python -m build --sdist --wheel -n +.PHONY: upgrade-pip +upgrade-pip: + $(VENV_BIN)/python -m pip install --upgrade pip -build-full: dev-setup updatereqs install-all docs lint tests-all ## Go through the full linting, testing, and building process - $(VENV_BIN)/python -m build --sdist --wheel -n +.PHONY: clean +clean: ## Clean up caches and build artifacts + @rm -rf *.egg-info + @rm -rf dist + @rm -rf **/build/ + @rm -rf python/docs/_build + @rm -rf **/.pytest_cache/ + @rm -rf **/.ipynb_checkpoints + @rm -rf .ruff_cache/ + @rm -rf **/.hypothesis/ + @rm -rf **/junit/ + @cargo clean # Help # ---- +.PHONY: help help: ## Show the help menu @echo "Available make commands:" @echo "" @grep -E '^[a-z.A-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-22s\033[0m %s\n", $$1, $$2}' - -# Utility targets -# --------------- - -upgrade-pip: - $(VENV_BIN)/python -m pip install --upgrade pip - -dev-setup: clean venv requirements metadeps diff --git a/README.md b/README.md index 33c405f2..345b800c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# ![PECOS](branding/logo/pecos_logo_v2.png) +# ![PECOS](branding/logo/pecos_logo_v2.svg) [![PyPI version](https://badge.fury.io/py/quantum-pecos.svg)](https://badge.fury.io/py/quantum-pecos) [![Documentation Status](https://readthedocs.org/projects/quantum-pecos/badge/?version=latest)](https://quantum-pecos.readthedocs.io/en/latest/?badge=latest) @@ -6,28 +6,43 @@ [![Supported by Quantinuum](https://img.shields.io/badge/supported_by-Quantinuum-blue)](https://www.quantinuum.com/) **Performance Estimator of Codes On Surfaces (PECOS)** is a library/framework dedicated to the study, development, and -evaluation of quantum error-correction protocols. It offers tools for the study and evaluation of hybrid +evaluation of quantum error-correction protocols. It also offers tools for the study and evaluation of hybrid quantum/classical compute execution models for NISQ algorithms and beyond. Initially conceived and developed in 2014 to verify lattice-surgery procedures presented in -[arXiv:1407.5103](https://arxiv.org/abs/1407.5103) and released publicly in 2018, PECOS filled a significant gap in +[arXiv:1407.5103](https://arxiv.org/abs/1407.5103) and released publicly in 2018, PECOS filled the gap in the QEC/QC tools available at that time. Over the years, it has grown into a framework for studying general QECCs and hybrid computation. -With an emphasis on clarity, flexibility, and performance and catering to both QEC students and developers, PECOS is -refined continually with these attributes in mind. - ## Features - Quantum Error-Correction Tools: Advanced tools for studying quantum error-correction protocols and error models. - Hybrid Quantum/Classical Execution: Evaluate advanced hybrid compute models, including support for classical compute, calls to Wasm VMs, conditional branching, and more. -- Fast Simulation: Leverage the fast stabilizer-simulation algorithm. -- Extensible: Add-ons and extensions support in C and C++ via Cython. +- Fast Simulation: Leverages a fast stabilizer simulation algorithm. +- Multi-language extensions: Core functionalities implemented via Rust for performance and safety. Additional add-ons +and extension support in C/C++ via Cython. ## Getting Started -Explore the capabilities of PECOS by delving into the [official documentation](https://quantum-pecos.readthedocs.io). +Explore the capabilities of PECOS by delving into the [documentation](https://quantum-pecos.readthedocs.io). + +## Repository Structure + +PECOS now consists of multiple interconnected components: + +- `/python/`: Contains Python packages + - `/python/quantum-pecos/`: Main Python package (imports as `pecos`) + - `/python/pecos-rslib/`: Python package with Rust extensions that utilize the `pecos` crate +- `/crates/`: Contains Rust crates + - `/crates/pecos/`: Main Rust crate that collects the functionality of the other crates into one library + - `/crates/pecos-core/`: Core Rust functionalities + - `/crates/pecos-qsims/`: A collection of quantum simulators + - `/crates/pecos-qec/`: Rust code for analyzing and exploring quantum error correction (QEC) + - `/crates/pecos-python/`: Rust code for Python extensions + - `/crates/benchmarks/`: A collection of benchmarks to test the performance of the crates + +You may find most of these crates in crates.io if you wish to utilize only a part of PECOS, e.g., the simulators. ## Versioning @@ -35,6 +50,9 @@ We follow semantic versioning principles. However, before version 1.0.0, the MAJ of MAJOR and MINOR shifted down a step. This means potential breaking changes might occur between MINOR increments, such as moving from versions 0.1.0 to 0.2.0. +All Python packages and all Rust crates will have the same version amongst their +respective languages; however, Python and Rust versioning will differ. + ## Latest Development Stay updated with the latest developments on the @@ -42,64 +60,60 @@ Stay updated with the latest developments on the ## Installation -1. Clone or download the desired version of PECOS. -2. Navigate to the root directory, where `pyproject.toml` is located. -3. Install using pip: +### Python Package -```sh -pip install . -``` - -To install optional dependencies, such as for Wasm support or state vector simulations, see `pyproject.toml` for list of -options. To install all optional dependencies use: +To install the main Python package for general usage: ```sh -pip install .[all] +pip install quantum-pecos ``` -Certain simulators have special requirements and are not installed by the command above. Installation instructions for these are provided [here](#simulators-with-special-requirements). +This will install both `quantum-pecos` and its dependency `pecos-rslib`. -For development, use (while including installation options as necessary): - -On Linux/Mac: +For optional dependencies: ```sh -python -m venv .venv -source .venv/bin/activate -pip install -U pip setuptools -pip install -r requirements.txt -make metadeps -pre-commit install -pip install -e . +pip install quantum-pecos[all] ``` -On Windows: +**NOTE:** The `quantum-pecos` package is imported like: `import pecos` and not `import quantum_pecos`. +**NOTE:** To install pre-releases (the latest development code) from pypi you may have to specify the version you are +interested like so (e.g., for version `0.6.0.dev5`): ```sh -python -m venv .venv -.\venv\Scripts\activate -pip install -U pip setuptools -pip install -r requirements.txt -make metadeps -pre-commit install -pip install -e . +pip install quantum-pecos==0.6.0.dev5 ``` -See `Makefile` for other useful commands. +**NOTE:** Certain simulators have special requirements and are not installed by the command above. Installation instructions for +these are provided [here](#simulators-with-special-requirements). -Tests can be run using: -```sh -pytest tests +### Rust Crates + +To use PECOS in your Rust project, add the following to your `Cargo.toml`: + +```toml +[dependencies] +pecos = "0.x.x" # Replace with the latest version ``` -### Simulators with special requirements +## Development Setup + +If you are interested in editing or developing the code in this project, see this +[development documentation](dev_steps.md) to get started. + +## Simulators with special requirements Certain simulators from `pecos.simulators` require external packages that are not installed by `pip install .[all]`. -- `QuEST` is installed along with the python package `pyquest` when calling `pip install .[all]`. However, it uses 64-bit float point precision by default, and if you wish to make use of 32-bit float point precision you will need to follow the installation instructions provided by the developers [here](https://github.com/rrmeister/pyQuEST/tree/develop). -- `CuStateVec` requires a Linux machine with an NVIDIA GPU (see requirements [here](https://docs.nvidia.com/cuda/cuquantum/latest/getting_started/getting_started.html#dependencies-custatevec-label)). PECOS' dependencies are specified in the `[cuda]` section of `pyproject.toml`, however, installation via `pip` is not reliable. The recommended method of installation is via `conda`, as discussed [here](https://docs.nvidia.com/cuda/cuquantum/latest/getting_started/getting_started.html#installing-cuquantum). Note that there might be conflicts between `conda` and `venv`; if you intend to use `CuStateVec`, you may follow the installation instructions for PECOS within a `conda` environment without involving the `venv` commands. -- `MPS` uses `pytket-cutensornet` (see [repository](https://github.com/CQCL/pytket-cutensornet)) and can be installed via `pip install .[cuda]`. This simulators uses NVIDIA GPUs and cuQuantum. Unfortunately, installation of cuQuantum does not currently work via `pip`. Please follow the instructions specified above for `CuStateVec` to install cuQuantum. +- `QuEST` is installed along with the python package `pyquest` when calling `pip install .[all]`. However, it uses +64-bit float point precision by default, and if you wish to make use of 32-bit float point precision you will need to +follow the installation instructions provided by the developers [here](https://github.com/rrmeister/pyQuEST/tree/develop). +- `CuStateVec` requires a Linux machine with an NVIDIA GPU (see requirements [here](https://docs.nvidia.com/cuda/cuquantum/latest/getting_started/getting_started.html#dependencies-custatevec-label)). PECOS' dependencies are +specified in the `[cuda]` section of `pyproject.toml`, however, installation via `pip` is not reliable. The recommended method of installation is via `conda`, as discussed [here](https://docs.nvidia.com/cuda/cuquantum/latest/getting_started/getting_started.html#installing-cuquantum). Note that there might be conflicts between `conda` and `venv`; if you intend to use `CuStateVec`, you may follow the installation instructions for PECOS within a `conda` environment without involving the `venv` commands. +- `MPS` uses `pytket-cutensornet` (see [repository](https://github.com/CQCL/pytket-cutensornet)) and can be installed via `pip install .[cuda]`. These +simulators use NVIDIA GPUs and cuQuantum. Unfortunately, installation of cuQuantum does not currently work via `pip`. +Please follow the instructions specified above for `CuStateVec` to install cuQuantum. ## Uninstall @@ -115,23 +129,42 @@ For publications utilizing PECOS, kindly cite PECOS such as: ```bibtex @misc{pecos, - author={Ciaran Ryan-Anderson}, + author={Ciar\'{a}n Ryan-Anderson}, title={PECOS: Performance Estimator of Codes On Surfaces}, - journal={GitHub}, + publisher = {GitHub}, + journal = {GitHub repository}, howpublished={\url{https://github.com/PECOS-packages/PECOS}}, URL = {https://github.com/PECOS-packages/PECOS}, year={2018} } - +``` +And/or the PhD thesis PECOS was first described in: +```bibtex @phdthesis{crathesis, - author={Ciaran Ryan-Anderson}, + author={Ciar\'{a}n Ryan-Anderson}, school = {University of New Mexico}, title={Quantum Algorithms, Architecture, and Error Correction}, journal={arXiv:1812.04735}, + URL = {https://digitalrepository.unm.edu/phyc_etds/203}, year={2018} } ``` +You can also use the [Zenodo DOI](https://zenodo.org/records/13700104), which would result in a bibtex like: +```bibtex +@software{pecos_[year], + author = {Ciar\'{a}n Ryan-Anderson}, + title = {PECOS-packages/PECOS: [version]]}, + month = [month], + year = [year], + publisher = {Zenodo}, + version = {[version]]}, + doi = {10.5281/zenodo.13700104}, + url = {https://doi.org/10.5281/zenodo.13700104} +} +``` + + ## License This project is licensed under the Apache-2.0 License - see the [LICENSE](./LICENSE) and [NOTICE](NOTICE) files for diff --git a/branding/logo/pecos_logo.png b/branding/logo/pecos_logo.png deleted file mode 100644 index d30337d2..00000000 Binary files a/branding/logo/pecos_logo.png and /dev/null differ diff --git a/branding/logo/pecos_logo_v2.png b/branding/logo/pecos_logo_v2.png deleted file mode 100644 index 5607a7fb..00000000 Binary files a/branding/logo/pecos_logo_v2.png and /dev/null differ diff --git a/branding/logo/pecos_logo_v2.svg b/branding/logo/pecos_logo_v2.svg index ed733d3d..0d07528a 100644 --- a/branding/logo/pecos_logo_v2.svg +++ b/branding/logo/pecos_logo_v2.svg @@ -2,42 +2,38 @@ + style="enable-background:new" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + style="color-interpolation-filters:sRGB" + x="-0.017638889" + width="1.0352778" + y="-inf" + height="inf"> - + showguides="false" + inkscape:showpageshadow="2" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1"> + spacingy="1" + units="px" /> + originy="-3.4038546" + spacingy="1" + gridanglex="30" + gridanglez="30" /> @@ -99,7 +102,6 @@ image/svg+xml - @@ -198,7 +200,7 @@ style="font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'Cambria Math';-inkscape-font-specification:'Sans Oblique';letter-spacing:0px;word-spacing:0px;fill:#4d4d4d;fill-opacity:1;stroke:none" xml:space="preserve" transform="scale(1.0009214,0.99907944)"> + PECOS + x="494.43301" + y="436.61966" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:96px;font-family:Helvetica;-inkscape-font-specification:Helvetica;fill:#666666">PECOS + id="flowPara882" /> + + style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:4.9801;marker:none;enable-background:accumulate" /> + style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:4.9801;marker:none;enable-background:accumulate" /> diff --git a/crates/benchmarks/Cargo.toml b/crates/benchmarks/Cargo.toml new file mode 100644 index 00000000..eb9a774f --- /dev/null +++ b/crates/benchmarks/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "benchmarks" +version.workspace = true +edition.workspace = true +authors.workspace = true +homepage.workspace = true +repository.workspace = true +license.workspace = true +keywords.workspace = true +categories.workspace = true +publish = false + +[dev-dependencies] +criterion = "0.5" +pecos = { path = "../pecos" } +pecos-core = { path = "../pecos-core" } +pecos-qsims = { path = "../pecos-qsims" } +pecos-qec = { path = "../pecos-qec" } + +[[bench]] +name = "benchmarks" +harness = false + +[lints] +workspace = true diff --git a/crates/benchmarks/LICENSE b/crates/benchmarks/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/crates/benchmarks/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/crates/benchmarks/README.md b/crates/benchmarks/README.md new file mode 100644 index 00000000..91b6586f --- /dev/null +++ b/crates/benchmarks/README.md @@ -0,0 +1,5 @@ +# benchmarks + +`benchmarks` is an **internal crate** to provide benchmarking of Rust code. + +This is not intended for external use. diff --git a/crates/benchmarks/benches/benchmarks.rs b/crates/benchmarks/benches/benchmarks.rs new file mode 100644 index 00000000..76c041c0 --- /dev/null +++ b/crates/benchmarks/benches/benchmarks.rs @@ -0,0 +1,36 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +use criterion::{criterion_group, criterion_main, Criterion}; + +mod modules { + pub mod element_ops; + // TODO: pub mod hadamard_ops; + // TODO: pub mod pauli_ops; + pub mod set_ops; +} + +use modules::{element_ops, set_ops}; + +fn all_benchmarks(c: &mut Criterion) { + element_ops::benchmarks(c); + set_ops::benchmarks(c); + // TODO: pauli_ops::benchmarks(c); + // TODO: hadamard_ops::benchmarks(c); +} + +criterion_group! { + name = benches; + config = Criterion::default().sample_size(100).measurement_time(core::time::Duration::from_secs(10)); + targets = all_benchmarks +} +criterion_main!(benches); diff --git a/crates/benchmarks/benches/modules/element_ops.rs b/crates/benchmarks/benches/modules/element_ops.rs new file mode 100644 index 00000000..e7b55e1a --- /dev/null +++ b/crates/benchmarks/benches/modules/element_ops.rs @@ -0,0 +1,58 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +use criterion::{black_box, measurement::Measurement, BenchmarkGroup, Criterion}; +use pecos_core::IndexableElement; + +pub fn benchmarks(c: &mut Criterion) { + let mut group = c.benchmark_group("Element Operations"); + bench_conversion::(&mut group, "usize"); + bench_conversion::(&mut group, "u16"); + bench_memory_access::(&mut group, "usize"); + bench_memory_access::(&mut group, "u16"); + group.finish(); +} + +fn bench_conversion, M: Measurement>( + group: &mut BenchmarkGroup, + type_name: &str, +) { + group.bench_function(format!("conversion_{type_name}"), |b| { + b.iter(|| { + let mut sum = 0_usize; + for i in 0..1000_u16 { + sum += E::from(i).to_usize(); + } + black_box(sum) + }); + }); +} + +#[allow(clippy::cast_possible_truncation)] +fn bench_memory_access, M: Measurement>( + group: &mut BenchmarkGroup, + type_name: &str, +) { + group.bench_function(format!("memory_access_{type_name}"), |b| { + let mut vec = Vec::new(); + for i in 0..1000_u16 { + vec.push(E::from(i)); + } + b.iter(|| { + let mut sum = E::from(0_u16); + for &item in &vec { + sum = E::from((sum.to_usize() + item.to_usize()) as u16); + } + black_box(sum) + }); + }); +} diff --git a/crates/benchmarks/benches/modules/set_ops.rs b/crates/benchmarks/benches/modules/set_ops.rs new file mode 100644 index 00000000..07c2d19a --- /dev/null +++ b/crates/benchmarks/benches/modules/set_ops.rs @@ -0,0 +1,104 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +use criterion::{black_box, measurement::Measurement, BenchmarkGroup, Criterion}; +use pecos_core::{IndexableElement, Set, VecSet}; + +pub fn benchmarks(c: &mut Criterion) { + let mut group = c.benchmark_group("Set Operations"); + bench_set_operations::(&mut group, "usize"); + bench_set_operations::(&mut group, "u16"); + bench_vecset_operations::(&mut group, "usize"); + bench_vecset_operations::(&mut group, "u16"); + group.finish(); +} + +fn bench_set_operations, M: Measurement>( + group: &mut BenchmarkGroup, + type_name: &str, +) { + group.bench_function(format!("set_operations_{type_name}"), |b| { + b.iter(|| { + let mut set = VecSet::::new(); + for i in 0..100_u16 { + set.insert(E::from(i)); + } + for i in 0..100_u16 { + black_box(set.contains(&E::from(i))); + } + for i in 0..100_u16 { + set.remove(&E::from(i)); + } + }); + }); +} + +fn bench_vecset_operations + Copy, M: Measurement>( + group: &mut BenchmarkGroup, + type_name: &str, +) { + // Benchmark insert + group.bench_function(format!("VecSet<{type_name}>/insert"), |b| { + b.iter(|| { + let mut set = VecSet::::new(); + for i in 0..100_u8 { + set.insert(E::from(i)); + } + }); + }); + + // Benchmark contains + group.bench_function(format!("VecSet<{type_name}>/contains"), |b| { + let set: VecSet = (0..100_u8).map(E::from).collect(); + b.iter(|| { + for i in 0..100_u8 { + black_box(set.contains(&E::from(i))); + } + }); + }); + + // Benchmark remove + group.bench_function(format!("VecSet<{type_name}>/remove"), |b| { + b.iter(|| { + let mut set: VecSet = (0..100_u8).map(E::from).collect(); + for i in 0..100_u8 { + set.remove(&E::from(i)); + } + }); + }); + + // Benchmark union + group.bench_function(format!("VecSet<{type_name}>/union"), |b| { + let set1: VecSet = (0..50_u8).map(E::from).collect(); + let set2: VecSet = (25..75_u8).map(E::from).collect(); + b.iter(|| { + let mut result = VecSet::::new(); + for &item in set1.union(&set2) { + result.insert(item); + } + black_box(result); + }); + }); + + // Benchmark intersection + group.bench_function(format!("VecSet<{type_name}>/intersection"), |b| { + let set1: VecSet = (0..50_u8).map(E::from).collect(); + let set2: VecSet = (25..75_u8).map(E::from).collect(); + b.iter(|| { + let mut result = VecSet::::new(); + for &item in set1.intersection(&set2) { + result.insert(item); + } + black_box(result); + }); + }); +} diff --git a/crates/benchmarks/src/lib.rs b/crates/benchmarks/src/lib.rs new file mode 100644 index 00000000..3f3365f9 --- /dev/null +++ b/crates/benchmarks/src/lib.rs @@ -0,0 +1,13 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +// Intentionally empty diff --git a/crates/pecos-core/Cargo.toml b/crates/pecos-core/Cargo.toml new file mode 100644 index 00000000..260541d6 --- /dev/null +++ b/crates/pecos-core/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "pecos-core" +version.workspace = true +edition.workspace = true +authors.workspace = true +homepage.workspace = true +repository.workspace = true +license.workspace = true +keywords.workspace = true +categories.workspace = true +description = "Provides core definitions and functions for PECOS simulations." + +[dependencies] +rand = { workspace = true } +rand_chacha = { workspace = true } +rand_xoshiro = { workspace = true } + +[lints] +workspace = true diff --git a/crates/pecos-core/LICENSE b/crates/pecos-core/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/crates/pecos-core/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/crates/pecos-core/README.md b/crates/pecos-core/README.md new file mode 100644 index 00000000..a4d2b2b8 --- /dev/null +++ b/crates/pecos-core/README.md @@ -0,0 +1,5 @@ +# pecos-core + +`pecos-core` is an **internal crate** to provide core functionality. + +This is not intended for external use. diff --git a/crates/pecos-core/src/lib.rs b/crates/pecos-core/src/lib.rs new file mode 100644 index 00000000..26c77661 --- /dev/null +++ b/crates/pecos-core/src/lib.rs @@ -0,0 +1,28 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +mod sets; +mod sims_rngs; + +pub use sets::element::{Element, IndexableElement}; +pub use sets::set::Set; +pub use sets::vec_set::VecSet; + +pub use crate::sims_rngs::chacha_rng::{ChaCha12Rng, ChaCha20Rng, ChaCha8Rng}; +pub use crate::sims_rngs::choices::Choices; +pub use crate::sims_rngs::cyclic_rng::{CyclicRng, CyclicSeed}; +// pub use crate::sims_rngs::mock_rng::MockRng; +pub use crate::sims_rngs::sim_rng::SimRng; +pub use crate::sims_rngs::xoshiro_rng::{ + Xoshiro128PlusPlus, Xoshiro128StarStar, Xoshiro256PlusPlus, Xoshiro256StarStar, + Xoshiro512PlusPlus, Xoshiro512StarStar, +}; diff --git a/crates/pecos-core/src/sets.rs b/crates/pecos-core/src/sets.rs new file mode 100644 index 00000000..b7f39915 --- /dev/null +++ b/crates/pecos-core/src/sets.rs @@ -0,0 +1,15 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +pub mod element; +pub mod set; +pub mod vec_set; diff --git a/crates/pecos-core/src/sets/element.rs b/crates/pecos-core/src/sets/element.rs new file mode 100644 index 00000000..a34a3509 --- /dev/null +++ b/crates/pecos-core/src/sets/element.rs @@ -0,0 +1,80 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +use core::fmt::Debug; +use core::hash::Hash; + +pub trait Element: Debug + Clone + Ord + Copy + Hash {} + +// blanket implementation should allow for integers, char, etc. +impl Element for T {} + +#[allow(clippy::module_name_repetitions)] +pub trait IndexableElement: Element { + fn to_usize(&self) -> usize; + fn from_usize(value: usize) -> Self; +} + +macro_rules! impl_indexable_element_safe { + ($t:ty) => { + impl IndexableElement for $t { + #[allow(clippy::as_conversions, clippy::cast_possible_truncation)] + #[inline(always)] + fn to_usize(&self) -> usize { + *self as usize + } + + #[allow(clippy::as_conversions, clippy::cast_possible_truncation)] + #[inline(always)] + fn from_usize(value: usize) -> Self { + value as $t + } + } + }; +} + +// Safe implementations for types that are always smaller than or equal to usize +impl_indexable_element_safe!(u8); +impl_indexable_element_safe!(u16); +impl_indexable_element_safe!(u32); +impl_indexable_element_safe!(usize); + +// Conditional implementation for u64 +#[cfg(target_pointer_width = "64")] +impl_indexable_element_safe!(u64); + +#[cfg(target_pointer_width = "32")] +impl IndexableElement for u64 { + #[inline(always)] + fn to_usize(&self) -> usize { + usize::try_from(*self).expect("u64 value too large for 32-bit usize") + } + + #[allow(clippy::as_conversions)] + #[inline(always)] + fn from_usize(value: usize) -> Self { + value as u64 + } +} + +// u128 is always problematic for current architectures, so we'll implement it to always panic +impl IndexableElement for u128 { + #[inline(always)] + fn to_usize(&self) -> usize { + panic!("u128 cannot be safely converted to usize without potential data loss") + } + + #[inline(always)] + fn from_usize(_value: usize) -> Self { + panic!("usize cannot be safely converted to u128 on all platforms") + } +} diff --git a/crates/pecos-core/src/sets/set.rs b/crates/pecos-core/src/sets/set.rs new file mode 100644 index 00000000..a95f880d --- /dev/null +++ b/crates/pecos-core/src/sets/set.rs @@ -0,0 +1,187 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +use crate::Element; +use core::fmt::Debug; +use core::ops::{BitAndAssign, BitOrAssign, BitXorAssign, SubAssign}; + +pub trait Set<'a>: + Debug + + Clone + + Default + + BitAndAssign<&'a Self> + + BitAndAssign<&'a Self::Element> + + BitOrAssign<&'a Self> + + BitOrAssign<&'a Self::Element> + + BitXorAssign<&'a Self> + + BitXorAssign<&'a Self::Element> + + SubAssign<&'a Self> + + SubAssign<&'a Self::Element> +where + Self: 'a, +{ + type Element: Element + 'a; + + type Iter: Iterator; + type Difference: Iterator; + type Intersection: Iterator; + type SymmetricDifference: Iterator; + type Union: Iterator; + + fn new() -> Self; + + fn capacity(&self) -> usize; + fn clear(&mut self); + fn contains(&self, value: &Self::Element) -> bool; + /// Returns an iterator of elements representing the difference between this set and another, + /// i.e., the elements that are in `self` but not in `other`. + fn difference(&'a self, other: &'a Self) -> Self::Difference; + fn difference_ref(&'a self, other: &'a Self) -> Self::Difference; + fn insert(&mut self, value: Self::Element); + // TODO: Make signature that matches HashSet + fn intersection(&'a self, other: &'a Self) -> Self::Intersection; + #[inline] + fn intersection_update(&mut self, rhs: &Self) { + self.retain(|&x| rhs.contains(&x)); + } + #[inline] + fn intersection_item_update(&mut self, value: &Self::Element) { + self.retain(|&x| x == *value); + } + fn is_empty(&self) -> bool; + fn iter(&'a self) -> Self::Iter; + fn len(&self) -> usize; + fn remove(&mut self, value: &Self::Element); + fn retain(&mut self, f: F) + where + F: FnMut(&Self::Element) -> bool; + fn symmetric_difference(&'a self, other: &'a Self) -> Self::SymmetricDifference; + fn symmetric_difference_update(&mut self, rhs: &Self); + + #[inline] + fn symmetric_difference_item_update(&mut self, value: &Self::Element) { + if self.contains(value) { + self.remove(value); + } else { + self.insert(*value); + } + } + fn union(&'a self, other: &'a Self) -> Self::Union; + fn union_update(&mut self, rhs: &Self); + #[inline] + fn union_item_update(&mut self, value: &Self::Element) { + self.insert(*value); + } + fn with_capacity(capacity: usize) -> Self; + + #[inline] + // Default implementations for BitAndAssign, BitOrAssign, BitXorAssign, and SubAssign + fn bitand_assign_set(&mut self, rhs: &Self) { + self.intersection_update(rhs); + } + + #[inline] + fn bitand_assign_item(&mut self, rhs: &Self::Element) { + self.intersection_item_update(rhs); + } + + #[inline] + fn bitor_assign_set(&mut self, rhs: &Self) { + self.union_update(rhs); + } + + #[inline] + fn bitor_assign_item(&mut self, rhs: &Self::Element) { + self.union_item_update(rhs); + } + + #[inline] + fn bitxor_assign_set(&mut self, rhs: &Self) { + self.symmetric_difference_update(rhs); + } + + #[inline] + fn bitxor_assign_item(&mut self, rhs: &Self::Element) { + self.symmetric_difference_item_update(rhs); + } + + #[inline] + fn sub_assign_set(&mut self, rhs: &Self) { + self.retain(|x| !rhs.contains(x)); + } + + #[inline] + fn sub_assign_item(&mut self, rhs: &Self::Element) { + self.remove(rhs); + } +} + +#[macro_export] +macro_rules! build_set_bit_ops { + ($set_type:ty) => { + impl<'a, E: Element> BitAndAssign<&'a $set_type> for $set_type { + #[inline] + fn bitand_assign(&mut self, rhs: &$set_type) { + self.bitand_assign_set(rhs); + } + } + + impl<'a, E: Element> BitAndAssign<&'a E> for $set_type { + #[inline] + fn bitand_assign(&mut self, rhs: &E) { + self.bitand_assign_item(rhs); + } + } + + impl<'a, E: Element> BitOrAssign<&'a $set_type> for $set_type { + #[inline] + fn bitor_assign(&mut self, rhs: &$set_type) { + self.bitor_assign_set(rhs); + } + } + + impl<'a, E: Element> BitOrAssign<&'a E> for $set_type { + #[inline] + fn bitor_assign(&mut self, rhs: &E) { + self.bitor_assign_item(rhs); + } + } + + impl<'a, E: Element> BitXorAssign<&'a $set_type> for $set_type { + #[inline] + fn bitxor_assign(&mut self, rhs: &$set_type) { + self.bitxor_assign_set(rhs); + } + } + + impl<'a, E: Element> BitXorAssign<&'a E> for $set_type { + #[inline] + fn bitxor_assign(&mut self, rhs: &E) { + self.bitxor_assign_item(rhs); + } + } + + impl<'a, E: Element> SubAssign<&'a $set_type> for $set_type { + #[inline] + fn sub_assign(&mut self, rhs: &$set_type) { + self.sub_assign_set(rhs); + } + } + + impl<'a, E: Element> SubAssign<&'a E> for $set_type { + #[inline] + fn sub_assign(&mut self, rhs: &E) { + self.sub_assign_item(rhs); + } + } + }; +} diff --git a/crates/pecos-core/src/sets/vec_set.rs b/crates/pecos-core/src/sets/vec_set.rs new file mode 100644 index 00000000..fb0e182c --- /dev/null +++ b/crates/pecos-core/src/sets/vec_set.rs @@ -0,0 +1,276 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +mod iterators; +mod operators; +mod set_impl; + +use crate::{Element, Set}; +use core::slice::Iter; + +#[derive(Clone, Debug)] +pub struct VecSet { + elements: Vec, +} + +#[macro_export] +macro_rules! vecset { + ($($x:expr),+ $(,)?) => { + { + let arr = [$($x),+]; + VecSet::from(arr) + } + }; +} + +impl From<[E; N]> for VecSet { + #[inline] + fn from(arr: [E; N]) -> Self { + Self::from_iter(arr) + } +} + +impl FromIterator for VecSet { + #[inline] + fn from_iter>(iter: I) -> Self { + let mut set = Self::new(); + for item in iter { + set.insert(item); + } + set + } +} + +impl VecSet { + #[inline] + #[must_use] + pub fn new() -> Self { + Self::default() + } + + #[inline] + pub fn iter(&self) -> Iter<'_, E> { + return self.elements.iter(); + } +} + +impl Default for VecSet { + #[inline] + fn default() -> Self { + Self { + elements: Vec::default(), + } + } +} + +impl<'a, E: Element> IntoIterator for &'a VecSet { + type Item = &'a E; + type IntoIter = Iter<'a, E>; + + #[inline] + fn into_iter(self) -> Self::IntoIter { + return self.iter(); + } +} + +#[cfg(test)] +mod tests { + use super::super::set::Set; + use super::VecSet; + + #[test] + fn test_new() { + let set = VecSet::::new(); + assert!(set.elements.is_empty()); + } + + #[test] + fn test_with_capacity() { + let set = VecSet::::with_capacity(10); + assert!(set.elements.is_empty()); + assert_eq!(set.capacity(), 10); + } + + #[test] + fn test_new_with_vec() { + let set: VecSet = vec![4, 5, 6, 4].into_iter().collect(); + assert_eq!(set.elements, vec![4, 5, 6]); + } + + #[test] + fn test_new_from() { + let set = VecSet::::from([4, 5, 6, 4]); + assert_eq!(set.elements, vec![4, 5, 6]); + } + + #[test] + fn test_insert() { + let mut set = VecSet::::new(); + set.insert(1); + assert_eq!(set.elements, vec![1]); + set.insert(5); + set.insert(1); + assert_eq!(set.elements, vec![1, 5]); + } + + #[test] + fn test_remove() { + let mut set: VecSet = VecSet::from([4, 5, 6, 4]); + set.remove(&5); + assert_eq!(set.elements, vec![4, 6]); + set.remove(&7); + assert_eq!(set.elements, vec![4, 6]); + } + + #[test] + fn test_union() { + let mut set_a: VecSet = VecSet::from([1, 2]); + let set_b = VecSet::from([2, 3]); + set_a.union_update(&set_b); + assert_eq!(set_a.elements, vec![1, 2, 3]); + } + + #[test] + fn test_symmetric_difference_update() { + let mut set_a = VecSet::::from([4, 5, 6, 4]); + let set_b = VecSet::::from([1, 3, 4]); + set_a.symmetric_difference_update(&set_b); + assert_eq!(set_a.elements, vec![5, 6, 1, 3]); + } + + #[test] + fn test_intersection_update() { + let mut set_a: VecSet = VecSet::from([1, 2, 3]); + let set_b = VecSet::from([2, 3, 4]); + set_a.intersection_update(&set_b); + assert_eq!(set_a.elements, vec![2, 3]); + } + + #[test] + fn test_intersection() { + let set_a: VecSet = VecSet::from([1, 2, 3]); + let set_b = VecSet::from([2, 3, 4]); + let intersection: Vec<_> = set_a.intersection(&set_b).copied().collect(); + assert_eq!(intersection, vec![2, 3]); + } + + #[test] + fn test_symmetric_difference() { + let set_a = VecSet::::from([4, 5, 6, 4]); + let set_b = VecSet::::from([1, 3, 4]); + let sym_diff: Vec<_> = set_a.symmetric_difference(&set_b).copied().collect(); + assert_eq!(sym_diff, vec![5, 6, 1, 3]); + } + + #[test] + fn test_bitor_assign() { + let mut set_a: VecSet = VecSet::from([1, 2]); + let set_b: VecSet = VecSet::from([2, 3]); + set_a |= &set_b; + assert_eq!(set_a.elements, vec![1, 2, 3]); + } + + #[test] + fn test_bitxor_assign() { + let mut set_a: VecSet = VecSet::from([1, 2, 3]); + let set_b: VecSet = VecSet::from([2, 3, 4]); + set_a ^= &set_b; + assert_eq!(set_a.elements, vec![1, 4]); + } + + #[test] + fn test_bitand_assign() { + let mut set_a: VecSet = VecSet::from([1, 2, 3]); + let set_b = VecSet::from([2, 3, 4]); + set_a &= &set_b; + assert_eq!(set_a.elements, vec![2, 3]); + } + + #[test] + fn test_bitand_assign_single_element_ref() { + let mut set_a: VecSet = VecSet::from([1, 2, 3]); + let element: u8 = 2; + set_a &= &element; + assert_eq!(set_a.elements, vec![2]); + + let mut set_b: VecSet = VecSet::from([1, 2, 3]); + let non_existing_element: u8 = 4; + set_b &= &non_existing_element; + assert_eq!(set_b.elements, Vec::::new()); + } + + #[test] + fn test_difference() { + let set_a: VecSet = VecSet::from([1, 2, 3]); + let set_b = VecSet::from([2, 3, 4]); + let diff: Vec<_> = set_a.difference(&set_b).copied().collect(); + assert_eq!(diff, vec![1]); + } + + #[test] + fn test_capacity() { + let mut set = VecSet::::with_capacity(10); + assert_eq!(set.capacity(), 10); + set.insert(1); + assert!(set.capacity() >= 1); + } + + #[test] + fn test_clear() { + let mut set = VecSet::::from([1, 2, 3]); + assert!(!set.is_empty()); + set.clear(); + assert!(set.is_empty()); + } + + #[test] + fn test_symmetric_difference_item_update() { + let mut set = VecSet::::from([1, 2, 3]); + set.symmetric_difference_item_update(&2); + assert_eq!(set.elements, vec![1, 3]); + set.symmetric_difference_item_update(&4); + assert_eq!(set.elements, vec![1, 3, 4]); + } + + #[test] + fn test_union_item_update() { + let mut set = VecSet::::from([1, 2, 3]); + set.union_item_update(&4); + assert_eq!(set.elements, vec![1, 2, 3, 4]); + } + + #[test] + fn test_sub_ref() { + let set_a: VecSet = VecSet::from([1, 2, 3]); + let set_b: VecSet = VecSet::from([2, 3, 4]); + let difference: Vec<_> = set_a.difference_ref(&set_b).copied().collect(); + assert_eq!(difference, vec![1]); + } + + #[test] + fn test_a_xor_b_sub_c() { + let mut set_a: VecSet = VecSet::from([1, 2, 3, 4, 5]); + let set_b: VecSet = VecSet::from([2, 3, 6]); + let set_c: VecSet = VecSet::from([3]); + set_a ^= set_b.difference(&set_c).copied().collect::>(); + assert_eq!(set_a.elements, vec![1, 3, 4, 5, 6]); + } + + #[test] + fn test_a_xor_b_sub_c_glyphs() { + let mut set_a: VecSet = VecSet::from([1, 2, 3, 4, 5]); + let set_b: VecSet = VecSet::from([2, 3, 6]); + let set_c: VecSet = VecSet::from([3]); + set_a ^= &set_b - &set_c; // TODO: Get this to work for Set + assert_eq!(set_a.elements, vec![1, 3, 4, 5, 6]); + } +} diff --git a/crates/pecos-core/src/sets/vec_set/iterators.rs b/crates/pecos-core/src/sets/vec_set/iterators.rs new file mode 100644 index 00000000..80459068 --- /dev/null +++ b/crates/pecos-core/src/sets/vec_set/iterators.rs @@ -0,0 +1,205 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +use crate::Set; +use crate::VecSet; +use core::fmt; +use core::iter::Chain; +use core::slice::Iter; + +use crate::Element; + +pub struct SymmetricDifference<'a, E: Element> { + pub(crate) iter: Chain, Difference<'a, E>>, +} + +#[derive(Clone)] +pub struct Difference<'a, E: Element> { + pub(crate) iter: Iter<'a, E>, + pub(crate) other: &'a VecSet, +} + +#[derive(Clone)] +pub struct Intersection<'a, E: Element> { + pub(crate) iter: Iter<'a, E>, + pub(crate) other: &'a VecSet, +} + +#[derive(Clone)] +pub struct Union<'a, E: Element> { + pub(crate) iter: Chain, Difference<'a, E>>, +} + +impl Clone for SymmetricDifference<'_, E> { + #[inline] + fn clone(&self) -> Self { + SymmetricDifference { + iter: self.iter.clone(), + } + } +} + +impl<'a, E: Element> Iterator for SymmetricDifference<'a, E> { + type Item = &'a E; + + #[inline] + fn next(&mut self) -> Option<&'a E> { + self.iter.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + + #[inline] + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.iter.fold(init, f) + } +} + +impl<'a, E: Element> Iterator for Difference<'a, E> { + type Item = &'a E; + + #[inline] + fn next(&mut self) -> Option<&'a E> { + self.iter.by_ref().find(|&item| !self.other.contains(item)) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } + + #[inline] + fn fold(self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.iter.fold(init, |acc, elt| { + if self.other.contains(elt) { + acc + } else { + f(acc, elt) + } + }) + } +} + +impl<'a, E: Element> Iterator for Intersection<'a, E> { + type Item = &'a E; + + #[inline] + fn next(&mut self) -> Option<&'a E> { + loop { + let elt = self.iter.next()?; + if self.other.contains(elt) { + return Some(elt); + } + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } + + #[inline] + fn fold(self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.iter.fold(init, |acc, elt| { + if self.other.contains(elt) { + f(acc, elt) + } else { + acc + } + }) + } +} + +impl<'a, E: Element> Iterator for Union<'a, E> { + type Item = &'a E; + + #[inline] + fn next(&mut self) -> Option<&'a E> { + self.iter.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + + #[inline] + fn count(self) -> usize { + self.iter.count() + } + + #[inline] + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.iter.fold(init, f) + } +} + +impl fmt::Debug for Difference<'_, E> +// where +// T: fmt::Debug + UnsignedInt, +{ + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + return f.debug_list().entries(self.clone()).finish(); + } +} + +impl fmt::Debug for SymmetricDifference<'_, E> +// where +// T: fmt::Debug + UnsignedInt, +{ + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + return f.debug_list().entries(self.clone()).finish(); + } +} + +impl fmt::Debug for Intersection<'_, E> +// where +// T: fmt::Debug + UnsignedInt, +{ + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + return f.debug_list().entries(self.clone()).finish(); + } +} + +impl fmt::Debug for Union<'_, E> +//where +// T: fmt::Debug + UnsignedInt, +{ + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + return f.debug_list().entries(self.clone()).finish(); + } +} diff --git a/crates/pecos-core/src/sets/vec_set/operators.rs b/crates/pecos-core/src/sets/vec_set/operators.rs new file mode 100644 index 00000000..19a0767b --- /dev/null +++ b/crates/pecos-core/src/sets/vec_set/operators.rs @@ -0,0 +1,96 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +use crate::build_set_bit_ops; +use crate::Set; +use crate::VecSet; +use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Sub, SubAssign}; + +use crate::Element; + +impl<'a, E: Element> BitAnd<&'a VecSet> for &'a VecSet { + type Output = VecSet; + + #[inline] + fn bitand(self, rhs: &'a VecSet) -> Self::Output { + return VecSet { + elements: self.intersection(rhs).copied().collect(), + }; + } +} + +impl<'a, E: Element> BitOr<&'a VecSet> for &VecSet { + type Output = VecSet; + + #[inline] + fn bitor(self, rhs: &'a VecSet) -> VecSet { + return VecSet { + elements: self.union(rhs).copied().collect(), + }; + } +} + +impl<'a, E: Element> BitXor<&'a VecSet> for &VecSet { + type Output = VecSet; + + #[inline] + fn bitxor(self, rhs: &'a VecSet) -> VecSet { + return VecSet { + elements: self.symmetric_difference(rhs).copied().collect(), + }; + } +} + +impl<'a, E: Element> Sub<&'a VecSet> for &VecSet { + type Output = VecSet; + + #[inline] + fn sub(self, rhs: &'a VecSet) -> VecSet { + return VecSet { + elements: self.difference(rhs).copied().collect(), + }; + } +} + +// TODO: Shouldn't this be fore &VecSet? +impl BitXorAssign> for VecSet { + #[inline] + fn bitxor_assign(&mut self, rhs: VecSet) { + for item in rhs.elements { + if self.contains(&item) { + self.remove(&item); + } else { + self.insert(item); + } + } + } +} + +//impl<'a, T> BitXorAssign<&'a Self> for VecSet +//where +//T: UnsignedInt + 'a, +//{ +//fn bitxor_assign(&mut self, rhs: &Self) { +//self.bitxor_assign_set(rhs); +//} +//} + +//impl<'a, T> BitXorAssign<&'a T> for VecSet +//where +//T: UnsignedInt + 'a, +//{ +//fn bitxor_assign(&mut self, rhs: &T) { +//self.bitxor_assign_item(rhs); +//} +//} + +build_set_bit_ops!(VecSet); diff --git a/crates/pecos-core/src/sets/vec_set/set_impl.rs b/crates/pecos-core/src/sets/vec_set/set_impl.rs new file mode 100644 index 00000000..16275d6b --- /dev/null +++ b/crates/pecos-core/src/sets/vec_set/set_impl.rs @@ -0,0 +1,163 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +use crate::sets::vec_set::iterators::{Difference, Intersection, SymmetricDifference, Union}; +use crate::VecSet; +use core::slice::Iter; + +use crate::{Element, Set}; + +impl<'a, E: Element + 'a> Set<'a> for VecSet { + type Element = E; + type Iter = Iter<'a, E>; + type Difference = Difference<'a, E>; + type Intersection = Intersection<'a, E>; + type SymmetricDifference = SymmetricDifference<'a, E>; + type Union = Union<'a, E>; + + #[inline] + #[must_use] + fn new() -> Self { + Self::new() + } + + #[inline] + fn capacity(&self) -> usize { + self.elements.capacity() + } + + #[inline] + fn clear(&mut self) { + self.elements.clear(); + } + + #[inline] + fn contains(&self, value: &E) -> bool { + self.elements.contains(value) + } + + #[inline] + fn difference(&'a self, other: &'a Self) -> Self::Difference { + Difference { + iter: self.elements.iter(), + other, + } + } + + #[inline] + fn difference_ref(&'a self, other: &'a Self) -> Self::Difference { + self.difference(other) + } + + #[inline] + fn insert(&mut self, value: E) { + if !self.elements.contains(&value) { + self.elements.push(value); + } + } + + #[inline] + fn intersection(&'a self, other: &'a Self) -> Self::Intersection { + if self.len() <= other.len() { + Intersection { + iter: self.iter(), + other, + } + } else { + Intersection { + iter: other.iter(), + other: self, + } + } + } + + #[inline] + fn is_empty(&self) -> bool { + self.elements.is_empty() + } + + #[inline] + fn iter(&'a self) -> Self::Iter { + self.elements.iter() + } + + #[inline] + fn len(&self) -> usize { + self.elements.len() + } + + #[inline] + fn remove(&mut self, value: &E) { + self.elements.retain(|&x| x != *value); + } + + #[inline] + fn retain(&mut self, f: F) + where + F: FnMut(&E) -> bool, + { + self.elements.retain(f); + } + + #[inline] + fn symmetric_difference(&'a self, other: &'a Self) -> Self::SymmetricDifference { + SymmetricDifference { + iter: self.difference(other).chain(other.difference(self)), + } + } + + #[inline] + fn symmetric_difference_update(&mut self, rhs: &Self) { + let mut temp = Self::new(); + self.retain(|x| { + if rhs.contains(x) { + temp.insert(*x); + false + } else { + true + } + }); + for item in &rhs.elements { + if !temp.contains(item) { + self.insert(*item); + } + } + } + + #[inline] + fn union(&'a self, other: &'a Self) -> Self::Union { + if self.len() >= other.len() { + Union { + iter: self.iter().chain(other.difference(self)), + } + } else { + Union { + iter: other.iter().chain(self.difference(other)), + } + } + } + + #[inline] + fn union_update(&mut self, rhs: &Self) { + for &item in &rhs.elements { + self.insert(item); + } + } + + #[inline] + #[must_use] + fn with_capacity(capacity: usize) -> Self { + Self { + elements: Vec::with_capacity(capacity), + } + } +} diff --git a/crates/pecos-core/src/sims_rngs.rs b/crates/pecos-core/src/sims_rngs.rs new file mode 100644 index 00000000..ef71b98a --- /dev/null +++ b/crates/pecos-core/src/sims_rngs.rs @@ -0,0 +1,18 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +pub mod chacha_rng; +pub mod choices; +pub mod cyclic_rng; +// pub mod mock_rng; +pub mod sim_rng; +pub mod xoshiro_rng; diff --git a/crates/pecos-core/src/sims_rngs/chacha_rng.rs b/crates/pecos-core/src/sims_rngs/chacha_rng.rs new file mode 100644 index 00000000..37a8d4f7 --- /dev/null +++ b/crates/pecos-core/src/sims_rngs/chacha_rng.rs @@ -0,0 +1,18 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +use super::sim_rng::SimRng; +pub use rand_chacha::{ChaCha12Rng, ChaCha20Rng, ChaCha8Rng}; + +impl SimRng for ChaCha8Rng {} // fastest but less cryptographically secure +impl SimRng for ChaCha12Rng {} +impl SimRng for ChaCha20Rng {} // slowest but most cryptographically secure diff --git a/crates/pecos-core/src/sims_rngs/choices.rs b/crates/pecos-core/src/sims_rngs/choices.rs new file mode 100644 index 00000000..b7c50495 --- /dev/null +++ b/crates/pecos-core/src/sims_rngs/choices.rs @@ -0,0 +1,73 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +use rand::distributions::{Distribution, WeightedIndex}; +use rand::RngCore; + +const EPSILON: f64 = 1e-9; + +/// Struct to hold choices and pre-validated `WeightedIndex` +/// The weights need to sum up close to 1.0 and will be re-normalized if they do so. +#[derive(Debug)] +pub struct Choices { + items: Vec, + weighted_index: WeightedIndex, +} + +impl Choices { + /// Validate and normalize weights, then create Choices struct + /// # Panics + /// This will panic if the number of weights and number of items are not the same. + #[inline] + #[allow(clippy::float_arithmetic)] + #[must_use] + pub fn new(items: Vec, weights: &[f64]) -> Self { + assert_eq!( + items.len(), + weights.len(), + "Number of items needs to equal number of weights" + ); + assert!( + weights.iter().all(|&w| w >= 0.0f64), + "All weights must be positive numbers since they represent probabilities." + ); + + let sum_weights: f64 = weights.iter().sum(); + assert!( + isclose(sum_weights, 1.0, EPSILON), + "Weights do not sum to 1 \u{b1} \u{3b5}" // 1 ± ε + ); + + let normalized_weights: Vec = weights.iter().map(|&w| w / sum_weights).collect(); + let weighted_index = WeightedIndex::new(normalized_weights) + .expect("Failed to create WeightedIndex due to invalid weights"); + + Choices { + items, + weighted_index, + } + } + + /// Sample a choice based on the weights + #[inline] + pub fn sample(&self, rng: &mut R) -> &T { + let index = self.weighted_index.sample(rng); + &self.items[index] + } +} + +/// Determine if two floats are close to each other. +#[inline] +#[allow(clippy::single_call_fn, clippy::float_arithmetic)] +fn isclose(a: f64, b: f64, epsilon: f64) -> bool { + (a - b).abs() <= epsilon +} diff --git a/crates/pecos-core/src/sims_rngs/cyclic_rng.rs b/crates/pecos-core/src/sims_rngs/cyclic_rng.rs new file mode 100644 index 00000000..a578f67e --- /dev/null +++ b/crates/pecos-core/src/sims_rngs/cyclic_rng.rs @@ -0,0 +1,88 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +use super::sim_rng::SimRng; +use rand::{Error, RngCore, SeedableRng}; + +const N: usize = 64; + +#[derive(Debug)] +pub struct CyclicSeed(pub [u8; N]); + +impl Default for CyclicSeed { + #[inline] + fn default() -> Self { + Self([0; N]) + } +} + +impl AsMut<[u8]> for CyclicSeed { + #[inline] + fn as_mut(&mut self) -> &mut [u8] { + &mut self.0 + } +} + +#[allow(unused)] +#[derive(Debug)] +pub struct CyclicRng { + seed: CyclicSeed, + bools: Vec, +} + +impl CyclicRng { + #[allow(dead_code)] + #[inline] + fn set_bools(&mut self, bools: &[bool]) { + bools.clone_into(&mut self.bools); + } +} + +impl RngCore for CyclicRng { + #[allow(unused)] + #[inline] + fn next_u32(&mut self) -> u32 { + todo!() + } + + #[allow(unused)] + #[inline] + fn next_u64(&mut self) -> u64 { + todo!() + } + + #[allow(unused)] + #[inline] + fn fill_bytes(&mut self, dest: &mut [u8]) { + todo!() + } + + #[allow(unused)] + #[inline] + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + todo!() + } +} + +impl SeedableRng for CyclicRng { + type Seed = CyclicSeed; + + #[inline] + fn from_seed(seed: Self::Seed) -> Self { + Self { + seed, + bools: vec![], + } + } +} + +impl SimRng for CyclicRng {} diff --git a/crates/pecos-core/src/sims_rngs/sim_rng.rs b/crates/pecos-core/src/sims_rngs/sim_rng.rs new file mode 100644 index 00000000..e8a150eb --- /dev/null +++ b/crates/pecos-core/src/sims_rngs/sim_rng.rs @@ -0,0 +1,56 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +use crate::sims_rngs::choices::Choices; +use core::fmt::Debug; +use rand::distributions::{Bernoulli, Distribution}; +use rand::{RngCore, SeedableRng}; + +/// Represents the minimal interface needed for simulations. +/// This trait also allows the blanket implementation provided by Rng to be overridden in favor of +/// potentially more efficient implementations. +pub trait SimRng: RngCore + SeedableRng + Debug { + /// Generate a single bool where true has a probability of `p`. + #[inline] + fn gen_bool(&mut self, p: f64) -> bool { + Bernoulli::new(p) + .expect("Failed to create Bernoulli distribution due to invalid probability") + .sample(self) + } + + /// Generates a vector of bools, where true has an independent probability of `p`. + #[inline] + fn gen_bools(&mut self, p: f64, n: usize) -> Vec { + let bernoulli = Bernoulli::new(p) + .expect("Failed to create Bernoulli distribution due to invalid probability"); + (0..n).map(|_| bernoulli.sample(self)).collect() + } + + /// Gives true and false each with probability of 50% + #[inline] + #[allow(clippy::cast_possible_wrap, clippy::as_conversions)] + fn coin_flip(&mut self) -> bool { + (self.next_u32() as i32) < 0 + } + + /// Choose between options given a weighted probabilities. + #[inline] + fn choose_weighted<'a, T>(&mut self, choices: &'a Choices) -> &'a T { + return choices.sample(self); + } + + #[inline] + #[must_use] + fn from_entropy() -> Self { + SeedableRng::from_entropy() + } +} diff --git a/crates/pecos-core/src/sims_rngs/xoshiro_rng.rs b/crates/pecos-core/src/sims_rngs/xoshiro_rng.rs new file mode 100644 index 00000000..a912e89a --- /dev/null +++ b/crates/pecos-core/src/sims_rngs/xoshiro_rng.rs @@ -0,0 +1,26 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +use super::sim_rng::SimRng; +pub use rand_xoshiro::{ + Xoshiro128PlusPlus, Xoshiro128StarStar, Xoshiro256PlusPlus, Xoshiro256StarStar, + Xoshiro512PlusPlus, Xoshiro512StarStar, +}; + +impl SimRng for Xoshiro128PlusPlus {} // Recommended for 32-bit systems +impl SimRng for Xoshiro256PlusPlus {} // Recommended for 64-bit systems +impl SimRng for Xoshiro512PlusPlus {} // Recommended if paranoid about parallelization (bigger state) + +// StarStar can be faster for some systems +impl SimRng for Xoshiro128StarStar {} +impl SimRng for Xoshiro256StarStar {} +impl SimRng for Xoshiro512StarStar {} diff --git a/crates/pecos-python/Cargo.toml b/crates/pecos-python/Cargo.toml new file mode 100644 index 00000000..c0e81a66 --- /dev/null +++ b/crates/pecos-python/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "pecos-python" +version.workspace = true +edition.workspace = true +authors.workspace = true +homepage.workspace = true +repository.workspace = true +license.workspace = true +keywords.workspace = true +categories.workspace = true +description = "Allows running Rust code in Python." +publish = false + +[lib] +crate-type = ["cdylib"] + +[dependencies] +pyo3 = { workspace=true, features = ["extension-module"] } +pecos = { path = "../pecos" } + +[lints] +workspace = true diff --git a/crates/pecos-python/LICENSE b/crates/pecos-python/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/crates/pecos-python/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/crates/pecos-python/README.md b/crates/pecos-python/README.md new file mode 100644 index 00000000..bd1237cb --- /dev/null +++ b/crates/pecos-python/README.md @@ -0,0 +1,5 @@ +# pecos-python + +`pecos-python` is an **internal crate** to provide Rust extensions to PECOS in Python. + +This is not intended for external use. diff --git a/crates/pecos-python/src/lib.rs b/crates/pecos-python/src/lib.rs new file mode 100644 index 00000000..8cb94545 --- /dev/null +++ b/crates/pecos-python/src/lib.rs @@ -0,0 +1,22 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +mod sparse_sim; +use sparse_sim::SparseSim; + +use pyo3::prelude::*; + +#[pymodule] +fn _pecos_rslib(_py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> { + m.add_class::()?; + Ok(()) +} diff --git a/crates/pecos-python/src/sparse_sim.rs b/crates/pecos-python/src/sparse_sim.rs new file mode 100644 index 00000000..6f5442e7 --- /dev/null +++ b/crates/pecos-python/src/sparse_sim.rs @@ -0,0 +1,327 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +// use pecos_core::VecSet; +// use pecos_qsims::CliffordSimulator; +// use pecos_qsims::SparseStab; +use pecos::prelude::*; +use pyo3::prelude::*; +use pyo3::types::{PyDict, PyTuple}; +use std::collections::HashMap; + +#[pyclass] +pub struct SparseSim { + inner: SparseStab, usize>, +} + +#[pymethods] +impl SparseSim { + #[new] + fn new(num_qubits: usize) -> Self { + SparseSim { + inner: SparseStab::, usize>::new(num_qubits), + } + } + + #[allow(clippy::too_many_lines)] + #[pyo3(signature = (symbol, location, params=None))] + fn run_gate( + &mut self, + symbol: &str, + location: &Bound<'_, PyTuple>, + params: Option<&Bound<'_, PyDict>>, + ) -> PyResult>> { + match (symbol, location.len()) { + ("X", 1) => { + self.inner.x(location.get_item(0)?.extract()?); + Ok(None) + } + ("Y", 1) => { + self.inner.y(location.get_item(0)?.extract()?); + Ok(None) + } + ("Z", 1) => { + self.inner.z(location.get_item(0)?.extract()?); + Ok(None) + } + ("H", 1) => { + self.inner.h(location.get_item(0)?.extract()?); + Ok(None) + } + ("H2", 1) => { + self.inner.h2(location.get_item(0)?.extract()?); + Ok(None) + } + ("H3", 1) => { + self.inner.h3(location.get_item(0)?.extract()?); + Ok(None) + } + ("H4", 1) => { + self.inner.h4(location.get_item(0)?.extract()?); + Ok(None) + } + ("H5", 1) => { + self.inner.h5(location.get_item(0)?.extract()?); + Ok(None) + } + ("H6", 1) => { + self.inner.h6(location.get_item(0)?.extract()?); + Ok(None) + } + ("F", 1) => { + self.inner.f(location.get_item(0)?.extract()?); + Ok(None) + } + ("Fdg", 1) => { + self.inner.fdg(location.get_item(0)?.extract()?); + Ok(None) + } + ("F2", 1) => { + self.inner.f2(location.get_item(0)?.extract()?); + Ok(None) + } + ("F2dg", 1) => { + self.inner.f2dg(location.get_item(0)?.extract()?); + Ok(None) + } + ("F3", 1) => { + self.inner.f3(location.get_item(0)?.extract()?); + Ok(None) + } + ("F3dg", 1) => { + self.inner.f3dg(location.get_item(0)?.extract()?); + Ok(None) + } + ("F4", 1) => { + self.inner.f4(location.get_item(0)?.extract()?); + Ok(None) + } + ("F4dg", 1) => { + self.inner.f4dg(location.get_item(0)?.extract()?); + Ok(None) + } + ("SX", 1) => { + self.inner.sx(location.get_item(0)?.extract()?); + Ok(None) + } + ("SXdg", 1) => { + self.inner.sxdg(location.get_item(0)?.extract()?); + Ok(None) + } + ("SY", 1) => { + self.inner.sy(location.get_item(0)?.extract()?); + Ok(None) + } + ("SYdg", 1) => { + self.inner.sydg(location.get_item(0)?.extract()?); + Ok(None) + } + ("SZ", 1) => { + self.inner.sz(location.get_item(0)?.extract()?); + Ok(None) + } + ("SZdg", 1) => { + self.inner.szdg(location.get_item(0)?.extract()?); + Ok(None) + } + ("CX", 2) => { + self.inner.cx( + location.get_item(0)?.extract()?, + location.get_item(1)?.extract()?, + ); + Ok(None) + } + ("CY", 2) => { + self.inner.cy( + location.get_item(0)?.extract()?, + location.get_item(1)?.extract()?, + ); + Ok(None) + } + ("CZ", 2) => { + self.inner.cz( + location.get_item(0)?.extract()?, + location.get_item(1)?.extract()?, + ); + Ok(None) + } + ("SXX", 2) => { + self.inner.sxx( + location.get_item(0)?.extract()?, + location.get_item(1)?.extract()?, + ); + Ok(None) + } + ("SXXdg", 2) => { + self.inner.sxxdg( + location.get_item(0)?.extract()?, + location.get_item(1)?.extract()?, + ); + Ok(None) + } + ("SYY", 2) => { + self.inner.syy( + location.get_item(0)?.extract()?, + location.get_item(1)?.extract()?, + ); + Ok(None) + } + ("SYYdg", 2) => { + self.inner.syydg( + location.get_item(0)?.extract()?, + location.get_item(1)?.extract()?, + ); + Ok(None) + } + ("SZZ", 2) => { + self.inner.szz( + location.get_item(0)?.extract()?, + location.get_item(1)?.extract()?, + ); + Ok(None) + } + ("SZZdg", 2) => { + self.inner.szzdg( + location.get_item(0)?.extract()?, + location.get_item(1)?.extract()?, + ); + Ok(None) + } + ("SWAP", 2) => { + self.inner.swap( + location.get_item(0)?.extract()?, + location.get_item(1)?.extract()?, + ); + Ok(None) + } + + ("G2", 2) => { + self.inner.g2( + location.get_item(0)?.extract()?, + location.get_item(1)?.extract()?, + ); + Ok(None) + } + ( + "MZ" | "MX" | "MY" | "MZForced" | "PZ" | "PX" | "PY" | "PZForced" | "PnZ" | "PnX" + | "PnY", + 1, + ) => { + let qubit: usize = location.get_item(0)?.extract()?; + let (result, _) = match symbol { + "MZ" => self.inner.mz(qubit), + "MX" => self.inner.mx(qubit), + "MY" => self.inner.my(qubit), + "MZForced" => { + let forced_value = params + .ok_or_else(|| { + PyErr::new::( + "MZForced requires params", + ) + })? + .get_item("forced_outcome")? + .ok_or_else(|| { + PyErr::new::( + "MZForced requires a 'forced_outcome' parameter", + ) + })? + .call_method0("__bool__")? + .extract::()?; + self.inner.mz_forced(qubit, forced_value) + } + "PZ" => self.inner.pz(qubit), + "PX" => self.inner.px(qubit), + "PY" => self.inner.py(qubit), + "PZForced" => { + let forced_value = params + .ok_or_else(|| { + PyErr::new::( + "PZForced requires params", + ) + })? + .get_item("forced_outcome")? + .ok_or_else(|| { + PyErr::new::( + "PZForced requires a 'forced_outcome' parameter", + ) + })? + .call_method0("__bool__")? + .extract::()?; + self.inner.pz_forced(qubit, forced_value) + } + "PnZ" => self.inner.pnz(qubit), + "PnX" => self.inner.pnx(qubit), + "PnY" => self.inner.pny(qubit), + _ => unreachable!(), + }; + let mut map = HashMap::new(); + if result { + map.insert(qubit, 1); + } + Ok(Some(map)) + } + _ => Err(PyErr::new::( + "Unsupported gate or incorrect number of qubits", + )), + } + } + + fn stab_tableau(&self) -> String { + self.inner.stab_tableau() + } + + fn destab_tableau(&self) -> String { + self.inner.destab_tableau() + } + + #[pyo3(signature = (verbose=None, _print_y=None, print_destabs=None))] + fn print_stabs( + &self, + verbose: Option, + _print_y: Option, + print_destabs: Option, + ) -> Vec { + let verbose = verbose.unwrap_or(true); + // let print_y = print_y.unwrap_or(true); + let print_destabs = print_destabs.unwrap_or(false); + + let stabs = self.inner.stab_tableau(); + let stab_lines: Vec = stabs.lines().map(String::from).collect(); + + if print_destabs { + let destabs = self.inner.destab_tableau(); + let destab_lines: Vec = destabs.lines().map(String::from).collect(); + + if verbose { + println!("Stabilizers:"); + for line in &stab_lines { + println!("{line}"); + } + println!("Destabilizers:"); + for line in &destab_lines { + println!("{line}"); + } + } + + [stab_lines, destab_lines].concat() + } else { + if verbose { + println!("Stabilizers:"); + for line in &stab_lines { + println!("{line}"); + } + } + + stab_lines + } + } +} diff --git a/crates/pecos-qec/Cargo.toml b/crates/pecos-qec/Cargo.toml new file mode 100644 index 00000000..4d299170 --- /dev/null +++ b/crates/pecos-qec/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "pecos-qec" +version.workspace = true +edition.workspace = true +authors.workspace = true +homepage.workspace = true +repository.workspace = true +license.workspace = true +keywords.workspace = true +categories.workspace = true +description = "QEC for Rust PECOS." + +[dependencies] +pecos-qsims = { path= "../pecos-qsims" } + +[lints] +workspace = true diff --git a/crates/pecos-qec/LICENSE b/crates/pecos-qec/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/crates/pecos-qec/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/crates/pecos-qec/README.md b/crates/pecos-qec/README.md new file mode 100644 index 00000000..502061e8 --- /dev/null +++ b/crates/pecos-qec/README.md @@ -0,0 +1,3 @@ +# pecos-qec + +`pecos-qec` provides all QEC functionality of the Rust version of PECOS. diff --git a/crates/pecos-qec/src/lib.rs b/crates/pecos-qec/src/lib.rs new file mode 100644 index 00000000..4ca75661 --- /dev/null +++ b/crates/pecos-qec/src/lib.rs @@ -0,0 +1,13 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +// pecos-qec stub. Left intentionally blank for now. diff --git a/crates/pecos-qsims/Cargo.toml b/crates/pecos-qsims/Cargo.toml new file mode 100644 index 00000000..15bc0443 --- /dev/null +++ b/crates/pecos-qsims/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "pecos-qsims" +version.workspace = true +edition.workspace = true +authors.workspace = true +homepage.workspace = true +repository.workspace = true +license.workspace = true +keywords.workspace = true +categories.workspace = true +description = "Provides simulators and related elements for PECOS simulations." + +[dependencies] +pecos-core = { path= "../pecos-core" } +rand_chacha = { workspace = true } + +[lints] +workspace = true diff --git a/crates/pecos-qsims/LICENSE b/crates/pecos-qsims/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/crates/pecos-qsims/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/crates/pecos-qsims/README.md b/crates/pecos-qsims/README.md new file mode 100644 index 00000000..c00a9515 --- /dev/null +++ b/crates/pecos-qsims/README.md @@ -0,0 +1,3 @@ +# pecos-qsims + +`pecos-qsims` provides quantum simulation functionality of the Rust version of PECOS. diff --git a/crates/pecos-qsims/src/clifford_simulator.rs b/crates/pecos-qsims/src/clifford_simulator.rs new file mode 100644 index 00000000..58425efc --- /dev/null +++ b/crates/pecos-qsims/src/clifford_simulator.rs @@ -0,0 +1,488 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +use super::quantum_simulator::QuantumSimulator; +use pecos_core::IndexableElement; + +/// A simulator that implements Clifford gates. +#[expect(clippy::min_ident_chars)] +pub trait CliffordSimulator: QuantumSimulator { + #[inline] + #[must_use] + fn new(num_qubits: usize) -> Self + where + Self: Sized, + { + ::new(num_qubits) + } + + #[inline] + fn num_qubits(&self) -> usize { + ::num_qubits(self) + } + + #[inline] + fn reset(&mut self) -> &mut Self { + return ::reset(self); + } + + /// Preparation of the +`X_q` operator. + /// # Panics + /// Will panic if qubit ids don't convert to usize. + #[inline] + fn px(&mut self, q: T) -> (bool, bool) { + let (meas, deter) = self.mx(q); + if meas { + self.z(q); + } + + (meas, deter) + } + + /// Preparation of the -`X_q` operator. + /// # Panics + /// Will panic if qubit ids don't convert to usize. + #[inline] + fn pnx(&mut self, q: T) -> (bool, bool) { + let (meas, deter) = self.mnx(q); + if meas { + self.z(q); + } + (meas, deter) + } + + /// Preparation of the +`Y_q` operator. + /// # Panics + /// Will panic if qubit ids don't convert to usize. + #[inline] + fn py(&mut self, q: T) -> (bool, bool) { + let (meas, deter) = self.my(q); + if meas { + self.z(q); + } + // let (meas, deter) = self.pz(q); + // self.h5(q); + (meas, deter) + } + + /// Preparation of the -`Y_q` operator. + /// # Panics + /// Will panic if qubit ids don't convert to usize. + #[inline] + fn pny(&mut self, q: T) -> (bool, bool) { + let (meas, deter) = self.mny(q); + if meas { + self.z(q); + } + // let (meas, deter) = self.pz(q); + // self.h6(q); + (meas, deter) + } + + /// Preparation of the +`Z_q` operator. + /// # Panics + /// Will panic if qubit ids don't convert to usize. + #[inline] + fn pz(&mut self, q: T) -> (bool, bool) { + let (meas, deter) = self.mz(q); + if meas { + self.x(q); + } + (meas, deter) + } + + /// Preparation of the -`Z_q` operator. + /// # Panics + /// Will panic if qubit ids don't convert to usize. + #[inline] + fn pnz(&mut self, q: T) -> (bool, bool) { + let (meas, deter) = self.mnz(q); + if meas { + self.x(q); + } + (meas, deter) + } + + /// Measurement of the +`X_q` operator. + #[inline] + fn mx(&mut self, q: T) -> (bool, bool) { + // +X -> +Z + self.h(q); + let (meas, deter) = self.mz(q); + // +Z -> +X + self.h(q); + + (meas, deter) + } + + /// Measurement of the -`X_q` operator. + #[inline] + fn mnx(&mut self, q: T) -> (bool, bool) { + // -X -> +Z + self.h(q); + self.x(q); + let (meas, deter) = self.mz(q); + // +Z -> -X + self.x(q); + self.h(q); + + (meas, deter) + } + + /// Measurement of the +`Y_q` operator. + /// # Panics + /// Will panic if qubit ids don't convert to usize. + #[inline] + fn my(&mut self, q: T) -> (bool, bool) { + // +Y -> +Z + self.sx(q); + // self.h5(q); + let (meas, deter) = self.mz(q); + // +Z -> +Y + self.sxdg(q); + // self.h5(q); + + (meas, deter) + } + + /// Measurement of the -`Y_q` operator. + /// # Panics + /// Will panic if qubit ids don't convert to usize. + #[inline] + fn mny(&mut self, q: T) -> (bool, bool) { + // -Y -> +Z + self.sxdg(q); + // self.h6(q); + let (meas, deter) = self.mz(q); + // +Z -> -Y + self.sx(q); + // self.h6(q); + + (meas, deter) + } + + /// Measurement of the +`Z_q` operator. + fn mz(&mut self, q: T) -> (bool, bool); + + /// Measurement of the -`Z_q` operator. + /// # Panics + /// Will panic if qubit ids don't convert to usize. + #[inline] + fn mnz(&mut self, q: T) -> (bool, bool) { + // -Z -> +Z + self.x(q); + let (meas, deter) = self.mz(q); + // +Z -> -Z + self.x(q); + + (meas, deter) + } + + /// Identity on qubit q. X -> X, Z -> Z + #[inline] + fn identity(&mut self, _q: T) {} + + /// Pauli X gate. X -> X, Z -> -Z + fn x(&mut self, q: T); + + /// Pauli Y gate. X -> -X, Z -> -Z + fn y(&mut self, q: T); + + /// Pauli Z gate. X -> -X, Z -> Z + fn z(&mut self, q: T); + + /// Sqrt of X gate. + /// X -> X + /// Z -> -iW = -Y + /// W -> -iZ + /// Y -> Z + #[inline] + fn sx(&mut self, q: T) { + // X -H-> Z -SZ-> Z -H-> X + // Z -H-> X -SZ-> Y -H-> -Y + // Y -H-> -Y -SZ-> X -H-> Z + self.h(q); + self.sz(q); + self.h(q); + } + + /// Adjoint of Sqrt X gate. + /// X -> X + /// Z -> iW = Y + /// W -> iZ + /// Y -> -Z + #[inline] + fn sxdg(&mut self, q: T) { + // X -H-> Z -Z-> Z -SZ-> Z -H-> X + // Z -H-> X -Z-> -X -SZ-> -Y -H-> Y + // Y -H-> -Y -Z-> Y -SZ-> -X -H-> -Z + self.h(q); + self.szdg(q); + self.h(q); + } + + /// Sqrt of Y gate. + /// X -> -Z + /// Z -> X + /// W -> W + /// Y -> Y + /// # Panics + /// Will panic if qubit ids don't convert to usize. + #[inline] + fn sy(&mut self, q: T) { + self.h(q); + self.x(q); + } + + /// Adjoint of sqrt of Y gate. + /// X -> Z + /// Z -> -X + /// W -> W + /// Y -> Y + /// # Panics + /// Will panic if qubit ids don't convert to usize. + #[inline] + fn sydg(&mut self, q: T) { + self.x(q); + self.h(q); + } + + /// Sqrt of Z gate. +X -> +Y; +Z -> +Z; +Y -> -X; + fn sz(&mut self, q: T); + + /// Adjoint of Sqrt of Z gate. X -> ..., Z -> ... + /// X -> -iW = -Y + /// Z -> Z + /// W -> -iX + /// Y -> X + #[inline] + fn szdg(&mut self, q: T) { + // X -Z-> -X -SZ-> -Y + // Z -Z-> Z -SZ-> Z + // Y -Z-> -Y -SZ-> X + self.z(q); + self.sz(q); + } + + /// Hadamard gate. X -> Z, Z -> X + fn h(&mut self, q: T); + + /// X -> -Z, Z -> -X, Y -> -Y + #[inline] + fn h2(&mut self, q: T) { + self.sy(q); + self.z(q); + } + + /// X -> Y, Z -> -Z, Y -> X + #[inline] + fn h3(&mut self, q: T) { + self.sz(q); + self.y(q); + } + + /// X -> -Y, Z -> -Z, Y -> -X + #[inline] + fn h4(&mut self, q: T) { + self.sz(q); + self.x(q); + } + + /// X -> -X, Z -> Y, Y -> Z + #[inline] + fn h5(&mut self, q: T) { + self.sx(q); + self.z(q); + } + + /// X -> -X, Z -> -Y, Y -> -Z + #[inline] + fn h6(&mut self, q: T) { + self.sx(q); + self.y(q); + } + + /// X -> Y, Z -> X, Y -> Z + #[inline] + fn f(&mut self, q: T) { + self.sx(q); + self.sz(q); + } + + /// X -> Z, Z -> Y, Y -> X + #[inline] + fn fdg(&mut self, q: T) { + self.szdg(q); + self.sxdg(q); + } + + /// X -> -Z, Z -> Y, Y -> -X + #[inline] + fn f2(&mut self, q: T) { + self.sxdg(q); + self.sy(q); + } + + /// X -> -Y, Z -> -X, Y -> Z + #[inline] + fn f2dg(&mut self, q: T) { + self.sydg(q); + self.sx(q); + } + + /// X -> Y, Z -> -X, Y -> -Z + #[inline] + fn f3(&mut self, q: T) { + self.sxdg(q); + self.sz(q); + } + + /// X -> -Z, Z -> -Y, Y -> X + #[inline] + fn f3dg(&mut self, q: T) { + self.szdg(q); + self.sx(q); + } + + /// X -> Z, Z -> -Y, Y -> -X + #[inline] + fn f4(&mut self, q: T) { + self.sz(q); + self.sx(q); + } + + /// X -> -Y, Z -> X, Y -> -Z + #[inline] + fn f4dg(&mut self, q: T) { + self.sxdg(q); + self.szdg(q); + } + + /// Controlled-not gate. IX -> IX, IZ -> ZZ, XI -> XX, ZI -> ZZ + fn cx(&mut self, q1: T, q2: T); + + /// CY: +IX -> +ZX; +IZ -> +ZZ; +XI -> -XY; +ZI -> +ZI; + #[inline] + fn cy(&mut self, q1: T, q2: T) { + self.sz(q2); + self.cx(q1, q2); + self.szdg(q2); + } + + /// CZ: +IX -> +ZX; +IZ -> +IZ; +XI -> +XZ; +ZI -> +ZI; + #[inline] + fn cz(&mut self, q1: T, q2: T) { + self.h(q2); + self.cx(q1, q2); + self.h(q2); + } + + /// SXX: XI -> XI + /// IX -> IX + /// ZI -> -YX + /// IZ -> -XY + #[inline] + fn sxx(&mut self, q1: T, q2: T) { + self.sx(q1); + self.sx(q2); + self.sydg(q1); + self.cx(q1, q2); + self.sy(q1); + } + + /// `SXXdg`: XI -> XI + /// IX -> IX + /// ZI -> YX + /// IZ -> XY + #[inline] + fn sxxdg(&mut self, q1: T, q2: T) { + self.x(q1); + self.x(q2); + self.sxx(q1, q2); + } + + /// SYY: XI -> -ZY + /// IX -> -YZ + /// ZI -> XY + /// IZ -> YX + #[inline] + fn syy(&mut self, q1: T, q2: T) { + self.szdg(q1); + self.szdg(q2); + self.sxx(q1, q2); + self.sz(q1); + self.sz(q2); + } + + /// `SYYdg`: XI -> ZY + /// IX -> YZ + /// ZI -> -XY + /// IZ -> -YX + #[inline] + fn syydg(&mut self, q1: T, q2: T) { + self.y(q1); + self.y(q2); + self.syy(q1, q2); + } + + /// SZZ: +IX -> +ZY; + /// +IZ -> +IZ; + /// +XI -> +YZ; + /// +ZI -> +ZI; + #[inline] + fn szz(&mut self, q1: T, q2: T) { + self.sydg(q1); + self.sydg(q2); + self.sxx(q1, q2); + self.sy(q1); + self.sy(q2); + } + + /// `SZZdg`: +IX -> -ZY; + /// +IZ -> +IZ; + /// +XI -> -ZY; + /// +ZI -> +ZI; + #[inline] + fn szzdg(&mut self, q1: T, q2: T) { + self.z(q1); + self.z(q2); + self.szz(q1, q2); + // self.sy(q1); + // self.sy(q2); + // self.sxxdg(q1, q2); + // self.sydg(q1); + // self.sydg(q2); + } + + /// SWAP: +IX -> XI; + /// +IZ -> ZI; + /// +XI -> IX; + /// +ZI -> IZ; + #[inline] + fn swap(&mut self, q1: T, q2: T) { + self.cx(q1, q2); + self.cx(q2, q1); + self.cx(q1, q2); + } + + /// G2: +XI -> +IX + /// +IX -> +XI + /// +ZI -> +XZ + /// +IZ -> +ZX + #[inline] + fn g2(&mut self, q1: T, q2: T) { + self.cz(q1, q2); + self.h(q1); + self.h(q2); + self.cz(q1, q2); + } +} diff --git a/crates/pecos-qsims/src/gens.rs b/crates/pecos-qsims/src/gens.rs new file mode 100644 index 00000000..377f3652 --- /dev/null +++ b/crates/pecos-qsims/src/gens.rs @@ -0,0 +1,104 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +use core::fmt::Debug; +use core::marker::PhantomData; +use pecos_core::{IndexableElement, Set}; + +#[derive(Clone, Debug)] +pub struct Gens +where + T: for<'a> Set<'a, Element = E>, + E: IndexableElement, +{ + num_qubits: usize, + pub col_x: Vec, + pub col_z: Vec, + pub row_x: Vec, + pub row_z: Vec, + pub sign: T, + pub signs_minus: T, + pub signs_i: T, + _marker: PhantomData, +} + +impl Gens +where + T: for<'a> Set<'a, Element = E>, + E: IndexableElement, +{ + #[must_use] + #[inline] + pub fn new(num_qubits: usize) -> Gens { + Self { + num_qubits, + col_x: vec![T::new(); num_qubits], + col_z: vec![T::new(); num_qubits], + row_x: vec![T::new(); num_qubits], + row_z: vec![T::new(); num_qubits], + sign: T::new(), + signs_minus: T::new(), + signs_i: T::new(), + _marker: PhantomData, + } + } + + pub fn get_num_qubits(&self) -> usize { + self.num_qubits + } + + #[inline] + pub fn clear(&mut self) { + self.col_x.clear(); + self.col_z.clear(); + self.row_x.clear(); + self.row_z.clear(); + self.sign.clear(); + self.signs_minus.clear(); + self.signs_i.clear(); + } + + #[inline] + pub fn init_all_z(&mut self) { + self.clear(); + // TODO: Change these to not create a new Vec... instead populate them... + self.col_x = vec![T::new(); self.get_num_qubits()]; + self.col_z = new_index_set::(self.get_num_qubits()); + self.row_x = vec![T::new(); self.get_num_qubits()]; + self.row_z = new_index_set::(self.get_num_qubits()); + } + + #[inline] + pub fn init_all_x(&mut self) { + // TODO: Change these to not create a new Vec... instead populate them... + self.clear(); + self.col_x = new_index_set::(self.get_num_qubits()); + self.col_z = vec![T::new(); self.get_num_qubits()]; + self.row_x = new_index_set::(self.get_num_qubits()); + self.row_z = vec![T::new(); self.get_num_qubits()]; + } +} + +#[inline] +fn new_index_set(num_qubits: usize) -> Vec +where + T: for<'a> Set<'a, Element = E>, + E: IndexableElement, +{ + let mut sets = Vec::with_capacity(num_qubits); + for i in 0..num_qubits { + let mut set = T::new(); + set.insert(E::from_usize(i)); + sets.push(set); + } + sets +} diff --git a/crates/pecos-qsims/src/lib.rs b/crates/pecos-qsims/src/lib.rs new file mode 100644 index 00000000..6f06c952 --- /dev/null +++ b/crates/pecos-qsims/src/lib.rs @@ -0,0 +1,29 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +pub mod clifford_simulator; +pub mod gens; +// pub mod measurement; +// pub mod nonclifford_simulator; +// pub mod pauli_prop; +// pub mod paulis; +pub mod quantum_simulator; +pub mod sparse_stab; + +pub use clifford_simulator::CliffordSimulator; +pub use gens::Gens; +// pub use measurement::{MeasBitValue, MeasValue, Measurement}; // TODO: Distinguish between trait and struct/enum +// pub use nonclifford_simulator::NonCliffordSimulator; +// pub use pauli_prop::{PauliProp, StdPauliProp}; +// pub use paulis::Paulis; +pub use quantum_simulator::QuantumSimulator; +pub use sparse_stab::SparseStab; diff --git a/crates/pecos-qsims/src/quantum_simulator.rs b/crates/pecos-qsims/src/quantum_simulator.rs new file mode 100644 index 00000000..06dc27fa --- /dev/null +++ b/crates/pecos-qsims/src/quantum_simulator.rs @@ -0,0 +1,19 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +pub trait QuantumSimulator { + fn new(num_qubits: usize) -> Self; + + fn num_qubits(&self) -> usize; + + fn reset(&mut self) -> &mut Self; +} diff --git a/crates/pecos-qsims/src/sparse_stab.rs b/crates/pecos-qsims/src/sparse_stab.rs new file mode 100644 index 00000000..9a42e2ca --- /dev/null +++ b/crates/pecos-qsims/src/sparse_stab.rs @@ -0,0 +1,2226 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +use crate::{CliffordSimulator, Gens, QuantumSimulator}; +use core::fmt::Debug; +use core::mem; +use pecos_core::SimRng; +use pecos_core::{IndexableElement, Set}; +use rand_chacha::ChaCha8Rng; +// TODO: Look into seeing if a dense bool for signs_minus and signs_i is more efficient + +#[derive(Clone, Debug)] +pub struct SparseStab +where + T: for<'a> Set<'a, Element = E>, + E: IndexableElement, + R: SimRng, +{ + num_qubits: usize, + stabs: Gens, + destabs: Gens, + rng: R, +} +impl SparseStab +where + E: IndexableElement, + R: SimRng, + T: for<'a> Set<'a, Element = E>, +{ + #[inline] + #[must_use] + fn new(num_qubits: usize) -> Self { + let rng = SimRng::from_entropy(); + Self::with_rng(num_qubits, rng) + } + + #[inline] + pub fn with_rng(num_qubits: usize, rng: R) -> Self { + let mut stab = Self { + num_qubits, + stabs: Gens::::new(num_qubits), + destabs: Gens::::new(num_qubits), + rng, + }; + stab.reset(); + stab + } + + #[expect(clippy::single_call_fn)] + #[inline] + fn reset(&mut self) -> &mut Self { + self.stabs.init_all_z(); + self.destabs.init_all_x(); + self + } + + #[inline] + pub fn verify_matrix(&self) { + Self::check_row_eq_col(&self.stabs); + Self::check_row_eq_col(&self.destabs); + + // TODO: Check that stabilizers commute. + // TODO: Check destabilizers commute. + // TODO: Check that only stab[i] anti-commutes with destab[j] only iff i == j; + todo!() + } + + #[inline] + fn check_row_eq_col(gens: &Gens) { + // TODO: Verify that this is doing what is intended... + for (i, row) in gens.row_x.iter().enumerate() { + for j in row.iter() { + assert!( + gens.col_x[j.to_usize()].contains(&E::from_usize(i)), + "Column-wise sparse matrix doesn't match row-wise spare matrix" + ); + } + } + } + + /// Utility that creates a string for the Pauli generates of a `Gens`. + fn tableau_string(num_qubits: usize, gens: &Gens) -> String { + // TODO: calculate signs so we are really doing Y and not W + let mut result = + String::with_capacity(num_qubits * gens.row_x.len() + gens.row_x.len() + 2); + for i in 0..gens.row_x.len() { + if gens.signs_minus.contains(&(E::from_usize(i))) { + result.push('-'); + } else { + result.push('+'); + } + if gens.signs_i.contains(&(E::from_usize(i))) { + result.push('i'); + } + + for qubit in 0..num_qubits { + let qubit_u = E::from_usize(qubit); + let in_row_x = gens.row_x[i].contains(&qubit_u); + let in_row_z = gens.row_z[i].contains(&qubit_u); + + let char = match (in_row_x, in_row_z) { + (false, false) => 'I', + (true, false) => 'X', + (false, true) => 'Z', + (true, true) => 'Y', + }; + result.push(char); + } + result.push('\n'); + } + + result + } + + /// Produces a textual representation of the stabilizer in tableau form. + #[inline] + pub fn stab_tableau(&self) -> String { + Self::tableau_string(self.num_qubits, &self.stabs) + } + + /// Produces a textual representation of the destabilizer in tableau form. + #[inline] + pub fn destab_tableau(&self) -> String { + Self::tableau_string(self.num_qubits, &self.destabs) + } + + /// Negate the sign of a stabilizer generator. + #[inline] + pub fn neg(&mut self, s: E) { + self.stabs.signs_minus ^= &s; + } + + #[inline] + pub fn signs_minus(&self) -> &T { + &self.stabs.signs_minus + } + + /// # Panics + /// Will panic if qubit ids don't convert to usize. + #[inline] + fn deterministic_meas(&mut self, q: E) -> bool { + let qu = q.to_usize(); + + let mut num_minuses = self.destabs.col_x[qu] + .intersection(&self.stabs.signs_minus) + .count(); + + let num_is = &self.destabs.col_x[qu] + .intersection(&self.stabs.signs_i) + .count(); + + let mut cumulative_x = T::new(); + for row in self.destabs.col_x[qu].iter() { + let rowu = row.to_usize(); + num_minuses += &self.stabs.row_z[rowu].intersection(&cumulative_x).count(); + cumulative_x ^= &self.stabs.row_x[rowu]; + } + if num_is & 3 != 0 { + // num_is % 4 != 0 + num_minuses += 1; + } + num_minuses & 1 != 0 // num_minuses % 2 != 0 (is odd) + } + + /// # Panics + /// Will panic if qubit ids don't convert to usize. + #[inline] + fn nondeterministic_meas(&mut self, q: E) -> E { + let qu = q.to_usize(); + + let mut anticom_stabs_col = self.stabs.col_x[qu].clone(); + let mut anticom_destabs_col = self.destabs.col_x[qu].clone(); + + let mut smallest_wt = 2 * self.num_qubits + 2; + let mut removed_id: Option = None; + + for stab_id in anticom_stabs_col.iter() { + let stab_usize = stab_id.to_usize(); + let weight = self.stabs.row_x[stab_usize].len() + self.stabs.row_z[stab_usize].len(); + + if weight < smallest_wt { + smallest_wt = weight; + removed_id = Some(*stab_id); + // break // TODO: Should it exit early? // If we do... it avoids smallest weight + // TODO: Does the smallest weight matter? Maybe at least break if smallest weight == 1 + // TODO: Does it always exist? If so, can we avoid Some()? + } + } + + let id = removed_id.expect("Critical error: removed_id was None"); + + anticom_stabs_col.remove(&id); + let id_usize = id.to_usize(); // Convert `id` to `usize` + let removed_row_x = self.stabs.row_x[id_usize].clone(); + let removed_row_z = self.stabs.row_z[id_usize].clone(); + + if self.stabs.signs_minus.contains(&id) { + self.stabs.signs_minus ^= &anticom_stabs_col; + } + + if self.stabs.signs_i.contains(&id) { + self.stabs.signs_i.remove(&id); + + let gens_common = self + .stabs + .signs_i + .intersection(&anticom_stabs_col) + .copied() + .collect::>(); + let gens_only_stabs = anticom_stabs_col + .difference(&self.stabs.signs_i) + .copied() + .collect::>(); + + for i in gens_common { + self.stabs.signs_minus ^= &i; + self.stabs.signs_i.remove(&i); + } + + for i in gens_only_stabs { + self.stabs.signs_i.insert(i); + } + } + + for gen in anticom_stabs_col.iter() { + let gen_usize = gen.to_usize(); // Convert `gen` to `usize` + let num_minuses = removed_row_z + .intersection(&self.stabs.row_x[gen_usize]) + .count(); + + if num_minuses & 1 != 0 { + // num_minuses % 2 != 0 (is odd) + self.stabs.signs_minus ^= gen; + } + + self.stabs.row_x[gen_usize] ^= &removed_row_x; + self.stabs.row_z[gen_usize] ^= &removed_row_z; + // Use `num_minuses` as needed + } + + for i in removed_row_x.iter() { + let iu = i.to_usize(); + self.stabs.col_x[iu] ^= &anticom_stabs_col; + } + + for i in removed_row_z.iter() { + let iu = i.to_usize(); + self.stabs.col_z[iu] ^= &anticom_stabs_col; + } + + for i in self.stabs.row_x[id_usize].iter() { + let iu = i.to_usize(); + self.stabs.col_x[iu].remove(&id); + } + + for i in self.stabs.row_z[id_usize].iter() { + let iu = i.to_usize(); + self.stabs.col_z[iu].remove(&id); + } + + // Remove replaced stabilizer with the measured stabilizer + self.stabs.col_z[qu].insert(id); + + // Row update + self.stabs.row_x[id_usize].clear(); + self.stabs.row_z[id_usize].clear(); + self.stabs.row_z[id_usize].insert(q); + + for i in self.destabs.row_x[id_usize].iter() { + let iu = i.to_usize(); + self.destabs.col_x[iu].remove(&id); + } + + for i in self.destabs.row_z[id_usize].iter() { + let iu = i.to_usize(); + self.destabs.col_z[iu].remove(&id); + } + + anticom_destabs_col.remove(&id); + + for i in removed_row_x.iter() { + let iu = i.to_usize(); + self.destabs.col_x[iu].insert(id); + self.destabs.col_x[iu] ^= &anticom_destabs_col; + } + + for i in removed_row_z.iter() { + let iu = i.to_usize(); + self.destabs.col_z[iu].insert(id); + self.destabs.col_z[iu] ^= &anticom_destabs_col; + } + + for row in anticom_destabs_col.iter() { + let ru = row.to_usize(); + self.destabs.row_x[ru] ^= &removed_row_x; + self.destabs.row_z[ru] ^= &removed_row_z; + } + + self.destabs.row_x[id_usize] = removed_row_x; + self.destabs.row_z[id_usize] = removed_row_z; + + id + } + + /// Measurement of the +`Z_q` operator where random outcomes are forced to a particular value. + /// # Panics + /// Will panic if qubit ids don't convert to usize. + #[inline] + pub fn mz_forced(&mut self, q: E, forced_outcome: bool) -> (bool, bool) { + let qu = q.to_usize(); + + let deterministic = self.stabs.col_x[qu].is_empty(); + + // There are no stabilizers that anti-commute with Z_q + let meas_out = if deterministic { + self.deterministic_meas(q) + } else { + let id = self.nondeterministic_meas(q); + + self.apply_outcome(id, forced_outcome) + }; + (meas_out, deterministic) + } + + /// Preparation of the +`Z_q` operator where random outcomes are forced to a particular value. + /// # Panics + /// Will panic if qubit ids don't convert to usize. + #[inline] + pub fn pz_forced(&mut self, q: E, forced_outcome: bool) -> (bool, bool) { + let (meas, deter) = self.mz_forced(q, forced_outcome); + if meas { + self.x(q); + } + (meas, deter) + } + + /// Apply measurement outcome + #[inline] + fn apply_outcome(&mut self, id: E, meas_outcome: bool) -> bool { + if meas_outcome { + self.stabs.signs_minus.insert(id); + } else { + self.stabs.signs_minus.remove(&id); + } + meas_outcome + } +} + +impl QuantumSimulator for SparseStab +where + E: IndexableElement, + R: SimRng, + T: for<'a> Set<'a, Element = E>, +{ + #[inline] + #[must_use] + fn new(num_qubits: usize) -> Self { + Self::new(num_qubits) + } + + #[inline] + fn num_qubits(&self) -> usize { + self.num_qubits + } + + #[inline] + fn reset(&mut self) -> &mut Self { + return Self::reset(self); + } +} + +impl CliffordSimulator for SparseStab +where + T: for<'a> Set<'a, Element = E>, + E: IndexableElement, + R: SimRng, +{ + // TODO: pub fun p(&mut self, pauli: &pauli, q: U) { todo!() } + // TODO: pub fun m(&mut self, pauli: &pauli, q: U) -> bool { todo!() } + + /// Measurement of the +`Z_q` operator. + /// # Panics + /// Will panic if qubit ids don't convert to usize. + #[inline] + fn mz(&mut self, q: E) -> (bool, bool) { + let qu = q.to_usize(); + + let deterministic = self.stabs.col_x[qu].is_empty(); + + // There are no stabilizers that anti-commute with Z_q + let meas_out = if deterministic { + self.deterministic_meas(q) + } else { + let id = self.nondeterministic_meas(q); + + let meas_outcome = self.rng.gen_bool(0.5); + + self.apply_outcome(id, meas_outcome) + }; + (meas_out, deterministic) + } + + /// Pauli X gate. X -> X, Z -> -Z + /// # Panics + /// Will panic if qubit ids don't convert to usize. + #[inline] + fn x(&mut self, q: E) { + let qu = q.to_usize(); + self.stabs.signs_minus ^= &self.stabs.col_z[qu]; + } + + /// Pauli Y gate. X -> -X, Z -> -Z + /// # Panics + /// Will panic if qubit ids don't convert to usize. + #[inline] + fn y(&mut self, q: E) { + // TODO: Add test + let qu = q.to_usize(); + // stabs.signs_minus ^= stabs.col_x[qubit] ^ stabs.col_z[qubit] + for i in self.stabs.col_x[qu].symmetric_difference(&self.stabs.col_z[qu]) { + self.stabs.signs_minus ^= i; + } + } + + /// Pauli Z gate. X -> -X, Z -> Z + /// # Panics + /// Will panic if qubit ids don't convert to usize. + #[inline] + fn z(&mut self, q: E) { + // TODO: Add test + self.stabs.signs_minus ^= &self.stabs.col_x[q.to_usize()]; + } + + /// Sqrt of Z gate. + /// X -> iW = Y + /// Z -> Z + /// W -> iX + /// Y -> -X + /// # Panics + /// Will panic if qubit ids don't convert to usize. + #[inline] + fn sz(&mut self, q: E) { + let qu = q.to_usize(); + + // X -> i + // --------------------- + // i * i = -1 + // stabs.signs_minus ^= stabs.signs_i & stabs.col_x[qubit] + // For each X add an i unless there is already an i there then delete it. + // stabs.signs_i ^= stabs.col_x[qubit] + for i in self.stabs.signs_i.intersection(&self.stabs.col_x[qu]) { + self.stabs.signs_minus ^= i; + } + self.stabs.signs_i ^= &self.stabs.col_x[qu]; + + for g in [&mut self.stabs, &mut self.destabs] { + g.col_z[qu] ^= &g.col_x[qu]; + + for &i in g.col_x[qu].iter() { + let iu = i.to_usize(); + g.row_z[iu] ^= &q; + } + } + } + + /// Hadamard gate. X -> Z, Z -> X + /// # Panics + /// Will panic if qubit ids don't convert to usize. + #[inline] + fn h(&mut self, q: E) { + let qu = q.to_usize(); + + // self.stabs.signs_minus.symmetric_difference_update(self.stabs.col_x[qu].intersection()) + // self.stabs.signs_minus ^= &self.stabs.col_x[qu] & &self.stabs.col_z[qu]; + for i in self.stabs.col_x[qu].intersection(&self.stabs.col_z[qu]) { + self.stabs.signs_minus ^= i; + } + + for g in [&mut self.stabs, &mut self.destabs] { + for i in g.col_x[qu].difference(&g.col_z[qu]) { + let iu = i.to_usize(); + g.row_x[iu].remove(&q); + g.row_z[iu].insert(q); + } + + for i in g.col_z[qu].difference(&g.col_x[qu]) { + let iu = i.to_usize(); + g.row_z[iu].remove(&q); + g.row_x[iu].insert(q); + } + + mem::swap(&mut g.col_x[qu], &mut g.col_z[qu]); + } + } + + /// CX: +IX -> +IX; +IZ -> +ZZ; +XI -> +XX; +ZI -> +ZI + /// # Panics + /// Will panic if qubit ids don't convert to usize. + #[inline] + fn cx(&mut self, q1: E, q2: E) { + let qu1 = q1.to_usize(); + let qu2 = q2.to_usize(); + + for g in &mut [&mut self.stabs, &mut self.destabs] { + let (qu_min, qu_max) = if qu1 < qu2 { (qu1, qu2) } else { (qu2, qu1) }; + + // Handle col_x + { + let (_left, right) = g.col_x.split_at_mut(qu_min); + let (mid, right) = right.split_at_mut(qu_max - qu_min); + let col_x_min = &mut mid[0]; + let col_x_max = &mut right[0]; + + let (col_x_qu1, col_x_qu2) = if qu1 < qu2 { + (col_x_min, col_x_max) + } else { + (col_x_max, col_x_min) + }; + + let mut q2_set = T::new(); + q2_set.insert(q2); + + for i in col_x_qu1.iter() { + let iu = i.to_usize(); + g.row_x[iu].symmetric_difference_update(&q2_set); + } + col_x_qu2.symmetric_difference_update(col_x_qu1); + } + + // Handle col_z + { + let (_left, right) = g.col_z.split_at_mut(qu_min); + let (mid, right) = right.split_at_mut(qu_max - qu_min); + let col_z_min = &mut mid[0]; + let col_z_max = &mut right[0]; + + let (col_z_qu1, col_z_qu2) = if qu1 < qu2 { + (col_z_min, col_z_max) + } else { + (col_z_max, col_z_min) + }; + + let mut q1_set = T::new(); + q1_set.insert(q1); + + for i in col_z_qu2.iter() { + let iu = i.to_usize(); + g.row_z[iu].symmetric_difference_update(&q1_set); + } + col_z_qu1.symmetric_difference_update(col_z_qu2); + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use pecos_core::VecSet; + + #[allow(clippy::cast_possible_truncation)] + fn check_matrix(m: &[&str], gens: &Gens, u32>) { + for (r, v) in m.iter().enumerate() { + let ru32 = &(r as u32); + + let (_, phase, v) = split_pauli(v); + + // TODO: Allow +Y in place of +iW + // TODO: Return bools instead of doing the asserts here... + + match phase { + "+" => { + assert!(!gens.signs_minus.contains(ru32)); + assert!(!gens.signs_i.contains(ru32)); + } + "-" => { + assert!(gens.signs_minus.contains(ru32)); + assert!(!gens.signs_i.contains(ru32)); + } + "+i" => { + assert!(!gens.signs_minus.contains(ru32)); + assert!(gens.signs_i.contains(ru32)); + } + "-i" => { + assert!(gens.signs_minus.contains(ru32)); + assert!(gens.signs_i.contains(ru32)); + } + _ => unreachable!(), + } + + for (c, val) in v.chars().enumerate() { + let cu32 = &(c as u32); + match val { + 'I' => { + assert!(!gens.col_x[c].contains(ru32)); + assert!(!gens.col_z[c].contains(ru32)); + assert!(!gens.row_x[r].contains(cu32)); + assert!(!gens.row_z[r].contains(cu32)); + } + 'X' => { + assert!(gens.col_x[c].contains(ru32)); + assert!(!gens.col_z[c].contains(ru32)); + assert!(gens.row_x[r].contains(cu32)); + assert!(!gens.row_z[r].contains(cu32)); + } + 'Z' => { + assert!(!gens.col_x[c].contains(ru32)); + assert!(gens.col_z[c].contains(ru32)); + assert!(!gens.row_x[r].contains(cu32)); + assert!(gens.row_z[r].contains(cu32)); + } + 'W' => { + assert!(gens.col_x[c].contains(ru32)); + assert!(gens.col_z[c].contains(ru32)); + assert!(gens.row_x[r].contains(cu32)); + assert!(gens.row_z[r].contains(cu32)); + } + _ => unreachable!(), + } + } + } + } + + fn check_state(state: &SparseStab, u32>, stabs: &[&str], destabs: &[&str]) { + check_matrix(stabs, &state.stabs); + check_matrix(destabs, &state.destabs); + // SparseStab::verify_matrix(&state); + // TODO: Add matrix verification func + } + + fn split_pauli(pauli_str: &str) -> (usize, &str, &str) { + let (phase, pauli_str) = if pauli_str.contains("+i") || pauli_str.contains("-i") { + pauli_str.split_at(2) + } else if pauli_str.contains('+') || pauli_str.contains('-') || pauli_str.contains('i') { + pauli_str.split_at(1) + } else { + ("+", pauli_str) + }; + let n = pauli_str.chars().count(); + + let phase = if phase == "i" { "+i" } else { phase }; + + (n, phase, pauli_str) + } + + #[allow(clippy::cast_possible_truncation)] + fn prep_pauli_gens(pauli_vec: &[&str], gens: &mut Gens, u32>) { + // TODO: Think about how to automatically determine the destabilizers you need so you can optionally only provide stabilizers... + + gens.signs_i.clear(); + gens.signs_minus.clear(); + + let (n, _, _) = split_pauli(pauli_vec[0]); + + for u in 0..n { + gens.col_x[u].clear(); + gens.col_z[u].clear(); + gens.row_x[u].clear(); + gens.row_z[u].clear(); + } + + for (ru, pauli_str) in pauli_vec.iter().enumerate() { + let (n_, phase, pauli_str) = split_pauli(pauli_str); + + assert_eq!( + n, n_, + "The number of qubits differs between the first generator and another!" + ); + + match phase { + "+" => {} + "-" => { + gens.signs_minus.insert(ru as u32); + } + "+i" => { + gens.signs_i.insert(ru as u32); + } + "-i" => { + gens.signs_minus.insert(ru as u32); + gens.signs_i.insert(ru as u32); + } + _ => unreachable!(), + } + + for (cu, p) in pauli_str.chars().enumerate() { + match p { + 'I' => {} + 'X' => { + gens.col_x[cu].insert(ru as u32); + gens.row_x[ru].insert(cu as u32); + } + 'W' => { + gens.col_x[cu].insert(ru as u32); + gens.col_z[cu].insert(ru as u32); + gens.row_x[ru].insert(cu as u32); + gens.row_z[ru].insert(cu as u32); + } + 'Z' => { + gens.col_z[cu].insert(ru as u32); + gens.row_z[ru].insert(cu as u32); + } + _ => unreachable!(), + } + } + } + } + + fn prep_state(stabs: &[&str], destabs: &[&str]) -> SparseStab, u32> { + let mut state = SparseStab::, u32>::new(3); + prep_pauli_gens(stabs, &mut state.stabs); + prep_pauli_gens(destabs, &mut state.destabs); + + state + } + + #[test] + fn test_setting_up_stab_state() { + let tab_stab = vec!["XII", "iIWI", "IIZ"]; + let tab_destab = vec!["ZII", "IXI", "IIX"]; + + let state = prep_state(&tab_stab, &tab_destab); + check_state(&state, &tab_stab, &tab_destab); + } + + #[test] + fn test_setting_up_neg_stab_state() { + let tab_stab = vec!["-XII", "-iIWI", "-IIZ"]; + let tab_destab = vec!["ZII", "IXI", "IIX"]; + + let state = prep_state(&tab_stab, &tab_destab); + check_state(&state, &tab_stab, &tab_destab); + } + + #[test] + fn test_nondeterministic_px() { + for _ in 1_u32..=100 { + let mut state = prep_state(&["Z"], &["X"]); + let (_m0, d0) = state.px(0); + let (m1, d1) = state.mx(0); + let m1_int = u8::from(m1); + + assert_eq!(m1_int, 0); // |+X> + assert!(!d0); // Not deterministic + assert!(d1); // Deterministic + } + } + + #[test] + fn test_deterministic_px() { + let mut state = prep_state(&["X"], &["Z"]); + let (m0, d0) = state.px(0); + let m0_int = u8::from(m0); + + assert!(d0); // Deterministic + assert_eq!(m0_int, 0); // |+X> + } + + #[test] + fn test_nondeterministic_pnx() { + for _ in 1_u32..=100 { + let mut state = prep_state(&["Z"], &["X"]); + let (_m0, d0) = state.pnx(0); + let (m1, d1) = state.mx(0); + let m1_int = u8::from(m1); + + assert_eq!(m1_int, 1); // |-X> + assert!(!d0); // Not deterministic + assert!(d1); // Deterministic + } + } + + #[test] + fn test_deterministic_pnx() { + let mut state = prep_state(&["-X"], &["Z"]); + let (m0, d0) = state.pnx(0); + let m0_int = u8::from(m0); + + assert!(d0); // Deterministic + assert_eq!(m0_int, 0); // |-X> + } + + #[test] + fn test_nondeterministic_py() { + for _ in 1_u32..=100 { + let mut state = prep_state(&["Z"], &["X"]); + let (_m0, d0) = state.py(0); + let (m1, d1) = state.my(0); + let m1_int = u8::from(m1); + + assert_eq!(m1_int, 0); // |+Y> + assert!(!d0); // Not deterministic + assert!(d1); // Deterministic + } + } + + #[test] + fn test_deterministic_py() { + let mut state = prep_state(&["iW"], &["Z"]); + let (m0, d0) = state.py(0); + let m0_int = u8::from(m0); + + assert!(d0); // Deterministic + assert_eq!(m0_int, 0); // |+Y> + } + + #[test] + fn test_nondeterministic_pny() { + for _ in 1_u32..=100 { + let mut state = prep_state(&["Z"], &["X"]); + let (_m0, d0) = state.pny(0); + let (m1, d1) = state.my(0); + let m1_int = u8::from(m1); + + assert_eq!(m1_int, 1); // |-Y> + assert!(!d0); // Not deterministic + assert!(d1); // Deterministic + } + } + + #[test] + fn test_deterministic_pny() { + let mut state = prep_state(&["-iW"], &["Z"]); + let (m0, d0) = state.pny(0); + let m0_int = u8::from(m0); + + assert!(d0); // Deterministic + assert_eq!(m0_int, 0); // |-Y> + } + + #[test] + fn test_nondeterministic_pz() { + for _ in 1_u32..=100 { + let mut state = prep_state(&["X"], &["Z"]); + let (_m0, d0) = state.pz(0); + let (m1, d1) = state.mz(0); + let m1_int = u8::from(m1); + + assert_eq!(m1_int, 0); // |0> + assert!(!d0); // Not deterministic + assert!(d1); // Deterministic + } + } + + #[test] + fn test_deterministic_pz() { + let mut state = prep_state(&["Z"], &["X"]); + let (m0, d0) = state.pz(0); + let m0_int = u8::from(m0); + + assert!(d0); // Deterministic + assert_eq!(m0_int, 0); // |+Z> + } + + #[test] + fn test_nondeterministic_pnz() { + for _ in 1_u32..=100 { + let mut state = prep_state(&["X"], &["Z"]); + let (_m0, d0) = state.pnz(0); + let (m1, d1) = state.mz(0); + let m1_int = u8::from(m1); + + assert_eq!(m1_int, 1); // |1> + assert!(!d0); // Not deterministic + assert!(d1); // Deterministic + } + } + + #[test] + fn test_deterministic_pnz() { + let mut state = prep_state(&["-Z"], &["X"]); + let (m0, d0) = state.pnz(0); + let m0_int = u8::from(m0); + + assert!(d0); // Deterministic + assert_eq!(m0_int, 0); // |-Z> + } + + #[test] + fn test_nondeterministic_mx() { + let mut state = prep_state(&["Z"], &["X"]); + let (_meas, determined) = state.mx(0); + assert!(!determined); + } + + #[test] + fn test_deterministic_mx() { + let mut state0 = prep_state(&["X"], &["Z"]); + let (meas0, determined0) = state0.mx(0); + assert!(determined0); + assert!(!meas0); + + let mut state1 = prep_state(&["-X"], &["Z"]); + let (meas1, determined1) = state1.mx(0); + assert!(determined1); + assert!(meas1); + } + + #[test] + fn test_nondeterministic_mnx() { + let mut state = prep_state(&["Z"], &["X"]); + let (_meas, determined) = state.mnx(0); + assert!(!determined); + } + + #[test] + fn test_deterministic_mnx() { + let mut state0 = prep_state(&["-X"], &["Z"]); + let (meas0, determined0) = state0.mnx(0); + assert!(determined0); + assert!(!meas0); + + let mut state1 = prep_state(&["X"], &["Z"]); + let (meas1, determined1) = state1.mnx(0); + assert!(determined1); + assert!(meas1); + } + + #[test] + fn test_nondeterministic_my() { + let mut state = prep_state(&["Z"], &["X"]); + let (_meas, determined) = state.my(0); + assert!(!determined); + } + + #[test] + fn test_deterministic_my() { + let mut state0 = prep_state(&["iW"], &["Z"]); + let (meas0, determined0) = state0.my(0); + assert!(determined0); + assert!(!meas0); + + let mut state1 = prep_state(&["-iW"], &["Z"]); + let (meas1, determined1) = state1.my(0); + assert!(determined1); + assert!(meas1); + } + + #[test] + fn test_nondeterministic_mny() { + let mut state = prep_state(&["Z"], &["X"]); + let (_meas, determined) = state.mny(0); + assert!(!determined); + } + + #[test] + fn test_deterministic_mny() { + let mut state0 = prep_state(&["-iW"], &["Z"]); + let (meas0, determined0) = state0.mny(0); + assert!(determined0); + assert!(!meas0); + + let mut state1 = prep_state(&["iW"], &["Z"]); + let (meas1, determined1) = state1.mny(0); + assert!(determined1); + assert!(meas1); + } + + #[test] + fn test_nondeterministic_mz() { + let mut state = prep_state(&["X"], &["Z"]); + let (_meas, determined) = state.mz(0); + assert!(!determined); + } + + #[test] + fn test_deterministic_mz() { + let mut state0 = prep_state(&["Z"], &["X"]); + let (meas0, determined0) = state0.mz(0); + assert!(determined0); + assert!(!meas0); + + let mut state1 = prep_state(&["-Z"], &["X"]); + let (meas1, determined1) = state1.mz(0); + assert!(determined1); + assert!(meas1); + } + + #[test] + fn test_nondeterministic_mnz() { + let mut state = prep_state(&["X"], &["Z"]); + let (_meas, determined) = state.mnz(0); + assert!(!determined); + } + + #[test] + fn test_deterministic_mnz() { + let mut state0 = prep_state(&["Z"], &["X"]); + let (meas0, determined0) = state0.mnz(0); + assert!(determined0); + assert!(meas0); + + let mut state1 = prep_state(&["-Z"], &["X"]); + let (meas1, determined1) = state1.mnz(0); + assert!(determined1); + assert!(!meas1); + } + + #[test] + fn test_identity() { + // I: +X -> +X; +Z -> +Z; +Y -> +Y; + + // +X -> +X + let mut state = prep_state(&["X"], &["Z"]); + state.identity(0); + check_state(&state, &["X"], &["Z"]); + + // +Y -> -Y + let mut state = prep_state(&["iW"], &["X"]); + state.identity(0); + check_state(&state, &["iW"], &["X"]); + + // +Z -> -Z + let mut state = prep_state(&["Z"], &["X"]); + state.identity(0); + check_state(&state, &["Z"], &["X"]); + + // -IYI -> +IYI + let mut state = prep_state(&["-iIWI"], &["IXI"]); + state.identity(1); + check_state(&state, &["-iIWI"], &["IXI"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_x() { + // X: +X -> +X; +Z -> -Z; +Y -> -Y; + + // +X -> +X + let mut state = prep_state(&["X"], &["Z"]); + state.x(0); + check_state(&state, &["X"], &["Z"]); + + // +Y -> -Y + let mut state = prep_state(&["iW"], &["X"]); + state.x(0); + check_state(&state, &["-iW"], &["X"]); + + // +Z -> -Z + let mut state = prep_state(&["Z"], &["X"]); + state.x(0); + check_state(&state, &["-Z"], &["X"]); + + // -IYI -> +IYI + let mut state = prep_state(&["-iIWI"], &["IXI"]); + state.x(1); + check_state(&state, &["iIWI"], &["IXI"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_y() { + // Y: +X -> -X; +Z -> -Z; +Y -> +Y; + + // +X -> -X + let mut state = prep_state(&["X"], &["Z"]); + state.y(0); + check_state(&state, &["-X"], &["Z"]); + + // +Y -> +Y + let mut state = prep_state(&["iW"], &["X"]); + state.y(0); + check_state(&state, &["iW"], &["X"]); + + // +Z -> -Z + let mut state = prep_state(&["Z"], &["X"]); + state.y(0); + check_state(&state, &["-Z"], &["X"]); + + // -IXI -> +IXI + let mut state = prep_state(&["-IXI"], &["IZI"]); + state.y(1); + check_state(&state, &["IXI"], &["IZI"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_z() { + // Z: +X -> -X; +Z -> +Z; +Y -> -Y; + + // +X -> -X + let mut state = prep_state(&["X"], &["Z"]); + state.z(0); + check_state(&state, &["-X"], &["Z"]); + + // +Y -> -Y + let mut state = prep_state(&["iW"], &["X"]); + state.z(0); + check_state(&state, &["-iW"], &["X"]); + + // +Z -> +Z + let mut state = prep_state(&["Z"], &["X"]); + state.z(0); + check_state(&state, &["Z"], &["X"]); + + // -IXI -> +IXI + let mut state = prep_state(&["-IXI"], &["IZI"]); + state.z(1); + check_state(&state, &["IXI"], &["IZI"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_sx() { + // SX: +X -> +X; +Z -> -Y; +Y -> +Z; + + // +X -> +X + let mut state = prep_state(&["X"], &["Z"]); + state.sx(0); + check_state(&state, &["X"], &["W"]); + + // +Y -> +Z + let mut state = prep_state(&["iW"], &["X"]); + state.sx(0); + check_state(&state, &["Z"], &["X"]); + + // +Z -> -Y + let mut state = prep_state(&["Z"], &["X"]); + state.sx(0); + check_state(&state, &["-iW"], &["X"]); + + // -IYI -> -IZI + let mut state = prep_state(&["-iIWI"], &["IXI"]); + state.sx(1); + check_state(&state, &["-IZI"], &["IXI"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_sxdg() { + // SXdg: +X -> +X; +Z -> +Y; +Y -> -Z; + + // +X -> +X + let mut state = prep_state(&["X"], &["Z"]); + state.sxdg(0); + check_state(&state, &["X"], &["W"]); + + // +Y -> -Z + let mut state = prep_state(&["iW"], &["X"]); + state.sxdg(0); + check_state(&state, &["-Z"], &["X"]); + + // +Z -> +Y + let mut state = prep_state(&["Z"], &["X"]); + state.sxdg(0); + check_state(&state, &["iW"], &["X"]); + + // -IYI -> +IZI + let mut state = prep_state(&["-iIWI"], &["IXI"]); + state.sxdg(1); + check_state(&state, &["IZI"], &["IXI"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_sy() { + // SY: +X -> -Z; +Z -> +X; +Y -> +Y; + + // +X -> -Z + let mut state = prep_state(&["X"], &["Z"]); + state.sy(0); + check_state(&state, &["-Z"], &["X"]); + + // +Y -> +Y + let mut state = prep_state(&["iW"], &["X"]); + state.sy(0); + check_state(&state, &["iW"], &["Z"]); + + // +Z -> +X + let mut state = prep_state(&["Z"], &["X"]); + state.sy(0); + check_state(&state, &["X"], &["Z"]); + + // -IYI -> -IYI + let mut state = prep_state(&["-iIWI"], &["IXI"]); + state.sy(1); + check_state(&state, &["-iIWI"], &["IZI"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_sydg() { + // SYdg: +X -> +Z; +Z -> -X; +Y -> +Y; + + // +X -> +Z + let mut state = prep_state(&["X"], &["Z"]); + state.sydg(0); + check_state(&state, &["Z"], &["X"]); + + // +Y -> +Y + let mut state = prep_state(&["iW"], &["X"]); + state.sydg(0); + check_state(&state, &["iW"], &["Z"]); + + // +Z -> -X + let mut state = prep_state(&["Z"], &["X"]); + state.sydg(0); + check_state(&state, &["-X"], &["Z"]); + + // -IYI -> -IYI + let mut state = prep_state(&["-iIWI"], &["IXI"]); + state.sydg(1); + check_state(&state, &["-iIWI"], &["IZI"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_sz() { + // SZ: +X -> +Y; +Z -> +Z; +Y -> -X; + + // +X -> +Y + let mut state = prep_state(&["X"], &["Z"]); + state.sz(0); + check_state(&state, &["iW"], &["Z"]); + + // +Y -> -X + let mut state = prep_state(&["iW"], &["X"]); + state.sz(0); + check_state(&state, &["-X"], &["W"]); + + // +Z -> +Z + let mut state = prep_state(&["Z"], &["X"]); + state.sz(0); + check_state(&state, &["Z"], &["W"]); + + // -IYI -> +IXI + let mut state = prep_state(&["-iIWI"], &["IXI"]); + state.sz(1); + check_state(&state, &["IXI"], &["IWI"]); + } + + #[test] + fn test_szdg() { + // SZdg: +X -> -Y; +Z -> +Z; +Y -> +X; + + // +X -> -Y + let mut state = prep_state(&["X"], &["Z"]); + state.szdg(0); + check_state(&state, &["-iW"], &["Z"]); + + // +Y -> +X + let mut state = prep_state(&["iW"], &["X"]); + state.szdg(0); + check_state(&state, &["X"], &["W"]); + + // +Z -> +Z + let mut state = prep_state(&["Z"], &["X"]); + state.szdg(0); + check_state(&state, &["Z"], &["W"]); + + // -IYI -> -IXI + let mut state = prep_state(&["-iIWI"], &["IXI"]); + state.szdg(1); + check_state(&state, &["-IXI"], &["IWI"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_h() { + // H: X -> Z; Z -> X; Y -> -Y; + + // +X -> +Z + let mut state = prep_state(&["X"], &["Z"]); + state.h(0); + check_state(&state, &["Z"], &["X"]); + + // +Y -> -Y + let mut state = prep_state(&["iW"], &["X"]); + state.h(0); + check_state(&state, &["-iW"], &["Z"]); + + // +Z -> +X + let mut state = prep_state(&["Z"], &["X"]); + state.h(0); + check_state(&state, &["X"], &["Z"]); + + // -IYI -> +IYI + let mut state = prep_state(&["-iIWI"], &["IXI"]); + state.h(1); + check_state(&state, &["iIWI"], &["IZI"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_h2() { + // H2: X -> -Z, Z -> -X, Y -> -Y + + // +X -> -Z + let mut state = prep_state(&["X"], &["Z"]); + state.h2(0); + check_state(&state, &["-Z"], &["X"]); + + // +Y -> -Y + let mut state = prep_state(&["iW"], &["X"]); + state.h2(0); + check_state(&state, &["-iW"], &["Z"]); + + // +Z -> -X + let mut state = prep_state(&["Z"], &["X"]); + state.h2(0); + check_state(&state, &["-X"], &["Z"]); + + // -IYI -> +IYI + let mut state = prep_state(&["-iIWI"], &["IXI"]); + state.h2(1); + check_state(&state, &["iIWI"], &["IZI"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_h3() { + // H3: X -> Y, Z -> -Z, Y -> X + + // +X -> Y + let mut state = prep_state(&["X"], &["Z"]); + state.h3(0); + check_state(&state, &["iW"], &["Z"]); + + // +Y -> +X + let mut state = prep_state(&["iW"], &["X"]); + state.h3(0); + check_state(&state, &["X"], &["W"]); + + // +Z -> -Z + let mut state = prep_state(&["Z"], &["X"]); + state.h3(0); + check_state(&state, &["-Z"], &["W"]); + + // -IYI -> -IXI + let mut state = prep_state(&["-iIWI"], &["IXI"]); + state.h3(1); + check_state(&state, &["-IXI"], &["IWI"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_h4() { + // H4: X -> -Y, Z -> -Z, Y -> -X + + // +X -> -Y + let mut state = prep_state(&["X"], &["Z"]); + state.h4(0); + check_state(&state, &["-iW"], &["Z"]); + + // +Y -> -X + let mut state = prep_state(&["iW"], &["X"]); + state.h4(0); + check_state(&state, &["-X"], &["W"]); + + // +Z -> -Z + let mut state = prep_state(&["Z"], &["X"]); + state.h4(0); + check_state(&state, &["-Z"], &["W"]); + + // -IYI -> IXI + let mut state = prep_state(&["-iIWI"], &["IXI"]); + state.h4(1); + check_state(&state, &["IXI"], &["IWI"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_h5() { + // H5: X -> -X, Z -> Y, Y -> Z + + // +X -> -X + let mut state = prep_state(&["X"], &["Z"]); + state.h5(0); + check_state(&state, &["-X"], &["W"]); + + // +Y -> +Z + let mut state = prep_state(&["iW"], &["X"]); + state.h5(0); + check_state(&state, &["Z"], &["X"]); + + // +Z -> +Y + let mut state = prep_state(&["Z"], &["X"]); + state.h5(0); + check_state(&state, &["iW"], &["X"]); + + // -IYI -> -IZI + let mut state = prep_state(&["-iIWI"], &["IXI"]); + state.h5(1); + check_state(&state, &["-IZI"], &["IXI"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_h6() { + // H6: X -> -X, Z -> -Y, Y -> -Z + + // +X -> -X + let mut state = prep_state(&["X"], &["Z"]); + state.h6(0); + check_state(&state, &["-X"], &["W"]); + + // +Y -> -Z + let mut state = prep_state(&["iW"], &["X"]); + state.h6(0); + check_state(&state, &["-Z"], &["X"]); + + // +Z -> -Y + let mut state = prep_state(&["Z"], &["X"]); + state.h6(0); + check_state(&state, &["-iW"], &["X"]); + + // -IYI -> IZI + let mut state = prep_state(&["-iIWI"], &["IXI"]); + state.h6(1); + check_state(&state, &["IZI"], &["IXI"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_f() { + // F: X -> Y, Z -> X, Y -> Z + + // +X -> +Y + let mut state = prep_state(&["X"], &["Z"]); + state.f(0); + check_state(&state, &["iW"], &["X"]); + + // +Y -> +Z + let mut state = prep_state(&["iW"], &["X"]); + state.f(0); + check_state(&state, &["Z"], &["W"]); + + // +Z -> +X + let mut state = prep_state(&["Z"], &["X"]); + state.f(0); + check_state(&state, &["X"], &["W"]); + + // -IYI -> -IZI + let mut state = prep_state(&["-iIWI"], &["IXI"]); + state.f(1); + check_state(&state, &["-IZI"], &["IWI"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_fdg() { + // Fdg: X -> Z, Z -> Y, Y -> X + + // +X -> +Z + let mut state = prep_state(&["X"], &["Z"]); + state.fdg(0); + check_state(&state, &["Z"], &["W"]); + + // +Y -> +X + let mut state = prep_state(&["iW"], &["X"]); + state.fdg(0); + check_state(&state, &["X"], &["Z"]); + + // +Z -> +Y + let mut state = prep_state(&["Z"], &["X"]); + state.fdg(0); + check_state(&state, &["iW"], &["Z"]); + + // -IYI -> -IXI + let mut state = prep_state(&["-iIWI"], &["IXI"]); + state.fdg(1); + check_state(&state, &["-IXI"], &["IZI"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_f2() { + // F2: X -> -Z, Z -> Y, Y -> -X + + // +X -> -Z + let mut state = prep_state(&["X"], &["Z"]); + state.f2(0); + check_state(&state, &["-Z"], &["W"]); + + // +Y -> -X + let mut state = prep_state(&["iW"], &["X"]); + state.f2(0); + check_state(&state, &["-X"], &["Z"]); + + // +Z -> +Y + let mut state = prep_state(&["Z"], &["X"]); + state.f2(0); + check_state(&state, &["iW"], &["Z"]); + + // -IYI -> IXI + let mut state = prep_state(&["-iIWI"], &["IXI"]); + state.f2(1); + check_state(&state, &["IXI"], &["IZI"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_f2dg() { + // F2dg: X -> -Y, Z -> -X, Y -> Z + + // +X -> -Y + let mut state = prep_state(&["X"], &["Z"]); + state.f2dg(0); + check_state(&state, &["-iW"], &["X"]); + + // +Y -> +Z + let mut state = prep_state(&["iW"], &["X"]); + state.f2dg(0); + check_state(&state, &["Z"], &["W"]); + + // +Z -> -X + let mut state = prep_state(&["Z"], &["X"]); + state.f2dg(0); + check_state(&state, &["-X"], &["W"]); + + // -IYI -> -IZI + let mut state = prep_state(&["-iIWI"], &["IXI"]); + state.f2dg(1); + check_state(&state, &["-IZI"], &["IWI"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_f3() { + // F3: X -> Y, Z -> -X, Y -> -Z + + // +X -> +Y + let mut state = prep_state(&["X"], &["Z"]); + state.f3(0); + check_state(&state, &["iW"], &["X"]); + + // +Y -> -Z + let mut state = prep_state(&["iW"], &["X"]); + state.f3(0); + check_state(&state, &["-Z"], &["W"]); + + // +Z -> -X + let mut state = prep_state(&["Z"], &["X"]); + state.f3(0); + check_state(&state, &["-X"], &["W"]); + + // -IYI -> IZI + let mut state = prep_state(&["-iIWI"], &["IXI"]); + state.f3(1); + check_state(&state, &["IZI"], &["IWI"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_f3dg() { + // F3dg: X -> -Z, Z -> -Y, Y -> X + + // +X -> -Z + let mut state = prep_state(&["X"], &["Z"]); + state.f3dg(0); + check_state(&state, &["-Z"], &["W"]); + + // +Y -> +X + let mut state = prep_state(&["iW"], &["X"]); + state.f3dg(0); + check_state(&state, &["X"], &["Z"]); + + // +Z -> -Y + let mut state = prep_state(&["Z"], &["X"]); + state.f3dg(0); + check_state(&state, &["-iW"], &["Z"]); + + // -IYI -> -IXI + let mut state = prep_state(&["-iIWI"], &["IXI"]); + state.f3dg(1); + check_state(&state, &["-IXI"], &["IZI"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_f4() { + // F4: X -> Z, Z -> -Y, Y -> -X + + // +X -> +Z + let mut state = prep_state(&["X"], &["Z"]); + state.f4(0); + check_state(&state, &["Z"], &["W"]); + + // +Y -> -X + let mut state = prep_state(&["iW"], &["X"]); + state.f4(0); + check_state(&state, &["-X"], &["Z"]); + + // +Z -> -Y + let mut state = prep_state(&["Z"], &["X"]); + state.f4(0); + check_state(&state, &["-iW"], &["Z"]); + + // -IYI -> IXI + let mut state = prep_state(&["-iIWI"], &["IXI"]); + state.f4(1); + check_state(&state, &["IXI"], &["IZI"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_f4dg() { + // F4dg: X -> -Y, Z -> X, Y -> -Z + + // +X -> -Y + let mut state = prep_state(&["X"], &["Z"]); + state.f4dg(0); + check_state(&state, &["-iW"], &["X"]); + + // +Y -> -Z + let mut state = prep_state(&["iW"], &["X"]); + state.f4dg(0); + check_state(&state, &["-Z"], &["W"]); + + // +Z -> +X + let mut state = prep_state(&["Z"], &["X"]); + state.f4dg(0); + check_state(&state, &["X"], &["W"]); + + // -IYI -> +IZI + let mut state = prep_state(&["-iIWI"], &["IXI"]); + state.f4dg(1); + check_state(&state, &["IZI"], &["IWI"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_cx() { + // CX: +IX -> +IX; +IZ -> +ZZ; +XI -> +XX; +ZI -> +ZI; + + // TODO: Expand the set of stabilizer transformations evaluated. + + // +IX -> +IX + let mut state = prep_state(&["IX"], &["IZ"]); + state.cx(0, 1); + check_state(&state, &["IX"], &["ZZ"]); + + // +IZ -> +ZZ + let mut state = prep_state(&["IZ"], &["IX"]); + state.cx(0, 1); + check_state(&state, &["ZZ"], &["IX"]); + + // +XI -> +XX + let mut state = prep_state(&["XI"], &["ZI"]); + state.cx(0, 1); + check_state(&state, &["XX"], &["ZI"]); + + // +ZI -> +ZI + let mut state = prep_state(&["ZI"], &["XI"]); + state.cx(0, 1); + check_state(&state, &["ZI"], &["XX"]); + } + + #[test] + fn test_cy() { + // CY: +IX -> +ZX; +IZ -> +ZZ; +XI -> -XY; +ZI -> +ZI; + + // TODO: Expand the set of stabilizer transformations evaluated. + + // +IX -> +ZX + let mut state = prep_state(&["IX"], &["IZ"]); + state.cy(0, 1); + check_state(&state, &["ZX"], &["ZZ"]); + + // +IZ -> +ZZ + let mut state = prep_state(&["IZ"], &["IX"]); + state.cy(0, 1); + check_state(&state, &["ZZ"], &["ZX"]); + + // +XI -> -XY + let mut state = prep_state(&["XI"], &["ZI"]); + state.cy(0, 1); + check_state(&state, &["-iXW"], &["ZI"]); + + // +ZI -> +ZI + let mut state = prep_state(&["ZI"], &["XI"]); + state.cy(0, 1); + check_state(&state, &["ZI"], &["XW"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_cz() { + // CZ: +IX -> +ZX; +IZ -> +IZ; +XI -> +XZ; +ZI -> +ZI; + + // TODO: Expand the set of stabilizer transformations evaluated. + + // +IX -> +ZX + let mut state = prep_state(&["IX"], &["IZ"]); + state.cz(0, 1); + check_state(&state, &["ZX"], &["IZ"]); + + // +IZ -> +IZ + let mut state = prep_state(&["IZ"], &["IX"]); + state.cz(0, 1); + check_state(&state, &["IZ"], &["ZX"]); + + // +XI -> +XZ + let mut state = prep_state(&["XI"], &["ZI"]); + state.cz(0, 1); + check_state(&state, &["XZ"], &["ZI"]); + + // +ZI -> +ZI + let mut state = prep_state(&["ZI"], &["XI"]); + state.cz(0, 1); + check_state(&state, &["ZI"], &["XZ"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_sxx() { + // SXX: XI -> XI + // IX -> IX + // ZI -> -YX + // IZ -> -XY + + // TODO: Expand the set of stabilizer transformations evaluated. + + // +IX -> +XI + let mut state = prep_state(&["IX"], &["IZ"]); + state.sxx(0, 1); + check_state(&state, &["IX"], &["XW"]); + + // +IZ -> -XY + let mut state = prep_state(&["IZ"], &["IX"]); + state.sxx(0, 1); + check_state(&state, &["-iXW"], &["IX"]); + + // +XI -> +XI + let mut state = prep_state(&["XI"], &["ZI"]); + state.sxx(0, 1); + check_state(&state, &["XI"], &["WX"]); + + // +ZI -> -YX + let mut state = prep_state(&["ZI"], &["XI"]); + state.sxx(0, 1); + check_state(&state, &["-iWX"], &["XI"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_sxxdg() { + // SXXdg: XI -> XI + // IX -> IX + // ZI -> YX + // IZ -> XY + + // TODO: Expand the set of stabilizer transformations evaluated. + + // +IX -> +XI + let mut state = prep_state(&["IX"], &["IZ"]); + state.sxxdg(0, 1); + check_state(&state, &["IX"], &["XW"]); + + // +IZ -> +XY + let mut state = prep_state(&["IZ"], &["IX"]); + state.sxxdg(0, 1); + check_state(&state, &["iXW"], &["IX"]); + + // +XI -> +XI + let mut state = prep_state(&["XI"], &["ZI"]); + state.sxxdg(0, 1); + check_state(&state, &["XI"], &["WX"]); + + // +ZI -> +YX + let mut state = prep_state(&["ZI"], &["XI"]); + state.sxxdg(0, 1); + check_state(&state, &["iWX"], &["XI"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_syy() { + // SYY: XI -> -ZY + // IX -> -YZ + // ZI -> XY + // IZ -> YX + + // TODO: Expand the set of stabilizer transformations evaluated. + + // +IX -> -YZ + let mut state = prep_state(&["IX"], &["IZ"]); + state.syy(0, 1); + check_state(&state, &["-iWZ"], &["WX"]); + + // +IZ -> +YX + let mut state = prep_state(&["IZ"], &["IX"]); + state.syy(0, 1); + check_state(&state, &["iWX"], &["WZ"]); + + // +XI -> -ZY + let mut state = prep_state(&["XI"], &["ZI"]); + state.syy(0, 1); + check_state(&state, &["-iZW"], &["XW"]); + + // +ZI -> +XY + let mut state = prep_state(&["ZI"], &["XI"]); + state.syy(0, 1); + check_state(&state, &["iXW"], &["ZW"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_syydg() { + // SYYdg: XI -> ZY + // IX -> YZ + // ZI -> -XY + // IZ -> -YX + + // TODO: Expand the set of stabilizer transformations evaluated. + + // +IX -> YZ + let mut state = prep_state(&["IX"], &["IZ"]); + state.syydg(0, 1); + check_state(&state, &["iWZ"], &["WX"]); + + // +IZ -> -YX + let mut state = prep_state(&["IZ"], &["IX"]); + state.syydg(0, 1); + check_state(&state, &["-iWX"], &["WZ"]); + + // +XI -> ZY + let mut state = prep_state(&["XI"], &["ZI"]); + state.syydg(0, 1); + check_state(&state, &["iZW"], &["XW"]); + + // +ZI -> +XY + let mut state = prep_state(&["ZI"], &["XI"]); + state.syydg(0, 1); + check_state(&state, &["-iXW"], &["ZW"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_szz() { + // SZZ: +IX -> +ZY; + // +IZ -> +IZ; + // +XI -> +ZY; + // +ZI -> +ZI; + + // TODO: Expand the set of stabilizer transformations evaluated. + + // +IX -> ZY + let mut state = prep_state(&["IX"], &["IZ"]); + state.szz(0, 1); + check_state(&state, &["iZW"], &["IZ"]); + + // +IZ -> IZ + let mut state = prep_state(&["IZ"], &["IX"]); + state.szz(0, 1); + check_state(&state, &["IZ"], &["ZW"]); + + // +XI -> YZ + let mut state = prep_state(&["XI"], &["ZI"]); + state.szz(0, 1); + check_state(&state, &["iWZ"], &["ZI"]); + + // +ZI -> ZI + let mut state = prep_state(&["ZI"], &["XI"]); + state.szz(0, 1); + check_state(&state, &["ZI"], &["WZ"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_szzdg() { + // SZZ: +IX -> -ZY; + // +IZ -> +IZ; + // +XI -> -ZY; + // +ZI -> +ZI; + + // TODO: Expand the set of stabilizer transformations evaluated. + + // +IX -> -ZY + let mut state = prep_state(&["IX"], &["IZ"]); + state.szzdg(0, 1); + check_state(&state, &["-iZW"], &["IZ"]); + + // +IZ -> IZ + let mut state = prep_state(&["IZ"], &["IX"]); + state.szzdg(0, 1); + check_state(&state, &["IZ"], &["ZW"]); + + // +XI -> -YZ + let mut state = prep_state(&["XI"], &["ZI"]); + state.szzdg(0, 1); + check_state(&state, &["-iWZ"], &["ZI"]); + + // +ZI -> ZI + let mut state = prep_state(&["ZI"], &["XI"]); + state.szzdg(0, 1); + check_state(&state, &["ZI"], &["WZ"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_swap() { + // SWAP: +IX -> +XI; + // +IZ -> +ZI; + // +XI -> +IX; + // +ZI -> +IZ; + + // TODO: Expand the set of stabilizer transformations evaluated. + + // +IX -> +XI + let mut state = prep_state(&["IX"], &["IZ"]); + state.swap(0, 1); + check_state(&state, &["XI"], &["ZI"]); + + // +IZ -> +ZI + let mut state = prep_state(&["IZ"], &["IX"]); + state.swap(0, 1); + check_state(&state, &["ZI"], &["XI"]); + + // +XI -> +IX + let mut state = prep_state(&["XI"], &["ZI"]); + state.swap(0, 1); + check_state(&state, &["IX"], &["IZ"]); + + // +ZI -> +IZ + let mut state = prep_state(&["ZI"], &["XI"]); + state.swap(0, 1); + check_state(&state, &["IZ"], &["IX"]); + } + + #[test] + #[expect(clippy::shadow_unrelated)] + fn test_g2() { + // G2: +XI -> +IX + // +IX -> +XI + // +ZI -> +XZ + // +IZ -> +ZX + + // TODO: Expand the set of stabilizer transformations evaluated. + + // +IX -> +XI + let mut state = prep_state(&["IX"], &["IZ"]); + state.g2(0, 1); + check_state(&state, &["XI"], &["ZX"]); + + // +IZ -> +ZX + let mut state = prep_state(&["IZ"], &["IX"]); + state.g2(0, 1); + check_state(&state, &["ZX"], &["XI"]); + + // +XI -> +IX + let mut state = prep_state(&["XI"], &["ZI"]); + state.g2(0, 1); + check_state(&state, &["IX"], &["XZ"]); + + // +ZI -> +XZ + let mut state = prep_state(&["ZI"], &["XI"]); + state.g2(0, 1); + check_state(&state, &["XZ"], &["IX"]); + } + + fn one_bit_z_teleport( + mut state: SparseStab, u32>, + ) -> (SparseStab, u32>, bool) { + state.cx(1, 0); + state.h(1); + let (m1, d1) = state.mz(1); + if m1 { + state.z(0); + } + (state, d1) + } + + /// Test one-bit Z teleportation of |+X> + #[test] + fn test_nondeterministic_mz_one_bit_z_teleportation_of_x() { + // See: arXiv:quant-ph/0002039 + + for _ in 1_u32..=100 { + let d1; + let mut state: SparseStab, u32> = SparseStab::new(2); + state.h(1); // Set input to |+> + (state, d1) = one_bit_z_teleport(state); + // X basis meas + state.h(0); + let (m0, d0) = state.mz(0); + let m0_int = u8::from(m0); + assert_eq!(m0_int, 0); // |+> -> 0 == false + assert!(!d1); // Not deterministic + assert!(d0); // Deterministic + } + } + + /// Test one-bit Z teleportation of |-X> + #[test] + fn test_nondeterministic_mz_one_bit_z_teleportation_of_nx() { + // See: arXiv:quant-ph/0002039 + + for _ in 1_u32..=100 { + let d1; + let mut state: SparseStab, u32> = SparseStab::new(2); + state.x(1); + state.h(1); // Set input to |-> + (state, d1) = one_bit_z_teleport(state); + // X basis meas + state.h(0); + let (m0, d0) = state.mz(0); + let m0_int = u8::from(m0); + assert_eq!(m0_int, 1); // |-> -> 1 == true + assert!(!d1); // Not deterministic + assert!(d0); // Deterministic + } + } + + /// Test one-bit Z teleportation of |+Y> + #[test] + fn test_nondeterministic_mz_one_bit_z_teleportation_of_y() { + // See: arXiv:quant-ph/0002039 + + for _ in 1_u32..=100 { + let d1; + let mut state: SparseStab, u32> = SparseStab::new(2); + state.sxdg(1); // Set input to |+i> + (state, d1) = one_bit_z_teleport(state); + // Y basis meas + state.sx(0); // Y -> Z + let (m0, d0) = state.mz(0); + let m0_int = u8::from(m0); + assert_eq!(m0_int, 0); // |+X> -> 0 == false + assert!(!d1); // Not deterministic + assert!(d0); // Deterministic + } + } + + /// Test one-bit Z teleportation of |-Y> + #[test] + fn test_nondeterministic_mz_one_bit_z_teleportation_of_ny() { + // See: arXiv:quant-ph/0002039 + + for _ in 1_u32..=100 { + let d1; + let mut state: SparseStab, u32> = SparseStab::new(2); + state.x(1); + state.sxdg(1); // Set input to |-i> + (state, d1) = one_bit_z_teleport(state); + // Y basis meas + state.sx(0); // Y -> Z + let (m0, d0) = state.mz(0); + let m0_int = u8::from(m0); + assert_eq!(m0_int, 1); // |-Y> -> 1 == true + assert!(!d1); // Not deterministic + assert!(d0); // Deterministic + } + } + + /// Test one-bit Z teleportation of |+Z> + #[test] + fn test_nondeterministic_mz_one_bit_z_teleportation_of_z() { + // See: arXiv:quant-ph/0002039 + + for _ in 1_u32..=100 { + let d1; + let mut state: SparseStab, u32> = SparseStab::new(2); + // Set input to |0> + (state, d1) = one_bit_z_teleport(state); + let (m0, d0) = state.mz(0); + let m0_int = u8::from(m0); + assert_eq!(m0_int, 0); // |0> + assert!(!d1); // Not deterministic + assert!(d0); // Deterministic + } + } + + /// Test one-bit Z teleportation of |-Z> + #[test] + fn test_nondeterministic_mz_one_bit_z_teleportation_of_nz() { + // See: arXiv:quant-ph/0002039 + + for _ in 1_u32..=100 { + let d1; + let mut state: SparseStab, u32> = SparseStab::new(2); + state.x(1); // Set input to |1> + (state, d1) = one_bit_z_teleport(state); + let (m0, d0) = state.mz(0); + let m0_int = u8::from(m0); + assert_eq!(m0_int, 1); // |1> -> 1 == true + assert!(!d1); // Not deterministic + assert!(d0); // Deterministic + } + } + + fn teleport( + mut state: SparseStab, u32>, + ) -> (SparseStab, u32>, bool, bool) { + // |psi> -----.-H-MZ=m0 + // | + // |0> -H-.-X---MZ=m1 + // | + // |0> ---X------------X^m1-Z^m0-MZ=m2 + + state.h(1); + state.cx(1, 2); + state.cx(0, 1); + state.h(0); + let (m0, d0) = state.mz(0); + let (m1, d1) = state.mz(1); + if m1 { + state.x(2); + } + if m0 { + state.z(2); + } + (state, d0, d1) + } + + #[test] + fn test_nondeterministic_mz_via_teleportation_x() { + for _ in 1_u32..=100 { + let d0; + let d1; + let mut state: SparseStab, u32> = SparseStab::new(3); + state.h(0); + (state, d0, d1) = teleport(state); + state.h(2); + let (m2, d2) = state.mz(2); + let m2_int = u8::from(m2); + assert_eq!(m2_int, 0); + assert!(!d0); + assert!(!d1); + assert!(d2); + } + } + + #[test] + fn test_nondeterministic_mz_via_teleportation_nx() { + for _ in 1_u32..=100 { + let d0; + let d1; + let mut state: SparseStab, u32> = SparseStab::new(3); + state.x(0); + state.h(0); + (state, d0, d1) = teleport(state); + state.h(2); + let (m2, d2) = state.mz(2); + let m2_int = u8::from(m2); + + assert_eq!(m2_int, 1); + assert!(!d0); + assert!(!d1); + assert!(d2); + } + } + + #[test] + fn test_nondeterministic_mz_via_teleportation_y() { + for _ in 1_u32..=100 { + let d0; + let d1; + let mut state: SparseStab, u32> = SparseStab::new(3); + state.sxdg(0); + (state, d0, d1) = teleport(state); + state.sx(2); + let (m2, d2) = state.mz(2); + let m2_int = u8::from(m2); + assert_eq!(m2_int, 0); + assert!(!d0); + assert!(!d1); + assert!(d2); + } + } + + #[test] + fn test_nondeterministic_mz_via_teleportation_ny() { + for _ in 1_u32..=100 { + let d0; + let d1; + let mut state: SparseStab, u32> = SparseStab::new(3); + state.x(0); + state.sxdg(0); + (state, d0, d1) = teleport(state); + state.sx(2); + let (m2, d2) = state.mz(2); + let m2_int = u8::from(m2); + assert_eq!(m2_int, 1); + assert!(!d0); + assert!(!d1); + assert!(d2); + } + } + + #[test] + fn test_nondeterministic_mz_via_teleportation_z() { + for _ in 1_u32..=100 { + let d0; + let d1; + let mut state: SparseStab, u32> = SparseStab::new(3); + (state, d0, d1) = teleport(state); + let (m2, d2) = state.mz(2); + let m2_int = u8::from(m2); + + assert_eq!(m2_int, 0); + assert!(!d0); + assert!(!d1); + assert!(d2); + } + } + + #[test] + fn test_nondeterministic_mz_via_teleportation_nz() { + for _ in 1_u32..=100 { + let d0; + let d1; + let mut state: SparseStab, u32> = SparseStab::new(3); + state.x(0); // input state |-Z> + (state, d0, d1) = teleport(state); + let (m2, d2) = state.mz(2); + let m2_int = u8::from(m2); + + assert_eq!(m2_int, 1); + assert!(!d0); + assert!(!d1); + assert!(d2); + } + } + + // TODO: Consider "forcing" the random number for cleaner testing. + // TODO: Consider a seed to still have random numbers but make them predictable +} diff --git a/crates/pecos/Cargo.toml b/crates/pecos/Cargo.toml new file mode 100644 index 00000000..3ff03c78 --- /dev/null +++ b/crates/pecos/Cargo.toml @@ -0,0 +1,48 @@ +[package] +name = "pecos" +version.workspace = true +edition.workspace = true +authors.workspace = true +homepage.workspace = true +repository.workspace = true +license.workspace = true +keywords.workspace = true +categories.workspace = true +readme = "../../README.md" +description = "A crate for evaluating and exploring quantum error correction." + +[dependencies] +rand = { workspace = true } +rand_chacha = { workspace = true } +rand_xoshiro = { workspace = true } +pecos-core = { path= "../pecos-core" } +pecos-qsims = { path= "../pecos-qsims" } +pecos-qec = { path= "../pecos-qec" } + +# For Wasm tests, see: https://rustwasm.github.io/wasm-bindgen/wasm-bindgen-test/index.html +# make sure to run: +# rustup target add wasm32-unknown-unknown +# cargo install wasm-pack +# wasm-pack test --node +[target.'cfg(target_arch = "wasm32")'.dev-dependencies] +wasm-bindgen-test = "0.3" +getrandom = { version = "0.2", features = ["js"] } +rand = { version = "0.8", features = ["getrandom"] } + +[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] +criterion = "0.5" +flamegraph = "0.6" + +# Read the following for opitmization settings: https://nnethercote.github.io/perf-book/build-configuration.html +# Compress filesize: https://github.com/johnthagen/min-sized-rust + +#[profile.release] +#codegen-units = 1 +#lto = "fat" # false, "fat", "thin", "off" +# +## opt-level = "z" # "z", "s" +## panic = "abort" +## strip = "symbols" # "debuginfo", "symbols" + +[lints] +workspace = true diff --git a/crates/pecos/LICENSE b/crates/pecos/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/crates/pecos/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/crates/pecos/src/lib.rs b/crates/pecos/src/lib.rs new file mode 100644 index 00000000..d778297d --- /dev/null +++ b/crates/pecos/src/lib.rs @@ -0,0 +1,13 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +pub mod prelude; diff --git a/crates/pecos/src/prelude.rs b/crates/pecos/src/prelude.rs new file mode 100644 index 00000000..60ec14ab --- /dev/null +++ b/crates/pecos/src/prelude.rs @@ -0,0 +1,27 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +// re-exporting pecos-core +pub use pecos_core::VecSet; + +// re-exporting pecos-qsims +pub use pecos_qsims::CliffordSimulator; +pub use pecos_qsims::SparseStab; +// TODO: add the following in the future as makes sense... +// pub use pecos_qsims::clifford_simulator::CliffordSimulator; +// pub use pecos_qsims::gens::Gens; +// pub use pecos_qsims::measurement::{MeasBitValue, MeasValue, Measurement}; // TODO: Distinguish between trait and struct/enum +// pub use pecos_qsims::nonclifford_simulator::NonCliffordSimulator; +// pub use pecos_qsims::pauli_prop::{PauliProp, StdPauliProp}; +// pub use pecos_qsims::paulis::Paulis; +// pub use pecos_qsims::quantum_simulator::QuantumSimulator; +// pub use pecos_qsims::sparse_stab::SparseStab; diff --git a/crates/pecos/tests/wasm_compatibility.rs b/crates/pecos/tests/wasm_compatibility.rs new file mode 100644 index 00000000..c81e0ce5 --- /dev/null +++ b/crates/pecos/tests/wasm_compatibility.rs @@ -0,0 +1,56 @@ +// Copyright 2024 The PECOS Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License.You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +#![cfg(target_arch = "wasm32")] + +use wasm_bindgen_test::*; + +// wasm_bindgen_test_configure!(run_in_browser); + +use pecos::sets::{Set, VecSet}; +use pecos_qsims::SparseStab; +// use pecos-qsims; + +#[wasm_bindgen_test] +fn wasm_compatibility_test() { + // Small example program using your library + let mut state = SparseStab::, u32>::new(3); + + // Perform some operations + state.h(0); + state.cx(0, 1); + state.cz(1, 2); + + // Perform measurements + let (m0, _) = state.mz(0); + let (m1, _) = state.mx(1); + let (m2, _) = state.my(2); + + // Check that the operations completed without error + // We can't assert specific measurement outcomes as they're probabilistic + println!("Measurements: {} {} {}", m0, m1, m2); + + // Test VecSet operations + let mut set = VecSet::::new(); + set.insert(1); + set.insert(2); + set.insert(3); + + assert_eq!(set.len(), 3); + assert!(set.contains(&2)); + + set.remove(&2); + assert_eq!(set.len(), 2); + assert!(!set.contains(&2)); + + println!("WASM compatibility test passed!"); +} diff --git a/dev_steps.md b/dev_steps.md new file mode 100644 index 00000000..48530f51 --- /dev/null +++ b/dev_steps.md @@ -0,0 +1,53 @@ +# Basic development steps + +For developers who want to contribute or modify PECOS: + +1. Make sure you have [Python](https://www.python.org/downloads/) and [Rust](https://www.rust-lang.org/tools/install) installed for you system (although you can get away with developing in one or the other). + +2. Clone the repository: + ```sh + git clone https://github.com/PECOS-packages/PECOS.git + cd PECOS + ``` + +3. Set up the development environment either using the `Makefile` (Note: for Windows to use the `Makefile` you may need to use a shell that has access to Linux commands such as utilizing [git bash](https://gitforwindows.org/)): + ```sh + make venv + ``` + or manually following [these steps](venv_setup.md). + + When developing in the development environment, be sure to activate the venv: + + On Linux/Mac: + ```sh + source .venv/bin/activate + ``` + + On Windows: + ```sh + .\venv\Scripts\activate + ``` + +4. Build the project in editable mode + ```sh + make build + ``` + See other build options in the `Makefile`. + +5. Run all Python and Rust tests: + ```sh + make test + ``` + Note: Make sure you have ran a build command before running tests. + +6. Run pre-commit (after [installing it](https://pre-commit.com/)) to make sure all everything is properly linted/formated + ```sh + make pre-commit + ``` + +7. To deactivate your development venv: + ```sh + deactivate + ``` + +Note: For the Rust side of the project, you can use `cargo` to run tests, benchmarks, formatting, etc. diff --git a/examples/logical_steane_code_program.py b/examples/python_examples/logical_steane_code_program.py similarity index 100% rename from examples/logical_steane_code_program.py rename to examples/python_examples/logical_steane_code_program.py diff --git a/.readthedocs.yaml b/python/.readthedocs.yaml similarity index 100% rename from .readthedocs.yaml rename to python/.readthedocs.yaml diff --git a/docs/Documentation.lnk b/python/docs/Documentation.lnk similarity index 100% rename from docs/Documentation.lnk rename to python/docs/Documentation.lnk diff --git a/python/docs/LICENSE b/python/docs/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/python/docs/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/docs/Makefile b/python/docs/Makefile similarity index 100% rename from docs/Makefile rename to python/docs/Makefile diff --git a/docs/README.md b/python/docs/README.md similarity index 100% rename from docs/README.md rename to python/docs/README.md diff --git a/python/docs/_static/custom.css b/python/docs/_static/custom.css new file mode 100644 index 00000000..c5662096 --- /dev/null +++ b/python/docs/_static/custom.css @@ -0,0 +1,10 @@ +/* custom.css */ +[data-theme="dark"] .table { + background-color: #232b33; +} + +[data-theme="dark"] .table th, +[data-theme="dark"] .table td { + background-color: #232b33; + border-bottom-color: #506071; +} diff --git a/python/docs/_static/mathconf.js b/python/docs/_static/mathconf.js new file mode 100644 index 00000000..f72c3246 --- /dev/null +++ b/python/docs/_static/mathconf.js @@ -0,0 +1,8 @@ +MathJax.Hub.Config({ + TeX: { + Macros: { + RR: '{\\bf R}', + ket: ['{| #1 \rangle}', 1], + } + } +}) diff --git a/docs/api_guide/circuit_runners.rst b/python/docs/api_guide/circuit_runners.rst similarity index 100% rename from docs/api_guide/circuit_runners.rst rename to python/docs/api_guide/circuit_runners.rst diff --git a/docs/api_guide/decoders.rst b/python/docs/api_guide/decoders.rst similarity index 88% rename from docs/api_guide/decoders.rst rename to python/docs/api_guide/decoders.rst index c38cdfc9..854193b0 100644 --- a/docs/api_guide/decoders.rst +++ b/python/docs/api_guide/decoders.rst @@ -26,7 +26,9 @@ decodes syndromes for a single round of error extraction: >>> circ_runner = pc.circuit_runners.Standard(seed=1) >>> state = pc.simulators.SparseSim(surface.num_qudits) >>> decode = pc.decoders.MWPM2D(surface).decode ->>> meas, err = circ_runner.run_logic(state, logic, error_gen=depolar, error_params={"p": 0.1}) +>>> meas, err = circ_runner.run_logic( +... state, logic, error_gen=depolar, error_params={"p": 0.1} +... ) >>> meas # doctest: +SKIP {(1, 0): {7: {3: 1, 5: 1, 9: 1, 15: 1}}} >>> err # doctest: +SKIP @@ -44,7 +46,9 @@ decodes syndromes for a single round of error extraction: >>> circ_runner = pc.circuit_runners.Standard(seed=1) >>> state = pc.simulators.SparseSim(surface.num_qudits) >>> decode = pc.decoders.MWPM2D(surface).decode ->>> meas, err = circ_runner.run_logic(state, logic, error_gen=depolar, error_params={"p": 0.1}) +>>> meas, err = circ_runner.run_logic( +... state, logic, error_gen=depolar, error_params={"p": 0.1} +... ) >>> meas # doctest: +SKIP {(1, 0): {7: {3: 1, 5: 1, 9: 1, 15: 1}}} >>> err # doctest: +SKIP @@ -62,7 +66,9 @@ decodes syndromes for a single round of error extraction: >>> circ_runner = pc.circuit_runners.Standard(seed=1) >>> state = pc.simulators.SparseSim(surface.num_qudits) >>> decode = pc.decoders.MWPM2D(surface).decode ->>> meas, err = circ_runner.run_logic(state, logic, error_gen=depolar, error_params={"p": 0.1}) +>>> meas, err = circ_runner.run_logic( +... state, logic, error_gen=depolar, error_params={"p": 0.1} +... ) >>> meas # doctest: +SKIP {(1, 0): {7: {3: 1, 5: 1, 9: 1, 15: 1}}} >>> err # doctest: +SKIP @@ -80,7 +86,9 @@ decodes syndromes for a single round of error extraction: >>> circ_runner = pc.circuit_runners.Standard(seed=1) >>> state = pc.simulators.SparseSim(surface.num_qudits) >>> decode = pc.decoders.MWPM2D(surface).decode ->>> meas, err = circ_runner.run_logic(state, logic, error_gen=depolar, error_params={"p": 0.1}) +>>> meas, err = circ_runner.run_logic( +... state, logic, error_gen=depolar, error_params={"p": 0.1} +... ) >>> meas # doctest: +SKIP {(1, 0): {7: {3: 1, 5: 1, 9: 1, 15: 1}}} >>> err # doctest: +SKIP @@ -98,7 +106,9 @@ decodes syndromes for a single round of error extraction: >>> circ_runner = pc.circuit_runners.Standard(seed=1) >>> state = pc.simulators.SparseSim(surface.num_qudits) >>> decode = pc.decoders.MWPM2D(surface).decode ->>> meas, err = circ_runner.run_logic(state, logic, error_gen=depolar, error_params={"p": 0.1}) +>>> meas, err = circ_runner.run_logic( +... state, logic, error_gen=depolar, error_params={"p": 0.1} +... ) >>> meas # doctest: +SKIP {(1, 0): {7: {3: 1, 5: 1, 9: 1, 15: 1}}} >>> err # doctest: +SKIP diff --git a/docs/api_guide/error_generators.rst b/python/docs/api_guide/error_generators.rst similarity index 87% rename from docs/api_guide/error_generators.rst rename to python/docs/api_guide/error_generators.rst index 14f316d6..155af083 100644 --- a/docs/api_guide/error_generators.rst +++ b/python/docs/api_guide/error_generators.rst @@ -31,27 +31,37 @@ measurements. In which case, the errors are applied before. An example of creating an instance of ``DepolarModel`` is seen here: >>> import pecos as pc ->>> depolar = pc.error_models.DepolarModel(model_level="code_capacity", has_idle_errors=False, perp_errors=True) +>>> depolar = pc.error_models.DepolarModel( +... model_level="code_capacity", has_idle_errors=False, perp_errors=True +... ) The >>> import pecos as pc ->>> depolar = pc.error_models.DepolarModel(model_level="code_capacity", has_idle_errors=False, perp_errors=True) +>>> depolar = pc.error_models.DepolarModel( +... model_level="code_capacity", has_idle_errors=False, perp_errors=True +... ) The >>> import pecos as pc ->>> depolar = pc.error_models.DepolarModel(model_level="code_capacity", has_idle_errors=False, perp_errors=True) +>>> depolar = pc.error_models.DepolarModel( +... model_level="code_capacity", has_idle_errors=False, perp_errors=True +... ) The >>> import pecos as pc ->>> depolar = pc.error_models.DepolarModel(model_level="code_capacity", has_idle_errors=False, perp_errors=True) +>>> depolar = pc.error_models.DepolarModel( +... model_level="code_capacity", has_idle_errors=False, perp_errors=True +... ) The >>> import pecos as pc ->>> depolar = pc.error_models.DepolarModel(model_level="code_capacity", has_idle_errors=False, perp_errors=True) +>>> depolar = pc.error_models.DepolarModel( +... model_level="code_capacity", has_idle_errors=False, perp_errors=True +... ) The ``model_level`` keyword is used to specify to what set of gates the ``DepolarModel`` is applied to. If ``model_level`` is set to the value of ``'code\_capacity'``, then the error model is applied before each ``LogicalInstruction`` to each @@ -80,7 +90,9 @@ An example of applying an error model using ``DepolarModel`` to a ``LogicalCircu >>> logic.append(surface.gate("I")) >>> circ_runner = pc.circuit_runners.Standard(seed=1) >>> state = pc.simulators.SparseSim(surface.num_qudits) ->>> meas, err = circ_runner.run(state, logic, error_model=depolar, error_params={"p": 0.1}) +>>> meas, err = circ_runner.run( +... state, logic, error_model=depolar, error_params={"p": 0.1} +... ) Note that the keyword argument @@ -92,7 +104,9 @@ Note that the keyword argument >>> logic.append(surface.gate("I")) >>> circ_runner = pc.circuit_runners.Standard(seed=1) >>> state = pc.simulators.SparseSim(surface.num_qudits) ->>> meas, err = circ_runner.run(state, logic, error_model=depolar, error_params={"p": 0.1}) +>>> meas, err = circ_runner.run( +... state, logic, error_model=depolar, error_params={"p": 0.1} +... ) Note that the keyword argument @@ -104,7 +118,9 @@ Note that the keyword argument >>> logic.append(surface.gate("I")) >>> circ_runner = pc.circuit_runners.Standard(seed=1) >>> state = pc.simulators.SparseSim(surface.num_qudits) ->>> meas, err = circ_runner.run(state, logic, error_model=depolar, error_params={"p": 0.1}) +>>> meas, err = circ_runner.run( +... state, logic, error_model=depolar, error_params={"p": 0.1} +... ) Note that the keyword argument @@ -116,7 +132,9 @@ Note that the keyword argument >>> logic.append(surface.gate("I")) >>> circ_runner = pc.circuit_runners.Standard(seed=1) >>> state = pc.simulators.SparseSim(surface.num_qudits) ->>> meas, err = circ_runner.run(state, logic, error_model=depolar, error_params={"p": 0.1}) +>>> meas, err = circ_runner.run( +... state, logic, error_model=depolar, error_params={"p": 0.1} +... ) Note that the keyword argument @@ -128,7 +146,9 @@ Note that the keyword argument >>> logic.append(surface.gate("I")) >>> circ_runner = pc.circuit_runners.Standard(seed=1) >>> state = pc.simulators.SparseSim(surface.num_qudits) ->>> meas, err = circ_runner.run(state, logic, error_model=depolar, error_params={"p": 0.1}) +>>> meas, err = circ_runner.run( +... state, logic, error_model=depolar, error_params={"p": 0.1} +... ) Note that the keyword argument ``error_params`` is used to pass a dictionary that indicates the probability :math:`p` of the depolarizing error model. diff --git a/docs/api_guide/index.rst b/python/docs/api_guide/index.rst similarity index 100% rename from docs/api_guide/index.rst rename to python/docs/api_guide/index.rst diff --git a/docs/api_guide/logical_circuits.rst b/python/docs/api_guide/logical_circuits.rst similarity index 100% rename from docs/api_guide/logical_circuits.rst rename to python/docs/api_guide/logical_circuits.rst diff --git a/docs/api_guide/qeccs.rst b/python/docs/api_guide/qeccs.rst similarity index 100% rename from docs/api_guide/qeccs.rst rename to python/docs/api_guide/qeccs.rst diff --git a/docs/api_guide/quantum_circuits.rst b/python/docs/api_guide/quantum_circuits.rst similarity index 100% rename from docs/api_guide/quantum_circuits.rst rename to python/docs/api_guide/quantum_circuits.rst diff --git a/docs/api_guide/simulators.rst b/python/docs/api_guide/simulators.rst similarity index 100% rename from docs/api_guide/simulators.rst rename to python/docs/api_guide/simulators.rst diff --git a/docs/api_guide/standard_gates.rst b/python/docs/api_guide/standard_gates.rst similarity index 100% rename from docs/api_guide/standard_gates.rst rename to python/docs/api_guide/standard_gates.rst diff --git a/docs/api_guide/tools.rst b/python/docs/api_guide/tools.rst similarity index 100% rename from docs/api_guide/tools.rst rename to python/docs/api_guide/tools.rst diff --git a/docs/bibliography.rst b/python/docs/bibliography.rst similarity index 100% rename from docs/bibliography.rst rename to python/docs/bibliography.rst diff --git a/docs/change_log.rst b/python/docs/change_log.rst similarity index 100% rename from docs/change_log.rst rename to python/docs/change_log.rst diff --git a/docs/conf.py b/python/docs/conf.py similarity index 96% rename from docs/conf.py rename to python/docs/conf.py index 6cf98112..8d9fa041 100644 --- a/docs/conf.py +++ b/python/docs/conf.py @@ -35,7 +35,7 @@ project = "PECOS" copyright = ( "2018-2023, The PECOS Developers. " - "\xA9 Copyright 2018, National Technology & Engineering Solutions of Sandia, LLC (NTESS)" + "\xa9 Copyright 2018, National Technology & Engineering Solutions of Sandia, LLC (NTESS)" ) author = "The PECOS Developers" @@ -208,7 +208,15 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, "PECOS", "PECOS Documentation", author, "PECOS", "One line description of project.", "Miscellaneous"), + ( + master_doc, + "PECOS", + "PECOS Documentation", + author, + "PECOS", + "One line description of project.", + "Miscellaneous", + ), ] # -- External links code: diff --git a/docs/development/index.rst b/python/docs/development/index.rst similarity index 100% rename from docs/development/index.rst rename to python/docs/development/index.rst diff --git a/docs/development/simulators.rst b/python/docs/development/simulators.rst similarity index 100% rename from docs/development/simulators.rst rename to python/docs/development/simulators.rst diff --git a/docs/examples/creating_qecc_class.rst b/python/docs/examples/creating_qecc_class.rst similarity index 94% rename from docs/examples/creating_qecc_class.rst rename to python/docs/examples/creating_qecc_class.rst index 5ff3bc1c..859844c5 100644 --- a/docs/examples/creating_qecc_class.rst +++ b/python/docs/examples/creating_qecc_class.rst @@ -335,7 +335,9 @@ following simulation: >>> logic.append(qecc.gate("I")) >>> circ_runner = pc.circuit_runners.Standard(seed=3) >>> state = circ_runner.init(qecc.num_qudits) - >>> meas, err = circ_runner.run_logic(state, logic, error_gen=depolar, error_params={"p": 0.1}) + >>> meas, err = circ_runner.run_logic( + ... state, logic, error_gen=depolar, error_params={"p": 0.1} + ... ) >>> meas {(1, 2): {3: {3: 1}}} >>> err @@ -348,7 +350,9 @@ following simulation: >>> logic.append(qecc.gate("I")) >>> circ_runner = pc.circuit_runners.Standard(seed=3) >>> state = circ_runner.init(qecc.num_qudits) - >>> meas, err = circ_runner.run_logic(state, logic, error_gen=depolar, error_params={"p": 0.1}) + >>> meas, err = circ_runner.run_logic( + ... state, logic, error_gen=depolar, error_params={"p": 0.1} + ... ) >>> meas {(1, 2): {3: {3: 1}}} >>> err @@ -361,7 +365,9 @@ following simulation: >>> logic.append(qecc.gate("I")) >>> circ_runner = pc.circuit_runners.Standard(seed=3) >>> state = circ_runner.init(qecc.num_qudits) - >>> meas, err = circ_runner.run_logic(state, logic, error_gen=depolar, error_params={"p": 0.1}) + >>> meas, err = circ_runner.run_logic( + ... state, logic, error_gen=depolar, error_params={"p": 0.1} + ... ) >>> meas {(1, 2): {3: {3: 1}}} >>> err @@ -374,7 +380,9 @@ following simulation: >>> logic.append(qecc.gate("I")) >>> circ_runner = pc.circuit_runners.Standard(seed=3) >>> state = circ_runner.init(qecc.num_qudits) - >>> meas, err = circ_runner.run_logic(state, logic, error_gen=depolar, error_params={"p": 0.1}) + >>> meas, err = circ_runner.run_logic( + ... state, logic, error_gen=depolar, error_params={"p": 0.1} + ... ) >>> meas {(1, 2): {3: {3: 1}}} >>> err @@ -387,7 +395,9 @@ following simulation: >>> logic.append(qecc.gate("I")) >>> circ_runner = pc.circuit_runners.Standard(seed=3) >>> state = circ_runner.init(qecc.num_qudits) - >>> meas, err = circ_runner.run_logic(state, logic, error_gen=depolar, error_params={"p": 0.1}) + >>> meas, err = circ_runner.run_logic( + ... state, logic, error_gen=depolar, error_params={"p": 0.1} + ... ) >>> meas {(1, 2): {3: {3: 1}}} >>> err @@ -400,7 +410,9 @@ following simulation: >>> logic.append(qecc.gate("I")) >>> circ_runner = pc.circuit_runners.Standard(seed=3) >>> state = circ_runner.init(qecc.num_qudits) - >>> meas, err = circ_runner.run_logic(state, logic, error_gen=depolar, error_params={"p": 0.1}) + >>> meas, err = circ_runner.run_logic( + ... state, logic, error_gen=depolar, error_params={"p": 0.1} + ... ) >>> meas {(1, 2): {3: {3: 1}}} >>> err @@ -413,7 +425,9 @@ following simulation: >>> logic.append(qecc.gate("I")) >>> circ_runner = pc.circuit_runners.Standard(seed=3) >>> state = circ_runner.init(qecc.num_qudits) - >>> meas, err = circ_runner.run_logic(state, logic, error_gen=depolar, error_params={"p": 0.1}) + >>> meas, err = circ_runner.run_logic( + ... state, logic, error_gen=depolar, error_params={"p": 0.1} + ... ) >>> meas {(1, 2): {3: {3: 1}}} >>> err @@ -426,7 +440,9 @@ following simulation: >>> logic.append(qecc.gate("I")) >>> circ_runner = pc.circuit_runners.Standard(seed=3) >>> state = circ_runner.init(qecc.num_qudits) - >>> meas, err = circ_runner.run_logic(state, logic, error_gen=depolar, error_params={"p": 0.1}) + >>> meas, err = circ_runner.run_logic( + ... state, logic, error_gen=depolar, error_params={"p": 0.1} + ... ) >>> meas {(1, 2): {3: {3: 1}}} >>> err @@ -439,7 +455,9 @@ following simulation: >>> logic.append(qecc.gate("I")) >>> circ_runner = pc.circuit_runners.Standard(seed=3) >>> state = circ_runner.init(qecc.num_qudits) - >>> meas, err = circ_runner.run_logic(state, logic, error_gen=depolar, error_params={"p": 0.1}) + >>> meas, err = circ_runner.run_logic( + ... state, logic, error_gen=depolar, error_params={"p": 0.1} + ... ) >>> meas {(1, 2): {3: {3: 1}}} >>> err diff --git a/docs/examples/index.rst b/python/docs/examples/index.rst similarity index 100% rename from docs/examples/index.rst rename to python/docs/examples/index.rst diff --git a/docs/examples/monte_carlo_script.rst b/python/docs/examples/monte_carlo_script.rst similarity index 91% rename from docs/examples/monte_carlo_script.rst rename to python/docs/examples/monte_carlo_script.rst index 11e6e881..469fbf88 100644 --- a/docs/examples/monte_carlo_script.rst +++ b/python/docs/examples/monte_carlo_script.rst @@ -74,8 +74,12 @@ We now create the Monte Carlo loop, which prepares a fresh initial state, applie fails = 0 for i in range(runs): state = pc.simulators.SparseSim(surface.num_qudits) - meas, _ = circ_runner.run(state, logic, error_gen=depolar, error_params={"p": p}) - fails = determine_fails(meas, decoder, circ_runner, state, logical_ops, fails) + meas, _ = circ_runner.run( + state, logic, error_gen=depolar, error_params={"p": p} + ) + fails = determine_fails( + meas, decoder, circ_runner, state, logical_ops, fails + ) plog.append(fails / runs) print("ps=", list(ps)) print("plog=", plog) @@ -96,7 +100,18 @@ When this script is ran, an example output is: 0.3666666666666667, 0.4, ] - plog = [0.0588, 0.102, 0.1497, 0.1835, 0.2241, 0.2702, 0.3052, 0.3485, 0.3783, 0.4017] + plog = [ + 0.0588, + 0.102, + 0.1497, + 0.1835, + 0.2241, + 0.2702, + 0.3052, + 0.3485, + 0.3783, + 0.4017, + ] One can then use plotting packages such as Matplotlib to produce plots as appropriate for the data. PECOS provides a diff --git a/docs/examples/stab_code_verification.rst b/python/docs/examples/stab_code_verification.rst similarity index 100% rename from docs/examples/stab_code_verification.rst rename to python/docs/examples/stab_code_verification.rst diff --git a/docs/images/bellcircuit.png b/python/docs/images/bellcircuit.png similarity index 100% rename from docs/images/bellcircuit.png rename to python/docs/images/bellcircuit.png diff --git a/docs/images/nonmedial_pseudo_threshold - Copy.png b/python/docs/images/nonmedial_pseudo_threshold - Copy.png similarity index 100% rename from docs/images/nonmedial_pseudo_threshold - Copy.png rename to python/docs/images/nonmedial_pseudo_threshold - Copy.png diff --git a/docs/images/nonmedial_pseudo_threshold.png b/python/docs/images/nonmedial_pseudo_threshold.png similarity index 100% rename from docs/images/nonmedial_pseudo_threshold.png rename to python/docs/images/nonmedial_pseudo_threshold.png diff --git a/docs/images/pecos_large_logo.png b/python/docs/images/pecos_large_logo.png similarity index 100% rename from docs/images/pecos_large_logo.png rename to python/docs/images/pecos_large_logo.png diff --git a/docs/images/pecos_large_logo_white.png b/python/docs/images/pecos_large_logo_white.png similarity index 100% rename from docs/images/pecos_large_logo_white.png rename to python/docs/images/pecos_large_logo_white.png diff --git a/docs/images/pecos_triangle_logo.png b/python/docs/images/pecos_triangle_logo.png similarity index 100% rename from docs/images/pecos_triangle_logo.png rename to python/docs/images/pecos_triangle_logo.png diff --git a/docs/images/qecc_zrep_syn_extract.png b/python/docs/images/qecc_zrep_syn_extract.png similarity index 100% rename from docs/images/qecc_zrep_syn_extract.png rename to python/docs/images/qecc_zrep_syn_extract.png diff --git a/docs/images/stabcode1.png b/python/docs/images/stabcode1.png similarity index 100% rename from docs/images/stabcode1.png rename to python/docs/images/stabcode1.png diff --git a/docs/images/stabcode2.png b/python/docs/images/stabcode2.png similarity index 100% rename from docs/images/stabcode2.png rename to python/docs/images/stabcode2.png diff --git a/docs/images/stabcode3.png b/python/docs/images/stabcode3.png similarity index 100% rename from docs/images/stabcode3.png rename to python/docs/images/stabcode3.png diff --git a/docs/images/stabcode4.png b/python/docs/images/stabcode4.png similarity index 100% rename from docs/images/stabcode4.png rename to python/docs/images/stabcode4.png diff --git a/docs/images/surface.png b/python/docs/images/surface.png similarity index 100% rename from docs/images/surface.png rename to python/docs/images/surface.png diff --git a/docs/images/surface_graph.png b/python/docs/images/surface_graph.png similarity index 100% rename from docs/images/surface_graph.png rename to python/docs/images/surface_graph.png diff --git a/docs/images/surfacemedialplot_layout.png b/python/docs/images/surfacemedialplot_layout.png similarity index 100% rename from docs/images/surfacemedialplot_layout.png rename to python/docs/images/surfacemedialplot_layout.png diff --git a/docs/images/surfacemedialplot_syn.png b/python/docs/images/surfacemedialplot_syn.png similarity index 100% rename from docs/images/surfacemedialplot_syn.png rename to python/docs/images/surfacemedialplot_syn.png diff --git a/docs/index.rst b/python/docs/index.rst similarity index 100% rename from docs/index.rst rename to python/docs/index.rst diff --git a/docs/install.rst b/python/docs/install.rst similarity index 100% rename from docs/install.rst rename to python/docs/install.rst diff --git a/docs/make.bat b/python/docs/make.bat similarity index 100% rename from docs/make.bat rename to python/docs/make.bat diff --git a/docs/reference/_autosummary/pecos.circuit_converters.checks2circuit.rst b/python/docs/reference/_autosummary/pecos.circuit_converters.checks2circuit.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuit_converters.checks2circuit.rst rename to python/docs/reference/_autosummary/pecos.circuit_converters.checks2circuit.rst diff --git a/docs/reference/_autosummary/pecos.circuit_converters.rst b/python/docs/reference/_autosummary/pecos.circuit_converters.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuit_converters.rst rename to python/docs/reference/_autosummary/pecos.circuit_converters.rst diff --git a/docs/reference/_autosummary/pecos.circuit_converters.std2chs.rst b/python/docs/reference/_autosummary/pecos.circuit_converters.std2chs.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuit_converters.std2chs.rst rename to python/docs/reference/_autosummary/pecos.circuit_converters.std2chs.rst diff --git a/docs/reference/_autosummary/pecos.circuits.hyqc.conditionals.rst b/python/docs/reference/_autosummary/pecos.circuits.hyqc.conditionals.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuits.hyqc.conditionals.rst rename to python/docs/reference/_autosummary/pecos.circuits.hyqc.conditionals.rst diff --git a/docs/reference/_autosummary/pecos.circuits.hyqc.cops.rst b/python/docs/reference/_autosummary/pecos.circuits.hyqc.cops.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuits.hyqc.cops.rst rename to python/docs/reference/_autosummary/pecos.circuits.hyqc.cops.rst diff --git a/docs/reference/_autosummary/pecos.circuits.hyqc.fund.rst b/python/docs/reference/_autosummary/pecos.circuits.hyqc.fund.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuits.hyqc.fund.rst rename to python/docs/reference/_autosummary/pecos.circuits.hyqc.fund.rst diff --git a/docs/reference/_autosummary/pecos.circuits.hyqc.hyqc.rst b/python/docs/reference/_autosummary/pecos.circuits.hyqc.hyqc.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuits.hyqc.hyqc.rst rename to python/docs/reference/_autosummary/pecos.circuits.hyqc.hyqc.rst diff --git a/docs/reference/_autosummary/pecos.circuits.hyqc.int.rst b/python/docs/reference/_autosummary/pecos.circuits.hyqc.int.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuits.hyqc.int.rst rename to python/docs/reference/_autosummary/pecos.circuits.hyqc.int.rst diff --git a/docs/reference/_autosummary/pecos.circuits.hyqc.misc_stmts.rst b/python/docs/reference/_autosummary/pecos.circuits.hyqc.misc_stmts.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuits.hyqc.misc_stmts.rst rename to python/docs/reference/_autosummary/pecos.circuits.hyqc.misc_stmts.rst diff --git a/docs/reference/_autosummary/pecos.circuits.hyqc.qops.rst b/python/docs/reference/_autosummary/pecos.circuits.hyqc.qops.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuits.hyqc.qops.rst rename to python/docs/reference/_autosummary/pecos.circuits.hyqc.qops.rst diff --git a/docs/reference/_autosummary/pecos.circuits.hyqc.qubits.rst b/python/docs/reference/_autosummary/pecos.circuits.hyqc.qubits.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuits.hyqc.qubits.rst rename to python/docs/reference/_autosummary/pecos.circuits.hyqc.qubits.rst diff --git a/docs/reference/_autosummary/pecos.circuits.hyqc.rst b/python/docs/reference/_autosummary/pecos.circuits.hyqc.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuits.hyqc.rst rename to python/docs/reference/_autosummary/pecos.circuits.hyqc.rst diff --git a/docs/reference/_autosummary/pecos.circuits.hyqc.vars.rst b/python/docs/reference/_autosummary/pecos.circuits.hyqc.vars.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuits.hyqc.vars.rst rename to python/docs/reference/_autosummary/pecos.circuits.hyqc.vars.rst diff --git a/docs/reference/_autosummary/pecos.circuits.logical_circuit.rst b/python/docs/reference/_autosummary/pecos.circuits.logical_circuit.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuits.logical_circuit.rst rename to python/docs/reference/_autosummary/pecos.circuits.logical_circuit.rst diff --git a/docs/reference/_autosummary/pecos.circuits.qasm.barrier.rst b/python/docs/reference/_autosummary/pecos.circuits.qasm.barrier.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuits.qasm.barrier.rst rename to python/docs/reference/_autosummary/pecos.circuits.qasm.barrier.rst diff --git a/docs/reference/_autosummary/pecos.circuits.qasm.block.rst b/python/docs/reference/_autosummary/pecos.circuits.qasm.block.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuits.qasm.block.rst rename to python/docs/reference/_autosummary/pecos.circuits.qasm.block.rst diff --git a/docs/reference/_autosummary/pecos.circuits.qasm.conditionals.rst b/python/docs/reference/_autosummary/pecos.circuits.qasm.conditionals.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuits.qasm.conditionals.rst rename to python/docs/reference/_autosummary/pecos.circuits.qasm.conditionals.rst diff --git a/docs/reference/_autosummary/pecos.circuits.qasm.expr.rst b/python/docs/reference/_autosummary/pecos.circuits.qasm.expr.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuits.qasm.expr.rst rename to python/docs/reference/_autosummary/pecos.circuits.qasm.expr.rst diff --git a/docs/reference/_autosummary/pecos.circuits.qasm.func.rst b/python/docs/reference/_autosummary/pecos.circuits.qasm.func.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuits.qasm.func.rst rename to python/docs/reference/_autosummary/pecos.circuits.qasm.func.rst diff --git a/docs/reference/_autosummary/pecos.circuits.qasm.gates.rst b/python/docs/reference/_autosummary/pecos.circuits.qasm.gates.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuits.qasm.gates.rst rename to python/docs/reference/_autosummary/pecos.circuits.qasm.gates.rst diff --git a/docs/reference/_autosummary/pecos.circuits.qasm.misc.rst b/python/docs/reference/_autosummary/pecos.circuits.qasm.misc.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuits.qasm.misc.rst rename to python/docs/reference/_autosummary/pecos.circuits.qasm.misc.rst diff --git a/docs/reference/_autosummary/pecos.circuits.qasm.qasm.rst b/python/docs/reference/_autosummary/pecos.circuits.qasm.qasm.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuits.qasm.qasm.rst rename to python/docs/reference/_autosummary/pecos.circuits.qasm.qasm.rst diff --git a/docs/reference/_autosummary/pecos.circuits.qasm.rst b/python/docs/reference/_autosummary/pecos.circuits.qasm.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuits.qasm.rst rename to python/docs/reference/_autosummary/pecos.circuits.qasm.rst diff --git a/docs/reference/_autosummary/pecos.circuits.qasm.std_gates.rst b/python/docs/reference/_autosummary/pecos.circuits.qasm.std_gates.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuits.qasm.std_gates.rst rename to python/docs/reference/_autosummary/pecos.circuits.qasm.std_gates.rst diff --git a/docs/reference/_autosummary/pecos.circuits.qasm.vars.rst b/python/docs/reference/_autosummary/pecos.circuits.qasm.vars.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuits.qasm.vars.rst rename to python/docs/reference/_autosummary/pecos.circuits.qasm.vars.rst diff --git a/docs/reference/_autosummary/pecos.circuits.qc2phir.rst b/python/docs/reference/_autosummary/pecos.circuits.qc2phir.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuits.qc2phir.rst rename to python/docs/reference/_autosummary/pecos.circuits.qc2phir.rst diff --git a/docs/reference/_autosummary/pecos.circuits.quantum_circuit.rst b/python/docs/reference/_autosummary/pecos.circuits.quantum_circuit.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuits.quantum_circuit.rst rename to python/docs/reference/_autosummary/pecos.circuits.quantum_circuit.rst diff --git a/docs/reference/_autosummary/pecos.circuits.rst b/python/docs/reference/_autosummary/pecos.circuits.rst similarity index 100% rename from docs/reference/_autosummary/pecos.circuits.rst rename to python/docs/reference/_autosummary/pecos.circuits.rst diff --git a/docs/reference/_autosummary/pecos.classical_interpreters.classical_interpreter_abc.rst b/python/docs/reference/_autosummary/pecos.classical_interpreters.classical_interpreter_abc.rst similarity index 100% rename from docs/reference/_autosummary/pecos.classical_interpreters.classical_interpreter_abc.rst rename to python/docs/reference/_autosummary/pecos.classical_interpreters.classical_interpreter_abc.rst diff --git a/docs/reference/_autosummary/pecos.classical_interpreters.phir_classical_interpreter.rst b/python/docs/reference/_autosummary/pecos.classical_interpreters.phir_classical_interpreter.rst similarity index 100% rename from docs/reference/_autosummary/pecos.classical_interpreters.phir_classical_interpreter.rst rename to python/docs/reference/_autosummary/pecos.classical_interpreters.phir_classical_interpreter.rst diff --git a/docs/reference/_autosummary/pecos.classical_interpreters.rst b/python/docs/reference/_autosummary/pecos.classical_interpreters.rst similarity index 100% rename from docs/reference/_autosummary/pecos.classical_interpreters.rst rename to python/docs/reference/_autosummary/pecos.classical_interpreters.rst diff --git a/docs/reference/_autosummary/pecos.decoders.dummy_decoder.dummy_decoder.rst b/python/docs/reference/_autosummary/pecos.decoders.dummy_decoder.dummy_decoder.rst similarity index 100% rename from docs/reference/_autosummary/pecos.decoders.dummy_decoder.dummy_decoder.rst rename to python/docs/reference/_autosummary/pecos.decoders.dummy_decoder.dummy_decoder.rst diff --git a/docs/reference/_autosummary/pecos.decoders.dummy_decoder.rst b/python/docs/reference/_autosummary/pecos.decoders.dummy_decoder.rst similarity index 100% rename from docs/reference/_autosummary/pecos.decoders.dummy_decoder.rst rename to python/docs/reference/_autosummary/pecos.decoders.dummy_decoder.rst diff --git a/docs/reference/_autosummary/pecos.decoders.mwpm2d.mwpm2d.rst b/python/docs/reference/_autosummary/pecos.decoders.mwpm2d.mwpm2d.rst similarity index 100% rename from docs/reference/_autosummary/pecos.decoders.mwpm2d.mwpm2d.rst rename to python/docs/reference/_autosummary/pecos.decoders.mwpm2d.mwpm2d.rst diff --git a/docs/reference/_autosummary/pecos.decoders.mwpm2d.precomputing.rst b/python/docs/reference/_autosummary/pecos.decoders.mwpm2d.precomputing.rst similarity index 100% rename from docs/reference/_autosummary/pecos.decoders.mwpm2d.precomputing.rst rename to python/docs/reference/_autosummary/pecos.decoders.mwpm2d.precomputing.rst diff --git a/docs/reference/_autosummary/pecos.decoders.mwpm2d.rst b/python/docs/reference/_autosummary/pecos.decoders.mwpm2d.rst similarity index 100% rename from docs/reference/_autosummary/pecos.decoders.mwpm2d.rst rename to python/docs/reference/_autosummary/pecos.decoders.mwpm2d.rst diff --git a/docs/reference/_autosummary/pecos.decoders.rst b/python/docs/reference/_autosummary/pecos.decoders.rst similarity index 100% rename from docs/reference/_autosummary/pecos.decoders.rst rename to python/docs/reference/_autosummary/pecos.decoders.rst diff --git a/docs/reference/_autosummary/pecos.engines.circuit_runners.rst b/python/docs/reference/_autosummary/pecos.engines.circuit_runners.rst similarity index 100% rename from docs/reference/_autosummary/pecos.engines.circuit_runners.rst rename to python/docs/reference/_autosummary/pecos.engines.circuit_runners.rst diff --git a/docs/reference/_autosummary/pecos.engines.circuit_runners.standard.rst b/python/docs/reference/_autosummary/pecos.engines.circuit_runners.standard.rst similarity index 100% rename from docs/reference/_autosummary/pecos.engines.circuit_runners.standard.rst rename to python/docs/reference/_autosummary/pecos.engines.circuit_runners.standard.rst diff --git a/docs/reference/_autosummary/pecos.engines.circuit_runners.timing_runner.rst b/python/docs/reference/_autosummary/pecos.engines.circuit_runners.timing_runner.rst similarity index 100% rename from docs/reference/_autosummary/pecos.engines.circuit_runners.timing_runner.rst rename to python/docs/reference/_autosummary/pecos.engines.circuit_runners.timing_runner.rst diff --git a/docs/reference/_autosummary/pecos.engines.cvm.binarray.rst b/python/docs/reference/_autosummary/pecos.engines.cvm.binarray.rst similarity index 100% rename from docs/reference/_autosummary/pecos.engines.cvm.binarray.rst rename to python/docs/reference/_autosummary/pecos.engines.cvm.binarray.rst diff --git a/docs/reference/_autosummary/pecos.engines.cvm.binarray2.rst b/python/docs/reference/_autosummary/pecos.engines.cvm.binarray2.rst similarity index 100% rename from docs/reference/_autosummary/pecos.engines.cvm.binarray2.rst rename to python/docs/reference/_autosummary/pecos.engines.cvm.binarray2.rst diff --git a/docs/reference/_autosummary/pecos.engines.cvm.classical.rst b/python/docs/reference/_autosummary/pecos.engines.cvm.classical.rst similarity index 100% rename from docs/reference/_autosummary/pecos.engines.cvm.classical.rst rename to python/docs/reference/_autosummary/pecos.engines.cvm.classical.rst diff --git a/docs/reference/_autosummary/pecos.engines.cvm.cvm.rst b/python/docs/reference/_autosummary/pecos.engines.cvm.cvm.rst similarity index 100% rename from docs/reference/_autosummary/pecos.engines.cvm.cvm.rst rename to python/docs/reference/_autosummary/pecos.engines.cvm.cvm.rst diff --git a/docs/reference/_autosummary/pecos.engines.cvm.rst b/python/docs/reference/_autosummary/pecos.engines.cvm.rst similarity index 100% rename from docs/reference/_autosummary/pecos.engines.cvm.rst rename to python/docs/reference/_autosummary/pecos.engines.cvm.rst diff --git a/docs/reference/_autosummary/pecos.engines.cvm.sim_func.rst b/python/docs/reference/_autosummary/pecos.engines.cvm.sim_func.rst similarity index 100% rename from docs/reference/_autosummary/pecos.engines.cvm.sim_func.rst rename to python/docs/reference/_autosummary/pecos.engines.cvm.sim_func.rst diff --git a/docs/reference/_autosummary/pecos.engines.cvm.wasm.rst b/python/docs/reference/_autosummary/pecos.engines.cvm.wasm.rst similarity index 100% rename from docs/reference/_autosummary/pecos.engines.cvm.wasm.rst rename to python/docs/reference/_autosummary/pecos.engines.cvm.wasm.rst diff --git a/docs/reference/_autosummary/pecos.engines.cvm.wasm_vms.pywasm.rst b/python/docs/reference/_autosummary/pecos.engines.cvm.wasm_vms.pywasm.rst similarity index 100% rename from docs/reference/_autosummary/pecos.engines.cvm.wasm_vms.pywasm.rst rename to python/docs/reference/_autosummary/pecos.engines.cvm.wasm_vms.pywasm.rst diff --git a/docs/reference/_autosummary/pecos.engines.cvm.wasm_vms.pywasm3.rst b/python/docs/reference/_autosummary/pecos.engines.cvm.wasm_vms.pywasm3.rst similarity index 100% rename from docs/reference/_autosummary/pecos.engines.cvm.wasm_vms.pywasm3.rst rename to python/docs/reference/_autosummary/pecos.engines.cvm.wasm_vms.pywasm3.rst diff --git a/docs/reference/_autosummary/pecos.engines.cvm.wasm_vms.rst b/python/docs/reference/_autosummary/pecos.engines.cvm.wasm_vms.rst similarity index 100% rename from docs/reference/_autosummary/pecos.engines.cvm.wasm_vms.rst rename to python/docs/reference/_autosummary/pecos.engines.cvm.wasm_vms.rst diff --git a/docs/reference/_autosummary/pecos.engines.cvm.wasm_vms.wasmer.rst b/python/docs/reference/_autosummary/pecos.engines.cvm.wasm_vms.wasmer.rst similarity index 100% rename from docs/reference/_autosummary/pecos.engines.cvm.wasm_vms.wasmer.rst rename to python/docs/reference/_autosummary/pecos.engines.cvm.wasm_vms.wasmer.rst diff --git a/docs/reference/_autosummary/pecos.engines.cvm.wasm_vms.wasmtime.rst b/python/docs/reference/_autosummary/pecos.engines.cvm.wasm_vms.wasmtime.rst similarity index 100% rename from docs/reference/_autosummary/pecos.engines.cvm.wasm_vms.wasmtime.rst rename to python/docs/reference/_autosummary/pecos.engines.cvm.wasm_vms.wasmtime.rst diff --git a/docs/reference/_autosummary/pecos.engines.hybrid_engine.rst b/python/docs/reference/_autosummary/pecos.engines.hybrid_engine.rst similarity index 100% rename from docs/reference/_autosummary/pecos.engines.hybrid_engine.rst rename to python/docs/reference/_autosummary/pecos.engines.hybrid_engine.rst diff --git a/docs/reference/_autosummary/pecos.engines.hybrid_engine_multiprocessing.rst b/python/docs/reference/_autosummary/pecos.engines.hybrid_engine_multiprocessing.rst similarity index 100% rename from docs/reference/_autosummary/pecos.engines.hybrid_engine_multiprocessing.rst rename to python/docs/reference/_autosummary/pecos.engines.hybrid_engine_multiprocessing.rst diff --git a/docs/reference/_autosummary/pecos.engines.hybrid_engine_old.rst b/python/docs/reference/_autosummary/pecos.engines.hybrid_engine_old.rst similarity index 100% rename from docs/reference/_autosummary/pecos.engines.hybrid_engine_old.rst rename to python/docs/reference/_autosummary/pecos.engines.hybrid_engine_old.rst diff --git a/docs/reference/_autosummary/pecos.engines.rst b/python/docs/reference/_autosummary/pecos.engines.rst similarity index 100% rename from docs/reference/_autosummary/pecos.engines.rst rename to python/docs/reference/_autosummary/pecos.engines.rst diff --git a/docs/reference/_autosummary/pecos.error_models.class_errors_circuit.rst b/python/docs/reference/_autosummary/pecos.error_models.class_errors_circuit.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.class_errors_circuit.rst rename to python/docs/reference/_autosummary/pecos.error_models.class_errors_circuit.rst diff --git a/docs/reference/_autosummary/pecos.error_models.depolarizing_error_model.rst b/python/docs/reference/_autosummary/pecos.error_models.depolarizing_error_model.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.depolarizing_error_model.rst rename to python/docs/reference/_autosummary/pecos.error_models.depolarizing_error_model.rst diff --git a/docs/reference/_autosummary/pecos.error_models.error_depolar.rst b/python/docs/reference/_autosummary/pecos.error_models.error_depolar.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.error_depolar.rst rename to python/docs/reference/_autosummary/pecos.error_models.error_depolar.rst diff --git a/docs/reference/_autosummary/pecos.error_models.error_model.rst b/python/docs/reference/_autosummary/pecos.error_models.error_model.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.error_model.rst rename to python/docs/reference/_autosummary/pecos.error_models.error_model.rst diff --git a/docs/reference/_autosummary/pecos.error_models.error_model_abc.rst b/python/docs/reference/_autosummary/pecos.error_models.error_model_abc.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.error_model_abc.rst rename to python/docs/reference/_autosummary/pecos.error_models.error_model_abc.rst diff --git a/docs/reference/_autosummary/pecos.error_models.fake_error_model.rst b/python/docs/reference/_autosummary/pecos.error_models.fake_error_model.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.fake_error_model.rst rename to python/docs/reference/_autosummary/pecos.error_models.fake_error_model.rst diff --git a/docs/reference/_autosummary/pecos.error_models.generic_error_model.rst b/python/docs/reference/_autosummary/pecos.error_models.generic_error_model.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.generic_error_model.rst rename to python/docs/reference/_autosummary/pecos.error_models.generic_error_model.rst diff --git a/docs/reference/_autosummary/pecos.error_models.noise_impl.noise_initz_bitflip.rst b/python/docs/reference/_autosummary/pecos.error_models.noise_impl.noise_initz_bitflip.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.noise_impl.noise_initz_bitflip.rst rename to python/docs/reference/_autosummary/pecos.error_models.noise_impl.noise_initz_bitflip.rst diff --git a/docs/reference/_autosummary/pecos.error_models.noise_impl.noise_initz_bitflip_leakage.rst b/python/docs/reference/_autosummary/pecos.error_models.noise_impl.noise_initz_bitflip_leakage.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.noise_impl.noise_initz_bitflip_leakage.rst rename to python/docs/reference/_autosummary/pecos.error_models.noise_impl.noise_initz_bitflip_leakage.rst diff --git a/docs/reference/_autosummary/pecos.error_models.noise_impl.noise_meas_bitflip.rst b/python/docs/reference/_autosummary/pecos.error_models.noise_impl.noise_meas_bitflip.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.noise_impl.noise_meas_bitflip.rst rename to python/docs/reference/_autosummary/pecos.error_models.noise_impl.noise_meas_bitflip.rst diff --git a/docs/reference/_autosummary/pecos.error_models.noise_impl.noise_meas_bitflip_leakage.rst b/python/docs/reference/_autosummary/pecos.error_models.noise_impl.noise_meas_bitflip_leakage.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.noise_impl.noise_meas_bitflip_leakage.rst rename to python/docs/reference/_autosummary/pecos.error_models.noise_impl.noise_meas_bitflip_leakage.rst diff --git a/docs/reference/_autosummary/pecos.error_models.noise_impl.noise_sq_bitflip.rst b/python/docs/reference/_autosummary/pecos.error_models.noise_impl.noise_sq_bitflip.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.noise_impl.noise_sq_bitflip.rst rename to python/docs/reference/_autosummary/pecos.error_models.noise_impl.noise_sq_bitflip.rst diff --git a/docs/reference/_autosummary/pecos.error_models.noise_impl.noise_sq_depolarizing.rst b/python/docs/reference/_autosummary/pecos.error_models.noise_impl.noise_sq_depolarizing.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.noise_impl.noise_sq_depolarizing.rst rename to python/docs/reference/_autosummary/pecos.error_models.noise_impl.noise_sq_depolarizing.rst diff --git a/docs/reference/_autosummary/pecos.error_models.noise_impl.noise_sq_depolarizing_leakage.rst b/python/docs/reference/_autosummary/pecos.error_models.noise_impl.noise_sq_depolarizing_leakage.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.noise_impl.noise_sq_depolarizing_leakage.rst rename to python/docs/reference/_autosummary/pecos.error_models.noise_impl.noise_sq_depolarizing_leakage.rst diff --git a/docs/reference/_autosummary/pecos.error_models.noise_impl.noise_tq_depolarizing.rst b/python/docs/reference/_autosummary/pecos.error_models.noise_impl.noise_tq_depolarizing.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.noise_impl.noise_tq_depolarizing.rst rename to python/docs/reference/_autosummary/pecos.error_models.noise_impl.noise_tq_depolarizing.rst diff --git a/docs/reference/_autosummary/pecos.error_models.noise_impl.noise_tq_depolarizing_leakage.rst b/python/docs/reference/_autosummary/pecos.error_models.noise_impl.noise_tq_depolarizing_leakage.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.noise_impl.noise_tq_depolarizing_leakage.rst rename to python/docs/reference/_autosummary/pecos.error_models.noise_impl.noise_tq_depolarizing_leakage.rst diff --git a/docs/reference/_autosummary/pecos.error_models.noise_impl.rst b/python/docs/reference/_autosummary/pecos.error_models.noise_impl.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.noise_impl.rst rename to python/docs/reference/_autosummary/pecos.error_models.noise_impl.rst diff --git a/docs/reference/_autosummary/pecos.error_models.noise_impl_old.gate_groups.rst b/python/docs/reference/_autosummary/pecos.error_models.noise_impl_old.gate_groups.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.noise_impl_old.gate_groups.rst rename to python/docs/reference/_autosummary/pecos.error_models.noise_impl_old.gate_groups.rst diff --git a/docs/reference/_autosummary/pecos.error_models.noise_impl_old.init_noise.rst b/python/docs/reference/_autosummary/pecos.error_models.noise_impl_old.init_noise.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.noise_impl_old.init_noise.rst rename to python/docs/reference/_autosummary/pecos.error_models.noise_impl_old.init_noise.rst diff --git a/docs/reference/_autosummary/pecos.error_models.noise_impl_old.meas_noise.rst b/python/docs/reference/_autosummary/pecos.error_models.noise_impl_old.meas_noise.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.noise_impl_old.meas_noise.rst rename to python/docs/reference/_autosummary/pecos.error_models.noise_impl_old.meas_noise.rst diff --git a/docs/reference/_autosummary/pecos.error_models.noise_impl_old.memory_noise.rst b/python/docs/reference/_autosummary/pecos.error_models.noise_impl_old.memory_noise.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.noise_impl_old.memory_noise.rst rename to python/docs/reference/_autosummary/pecos.error_models.noise_impl_old.memory_noise.rst diff --git a/docs/reference/_autosummary/pecos.error_models.noise_impl_old.rst b/python/docs/reference/_autosummary/pecos.error_models.noise_impl_old.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.noise_impl_old.rst rename to python/docs/reference/_autosummary/pecos.error_models.noise_impl_old.rst diff --git a/docs/reference/_autosummary/pecos.error_models.noise_impl_old.sq_noise.rst b/python/docs/reference/_autosummary/pecos.error_models.noise_impl_old.sq_noise.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.noise_impl_old.sq_noise.rst rename to python/docs/reference/_autosummary/pecos.error_models.noise_impl_old.sq_noise.rst diff --git a/docs/reference/_autosummary/pecos.error_models.noise_impl_old.tq_noise.rst b/python/docs/reference/_autosummary/pecos.error_models.noise_impl_old.tq_noise.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.noise_impl_old.tq_noise.rst rename to python/docs/reference/_autosummary/pecos.error_models.noise_impl_old.tq_noise.rst diff --git a/docs/reference/_autosummary/pecos.error_models.old.depolar_gen.rst b/python/docs/reference/_autosummary/pecos.error_models.old.depolar_gen.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.old.depolar_gen.rst rename to python/docs/reference/_autosummary/pecos.error_models.old.depolar_gen.rst diff --git a/docs/reference/_autosummary/pecos.error_models.old.gatewise_gen.rst b/python/docs/reference/_autosummary/pecos.error_models.old.gatewise_gen.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.old.gatewise_gen.rst rename to python/docs/reference/_autosummary/pecos.error_models.old.gatewise_gen.rst diff --git a/docs/reference/_autosummary/pecos.error_models.old.rst b/python/docs/reference/_autosummary/pecos.error_models.old.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.old.rst rename to python/docs/reference/_autosummary/pecos.error_models.old.rst diff --git a/docs/reference/_autosummary/pecos.error_models.old.xerror_gen.rst b/python/docs/reference/_autosummary/pecos.error_models.old.xerror_gen.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.old.xerror_gen.rst rename to python/docs/reference/_autosummary/pecos.error_models.old.xerror_gen.rst diff --git a/docs/reference/_autosummary/pecos.error_models.old.xzerror_gen.rst b/python/docs/reference/_autosummary/pecos.error_models.old.xzerror_gen.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.old.xzerror_gen.rst rename to python/docs/reference/_autosummary/pecos.error_models.old.xzerror_gen.rst diff --git a/docs/reference/_autosummary/pecos.error_models.old.zerror_gen.rst b/python/docs/reference/_autosummary/pecos.error_models.old.zerror_gen.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.old.zerror_gen.rst rename to python/docs/reference/_autosummary/pecos.error_models.old.zerror_gen.rst diff --git a/docs/reference/_autosummary/pecos.error_models.parent_class_error_gen.rst b/python/docs/reference/_autosummary/pecos.error_models.parent_class_error_gen.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.parent_class_error_gen.rst rename to python/docs/reference/_autosummary/pecos.error_models.parent_class_error_gen.rst diff --git a/docs/reference/_autosummary/pecos.error_models.rst b/python/docs/reference/_autosummary/pecos.error_models.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.rst rename to python/docs/reference/_autosummary/pecos.error_models.rst diff --git a/docs/reference/_autosummary/pecos.error_models.simple_depolarizing_error_model.rst b/python/docs/reference/_autosummary/pecos.error_models.simple_depolarizing_error_model.rst similarity index 100% rename from docs/reference/_autosummary/pecos.error_models.simple_depolarizing_error_model.rst rename to python/docs/reference/_autosummary/pecos.error_models.simple_depolarizing_error_model.rst diff --git a/docs/reference/_autosummary/pecos.errors.rst b/python/docs/reference/_autosummary/pecos.errors.rst similarity index 100% rename from docs/reference/_autosummary/pecos.errors.rst rename to python/docs/reference/_autosummary/pecos.errors.rst diff --git a/docs/reference/_autosummary/pecos.foreign_objects.foreign_object_abc.rst b/python/docs/reference/_autosummary/pecos.foreign_objects.foreign_object_abc.rst similarity index 100% rename from docs/reference/_autosummary/pecos.foreign_objects.foreign_object_abc.rst rename to python/docs/reference/_autosummary/pecos.foreign_objects.foreign_object_abc.rst diff --git a/docs/reference/_autosummary/pecos.foreign_objects.object_pool.rst b/python/docs/reference/_autosummary/pecos.foreign_objects.object_pool.rst similarity index 100% rename from docs/reference/_autosummary/pecos.foreign_objects.object_pool.rst rename to python/docs/reference/_autosummary/pecos.foreign_objects.object_pool.rst diff --git a/docs/reference/_autosummary/pecos.foreign_objects.python.rst b/python/docs/reference/_autosummary/pecos.foreign_objects.python.rst similarity index 100% rename from docs/reference/_autosummary/pecos.foreign_objects.python.rst rename to python/docs/reference/_autosummary/pecos.foreign_objects.python.rst diff --git a/docs/reference/_autosummary/pecos.foreign_objects.rst b/python/docs/reference/_autosummary/pecos.foreign_objects.rst similarity index 100% rename from docs/reference/_autosummary/pecos.foreign_objects.rst rename to python/docs/reference/_autosummary/pecos.foreign_objects.rst diff --git a/docs/reference/_autosummary/pecos.foreign_objects.wasmer.rst b/python/docs/reference/_autosummary/pecos.foreign_objects.wasmer.rst similarity index 100% rename from docs/reference/_autosummary/pecos.foreign_objects.wasmer.rst rename to python/docs/reference/_autosummary/pecos.foreign_objects.wasmer.rst diff --git a/docs/reference/_autosummary/pecos.foreign_objects.wasmtime.rst b/python/docs/reference/_autosummary/pecos.foreign_objects.wasmtime.rst similarity index 100% rename from docs/reference/_autosummary/pecos.foreign_objects.wasmtime.rst rename to python/docs/reference/_autosummary/pecos.foreign_objects.wasmtime.rst diff --git a/docs/reference/_autosummary/pecos.machines.generic_machine.rst b/python/docs/reference/_autosummary/pecos.machines.generic_machine.rst similarity index 100% rename from docs/reference/_autosummary/pecos.machines.generic_machine.rst rename to python/docs/reference/_autosummary/pecos.machines.generic_machine.rst diff --git a/docs/reference/_autosummary/pecos.machines.machine_abc.rst b/python/docs/reference/_autosummary/pecos.machines.machine_abc.rst similarity index 100% rename from docs/reference/_autosummary/pecos.machines.machine_abc.rst rename to python/docs/reference/_autosummary/pecos.machines.machine_abc.rst diff --git a/docs/reference/_autosummary/pecos.machines.rst b/python/docs/reference/_autosummary/pecos.machines.rst similarity index 100% rename from docs/reference/_autosummary/pecos.machines.rst rename to python/docs/reference/_autosummary/pecos.machines.rst diff --git a/docs/reference/_autosummary/pecos.misc.commute.rst b/python/docs/reference/_autosummary/pecos.misc.commute.rst similarity index 100% rename from docs/reference/_autosummary/pecos.misc.commute.rst rename to python/docs/reference/_autosummary/pecos.misc.commute.rst diff --git a/docs/reference/_autosummary/pecos.misc.errors.rst b/python/docs/reference/_autosummary/pecos.misc.errors.rst similarity index 100% rename from docs/reference/_autosummary/pecos.misc.errors.rst rename to python/docs/reference/_autosummary/pecos.misc.errors.rst diff --git a/docs/reference/_autosummary/pecos.misc.gate_groups.rst b/python/docs/reference/_autosummary/pecos.misc.gate_groups.rst similarity index 100% rename from docs/reference/_autosummary/pecos.misc.gate_groups.rst rename to python/docs/reference/_autosummary/pecos.misc.gate_groups.rst diff --git a/docs/reference/_autosummary/pecos.misc.rst b/python/docs/reference/_autosummary/pecos.misc.rst similarity index 100% rename from docs/reference/_autosummary/pecos.misc.rst rename to python/docs/reference/_autosummary/pecos.misc.rst diff --git a/docs/reference/_autosummary/pecos.misc.stabilizer_funcs.rst b/python/docs/reference/_autosummary/pecos.misc.stabilizer_funcs.rst similarity index 100% rename from docs/reference/_autosummary/pecos.misc.stabilizer_funcs.rst rename to python/docs/reference/_autosummary/pecos.misc.stabilizer_funcs.rst diff --git a/docs/reference/_autosummary/pecos.misc.std_output.rst b/python/docs/reference/_autosummary/pecos.misc.std_output.rst similarity index 100% rename from docs/reference/_autosummary/pecos.misc.std_output.rst rename to python/docs/reference/_autosummary/pecos.misc.std_output.rst diff --git a/docs/reference/_autosummary/pecos.misc.symbol_library.rst b/python/docs/reference/_autosummary/pecos.misc.symbol_library.rst similarity index 100% rename from docs/reference/_autosummary/pecos.misc.symbol_library.rst rename to python/docs/reference/_autosummary/pecos.misc.symbol_library.rst diff --git a/docs/reference/_autosummary/pecos.misc.threshold_curve.rst b/python/docs/reference/_autosummary/pecos.misc.threshold_curve.rst similarity index 100% rename from docs/reference/_autosummary/pecos.misc.threshold_curve.rst rename to python/docs/reference/_autosummary/pecos.misc.threshold_curve.rst diff --git a/docs/reference/_autosummary/pecos.op_processors.generic_op_processor.rst b/python/docs/reference/_autosummary/pecos.op_processors.generic_op_processor.rst similarity index 100% rename from docs/reference/_autosummary/pecos.op_processors.generic_op_processor.rst rename to python/docs/reference/_autosummary/pecos.op_processors.generic_op_processor.rst diff --git a/docs/reference/_autosummary/pecos.op_processors.op_processor_abc.rst b/python/docs/reference/_autosummary/pecos.op_processors.op_processor_abc.rst similarity index 100% rename from docs/reference/_autosummary/pecos.op_processors.op_processor_abc.rst rename to python/docs/reference/_autosummary/pecos.op_processors.op_processor_abc.rst diff --git a/docs/reference/_autosummary/pecos.op_processors.rst b/python/docs/reference/_autosummary/pecos.op_processors.rst similarity index 100% rename from docs/reference/_autosummary/pecos.op_processors.rst rename to python/docs/reference/_autosummary/pecos.op_processors.rst diff --git a/docs/reference/_autosummary/pecos.qeccs.color_488.circuit_implementation1.rst b/python/docs/reference/_autosummary/pecos.qeccs.color_488.circuit_implementation1.rst similarity index 100% rename from docs/reference/_autosummary/pecos.qeccs.color_488.circuit_implementation1.rst rename to python/docs/reference/_autosummary/pecos.qeccs.color_488.circuit_implementation1.rst diff --git a/docs/reference/_autosummary/pecos.qeccs.color_488.color_488.rst b/python/docs/reference/_autosummary/pecos.qeccs.color_488.color_488.rst similarity index 100% rename from docs/reference/_autosummary/pecos.qeccs.color_488.color_488.rst rename to python/docs/reference/_autosummary/pecos.qeccs.color_488.color_488.rst diff --git a/docs/reference/_autosummary/pecos.qeccs.color_488.gates.rst b/python/docs/reference/_autosummary/pecos.qeccs.color_488.gates.rst similarity index 100% rename from docs/reference/_autosummary/pecos.qeccs.color_488.gates.rst rename to python/docs/reference/_autosummary/pecos.qeccs.color_488.gates.rst diff --git a/docs/reference/_autosummary/pecos.qeccs.color_488.instructions.rst b/python/docs/reference/_autosummary/pecos.qeccs.color_488.instructions.rst similarity index 100% rename from docs/reference/_autosummary/pecos.qeccs.color_488.instructions.rst rename to python/docs/reference/_autosummary/pecos.qeccs.color_488.instructions.rst diff --git a/docs/reference/_autosummary/pecos.qeccs.color_488.rst b/python/docs/reference/_autosummary/pecos.qeccs.color_488.rst similarity index 100% rename from docs/reference/_autosummary/pecos.qeccs.color_488.rst rename to python/docs/reference/_autosummary/pecos.qeccs.color_488.rst diff --git a/docs/reference/_autosummary/pecos.qeccs.gate_parent_class.rst b/python/docs/reference/_autosummary/pecos.qeccs.gate_parent_class.rst similarity index 100% rename from docs/reference/_autosummary/pecos.qeccs.gate_parent_class.rst rename to python/docs/reference/_autosummary/pecos.qeccs.gate_parent_class.rst diff --git a/docs/reference/_autosummary/pecos.qeccs.helper_functions.rst b/python/docs/reference/_autosummary/pecos.qeccs.helper_functions.rst similarity index 100% rename from docs/reference/_autosummary/pecos.qeccs.helper_functions.rst rename to python/docs/reference/_autosummary/pecos.qeccs.helper_functions.rst diff --git a/docs/reference/_autosummary/pecos.qeccs.instruction_parent_class.rst b/python/docs/reference/_autosummary/pecos.qeccs.instruction_parent_class.rst similarity index 100% rename from docs/reference/_autosummary/pecos.qeccs.instruction_parent_class.rst rename to python/docs/reference/_autosummary/pecos.qeccs.instruction_parent_class.rst diff --git a/docs/reference/_autosummary/pecos.qeccs.plot.rst b/python/docs/reference/_autosummary/pecos.qeccs.plot.rst similarity index 100% rename from docs/reference/_autosummary/pecos.qeccs.plot.rst rename to python/docs/reference/_autosummary/pecos.qeccs.plot.rst diff --git a/docs/reference/_autosummary/pecos.qeccs.qecc_parent_class.rst b/python/docs/reference/_autosummary/pecos.qeccs.qecc_parent_class.rst similarity index 100% rename from docs/reference/_autosummary/pecos.qeccs.qecc_parent_class.rst rename to python/docs/reference/_autosummary/pecos.qeccs.qecc_parent_class.rst diff --git a/docs/reference/_autosummary/pecos.qeccs.rst b/python/docs/reference/_autosummary/pecos.qeccs.rst similarity index 100% rename from docs/reference/_autosummary/pecos.qeccs.rst rename to python/docs/reference/_autosummary/pecos.qeccs.rst diff --git a/docs/reference/_autosummary/pecos.qeccs.surface_4444.gates.rst b/python/docs/reference/_autosummary/pecos.qeccs.surface_4444.gates.rst similarity index 100% rename from docs/reference/_autosummary/pecos.qeccs.surface_4444.gates.rst rename to python/docs/reference/_autosummary/pecos.qeccs.surface_4444.gates.rst diff --git a/docs/reference/_autosummary/pecos.qeccs.surface_4444.instructions.rst b/python/docs/reference/_autosummary/pecos.qeccs.surface_4444.instructions.rst similarity index 100% rename from docs/reference/_autosummary/pecos.qeccs.surface_4444.instructions.rst rename to python/docs/reference/_autosummary/pecos.qeccs.surface_4444.instructions.rst diff --git a/docs/reference/_autosummary/pecos.qeccs.surface_4444.rst b/python/docs/reference/_autosummary/pecos.qeccs.surface_4444.rst similarity index 100% rename from docs/reference/_autosummary/pecos.qeccs.surface_4444.rst rename to python/docs/reference/_autosummary/pecos.qeccs.surface_4444.rst diff --git a/docs/reference/_autosummary/pecos.qeccs.surface_4444.surface_4444.rst b/python/docs/reference/_autosummary/pecos.qeccs.surface_4444.surface_4444.rst similarity index 100% rename from docs/reference/_autosummary/pecos.qeccs.surface_4444.surface_4444.rst rename to python/docs/reference/_autosummary/pecos.qeccs.surface_4444.surface_4444.rst diff --git a/docs/reference/_autosummary/pecos.qeccs.surface_medial_4444.gates.rst b/python/docs/reference/_autosummary/pecos.qeccs.surface_medial_4444.gates.rst similarity index 100% rename from docs/reference/_autosummary/pecos.qeccs.surface_medial_4444.gates.rst rename to python/docs/reference/_autosummary/pecos.qeccs.surface_medial_4444.gates.rst diff --git a/docs/reference/_autosummary/pecos.qeccs.surface_medial_4444.instructions.rst b/python/docs/reference/_autosummary/pecos.qeccs.surface_medial_4444.instructions.rst similarity index 100% rename from docs/reference/_autosummary/pecos.qeccs.surface_medial_4444.instructions.rst rename to python/docs/reference/_autosummary/pecos.qeccs.surface_medial_4444.instructions.rst diff --git a/docs/reference/_autosummary/pecos.qeccs.surface_medial_4444.rst b/python/docs/reference/_autosummary/pecos.qeccs.surface_medial_4444.rst similarity index 100% rename from docs/reference/_autosummary/pecos.qeccs.surface_medial_4444.rst rename to python/docs/reference/_autosummary/pecos.qeccs.surface_medial_4444.rst diff --git a/docs/reference/_autosummary/pecos.qeccs.surface_medial_4444.surface_medial_4444.rst b/python/docs/reference/_autosummary/pecos.qeccs.surface_medial_4444.surface_medial_4444.rst similarity index 100% rename from docs/reference/_autosummary/pecos.qeccs.surface_medial_4444.surface_medial_4444.rst rename to python/docs/reference/_autosummary/pecos.qeccs.surface_medial_4444.surface_medial_4444.rst diff --git a/docs/reference/_autosummary/pecos.reps.pypmir.block_types.rst b/python/docs/reference/_autosummary/pecos.reps.pypmir.block_types.rst similarity index 100% rename from docs/reference/_autosummary/pecos.reps.pypmir.block_types.rst rename to python/docs/reference/_autosummary/pecos.reps.pypmir.block_types.rst diff --git a/docs/reference/_autosummary/pecos.reps.pypmir.data_types.rst b/python/docs/reference/_autosummary/pecos.reps.pypmir.data_types.rst similarity index 100% rename from docs/reference/_autosummary/pecos.reps.pypmir.data_types.rst rename to python/docs/reference/_autosummary/pecos.reps.pypmir.data_types.rst diff --git a/docs/reference/_autosummary/pecos.reps.pypmir.instr_type.rst b/python/docs/reference/_autosummary/pecos.reps.pypmir.instr_type.rst similarity index 100% rename from docs/reference/_autosummary/pecos.reps.pypmir.instr_type.rst rename to python/docs/reference/_autosummary/pecos.reps.pypmir.instr_type.rst diff --git a/docs/reference/_autosummary/pecos.reps.pypmir.list_types.rst b/python/docs/reference/_autosummary/pecos.reps.pypmir.list_types.rst similarity index 100% rename from docs/reference/_autosummary/pecos.reps.pypmir.list_types.rst rename to python/docs/reference/_autosummary/pecos.reps.pypmir.list_types.rst diff --git a/docs/reference/_autosummary/pecos.reps.pypmir.name_resolver.rst b/python/docs/reference/_autosummary/pecos.reps.pypmir.name_resolver.rst similarity index 100% rename from docs/reference/_autosummary/pecos.reps.pypmir.name_resolver.rst rename to python/docs/reference/_autosummary/pecos.reps.pypmir.name_resolver.rst diff --git a/docs/reference/_autosummary/pecos.reps.pypmir.op_types.rst b/python/docs/reference/_autosummary/pecos.reps.pypmir.op_types.rst similarity index 100% rename from docs/reference/_autosummary/pecos.reps.pypmir.op_types.rst rename to python/docs/reference/_autosummary/pecos.reps.pypmir.op_types.rst diff --git a/docs/reference/_autosummary/pecos.reps.pypmir.pypmir.rst b/python/docs/reference/_autosummary/pecos.reps.pypmir.pypmir.rst similarity index 100% rename from docs/reference/_autosummary/pecos.reps.pypmir.pypmir.rst rename to python/docs/reference/_autosummary/pecos.reps.pypmir.pypmir.rst diff --git a/docs/reference/_autosummary/pecos.reps.pypmir.rst b/python/docs/reference/_autosummary/pecos.reps.pypmir.rst similarity index 100% rename from docs/reference/_autosummary/pecos.reps.pypmir.rst rename to python/docs/reference/_autosummary/pecos.reps.pypmir.rst diff --git a/docs/reference/_autosummary/pecos.reps.pypmir.types.rst b/python/docs/reference/_autosummary/pecos.reps.pypmir.types.rst similarity index 100% rename from docs/reference/_autosummary/pecos.reps.pypmir.types.rst rename to python/docs/reference/_autosummary/pecos.reps.pypmir.types.rst diff --git a/docs/reference/_autosummary/pecos.reps.rst b/python/docs/reference/_autosummary/pecos.reps.rst similarity index 100% rename from docs/reference/_autosummary/pecos.reps.rst rename to python/docs/reference/_autosummary/pecos.reps.rst diff --git a/docs/reference/_autosummary/pecos.rst b/python/docs/reference/_autosummary/pecos.rst similarity index 100% rename from docs/reference/_autosummary/pecos.rst rename to python/docs/reference/_autosummary/pecos.rst diff --git a/docs/reference/_autosummary/pecos.simulators.cointoss.bindings.rst b/python/docs/reference/_autosummary/pecos.simulators.cointoss.bindings.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.cointoss.bindings.rst rename to python/docs/reference/_autosummary/pecos.simulators.cointoss.bindings.rst diff --git a/docs/reference/_autosummary/pecos.simulators.cointoss.gates.rst b/python/docs/reference/_autosummary/pecos.simulators.cointoss.gates.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.cointoss.gates.rst rename to python/docs/reference/_autosummary/pecos.simulators.cointoss.gates.rst diff --git a/docs/reference/_autosummary/pecos.simulators.cointoss.rst b/python/docs/reference/_autosummary/pecos.simulators.cointoss.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.cointoss.rst rename to python/docs/reference/_autosummary/pecos.simulators.cointoss.rst diff --git a/docs/reference/_autosummary/pecos.simulators.cointoss.state.rst b/python/docs/reference/_autosummary/pecos.simulators.cointoss.state.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.cointoss.state.rst rename to python/docs/reference/_autosummary/pecos.simulators.cointoss.state.rst diff --git a/docs/reference/_autosummary/pecos.simulators.compile_cython.rst b/python/docs/reference/_autosummary/pecos.simulators.compile_cython.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.compile_cython.rst rename to python/docs/reference/_autosummary/pecos.simulators.compile_cython.rst diff --git a/docs/reference/_autosummary/pecos.simulators.gate_syms.rst b/python/docs/reference/_autosummary/pecos.simulators.gate_syms.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.gate_syms.rst rename to python/docs/reference/_autosummary/pecos.simulators.gate_syms.rst diff --git a/docs/reference/_autosummary/pecos.simulators.parent_sim_classes.rst b/python/docs/reference/_autosummary/pecos.simulators.parent_sim_classes.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.parent_sim_classes.rst rename to python/docs/reference/_autosummary/pecos.simulators.parent_sim_classes.rst diff --git a/docs/reference/_autosummary/pecos.simulators.paulifaultprop.bindings.rst b/python/docs/reference/_autosummary/pecos.simulators.paulifaultprop.bindings.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.paulifaultprop.bindings.rst rename to python/docs/reference/_autosummary/pecos.simulators.paulifaultprop.bindings.rst diff --git a/docs/reference/_autosummary/pecos.simulators.paulifaultprop.gates_init.rst b/python/docs/reference/_autosummary/pecos.simulators.paulifaultprop.gates_init.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.paulifaultprop.gates_init.rst rename to python/docs/reference/_autosummary/pecos.simulators.paulifaultprop.gates_init.rst diff --git a/docs/reference/_autosummary/pecos.simulators.paulifaultprop.gates_meas.rst b/python/docs/reference/_autosummary/pecos.simulators.paulifaultprop.gates_meas.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.paulifaultprop.gates_meas.rst rename to python/docs/reference/_autosummary/pecos.simulators.paulifaultprop.gates_meas.rst diff --git a/docs/reference/_autosummary/pecos.simulators.paulifaultprop.gates_one_qubit.rst b/python/docs/reference/_autosummary/pecos.simulators.paulifaultprop.gates_one_qubit.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.paulifaultprop.gates_one_qubit.rst rename to python/docs/reference/_autosummary/pecos.simulators.paulifaultprop.gates_one_qubit.rst diff --git a/docs/reference/_autosummary/pecos.simulators.paulifaultprop.gates_two_qubit.rst b/python/docs/reference/_autosummary/pecos.simulators.paulifaultprop.gates_two_qubit.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.paulifaultprop.gates_two_qubit.rst rename to python/docs/reference/_autosummary/pecos.simulators.paulifaultprop.gates_two_qubit.rst diff --git a/docs/reference/_autosummary/pecos.simulators.paulifaultprop.logical_sign.rst b/python/docs/reference/_autosummary/pecos.simulators.paulifaultprop.logical_sign.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.paulifaultprop.logical_sign.rst rename to python/docs/reference/_autosummary/pecos.simulators.paulifaultprop.logical_sign.rst diff --git a/docs/reference/_autosummary/pecos.simulators.paulifaultprop.rst b/python/docs/reference/_autosummary/pecos.simulators.paulifaultprop.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.paulifaultprop.rst rename to python/docs/reference/_autosummary/pecos.simulators.paulifaultprop.rst diff --git a/docs/reference/_autosummary/pecos.simulators.paulifaultprop.state.rst b/python/docs/reference/_autosummary/pecos.simulators.paulifaultprop.state.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.paulifaultprop.state.rst rename to python/docs/reference/_autosummary/pecos.simulators.paulifaultprop.state.rst diff --git a/docs/reference/_autosummary/pecos.simulators.projectq.bindings.rst b/python/docs/reference/_autosummary/pecos.simulators.projectq.bindings.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.projectq.bindings.rst rename to python/docs/reference/_autosummary/pecos.simulators.projectq.bindings.rst diff --git a/docs/reference/_autosummary/pecos.simulators.projectq.gates_init.rst b/python/docs/reference/_autosummary/pecos.simulators.projectq.gates_init.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.projectq.gates_init.rst rename to python/docs/reference/_autosummary/pecos.simulators.projectq.gates_init.rst diff --git a/docs/reference/_autosummary/pecos.simulators.projectq.gates_meas.rst b/python/docs/reference/_autosummary/pecos.simulators.projectq.gates_meas.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.projectq.gates_meas.rst rename to python/docs/reference/_autosummary/pecos.simulators.projectq.gates_meas.rst diff --git a/docs/reference/_autosummary/pecos.simulators.projectq.gates_one_qubit.rst b/python/docs/reference/_autosummary/pecos.simulators.projectq.gates_one_qubit.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.projectq.gates_one_qubit.rst rename to python/docs/reference/_autosummary/pecos.simulators.projectq.gates_one_qubit.rst diff --git a/docs/reference/_autosummary/pecos.simulators.projectq.gates_two_qubit.rst b/python/docs/reference/_autosummary/pecos.simulators.projectq.gates_two_qubit.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.projectq.gates_two_qubit.rst rename to python/docs/reference/_autosummary/pecos.simulators.projectq.gates_two_qubit.rst diff --git a/docs/reference/_autosummary/pecos.simulators.projectq.helper.rst b/python/docs/reference/_autosummary/pecos.simulators.projectq.helper.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.projectq.helper.rst rename to python/docs/reference/_autosummary/pecos.simulators.projectq.helper.rst diff --git a/docs/reference/_autosummary/pecos.simulators.projectq.logical_sign.rst b/python/docs/reference/_autosummary/pecos.simulators.projectq.logical_sign.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.projectq.logical_sign.rst rename to python/docs/reference/_autosummary/pecos.simulators.projectq.logical_sign.rst diff --git a/docs/reference/_autosummary/pecos.simulators.projectq.rst b/python/docs/reference/_autosummary/pecos.simulators.projectq.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.projectq.rst rename to python/docs/reference/_autosummary/pecos.simulators.projectq.rst diff --git a/docs/reference/_autosummary/pecos.simulators.projectq.state.rst b/python/docs/reference/_autosummary/pecos.simulators.projectq.state.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.projectq.state.rst rename to python/docs/reference/_autosummary/pecos.simulators.projectq.state.rst diff --git a/docs/reference/_autosummary/pecos.simulators.quantum_simulator.rst b/python/docs/reference/_autosummary/pecos.simulators.quantum_simulator.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.quantum_simulator.rst rename to python/docs/reference/_autosummary/pecos.simulators.quantum_simulator.rst diff --git a/docs/reference/_autosummary/pecos.simulators.rst b/python/docs/reference/_autosummary/pecos.simulators.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.rst rename to python/docs/reference/_autosummary/pecos.simulators.rst diff --git a/docs/reference/_autosummary/pecos.simulators.sim_class_types.rst b/python/docs/reference/_autosummary/pecos.simulators.sim_class_types.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.sim_class_types.rst rename to python/docs/reference/_autosummary/pecos.simulators.sim_class_types.rst diff --git a/docs/reference/_autosummary/pecos.simulators.sparsesim.bindings.rst b/python/docs/reference/_autosummary/pecos.simulators.sparsesim.bindings.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.sparsesim.bindings.rst rename to python/docs/reference/_autosummary/pecos.simulators.sparsesim.bindings.rst diff --git a/docs/reference/_autosummary/pecos.simulators.sparsesim.cmd_init.rst b/python/docs/reference/_autosummary/pecos.simulators.sparsesim.cmd_init.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.sparsesim.cmd_init.rst rename to python/docs/reference/_autosummary/pecos.simulators.sparsesim.cmd_init.rst diff --git a/docs/reference/_autosummary/pecos.simulators.sparsesim.cmd_meas.rst b/python/docs/reference/_autosummary/pecos.simulators.sparsesim.cmd_meas.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.sparsesim.cmd_meas.rst rename to python/docs/reference/_autosummary/pecos.simulators.sparsesim.cmd_meas.rst diff --git a/docs/reference/_autosummary/pecos.simulators.sparsesim.cmd_one_qubit.rst b/python/docs/reference/_autosummary/pecos.simulators.sparsesim.cmd_one_qubit.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.sparsesim.cmd_one_qubit.rst rename to python/docs/reference/_autosummary/pecos.simulators.sparsesim.cmd_one_qubit.rst diff --git a/docs/reference/_autosummary/pecos.simulators.sparsesim.cmd_two_qubit.rst b/python/docs/reference/_autosummary/pecos.simulators.sparsesim.cmd_two_qubit.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.sparsesim.cmd_two_qubit.rst rename to python/docs/reference/_autosummary/pecos.simulators.sparsesim.cmd_two_qubit.rst diff --git a/docs/reference/_autosummary/pecos.simulators.sparsesim.logical_sign.rst b/python/docs/reference/_autosummary/pecos.simulators.sparsesim.logical_sign.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.sparsesim.logical_sign.rst rename to python/docs/reference/_autosummary/pecos.simulators.sparsesim.logical_sign.rst diff --git a/docs/reference/_autosummary/pecos.simulators.sparsesim.refactor.rst b/python/docs/reference/_autosummary/pecos.simulators.sparsesim.refactor.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.sparsesim.refactor.rst rename to python/docs/reference/_autosummary/pecos.simulators.sparsesim.refactor.rst diff --git a/docs/reference/_autosummary/pecos.simulators.sparsesim.rst b/python/docs/reference/_autosummary/pecos.simulators.sparsesim.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.sparsesim.rst rename to python/docs/reference/_autosummary/pecos.simulators.sparsesim.rst diff --git a/docs/reference/_autosummary/pecos.simulators.sparsesim.state.rst b/python/docs/reference/_autosummary/pecos.simulators.sparsesim.state.rst similarity index 100% rename from docs/reference/_autosummary/pecos.simulators.sparsesim.state.rst rename to python/docs/reference/_autosummary/pecos.simulators.sparsesim.state.rst diff --git a/docs/reference/_autosummary/pecos.slr.block.rst b/python/docs/reference/_autosummary/pecos.slr.block.rst similarity index 100% rename from docs/reference/_autosummary/pecos.slr.block.rst rename to python/docs/reference/_autosummary/pecos.slr.block.rst diff --git a/docs/reference/_autosummary/pecos.slr.cond_block.rst b/python/docs/reference/_autosummary/pecos.slr.cond_block.rst similarity index 100% rename from docs/reference/_autosummary/pecos.slr.cond_block.rst rename to python/docs/reference/_autosummary/pecos.slr.cond_block.rst diff --git a/docs/reference/_autosummary/pecos.slr.cops.rst b/python/docs/reference/_autosummary/pecos.slr.cops.rst similarity index 100% rename from docs/reference/_autosummary/pecos.slr.cops.rst rename to python/docs/reference/_autosummary/pecos.slr.cops.rst diff --git a/docs/reference/_autosummary/pecos.slr.fund.rst b/python/docs/reference/_autosummary/pecos.slr.fund.rst similarity index 100% rename from docs/reference/_autosummary/pecos.slr.fund.rst rename to python/docs/reference/_autosummary/pecos.slr.fund.rst diff --git a/docs/reference/_autosummary/pecos.slr.misc.rst b/python/docs/reference/_autosummary/pecos.slr.misc.rst similarity index 100% rename from docs/reference/_autosummary/pecos.slr.misc.rst rename to python/docs/reference/_autosummary/pecos.slr.misc.rst diff --git a/docs/reference/_autosummary/pecos.slr.rst b/python/docs/reference/_autosummary/pecos.slr.rst similarity index 100% rename from docs/reference/_autosummary/pecos.slr.rst rename to python/docs/reference/_autosummary/pecos.slr.rst diff --git a/docs/reference/_autosummary/pecos.slr.slr.rst b/python/docs/reference/_autosummary/pecos.slr.slr.rst similarity index 100% rename from docs/reference/_autosummary/pecos.slr.slr.rst rename to python/docs/reference/_autosummary/pecos.slr.slr.rst diff --git a/docs/reference/_autosummary/pecos.slr.std.phys.cliffords_tq.rst b/python/docs/reference/_autosummary/pecos.slr.std.phys.cliffords_tq.rst similarity index 100% rename from docs/reference/_autosummary/pecos.slr.std.phys.cliffords_tq.rst rename to python/docs/reference/_autosummary/pecos.slr.std.phys.cliffords_tq.rst diff --git a/docs/reference/_autosummary/pecos.slr.std.phys.face_rots.rst b/python/docs/reference/_autosummary/pecos.slr.std.phys.face_rots.rst similarity index 100% rename from docs/reference/_autosummary/pecos.slr.std.phys.face_rots.rst rename to python/docs/reference/_autosummary/pecos.slr.std.phys.face_rots.rst diff --git a/docs/reference/_autosummary/pecos.slr.std.phys.hadamards.rst b/python/docs/reference/_autosummary/pecos.slr.std.phys.hadamards.rst similarity index 100% rename from docs/reference/_autosummary/pecos.slr.std.phys.hadamards.rst rename to python/docs/reference/_autosummary/pecos.slr.std.phys.hadamards.rst diff --git a/docs/reference/_autosummary/pecos.slr.std.phys.metaclasses.rst b/python/docs/reference/_autosummary/pecos.slr.std.phys.metaclasses.rst similarity index 100% rename from docs/reference/_autosummary/pecos.slr.std.phys.metaclasses.rst rename to python/docs/reference/_autosummary/pecos.slr.std.phys.metaclasses.rst diff --git a/docs/reference/_autosummary/pecos.slr.std.phys.misc.rst b/python/docs/reference/_autosummary/pecos.slr.std.phys.misc.rst similarity index 100% rename from docs/reference/_autosummary/pecos.slr.std.phys.misc.rst rename to python/docs/reference/_autosummary/pecos.slr.std.phys.misc.rst diff --git a/docs/reference/_autosummary/pecos.slr.std.phys.paulis.rst b/python/docs/reference/_autosummary/pecos.slr.std.phys.paulis.rst similarity index 100% rename from docs/reference/_autosummary/pecos.slr.std.phys.paulis.rst rename to python/docs/reference/_autosummary/pecos.slr.std.phys.paulis.rst diff --git a/docs/reference/_autosummary/pecos.slr.std.phys.projective.rst b/python/docs/reference/_autosummary/pecos.slr.std.phys.projective.rst similarity index 100% rename from docs/reference/_autosummary/pecos.slr.std.phys.projective.rst rename to python/docs/reference/_autosummary/pecos.slr.std.phys.projective.rst diff --git a/docs/reference/_autosummary/pecos.slr.std.phys.rots.rst b/python/docs/reference/_autosummary/pecos.slr.std.phys.rots.rst similarity index 100% rename from docs/reference/_autosummary/pecos.slr.std.phys.rots.rst rename to python/docs/reference/_autosummary/pecos.slr.std.phys.rots.rst diff --git a/docs/reference/_autosummary/pecos.slr.std.phys.rst b/python/docs/reference/_autosummary/pecos.slr.std.phys.rst similarity index 100% rename from docs/reference/_autosummary/pecos.slr.std.phys.rst rename to python/docs/reference/_autosummary/pecos.slr.std.phys.rst diff --git a/docs/reference/_autosummary/pecos.slr.std.phys.sqrt_paulis.rst b/python/docs/reference/_autosummary/pecos.slr.std.phys.sqrt_paulis.rst similarity index 100% rename from docs/reference/_autosummary/pecos.slr.std.phys.sqrt_paulis.rst rename to python/docs/reference/_autosummary/pecos.slr.std.phys.sqrt_paulis.rst diff --git a/docs/reference/_autosummary/pecos.slr.std.rst b/python/docs/reference/_autosummary/pecos.slr.std.rst similarity index 100% rename from docs/reference/_autosummary/pecos.slr.std.rst rename to python/docs/reference/_autosummary/pecos.slr.std.rst diff --git a/docs/reference/_autosummary/pecos.slr.util.rst b/python/docs/reference/_autosummary/pecos.slr.util.rst similarity index 100% rename from docs/reference/_autosummary/pecos.slr.util.rst rename to python/docs/reference/_autosummary/pecos.slr.util.rst diff --git a/docs/reference/_autosummary/pecos.slr.vars.rst b/python/docs/reference/_autosummary/pecos.slr.vars.rst similarity index 100% rename from docs/reference/_autosummary/pecos.slr.vars.rst rename to python/docs/reference/_autosummary/pecos.slr.vars.rst diff --git a/docs/reference/_autosummary/pecos.tools.fault_tolerance_checking.rst b/python/docs/reference/_autosummary/pecos.tools.fault_tolerance_checking.rst similarity index 100% rename from docs/reference/_autosummary/pecos.tools.fault_tolerance_checking.rst rename to python/docs/reference/_autosummary/pecos.tools.fault_tolerance_checking.rst diff --git a/docs/reference/_autosummary/pecos.tools.fault_tolerance_checks.rst b/python/docs/reference/_autosummary/pecos.tools.fault_tolerance_checks.rst similarity index 100% rename from docs/reference/_autosummary/pecos.tools.fault_tolerance_checks.rst rename to python/docs/reference/_autosummary/pecos.tools.fault_tolerance_checks.rst diff --git a/docs/reference/_autosummary/pecos.tools.find_cliffs.rst b/python/docs/reference/_autosummary/pecos.tools.find_cliffs.rst similarity index 100% rename from docs/reference/_autosummary/pecos.tools.find_cliffs.rst rename to python/docs/reference/_autosummary/pecos.tools.find_cliffs.rst diff --git a/docs/reference/_autosummary/pecos.tools.logic_circuit_speed.rst b/python/docs/reference/_autosummary/pecos.tools.logic_circuit_speed.rst similarity index 100% rename from docs/reference/_autosummary/pecos.tools.logic_circuit_speed.rst rename to python/docs/reference/_autosummary/pecos.tools.logic_circuit_speed.rst diff --git a/docs/reference/_autosummary/pecos.tools.pseudo_threshold_tools.rst b/python/docs/reference/_autosummary/pecos.tools.pseudo_threshold_tools.rst similarity index 100% rename from docs/reference/_autosummary/pecos.tools.pseudo_threshold_tools.rst rename to python/docs/reference/_autosummary/pecos.tools.pseudo_threshold_tools.rst diff --git a/docs/reference/_autosummary/pecos.tools.random_circuit_speed.rst b/python/docs/reference/_autosummary/pecos.tools.random_circuit_speed.rst similarity index 100% rename from docs/reference/_autosummary/pecos.tools.random_circuit_speed.rst rename to python/docs/reference/_autosummary/pecos.tools.random_circuit_speed.rst diff --git a/docs/reference/_autosummary/pecos.tools.rst b/python/docs/reference/_autosummary/pecos.tools.rst similarity index 100% rename from docs/reference/_autosummary/pecos.tools.rst rename to python/docs/reference/_autosummary/pecos.tools.rst diff --git a/docs/reference/_autosummary/pecos.tools.stabilizer_verification.rst b/python/docs/reference/_autosummary/pecos.tools.stabilizer_verification.rst similarity index 100% rename from docs/reference/_autosummary/pecos.tools.stabilizer_verification.rst rename to python/docs/reference/_autosummary/pecos.tools.stabilizer_verification.rst diff --git a/docs/reference/_autosummary/pecos.tools.threshold_tools.rst b/python/docs/reference/_autosummary/pecos.tools.threshold_tools.rst similarity index 100% rename from docs/reference/_autosummary/pecos.tools.threshold_tools.rst rename to python/docs/reference/_autosummary/pecos.tools.threshold_tools.rst diff --git a/docs/reference/_autosummary/pecos.tools.tool_anticommute.rst b/python/docs/reference/_autosummary/pecos.tools.tool_anticommute.rst similarity index 100% rename from docs/reference/_autosummary/pecos.tools.tool_anticommute.rst rename to python/docs/reference/_autosummary/pecos.tools.tool_anticommute.rst diff --git a/docs/reference/_autosummary/pecos.tools.tool_collection.rst b/python/docs/reference/_autosummary/pecos.tools.tool_collection.rst similarity index 100% rename from docs/reference/_autosummary/pecos.tools.tool_collection.rst rename to python/docs/reference/_autosummary/pecos.tools.tool_collection.rst diff --git a/docs/reference/_autosummary/pecos.typed_list.rst b/python/docs/reference/_autosummary/pecos.typed_list.rst similarity index 100% rename from docs/reference/_autosummary/pecos.typed_list.rst rename to python/docs/reference/_autosummary/pecos.typed_list.rst diff --git a/docs/reference/index.rst b/python/docs/reference/index.rst similarity index 100% rename from docs/reference/index.rst rename to python/docs/reference/index.rst diff --git a/docs/requirements.txt b/python/docs/requirements.txt similarity index 52% rename from docs/requirements.txt rename to python/docs/requirements.txt index 474478ce..6473b091 100644 --- a/docs/requirements.txt +++ b/python/docs/requirements.txt @@ -1,7 +1,7 @@ -matplotlib==3.8.0 -networkx==2.8.8 -numpy==1.26.0 -scipy==1.11.3 +matplotlib==3.9.2 +networkx==3.3 +numpy==1.26.4 +scipy==1.14.1 sphinx~=7.2.4 pydata-sphinx-theme~=0.14.1 diff --git a/docs/todo_list.rst b/python/docs/todo_list.rst similarity index 100% rename from docs/todo_list.rst rename to python/docs/todo_list.rst diff --git a/python/pecos-rslib/LICENSE b/python/pecos-rslib/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/python/pecos-rslib/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/python/pecos-rslib/README.md b/python/pecos-rslib/README.md new file mode 100644 index 00000000..67d05d12 --- /dev/null +++ b/python/pecos-rslib/README.md @@ -0,0 +1,3 @@ +# pecos-rslib + +`pecos-rslib` provides Rust extensions for the Python version of PECOS. diff --git a/python/pecos-rslib/pyproject.toml b/python/pecos-rslib/pyproject.toml new file mode 100644 index 00000000..c1b8b215 --- /dev/null +++ b/python/pecos-rslib/pyproject.toml @@ -0,0 +1,23 @@ +[project] +name = "pecos-rslib" +version = "0.6.0.dev6" +description = "Rust libary extensions for Python PECOS." +authors = [ + {name = "The PECOS Developers"}, +] +maintainers =[ + {name = "Ciaran Ryan-Anderson", email = "ciaranra@gmail.com"}, +] +dependencies = [] +readme = "README.md" +requires-python = ">= 3.8" + +[build-system] +requires = ["maturin>=1.2,<2.0"] +build-backend = "maturin" + +[tool.maturin] +features = ["pyo3/extension-module"] +python-source = "src" +module-name = "pecos_rslib._pecos_rslib" +manifest-path = "../../crates/pecos-python/Cargo.toml" diff --git a/python/pecos/simulators/cuquantum_old/cuconn.py b/python/pecos-rslib/src/pecos_rslib/__init__.py similarity index 63% rename from python/pecos/simulators/cuquantum_old/cuconn.py rename to python/pecos-rslib/src/pecos_rslib/__init__.py index b0a6ef37..b732f0c3 100644 --- a/python/pecos/simulators/cuquantum_old/cuconn.py +++ b/python/pecos-rslib/src/pecos_rslib/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022 The PECOS Developers +# Copyright 2024 The PECOS Developers # # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with # the License.You may obtain a copy of the License at @@ -9,9 +9,16 @@ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the # specific language governing permissions and limitations under the License. -import os -import sys +# ruff: noqa: TID252 +from importlib.metadata import PackageNotFoundError, version -cupath = os.path.abspath(os.path.join(os.path.dirname(__file__), "cuquantum_wrapper", "build", "bin")) -sys.path.append(cupath) -import cuquantum_wrapper as cq +from pecos_rslib.rssparse_sim import SparseSimRs + +try: + __version__ = version("pecos-rslib") +except PackageNotFoundError: + __version__ = "0.0.0" + +__all__ = [ + "SparseSimRs", +] diff --git a/python/pecos-rslib/src/pecos_rslib/rssparse_sim.py b/python/pecos-rslib/src/pecos_rslib/rssparse_sim.py new file mode 100644 index 00000000..5c8ce2ab --- /dev/null +++ b/python/pecos-rslib/src/pecos_rslib/rssparse_sim.py @@ -0,0 +1,281 @@ +# Copyright 2024 The PECOS Developers +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with +# the License.You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. + +# ruff: noqa: SLF001 + +from __future__ import annotations + +from typing import Any + +from pecos_rslib._pecos_rslib import SparseSim as RustSparseSim + + +class SparseSimRs: + def __init__(self, num_qubits: int): + self._sim = RustSparseSim(num_qubits) + self.num_qubits = num_qubits + self.bindings = dict(gate_dict) + + def reset(self): + self._sim.reset() + return self + + def run_gate( + self, + symbol: str, + locations: set[int] | set[tuple[int, ...]], + **params: Any, + ) -> dict[int, int]: + output = {} + + if params.get("simulate_gate", True) and locations: + for location in locations: + if isinstance(location, int): + location = (location,) + + if params.get("angles") and len(params["angles"]) == 1: + params.update({"angle": params["angles"][0]}) + elif "angle" in params and "angles" not in params: + params["angles"] = (params["angle"],) + + if symbol in self.bindings: + results = self.bindings[symbol](self, location, **params) + else: + results = self._sim.run_gate(symbol, location, params) + + if results: + output.update(results) + + return output + + def run_circuit( + self, + circuit, + removed_locations: set[int] | None = None, + ) -> dict[int, int]: + if removed_locations is None: + removed_locations = set() + + results = {} + for symbol, locations, params in circuit.items(): + gate_results = self.run_gate( + symbol, + locations - removed_locations, + **params, + ) + results.update(gate_results) + + return results + + def add_faults(self, circuit, removed_locations: set[int] | None = None) -> None: + self.run_circuit(circuit, removed_locations) + + # def print_stabs(self, *, verbose: bool = True, print_y: bool = True, print_destabs: bool = False) -> list[str]: + # return self._sim.print_stabs(verbose, print_y, print_destabs) + + @property + def stabs(self): + return TableauWrapper(self._sim, is_stab=True) + + @property + def destabs(self): + return TableauWrapper(self._sim, is_stab=False) + + def print_stabs( + self, + *, + verbose: bool = True, + print_y: bool = True, + print_destabs: bool = False, + ): + stabs = self._sim.stab_tableau() + if print_destabs: + destabs = self._sim.destab_tableau() + if verbose: + print("Stabilizers:") + print(stabs) + print("Destabilizers:") + print(destabs) + return stabs, destabs + else: + if verbose: + print("Stabilizers:") + print(stabs) + return stabs + + def logical_sign(self, logical_op): + # This method needs to be implemented based on the Python version + # It might require additional Rust functions to be exposed + msg = "logical_sign method not implemented yet" + raise NotImplementedError(msg) + + def refactor(self, xs, zs, choose=None, prefer=None, protected=None): + # This method needs to be implemented based on the Python version + # It might require additional Rust functions to be exposed + msg = "refactor method not implemented yet" + raise NotImplementedError(msg) + + def find_stab(self, xs, zs): + # This method needs to be implemented based on the Python version + # It might require additional Rust functions to be exposed + msg = "find_stab method not implemented yet" + raise NotImplementedError(msg) + + def copy(self): + # This method needs to be implemented + # It might require an additional Rust function to be exposed + msg = "copy method not implemented yet" + raise NotImplementedError(msg) + + +class TableauWrapper: + def __init__(self, sim, *, is_stab: bool): + self._sim = sim + self._is_stab = is_stab + + def print_tableau(self, *, verbose: bool = False) -> list[str]: + if self._is_stab: + tableau = self._sim.stab_tableau() + else: + tableau = self._sim.destab_tableau() + + lines = tableau.strip().split("\n") + adjusted_lines = [ + adjust_tableau_string(line, is_stab=self._is_stab) for line in lines + ] + + if verbose: + for line in adjusted_lines: + print(line) + + return adjusted_lines + + +def adjust_tableau_string(line: str, *, is_stab: bool) -> str: + """ + Adjust the tableau string to ensure the sign part always takes up two spaces + and convert 'Y' to 'W'. For destabilizers, always use two spaces for the sign. + + Args: + line (str): A single line from the tableau string. + is_stab (bool): True if this is a stabilizer, False if destabilizer. + + Returns: + str: The adjusted line with proper spacing for signs and 'W' instead of 'Y'. + """ + if is_stab: + if line.startswith("+i"): + adjusted = " i" + line[2:] + elif line.startswith("-i"): + adjusted = "-i" + line[2:] + elif line.startswith("+"): + adjusted = " " + line[1:] + elif line.startswith("-"): + adjusted = " -" + line[1:] + else: + adjusted = " " + line # Default case, shouldn't happen with correct input + else: + # For destabilizers, always use two spaces for the sign + adjusted = " " + line[1:] + + return adjusted.replace("Y", "W") + + +# Define the gate dictionary +gate_dict = { + "I": lambda sim, q, **params: None, + "X": lambda sim, q, **params: sim._sim.run_gate("X", q, params), + "Y": lambda sim, q, **params: sim._sim.run_gate("Y", q, params), + "Z": lambda sim, q, **params: sim._sim.run_gate("Z", q, params), + "SX": lambda sim, q, **params: sim._sim.run_gate("SX", q, params), + "SXdg": lambda sim, q, **params: sim._sim.run_gate("SXdg", q, params), + "SY": lambda sim, q, **params: sim._sim.run_gate("SY", q, params), + "SYdg": lambda sim, q, **params: sim._sim.run_gate("SYdg", q, params), + "SZ": lambda sim, q, **params: sim._sim.run_gate("SZ", q, params), + "SZdg": lambda sim, q, **params: sim._sim.run_gate("SZdg", q, params), + "H": lambda sim, q, **params: sim._sim.run_gate("H", q, params), + "H2": lambda sim, q, **params: sim._sim.run_gate("H2", q, params), + "H3": lambda sim, q, **params: sim._sim.run_gate("H3", q, params), + "H4": lambda sim, q, **params: sim._sim.run_gate("H4", q, params), + "H5": lambda sim, q, **params: sim._sim.run_gate("H5", q, params), + "H6": lambda sim, q, **params: sim._sim.run_gate("H6", q, params), + "F": lambda sim, q, **params: sim._sim.run_gate("F", q, params), + "Fdg": lambda sim, q, **params: sim._sim.run_gate("Fdg", q, params), + "F2": lambda sim, q, **params: sim._sim.run_gate("F2", q, params), + "F2dg": lambda sim, q, **params: sim._sim.run_gate("F2dg", q, params), + "F3": lambda sim, q, **params: sim._sim.run_gate("F3", q, params), + "F3dg": lambda sim, q, **params: sim._sim.run_gate("F3dg", q, params), + "F4": lambda sim, q, **params: sim._sim.run_gate("F4", q, params), + "F4dg": lambda sim, q, **params: sim._sim.run_gate("F4dg", q, params), + "II": lambda sim, qs, **params: None, + "CX": lambda sim, qs, **params: sim._sim.run_gate("CX", qs, params), + "CNOT": lambda sim, qs, **params: sim._sim.run_gate("CX", qs, params), + "CY": lambda sim, qs, **params: sim._sim.run_gate("CY", qs, params), + "CZ": lambda sim, qs, **params: sim._sim.run_gate("CZ", qs, params), + "SXX": lambda sim, qs, **params: sim._sim.run_gate("SXX", qs, params), + "SXXdg": lambda sim, qs, **params: sim._sim.run_gate("SXXdg", qs, params), + "SYY": lambda sim, qs, **params: sim._sim.run_gate("SYY", qs, params), + "SYYdg": lambda sim, qs, **params: sim._sim.run_gate("SYYdg", qs, params), + "SZZ": lambda sim, qs, **params: sim._sim.run_gate("SZZ", qs, params), + "SZZdg": lambda sim, qs, **params: sim._sim.run_gate("SZZdg", qs, params), + "SWAP": lambda sim, qs, **params: sim._sim.run_gate("SWAP", qs, params), + "G": lambda sim, qs, **params: sim._sim.run_gate("G2", qs, params), + "G2": lambda sim, qs, **params: sim._sim.run_gate("G2", qs, params), + "MZ": lambda sim, q, **params: sim._sim.run_gate("MZ", q, params), + "MX": lambda sim, q, **params: sim._sim.run_gate("MX", q, params), + "MY": lambda sim, q, **params: sim._sim.run_gate("MY", q, params), + "PZ": lambda sim, q, **params: sim._sim.run_gate("PZ", q, params), + "PX": lambda sim, q, **params: sim._sim.run_gate("PX", q, params), + "PY": lambda sim, q, **params: sim._sim.run_gate("PY", q, params), + "PnZ": lambda sim, q, **params: sim._sim.run_gate("PnZ", q, params), + "Init +Z": lambda sim, q, **params: sim._sim.run_gate("PZ", q, params), + "Init -Z": lambda sim, q, **params: sim._sim.run_gate("PnZ", q, params), + "Init +X": lambda sim, q, **params: sim._sim.run_gate("PX", q, params), + "Init -X": lambda sim, q, **params: sim._sim.run_gate("PnX", q, params), + "Init +Y": lambda sim, q, **params: sim._sim.run_gate("PY", q, params), + "Init -Y": lambda sim, q, **params: sim._sim.run_gate("PnY", q, params), + "init |0>": lambda sim, q, **params: sim._sim.run_gate("PZ", q, params), + "init |1>": lambda sim, q, **params: sim._sim.run_gate("PnZ", q, params), + "init |+>": lambda sim, q, **params: sim._sim.run_gate("PX", q, params), + "init |->": lambda sim, q, **params: sim._sim.run_gate("PnX", q, params), + "init |+i>": lambda sim, q, **params: sim._sim.run_gate("PY", q, params), + "init |-i>": lambda sim, q, **params: sim._sim.run_gate("PnY", q, params), + "leak": lambda sim, q, **params: sim._sim.run_gate("PZ", q, params), + "leak |0>": lambda sim, q, **params: sim._sim.run_gate("PZ", q, params), + "leak |1>": lambda sim, q, **params: sim._sim.run_gate("PnZ", q, params), + "unleak |0>": lambda sim, q, **params: sim._sim.run_gate("PZ", q, params), + "unleak |1>": lambda sim, q, **params: sim._sim.run_gate("PnZ", q, params), + "Measure +X": lambda sim, q, **params: sim._sim.run_gate("MX", q, params), + "Measure +Y": lambda sim, q, **params: sim._sim.run_gate("MY", q, params), + "Measure +Z": lambda sim, q, **params: sim._sim.run_gate("MZ", q, params), + "Q": lambda sim, q, **params: sim._sim.run_gate("SX", q, params), + "Qd": lambda sim, q, **params: sim._sim.run_gate("SXdg", q, params), + "R": lambda sim, q, **params: sim._sim.run_gate("SY", q, params), + "Rd": lambda sim, q, **params: sim._sim.run_gate("SYdg", q, params), + "S": lambda sim, q, **params: sim._sim.run_gate("SZ", q, params), + "Sd": lambda sim, q, **params: sim._sim.run_gate("SZdg", q, params), + "H1": lambda sim, q, **params: sim._sim.run_gate("H1", q, params), + "F1": lambda sim, q, **params: sim._sim.run_gate("F", q, params), + "F1d": lambda sim, q, **params: sim._sim.run_gate("Fdg", q, params), + "F2d": lambda sim, q, **params: sim._sim.run_gate("F2dg", q, params), + "F3d": lambda sim, q, **params: sim._sim.run_gate("F3dg", q, params), + "F4d": lambda sim, q, **params: sim._sim.run_gate("F4dg", q, params), + "SqrtXX": lambda sim, qs, **params: sim._sim.run_gate("SXX", qs, params), + "SqrtYY": lambda sim, qs, **params: sim._sim.run_gate("SYY", qs, params), + "SqrtZZ": lambda sim, qs, **params: sim._sim.run_gate("SZZ", qs, params), + "measure Z": lambda sim, q, **params: sim._sim.run_gate("MZ", q, params), + "MZForced": lambda sim, q, **params: sim._sim.run_gate("MZForced", q, params), + "PZForced": lambda sim, q, **params: sim._sim.run_gate("PZForced", q, params), +} + +# "force output": qmeas.force_output, + +__all__ = ["SparseSimRs", "gate_dict"] diff --git a/python/pecos/foreign_objects/wasm_execution_timer_thread.py b/python/pecos/foreign_objects/wasm_execution_timer_thread.py deleted file mode 100644 index 3749c571..00000000 --- a/python/pecos/foreign_objects/wasm_execution_timer_thread.py +++ /dev/null @@ -1,16 +0,0 @@ -from threading import Event, Thread - -# These values multiplied should equal the intended maximum execution time -WASM_EXECUTION_TICK_LENGTH_S: float = 0.25 -WASM_EXECUTION_MAX_TICKS: int = 4 - - -class WasmExecutionTimerThread(Thread): - def __init__(self, stop_event: Event, func) -> None: - Thread.__init__(self, daemon=True) - self._stop_event = stop_event - self._func = func - - def run(self): - while not self._stop_event.wait(WASM_EXECUTION_TICK_LENGTH_S): - self._func() diff --git a/python/pecos/reps/pypmir/instr_type.py b/python/pecos/reps/pypmir/instr_type.py deleted file mode 100644 index 82e251c6..00000000 --- a/python/pecos/reps/pypmir/instr_type.py +++ /dev/null @@ -1,8 +0,0 @@ -from __future__ import annotations - - -class Instr: - """Base type for all PyMIR instructions including QOps, Blocks, MOps, etc.""" - - def __init__(self, metadata: dict | None = None) -> None: - self.metadata = metadata diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/.gitignore b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/.gitignore deleted file mode 100644 index 551304c9..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/.gitignore +++ /dev/null @@ -1,12 +0,0 @@ -build - -# Python files -*.pyc - -# Temporary folders -.cache -temp -tmp - -# vim files -*.swp diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/CMakeLists.txt b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/CMakeLists.txt deleted file mode 100644 index db98cbed..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/CMakeLists.txt +++ /dev/null @@ -1,114 +0,0 @@ -# Copyright 2022 The PECOS Developers -# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -# the License.You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. - -# Initial author: Tyson Lawrence - -# cmake_minimum_required(VERSION 3.12...3.17) -cmake_minimum_required(VERSION 3.13.0 FATAL_ERROR) -if(CMAKE_VERSION VERSION_GREATER 3.18) - cmake_policy(SET CMP0104 OLD) - set(CUDA_ARCHITECTURES FALSE) -endif() - -project(cuquantum_wrapper - VERSION 0.0.22 - DESCRIPTION "Abstraction layer (wrapper) for cuQuantum" - LANGUAGES C CXX CUDA) - -# -# Options -# -option(DEBUG_BUILD "Build with debugging" OFF) -option(BUILD_TESTS "Build tests" ON) -option(BUILD_EXAMPLES "Build examples" ON) -option(USE_WARNING_FLAGS "Enable warnings" OFF) -option(USE_ERROR_FLAGS "Enable errors" OFF) -option(USE_DEV_FLAGS "Use some flags to disable some warnings during development" OFF) - -# -# CUDA -# -find_package(CUDA 10.1 REQUIRED) - -if (NOT CUSTATEVEC_ROOT) - set(CUSTATEVEC_ROOT ${CUDA_TOOLKIT_ROOT_DIR}) -endif() - -# -# Print build config -# -message(STATUS " ") -message(STATUS " Project: " ${PROJECT_NAME}) -message(STATUS "Building version: " ${PROJECT_VERSION}) -message(STATUS " System Name: " ${CMAKE_SYSTEM_NAME}) -message(STATUS "System Processor: " ${CMAKE_SYSTEM_PROCESSOR}) -message(STATUS " ") - -# -# Put all build targets in the same directory for simplicity -# -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) - -# -# Set global language standards project wide -# -set(CMAKE_C_STANDARD 11) -set(CMAKE_C_STANDARD_REQUIRED ON) -set(CMAKE_C_EXTENSIONS OFF) - -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) - -# Global CUDA CXX flags/options -set(CUDA_HOST_COMPILER ${CMAKE_CXX_COMPILER}) -set(CMAKE_CUDA_STANDARD 11) -set(CMAKE_CUDA_STANDARD_REQUIRED ON) -set(CMAKE_CUDA_EXTENSIONS OFF) - - -# -# Create lists of possible build flags to use in the project. These -# are not necessarily used -# -# TODO FIXME Not all compiler options all work with nvcc -# set(WARNING_FLAGS -Wall -pedantic) -# set(ERROR_FLAGS -Werror -pedantic-errors) -# set(DEV_FLAGS -g -# -Wno-unused-variable -# -Wno-unused-but-set-variable -# -Wno-unused-function -# -Wno-attributes) - -# if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") -# set(CLANG_FLAGS -Wno-unused-private-field -# -Wno-unknown-warning-option) -# endif() - -add_subdirectory(extern/pybind11) - -# -# Main source directories in project -# -add_subdirectory(src) - -if (BUILD_EXAMPLES) - add_subdirectory(examples) -endif () - -# -# Testing -# -if (BUILD_TESTS) - enable_testing() - add_subdirectory(test) -endif () diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/README.md b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/README.md deleted file mode 100644 index 44293a42..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# cuQuantum Wrapper - -## Overview - -**cuquantum_wrapper** is an small library that is intended to serve as an abstraction layer around Nvidia's **cuQuantum** state vector and tensor libraries. At present, only the state vector library is supported. - -The library uses the **Eigen** linear algebra library. - -## Use - -1. Clone the repository -2. Setup project - * `$ cd cuquantum_wrapper` - * `$ source setup_build.sh` or `$ mkdir build && cd build && cmake ..` -3. Build - * `$ make` -4. Run test - * `$ make test` or `$ ctest --verbose`. The latter provides more verbose output. diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/__init__.py b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/__init__.py deleted file mode 100644 index 3c7f0bf4..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright 2023 The PECOS Developers -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -# the License.You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. - -from pecos.simulators.cointoss import bindings -from pecos.simulators.cointoss.state import CoinToss diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/examples/CMakeLists.txt b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/examples/CMakeLists.txt deleted file mode 100644 index ecfac42b..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/examples/CMakeLists.txt +++ /dev/null @@ -1,39 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -# the License.You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# -# Initial author: Tyson Lawrence -# -# Set include directories -# -set(EX_INCLUDE_DIRS - ${PROJECT_SOURCE_DIR}/extern/argparse - ) -# -# Helper function to simplify adding an example. The example name -# should correspond the example file name. -# e.g. example1 goes with example1.cpp -# -function(add_example EXAMPLE_NAME) - # Get the main test source file and append it to the list of extra sources - set(EXAMPLE_SOURCE ${EXAMPLE_NAME}.cpp) - # Create the example program - add_executable(${EXAMPLE_NAME} ${EXAMPLE_SOURCE}) - target_include_directories(${EXAMPLE_NAME} PRIVATE ${EX_INCLUDE_DIRS}) - # Link the the wrapper library - target_include_directories(${EXAMPLE_NAME} PRIVATE /usr/include/eigen3/) - target_include_directories(${EXAMPLE_NAME} PRIVATE /usr/include/eigen3/Eigen/) - target_include_directories(${EXAMPLE_NAME} PRIVATE /usr/include/eigen3/Eigen/src) - target_link_libraries(${EXAMPLE_NAME} PRIVATE custatevec_wrapper) -endfunction() - -# -# The examples -# -add_example(bell_state) -add_example(quantum_volume) diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/examples/bell_state.cpp b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/examples/bell_state.cpp deleted file mode 100644 index c0fe7d69..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/examples/bell_state.cpp +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2022 The PECOS developers -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -// the License.You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Initial author: Tyson Lawrence - -#include - -#include "custatevec_workspace.hpp" -#include "gate.hpp" -#include "state_vector.hpp" -#include "utils.hpp" -#include "quantum_volume.hpp" -#include "version.h" - -#include "Eigen/KroneckerProduct" - -using Eigen::KroneckerProduct; - -// macro to print simple things to stdout -#define PRINT(x) std::cout << x << std::endl; -#define ELAPSED(timer) std::cout << "Elapsed: " << timer.elapsed() << " s" << std::endl; - -void bell_state(double randnum=0) -{ - // Initialize the workspace - CuStatevecWorkspace workspace; - - StateVector sv = create_zero_state_vector(2); - - PRINT("Initial State"); - sv.print(); - - sv.copy_to_device(); - - // Create and apply the gates - Gate h = Hadamard(); - Gate cnot = CNOT(); - - h.copy_to_device(); - cnot.copy_to_device(); - - h.apply(sv, workspace, {}, {0}); - cnot.apply(sv, workspace, {0}, {1}); - - sv.read_from_device(); - - PRINT("Bell state"); - sv.print(); - - BasisBits basis_bits = {0,1}; - int parity0 = -1; - int parity1 = -1; - sv.measure(workspace, parity0, {0}, randnum); - sv.measure(workspace, parity1, {1}, randnum); - - sv.read_from_device(); - - PRINT("Measurement"); - std::cout << "Random Number: " << randnum << std::endl; - std::cout << " Bit 0: " << parity0 << std::endl; - std::cout << " Bit 1: " << parity1 << std::endl; - PRINT("Final State Vector"); - sv.print(); -} - - -int main(int argc, char *argv[]) -{ - // bell_state(); - - double randnum = 0; - if (argc > 1) - randnum = std::atof(argv[1]); - - if (randnum < 0) - randnum = 0; - - if (randnum >= 1) - randnum = 0.9999; - - bell_state(randnum); - - return 0; -} diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/examples/quantum_volume.cpp b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/examples/quantum_volume.cpp deleted file mode 100644 index 8eca1de2..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/examples/quantum_volume.cpp +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright 2022 The PECOS developers -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -// the License.You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Initial author: Tyson Lawrence - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "argparse.hpp" - -#include "custatevec_workspace.hpp" -#include "gate.hpp" -#include "state_vector.hpp" -#include "utils.hpp" -#include "quantum_volume.hpp" -#include "version.h" - -/* - * - * Run a quantum volume simulation on the device - * - */ -void run_quantum_volume(size_t num_qubits=2, size_t num_shots=1, bool verbose=true) -{ - Timer timer; - timer.tic(); - - // Initialize the workspace - CuStatevecWorkspace ws; - - // Initialize the state vector to |000...0> - StateVector sv(num_qubits); - sv.init_on_device(); - - // Create, apply, and free the QV circuit - QuantumVolume qv(num_qubits); - qv.copy_to_device(); - qv.apply(sv,ws); - qv.free_on_device(); - - // DISABLING FOR NOW - // Make measurements for the shots - // constexpr bool collapse = false; - // double randnum = rand_in_range(0.0, 1.0); - // std::vector results(num_shots); - // std::vector times(num_shots); - // BasisBits bit_string(num_qubits, -1); - // for (size_t shot = 0; shot < num_shots; shot++) { - // randnum = rand_in_range(0.0, 1.0); - // sv.batch_measure_all(ws, bit_string, randnum, collapse); - // results[shot] = compress_bit_string(bit_string); - // } - - std::vector probs = sv.get_probabilities(ws); - - sv.read_from_device(); - sv.free_on_device(); - - double total_time = timer.elapsed(); - - // Optionally, print some stuff to stdout - std::cout << " num_qubits: " << num_qubits << std::endl; - std::cout << " num_shots: " << num_shots << std::endl; - std::cout << " elapsed: " << total_time << " s" << std::endl; - if (verbose) { - std::cout << "probabilities: " << std::endl; - for (auto p : probs) - std::cout << p << std::endl; - } - - // DISABLING FOR NOW - // Write the results to file - // std::ofstream f; - // std::string fname = "results_" + std::to_string(num_qubits) + ".txt"; - // f.open (fname); - // f << num_qubits << "\n"; - // for (auto result : results) - // f << result << "\n"; - // f.close(); -} - - -/* - * - * Main - * - */ -int main(int argc, char *argv[]) -{ - argparse::ArgumentParser args(argv[0], "0", argparse::default_arguments::help); - - args.add_argument("-n", "--num-qubits") - .default_value(10) - .scan<'i', int>() - .help("Number of qubits (should be even)"); - - args.add_argument("-s", "--num-shots") - .default_value(3) - .scan<'i', int>() - .help("Number of shots (iterations) to run the circuit"); - - args.add_argument("-v", "--verbose") - .default_value(false) - .implicit_value(true) - .help("Verbose output"); - - try { - args.parse_args(argc, argv); - } - catch (const std::runtime_error& err) { - std::cerr << err.what() << std::endl; - std::cerr << args; - std::exit(1); - } - - // Get command line arguments - size_t num_qubits = args.get("num-qubits"); - num_qubits = is_odd(num_qubits) ? num_qubits++ : num_qubits; - - size_t num_shots = args.get("num-shots"); - num_shots = (num_shots < 1) ? 1 : num_shots; - - bool verbose = args.get("verbose"); - - run_quantum_volume(num_qubits, num_shots, verbose); - - return 0; -} diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/setup_build.sh b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/setup_build.sh deleted file mode 100644 index 0a2afb48..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/setup_build.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/bash - -# -# Copyright 2022 The PECOS Developers -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -# the License.You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -# -# Initial author: Tyson Lawrence -# - -# -# This script needs to be sourced from within the -# base project directory -# - - -RAN_NAME=$( basename ${0#-} ) #- needed if sourced no path -SCRIPT_NAME=$( basename ${BASH_SOURCE} ) - -BUILD_DIR="./build" - -USAGE_STR="Usage: source scripts/$SCRIPT_NAME" - -if [[ $RAN_NAME == $SCRIPT_NAME ]]; then - echo "Error: Script needs to be sourced, not ran directly" - echo $USAGE_STR - exit -fi - -# Delete the build directory if it exists, so we start fresh -if [ -d "$BUILD_DIR" ]; then - rm -r $BUILD_DIR -fi - -mkdir $BUILD_DIR - -cd $BUILD_DIR - -# Just pass on all command line arguments to cmake -cmake .. -D CMAKE_EXPORT_COMPILE_COMMANDS=ON $@ -RET=$? - -# If we couldn't setup the build, return to the base -# project directory and remove the build directory -if [ $RET -ne 0 ] -then - cd .. - rm -r $BUILD_DIR -fi diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/CMakeLists.txt b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/CMakeLists.txt deleted file mode 100644 index 1bfa7a51..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/CMakeLists.txt +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright 2022 The PECOS developers -# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -# the License.You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. - -# Initial author: Tyson Lawrence - -# Configure the version file -configure_file( - ${PROJECT_SOURCE_DIR}/src/version.h.in - ${PROJECT_SOURCE_DIR}/src/version.h - ) -configure_file( - ${PROJECT_SOURCE_DIR}/src/version.c.in - ${PROJECT_SOURCE_DIR}/src/version.c - ) - - -set(LIB_INCLUDE_DIRS - ${PROJECT_SOURCE_DIR}/src - ${PROJECT_SOURCE_DIR}/extern/eigen - ${PROJECT_SOURCE_DIR}/extern/eigen/unsupported - ${CUSTATEVEC_ROOT}/include - /opt/nvidia/cuquantum/include - /usr/include/eigen3 - /usr/include/eigen3/Eigen - /usr/local/cuda/lib64 - ) - -set(LIB_SOURCES - version.c - custatevec_wrapper.cpp - - custatevec_workspace.cpp - utils.cpp - state_vector.cpp - gate.cpp - gate_matrices.cpp - quantum_volume.cpp - - custom_kernels.cu - ) - -# TODO FIXME Not all compiler options all work with nvcc -# set(_COMPILE_FLAGS -# $<$:${DEV_FLAGS}> -# $<$:${WARNING_FLAGS}> -# $<$:${ERROR_FLAGS}> -# ) - -add_library(custatevec_wrapper SHARED ${LIB_SOURCES}) -target_include_directories(custatevec_wrapper PUBLIC ${LIB_INCLUDE_DIRS}) -target_link_directories(custatevec_wrapper PUBLIC ${CUSTATEVEC_ROOT}/lib) -target_link_directories(custatevec_wrapper PUBLIC /usr/local/cuda/lib64) -target_link_libraries(custatevec_wrapper PUBLIC custatevec cudart cublas cublasLt) -# target_compile_options(custatevec_wrapper PUBLIC ${_COMPILE_FLAGS}) -set_target_properties(custatevec_wrapper PROPERTIES - SOVERSION ${PROJECT_VERSION_MAJOR} - VERSION ${PROJECT_VERSION} -) - -# -# Create the Python bindings -# -set(PYBINDING_SOURCES python_bindings.cpp ${LIB_SOURCES}) -pybind11_add_module(cuquantum_wrapper ${PYBINDING_SOURCES}) -target_include_directories(cuquantum_wrapper PUBLIC ${LIB_INCLUDE_DIRS}) -target_include_directories(cuquantum_wrapper PUBLIC /usr/include/eigen3/) -target_include_directories(cuquantum_wrapper PUBLIC /usr/include/eigen3/Eigen) -target_include_directories(cuquantum_wrapper PUBLIC /usr/include/eigen3/Eigen/src/KLUSupport) -target_link_directories(cuquantum_wrapper PUBLIC ${CUSTATEVEC_ROOT}/lib) -target_link_libraries(cuquantum_wrapper PUBLIC custatevec cudart cublas cublasLt) -set_property(TARGET cuquantum_wrapper PROPERTY CUDA_ARCHITECTURES 80) diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/custatevec_workspace.cpp b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/custatevec_workspace.cpp deleted file mode 100644 index 456165e3..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/custatevec_workspace.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2022 The PECOS developers -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -// the License.You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Initial author: Tyson Lawrence - -#include "custatevec_workspace.hpp" - -/* - * - * Constructor and desctuctor - * - */ -CuStatevecWorkspace::CuStatevecWorkspace() -{ - extra_sz = 0; - extra = nullptr; - custatevecCreate(&handle); -} - -CuStatevecWorkspace::~CuStatevecWorkspace() -{ - custatevecDestroy(handle); - if (extra_sz) - cudaFree(extra); - extra = nullptr; - extra_sz = 0; -} - - -/* - * - * Member functions - * - */ -size_t CuStatevecWorkspace::get_extra_sz() -{ - return extra_sz; -} diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/custatevec_workspace.hpp b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/custatevec_workspace.hpp deleted file mode 100644 index 20e1ccef..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/custatevec_workspace.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2022 The PECOS developers -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -// the License.You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Initial author: Tyson Lawrence - -#ifndef CUSTATEVEC_WORKSPACE_HPP -#define CUSTATEVEC_WORKSPACE_HPP - -#include // cudaMalloc, cudaMemcpy, etc. -#include // custatevecApplyMatrix - -/* - * - * Helper class for managing custatevector workspaces - * - */ -class CuStatevecWorkspace -{ - // Only the following classes should access the private - // members of this class - friend class StateVector; - friend class Gate; - - // Members - custatevecHandle_t handle; - void* extra; - size_t extra_sz; - -public: - - // Constructor - CuStatevecWorkspace(); - - // Destructor - ~CuStatevecWorkspace(); - - // Return the current size of the external (extra) workspace - size_t get_extra_sz(); - -}; - -#endif // CUSTATEVEC_WORKSPACE_HPP diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/custatevec_wrapper.cpp b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/custatevec_wrapper.cpp deleted file mode 100644 index 0e4c694a..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/custatevec_wrapper.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2022 The PECOS developers -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -// the License.You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Initial author: Tyson Lawrence - -#include "custatevec_wrapper.h" - -#include "quantum_volume.hpp" -#include "utils.hpp" - -int run_quantum_volume(int num_qubits, int num_shots, double results[], int len_results) -{ - // Initialize the workspace - CuStatevecWorkspace ws; - - // Initialize the state vector to |000...0> - StateVector sv(num_qubits); - sv.init_on_device(); - - // Create, apply, and free the QV circuit - QuantumVolume qv(num_qubits); - qv.copy_to_device(); - qv.apply(sv,ws); - qv.free_on_device(); - - std::vector probs = sv.get_probabilities(ws); - for (int n = 0; n < len_results; n++) - results[n] = probs[n]; - - // // Make measurements for the shots - // constexpr bool collapse = false; - // double randnum = rand_in_range(0.0, 1.0); - // // std::vector bit_string(num_qubits, -1); - // BasisBits bit_string(num_qubits, -1); - // for (size_t shot = 0; shot < num_shots; shot++) { - // randnum = rand_in_range(0.0, 1.0); - // sv.batch_measure_all(ws, bit_string, randnum, collapse); - // results[shot] = compress_bit_string(bit_string); - // } - - sv.read_from_device(); - sv.free_on_device(); - - return 0; -} - -int run_quantum_volume_2(int num_qubits, double angles[][8][3], int targets[], double results[], int len_results) -{ - // Initialize the workspace - CuStatevecWorkspace ws; - - // Initialize the state vector to |000...0> - StateVector sv = create_zero_state_vector(num_qubits); - sv.copy_to_device(); - - // Convert the C-array to a Targets vector. - Targets _targets(targets, targets+num_qubits); - - // Create, apply, and free the QV circuit - QuantumVolume qv(num_qubits, angles, _targets); - qv.copy_to_device(); - qv.apply(sv,ws); - qv.free_on_device(); - - std::vector probs = sv.get_probabilities(ws); - for (int n = 0; n < len_results; n++) - results[n] = probs[n]; - - sv.read_from_device(); - sv.free_on_device(); - - return 0; -} diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/custatevec_wrapper.h b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/custatevec_wrapper.h deleted file mode 100644 index 493f3cb5..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/custatevec_wrapper.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2022 The PECOS developers -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -// the License.You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Initial author: Tyson Lawrence - -#ifndef CUSTATEVEC_WRAPPER_H -#define CUSTATEVEC_WRAPPER_H - -/* - * - * C API - * - */ -#ifdef __cplusplus -extern "C" { -#endif - -#include "version.h" - -int run_quantum_volume(int num_qubits, int num_shots, double results[], int len_results); - -int run_quantum_volume_2(int num_qubits, double angles[][8][3], int targets[], double results[], int len_results); - -#ifdef __cplusplus -} -#endif - -#endif // CUSTATEVEC_WRAPPER_H diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/custom_kernels.cu b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/custom_kernels.cu deleted file mode 100644 index c21552cf..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/custom_kernels.cu +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2022 The PECOS developers -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -// the License.You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Initial author: Tyson Lawrence - -#include "custom_kernels.hpp" - -__global__ void _initialize_sv(cuDoubleComplex* sv, int64_t dim) -{ - int64_t i = static_cast(blockIdx.x) * blockDim.x + threadIdx.x; - if(i == 0) { - sv[i].x = 1.f; - sv[i].y = 0.f; - } - else if(i < dim) { - sv[i].x = 0.f; - sv[i].y = 0.f; - } -} - -void initialize_sv(cuDoubleComplex* sv, int64_t dim) -{ - constexpr int32_t threads_per_block = 256; // number of threads per CUDA thread block, typically 128/256/512/1024. - uint32_t n_blocks = (dim + threads_per_block - 1) / threads_per_block; // ceiling divide - _initialize_sv<<>>(sv, dim); // launch the CUDA kernel on the GPU -} diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/custom_kernels.hpp b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/custom_kernels.hpp deleted file mode 100644 index 94318a6a..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/custom_kernels.hpp +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2022 The PECOS developers -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -// the License.You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Initial author: Tyson Lawrence - -#ifndef CUSTOM_KERNELS_HPP -#define CUSTOM_KERNELS_HPP - -#include - -#include // cuDoubleComplex -#include // cudaMalloc, cudaMemcpy, etc. - -void initialize_sv(cuDoubleComplex* sv, int64_t dim); - -#endif // CUSTOM_KERNELS_HPP diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/gate.cpp b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/gate.cpp deleted file mode 100644 index 8918c408..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/gate.cpp +++ /dev/null @@ -1,248 +0,0 @@ -// Copyright 2022 The PECOS developers -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -// the License.You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Initial author: Tyson Lawrence - -#include "gate.hpp" -#include "gate_matrices.hpp" - -#include "Eigen/Dense" - -using Eigen::Matrix2cd; -using Eigen::Matrix4cd; - -// #include "gate_matrices.hpp" - -/* - * - * Constructors - * - */ -Gate::Gate() : - mat(Eigen::MatrixXcd()) - {} - -Gate::Gate(size_t rows, size_t cols) : - mat(Eigen::MatrixXcd(rows,cols)) - {} - -Gate::Gate(const Eigen::MatrixXcd mat) : - mat(mat) - {} - -/* - * - * Device functions - * - */ -void Gate::set(const Eigen::MatrixXcd mat_new) -{ - mat = mat_new; -} - -size_t Gate::size() -{ - return mat.size(); -} - -size_t Gate::mem_size() -{ - return size() * sizeof(cuDoubleComplex); -} - -void Gate::copy_to_device() -{ - // Allocate space on the device - cudaError_t status = cudaMalloc((void **)&d_mat, mem_size()); - if(status != cudaSuccess) - throw std::runtime_error("cudaMalloc error"); - - // Copy gate matrix to the device - cudaMemcpy(d_mat, mat.data(), mem_size(), cudaMemcpyHostToDevice); -} - -void Gate::free_on_device() -{ - // Free memory on device - cudaFree(d_mat); - d_mat = nullptr; -} - -/* - * - * Apply the gate to a state vector on the host - * - */ -void Gate::apply(StateVector &sv) -{ - sv.sv = mat * sv.sv; -} - -/* - * - * Apply the gate to a state vector in the provided workspace using pre-configured - * control and target bits. Optionally, apply the adjoint of the gate - * - */ -void Gate::apply(StateVector &sv, CuStatevecWorkspace &workspace, bool adjoint) -{ - apply(sv, workspace, controls, targets, adjoint); -} - - -/* - * - * Apply the gate to a state vector in the provided workspace using the provided - * control and target bits. Optionally, apply the adjoint of the gate - * - */ -void Gate::apply(StateVector &sv, CuStatevecWorkspace &workspace, - const Controls &controls, const Targets &targets, - bool adjoint) -{ - // If the gate has been copied to the device, use the on device copy - void *ptr = mat.data(); - if (d_mat != nullptr) - ptr = d_mat; - - // First, check to see if workspace can handle the gate - custatevecApplyMatrixGetWorkspaceSize( - workspace.handle, CUDA_C_64F, sv.num_bits, ptr, - CUDA_C_64F, CUSTATEVEC_MATRIX_LAYOUT_COL, - adjoint, targets.size(), controls.size(), CUSTATEVEC_COMPUTE_64F, - &workspace.extra_sz); - - // Allocate external workspace if necessary - if (workspace.extra_sz > 0) - cudaMalloc(&workspace.extra, workspace.extra_sz); - - int32_t csize = controls.size(); - - // Apply the gate - custatevecApplyMatrix(workspace.handle, sv.d_sv, CUDA_C_64F, - sv.num_bits, ptr, CUDA_C_64F, - CUSTATEVEC_MATRIX_LAYOUT_COL, adjoint, - targets.data(), targets.size(), - controls.data(), nullptr, controls.size(), - CUSTATEVEC_COMPUTE_64F, - &workspace.extra, workspace.extra_sz); -} - - -void Gate::print() -{ - std::cout << mat << std::endl; -} - -/* - * - * Factory functions for specific gates - * - */ - -static constexpr std::complex i = {0,1}; - -Gate Rx(double theta) -{ - return Gate(gate_matrices::Rx(theta)); -} - - -Gate Ry(double theta) -{ - return Gate(gate_matrices::Ry(theta)); -} - - -Gate Rz(double theta) -{ - return Gate(gate_matrices::Rz(theta)); -} - - -Gate U(double theta, double phi, double lambda) -{ - Matrix2cd m(2,2); - m = gate_matrices::Rx(theta) * gate_matrices::Ry(phi) * gate_matrices::Rz(lambda); - return Gate(m); -} - -Gate create_random_U() -{ - std::random_device rd; - std::mt19937 rng(rd()); - std::uniform_real_distribution<> dist(0, 2*M_PI); - - double theta = dist(rng); - double phi = dist(rng); - double lambda = dist(rng); - - return U(theta, phi, lambda); -} - - -Gate U1q(double theta, double phi) -{ - Matrix2cd m(2,2); - m = gate_matrices::Rz(phi-M_PI/2) * gate_matrices::Ry(theta) * gate_matrices::Rz(-phi+M_PI/2); - return Gate(m); -} - - -Gate Hadamard() -{ - return Gate(gate_matrices::Hadamard()); -} - - -Gate CNOT() -{ - return Gate(gate_matrices::CNOT()); -} - - -Gate Toffoli() -{ - return CNOT(); -} - - -Gate PauliX() -{ - return Gate(gate_matrices::PauliX()); -} - - -Gate PauliY() -{ - return Gate(gate_matrices::PauliY()); -} - - -Gate PauliZ() -{ - return Gate(gate_matrices::PauliZ()); -} - - -/* - * - * Two qubit gates - * - */ -Gate SqrtZZ() -{ - return Gate(gate_matrices::SqrtZZ()); -} - -Gate RZZ(double theta) -{ - return Gate(gate_matrices::RZZ(theta)); -} diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/gate.hpp b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/gate.hpp deleted file mode 100644 index f1435c11..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/gate.hpp +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2022 The PECOS developers -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -// the License.You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Initial author: Tyson Lawrence - -#ifndef GATE_HPP -#define GATE_HPP - -#include -#include -#include -#include - -#include // cudaMalloc, cudaMemcpy, etc. -#include // cuDoubleComplex -#include // custatevecApplyMatrix - -#include "state_vector.hpp" -#include "custatevec_workspace.hpp" -#include "utils.hpp" - - -/* - * - * Typedefs - * - */ -using Targets = std::vector; -using Controls = Targets; - - -/* - * - * Gate wrapper class - * - */ -class Gate -{ - // Gate matrix on host - Eigen::MatrixXcd mat; - - // Gate matrix (pointer) on device - void *d_mat = nullptr; - -public: - // Control and target qubits for gate - Controls controls; - Targets targets; - - /* - * - * Constructors - * - */ - Gate(); - Gate(size_t rows, size_t cols); - Gate(const Eigen::MatrixXcd m); - - /* - * - * Member functions - * - */ - // Set the on host gate - void set(const Eigen::MatrixXcd mat_new); - - // Get the size and size in memory - size_t size(); - size_t mem_size(); - - // Copy and free the state vector on the device - void copy_to_device(); - void free_on_device(); - - // Apply the gate to the state vector on the host - void apply(StateVector &sv); - - // Apply the gate to the state vector on the device - void apply(StateVector &sv, CuStatevecWorkspace &workspace, - bool adjoint=false); - - void apply(StateVector &sv, CuStatevecWorkspace &workspace, - const Controls &cs, const Targets &ts, bool adjoint=false); - - // Print the gate to stdout - void print(); - -}; - - -/* - * - * Factory functions for specific gates - * - */ -constexpr double S2 = 0.707106781186547524401; // 1/sqrt(2) - -// Single qubit gates -Gate Rx(double theta); -Gate Ry(double theta); -Gate Rz(double theta); -Gate U1q(double theta, double phi); -Gate U(double theta, double phi, double lambda); - -Gate create_random_U(); - -Gate Hadamard(); - -Gate PauliX(); -Gate PauliY(); -Gate PauliZ(); - -// Two qubit gates -Gate SqrtZZ(); -Gate RZZ(double theta); -Gate CNOT(); -Gate Toffoli(); - -#endif diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/python_bindings.cpp b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/python_bindings.cpp deleted file mode 100644 index 323726f2..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/python_bindings.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2022 The PECOS developers -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -// the License.You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Initial author: Tyson Lawrence - -#include - -#include -#include -#include - -#include "custatevec_workspace.hpp" -#include "state_vector.hpp" -#include "gate.hpp" -#include "quantum_volume.hpp" -#include "version.h" - -#define STRINGIFY(x) #x -#define MACRO_STRINGIFY(x) STRINGIFY(x) - -namespace py = pybind11; - -PYBIND11_MODULE(cuquantum_wrapper, m) { - - m.attr("__version__") = VERSION_STR; - - m.doc() = R"pbdoc( - cuQuantum Wrapper library Python bindings - --------------------------------- - CuStatevecWorkspace - StateVector - Gate - QuantumVolume - )pbdoc"; - - /* - * - * Bindings (limited) for some of the main classes - * - */ - py::class_(m, "CuStatevecWorkspace") - .def(py::init<>(), R"pbdoc(Workspace Workspace for state vector simulations)pbdoc") - .def("get_extra_sz", &CuStatevecWorkspace::get_extra_sz); - - py::class_(m, "StateVector") - .def(py::init(), R"pbdoc(A state vector)pbdoc") - .def(py::init(), R"pbdoc(A state vector)pbdoc") - .def("set", &StateVector::set, "Set the on host state vector from a numpy array") - .def("get", &StateVector::get, "Get the on host state vector as a numpy array") - .def("init_on_device", &StateVector::init_on_device, "Initialize the on device state vector to the zero state") - .def("copy_to_device", &StateVector::copy_to_device, "Copy the on host state vector to the device") - .def("free_on_device", &StateVector::free_on_device, "Free the state vector on the device") - .def("read_from_device", &StateVector::read_from_device, "Read the state vector on the device back to the host") - .def("print", &StateVector::print, "Print the on host state vector to stdout") - .def("reset", static_cast< - void (StateVector::*)(CuStatevecWorkspace&) - >(&StateVector::reset), "Reset the on device statevector") - .def("measure", static_cast< - int32_t (StateVector::*)(CuStatevecWorkspace&, const BasisBits&, double, bool) - >(&StateVector::measure), "Measure") - .def("batch_measure", static_cast< - std::vector (StateVector::*)(CuStatevecWorkspace&, const BasisBits&, double, bool) - >(&StateVector::batch_measure), "Batch measure select qubits") - .def("batch_measure_all", &StateVector::batch_measure_all, "Batch measure all qubits") - .def("get_probabilities", &StateVector::get_probabilities, "Get the state probabilities"); - - py::class_(m, "Gate") - .def(py::init(), R"pbdoc(A gate)pbdoc") - .def(py::init(), R"pbdoc(A gate)pbdoc") - .def("copy_to_device", &Gate::copy_to_device, "Copy the gate from the host to the device") - .def("free_on_device", &Gate::free_on_device, "Free the gate on the device") - .def("apply", static_cast< - void (Gate::*)(StateVector&, CuStatevecWorkspace&, const Controls&, const Targets&, bool) - >(&Gate::apply), "Apply the gate to the target state vector"); - - py::class_(m, "QuantumVolume") - .def(py::init(), R"pbdoc(A randomized quantum volume circuit)pbdoc") - .def("print", &QuantumVolume::print, "Print the QV circuit to stdout") - .def("copy_to_device", &QuantumVolume::copy_to_device, "Copy QV circuit from the host to the device") - .def("free_on_device", &QuantumVolume::free_on_device, "Free the QV circuit on the device") - .def("apply", &QuantumVolume::apply, "Run the QV circuit"); - - /* - * - * Bindings for select gate matrices - * - */ - // Single qubit gates - m.def("Rx", &Rx, R"pbdoc(Rx gate)pbdoc"); - m.def("Ry", &Ry, R"pbdoc(Ry gate)pbdoc"); - m.def("Rz", &Rz, R"pbdoc(Rz gate)pbdoc"); - m.def("U1q", &U1q, R"pbdoc(U1q gate)pbdoc"); - m.def("U", &U, R"pbdoc(U gate)pbdoc"); - m.def("PauliX", &PauliX, R"pbdoc(PauliX gate)pbdoc"); - m.def("PauliY", &PauliY, R"pbdoc(PauliY gate)pbdoc"); - m.def("PauliZ", &PauliZ, R"pbdoc(PauliZ gate)pbdoc"); - - // Two qubit gates - m.def("SqrtZZ", &SqrtZZ, R"pbdoc(SqrtZZ gate)pbdoc"); - m.def("RZZ", &RZZ, R"pbdoc(RZZ gate)pbdoc"); - m.def("Hadamard", &Hadamard, R"pbdoc(Hadamard gate)pbdoc"); - m.def("CNOT", &CNOT, R"pbdoc(CNOT gate)pbdoc"); - - -} diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/quantum_volume.cpp b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/quantum_volume.cpp deleted file mode 100644 index 2533b763..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/quantum_volume.cpp +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright 2022 The PECOS developers -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -// the License.You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Initial author: Tyson Lawrence - -#include "quantum_volume.hpp" - -#include "utils.hpp" - -/* - * - * Helper functions - * - */ -/* - * - * SU(4) gate - * KAK-like decomposition ??? - * - */ -SU4Gate::SU4Gate() : szz(SqrtZZ()) -{ - randomize_us(); -} - -SU4Gate::SU4Gate(double angles[8][3]) : szz(SqrtZZ()) -{ - create_us(angles); -} - -/* - * - * Create randomized U gates for the SU(4) - * - */ -void SU4Gate::randomize_us() -{ - for (auto &u : us) { - u.free_on_device(); - u = create_random_U(); - } -} - -void SU4Gate::create_us(double angles[8][3]) -{ - for (int n = 0; n < 8; n++) { - us[n] = U(angles[n][0], angles[n][1], angles[n][2]); - } -} - -/* - * - * Copy and free the gate on the device - * - */ -void SU4Gate::copy_to_device() -{ - free_on_device(); - - szz.copy_to_device(); - for (auto &u : us) - u.copy_to_device(); -} - -void SU4Gate::free_on_device() -{ - szz.free_on_device(); - for (auto &u : us) - u.free_on_device(); -} - -/* - * - * Print the gate matrices to stdout - * - */ -void SU4Gate::print() -{ - szz.print(); - for (auto &u : us) - u.print(); -} - -/* - * - * Apply the gate to the target bits (ts) in the given state vector within - * the given workspace - * - */ -void SU4Gate::apply(StateVector &sv, CuStatevecWorkspace &ws, const Targets &ts) -{ - us[0].apply(sv, ws, {}, {ts[0]}); - us[1].apply(sv, ws, {}, {ts[1]}); - szz.apply(sv, ws, {}, ts); - us[2].apply(sv, ws, {}, {ts[0]}); - us[3].apply(sv, ws, {}, {ts[1]}); - szz.apply(sv, ws, {}, ts); - us[4].apply(sv, ws, {}, {ts[0]}); - us[5].apply(sv, ws, {}, {ts[1]}); - szz.apply(sv, ws, {}, ts); - us[6].apply(sv, ws, {}, {ts[0]}); - us[7].apply(sv, ws, {}, {ts[1]}); -} - - -/* - * - * Quantum Volume Circuit - * - */ -QuantumVolume::QuantumVolume(size_t num_qubits) : num_qubits(num_qubits) -{ - targets = arange(0, num_qubits); - create_circuit(); -} - -QuantumVolume::QuantumVolume(size_t num_qubits, double angles[][8][3], Targets ts) : num_qubits(num_qubits), targets(ts) -{ - create_circuit(angles); -} - -/* - * - * Private method to create the actual circuit. Circuit is comprised of layers - * of SU(4) gates. The number of layers equals the number of qubits. - * - */ -void QuantumVolume::create_circuit() -{ - for (size_t i = 0; i < num_qubits; i++) { - std::vector layer; - for (size_t j = 0; j < num_qubits/2; j++) - layer.push_back(SU4Gate()); - circuit.push_back(layer); - } -} - -void QuantumVolume::create_circuit(double angles[][8][3]) -{ - for (size_t i = 0; i < num_qubits; i++) { - std::vector layer; - for (size_t j = 0; j < num_qubits/2; j++) { - layer.push_back(SU4Gate(angles[i])); - } - circuit.push_back(layer); - } -} - -/* - * - * Copy and free the circuit on the device - * - */ -void QuantumVolume::copy_to_device() -{ - for (auto &layer : circuit) - for (auto &gate : layer) - gate.copy_to_device(); -} - -void QuantumVolume::free_on_device() -{ - for (auto &layer : circuit) - for (auto &gate : layer) - gate.free_on_device(); -} - -/* - * - * Print the gate matrices to stdout - * - */ -void QuantumVolume::print() -{ - for (auto &layer : circuit) - for (auto &gate : layer) - gate.print(); -} - -/* - * - * Apply the circuit to the target state vector within the target workspace - * - */ -void QuantumVolume::apply(StateVector &sv, CuStatevecWorkspace &ws) -{ - for (auto &layer : circuit) { - std::random_shuffle(targets.begin(), targets.end()); - for (int32_t i = 0; i < layer.size(); i++) - layer[i].apply(sv, ws, {2*i, 2*i+1}); - } -} diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/quantum_volume.hpp b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/quantum_volume.hpp deleted file mode 100644 index 3c8a8403..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/quantum_volume.hpp +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2022 The PECOS developers -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -// the License.You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Initial author: Tyson Lawrence - -#ifndef QUANTUM_VOLUME_HPP -#define QUANTUM_VOLUME_HPP - -#include "gate.hpp" - -/* - * - * SU(4) gate - * KAK-like decomposition ??? - * - */ -class SU4Gate -{ - Gate szz; - std::array us; - -public: - SU4Gate(); - SU4Gate(double angles[8][3]); - // Randomize the U gates within the SU(4) - void randomize_us(); - // Create the 8 U gates within the given angles (theta, phi, lambda) - void create_us(double angles[8][3]); - void copy_to_device(); - void free_on_device(); - void print(); - void apply(StateVector &sv, CuStatevecWorkspace &ws, const Targets &ts); -}; - -/* - * - * Quantum Volume circuit - * - */ -class QuantumVolume -{ - size_t num_qubits; - std::vector> circuit; - Targets targets; - - void create_circuit(); - void create_circuit(double angles[][8][3]); - -public: - QuantumVolume(size_t num_qubits); - QuantumVolume(size_t num_qubits, double angles[][8][3], Targets ts); - void copy_to_device(); - void free_on_device(); - void print(); - void apply(StateVector &sv, CuStatevecWorkspace &ws); -}; - -#endif // QUANTUM_VOLUME_HPP diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/state_vector.cpp b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/state_vector.cpp deleted file mode 100644 index 9be5831d..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/state_vector.cpp +++ /dev/null @@ -1,266 +0,0 @@ -// Copyright 2022 The PECOS developers -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -// the License.You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Initial author: Tyson Lawrence - -#include -#include -#include -#include - -#include "state_vector.hpp" -#include "custom_kernels.hpp" - -/* - * - * Constructors - * - */ -StateVector::StateVector() : - sv(Eigen::VectorXcd()) - {} - -StateVector::StateVector(size_t num_bits) : - sv(Eigen::VectorXcd(static_cast(std::pow(2,num_bits)))), - num_bits(num_bits) - {} - -StateVector::StateVector(const Eigen::VectorXcd sv) : - sv(sv), - num_bits(get_power_of_two_exponent(sv.size())) - {} - -StateVector::~StateVector() -{ - free_on_device(); -} - -/* - * - * Member functions - * - */ -void StateVector::set(const Eigen::VectorXcd sv_new) -{ - sv = sv_new; -} - -Eigen::VectorXcd StateVector::get() -{ - return sv; -} - -size_t StateVector::size() -{ - return sv.size(); -} - -size_t StateVector::mem_size() -{ - return size() * sizeof(cuDoubleComplex); -} - -void StateVector::init_on_device() -{ - // Allocate space on the device - cudaError_t status = cudaMalloc((void **)&d_sv, sizeof(cuDoubleComplex)*size()); - if(status != cudaSuccess) - throw std::runtime_error("cudaMalloc error"); - - // TODO does the following need to be const? - constexpr int32_t threads_per_block = 256; // number of threads per CUDA thread block, typically 128/256/512/1024. - uint32_t n_blocks = (size() + threads_per_block - 1) / threads_per_block; // ceiling divide - initialize_sv(d_sv, size()); // launch the CUDA kernel on the GPU -} - -void StateVector::copy_to_device() -{ - // Allocate space on the device - cudaError_t status = cudaMalloc((void **)&d_sv, mem_size()); - if(status != cudaSuccess) - throw std::runtime_error("cudaMalloc error"); - - // Copy state vector to device - cudaMemcpy(d_sv, sv.data(), mem_size(), cudaMemcpyHostToDevice); -} - -void StateVector::read_from_device() -{ - // Copy state vector back to host - cudaMemcpy(sv.data(), d_sv, mem_size(), cudaMemcpyDeviceToHost); -} - -void StateVector::free_on_device() -{ - // Free memory on device - cudaFree(d_sv); - d_sv = nullptr; -} - -custatevecCollapseOp_t StateVector::get_collapse_op(bool collapse) -{ - custatevecCollapseOp_t op = CUSTATEVEC_COLLAPSE_NONE; - if (collapse) - op = CUSTATEVEC_COLLAPSE_NORMALIZE_AND_ZERO; - return op; -} - -/* - * - * Measure on the Z-basis - * - */ -int32_t StateVector::measure(CuStatevecWorkspace &workspace, const BasisBits &basis_bits, - double randnum, bool collapse) -{ - int32_t parity; - custatevecMeasureOnZBasis( - workspace.handle, d_sv, CUDA_C_64F, num_bits, &parity, - basis_bits.data(), basis_bits.size(), - randnum, get_collapse_op(collapse)); - return parity; -} - -void StateVector::measure(CuStatevecWorkspace &workspace, int32_t &parity, - const BasisBits &basis_bits, double randnum, - bool collapse) -{ - custatevecMeasureOnZBasis( - workspace.handle, d_sv, CUDA_C_64F, num_bits, &parity, - basis_bits.data(), basis_bits.size(), - randnum, get_collapse_op(collapse)); - -} - -/* - * - * Batch measure on the Z-basis - * - */ -std::vector StateVector::batch_measure(CuStatevecWorkspace &workspace, const BasisBits &bit_ordering, - double randnum, bool collapse) -{ - BasisBits bit_string(bit_ordering.size(), -1); - - custatevecBatchMeasure( - workspace.handle, d_sv, CUDA_C_64F, num_bits, - bit_string.data(), bit_ordering.data(), bit_string.size(), - randnum, get_collapse_op(collapse)); - - return bit_string; - -} - -void StateVector::batch_measure(CuStatevecWorkspace &workspace, BasisBits &bit_string, - const BasisBits &bit_ordering, double randnum, - bool collapse) -{ - if (bit_string.size() < bit_ordering.size()) - bit_string.resize(bit_ordering.size()); - - custatevecBatchMeasure( - workspace.handle, d_sv, CUDA_C_64F, num_bits, - bit_string.data(), bit_ordering.data(), bit_string.size(), - randnum, get_collapse_op(collapse)); - -} - -/* - * - * Batch measure all qubits on the Z-basis - * - */ -void StateVector::batch_measure_all(CuStatevecWorkspace &workspace, BasisBits &bit_string, - double randnum, bool collapse) -{ - BasisBits bit_ordering = arange(num_bits-1, -1, -1); - batch_measure(workspace, bit_string, bit_ordering, randnum, collapse); -} - -/* - * - * Get probabilities for states - * - */ -std::vector StateVector::get_probabilities(CuStatevecWorkspace &workspace) -{ - // Calculate the probabilities for each state - BasisBits bit_string_order = arange(num_bits-1, -1, -1); - std::vector probs(size(), 0); - custatevecAbs2SumArray( - workspace.handle, d_sv, CUDA_C_64F, num_bits, - probs.data(), bit_string_order.data(), num_bits, - NULL, NULL, 0); - - return probs; -} - -/* - * - * Reset the state vector to the zero state on the device - * - */ -void StateVector::reset(CuStatevecWorkspace &workspace) -{ - // Calculate the probabilities for each state - BasisBits bit_string_order = arange(num_bits-1, -1, -1); - std::vector abs2sum(size(), 0); - custatevecAbs2SumArray( - workspace.handle, d_sv, CUDA_C_64F, num_bits, - abs2sum.data(), bit_string_order.data(), num_bits, - NULL, NULL, 0); - - // Normalization factor here is the probability of the |00...0> - // state, which is 0th index - double norm = abs2sum[0]; - - // Collapse to |00...0> - BasisBits bit_string(num_bits, 0); - custatevecCollapseByBitString( - workspace.handle, d_sv, CUDA_C_64F, num_bits, - bit_string.data(), bit_string_order.data(), num_bits, norm); -} - -/* - * - * Print the state vector to stdout in a formatted manner - * - */ -void StateVector::print() -{ - for (size_t i = 0; i < size(); i++) { - std::cout << "|" << num_to_binary(i, num_bits) << "> "; - std::cout << sv.coeff(i) << std::endl;; - } - -} - -/* - * - * StateVector helper functions - * - */ -StateVector create_random_state_vector(size_t num_bits) -{ - srand((unsigned int) time(0)); - size_t num_states = std::pow(2, num_bits); - Eigen::VectorXcd v = Eigen::VectorXcd::Random(num_states).normalized(); - StateVector sv(v); - return sv; -} - -StateVector create_zero_state_vector(size_t num_bits) -{ - size_t num_states = std::pow(2, num_bits); - Eigen::VectorXcd v = Eigen::VectorXcd::Zero(num_states); - v[0] = 1; - StateVector sv(v); - return sv; -} diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/state_vector.hpp b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/state_vector.hpp deleted file mode 100644 index d5c3937c..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/state_vector.hpp +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2022 The PECOS developers -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -// the License.You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Initial author: Tyson Lawrence - -#ifndef STATE_VECTOR_HPP -#define STATE_VECTOR_HPP - -#include -#include -#include -#include - -#include // cudaMalloc, cudaMemcpy, etc. -#include // cuDoubleComplex -#include // custatevecApplyMatrix - -#include "Eigen/Dense" -#include "custatevec_workspace.hpp" -#include "utils.hpp" - -/* - * - * Typedefs - * - */ -using BasisBits = std::vector; - - -/* - * - * StateVector wrapper class - * - */ -class StateVector -{ - friend class Gate; - - // State vector on host - Eigen::VectorXcd sv; - - // State vector (pointer) on device - cuDoubleComplex *d_sv = nullptr; - - // Helper to get the cuda op codes for collapse operations - custatevecCollapseOp_t get_collapse_op(bool collapse); - -public: - size_t num_bits; - - /* - * - * Constructors and destructor - * - */ - StateVector(); - StateVector(size_t num_bits); - StateVector(const Eigen::VectorXcd v); - ~StateVector(); - - // Overload comparison to compare on host sv - bool operator==(const StateVector& other) const - { - return (this->sv == other.sv); - } - - /* - * - * Member functions - * - */ - // Set the on host state vector - void set(const Eigen::VectorXcd v_new); - // Get the on host state vector - Eigen::VectorXcd get(); - - // Get the size and size in memory - size_t size(); - size_t mem_size(); - - // Initiailze the state vector on the device to the zero state - void init_on_device(); - - // Copy, read, and free the state vector on the device - void copy_to_device(); - void read_from_device(); - void free_on_device(); - - // Measure on the Z-basis - int32_t measure(CuStatevecWorkspace &workspace, const BasisBits &basis_bits, - double randnum=0, bool collapse=true); - - void measure(CuStatevecWorkspace &workspace, int32_t &parity, - const BasisBits &basis_bits, double randnum=0, - bool collapse=true); - - // Batch measure multiple qubits on the Z-basis - std::vector batch_measure(CuStatevecWorkspace &workspace, const BasisBits &bit_ordering, - double randnum=0, bool collapse=true); - - void batch_measure(CuStatevecWorkspace &workspace, BasisBits &bit_string, - const BasisBits &bit_ordering, double randnum=0, - bool collapse=true); - - // Batch measure all qubits on the Z-basis - void batch_measure_all(CuStatevecWorkspace &workspace, BasisBits &bit_string, - double randnum=0, bool collapse=true); - - // Get the state vector probabilities - std::vector get_probabilities(CuStatevecWorkspace &workspace); - - // Reset to the zero state - void reset(CuStatevecWorkspace &workspace); - - // Print the state vector in a nicely formatted manner to stdout - void print(); - -}; - - -/* - * - * StateVector helper functions - * - */ -StateVector create_random_state_vector(size_t num_bits); -StateVector create_zero_state_vector(size_t num_bits); - - -#endif diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/utils.cpp b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/utils.cpp deleted file mode 100644 index be1796a2..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/utils.cpp +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2022 The PECOS developers -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -// the License.You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Initial author: Tyson Lawrence - -#include "utils.hpp" - - -/* - * - * Binary string conversion - * - */ -std::string num_to_binary(int num, size_t len) -{ - std::string bstr; - for (size_t i = (1 << (len - 1)); i > 0; i = i / 2) - bstr += (num & i) ? "1" : "0"; - return bstr; -} - -/* - * - * Get the power of two exponent - * - */ -size_t get_power_of_two_exponent(size_t value) -{ - size_t x = 0; - while(static_cast( 1 << x ) != value) - x ++; - return x; -} - -/* - * - * Random numbers - * - */ -double rand_in_range(double rmin, double rmax) -{ - std::random_device rd; - std::mt19937 rng(rd()); - std::uniform_real_distribution<> dist(rmin, rmax); - return dist(rng); -} - -/* - * - * Bit string (vector of int 0s and 1s) helpers - * - */ -// Compress the bit string, which is a vector of int 0s and 1s to an -// unsigned integer with the same bit representation -uint64_t compress_bit_string(std::vector const &bit_string) -{ - if (bit_string.size() > 64) { - throw std::runtime_error("Can not compress bit string larger than 64 bits"); - } - - uint64_t result = 0; - for (size_t i = 0; i < bit_string.size(); i++) { - if (bit_string[i]) - result |= (1 << i); - - } - return result; -} - -// Print a bit string to stdout -void print_bit_string(std::vector const &bit_string, bool add_newline) -{ - auto it = bit_string.rbegin(); - for (size_t i = 0; i < bit_string.size(); i++) { - std::cout << *it; - it++; - } - if (add_newline) - std::cout << std::endl; -} diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/utils.hpp b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/utils.hpp deleted file mode 100644 index 292e47c5..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/utils.hpp +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright 2022 The PECOS developers -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -// the License.You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Initial author: Tyson Lawrence - -#ifndef UTILS_HPP -#define UTILS_HPP - -#include -#include -#include -#include -#include -#include - -/* - * - * Helper macros for during development and in examples - * - */ -#define PRINT(x) std::cout << x << std::endl; -#define ELAPSED(timer) std::cout << "Elapsed: " << timer.elapsed() << " s" << std::endl; - -/* - * - * Timer class with Matlab-like semantics (tic and toc) - * - */ -template , - typename CLOCK_T = std::chrono::high_resolution_clock> -class Timer -{ - public: - Timer() noexcept : t_start{CLOCK_T::now()}, t_stop{t_start} {} - - // Start the timer - Timer& tic() noexcept - { - t_start = t_stop = CLOCK_T::now(); - return *this; - } - - // Stop the timer - Timer& toc() noexcept - { - t_stop = CLOCK_T::now(); - return *this; - } - - // Return the elapsed tics/counts between tic and now - double elapsed(bool do_toc=true) noexcept - { - if (do_toc) - toc(); - - return static_cast( - std::chrono::duration_cast(t_stop - t_start).count()); - } - -private: - - // Start and stop time points - typename CLOCK_T::time_point t_start, t_stop; - -}; // class Timer - - -/* - * - * Create a range of integral values as a vector (like Python's arange) - * - */ -template -std::vector arange(T start, T stop, T step = 1) -{ - static_assert(std::is_integral::value, "Integral required."); - std::vector values; - for (T value = start; value != stop; value += step) - values.push_back(value); - return values; -} - -template -void print_vector(const std::vector &vec, size_t wrap=16) -{ - for (size_t i = 0; i < vec.size(); i++) { - std::cout << vec[i]; - if ( i < vec.size()-1 ) - std::cout << ", "; - if ( (i+1) % wrap == 0 ) - std::cout << "\n"; - } - std::cout << std::endl; -} - - -/* - * - * Binary string conversion - * - */ -std::string num_to_binary(int num, size_t len); - -/* - * - * Get the power of two exponent - * - */ -size_t get_power_of_two_exponent(size_t value); - -/* - * - * Is a number odd or even - * - */ -template -bool is_odd(T n) -{ - return n % 2 != 0; -} - -template -bool is_even(T n) -{ - return n % 2 == 0; -} - -/* - * - * Random numbers - * - */ -double rand_in_range(double rmin=0.0, double rmax=1.0); - -/* - * - * Math - * - */ -template -T mean(std::vector const& v) -{ - if (v.empty()) - return 0; - return std::accumulate(v.begin(), v.end(), 0.0) / static_cast(v.size()); -} - - -/* - * - * Bit string (vector of int 0s and 1s) helpers - * - */ -// Compress the bit string, which is a vector of int 0s and 1s to an -// unsigned integer with the same bit representation -uint64_t compress_bit_string(std::vector const &bit_string); - -// Print a bit string to stdout -void print_bit_string(std::vector const &bit_string, bool add_newline=true); - - - -#endif // UTILS_HPP diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/version.c b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/version.c deleted file mode 100644 index e3d165ee..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/version.c +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2022 The PECOS developers -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -// the License.You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Initial author: Tyson Lawrence - -const char * const version_str = "0.0.22"; - -const char * const get_version() -{ - return version_str; -} diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/version.c.in b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/version.c.in deleted file mode 100644 index aa9dcf6d..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/version.c.in +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2022 The PECOS developers -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -// the License.You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Initial author: Tyson Lawrence - -const char * const version_str = "${PROJECT_VERSION}"; - -const char * const get_version() -{ - return version_str; -} diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/version.h b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/version.h deleted file mode 100644 index 3f6fb568..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/version.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2022 The PECOS developers -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -// the License.You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Initial author: Tyson Lawrence - -#ifndef VERSION_H -#define VERSION_H - -#define VERSION_STR "0.0.22" - -extern const char * const version_str; - -const char * const get_version(); - -#endif /* ifndef VERSION_H */ diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/version.h.in b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/version.h.in deleted file mode 100644 index 82a60ba5..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/src/version.h.in +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2022 The PECOS developers -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -// the License.You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Initial author: Tyson Lawrence - -#ifndef VERSION_H -#define VERSION_H - -#define VERSION_STR "${PROJECT_VERSION}" - -extern const char * const version_str; - -const char * const get_version(); - -#endif /* ifndef VERSION_H */ diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/test/CMakeLists.txt b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/test/CMakeLists.txt deleted file mode 100644 index eea52f2f..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/test/CMakeLists.txt +++ /dev/null @@ -1,95 +0,0 @@ -# Copyright 2022 The PECOS Developers -# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -# the License.You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. - -# Initial author: Tyson Lawrence - -# -# Set include directories -# -set(TEST_INCLUDE_DIRS - ${PROJECT_SOURCE_DIR}/extern/catch - ${PROJECT_SOURCE_DIR}/extern/eigen - ${PROJECT_SOURCE_DIR}/extern/eigen/unsupported - ${PROJECT_SOURCE_DIR}/src - ${CUSTATEVEC_ROOT}/include - /opt/nvidia/cuquantum/include - /usr/include/eigen3 - /usr/include/eigen3/Eigen - ) - -# -# Set some shortcuts to some directories we are interested in -# -set(SRC_DIR ${PROJECT_SOURCE_DIR}/src) -set(TEST_DIR ${PROJECT_SOURCE_DIR}/test) -set(CATCH_HEADER_DIR ${PROJECT_SOURCE_DIR}/extern/catch) - -# -# Create main catch object file -# -if (NOT TARGET catch_main) - add_library(catch_main OBJECT ${TEST_DIR}/catch_main.cpp ${CATCH_HEADER_DIR}/catch.hpp ) - target_include_directories(catch_main PUBLIC ${CATCH_HEADER_DIR}) -endif() - -# -# Function to simplify adding a Catch based unit test. The test name -# should correspond the main test source file. EX: test_foo target -# corresponds to test_foo.cpp -# -function(add_catch_test TEST_NAME TEST_SOURCES) - # Get the main test source file and append it to the list of test sources - set(TEST_MAIN "${TEST_DIR}/${TEST_NAME}.cpp") - set(TEST_SOURCES ${TEST_MAIN} ${TEST_SOURCES}) - # Create the test program - add_executable(${TEST_NAME} ${TEST_SOURCES} $) - target_include_directories(${TEST_NAME} PRIVATE ${TEST_INCLUDE_DIRS}) - # Add the test to CTest - add_test(NAME ${TEST_NAME} COMMAND $) - target_include_directories(${TEST_NAME} PRIVATE ${TEST_INCLUDE_DIRS}) - target_link_directories(${TEST_NAME} PRIVATE ${CUSTATEVEC_ROOT}/lib64) - target_link_libraries(${TEST_NAME} PRIVATE custatevec cudart cublas cublasLt) -endfunction() - -# -# The unit tests -# -set(TEST_SOURCES - ${SRC_DIR}/gate_matrices.cpp - ) -add_catch_test(test_gate_matrices "${TEST_SOURCES}") - -set(TEST_SOURCES - ${SRC_DIR}/custatevec_workspace.cpp - ${SRC_DIR}/utils.cpp - ${SRC_DIR}/state_vector.cpp - ${SRC_DIR}/custom_kernels.cu - ) -add_catch_test(test_state_vector "${TEST_SOURCES}") - -set(TEST_SOURCES - ${SRC_DIR}/custatevec_workspace.cpp - ${SRC_DIR}/utils.cpp - ${SRC_DIR}/gate_matrices.cpp - ${SRC_DIR}/state_vector.cpp - ${SRC_DIR}/custom_kernels.cu - ${SRC_DIR}/gate.cpp - ) -add_catch_test(test_gate "${TEST_SOURCES}") - - -# -# Generic test / scratch pad -# -set(TEST_SOURCES - test_stuff.cpp - ) -add_executable(test_stuff "${TEST_SOURCES}") -target_link_libraries(test_stuff PRIVATE custatevec_wrapper) diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/test/catch_main.cpp b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/test/catch_main.cpp deleted file mode 100644 index 74a1eb59..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/test/catch_main.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2022 The PECOS developers -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -// the License.You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Initial author: Tyson Lawrence - -#define CATCH_CONFIG_MAIN -#define CATCH_CONFIG_NO_POSIX_SIGNALS -#include "catch.hpp" diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/test/cuda_helper.hpp b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/test/cuda_helper.hpp deleted file mode 100644 index 989f9777..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/test/cuda_helper.hpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - Neither the name(s) of the copyright holder(s) nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef CUDA_HELPER_HPP -#define CUDA_HELPER_HPP - -#define HANDLE_ERROR(x) \ -{ const auto err = x; \ - if (err != CUSTATEVEC_STATUS_SUCCESS ) { \ - printf("Error: %s in line %d\n", \ - custatevecGetErrorString(err), __LINE__); return err; } \ -}; - -#define HANDLE_CUDA_ERROR(x) \ -{ const auto err = x; \ - if (err != cudaSuccess ) { \ - printf("Error: %s in line %d\n", \ - cudaGetErrorString(err), __LINE__); return err; } \ -}; - -bool almost_equal(cuDoubleComplex x, cuDoubleComplex y) { - const double eps = 1.0e-5; - const cuDoubleComplex diff = cuCsub(x, y); - return (cuCabs(diff) < eps); -} - -#endif // CUDA_HELPER_HPP diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/test/test_gate.cpp b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/test/test_gate.cpp deleted file mode 100644 index 5b0395e0..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/test/test_gate.cpp +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright 2022 The PECOS developers -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -// the License.You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Initial author: Tyson Lawrence - -#include "catch.hpp" - -#include "custatevec_workspace.hpp" -#include "gate.hpp" -#include "state_vector.hpp" - -#include "cuda_helper.hpp" // HANDLE_ERROR, HANDLE_CUDA_ERROR - -using namespace std; - -using CD = std::complex; - -/* - * - * Single gate tests - * - */ - -// Helper to run a single gate test -void run_gate_test(Gate &gate, StateVector &sv) -{ - // Copy state vector to device - sv.copy_to_device(); - - // Initialize the workspace - CuStatevecWorkspace workspace; - - // Apply gate - gate.copy_to_device(); - gate.apply(sv, workspace); - gate.free_on_device(); - - // Copy state vector back to host - sv.read_from_device(); -} - - -TEST_CASE("Hadamard") -{ - // Create the gate - Gate gate = Hadamard(); - gate.targets = {0}; - gate.controls = {}; - - // Create the state vector - StateVector sv = create_zero_state_vector(1); - StateVector sv_expected = create_zero_state_vector(1); - - // Directly calculate the expected result before running test - gate.apply(sv_expected); - - // Modifies the state vector - run_gate_test(gate, sv); - - REQUIRE(sv == sv_expected); -} - - -TEST_CASE("Toffoli From Docs") -{ - // Create the gate - Gate gate = Toffoli(); - gate.controls = {0,1}; - gate.targets = {2}; - - // Create the state vector - Eigen::VectorXcd v(8); - v << (0.0, 0.0), (0.0, 0.1), (0.1, 0.1), (0.1, 0.2), - (0.2, 0.2), (0.3, 0.3), (0.3, 0.4), (0.4, 0.5); - StateVector sv(v); - sv.copy_to_device(); - - run_gate_test(gate, sv); - - // Check results - StateVector ex(3); - Eigen::VectorXcd vex(8); - vex << (0.0, 0.0), (0.0, 0.1), (0.1, 0.1), (0.4, 0.5), - (0.2, 0.2), (0.3, 0.3), (0.3, 0.4), (0.1, 0.2); - StateVector svex(vex); - - REQUIRE(sv == svex); -} - - -// TODO FIXME Broken after change to composition -// TEST_CASE("Toffoli") -// { -// // Create the gate -// Gate gate = Toffoli(); -// gate.controls = {0,1}; -// gate.targets = {2}; - -// // Create the input and expected state vectors -// StateVector sv(3); -// StateVector ex(3); - -// // 000 -> 000 -// sv << 1, 0, 0, 0, 0, 0, 0, 0; -// ex = sv; -// run_gate_test(gate, sv); -// REQUIRE(sv == ex); - -// // 010 -> 010 -// sv << 0, 1, 0, 0, 0, 0, 0, 0; -// ex = sv; -// run_gate_test(gate, sv); -// REQUIRE(sv == ex); - -// // skip to the ones that flip bits - -// // 111 -> 110 -// sv << 0, 0, 0, 0, 0, 0, 0, 1; -// ex << 0, 0, 0, 1, 0, 0, 0, 0; -// run_gate_test(gate, sv); -// REQUIRE(sv == ex); - -// // 110 -> 111 -// sv << 0, 0, 0, 1, 0, 0, 0, 0; -// ex << 0, 0, 0, 0, 0, 0, 0, 1; -// run_gate_test(gate, sv); -// REQUIRE(sv == ex); -// } - - -// TODO FIXME Broken after change to composition -// TEST_CASE("CNOT") -// { -// Gate gate = CNOT(); -// gate.targets = {1}; -// gate.controls = {0}; - -// // Create the input and expected state vectors -// StateVector sv(2); -// StateVector ex(2); - -// // 00 -> 00 -// sv << 1, 0, 0, 0; -// ex = sv; -// run_gate_test(gate, sv); -// REQUIRE(sv == ex); - -// // 01 -> 01 -// sv << 0, 0, 1, 0; -// ex = sv; -// run_gate_test(gate, sv); -// REQUIRE(sv == ex); - -// // 10 -> 11 -// sv << 0, 1, 0, 0; -// ex << 0, 0, 0, 1; -// run_gate_test(gate, sv); -// REQUIRE(sv == ex); - -// // 11 -> 10 -// sv << 0, 0, 0, 1; -// ex << 0, 1, 0, 0; -// run_gate_test(gate, sv); -// REQUIRE(sv == ex); - -// } - - -/* - * - * Multi-gate (circuit) tests - * - */ - -TEST_CASE("Bell State") -{ - Gate h = Hadamard(); - h.targets = {0}; - h.controls = {}; - - Gate cnot = CNOT(); - cnot.targets = {1}; - cnot.controls = {0}; - - Eigen::VectorXcd v(4); - v << 1, 0, 0, 0; - StateVector sv(v); - - sv.copy_to_device(); - - // Initialize the workspace - CuStatevecWorkspace workspace; - - // Copy gates to device - h.copy_to_device(); - cnot.copy_to_device(); - - // Apply gates - h.apply(sv, workspace); - cnot.apply(sv, workspace); - - sv.read_from_device(); - - // Bell state - v << S2, 0, 0, S2; - StateVector sv_bell(v); - - REQUIRE(sv == sv_bell); -} diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/test/test_gate_matrices.cpp b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/test/test_gate_matrices.cpp deleted file mode 100644 index c0cd4210..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/test/test_gate_matrices.cpp +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2022 The PECOS developers -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -// the License.You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Initial author: Tyson Lawrence - -#include "catch.hpp" - -#include -#include - -#include "gate_matrices.hpp" - -using namespace gate_matrices; - -const Eigen::Matrix2cd I = Eigen::Matrix2d::Identity(); -const std::complex i = {0,1}; -const auto X = PauliX(); -const auto Y = PauliY(); -const auto Z = PauliZ(); - -using namespace std; - -TEST_CASE("Rotation matrices") -{ - // No rotation should be identity - REQUIRE(Rx(0) == I); - REQUIRE(Ry(0) == I); - REQUIRE(Rz(0) == I); - - REQUIRE(Rz(M_PI).isApprox(-i * Z)); -} - -TEST_CASE("Pauli matrices") -{ - REQUIRE(X*X == I); - REQUIRE(Y*Y == I); - REQUIRE(Z*Z == I); - - REQUIRE(X*Y == -Y*X); - REQUIRE(X*Z == -Z*X); - REQUIRE(Y*Z == -Z*Y); - REQUIRE(Y == i*X*Z); - REQUIRE(X == i*Z*Y); - REQUIRE(Z == i*Y*X); -} - -TEST_CASE("U1q") -{ - Matrix2cd m; - Matrix2cd m_expected; - - m = U1q(0,0); - REQUIRE(m == I); - - m = U1q(M_PI,0); - REQUIRE(m.isApprox(-i * X)); - - m = U1q(M_PI,M_PI/2); - REQUIRE(m.isApprox(-i * Y)); -} - -TEST_CASE("SqrtZZ") { - auto m = SqrtZZ(); - /* cout << m << endl; */ - REQUIRE(true); -} diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/test/test_python_bindings.py b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/test/test_python_bindings.py deleted file mode 100644 index 37e7a9b5..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/test/test_python_bindings.py +++ /dev/null @@ -1,148 +0,0 @@ -#!/usr/bin/env python - -# copyright 2022 The PECOS Developers -# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -# the License.You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. - -# Initial author: Tyson Lawrence - -import os -import sys -import unittest - -import numpy as np -from numpy.testing import assert_array_equal, assert_allclose - -sys.path.append("./build/bin") -sys.path.append("../build/bin") -import cuquantum_wrapper as cq - - -class TestPythonBindings(unittest.TestCase): - def test_bell_state(self): - """Test Bell state""" - - # Create a workspace - ws = cq.CuStatevecWorkspace() - - # Initialize a zero state on th device - sv = cq.StateVector(2) - sv.init_on_device() - - # Since we initialized on the device, we need to read back to check - sv.read_from_device() - v = sv.get() - v_expected = np.array([1, 0, 0, 0], dtype=complex) - assert_array_equal(v, v_expected) - - # Create gates, copy to device, apply to target qubits, and free - h = cq.Hadamard() - cnot = cq.CX() - h.copy_to_device() - cnot.copy_to_device() - h.apply(sv, ws, [], [0], False) - cnot.apply(sv, ws, [0], [1], False) - h.free_on_device() - cnot.free_on_device() - - # Read final state - sv.read_from_device() - v = sv.get() - S2 = 1 / np.sqrt(2) - v_expected = np.array([S2, 0, 0, S2], dtype=complex) - assert_allclose(v, v_expected) - - # Reset back to zero state - sv.reset(ws) - sv.read_from_device() - v = sv.get() - v_expected = np.array([1, 0, 0, 0], dtype=complex) - assert_array_equal(v, v_expected) - - def test_tq_gates(self): - """Test TQ gates not already tested work.""" - # Create a workspace - ws = cq.CuStatevecWorkspace() - - # Initialize a zero state on th device - sv = cq.StateVector(2) - sv.init_on_device() - - # test some other TQ gates - sqrtzz = cq.SZZ() - rzz = cq.RZZ(0.234) - rzz.copy_to_device() - sqrtzz.copy_to_device() - rzz.apply(sv, ws, [0], [1], False) - sqrtzz.apply(sv, ws, [0], [1], False) - rzz.free_on_device() - sqrtzz.free_on_device() - - def test_measure_channels(self): - """Test batch measure""" - # Create a workspace - ws = cq.CuStatevecWorkspace() - - # Create the input (to be measured) state vector - v = np.array( - [0, 0 + 0.1j, 0.1 + 0.1j, 0.1 + 0.2j, 0.2 + 0.2j, 0.3 + 0.3j, 0.3 + 0.4j, 0.4 + 0.5j], dtype=complex - ) - sv = cq.StateVector(v) - - sv.copy_to_device() - - # Batch measure the qubits (all of them) - bit_order = [2, 1, 0] - randnum = 0.5 - collapse = True - - res = sv.batch_measure(ws, bit_order, randnum, collapse) - - sv.read_from_device() - sv.free_on_device() - - # Get the final state as a numpy array - v = sv.get() - - # Expected state vector and results - res_expected = [1, 1, 0] - v_expected = np.array([0, 0, 0, 0, 0, 0, 0.6 + 0.8j, 0], dtype=complex) - - # Check - assert_array_equal(v, v_expected) - self.assertEqual(res, res_expected) - - def test_quantum_volume(self): - """Test quantum volume... not a real test""" - - num_qubits = 4 - - # Create the workspace - ws = cq.CuStatevecWorkspace() - - # Initialize the state vector to the zero state on the device - sv = cq.StateVector(num_qubits) - sv.init_on_device() - - # Create and run the QV sim - qv = cq.QuantumVolume(num_qubits) - qv.copy_to_device() - qv.apply(sv, ws) - qv.free_on_device() - - # Get probabilities out - probs = sv.get_probabilities(ws) - - # Read the final state and free - sv.read_from_device() - sv.free_on_device() - - -if __name__ == "__main__": - unittest.main() diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/test/test_state_vector.cpp b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/test/test_state_vector.cpp deleted file mode 100644 index bc735ad0..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/test/test_state_vector.cpp +++ /dev/null @@ -1,273 +0,0 @@ -// Copyright 2022 The PECOS developers -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -// the License.You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Initial author: Tyson Lawrence - -#include "catch.hpp" - -#include -#include -#include - -#include "custatevec_workspace.hpp" -#include "state_vector.hpp" -#include "utils.hpp" - -#include "cuda_helper.hpp" // HANDLE_ERROR, HANDLE_CUDA_ERROR - -using namespace std; - -using CD = std::complex; - -/* - * - * StateVector tests - * - */ - -TEST_CASE("StateVector") -{ - // Create the state vectors - Eigen::VectorXcd v(8); - v << CD(1.3, 3.7), CD(7.1, 2.1), CD(4.3, 0.5), CD(6.1, 9.2), - CD(9.0, 8.8), CD(3.3, 3.3), CD(6.6, 6.6), CD(2.3, 8.5); - StateVector sv(v); - StateVector sv_expected = sv; - - REQUIRE(sv.num_bits == 3); - REQUIRE(sv.size() == 8); - - sv.copy_to_device(); - sv.read_from_device(); - sv.free_on_device(); - - REQUIRE(sv == sv_expected); -} - - -// ************************************** -// THIS TEST IS BROKEN DUE TO COMPOSITION CHANGE -// ************************************** -// TEST_CASE("StateVector memory") -// { -// // C-array -// const int nIndexBits = 3; -// const int nSvSize = (1 << nIndexBits); -// cuDoubleComplex sv_orig[] = {{ 0.0, 0.0}, { 0.0, 0.1}, { 0.3, 0.4}, { 0.1, 0.2}, -// { 0.2, 0.2}, { 0.3, 0.3}, { 0.1, 0.1}, { 0.4, 0.5}}; - -// // Create the state vector -// Eigen::VectorXcd v(8); -// v << CD(0.0, 0.0), CD(0.0, 0.1), CD(0.3, 0.4), CD(0.1, 0.2), -// CD(0.2, 0.2), CD(0.3, 0.3), CD(0.1, 0.1), CD(0.4, 0.5); -// StateVector sv(v); - -// // Sanity check that the C-style and StateVector representations are the same -// bool same = true; -// for (int i = 0; i < nSvSize; i++) { -// cuDoubleComplex *v = reinterpret_cast(&sv(i)); -// if (!almost_equal(*v, sv_orig[i])) -// same = false; -// } - -// // Print to stdout if not the same -// if ( !same ) { -// for (int i = 0; i < nSvSize; i++) { -// cuDoubleComplex *v = reinterpret_cast(&sv(i)); -// std::cout << sv(i) << " " ; -// std::cout << std::setw(3) << sv_orig[i].x << "," << sv_orig[i].y << "\n"; -// } -// } - -// REQUIRE(same); -// } - - -TEST_CASE("Measurement") -{ - const BasisBits basis_bits = {0, 1, 2}; - - int parity = -1; - - // In real application, random number in range [0, 1) will be used. - const double randnum = 0.2; - - // Create the state vector - Eigen::VectorXcd v(8); - v << CD(0.0, 0.0), CD(0.0, 0.1), CD(0.3, 0.4), CD(0.1, 0.2), - CD(0.2, 0.2), CD(0.3, 0.3), CD(0.1, 0.1), CD(0.4, 0.5); - StateVector sv(v); - - sv.copy_to_device(); - - // Initialize the workspace - CuStatevecWorkspace workspace; - - // Measure - sv.measure(workspace, parity, basis_bits, randnum); - - sv.read_from_device(); - - // Check results - Eigen::VectorXcd v_expected(8); - v_expected << CD(0.0, 0.0), CD(0.0, 0.0), CD(0.0, 0.0), CD(0.2, 0.4), - CD(0.0, 0.0), CD(0.6, 0.6), CD(0.2, 0.2), CD(0.0, 0.0); - StateVector sv_expected(v_expected); - int parity_expected = 0; - - REQUIRE(sv == sv_expected); - REQUIRE(parity == parity_expected); -} - - -void run_measure_test(double randnum) -{ - // Create the state vector - // 60% chance |00> and 40% change |01> - Eigen::VectorXcd v(4); - v << std::sqrt(0.6), 0, std::sqrt(0.4), 0; - StateVector sv(v); - - // Expected results - Eigen::VectorXcd v_00(4); - v_00 << 1, 0, 0, 0; - StateVector sv_00(v_00); - - Eigen::VectorXcd v_01(4); - v_01 << 0, 0, 1, 0; - StateVector sv_01(v_01); - - const BasisBits basis_bits = {0, 1}; - int parity = -1; - - sv.copy_to_device(); - - // Initialize the workspace - CuStatevecWorkspace workspace; - - // Perform measurement - sv.measure(workspace, parity, basis_bits, randnum); - - sv.read_from_device(); - - if (randnum <= 0.6) - REQUIRE(sv == sv_00); - else - REQUIRE(sv == sv_01); - -} - -TEST_CASE("Measurement on Z - Randnums") -{ - double step = 0.05; - for (double randnum = 0; randnum <= 1; randnum = randnum + step) - run_measure_test(randnum); -} - -TEST_CASE("Batch Measurement") -{ - Eigen::VectorXcd v(8); - v << CD(0.0, 0.0), CD(0.0, 0.1), CD(0.1, 0.1), CD(0.1, 0.2), - CD(0.2, 0.2), CD(0.3, 0.3), CD(0.3, 0.4), CD(0.4, 0.5); - StateVector sv(v); - - Eigen::VectorXcd v_expected(8); - v_expected << CD(0.0, 0.0), CD(0.0, 0.0), CD(0.0, 0.0), CD(0.0, 0.0), - CD(0.0, 0.0), CD(0.0, 0.0), CD(0.6, 0.8), CD(0.0, 0.0); - StateVector sv_expected(v_expected); - - const double randnum = 0.5; - const bool collapse = true; - - const BasisBits bit_ordering{2, 1, 0}; - BasisBits bit_string; - const BasisBits bit_string_expected{1, 1, 0}; - - CuStatevecWorkspace workspace; - sv.copy_to_device(); - - sv.batch_measure(workspace, bit_string, bit_ordering, randnum, collapse); - - sv.read_from_device(); - - REQUIRE(sv == sv_expected); - REQUIRE(bit_string == bit_string_expected); - -} - -TEST_CASE("Reset state") -{ - constexpr size_t NUM_BITS = 5; - constexpr size_t TEST_CASES = 5; - - const size_t num_states = 1 << NUM_BITS; - - CuStatevecWorkspace ws; - StateVector sv(NUM_BITS); - BasisBits bs(NUM_BITS, -1); - - bool check, all_zeros; - - // No reset - for (int i = 0; i < TEST_CASES; i++) { - sv = create_random_state_vector(NUM_BITS); - sv.copy_to_device(); - - check = true; - - // Make multiple measurements to ensure not in the zero state - for (float r = 0; r < 0.99; r+=0.05) { - // Reset bit sting - std::fill(bs.begin(), bs.end(), -1); - // Measure without collapsing - sv.batch_measure_all(ws, bs, r, false); - // Is |00...0> state? - all_zeros = std::all_of(bs.begin(), bs.end(), [](int32_t b) { return b==0; }); - check &= all_zeros; - } - - // Should be false, because the state is not in the zerio state - // NOTE: There is a small probability that this will fail b/c - // create random vector might create the zero state - REQUIRE_FALSE(check); - - sv.read_from_device(); - sv.free_on_device(); - } - - // Reset - for (int i = 0; i < TEST_CASES; i++) { - sv = create_random_state_vector(NUM_BITS); - sv.copy_to_device(); - - sv.reset(ws); - - check = true; - - // Measure to ensure in |00...0> state - for (float r = 0; r < 0.99; r+=0.05) { - // Reset bit sting - std::fill(bs.begin(), bs.end(), -1); - // Measure ... no collapse - sv.batch_measure_all(ws, bs, r, false); - // Is |00...0> state? - all_zeros = std::all_of(bs.begin(), bs.end(), [](int32_t b) { return b==0; }); - check &= all_zeros; - } - - // Should be true, because the state was reset to the zero state - // before measurements. Thus all measurements should yield the - // zero state - REQUIRE(check); - - sv.read_from_device(); - sv.free_on_device(); - } -} diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/test/test_stuff.cpp b/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/test/test_stuff.cpp deleted file mode 100644 index 72c6cdee..00000000 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/test/test_stuff.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2022 The PECOS developers -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -// the License.You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Initial author: Tyson Lawrence - -#include -#include -#include -#include -#include -#include -#include - -#include // cudaMalloc, cudaMemcpy, etc. -#include // cuDoubleComplex -#include // custatevecApplyMatrix -#include // printf -#include // EXIT_FAILURE - -#include "cuda_helper.hpp" // HANDLE_ERROR, HANDLE_CUDA_ERROR - -#include "custatevec_workspace.hpp" -#include "gate_matrices.hpp" -#include "gate.hpp" -#include "state_vector.hpp" -#include "utils.hpp" -#include "quantum_volume.hpp" -#include "version.h" - -using CD = std::complex; - -int main(int argc, char *argv[]) -{ - QuantumVolume qv(2); - qv.print(); -} diff --git a/python/pecos/simulators/cuquantum_old/custatevec/__init__.py b/python/pecos/simulators/cuquantum_old/custatevec/__init__.py deleted file mode 100644 index 37bccffb..00000000 --- a/python/pecos/simulators/cuquantum_old/custatevec/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright 2022 The PECOS Developers -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -# the License.You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. diff --git a/python/pecos/simulators/cuquantum_old/custatevec/bindings.py b/python/pecos/simulators/cuquantum_old/custatevec/bindings.py deleted file mode 100644 index fa62cba2..00000000 --- a/python/pecos/simulators/cuquantum_old/custatevec/bindings.py +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright 2022 The PECOS Developers -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -# the License.You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. - -from . import gates_sq -from . import gates_tq -from . import gates_meas -from . import gates_init - -gate_dict = { - - 'U1q': gates_sq.U1q, - 'RXY1Q': gates_sq.U1q, - - 'RX': gates_sq.RX, - 'RY': gates_sq.RY, - 'RZ': gates_sq.RZ, - - 'H': gates_sq.H, - - 'I': gates_sq.I, - 'X': gates_sq.X, - 'Y': gates_sq.Y, - 'Z': gates_sq.Z, - - 'SqrtZZ': gates_tq.SqrtZZ, - 'RZZ': gates_tq.RZZ, - 'CNOT': gates_tq.CX, - 'CX': gates_tq.CX, - - 'measure Z': gates_meas.Measure, - - 'init |0>': gates_init.init_zero, # Init by measuring (if entangle => random outcome - 'init |1>': gates_init.init_one, # Init by measuring (if entangle => random outcome - - 'leak': gates_init.init_zero, - 'unleak |0>': gates_init.init_zero, - 'unleak |1>': gates_init.init_one, - - # Square root of Paulis - 'Q': gates_sq.Q, # +x-y sqrt of X - 'Qd': gates_sq.Qd, # +x+y sqrt of X dagger - 'R': gates_sq.R, # -z+x sqrt of Y - 'Rd': gates_sq.Rd, # +z-x sqrt of Y dagger - 'S': gates_sq.S, # +y+z sqrt of Z - 'Sd': gates_sq.Sd, # -y+z sqrt of Z dagger - - 'SqrtX': gates_sq.Q, # +x-y sqrt of X - 'SqrtXd': gates_sq.Qd, # +x+y sqrt of X dagger - 'SqrtY': gates_sq.R, # -z+x sqrt of Y - 'SqrtYd': gates_sq.Rd, # +z-x sqrt of Y dagger - 'SqrtZ': gates_sq.S, # +y+z sqrt of Z - 'SqrtZd': gates_sq.Sd, # -y+z sqrt of Z dagger -} diff --git a/python/pecos/simulators/cuquantum_old/custatevec/gates_sq.py b/python/pecos/simulators/cuquantum_old/custatevec/gates_sq.py deleted file mode 100644 index e33e24d9..00000000 --- a/python/pecos/simulators/cuquantum_old/custatevec/gates_sq.py +++ /dev/null @@ -1,133 +0,0 @@ -# Copyright 2022 The PECOS Developers -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -# the License.You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. - -from typing import Tuple, Any -from numpy import pi -from ..cuconn import cq - - -def U1q(state, qubit: int, angles: Tuple[float, float], **params: Any) -> None: - """ - U1q(theta, phi) = RZ(phi-pi/2)*RY(theta)*RZ(-phi+pi/2) - - Args: - state: - qubit: - angles: - **params: - - Returns: - - """ - - theta, phi = angles - g = cq.U1q(theta, phi) - g.copy_to_device() - g.apply(state.statevec, state.workspace, [], [qubit], False) - g.free_on_device() - - -def RX(state, location, **params): - angle = params["angle"] - g = cq.Rx(angle) - g.copy_to_device() - g.apply(state.statevec, state.workspace, [], [location], False) - g.free_on_device() - - -def RY(state, location, **params): - angle = params["angle"] - g = cq.Ry(angle) - g.copy_to_device() - g.apply(state.statevec, state.workspace, [], [location], False) - g.free_on_device() - - -def RZ(state, location, **params): - angle = params["angle"] - g = cq.Rz(angle) - g.copy_to_device() - g.apply(state.statevec, state.workspace, [], [location], False) - g.free_on_device() - - -def I(state, location, **params): - pass - - -def X(state, location, **params): - g = cq.PauliX() - g.copy_to_device() - g.apply(state.statevec, state.workspace, [], [location], False) - g.free_on_device() - - -def Y(state, location, **params): - g = cq.PauliY() - g.copy_to_device() - g.apply(state.statevec, state.workspace, [], [location], False) - g.free_on_device() - - -def Z(state, location, **params): - g = cq.PauliZ() - g.copy_to_device() - g.apply(state.statevec, state.workspace, [], [location], False) - g.free_on_device() - - -def H(state, location, **params): - g = cq.Hadamard() - g.copy_to_device() - g.apply(state.statevec, state.workspace, [], [location], False) - g.free_on_device() - - -def Q(state, location, **params): - g = cq.Rx(pi / 2) - g.copy_to_device() - g.apply(state.statevec, state.workspace, [], [location], False) - g.free_on_device() - - -def Qd(state, location, **params): - g = cq.Rx(-pi / 2) - g.copy_to_device() - g.apply(state.statevec, state.workspace, [], [location], False) - g.free_on_device() - - -def R(state, location, **params): - g = cq.Ry(pi / 2) - g.copy_to_device() - g.apply(state.statevec, state.workspace, [], [location], False) - g.free_on_device() - - -def Rd(state, location, **params): - g = cq.Ry(-pi / 2) - g.copy_to_device() - g.apply(state.statevec, state.workspace, [], [location], False) - g.free_on_device() - - -def S(state, location, **params): - g = cq.Rz(pi / 2) - g.copy_to_device() - g.apply(state.statevec, state.workspace, [], [location], False) - g.free_on_device() - - -def Sd(state, location, **params): - g = cq.Rz(-pi / 2) - g.copy_to_device() - g.apply(state.statevec, state.workspace, [], [location], False) - g.free_on_device() diff --git a/python/pecos/simulators/cuquantum_old/custatevec/gates_tq.py b/python/pecos/simulators/cuquantum_old/custatevec/gates_tq.py deleted file mode 100644 index 3f160c4f..00000000 --- a/python/pecos/simulators/cuquantum_old/custatevec/gates_tq.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright 2022 The PECOS Developers -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -# the License.You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. - -from ..cuconn import cq - - -def CX(state, location, **params): - qc, qt = location - g = cq.PauliX() - g.copy_to_device() - g.apply(state.statevec, state.workspace, [qc], [qt], False) - g.free_on_device() - - -def SqrtZZ(state, location, **params): - g = cq.SqrtZZ() - g.copy_to_device() - g.apply(state.statevec, state.workspace, [], location, False) - g.free_on_device() - - -def RZZ(state, location, **params): - angle = params["angle"] - g = cq.RZZ(angle) - g.copy_to_device() - g.apply(state.statevec, state.workspace, [], location, False) - g.free_on_device() diff --git a/python/pecos/simulators/cuquantum_old/custatevec/state.py b/python/pecos/simulators/cuquantum_old/custatevec/state.py deleted file mode 100644 index b648c078..00000000 --- a/python/pecos/simulators/cuquantum_old/custatevec/state.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright 2022 The PECOS Developers -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -# the License.You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. - -from . import bindings -from ..cuconn import cq - -try: - from typing import Self -except: - from typing_extensions import Self - - -class CuStateVec: - def __init__(self, num_qubits: int) -> None: - if not isinstance(num_qubits, int): - raise Exception("``num_qubits`` should be of type ``int.``") - - self.num_qubits = num_qubits - self.workspace = cq.CuStatevecWorkspace() - self.statevec = cq.StateVector(num_qubits) - self.statevec.init_on_device() - self.workspace_gates = [] - - # result = state.bindings[symbol](state, location, **params) - self.bindings = bindings.gate_dict - - def get_probs(self) -> None: - self.statevec.read_from_device() - return self.statevec.get_probabilities(self.workspace)[0] - - def reset(self) -> Self: - """Reset the quantum state for another run without reinitializing.""" - self.statevec.free_on_device() - self.statevec.init_on_device() - - return self - - def __del__(self): - wqs = list(self.workspace_gates) - for g in wqs: - g.free_on_device() - self.workspace_gates.remove(g) - - self.statevec.free_on_device() - del self.statevec - del self.workspace diff --git a/python/pecos/simulators/custatevec/__init__.py b/python/pecos/simulators/custatevec/__init__.py deleted file mode 100644 index cd4bd477..00000000 --- a/python/pecos/simulators/custatevec/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright 2023 The PECOS Developers -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -# the License.You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. - -from pecos.simulators.custatevec import bindings -from pecos.simulators.custatevec.state import CuStateVec diff --git a/python/quantum-pecos/LICENSE b/python/quantum-pecos/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/python/quantum-pecos/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/MANIFEST.in b/python/quantum-pecos/MANIFEST.in similarity index 100% rename from MANIFEST.in rename to python/quantum-pecos/MANIFEST.in diff --git a/python/quantum-pecos/NOTICE b/python/quantum-pecos/NOTICE new file mode 120000 index 00000000..fb376cfa --- /dev/null +++ b/python/quantum-pecos/NOTICE @@ -0,0 +1 @@ +../../NOTICE \ No newline at end of file diff --git a/python/quantum-pecos/README.md b/python/quantum-pecos/README.md new file mode 120000 index 00000000..fe840054 --- /dev/null +++ b/python/quantum-pecos/README.md @@ -0,0 +1 @@ +../../README.md \ No newline at end of file diff --git a/pyproject.toml b/python/quantum-pecos/pyproject.toml similarity index 87% rename from pyproject.toml rename to python/quantum-pecos/pyproject.toml index 5050dfd7..ffce4c67 100644 --- a/pyproject.toml +++ b/python/quantum-pecos/pyproject.toml @@ -15,12 +15,12 @@ build-backend = "setuptools.build_meta" [project] name = "quantum-pecos" -version = "0.6.0.dev5" +version = "0.6.0.dev6" authors = [ {name = "The PECOS Developers"}, ] maintainers =[ - {name = "Ciaran Ryan-Anderson", email = "ciaran.ryan-anderson@quantinuum.com"}, + {name = "Ciaran Ryan-Anderson", email = "ciaranra@gmail.com"}, ] description = """PECOS is a library/framework for the evaluation, study, and design of QEC protocols. It also provides the ability to study and evaluate the performance advanced hybrid quantum/classical compute execution models for NISQ algorithms and beyond.""" readme = "README.md" @@ -28,11 +28,12 @@ requires-python = ">=3.10" license = { file = "LICENSE"} keywords = ["quantum", "QEC", "simulation", "PECOS"] dependencies = [ - "phir>=0.3.3,<0.4", + "pecos-rslib==0.6.0.dev6", + "phir>=0.3.3", "numpy>=1.15.0,<2.0", - "scipy>=1.1.0,<2.0", - "networkx>=2.1.0,<3.0", - "matplotlib>=2.2.0,<4.0", + "scipy>=1.1.0", + "networkx>=2.1.0", + "matplotlib>=2.2.0", ] classifiers = [ "Development Status :: 4 - Beta", @@ -55,8 +56,8 @@ repository = "https://github.com/PECOS-packages/PECOS" [project.optional-dependencies] simulators = [ "cython", - "pybind11>=2.2.3,<3.0", - "projectq>=0.5.0,<0.9.0", + "pybind11>=2.2.3", + "projectq>=0.5.0", "qulacs>=0.6.4", "pyquest>=0.0.1", ] @@ -88,6 +89,12 @@ all = [ "quantum-pecos[tests]", ] +[tool.hatc.metadata] +allow-direct-references = true + +[tool.hatch.build.targets.wheel] +packages = ["src/pecos"] + [tool.distutils.build_ext] inplace = 1 @@ -96,12 +103,12 @@ universal = 1 [tool.setuptools] zip-safe = false -package-dir = {"" = "python"} +package-dir = {"" = "src"} license-files = ["LICENSE"] include-package-data = false [tool.setuptools.packages.find] -where = ["python"] +where = ["src"] include = ["pecos*"] namespaces = true @@ -113,4 +120,3 @@ namespaces = true [tool.black] line-length = 120 -extend-exclude = "python/pecos/simulators/cuquantum_old/*" diff --git a/python/quantum-pecos/requirements.txt b/python/quantum-pecos/requirements.txt new file mode 100644 index 00000000..3f669181 --- /dev/null +++ b/python/quantum-pecos/requirements.txt @@ -0,0 +1,35 @@ +# +# This file is autogenerated by pip-compile with Python 3.12 +# by the following command: +# +# pip-compile --extra=tests --no-annotate --no-emit-index-url --output-file=python/quantum-pecos/requirements.txt --strip-extras python/quantum-pecos/pyproject.toml +# +annotated-types==0.7.0 +attrs==24.2.0 +contourpy==1.3.0 +cycler==0.12.1 +fonttools==4.54.1 +hypothesis==6.115.3 +iniconfig==2.0.0 +kiwisolver==1.4.7 +markdown-it-py==3.0.0 +matplotlib==3.9.2 +mdurl==0.1.2 +networkx==3.4.1 +numpy==1.26.4 +packaging==24.1 +phir==0.3.3 +pillow==11.0.0 +pluggy==1.5.0 +pydantic==2.9.2 +pydantic-core==2.23.4 +pygments==2.18.0 +pyparsing==3.2.0 +pytest==8.3.3 +python-dateutil==2.9.0.post0 +rich==13.9.2 +scipy==1.14.1 +six==1.16.0 +sortedcontainers==2.4.0 +typing-extensions==4.12.2 +pecos-rslib==0.6.0.dev6 diff --git a/python/pecos/__init__.py b/python/quantum-pecos/src/pecos/__init__.py similarity index 90% rename from python/pecos/__init__.py rename to python/quantum-pecos/src/pecos/__init__.py index 618b09c0..1f959d0f 100644 --- a/python/pecos/__init__.py +++ b/python/quantum-pecos/src/pecos/__init__.py @@ -26,7 +26,18 @@ __version__ = "0.0.0" # PECOS namespaces -from pecos import circuit_converters, circuits, decoders, engines, error_models, misc, qeccs, simulators, tools +from pecos import ( + circuit_converters, + circuits, + decoders, + engines, + error_models, + misc, + qeccs, + rslib, + simulators, + tools, +) from pecos.circuits.quantum_circuit import QuantumCircuit from pecos.engines import circuit_runners from pecos.engines.cvm.binarray2 import BinArray2 as BinArray @@ -34,6 +45,7 @@ __all__ = [ "__version__", + "rslib", "circuits", "qeccs", "simulators", diff --git a/python/pecos/circuit_converters/__init__.py b/python/quantum-pecos/src/pecos/circuit_converters/__init__.py similarity index 100% rename from python/pecos/circuit_converters/__init__.py rename to python/quantum-pecos/src/pecos/circuit_converters/__init__.py diff --git a/python/pecos/circuit_converters/checks2circuit.py b/python/quantum-pecos/src/pecos/circuit_converters/checks2circuit.py similarity index 83% rename from python/pecos/circuit_converters/checks2circuit.py rename to python/quantum-pecos/src/pecos/circuit_converters/checks2circuit.py index db2624dc..6be5ae36 100644 --- a/python/pecos/circuit_converters/checks2circuit.py +++ b/python/quantum-pecos/src/pecos/circuit_converters/checks2circuit.py @@ -76,8 +76,7 @@ def compile(self, instr, abstract_circuit, mapping=None): if make_ticks["max_zdatas"]: # init [data ticks] meas temp = make_ticks["max_zdatas"] + 1 - if temp > largest_tick: - largest_tick = temp + largest_tick = max(temp, largest_tick) if not make_ticks["max_xdatas"] and not make_ticks["max_zdatas"]: msg = "Something very weird happened!" @@ -88,7 +87,9 @@ def compile(self, instr, abstract_circuit, mapping=None): # find maximum tick for gate_symbol, _locations, params in abstract_circuit.items(): if gate_symbol in {"X check", "Z check"}: - ancilla_ticks = params["ancilla_ticks"] # Initialization of the ancilla. + ancilla_ticks = params[ + "ancilla_ticks" + ] # Initialization of the ancilla. data_ticks = params["data_ticks"] meas_ticks = params["meas_ticks"] @@ -98,14 +99,12 @@ def compile(self, instr, abstract_circuit, mapping=None): tick_list = [ticks] for t in tick_list: - if t > largest_tick: - largest_tick = t + largest_tick = max(t, largest_tick) else: tick = params["tick"] - if tick > largest_tick: - largest_tick = tick + largest_tick = max(tick, largest_tick) # A quantum circuit with number of ticks == ``largest_tick`` circuit = QuantumCircuit(largest_tick + 1, **gate_params) @@ -140,10 +139,16 @@ def compile(self, instr, abstract_circuit, mapping=None): # Add ancilla init # ---------------- if isinstance(ancilla_ticks, int): - circuit.update({"init |0>": {mapping[ancillas]}}, tick=ancilla_ticks) + circuit.update( + {"init |0>": {mapping[ancillas]}}, + tick=ancilla_ticks, + ) if gate_symbol == "X check": - circuit.update({"H": {mapping[ancillas]}}, tick=ancilla_ticks + 1) + circuit.update( + {"H": {mapping[ancillas]}}, + tick=ancilla_ticks + 1, + ) circuit.update({"H": {mapping[ancillas]}}, tick=meas_ticks - 1) else: msg = "Can not currently handle multiple ancilla checks!" @@ -154,10 +159,16 @@ def compile(self, instr, abstract_circuit, mapping=None): if hasattr(data_ticks, "__iter__"): if gate_symbol == "X check": for i, t in enumerate(data_ticks): - circuit.update({"CNOT": {(mapping[ancillas], mapping[datas[i]])}}, tick=t) + circuit.update( + {"CNOT": {(mapping[ancillas], mapping[datas[i]])}}, + tick=t, + ) elif gate_symbol == "Z check": for i, t in enumerate(data_ticks): - circuit.update({"CNOT": {(mapping[datas[i]], mapping[ancillas])}}, tick=t) + circuit.update( + {"CNOT": {(mapping[datas[i]], mapping[ancillas])}}, + tick=t, + ) else: msg = "Can not currently handle single data checks!" raise Exception(msg) @@ -166,16 +177,26 @@ def compile(self, instr, abstract_circuit, mapping=None): # ------------------------ if isinstance(meas_ticks, int): if forced_outcome: - circuit.update({"measure Z": {mapping[ancillas]}}, tick=meas_ticks) + circuit.update( + {"measure Z": {mapping[ancillas]}}, + tick=meas_ticks, + ) else: - circuit.update({"measure Z": {mapping[ancillas]}}, tick=meas_ticks, forced_outcome=0) + circuit.update( + {"measure Z": {mapping[ancillas]}}, + tick=meas_ticks, + forced_outcome=0, + ) else: msg = "Can not currently handle multiple ancilla checks!" raise Exception(msg) else: tick = params["tick"] - circuit.update({gate_symbol: self.mapset(mapping, set(locations))}, tick=tick) + circuit.update( + {gate_symbol: self.mapset(mapping, set(locations))}, + tick=tick, + ) return circuit # Return QuantumCircuit and number of ancillas used in this circuit. @@ -220,8 +241,7 @@ def _check_ticks(abstract_circuit): break if gate_symbol == "X check": - if len(datas) > max_xdatas: - max_xdatas = len(datas) + max_xdatas = max(len(datas), max_xdatas) elif len(datas) > max_zdatas: max_zdatas = len(datas) diff --git a/python/pecos/circuit_converters/std2chs.py b/python/quantum-pecos/src/pecos/circuit_converters/std2chs.py similarity index 97% rename from python/pecos/circuit_converters/std2chs.py rename to python/quantum-pecos/src/pecos/circuit_converters/std2chs.py index 0d1b3b0a..db9cbd70 100644 --- a/python/pecos/circuit_converters/std2chs.py +++ b/python/quantum-pecos/src/pecos/circuit_converters/std2chs.py @@ -138,6 +138,8 @@ def std2chs(quantum_circuit): compiled_circuit.append("CNOT", new_locations, **params) else: - raise Exception('Symbol "%s" is not currently handled by this converter!' % symbol) + raise Exception( + 'Symbol "%s" is not currently handled by this converter!' % symbol, + ) return compiled_circuit diff --git a/python/pecos/circuits/__init__.py b/python/quantum-pecos/src/pecos/circuits/__init__.py similarity index 100% rename from python/pecos/circuits/__init__.py rename to python/quantum-pecos/src/pecos/circuits/__init__.py diff --git a/python/pecos/circuits/hyqc/__init__.py b/python/quantum-pecos/src/pecos/circuits/hyqc/__init__.py similarity index 100% rename from python/pecos/circuits/hyqc/__init__.py rename to python/quantum-pecos/src/pecos/circuits/hyqc/__init__.py diff --git a/python/pecos/circuits/hyqc/conditionals.py b/python/quantum-pecos/src/pecos/circuits/hyqc/conditionals.py similarity index 100% rename from python/pecos/circuits/hyqc/conditionals.py rename to python/quantum-pecos/src/pecos/circuits/hyqc/conditionals.py diff --git a/python/pecos/circuits/hyqc/cops.py b/python/quantum-pecos/src/pecos/circuits/hyqc/cops.py similarity index 100% rename from python/pecos/circuits/hyqc/cops.py rename to python/quantum-pecos/src/pecos/circuits/hyqc/cops.py diff --git a/python/pecos/circuits/hyqc/fund.py b/python/quantum-pecos/src/pecos/circuits/hyqc/fund.py similarity index 100% rename from python/pecos/circuits/hyqc/fund.py rename to python/quantum-pecos/src/pecos/circuits/hyqc/fund.py diff --git a/python/pecos/circuits/hyqc/hyqc.py b/python/quantum-pecos/src/pecos/circuits/hyqc/hyqc.py similarity index 99% rename from python/pecos/circuits/hyqc/hyqc.py rename to python/quantum-pecos/src/pecos/circuits/hyqc/hyqc.py index b2366c6d..5e397ff9 100644 --- a/python/pecos/circuits/hyqc/hyqc.py +++ b/python/quantum-pecos/src/pecos/circuits/hyqc/hyqc.py @@ -10,6 +10,7 @@ # specific language governing permissions and limitations under the License. """A Pythonic representation of hybrid quantum-classical program.""" + from pecos.circuits.hyqc import qops from pecos.circuits.hyqc.fund import Block diff --git a/python/pecos/circuits/hyqc/int.py b/python/quantum-pecos/src/pecos/circuits/hyqc/int.py similarity index 95% rename from python/pecos/circuits/hyqc/int.py rename to python/quantum-pecos/src/pecos/circuits/hyqc/int.py index 1de4ab15..cdc1a5d9 100644 --- a/python/pecos/circuits/hyqc/int.py +++ b/python/quantum-pecos/src/pecos/circuits/hyqc/int.py @@ -105,4 +105,6 @@ def __str__(self) -> str: return f"{self.symbol}" def __repr__(self) -> str: - return f"<{self.__class__.__name__} {self.index} of {self.int.__repr__()[1:-1]}>" + return ( + f"<{self.__class__.__name__} {self.index} of {self.int.__repr__()[1:-1]}>" + ) diff --git a/python/pecos/circuits/hyqc/misc_stmts.py b/python/quantum-pecos/src/pecos/circuits/hyqc/misc_stmts.py similarity index 100% rename from python/pecos/circuits/hyqc/misc_stmts.py rename to python/quantum-pecos/src/pecos/circuits/hyqc/misc_stmts.py diff --git a/python/pecos/circuits/hyqc/qops.py b/python/quantum-pecos/src/pecos/circuits/hyqc/qops.py similarity index 100% rename from python/pecos/circuits/hyqc/qops.py rename to python/quantum-pecos/src/pecos/circuits/hyqc/qops.py diff --git a/python/pecos/circuits/hyqc/qubits.py b/python/quantum-pecos/src/pecos/circuits/hyqc/qubits.py similarity index 100% rename from python/pecos/circuits/hyqc/qubits.py rename to python/quantum-pecos/src/pecos/circuits/hyqc/qubits.py diff --git a/python/pecos/circuits/hyqc/vars.py b/python/quantum-pecos/src/pecos/circuits/hyqc/vars.py similarity index 100% rename from python/pecos/circuits/hyqc/vars.py rename to python/quantum-pecos/src/pecos/circuits/hyqc/vars.py diff --git a/python/pecos/circuits/logical_circuit.py b/python/quantum-pecos/src/pecos/circuits/logical_circuit.py similarity index 96% rename from python/pecos/circuits/logical_circuit.py rename to python/quantum-pecos/src/pecos/circuits/logical_circuit.py index ad80c39a..6e6adb3a 100644 --- a/python/pecos/circuits/logical_circuit.py +++ b/python/quantum-pecos/src/pecos/circuits/logical_circuit.py @@ -99,7 +99,10 @@ def iter_ticks(self): for logical_tick in range(len(self)): for logical_gate, _, _ in self.items(tick=logical_tick): for instr_index, instr_circuit in enumerate(logical_gate.circuits): - params = {"logical_circuit_params": self.metadata, "gate": logical_gate} + params = { + "logical_circuit_params": self.metadata, + "gate": logical_gate, + } params.update(instr_circuit.metadata) for tick in range(len(instr_circuit)): diff --git a/python/pecos/circuits/qasm/__init__.py b/python/quantum-pecos/src/pecos/circuits/qasm/__init__.py similarity index 82% rename from python/pecos/circuits/qasm/__init__.py rename to python/quantum-pecos/src/pecos/circuits/qasm/__init__.py index 24cea07c..33500036 100644 --- a/python/pecos/circuits/qasm/__init__.py +++ b/python/quantum-pecos/src/pecos/circuits/qasm/__init__.py @@ -15,4 +15,22 @@ from pecos.circuits.qasm.gates import ArgGate, Gate, MeasGate, ResetGate from pecos.circuits.qasm.misc import Comment, br from pecos.circuits.qasm.qasm import QASM -from pecos.circuits.qasm.std_gates import CNOT, CX, CY, CZ, RX, RY, RZ, H, Measure, Reset, S, Sdg, T, Tdg, X, Y, Z +from pecos.circuits.qasm.std_gates import ( + CNOT, + CX, + CY, + CZ, + RX, + RY, + RZ, + H, + Measure, + Reset, + S, + Sdg, + T, + Tdg, + X, + Y, + Z, +) diff --git a/python/pecos/circuits/qasm/barrier.py b/python/quantum-pecos/src/pecos/circuits/qasm/barrier.py similarity index 100% rename from python/pecos/circuits/qasm/barrier.py rename to python/quantum-pecos/src/pecos/circuits/qasm/barrier.py diff --git a/python/pecos/circuits/qasm/block.py b/python/quantum-pecos/src/pecos/circuits/qasm/block.py similarity index 100% rename from python/pecos/circuits/qasm/block.py rename to python/quantum-pecos/src/pecos/circuits/qasm/block.py diff --git a/python/pecos/circuits/qasm/conditionals.py b/python/quantum-pecos/src/pecos/circuits/qasm/conditionals.py similarity index 100% rename from python/pecos/circuits/qasm/conditionals.py rename to python/quantum-pecos/src/pecos/circuits/qasm/conditionals.py diff --git a/python/pecos/circuits/qasm/expr.py b/python/quantum-pecos/src/pecos/circuits/qasm/expr.py similarity index 100% rename from python/pecos/circuits/qasm/expr.py rename to python/quantum-pecos/src/pecos/circuits/qasm/expr.py diff --git a/python/pecos/circuits/qasm/func.py b/python/quantum-pecos/src/pecos/circuits/qasm/func.py similarity index 100% rename from python/pecos/circuits/qasm/func.py rename to python/quantum-pecos/src/pecos/circuits/qasm/func.py diff --git a/python/pecos/circuits/qasm/gates.py b/python/quantum-pecos/src/pecos/circuits/qasm/gates.py similarity index 100% rename from python/pecos/circuits/qasm/gates.py rename to python/quantum-pecos/src/pecos/circuits/qasm/gates.py diff --git a/python/pecos/circuits/qasm/misc.py b/python/quantum-pecos/src/pecos/circuits/qasm/misc.py similarity index 100% rename from python/pecos/circuits/qasm/misc.py rename to python/quantum-pecos/src/pecos/circuits/qasm/misc.py diff --git a/python/pecos/circuits/qasm/qasm.py b/python/quantum-pecos/src/pecos/circuits/qasm/qasm.py similarity index 100% rename from python/pecos/circuits/qasm/qasm.py rename to python/quantum-pecos/src/pecos/circuits/qasm/qasm.py diff --git a/python/pecos/circuits/qasm/std_gates.py b/python/quantum-pecos/src/pecos/circuits/qasm/std_gates.py similarity index 100% rename from python/pecos/circuits/qasm/std_gates.py rename to python/quantum-pecos/src/pecos/circuits/qasm/std_gates.py diff --git a/python/pecos/circuits/qasm/vars.py b/python/quantum-pecos/src/pecos/circuits/qasm/vars.py similarity index 100% rename from python/pecos/circuits/qasm/vars.py rename to python/quantum-pecos/src/pecos/circuits/qasm/vars.py diff --git a/python/pecos/circuits/qc2phir.py b/python/quantum-pecos/src/pecos/circuits/qc2phir.py similarity index 90% rename from python/pecos/circuits/qc2phir.py rename to python/quantum-pecos/src/pecos/circuits/qc2phir.py index 639f6650..c40bb404 100644 --- a/python/pecos/circuits/qc2phir.py +++ b/python/quantum-pecos/src/pecos/circuits/qc2phir.py @@ -79,8 +79,16 @@ def to_phir_dict(qc: "pecos.QuantumCircuit") -> dict: """Creates a json str representation of the QuantumCircuit listing all the gates. It does not preserve ticks or parallel gating of different gate types. """ - prog = {"format": "PHIR/JSON", "version": "0.1.0", "metadata": deepcopy(qc.metadata), "ops": []} - prog["metadata"]["source_program_type"] = ["PECOS.QuantumCircuit", ["PECOS", str(pecos.__version__)]] + prog = { + "format": "PHIR/JSON", + "version": "0.1.0", + "metadata": deepcopy(qc.metadata), + "ops": [], + } + prog["metadata"]["source_program_type"] = [ + "PECOS.QuantumCircuit", + ["PECOS", str(pecos.__version__)], + ] data = {"max_qid": 0} if "qvars" in qc.metadata: @@ -129,7 +137,14 @@ def flush_ops_buffer(ops, ops_buffer, current_cond) -> None: } ops.append(block) - def handle_ops_buffer(current_op, ops, ops_buffer, cond, current_cond, force_flush=False): + def handle_ops_buffer( + current_op, + ops, + ops_buffer, + cond, + current_cond, + force_flush=False, + ): if (cond != current_cond or force_flush) and ops_buffer: flush_ops_buffer(ops, ops_buffer, current_cond) ops_buffer = [] @@ -146,7 +161,11 @@ def ops_buffer_append(ops_buffer, current_op, compact_gates=True): if ops_buffer and compact_gates: last_op = ops_buffer[-1] if ( - ("qop" in last_op and "qop" in current_op and last_op["qop"] == current_op["qop"]) + ( + "qop" in last_op + and "qop" in current_op + and last_op["qop"] == current_op["qop"] + ) or (last_op.get("data") == last_op.get("data") == "cvar_export") ) and last_op.get("metadata") == current_op.get("metadata"): if "args" in current_op: @@ -284,11 +303,24 @@ def ops_buffer_append(ops_buffer, current_op, compact_gates=True): if metadata: op["metadata"] = metadata - ops, ops_buffer, current_cond = handle_ops_buffer(op, ops, ops_buffer, cond, current_cond) + ops, ops_buffer, current_cond = handle_ops_buffer( + op, + ops, + ops_buffer, + cond, + current_cond, + ) # Flush the buffer of any remaining operations if ops_buffer: - ops, ops_buffer, current_cond = handle_ops_buffer(None, ops, ops_buffer, None, current_cond, force_flush=True) + ops, ops_buffer, current_cond = handle_ops_buffer( + None, + ops, + ops_buffer, + None, + current_cond, + force_flush=True, + ) num_qubits = len(qid2qsym) prog["metadata"]["num_qubits"] = num_qubits diff --git a/python/pecos/circuits/quantum_circuit.py b/python/quantum-pecos/src/pecos/circuits/quantum_circuit.py similarity index 95% rename from python/pecos/circuits/quantum_circuit.py rename to python/quantum-pecos/src/pecos/circuits/quantum_circuit.py index 5c1fe927..a2dfddad 100644 --- a/python/pecos/circuits/quantum_circuit.py +++ b/python/quantum-pecos/src/pecos/circuits/quantum_circuit.py @@ -217,7 +217,9 @@ def to_json_str(self) -> str: def _fix_json_meta(meta): """Fix some of the type issues for converting json rep back to a QuantumCircuit.""" if "var_output" in meta: - meta["var_output"] = {int(k): tuple(v) for k, v in meta["var_output"].items()} + meta["var_output"] = { + int(k): tuple(v) for k, v in meta["var_output"].items() + } return meta @classmethod @@ -232,7 +234,11 @@ def from_json_str(cls, qc_json) -> QuantumCircuit: sym = gate_dict["sym"] qubits = gate_dict["qubits"] - qubits = set(qubits) if qubits and isinstance(qubits[0], int) else {tuple(q) for q in qubits} + qubits = ( + set(qubits) + if qubits and isinstance(qubits[0], int) + else {tuple(q) for q in qubits} + ) meta = gate_dict["metadata"] meta = cls._fix_json_meta(meta) @@ -301,7 +307,10 @@ def __str__(self) -> str: str_list.append("{%s}" % tick_list) if self.metadata: - return "QuantumCircuit(params={}, ticks=[{}])".format(str(self.metadata), ", ".join(str_list)) + return "QuantumCircuit(params={}, ticks=[{}])".format( + str(self.metadata), + ", ".join(str_list), + ) else: return "QuantumCircuit([%s])" % ", ".join(str_list) @@ -366,7 +375,9 @@ def add(self, symbol, locations=None, **params): gate.locations.update(gate_locations) break else: - self.symbols[gate_symbol].append(self.Gate(gate_symbol, params, gate_locations)) + self.symbols[gate_symbol].append( + self.Gate(gate_symbol, params, gate_locations), + ) return self @@ -429,7 +440,9 @@ def _verify_qudits(self, gate_dict): self.circuit.qudits.add(qi) if qi in self.active_qudits: - raise Exception("Qudit %s has already been acted on by a gate!" % str(qi)) + raise Exception( + "Qudit %s has already been acted on by a gate!" % str(qi), + ) else: self.active_qudits.add(qi) diff --git a/python/pecos/classical_interpreters/__init__.py b/python/quantum-pecos/src/pecos/classical_interpreters/__init__.py similarity index 100% rename from python/pecos/classical_interpreters/__init__.py rename to python/quantum-pecos/src/pecos/classical_interpreters/__init__.py diff --git a/python/pecos/classical_interpreters/classical_interpreter_abc.py b/python/quantum-pecos/src/pecos/classical_interpreters/classical_interpreter_abc.py similarity index 100% rename from python/pecos/classical_interpreters/classical_interpreter_abc.py rename to python/quantum-pecos/src/pecos/classical_interpreters/classical_interpreter_abc.py diff --git a/python/pecos/classical_interpreters/phir_classical_interpreter.py b/python/quantum-pecos/src/pecos/classical_interpreters/phir_classical_interpreter.py similarity index 94% rename from python/pecos/classical_interpreters/phir_classical_interpreter.py rename to python/quantum-pecos/src/pecos/classical_interpreters/phir_classical_interpreter.py index 14a623fd..42c2b72d 100644 --- a/python/pecos/classical_interpreters/phir_classical_interpreter.py +++ b/python/quantum-pecos/src/pecos/classical_interpreters/phir_classical_interpreter.py @@ -65,7 +65,11 @@ def reset(self): self.foreign_obj = None self._reset_env() - def init(self, program: str | (dict | QuantumCircuit), foreign_obj: ForeignObject | None = None) -> int: + def init( + self, + program: str | (dict | QuantumCircuit), + foreign_obj: ForeignObject | None = None, + ) -> int: """Initialize the interpreter to validate the format of the program, optimize the program representation, etc. """ @@ -73,7 +77,10 @@ def init(self, program: str | (dict | QuantumCircuit), foreign_obj: ForeignObjec self.foreign_obj = foreign_obj # Make sure we have `program` in the correct format or convert to PHIR/dict. - if isinstance(program, str): # Assume it is in the PHIR/JSON format and convert to dict + if isinstance( + program, + str, + ): # Assume it is in the PHIR/JSON format and convert to dict self.program = json.loads(program) elif isinstance(self.program, (PyPMIR, dict)): pass @@ -136,7 +143,12 @@ def add_cvar(self, cvar: str, dtype, size: int): self.cenv.append(dtype(0)) self.cid2dtype.append(dtype) self.cvar_meta.append( - pt.data.CVarDefine(size=size, data_type=data_type_map_rev[dtype], cvar_id=cid, variable=cvar), + pt.data.CVarDefine( + size=size, + data_type=data_type_map_rev[dtype], + cvar_id=cid, + variable=cvar, + ), ) def _flatten_blocks(self, seq: Sequence): @@ -338,7 +350,12 @@ def results(self, return_int=True) -> dict: return result - def result_bits(self, bits: Iterable[tuple[str, int]], *, filter_private=True) -> dict[tuple[str, int], int]: + def result_bits( + self, + bits: Iterable[tuple[str, int]], + *, + filter_private=True, + ) -> dict[tuple[str, int], int]: """Git a dictionary of bit values given an iterable of bits (which are encoded as tuple[str, int] for str[int]).""" send_meas = {} diff --git a/python/pecos/decoders/__init__.py b/python/quantum-pecos/src/pecos/decoders/__init__.py similarity index 100% rename from python/pecos/decoders/__init__.py rename to python/quantum-pecos/src/pecos/decoders/__init__.py diff --git a/python/pecos/decoders/dummy_decoder/__init__.py b/python/quantum-pecos/src/pecos/decoders/dummy_decoder/__init__.py similarity index 100% rename from python/pecos/decoders/dummy_decoder/__init__.py rename to python/quantum-pecos/src/pecos/decoders/dummy_decoder/__init__.py diff --git a/python/pecos/decoders/dummy_decoder/dummy_decoder.py b/python/quantum-pecos/src/pecos/decoders/dummy_decoder/dummy_decoder.py similarity index 100% rename from python/pecos/decoders/dummy_decoder/dummy_decoder.py rename to python/quantum-pecos/src/pecos/decoders/dummy_decoder/dummy_decoder.py diff --git a/python/pecos/decoders/mwpm2d/__init__.py b/python/quantum-pecos/src/pecos/decoders/mwpm2d/__init__.py similarity index 100% rename from python/pecos/decoders/mwpm2d/__init__.py rename to python/quantum-pecos/src/pecos/decoders/mwpm2d/__init__.py diff --git a/python/pecos/decoders/mwpm2d/mwpm2d.py b/python/quantum-pecos/src/pecos/decoders/mwpm2d/mwpm2d.py similarity index 97% rename from python/pecos/decoders/mwpm2d/mwpm2d.py rename to python/quantum-pecos/src/pecos/decoders/mwpm2d/mwpm2d.py index 03fc5298..9ecb8df6 100644 --- a/python/pecos/decoders/mwpm2d/mwpm2d.py +++ b/python/quantum-pecos/src/pecos/decoders/mwpm2d/mwpm2d.py @@ -104,7 +104,9 @@ def decode(self, measurements, error_params=None): n2 = matching[n1] # Don't continue if node has already been covered or path starts and ends with virtuals. - if n1 in nodes_paired or (str(n1).startswith("v") and str(n2).startswith("v")): + if n1 in nodes_paired or ( + str(n1).startswith("v") and str(n2).startswith("v") + ): continue nodes_paired.add(n2) diff --git a/python/pecos/decoders/mwpm2d/precomputing.py b/python/quantum-pecos/src/pecos/decoders/mwpm2d/precomputing.py similarity index 91% rename from python/pecos/decoders/mwpm2d/precomputing.py rename to python/quantum-pecos/src/pecos/decoders/mwpm2d/precomputing.py index 57f24cb6..07a57c45 100644 --- a/python/pecos/decoders/mwpm2d/precomputing.py +++ b/python/quantum-pecos/src/pecos/decoders/mwpm2d/precomputing.py @@ -27,10 +27,16 @@ def precompute(instr): """ qecc = instr.qecc - if qecc.name == "4.4.4.4 Surface Code" and qecc.circuit_compiler.name == "Check2Circuits": + if ( + qecc.name == "4.4.4.4 Surface Code" + and qecc.circuit_compiler.name == "Check2Circuits" + ): precomputed_data = code_surface4444(instr) - elif qecc.name == "Medial 4.4.4.4 Surface Code" and qecc.circuit_compiler.name == "Check2Circuits": + elif ( + qecc.name == "Medial 4.4.4.4 Surface Code" + and qecc.circuit_compiler.name == "Check2Circuits" + ): precomputed_data = code_surface4444medial(instr) else: @@ -160,7 +166,8 @@ def surface4444_identity(instr): edges = d2edge_z else: raise Exception( - "This decoder can only handle check of purely X or Z type rather than %s!" % gate_symbol, + "This decoder can only handle check of purely X or Z type rather than %s!" + % gate_symbol, ) syn_list = edges.setdefault(data, []) @@ -239,7 +246,7 @@ def surface4444_identity(instr): edge2d = edges_z virtual_edge_data = virtual_edge_data_z - paths = nx.shortest_path(temp_graph) + paths = dict(nx.shortest_path(temp_graph)) for n1, wdict in paths.items(): for n2, syn_path in wdict.items(): @@ -255,7 +262,13 @@ def surface4444_identity(instr): s1 = s2 if (n1 not in virt) and (n2 not in virt): - g.add_edge(n1, n2, weight=-weight, syn_path=syn_path, data_path=data_path) + g.add_edge( + n1, + n2, + weight=-weight, + syn_path=syn_path, + data_path=data_path, + ) syn = set(g.nodes()) syn -= virt @@ -283,7 +296,12 @@ def surface4444_identity(instr): data_path.append(data) s1 = s2 - virtual_edge_data[s] = {"virtual_node": v, "weight": -weight, "syn_path": syn_path, "data_path": data_path} + virtual_edge_data[s] = { + "virtual_node": v, + "weight": -weight, + "syn_path": syn_path, + "data_path": data_path, + } return info @@ -368,7 +386,8 @@ def surface4444medial_identity(instr): edges = d2edge_z else: raise Exception( - "This decoder can only handle check of purely X or Z type rather than %s!" % gate_symbol, + "This decoder can only handle check of purely X or Z type rather than %s!" + % gate_symbol, ) syn_list = edges.setdefault(data, []) @@ -480,7 +499,7 @@ def surface4444medial_identity(instr): edge2d = edges_z virtual_edge_data = virtual_edge_data_z - paths = nx.shortest_path(temp_graph) + paths = dict(nx.shortest_path(temp_graph)) for n1, wdict in paths.items(): for n2, syn_path in wdict.items(): @@ -496,7 +515,13 @@ def surface4444medial_identity(instr): s1 = s2 if (n1 not in virt) and (n2 not in virt): - g.add_edge(n1, n2, weight=-weight, syn_path=syn_path, data_path=data_path) + g.add_edge( + n1, + n2, + weight=-weight, + syn_path=syn_path, + data_path=data_path, + ) syn = set(g.nodes()) syn -= virt @@ -524,6 +549,11 @@ def surface4444medial_identity(instr): data_path.append(data) s1 = s2 - virtual_edge_data[s] = {"virtual_node": v, "weight": -weight, "syn_path": syn_path, "data_path": data_path} + virtual_edge_data[s] = { + "virtual_node": v, + "weight": -weight, + "syn_path": syn_path, + "data_path": data_path, + } return info diff --git a/python/pecos/engines/__init__.py b/python/quantum-pecos/src/pecos/engines/__init__.py similarity index 100% rename from python/pecos/engines/__init__.py rename to python/quantum-pecos/src/pecos/engines/__init__.py diff --git a/python/pecos/engines/circuit_runners/__init__.py b/python/quantum-pecos/src/pecos/engines/circuit_runners/__init__.py similarity index 100% rename from python/pecos/engines/circuit_runners/__init__.py rename to python/quantum-pecos/src/pecos/engines/circuit_runners/__init__.py diff --git a/python/pecos/engines/circuit_runners/standard.py b/python/quantum-pecos/src/pecos/engines/circuit_runners/standard.py similarity index 92% rename from python/pecos/engines/circuit_runners/standard.py rename to python/quantum-pecos/src/pecos/engines/circuit_runners/standard.py index 0283481c..98b1d9dd 100644 --- a/python/pecos/engines/circuit_runners/standard.py +++ b/python/quantum-pecos/src/pecos/engines/circuit_runners/standard.py @@ -42,7 +42,14 @@ def __init__(self, seed=None) -> None: random.seed(self.seed) @staticmethod - def run(state, circuit, error_gen=None, error_params=None, error_circuits=None, output=None): + def run( + state, + circuit, + error_gen=None, + error_params=None, + error_circuits=None, + output=None, + ): """Args: ---- state: @@ -85,7 +92,11 @@ def run(state, circuit, error_gen=None, error_params=None, error_circuits=None, errors = {} else: if generate_errors: - error_circuits = error_gen.generate_tick_errors(tick_circuit, time, **params) + error_circuits = error_gen.generate_tick_errors( + tick_circuit, + time, + **params, + ) errors = error_circuits.get(time, {}) before_errors = errors.get("before") diff --git a/python/pecos/engines/circuit_runners/timing_runner.py b/python/quantum-pecos/src/pecos/engines/circuit_runners/timing_runner.py similarity index 92% rename from python/pecos/engines/circuit_runners/timing_runner.py rename to python/quantum-pecos/src/pecos/engines/circuit_runners/timing_runner.py index 33ab98dd..672d6a7a 100644 --- a/python/pecos/engines/circuit_runners/timing_runner.py +++ b/python/quantum-pecos/src/pecos/engines/circuit_runners/timing_runner.py @@ -65,7 +65,11 @@ def run_gates(self, state, gates, removed_locations=None): gate_results = {} for symbol, physical_gate_locations, gate_kwargs in gates.items(): ti = timer() - gate_results = state.run_gate(symbol, physical_gate_locations - removed_locations, **gate_kwargs) + gate_results = state.run_gate( + symbol, + physical_gate_locations - removed_locations, + **gate_kwargs, + ) tf = timer() self.total_time += tf - ti self.num_gates += len(physical_gate_locations - removed_locations) diff --git a/python/pecos/engines/cvm/__init__.py b/python/quantum-pecos/src/pecos/engines/cvm/__init__.py similarity index 100% rename from python/pecos/engines/cvm/__init__.py rename to python/quantum-pecos/src/pecos/engines/cvm/__init__.py diff --git a/python/pecos/engines/cvm/binarray.py b/python/quantum-pecos/src/pecos/engines/cvm/binarray.py similarity index 98% rename from python/pecos/engines/cvm/binarray.py rename to python/quantum-pecos/src/pecos/engines/cvm/binarray.py index 43a0a081..4ceb4b76 100644 --- a/python/pecos/engines/cvm/binarray.py +++ b/python/quantum-pecos/src/pecos/engines/cvm/binarray.py @@ -39,7 +39,9 @@ def __init__(self, size: int | str, value: int | None = None) -> None: raise TypeError(msg) def __str__(self) -> str: - bin_str = ["1" if self.array[i] else "0" for i in range(len(self.array) - 1, -1, -1)] + bin_str = [ + "1" if self.array[i] else "0" for i in range(len(self.array) - 1, -1, -1) + ] return "".join(bin_str) def __repr__(self) -> str: diff --git a/python/pecos/engines/cvm/binarray2.py b/python/quantum-pecos/src/pecos/engines/cvm/binarray2.py similarity index 100% rename from python/pecos/engines/cvm/binarray2.py rename to python/quantum-pecos/src/pecos/engines/cvm/binarray2.py diff --git a/python/pecos/engines/cvm/classical.py b/python/quantum-pecos/src/pecos/engines/cvm/classical.py similarity index 93% rename from python/pecos/engines/cvm/classical.py rename to python/quantum-pecos/src/pecos/engines/cvm/classical.py index f810eac8..f97fcd69 100644 --- a/python/pecos/engines/cvm/classical.py +++ b/python/quantum-pecos/src/pecos/engines/cvm/classical.py @@ -127,7 +127,11 @@ def recur_eval_op(expr_dict, output, width): a = recur_eval_op(a, output, width) elif c: # c => unary operation - c = recur_eval_op(c, output, width) if isinstance(c, dict) else get_val(c, output, width) + c = ( + recur_eval_op(c, output, width) + if isinstance(c, dict) + else get_val(c, output, width) + ) a = eval_op(op, c, width=width) @@ -135,7 +139,11 @@ def recur_eval_op(expr_dict, output, width): a = get_val(a, output, width) if b: - b = recur_eval_op(b, output, width) if isinstance(b, dict) else get_val(b, output, width) + b = ( + recur_eval_op(b, output, width) + if isinstance(b, dict) + else get_val(b, output, width) + ) a = eval_op(op, a, b, width=width) @@ -155,7 +163,9 @@ def eval_cop(cop_expr, output, width): """ # Get `t` argument # ---------------- - t = cop_expr["t"] # symbol of where the resulting value will be stored in the output + t = cop_expr[ + "t" + ] # symbol of where the resulting value will be stored in the output if isinstance(t, str): t_sym = t @@ -203,7 +213,10 @@ def eval_condition(conditional_expr, output) -> bool: msg = "Expecting the second conditional element to be bool." raise TypeError(msg) - return eval_condition(conditional_expr[0], output) == eval_condition(conditional_expr[1], output) + return eval_condition(conditional_expr[0], output) == eval_condition( + conditional_expr[1], + output, + ) if conditional_expr: a = conditional_expr["a"] diff --git a/python/pecos/engines/cvm/cvm.py b/python/quantum-pecos/src/pecos/engines/cvm/cvm.py similarity index 100% rename from python/pecos/engines/cvm/cvm.py rename to python/quantum-pecos/src/pecos/engines/cvm/cvm.py diff --git a/python/pecos/engines/cvm/sim_func.py b/python/quantum-pecos/src/pecos/engines/cvm/sim_func.py similarity index 100% rename from python/pecos/engines/cvm/sim_func.py rename to python/quantum-pecos/src/pecos/engines/cvm/sim_func.py diff --git a/python/pecos/engines/cvm/wasm.py b/python/quantum-pecos/src/pecos/engines/cvm/wasm.py similarity index 100% rename from python/pecos/engines/cvm/wasm.py rename to python/quantum-pecos/src/pecos/engines/cvm/wasm.py diff --git a/python/pecos/engines/cvm/wasm_vms/__init__.py b/python/quantum-pecos/src/pecos/engines/cvm/wasm_vms/__init__.py similarity index 100% rename from python/pecos/engines/cvm/wasm_vms/__init__.py rename to python/quantum-pecos/src/pecos/engines/cvm/wasm_vms/__init__.py diff --git a/python/pecos/engines/cvm/wasm_vms/pywasm.py b/python/quantum-pecos/src/pecos/engines/cvm/wasm_vms/pywasm.py similarity index 100% rename from python/pecos/engines/cvm/wasm_vms/pywasm.py rename to python/quantum-pecos/src/pecos/engines/cvm/wasm_vms/pywasm.py diff --git a/python/pecos/engines/cvm/wasm_vms/pywasm3.py b/python/quantum-pecos/src/pecos/engines/cvm/wasm_vms/pywasm3.py similarity index 100% rename from python/pecos/engines/cvm/wasm_vms/pywasm3.py rename to python/quantum-pecos/src/pecos/engines/cvm/wasm_vms/pywasm3.py diff --git a/python/pecos/engines/cvm/wasm_vms/wasmer.py b/python/quantum-pecos/src/pecos/engines/cvm/wasm_vms/wasmer.py similarity index 93% rename from python/pecos/engines/cvm/wasm_vms/wasmer.py rename to python/quantum-pecos/src/pecos/engines/cvm/wasm_vms/wasmer.py index 8e71100c..c7b7abfa 100644 --- a/python/pecos/engines/cvm/wasm_vms/wasmer.py +++ b/python/quantum-pecos/src/pecos/engines/cvm/wasm_vms/wasmer.py @@ -46,7 +46,11 @@ def __init__(self, file: str | bytes, compiler="wasm_cl") -> None: else: wasm_b = file - store = Store(engine.JIT(CompilerLLVM)) if compiler == "wasm_llvm" else Store(engine.JIT(CompilerCranelift)) + store = ( + Store(engine.JIT(CompilerLLVM)) + if compiler == "wasm_llvm" + else Store(engine.JIT(CompilerCranelift)) + ) module = Module(store, wasm_b) instance = Instance(module) diff --git a/python/pecos/engines/cvm/wasm_vms/wasmtime.py b/python/quantum-pecos/src/pecos/engines/cvm/wasm_vms/wasmtime.py similarity index 100% rename from python/pecos/engines/cvm/wasm_vms/wasmtime.py rename to python/quantum-pecos/src/pecos/engines/cvm/wasm_vms/wasmtime.py diff --git a/python/pecos/engines/hybrid_engine.py b/python/quantum-pecos/src/pecos/engines/hybrid_engine.py similarity index 98% rename from python/pecos/engines/hybrid_engine.py rename to python/quantum-pecos/src/pecos/engines/hybrid_engine.py index 90457af2..c49a65d5 100644 --- a/python/pecos/engines/hybrid_engine.py +++ b/python/quantum-pecos/src/pecos/engines/hybrid_engine.py @@ -16,7 +16,9 @@ import numpy as np -from pecos.classical_interpreters.phir_classical_interpreter import PHIRClassicalInterpreter +from pecos.classical_interpreters.phir_classical_interpreter import ( + PHIRClassicalInterpreter, +) from pecos.engines import hybrid_engine_multiprocessing from pecos.error_models.error_model import NoErrorModel from pecos.machines.generic_machine import GenericMachine @@ -24,7 +26,9 @@ from pecos.simulators.quantum_simulator import QuantumSimulator if TYPE_CHECKING: - from pecos.classical_interpreters.phir_classical_interpreter import ClassicalInterpreter + from pecos.classical_interpreters.phir_classical_interpreter import ( + ClassicalInterpreter, + ) from pecos.error_models.error_model import ErrorModel from pecos.foreign_objects.foreign_object_abc import ForeignObject from pecos.machines.generic_machine import Machine diff --git a/python/pecos/engines/hybrid_engine_multiprocessing.py b/python/quantum-pecos/src/pecos/engines/hybrid_engine_multiprocessing.py similarity index 90% rename from python/pecos/engines/hybrid_engine_multiprocessing.py rename to python/quantum-pecos/src/pecos/engines/hybrid_engine_multiprocessing.py index 28f7efd0..ad51e98c 100644 --- a/python/pecos/engines/hybrid_engine_multiprocessing.py +++ b/python/quantum-pecos/src/pecos/engines/hybrid_engine_multiprocessing.py @@ -61,7 +61,7 @@ def run_multisim( np.random.seed(seed) max_value = np.iinfo(np.int32).max - manager = multiprocessing.Manager() + manager = multiprocessing.get_context("spawn").Manager() queue = manager.Queue() args = [] for i, sh in enumerate(multi_shots): @@ -76,7 +76,7 @@ def run_multisim( args.append((queue, eng.run, kwargs_temp, i)) # Launch multiple serial sims - with multiprocessing.Pool(processes=pool_size) as pool: + with multiprocessing.get_context("spawn").Pool(processes=pool_size) as pool: presults = pool.map(worker_wrapper, args) msg_dict = {} @@ -114,7 +114,10 @@ def run_multisim( if errors: for i, pid, error_msg in errors: - warn(f"process {i} with pid = {pid} had this error message: {error_msg}", stacklevel=2) + warn( + f"process {i} with pid = {pid} had this error message: {error_msg}", + stacklevel=2, + ) msg = "Processes experienced errors!" raise MultisimError(msg) @@ -137,8 +140,13 @@ def worker_wrapper(args) -> tuple[dict, dict]: # TODO: Find a more elegant solution. foreign_object = pkwargs["foreign_object"] - if isinstance(foreign_object, dict) and hasattr(foreign_object["fobj_class"], "from_dict"): - pkwargs["foreign_object"] = foreign_object["fobj_class"].from_dict(foreign_object) + if isinstance(foreign_object, dict) and hasattr( + foreign_object["fobj_class"], + "from_dict", + ): + pkwargs["foreign_object"] = foreign_object["fobj_class"].from_dict( + foreign_object, + ) results = {} try: diff --git a/python/pecos/engines/hybrid_engine_old.py b/python/quantum-pecos/src/pecos/engines/hybrid_engine_old.py similarity index 85% rename from python/pecos/engines/hybrid_engine_old.py rename to python/quantum-pecos/src/pecos/engines/hybrid_engine_old.py index 76391c35..9583382c 100644 --- a/python/pecos/engines/hybrid_engine_old.py +++ b/python/quantum-pecos/src/pecos/engines/hybrid_engine_old.py @@ -91,7 +91,12 @@ def run( if params.get("error_free", False): errors = {} else: - error_circuits = error_gen.generate_tick_errors(tick_circuit, time, output, **params) + error_circuits = error_gen.generate_tick_errors( + tick_circuit, + time, + output, + **params, + ) errors = error_circuits.get(time, {}) # TODO: Need run the error generator whether we want errors or not because of leakage @@ -114,7 +119,14 @@ def run( # ideal tick circuit # ------------------ - self.run_circuit(state, output, output_export, tick_circuit, error_gen, removed_locations=removed) + self.run_circuit( + state, + output, + output_export, + tick_circuit, + error_gen, + removed_locations=removed, + ) if circ_inspector: circ_inspector.analyze(tick_circuit, time, output) @@ -130,7 +142,15 @@ def run( return output, error_circuits - def run_circuit(self, state, output, output_export, circuit, error_gen, removed_locations=None): + def run_circuit( + self, + state, + output, + output_export, + circuit, + error_gen, + removed_locations=None, + ): """Args: circuit (QuantumCircuit): A circuit instance or object with an appropriate items() generator. @@ -149,7 +169,11 @@ def run_circuit(self, state, output, output_export, circuit, error_gen, removed_ if params.get("skip"): continue - eval_cond2 = eval_condition(params.get("cond2"), output) if params.get("cond2") else True + eval_cond2 = ( + eval_condition(params.get("cond2"), output) + if params.get("cond2") + else True + ) if eval_condition(params.get("cond"), output) and eval_cond2: # Run quantum simulator @@ -177,10 +201,16 @@ def run_circuit(self, state, output, output_export, circuit, error_gen, removed_ elif isinstance(val, BinArray): output_export[sym] = BinArray(str(val)) else: - msg = f"This output type `{type(val)}` not handled at export!" + msg = ( + f"This output type `{type(val)}` not handled at export!" + ) raise Exception(msg) - elif not params.get("comment") and not params.get("linebreak") and not params.get("barrier"): + elif ( + not params.get("comment") + and not params.get("linebreak") + and not params.get("barrier") + ): print("received:", symbol, locations, params) msg = "A cop must have an `expr`, `comment`, `linebreak`, or `barrier` entry!" raise Exception(msg) @@ -189,7 +219,13 @@ def run_circuit(self, state, output, output_export, circuit, error_gen, removed_ pass else: # quantum operation - self.run_gate(state, output, symbol, locations - removed_locations, **params) + self.run_gate( + state, + output, + symbol, + locations - removed_locations, + **params, + ) if symbol == "leak": error_gen.leaked_qubits |= locations @@ -214,7 +250,6 @@ def run_gate(state, output, symbol: str, locations, **params): if params.get("simulate_gate", True): for location in locations: - if params.get("angles") and len(params["angles"]) == 1: params.update({"angle": params["angles"][0]}) elif "angle" in params and "angles" not in params: diff --git a/python/pecos/error_models/__init__.py b/python/quantum-pecos/src/pecos/error_models/__init__.py similarity index 100% rename from python/pecos/error_models/__init__.py rename to python/quantum-pecos/src/pecos/error_models/__init__.py diff --git a/python/pecos/error_models/class_errors_circuit.py b/python/quantum-pecos/src/pecos/error_models/class_errors_circuit.py similarity index 91% rename from python/pecos/error_models/class_errors_circuit.py rename to python/quantum-pecos/src/pecos/error_models/class_errors_circuit.py index d61895f8..d553020e 100644 --- a/python/pecos/error_models/class_errors_circuit.py +++ b/python/quantum-pecos/src/pecos/error_models/class_errors_circuit.py @@ -18,7 +18,13 @@ class ErrorCircuits(dict): def __init__(self) -> None: super().__init__() - def add_circuits(self, time: int, before_faults=None, after_faults=None, replaced_locations=None): + def add_circuits( + self, + time: int, + before_faults=None, + after_faults=None, + replaced_locations=None, + ): """Add error circuits and gate locations to ignore (replaced_locations). Args: diff --git a/python/pecos/error_models/depolarizing_error_model.py b/python/quantum-pecos/src/pecos/error_models/depolarizing_error_model.py similarity index 100% rename from python/pecos/error_models/depolarizing_error_model.py rename to python/quantum-pecos/src/pecos/error_models/depolarizing_error_model.py diff --git a/python/pecos/error_models/error_depolar.py b/python/quantum-pecos/src/pecos/error_models/error_depolar.py similarity index 89% rename from python/pecos/error_models/error_depolar.py rename to python/quantum-pecos/src/pecos/error_models/error_depolar.py index 4c3b65a2..f1d4aa88 100644 --- a/python/pecos/error_models/error_depolar.py +++ b/python/quantum-pecos/src/pecos/error_models/error_depolar.py @@ -19,7 +19,9 @@ from pecos.error_models.noise_impl_old.meas_noise import noise_meas_bitflip from pecos.error_models.noise_impl_old.memory_noise import noise_tq_mem from pecos.error_models.noise_impl_old.sq_noise import noise_depolarizing_sq_gate -from pecos.error_models.noise_impl_old.tq_noise import noise_two_qubit_gates_depolarizing_with_noiseless +from pecos.error_models.noise_impl_old.tq_noise import ( + noise_two_qubit_gates_depolarizing_with_noiseless, +) from pecos.error_models.parent_class_error_gen import ParentErrorModel @@ -69,11 +71,20 @@ def start(self, circuit, error_params, reset_leakage=True): if not self.error_params.get("noiseless_qubits"): self.error_params["noiseless_qubits"] = set() - self.error_params["noiseless_qubits"] = set(self.error_params["noiseless_qubits"]) + self.error_params["noiseless_qubits"] = set( + self.error_params["noiseless_qubits"], + ) return self.error_circuits - def generate_tick_errors(self, tick_circuit, time, output=None, reset_leakage=False, **params): + def generate_tick_errors( + self, + tick_circuit, + time, + output=None, + reset_leakage=False, + **params, + ): """The method that gets called each circuit tick to generate circuit noise for that tick.""" # Get the tick tick_index = time[-1] if isinstance(time, tuple) else time @@ -122,7 +133,12 @@ def generate_tick_errors(self, tick_circuit, time, output=None, reset_leakage=Fa elif symbol == "measure Z": if eval_condition(cond, output): noisy = set(locations) - self.error_params["noiseless_qubits"] - noise_meas_bitflip(noisy, metadata, after, p=self.error_params["p_meas"]) + noise_meas_bitflip( + noisy, + metadata, + after, + p=self.error_params["p_meas"], + ) elif symbol in {"repump", "leak", "unleak"}: pass diff --git a/python/pecos/error_models/error_model.py b/python/quantum-pecos/src/pecos/error_models/error_model.py similarity index 100% rename from python/pecos/error_models/error_model.py rename to python/quantum-pecos/src/pecos/error_models/error_model.py diff --git a/python/pecos/error_models/error_model_abc.py b/python/quantum-pecos/src/pecos/error_models/error_model_abc.py similarity index 100% rename from python/pecos/error_models/error_model_abc.py rename to python/quantum-pecos/src/pecos/error_models/error_model_abc.py diff --git a/python/pecos/error_models/fake_error_model.py b/python/quantum-pecos/src/pecos/error_models/fake_error_model.py similarity index 100% rename from python/pecos/error_models/fake_error_model.py rename to python/quantum-pecos/src/pecos/error_models/fake_error_model.py diff --git a/python/pecos/error_models/generic_error_model.py b/python/quantum-pecos/src/pecos/error_models/generic_error_model.py similarity index 90% rename from python/pecos/error_models/generic_error_model.py rename to python/quantum-pecos/src/pecos/error_models/generic_error_model.py index 11b2986b..589425d9 100644 --- a/python/pecos/error_models/generic_error_model.py +++ b/python/quantum-pecos/src/pecos/error_models/generic_error_model.py @@ -16,10 +16,18 @@ import numpy as np from pecos.error_models.error_model_abc import ErrorModel -from pecos.error_models.noise_impl.noise_initz_bitflip_leakage import noise_initz_bitflip_leakage -from pecos.error_models.noise_impl.noise_meas_bitflip_leakage import noise_meas_bitflip_leakage -from pecos.error_models.noise_impl.noise_sq_depolarizing_leakage import noise_sq_depolarizing_leakage -from pecos.error_models.noise_impl.noise_tq_depolarizing_leakage import noise_tq_depolarizing_leakage +from pecos.error_models.noise_impl.noise_initz_bitflip_leakage import ( + noise_initz_bitflip_leakage, +) +from pecos.error_models.noise_impl.noise_meas_bitflip_leakage import ( + noise_meas_bitflip_leakage, +) +from pecos.error_models.noise_impl.noise_sq_depolarizing_leakage import ( + noise_sq_depolarizing_leakage, +) +from pecos.error_models.noise_impl.noise_tq_depolarizing_leakage import ( + noise_tq_depolarizing_leakage, +) from pecos.error_models.noise_impl_old.gate_groups import one_qubits, two_qubits if TYPE_CHECKING: @@ -112,7 +120,11 @@ def process(self, qops: list[QOp], call_back=None) -> list[QOp | SeqBlock]: # ######################################## # INITS WITH X NOISE if op.name in ["init |0>", "Init", "Init +Z"]: - qops_after = noise_initz_bitflip_leakage(op, p=self._eparams["p_init"], machine=self.machine) + qops_after = noise_initz_bitflip_leakage( + op, + p=self._eparams["p_init"], + machine=self.machine, + ) # ######################################## # ONE QUBIT GATES @@ -148,7 +160,11 @@ def process(self, qops: list[QOp], call_back=None) -> list[QOp | SeqBlock]: # ######################################## # MEASURE X NOISE elif op.name in ["measure Z", "Measure", "Measure +Z"]: - erroneous_ops = noise_meas_bitflip_leakage(op, p=self._eparams["p_meas"], machine=self.machine) + erroneous_ops = noise_meas_bitflip_leakage( + op, + p=self._eparams["p_meas"], + machine=self.machine, + ) else: raise Exception("This error model doesn't handle gate: %s!" % op.name) diff --git a/python/pecos/error_models/noise_impl/__init__.py b/python/quantum-pecos/src/pecos/error_models/noise_impl/__init__.py similarity index 100% rename from python/pecos/error_models/noise_impl/__init__.py rename to python/quantum-pecos/src/pecos/error_models/noise_impl/__init__.py diff --git a/python/pecos/error_models/noise_impl/noise_initz_bitflip.py b/python/quantum-pecos/src/pecos/error_models/noise_impl/noise_initz_bitflip.py similarity index 100% rename from python/pecos/error_models/noise_impl/noise_initz_bitflip.py rename to python/quantum-pecos/src/pecos/error_models/noise_impl/noise_initz_bitflip.py diff --git a/python/pecos/error_models/noise_impl/noise_initz_bitflip_leakage.py b/python/quantum-pecos/src/pecos/error_models/noise_impl/noise_initz_bitflip_leakage.py similarity index 90% rename from python/pecos/error_models/noise_impl/noise_initz_bitflip_leakage.py rename to python/quantum-pecos/src/pecos/error_models/noise_impl/noise_initz_bitflip_leakage.py index 526a6327..a73b0c68 100644 --- a/python/pecos/error_models/noise_impl/noise_initz_bitflip_leakage.py +++ b/python/quantum-pecos/src/pecos/error_models/noise_impl/noise_initz_bitflip_leakage.py @@ -31,7 +31,11 @@ def noise_initz_bitflip_leakage(op: QOp, p: float, machine): not_leaked = args - leaked if not_leaked: - remaining_inits = QOp(name=op.name, args=list(not_leaked), metadata=dict(op.metadata)) + remaining_inits = QOp( + name=op.name, + args=list(not_leaked), + metadata=dict(op.metadata), + ) noisy_ops = noise_initz_bitflip(remaining_inits, p) if noisy_ops: noise.extend(noisy_ops) diff --git a/python/pecos/error_models/noise_impl/noise_meas_bitflip.py b/python/quantum-pecos/src/pecos/error_models/noise_impl/noise_meas_bitflip.py similarity index 98% rename from python/pecos/error_models/noise_impl/noise_meas_bitflip.py rename to python/quantum-pecos/src/pecos/error_models/noise_impl/noise_meas_bitflip.py index ce758f0f..663f385a 100644 --- a/python/pecos/error_models/noise_impl/noise_meas_bitflip.py +++ b/python/quantum-pecos/src/pecos/error_models/noise_impl/noise_meas_bitflip.py @@ -42,8 +42,7 @@ def noise_meas_bitflip(op: QOp, p: float): ) noisy_op.metadata["bitflips"] = bitflips noise.append(noisy_op) - return noise else: - return noise + return None diff --git a/python/pecos/error_models/noise_impl/noise_meas_bitflip_leakage.py b/python/quantum-pecos/src/pecos/error_models/noise_impl/noise_meas_bitflip_leakage.py similarity index 95% rename from python/pecos/error_models/noise_impl/noise_meas_bitflip_leakage.py rename to python/quantum-pecos/src/pecos/error_models/noise_impl/noise_meas_bitflip_leakage.py index d2c94ded..59f0c71c 100644 --- a/python/pecos/error_models/noise_impl/noise_meas_bitflip_leakage.py +++ b/python/quantum-pecos/src/pecos/error_models/noise_impl/noise_meas_bitflip_leakage.py @@ -51,4 +51,7 @@ def noise_meas_bitflip_leakage(op: QOp, p: float, machine): return noise else: - return noise + if noise: + return noise + else: + return None diff --git a/python/pecos/error_models/noise_impl/noise_sq_bitflip.py b/python/quantum-pecos/src/pecos/error_models/noise_impl/noise_sq_bitflip.py similarity index 100% rename from python/pecos/error_models/noise_impl/noise_sq_bitflip.py rename to python/quantum-pecos/src/pecos/error_models/noise_impl/noise_sq_bitflip.py diff --git a/python/pecos/error_models/noise_impl/noise_sq_depolarizing.py b/python/quantum-pecos/src/pecos/error_models/noise_impl/noise_sq_depolarizing.py similarity index 100% rename from python/pecos/error_models/noise_impl/noise_sq_depolarizing.py rename to python/quantum-pecos/src/pecos/error_models/noise_impl/noise_sq_depolarizing.py diff --git a/python/pecos/error_models/noise_impl/noise_sq_depolarizing_leakage.py b/python/quantum-pecos/src/pecos/error_models/noise_impl/noise_sq_depolarizing_leakage.py similarity index 92% rename from python/pecos/error_models/noise_impl/noise_sq_depolarizing_leakage.py rename to python/quantum-pecos/src/pecos/error_models/noise_impl/noise_sq_depolarizing_leakage.py index 5938f268..0444c99c 100644 --- a/python/pecos/error_models/noise_impl/noise_sq_depolarizing_leakage.py +++ b/python/quantum-pecos/src/pecos/error_models/noise_impl/noise_sq_depolarizing_leakage.py @@ -48,7 +48,9 @@ def noise_sq_depolarizing_leakage(op: QOp, p: float, noise_dict: dict, machine): leak_ops = machine.leak(set(noise["L"])) buffered_ops.extend(leak_ops) else: - buffered_ops.extend((noisy_op, QOp(name=sym, args=args, metadata={}))) + buffered_ops.extend( + (noisy_op, QOp(name=sym, args=args, metadata={})), + ) else: buffered_ops.append(noisy_op) diff --git a/python/pecos/error_models/noise_impl/noise_tq_depolarizing.py b/python/quantum-pecos/src/pecos/error_models/noise_impl/noise_tq_depolarizing.py similarity index 100% rename from python/pecos/error_models/noise_impl/noise_tq_depolarizing.py rename to python/quantum-pecos/src/pecos/error_models/noise_impl/noise_tq_depolarizing.py diff --git a/python/pecos/error_models/noise_impl/noise_tq_depolarizing_leakage.py b/python/quantum-pecos/src/pecos/error_models/noise_impl/noise_tq_depolarizing_leakage.py similarity index 100% rename from python/pecos/error_models/noise_impl/noise_tq_depolarizing_leakage.py rename to python/quantum-pecos/src/pecos/error_models/noise_impl/noise_tq_depolarizing_leakage.py diff --git a/python/pecos/error_models/noise_impl_old/__init__.py b/python/quantum-pecos/src/pecos/error_models/noise_impl_old/__init__.py similarity index 100% rename from python/pecos/error_models/noise_impl_old/__init__.py rename to python/quantum-pecos/src/pecos/error_models/noise_impl_old/__init__.py diff --git a/python/pecos/error_models/noise_impl_old/gate_groups.py b/python/quantum-pecos/src/pecos/error_models/noise_impl_old/gate_groups.py similarity index 100% rename from python/pecos/error_models/noise_impl_old/gate_groups.py rename to python/quantum-pecos/src/pecos/error_models/noise_impl_old/gate_groups.py diff --git a/python/pecos/error_models/noise_impl_old/init_noise.py b/python/quantum-pecos/src/pecos/error_models/noise_impl_old/init_noise.py similarity index 91% rename from python/pecos/error_models/noise_impl_old/init_noise.py rename to python/quantum-pecos/src/pecos/error_models/noise_impl_old/init_noise.py index a828abf2..0e020bbf 100644 --- a/python/pecos/error_models/noise_impl_old/init_noise.py +++ b/python/quantum-pecos/src/pecos/error_models/noise_impl_old/init_noise.py @@ -21,7 +21,12 @@ from pecos import QuantumCircuit -def noise_init_bitflip(locations: Sequence[int], after: QuantumCircuit, flip: str, p: float) -> None: +def noise_init_bitflip( + locations: Sequence[int], + after: QuantumCircuit, + flip: str, + p: float, +) -> None: """The noise model for qubit (re)initialization. Args: diff --git a/python/pecos/error_models/noise_impl_old/meas_noise.py b/python/quantum-pecos/src/pecos/error_models/noise_impl_old/meas_noise.py similarity index 73% rename from python/pecos/error_models/noise_impl_old/meas_noise.py rename to python/quantum-pecos/src/pecos/error_models/noise_impl_old/meas_noise.py index f91a7d7f..2173e0c9 100644 --- a/python/pecos/error_models/noise_impl_old/meas_noise.py +++ b/python/quantum-pecos/src/pecos/error_models/noise_impl_old/meas_noise.py @@ -19,7 +19,12 @@ from pecos import QuantumCircuit -def noise_meas_bitflip(locations: set[int], metadata: dict, after: QuantumCircuit, p: float) -> None: +def noise_meas_bitflip( + locations: set[int], + metadata: dict, + after: QuantumCircuit, + p: float, +) -> None: """Bit-flip noise model for measurements. Args: @@ -35,6 +40,14 @@ def noise_meas_bitflip(locations: set[int], metadata: dict, after: QuantumCircui for r, loc in zip(rand_nums, locations): if r: - var = metadata["var_output"][loc] if metadata.get("var_output") else metadata["var"] - - after.append("cop", {loc}, expr={"t": var, "a": var, "op": "^", "b": 1}) # flip output bit + var = ( + metadata["var_output"][loc] + if metadata.get("var_output") + else metadata["var"] + ) + + after.append( + "cop", + {loc}, + expr={"t": var, "a": var, "op": "^", "b": 1}, + ) # flip output bit diff --git a/python/pecos/error_models/noise_impl_old/memory_noise.py b/python/quantum-pecos/src/pecos/error_models/noise_impl_old/memory_noise.py similarity index 91% rename from python/pecos/error_models/noise_impl_old/memory_noise.py rename to python/quantum-pecos/src/pecos/error_models/noise_impl_old/memory_noise.py index f85281f1..f9e674a2 100644 --- a/python/pecos/error_models/noise_impl_old/memory_noise.py +++ b/python/quantum-pecos/src/pecos/error_models/noise_impl_old/memory_noise.py @@ -19,7 +19,11 @@ from pecos import QuantumCircuit -def noise_tq_mem(locations: set[tuple[int, int]], after: QuantumCircuit, p: float) -> None: +def noise_tq_mem( + locations: set[tuple[int, int]], + after: QuantumCircuit, + p: float, +) -> None: """The memory noise model for idling qubits. Args: diff --git a/python/pecos/error_models/noise_impl_old/sq_noise.py b/python/quantum-pecos/src/pecos/error_models/noise_impl_old/sq_noise.py similarity index 90% rename from python/pecos/error_models/noise_impl_old/sq_noise.py rename to python/quantum-pecos/src/pecos/error_models/noise_impl_old/sq_noise.py index 5c671bf4..829f8d6a 100644 --- a/python/pecos/error_models/noise_impl_old/sq_noise.py +++ b/python/quantum-pecos/src/pecos/error_models/noise_impl_old/sq_noise.py @@ -21,7 +21,11 @@ from pecos import QuantumCircuit -def noise_depolarizing_sq_gate(locations: set[int], after: QuantumCircuit, p: float) -> None: +def noise_depolarizing_sq_gate( + locations: set[int], + after: QuantumCircuit, + p: float, +) -> None: """Apply a symmetric depolarizing noise model.""" rand_nums = np.random.random(len(locations)) <= p diff --git a/python/pecos/error_models/noise_impl_old/tq_noise.py b/python/quantum-pecos/src/pecos/error_models/noise_impl_old/tq_noise.py similarity index 91% rename from python/pecos/error_models/noise_impl_old/tq_noise.py rename to python/quantum-pecos/src/pecos/error_models/noise_impl_old/tq_noise.py index ba0cd0fa..d7cca0a4 100644 --- a/python/pecos/error_models/noise_impl_old/tq_noise.py +++ b/python/quantum-pecos/src/pecos/error_models/noise_impl_old/tq_noise.py @@ -15,13 +15,20 @@ import numpy as np -from pecos.error_models.noise_impl_old.gate_groups import error_one_paulis_collection, error_two_paulis_collection +from pecos.error_models.noise_impl_old.gate_groups import ( + error_one_paulis_collection, + error_two_paulis_collection, +) if TYPE_CHECKING: from pecos import QuantumCircuit -def noise_depolarizing_two_qubit_gates(locations: set[tuple[int, int]], after: QuantumCircuit, p: float) -> None: +def noise_depolarizing_two_qubit_gates( + locations: set[tuple[int, int]], + after: QuantumCircuit, + p: float, +) -> None: """Symmetric depolarizing noise for two-qubit gates. # TODO: Describe noise model diff --git a/python/pecos/error_models/old/__init__.py b/python/quantum-pecos/src/pecos/error_models/old/__init__.py similarity index 100% rename from python/pecos/error_models/old/__init__.py rename to python/quantum-pecos/src/pecos/error_models/old/__init__.py diff --git a/python/pecos/error_models/old/depolar_gen.py b/python/quantum-pecos/src/pecos/error_models/old/depolar_gen.py similarity index 86% rename from python/pecos/error_models/old/depolar_gen.py rename to python/quantum-pecos/src/pecos/error_models/old/depolar_gen.py index 28d40066..d08b2745 100644 --- a/python/pecos/error_models/old/depolar_gen.py +++ b/python/quantum-pecos/src/pecos/error_models/old/depolar_gen.py @@ -29,7 +29,14 @@ class DepolarModel(ParentErrorModel): """ measurements: ClassVar[set[str]] = {"measure X", "measure Y", "measure Z"} - inits: ClassVar[set[str]] = {"init |0>", "init |1>", "init |+>", "init |->", "init |+i>", "init |-i>"} + inits: ClassVar[set[str]] = { + "init |0>", + "init |1>", + "init |+>", + "init |->", + "init |+i>", + "init |-i>", + } two_qubits: ClassVar[set[str]] = {"CNOT", "CZ", "SWAP", "G"} inits_z: ClassVar[set[str]] = {"init |0>", "init |1>"} @@ -54,7 +61,12 @@ class DepolarModel(ParentErrorModel): ("Z", "Z"), ] - def __init__(self, model_level="circuit", has_idle_errors=False, perp_errors=False) -> None: + def __init__( + self, + model_level="circuit", + has_idle_errors=False, + perp_errors=False, + ) -> None: """Args: ---- model_level(str): @@ -77,7 +89,9 @@ def __init__(self, model_level="circuit", has_idle_errors=False, perp_errors=Fal zerror_before = self.gen.ErrorStaticSymbol("Z", after=False) pauli_errors = self.gen.ErrorSet({"X", "Y", "Z"}) pauli_errors_before = self.gen.ErrorSet({"X", "Y", "Z"}, after=False) - two_pauli_errors = self.gen.ErrorSetTwoQuditTensorProduct(self.error_two_paulis_collection) + two_pauli_errors = self.gen.ErrorSetTwoQuditTensorProduct( + self.error_two_paulis_collection, + ) if model_level == "code_capacity": self.has_data_errors = True @@ -107,7 +121,10 @@ def __init__(self, model_level="circuit", has_idle_errors=False, perp_errors=Fal self.has_meas_errors = True # Don't generate data errors - self.gen.set_gate_error("data", False) # Don't generate errors for data qudits. + self.gen.set_gate_error( + "data", + False, + ) # Don't generate errors for data qudits. # Generate measurement errors (before errors) self.gen.set_group_error("measurements", pauli_errors_before.error_func) @@ -125,7 +142,10 @@ def __init__(self, model_level="circuit", has_idle_errors=False, perp_errors=Fal self.gen.set_gate_error("measure Z", xerror_before.error_func) if model_level == "circuit": - self.gen.set_gate_group("Z on preps", {"init |+>", "init |->", "init |+i>", "init |-i>"}) + self.gen.set_gate_group( + "Z on preps", + {"init |+>", "init |->", "init |+i>", "init |-i>"}, + ) self.gen.set_gate_group("X on preps", {"init |0>", "init |1>"}) self.gen.set_group_error("Z on preps", zerror.error_func) self.gen.set_group_error("X on preps", xerror.error_func) @@ -180,13 +200,27 @@ def generate_tick_errors(self, tick_circuit, time, **params): # ------------------------------ if self.has_meas_errors or self.has_unitary_errors: for symbol, gate_locations, _ in circuit.items(tick=tick_index): - self.gen.create_errors(self, symbol, gate_locations, after, before, replace) + self.gen.create_errors( + self, + symbol, + gate_locations, + after, + before, + replace, + ) # idle errors # ----------- if self.has_idle_errors: inactive_qudits = circuit.qudits - circuit.active_qudits[tick_index] - self.gen.create_errors(self, "idle", inactive_qudits, after, before, replace) + self.gen.create_errors( + self, + "idle", + inactive_qudits, + after, + before, + replace, + ) self.error_circuits.add_circuits(time, before, after) diff --git a/python/pecos/error_models/old/gatewise_gen.py b/python/quantum-pecos/src/pecos/error_models/old/gatewise_gen.py similarity index 93% rename from python/pecos/error_models/old/gatewise_gen.py rename to python/quantum-pecos/src/pecos/error_models/old/gatewise_gen.py index 6fc2d873..1d823ace 100644 --- a/python/pecos/error_models/old/gatewise_gen.py +++ b/python/quantum-pecos/src/pecos/error_models/old/gatewise_gen.py @@ -29,7 +29,14 @@ class GatewiseModel(ParentErrorModel): """ measurements: ClassVar[set[str]] = {"measure X", "measure Y", "measure Z"} - inits: ClassVar[set[str]] = {"init |0>", "init |1>", "init |+>", "init |->", "init |+i>", "init |-i>"} + inits: ClassVar[set[str]] = { + "init |0>", + "init |1>", + "init |+>", + "init |->", + "init |+i>", + "init |-i>", + } two_qubits: ClassVar[set[str]] = {"CNOT", "CZ", "SWAP", "G"} one_qubits: ClassVar[set[str]] = { "I", @@ -147,7 +154,14 @@ def generate_tick_errors(self, tick_circuit, time, **params): data_qudit_set = params["data_qudit_set"] inactive_qudits -= data_qudit_set - self.gen.create_errors(self, "idle", inactive_qudits, after, before, replace) + self.gen.create_errors( + self, + "idle", + inactive_qudits, + after, + before, + replace, + ) self.error_circuits.add_circuits(time, before, after) diff --git a/python/pecos/error_models/old/xerror_gen.py b/python/quantum-pecos/src/pecos/error_models/old/xerror_gen.py similarity index 86% rename from python/pecos/error_models/old/xerror_gen.py rename to python/quantum-pecos/src/pecos/error_models/old/xerror_gen.py index 1dbfae72..a46acb8c 100644 --- a/python/pecos/error_models/old/xerror_gen.py +++ b/python/quantum-pecos/src/pecos/error_models/old/xerror_gen.py @@ -29,14 +29,25 @@ class XModel(ParentErrorModel): """ measurements: ClassVar[set[str]] = {"measure X", "measure Y", "measure Z"} - inits: ClassVar[set[str]] = {"init |0>", "init |1>", "init |+>", "init |->", "init |+i>", "init |-i>"} + inits: ClassVar[set[str]] = { + "init |0>", + "init |1>", + "init |+>", + "init |->", + "init |+i>", + "init |-i>", + } two_qubits: ClassVar[set[str]] = {"CNOT", "CZ", "SWAP", "G"} inits_z: ClassVar[set[str]] = {"init |0>", "init |1>"} inits_x: ClassVar[set[str]] = {"init |+>", "init |->"} inits_y: ClassVar[set[str]] = {"init |+i>", "init |-i>"} - error_two_paulis_collection: ClassVar[list[tuple[str, str]]] = [("I", "X"), ("X", "I"), ("X", "X")] + error_two_paulis_collection: ClassVar[list[tuple[str, str]]] = [ + ("I", "X"), + ("X", "I"), + ("X", "X"), + ] def __init__(self, model_level="circuit", has_idle_errors=False) -> None: """Args: @@ -55,7 +66,9 @@ def __init__(self, model_level="circuit", has_idle_errors=False) -> None: xerror = self.gen.ErrorStaticSymbol("X") xerror_before = self.gen.ErrorStaticSymbol("X", after=False) - two_pauli_errors = self.gen.ErrorSetTwoQuditTensorProduct(self.error_two_paulis_collection) + two_pauli_errors = self.gen.ErrorSetTwoQuditTensorProduct( + self.error_two_paulis_collection, + ) if model_level == "code_capacity": self.has_data_errors = True @@ -87,7 +100,10 @@ def __init__(self, model_level="circuit", has_idle_errors=False) -> None: self.has_meas_errors = True # Don't generate data errors - self.gen.set_gate_error("data", False) # Don't generate errors for data qudits. + self.gen.set_gate_error( + "data", + False, + ) # Don't generate errors for data qudits. # Generate measurement errors (before errors) self.gen.set_group_error("measurements", xerror_before.error_func) @@ -147,13 +163,27 @@ def generate_tick_errors(self, tick_circuit, time, **params): # ------------------------------ if self.has_meas_errors or self.has_unitary_errors: for symbol, gate_locations, _ in circuit.items(tick_index): - self.gen.create_errors(self, symbol, gate_locations, after, before, replace) + self.gen.create_errors( + self, + symbol, + gate_locations, + after, + before, + replace, + ) # idle errors # ----------- if self.has_idle_errors: inactive_qudits = circuit.qudits - circuit.active_qudits[tick_index] - self.gen.create_errors(self, "idle", inactive_qudits, after, before, replace) + self.gen.create_errors( + self, + "idle", + inactive_qudits, + after, + before, + replace, + ) self.error_circuits.add_circuits(time, before, after) diff --git a/python/pecos/error_models/old/xzerror_gen.py b/python/quantum-pecos/src/pecos/error_models/old/xzerror_gen.py similarity index 87% rename from python/pecos/error_models/old/xzerror_gen.py rename to python/quantum-pecos/src/pecos/error_models/old/xzerror_gen.py index 5cf6fe23..d211268c 100644 --- a/python/pecos/error_models/old/xzerror_gen.py +++ b/python/quantum-pecos/src/pecos/error_models/old/xzerror_gen.py @@ -29,7 +29,14 @@ class XZModel(ParentErrorModel): """ measurements: ClassVar[set[str]] = {"measure X", "measure Y", "measure Z"} - inits: ClassVar[set[str]] = {"init |0>", "init |1>", "init |+>", "init |->", "init |+i>", "init |-i>"} + inits: ClassVar[set[str]] = { + "init |0>", + "init |1>", + "init |+>", + "init |->", + "init |+i>", + "init |-i>", + } two_qubits: ClassVar[set[str]] = {"CNOT", "CZ", "SWAP", "G"} inits_z: ClassVar[set[str]] = {"init |0>", "init |1>"} @@ -47,7 +54,12 @@ class XZModel(ParentErrorModel): ("Z", "Z"), ] - def __init__(self, model_level="circuit", has_idle_errors=False, perp_errors=False) -> None: + def __init__( + self, + model_level="circuit", + has_idle_errors=False, + perp_errors=False, + ) -> None: """Args: ---- model_level(str): @@ -70,7 +82,9 @@ def __init__(self, model_level="circuit", has_idle_errors=False, perp_errors=Fal zerror_before = self.gen.ErrorStaticSymbol("Z", after=False) pauli_errors = self.gen.ErrorSet({"X", "Z"}) pauli_errors_before = self.gen.ErrorSet({"X", "Z"}, after=False) - two_pauli_errors = self.gen.ErrorSetTwoQuditTensorProduct(self.error_two_paulis_collection) + two_pauli_errors = self.gen.ErrorSetTwoQuditTensorProduct( + self.error_two_paulis_collection, + ) if model_level == "code_capacity": self.has_data_errors = True @@ -100,7 +114,10 @@ def __init__(self, model_level="circuit", has_idle_errors=False, perp_errors=Fal self.has_meas_errors = True # Don't generate data errors - self.gen.set_gate_error("data", False) # Don't generate errors for data qudits. + self.gen.set_gate_error( + "data", + False, + ) # Don't generate errors for data qudits. # Generate measurement errors (before errors) self.gen.set_group_error("measurements", pauli_errors_before.error_func) @@ -171,13 +188,27 @@ def generate_tick_errors(self, tick_circuit, time, **params): # ------------------------------ if self.has_meas_errors or self.has_unitary_errors: for symbol, gate_locations, _ in circuit.items(tick_index): - self.gen.create_errors(self, symbol, gate_locations, after, before, replace) + self.gen.create_errors( + self, + symbol, + gate_locations, + after, + before, + replace, + ) # idle errors # ----------- if self.has_idle_errors: inactive_qudits = circuit.qudits - circuit.active_qudits[tick_index] - self.gen.create_errors(self, "idle", inactive_qudits, after, before, replace) + self.gen.create_errors( + self, + "idle", + inactive_qudits, + after, + before, + replace, + ) self.error_circuits.add_circuits(time, before, after) diff --git a/python/pecos/error_models/old/zerror_gen.py b/python/quantum-pecos/src/pecos/error_models/old/zerror_gen.py similarity index 86% rename from python/pecos/error_models/old/zerror_gen.py rename to python/quantum-pecos/src/pecos/error_models/old/zerror_gen.py index 025ecb71..efed84fd 100644 --- a/python/pecos/error_models/old/zerror_gen.py +++ b/python/quantum-pecos/src/pecos/error_models/old/zerror_gen.py @@ -29,14 +29,25 @@ class ZModel(ParentErrorModel): """ measurements: ClassVar[set[str]] = {"measure X", "measure Y", "measure Z"} - inits: ClassVar[set[str]] = {"init |0>", "init |1>", "init |+>", "init |->", "init |+i>", "init |-i>"} + inits: ClassVar[set[str]] = { + "init |0>", + "init |1>", + "init |+>", + "init |->", + "init |+i>", + "init |-i>", + } two_qubits: ClassVar[set[str]] = {"CNOT", "CZ", "SWAP", "G"} inits_z: ClassVar[set[str]] = {"init |0>", "init |1>"} inits_x: ClassVar[set[str]] = {"init |+>", "init |->"} inits_y: ClassVar[set[str]] = {"init |+i>", "init |-i>"} - error_two_paulis_collection: ClassVar[list[tuple[str, str]]] = [("I", "Z"), ("Z", "I"), ("Z", "X")] + error_two_paulis_collection: ClassVar[list[tuple[str, str]]] = [ + ("I", "Z"), + ("Z", "I"), + ("Z", "X"), + ] def __init__(self, model_level="circuit", has_idle_errors=False) -> None: """Args: @@ -55,7 +66,9 @@ def __init__(self, model_level="circuit", has_idle_errors=False) -> None: zerror = self.gen.ErrorStaticSymbol("Z") zerror_before = self.gen.ErrorStaticSymbol("Z", after=False) - two_pauli_errors = self.gen.ErrorSetTwoQuditTensorProduct(self.error_two_paulis_collection) + two_pauli_errors = self.gen.ErrorSetTwoQuditTensorProduct( + self.error_two_paulis_collection, + ) if model_level == "code_capacity": self.has_data_errors = True @@ -87,7 +100,10 @@ def __init__(self, model_level="circuit", has_idle_errors=False) -> None: self.has_meas_errors = True # Don't generate data errors - self.gen.set_gate_error("data", False) # Don't generate errors for data qudits. + self.gen.set_gate_error( + "data", + False, + ) # Don't generate errors for data qudits. # Generate measurement errors (before errors) self.gen.set_group_error("measurements", zerror_before.error_func) @@ -147,13 +163,27 @@ def generate_tick_errors(self, tick_circuit, time, **params): # ------------------------------ if self.has_meas_errors or self.has_unitary_errors: for symbol, gate_locations, _ in circuit.items(tick_index): - self.gen.create_errors(self, symbol, gate_locations, after, before, replace) + self.gen.create_errors( + self, + symbol, + gate_locations, + after, + before, + replace, + ) # idle errors # ----------- if self.has_idle_errors: inactive_qudits = circuit.qudits - circuit.active_qudits[tick_index] - self.gen.create_errors(self, "idle", inactive_qudits, after, before, replace) + self.gen.create_errors( + self, + "idle", + inactive_qudits, + after, + before, + replace, + ) self.error_circuits.add_circuits(time, before, after) diff --git a/python/pecos/error_models/parent_class_error_gen.py b/python/quantum-pecos/src/pecos/error_models/parent_class_error_gen.py similarity index 91% rename from python/pecos/error_models/parent_class_error_gen.py rename to python/quantum-pecos/src/pecos/error_models/parent_class_error_gen.py index 4bfd1616..cffe4b15 100644 --- a/python/pecos/error_models/parent_class_error_gen.py +++ b/python/quantum-pecos/src/pecos/error_models/parent_class_error_gen.py @@ -12,6 +12,7 @@ # specific language governing permissions and limitations under the License. """Simple error generator meant to demonstrate a basic error generator that produces errors.""" + import numpy as np from pecos.error_models.class_errors_circuit import ErrorCircuits @@ -124,13 +125,19 @@ def set_gate_error(self, gate_symbol, error_func, error_param="p", after=True): error_func = list(error_func) first = error_func[0] - if (isinstance(first, str) and first not in ["CNOT", "II", "CZ", "SWAP", "G2"]) or not hasattr( + if ( + isinstance(first, str) + and first not in ["CNOT", "II", "CZ", "SWAP", "G2"] + ) or not hasattr( first, "__iter__", ): error_func = self.ErrorSet(error_func, after=after).error_func else: - error_func = self.ErrorSetMultiQuditGate(error_func, after=after).error_func + error_func = self.ErrorSetMultiQuditGate( + error_func, + after=after, + ).error_func self.error_func_dict[gate_symbol] = (error_func, error_param) @@ -169,7 +176,16 @@ def set_default_error(self, error_func, error_param="p"): """ self.default_error_tuple = (error_func, error_param) - def create_errors(self, err_gen, gate_symbol, locations, after, before, replace, **kwargs): + def create_errors( + self, + err_gen, + gate_symbol, + locations, + after, + before, + replace, + **kwargs, + ): """Used to determine if an error occurs and if so, calls the error function to determine errors. It also updates the `error_circuit` with the errors. @@ -186,7 +202,10 @@ def create_errors(self, err_gen, gate_symbol, locations, after, before, replace, Returns: None """ - error_func, error_param = self.error_func_dict.get(gate_symbol, self.default_error_tuple) + error_func, error_param = self.error_func_dict.get( + gate_symbol, + self.default_error_tuple, + ) if error_func is True: # Default error # Use the default error function. @@ -215,7 +234,14 @@ def create_errors(self, err_gen, gate_symbol, locations, after, before, replace, for i, loc in enumerate(locations): if rand_nums[i]: error_locations.add(loc) - error_func(after, before, replace, loc, err_gen.error_params, **kwargs) + error_func( + after, + before, + replace, + loc, + err_gen.error_params, + **kwargs, + ) return error_locations @@ -273,7 +299,10 @@ def error_func_after(self, after, before, replace, location, error_params): indx = np.random.choice(len(self.data)) error_symbols = self.data[indx] - if isinstance(error_symbols, (tuple, np.ndarray)) and len(error_symbols) > 1: + if ( + isinstance(error_symbols, (tuple, np.ndarray)) + and len(error_symbols) > 1 + ): for sym, loc in zip(error_symbols, location): if sym != "I": after.update(sym, {loc}, emptyappend=True) diff --git a/python/pecos/error_models/simple_depolarizing_error_model.py b/python/quantum-pecos/src/pecos/error_models/simple_depolarizing_error_model.py similarity index 90% rename from python/pecos/error_models/simple_depolarizing_error_model.py rename to python/quantum-pecos/src/pecos/error_models/simple_depolarizing_error_model.py index 5b6b7215..032bfb0b 100644 --- a/python/pecos/error_models/simple_depolarizing_error_model.py +++ b/python/quantum-pecos/src/pecos/error_models/simple_depolarizing_error_model.py @@ -102,7 +102,9 @@ def process(self, qops: list[QOp], call_back=None) -> list[QOp | SeqBlock]: for r, loc in zip(rand_nums, op.args): if r: err = np.random.choice(one_qubit_paulis) - erroneous_ops.append(QOp(name=err[0], args=[loc], metadata={})) + erroneous_ops.append( + QOp(name=err[0], args=[loc], metadata={}), + ) # ######################################## # TWO QUBIT GATES @@ -116,9 +118,13 @@ def process(self, qops: list[QOp], call_back=None) -> list[QOp | SeqBlock]: err = np.random.choice(two_qubit_paulis) loc1, loc2 = loc if err[0] != "I": - erroneous_ops.append(QOp(name=err[0], args=[loc1], metadata={})) + erroneous_ops.append( + QOp(name=err[0], args=[loc1], metadata={}), + ) if err[1] != "I": - erroneous_ops.append(QOp(name=err[1], args=[loc2], metadata={})) + erroneous_ops.append( + QOp(name=err[1], args=[loc2], metadata={}), + ) # ######################################## # MEASURE X NOISE diff --git a/python/pecos/errors.py b/python/quantum-pecos/src/pecos/errors.py similarity index 100% rename from python/pecos/errors.py rename to python/quantum-pecos/src/pecos/errors.py diff --git a/python/pecos/foreign_objects/__init__.py b/python/quantum-pecos/src/pecos/foreign_objects/__init__.py similarity index 100% rename from python/pecos/foreign_objects/__init__.py rename to python/quantum-pecos/src/pecos/foreign_objects/__init__.py diff --git a/python/pecos/foreign_objects/foreign_object_abc.py b/python/quantum-pecos/src/pecos/foreign_objects/foreign_object_abc.py similarity index 100% rename from python/pecos/foreign_objects/foreign_object_abc.py rename to python/quantum-pecos/src/pecos/foreign_objects/foreign_object_abc.py diff --git a/python/pecos/foreign_objects/object_pool.py b/python/quantum-pecos/src/pecos/foreign_objects/object_pool.py similarity index 92% rename from python/pecos/foreign_objects/object_pool.py rename to python/quantum-pecos/src/pecos/foreign_objects/object_pool.py index be138140..7644bb32 100644 --- a/python/pecos/foreign_objects/object_pool.py +++ b/python/quantum-pecos/src/pecos/foreign_objects/object_pool.py @@ -24,7 +24,7 @@ class NamedObjectPool(ForeignObject): def __init__(self, **objects: ForeignObject) -> None: self.objs = objects - self.default = objects.get("default", None) + self.default = objects.get("default") def new_instance(self) -> None: """Create new instance/internal state.""" @@ -53,7 +53,12 @@ def get_funcs(self) -> list[str]: """Get a list of function names available from the object.""" return [] - def exec(self, func_name: str, args: Sequence, namespace: str | None = None) -> tuple: + def exec( + self, + func_name: str, + args: Sequence, + namespace: str | None = None, + ) -> tuple: """Execute a function given a list of arguments.""" if namespace is None: obj = self.default diff --git a/python/pecos/foreign_objects/python.py b/python/quantum-pecos/src/pecos/foreign_objects/python.py similarity index 100% rename from python/pecos/foreign_objects/python.py rename to python/quantum-pecos/src/pecos/foreign_objects/python.py diff --git a/python/pecos/simulators/cuquantum_old/custatevec/gates_init.py b/python/quantum-pecos/src/pecos/foreign_objects/wasm_execution_timer_thread.py similarity index 50% rename from python/pecos/simulators/cuquantum_old/custatevec/gates_init.py rename to python/quantum-pecos/src/pecos/foreign_objects/wasm_execution_timer_thread.py index b7c73049..9c49777a 100644 --- a/python/pecos/simulators/cuquantum_old/custatevec/gates_init.py +++ b/python/quantum-pecos/src/pecos/foreign_objects/wasm_execution_timer_thread.py @@ -1,4 +1,4 @@ -# Copyright 2023 The PECOS Developers +# Copyright 2024 The PECOS Developers # # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with # the License.You may obtain a copy of the License at @@ -9,20 +9,19 @@ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the # specific language governing permissions and limitations under the License. -from typing import Any +from threading import Event, Thread -from pecos.simulators.custatevec.gates_meas import meas_z -from pecos.simulators.custatevec.gates_one_qubit import X +# These values multiplied should equal the intended maximum execution time +WASM_EXECUTION_TICK_LENGTH_S: float = 0.25 +WASM_EXECUTION_MAX_TICKS: int = 4 -def init_zero(state, qubit: int, **params: Any) -> None: - """Initialise or reset the qubit to state |0> +class WasmExecutionTimerThread(Thread): + def __init__(self, stop_event: Event, func) -> None: + Thread.__init__(self, daemon=True) + self._stop_event = stop_event + self._func = func - Args: - state: An instance of CuStateVec - qubit: The index of the qubit to be initialised - """ - result = meas_z(state, qubit) - - if result: - X(state, qubit) + def run(self): + while not self._stop_event.wait(WASM_EXECUTION_TICK_LENGTH_S): + self._func() diff --git a/python/pecos/foreign_objects/wasmer.py b/python/quantum-pecos/src/pecos/foreign_objects/wasmer.py similarity index 96% rename from python/pecos/foreign_objects/wasmer.py rename to python/quantum-pecos/src/pecos/foreign_objects/wasmer.py index 7a91bd68..5762acf3 100644 --- a/python/pecos/foreign_objects/wasmer.py +++ b/python/quantum-pecos/src/pecos/foreign_objects/wasmer.py @@ -30,7 +30,11 @@ class WasmerObj(ForeignObject): For more info on using Wasmer, see: https://wasmerio.github.io/wasmer-python/api/wasmer/wasmer.html """ - def __init__(self, file: str | bytes | Path, compiler: object | None = None) -> None: + def __init__( + self, + file: str | bytes | Path, + compiler: object | None = None, + ) -> None: self.compiler = compiler if isinstance(file, (str, Path)): diff --git a/python/pecos/foreign_objects/wasmtime.py b/python/quantum-pecos/src/pecos/foreign_objects/wasmtime.py similarity index 94% rename from python/pecos/foreign_objects/wasmtime.py rename to python/quantum-pecos/src/pecos/foreign_objects/wasmtime.py index 6576daa4..8822b998 100644 --- a/python/pecos/foreign_objects/wasmtime.py +++ b/python/quantum-pecos/src/pecos/foreign_objects/wasmtime.py @@ -78,7 +78,10 @@ def spin_up_wasm(self) -> None: self.store = Store(engine) self.module = Module(self.store.engine, self.wasm_bytes) self.stop_flag = Event() - self.inc_thread_handle = WasmExecutionTimerThread(self.stop_flag, self._increment_engine) + self.inc_thread_handle = WasmExecutionTimerThread( + self.stop_flag, + self._increment_engine, + ) self.inc_thread_handle.start() self.new_instance() @@ -123,7 +126,9 @@ def exec(self, func_name: str, args: Sequence) -> tuple: ) raise WasmRuntimeError(message) from t except Exception as e: - message = f"Error during execution of function '{func_name}' with args {args}" + message = ( + f"Error during execution of function '{func_name}' with args {args}" + ) raise WasmRuntimeError(message) from e def teardown(self) -> None: diff --git a/python/pecos/machines/__init__.py b/python/quantum-pecos/src/pecos/machines/__init__.py similarity index 100% rename from python/pecos/machines/__init__.py rename to python/quantum-pecos/src/pecos/machines/__init__.py diff --git a/python/pecos/machines/generic_machine.py b/python/quantum-pecos/src/pecos/machines/generic_machine.py similarity index 100% rename from python/pecos/machines/generic_machine.py rename to python/quantum-pecos/src/pecos/machines/generic_machine.py diff --git a/python/pecos/machines/machine_abc.py b/python/quantum-pecos/src/pecos/machines/machine_abc.py similarity index 100% rename from python/pecos/machines/machine_abc.py rename to python/quantum-pecos/src/pecos/machines/machine_abc.py diff --git a/python/pecos/misc/__init__.py b/python/quantum-pecos/src/pecos/misc/__init__.py similarity index 100% rename from python/pecos/misc/__init__.py rename to python/quantum-pecos/src/pecos/misc/__init__.py diff --git a/python/pecos/misc/commute.py b/python/quantum-pecos/src/pecos/misc/commute.py similarity index 86% rename from python/pecos/misc/commute.py rename to python/quantum-pecos/src/pecos/misc/commute.py index fda4d0cd..1ad7f3c1 100644 --- a/python/pecos/misc/commute.py +++ b/python/quantum-pecos/src/pecos/misc/commute.py @@ -33,7 +33,10 @@ def qubit_pauli(first_circuit, second_circuit): first_xs.update(gate_locations) first_zs.update(gate_locations) else: - raise Exception('Can not currently handle logical operator with operator "%s"!' % symbol) + raise Exception( + 'Can not currently handle logical operator with operator "%s"!' + % symbol, + ) second_xs = set() second_zs = set() @@ -46,6 +49,9 @@ def qubit_pauli(first_circuit, second_circuit): second_xs.update(gate_locations) second_zs.update(gate_locations) else: - raise Exception('Can not currently handle logical operator with operator "%s"!' % symbol) + raise Exception( + 'Can not currently handle logical operator with operator "%s"!' + % symbol, + ) return not (len(first_xs & second_zs) + len(first_zs & second_xs)) % 2 diff --git a/python/pecos/misc/errors.py b/python/quantum-pecos/src/pecos/misc/errors.py similarity index 100% rename from python/pecos/misc/errors.py rename to python/quantum-pecos/src/pecos/misc/errors.py diff --git a/python/pecos/misc/gate_groups.py b/python/quantum-pecos/src/pecos/misc/gate_groups.py similarity index 90% rename from python/pecos/misc/gate_groups.py rename to python/quantum-pecos/src/pecos/misc/gate_groups.py index 0d4854bb..476afcbf 100644 --- a/python/pecos/misc/gate_groups.py +++ b/python/quantum-pecos/src/pecos/misc/gate_groups.py @@ -11,7 +11,20 @@ import numpy as np -two_qubits = {"CNOT", "CX", "CZ", "SWAP", "G", "MS", "SqrtXX", "SqrtZZ", "RXX", "RYY", "RZZ", "RXXYYZZ"} +two_qubits = { + "CNOT", + "CX", + "CZ", + "SWAP", + "G", + "MS", + "SqrtXX", + "SqrtZZ", + "RXX", + "RYY", + "RZZ", + "RXXYYZZ", +} one_qubits = { "I", diff --git a/python/pecos/misc/stabilizer_funcs.py b/python/quantum-pecos/src/pecos/misc/stabilizer_funcs.py similarity index 94% rename from python/pecos/misc/stabilizer_funcs.py rename to python/quantum-pecos/src/pecos/misc/stabilizer_funcs.py index 069f8342..ef0be87f 100644 --- a/python/pecos/misc/stabilizer_funcs.py +++ b/python/quantum-pecos/src/pecos/misc/stabilizer_funcs.py @@ -149,11 +149,15 @@ def remove_stab(state, stab_xs, stab_zs, destab_xs, destab_zs): for q in logical_xs: # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # Use |= or ^= ?????????????????? - build_stabs ^= destabs.col_z[q] # These should point to all the stabilizers that will combine to give X on + build_stabs ^= destabs.col_z[ + q + ] # These should point to all the stabilizers that will combine to give X on # qubit q for q in logical_zs: - build_stabs ^= destabs.col_x[q] # These should point to all the stabilizers that will combine to give Z on + build_stabs ^= destabs.col_x[ + q + ] # These should point to all the stabilizers that will combine to give Z on # qubit q # Stabilizer to remove @@ -290,11 +294,15 @@ def is_not_stabilizer(state, qubits_x, qubits_z): build_stabs = set() for q in qubits_x: - build_stabs ^= destabs.col_z[q] # These should point to all the stabilizers that will combine to give X on + build_stabs ^= destabs.col_z[ + q + ] # These should point to all the stabilizers that will combine to give X on # qubit q for q in qubits_z: - build_stabs ^= destabs.col_x[q] # These should point to all the stabilizers that will combine to give Z on + build_stabs ^= destabs.col_x[ + q + ] # These should point to all the stabilizers that will combine to give Z on # qubit q # Build up the X and Z Paulis diff --git a/python/pecos/misc/std_output.py b/python/quantum-pecos/src/pecos/misc/std_output.py similarity index 100% rename from python/pecos/misc/std_output.py rename to python/quantum-pecos/src/pecos/misc/std_output.py diff --git a/python/pecos/misc/symbol_library.py b/python/quantum-pecos/src/pecos/misc/symbol_library.py similarity index 96% rename from python/pecos/misc/symbol_library.py rename to python/quantum-pecos/src/pecos/misc/symbol_library.py index a57d821e..744c44af 100644 --- a/python/pecos/misc/symbol_library.py +++ b/python/quantum-pecos/src/pecos/misc/symbol_library.py @@ -46,7 +46,12 @@ def add(self, symbol: str, obj: Any, params: dict[str, Any]) -> None: """ self.library[symbol].add((obj, params)) - def get(self, symbol: str, params: dict[str, Any], default: Any | None = None) -> Any: + def get( + self, + symbol: str, + params: dict[str, Any], + default: Any | None = None, + ) -> Any: """Get an instance associated with `symbol` that has the parameters `params`. Args: diff --git a/python/pecos/misc/threshold_curve.py b/python/quantum-pecos/src/pecos/misc/threshold_curve.py similarity index 98% rename from python/pecos/misc/threshold_curve.py rename to python/quantum-pecos/src/pecos/misc/threshold_curve.py index ebd34f8c..5beee808 100644 --- a/python/pecos/misc/threshold_curve.py +++ b/python/quantum-pecos/src/pecos/misc/threshold_curve.py @@ -93,7 +93,11 @@ def func3(x, pth, v0, a, b, c, d, uodd, ueven): x = (p - pth) * np.power(dist, 1.0 / v0) - z = np.where(bool(dist % 2), d * np.power(dist, -1.0 / uodd), d * np.power(dist, -1.0 / ueven)) + z = np.where( + bool(dist % 2), + d * np.power(dist, -1.0 / uodd), + d * np.power(dist, -1.0 / ueven), + ) z += a + b * x + c * np.power(x, 2) diff --git a/python/pecos/op_processors/__init__.py b/python/quantum-pecos/src/pecos/op_processors/__init__.py similarity index 100% rename from python/pecos/op_processors/__init__.py rename to python/quantum-pecos/src/pecos/op_processors/__init__.py diff --git a/python/pecos/op_processors/generic_op_processor.py b/python/quantum-pecos/src/pecos/op_processors/generic_op_processor.py similarity index 94% rename from python/pecos/op_processors/generic_op_processor.py rename to python/quantum-pecos/src/pecos/op_processors/generic_op_processor.py index c9bf44bc..d54d11be 100644 --- a/python/pecos/op_processors/generic_op_processor.py +++ b/python/quantum-pecos/src/pecos/op_processors/generic_op_processor.py @@ -22,7 +22,11 @@ class GenericOpProc(OpProcessor): - def __init__(self, machine: Machine | None = None, error_model: ErrorModel | None = None) -> None: + def __init__( + self, + machine: Machine | None = None, + error_model: ErrorModel | None = None, + ) -> None: self.machine = machine self.error_model = error_model diff --git a/python/pecos/op_processors/op_processor_abc.py b/python/quantum-pecos/src/pecos/op_processors/op_processor_abc.py similarity index 100% rename from python/pecos/op_processors/op_processor_abc.py rename to python/quantum-pecos/src/pecos/op_processors/op_processor_abc.py diff --git a/python/pecos/py.typed b/python/quantum-pecos/src/pecos/py.typed similarity index 100% rename from python/pecos/py.typed rename to python/quantum-pecos/src/pecos/py.typed diff --git a/python/pecos/qeccs/__init__.py b/python/quantum-pecos/src/pecos/qeccs/__init__.py similarity index 100% rename from python/pecos/qeccs/__init__.py rename to python/quantum-pecos/src/pecos/qeccs/__init__.py diff --git a/python/pecos/qeccs/color_488/__init__.py b/python/quantum-pecos/src/pecos/qeccs/color_488/__init__.py similarity index 100% rename from python/pecos/qeccs/color_488/__init__.py rename to python/quantum-pecos/src/pecos/qeccs/color_488/__init__.py diff --git a/python/pecos/qeccs/color_488/circuit_implementation1.py b/python/quantum-pecos/src/pecos/qeccs/color_488/circuit_implementation1.py similarity index 74% rename from python/pecos/qeccs/color_488/circuit_implementation1.py rename to python/quantum-pecos/src/pecos/qeccs/color_488/circuit_implementation1.py index 055c2181..40cff3ab 100644 --- a/python/pecos/qeccs/color_488/circuit_implementation1.py +++ b/python/quantum-pecos/src/pecos/qeccs/color_488/circuit_implementation1.py @@ -17,7 +17,13 @@ class OneAncillaPerCheck: """Class that describes an implementation of the 4.8.8 color code with one ancilla per face.""" - def __init__(self, square_x_ticks=None, square_z_ticks=None, octagon_x_ticks=None, octagon_z_ticks=None) -> None: + def __init__( + self, + square_x_ticks=None, + square_z_ticks=None, + octagon_x_ticks=None, + octagon_z_ticks=None, + ) -> None: """Args: ---- square_x_ticks: @@ -28,7 +34,16 @@ def __init__(self, square_x_ticks=None, square_z_ticks=None, octagon_x_ticks=Non if square_x_ticks is None: # 8 ticks - square_x_ticks = [0, 1, 2, 3, 4, 5, 6, 7] # init, H ticks # Data ticks # H, meas ticks + square_x_ticks = [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + ] # init, H ticks # Data ticks # H, meas ticks if square_z_ticks is None: # 6 ticks @@ -36,11 +51,35 @@ def __init__(self, square_x_ticks=None, square_z_ticks=None, octagon_x_ticks=Non if octagon_x_ticks is None: # 12 ticks - octagon_x_ticks = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] # init, H ticks # Data ticks # H, meas ticks + octagon_x_ticks = [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + ] # init, H ticks # Data ticks # H, meas ticks if octagon_z_ticks is None: # 10 ticks - octagon_z_ticks = [12, 13, 14, 15, 16, 17, 18, 19, 20, 21] # int tick # Data ticks # meas tick + octagon_z_ticks = [ + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + ] # int tick # Data ticks # meas tick self.square_x_ticks = square_x_ticks self.square_z_ticks = square_z_ticks @@ -110,7 +149,10 @@ def compile(self, instr, abstract_circuit, mapping=None): if polygon is None: # This is an actual circuit element if mapping: - circuit.update({check_type: self.mapset(mapping, set(locations))}, tick=params["tick"]) + circuit.update( + {check_type: self.mapset(mapping, set(locations))}, + tick=params["tick"], + ) else: circuit.update({check_type: set(locations)}, tick=params["tick"]) else: @@ -118,12 +160,24 @@ def compile(self, instr, abstract_circuit, mapping=None): datas = params["datas"] if polygon == "square": - ticks = square_x_ticks if check_type == "X check" else square_z_ticks + ticks = ( + square_x_ticks if check_type == "X check" else square_z_ticks + ) else: - ticks = octagon_x_ticks if check_type == "X check" else octagon_z_ticks - - self._create_check(circuit, polygon, ticks, check_type, datas, ancilla, mapping) + ticks = ( + octagon_x_ticks if check_type == "X check" else octagon_z_ticks + ) + + self._create_check( + circuit, + polygon, + ticks, + check_type, + datas, + ancilla, + mapping, + ) return circuit @@ -147,7 +201,16 @@ def mapset(mapping, oldset): return newset - def _create_check(self, circuit, polygon, ticks, check_type, datas, ancilla, mapping): + def _create_check( + self, + circuit, + polygon, + ticks, + check_type, + datas, + ancilla, + mapping, + ): """Args: ---- circuit: @@ -195,7 +258,10 @@ def _create_check(self, circuit, polygon, ticks, check_type, datas, ancilla, map for d, t in zip(datas, data_ticks): if d is not None: - circuit.update({"CNOT": {(mapping[ancilla], mapping[d])}}, tick=t) + circuit.update( + {"CNOT": {(mapping[ancilla], mapping[d])}}, + tick=t, + ) else: # Z check data_ticks = ticks[1 : sides + 1] @@ -207,7 +273,10 @@ def _create_check(self, circuit, polygon, ticks, check_type, datas, ancilla, map else: for d, t in zip(datas, data_ticks): if d is not None: - circuit.update({"CNOT": {(mapping[d], mapping[ancilla])}}, tick=t) + circuit.update( + {"CNOT": {(mapping[d], mapping[ancilla])}}, + tick=t, + ) init_tick = ticks[0] meas_tick = ticks[-1] diff --git a/python/pecos/qeccs/color_488/color_488.py b/python/quantum-pecos/src/pecos/qeccs/color_488/color_488.py similarity index 92% rename from python/pecos/qeccs/color_488/color_488.py rename to python/quantum-pecos/src/pecos/qeccs/color_488/color_488.py index f02dcda1..d90ab88a 100644 --- a/python/pecos/qeccs/color_488/color_488.py +++ b/python/quantum-pecos/src/pecos/qeccs/color_488/color_488.py @@ -15,9 +15,14 @@ Generates circuits for the repetition code in the Z-Basis. """ + from pecos.qeccs.color_488.circuit_implementation1 import OneAncillaPerCheck from pecos.qeccs.color_488.gates import GateIdentity, GateInitPlus, GateInitZero -from pecos.qeccs.color_488.instructions import InstrInitPlus, InstrInitZero, InstrSynExtraction +from pecos.qeccs.color_488.instructions import ( + InstrInitPlus, + InstrInitZero, + InstrSynExtraction, +) from pecos.qeccs.qecc_parent_class import QECC @@ -67,8 +72,13 @@ def __init__(self, distance=None, **qecc_params) -> None: # Determine number of ancillas to reserve given the check circuit implementation and, perhaps, the logical # gate circuits implemented by this class. # -------------------------------------------------------------------------------------------------------------- - self.circuit_compiler = qecc_params.get("circuit_compiler", OneAncillaPerCheck()) - self.num_ancilla_qudits = self.circuit_compiler.get_num_ancillas(self.num_syndromes) + self.circuit_compiler = qecc_params.get( + "circuit_compiler", + OneAncillaPerCheck(), + ) + self.num_ancilla_qudits = self.circuit_compiler.get_num_ancillas( + self.num_syndromes, + ) # Total number of qudits. # self.qudit_set, self.data_qudit_set, self.ancilla_qudit_set will be determined when creating the layout. @@ -116,8 +126,12 @@ def _get_distance(params): distance_width = distance_height = distance else: - distance_width = params.get("distance_width") # The width of the code. == Z? distance - distance_height = params.get("distance_height") # The height of the code. == X? distance + distance_width = params.get( + "distance_width", + ) # The width of the code. == Z? distance + distance_height = params.get( + "distance_height", + ) # The height of the code. == X? distance distance = min(distance_width, distance_height) return distance, distance_height, distance_width diff --git a/python/pecos/qeccs/color_488/gates.py b/python/quantum-pecos/src/pecos/qeccs/color_488/gates.py similarity index 88% rename from python/pecos/qeccs/color_488/gates.py rename to python/quantum-pecos/src/pecos/qeccs/color_488/gates.py index f473b998..8ae03b4a 100644 --- a/python/pecos/qeccs/color_488/gates.py +++ b/python/quantum-pecos/src/pecos/qeccs/color_488/gates.py @@ -30,7 +30,10 @@ def __init__(self, qecc, symbol, **gate_params) -> None: """ super().__init__(qecc, symbol, **gate_params) - expected_params(gate_params, {"num_syn_extract", "error_free", "forced_outcome"}) + expected_params( + gate_params, + {"num_syn_extract", "error_free", "forced_outcome"}, + ) self.num_syn_extract = gate_params.get("num_syn_extract", qecc.distance) @@ -50,7 +53,10 @@ def __init__(self, qecc, symbol, **gate_params) -> None: """ super().__init__(qecc, symbol, **gate_params) - expected_params(gate_params, {"num_syn_extract", "error_free", "forced_outcome"}) + expected_params( + gate_params, + {"num_syn_extract", "error_free", "forced_outcome"}, + ) self.num_syn_extract = gate_params.get("num_syn_extract", 0) @@ -72,7 +78,10 @@ def __init__(self, qecc, symbol, **gate_params) -> None: """ super().__init__(qecc, symbol, **gate_params) - expected_params(gate_params, {"num_syn_extract", "error_free", "forced_outcome"}) + expected_params( + gate_params, + {"num_syn_extract", "error_free", "forced_outcome"}, + ) self.num_syn_extract = gate_params.get("num_syn_extract", 0) diff --git a/python/pecos/qeccs/color_488/instructions.py b/python/quantum-pecos/src/pecos/qeccs/color_488/instructions.py similarity index 90% rename from python/pecos/qeccs/color_488/instructions.py rename to python/quantum-pecos/src/pecos/qeccs/color_488/instructions.py index 6da836d0..b313864f 100644 --- a/python/pecos/qeccs/color_488/instructions.py +++ b/python/quantum-pecos/src/pecos/qeccs/color_488/instructions.py @@ -44,7 +44,10 @@ def __init__(self, qecc, symbol, **params) -> None: logical_ops = [ # Each element in the list corresponds to a logical qubit # The keys label the type of logical operator - {"X": QuantumCircuit([{"X": x_qudits}]), "Z": QuantumCircuit([{"Z": z_qudits}])}, + { + "X": QuantumCircuit([{"X": x_qudits}]), + "Z": QuantumCircuit([{"Z": z_qudits}]), + }, ] self.initial_logical_ops = logical_ops @@ -83,8 +86,18 @@ def _create_checks(self, ancilla): break if found_square: - self.abstract_circuit.append("X check", polygon="square", locations={ancilla}, datas=square) - self.abstract_circuit.append("Z check", polygon="square", locations={ancilla}, datas=square) + self.abstract_circuit.append( + "X check", + polygon="square", + locations={ancilla}, + datas=square, + ) + self.abstract_circuit.append( + "Z check", + polygon="square", + locations={ancilla}, + datas=square, + ) else: if y != 0: @@ -111,8 +124,18 @@ def _create_checks(self, ancilla): ) octagon.extend([None, None, None, None]) - self.abstract_circuit.append("X check", polygon="octagon", locations={ancilla}, datas=octagon) - self.abstract_circuit.append("Z check", polygon="octagon", locations={ancilla}, datas=octagon) + self.abstract_circuit.append( + "X check", + polygon="octagon", + locations={ancilla}, + datas=octagon, + ) + self.abstract_circuit.append( + "Z check", + polygon="octagon", + locations={ancilla}, + datas=octagon, + ) class InstrInitZero(LogicalInstruction): diff --git a/python/pecos/qeccs/gate_parent_class.py b/python/quantum-pecos/src/pecos/qeccs/gate_parent_class.py similarity index 81% rename from python/pecos/qeccs/gate_parent_class.py rename to python/quantum-pecos/src/pecos/qeccs/gate_parent_class.py index 82479f2b..4a061113 100644 --- a/python/pecos/qeccs/gate_parent_class.py +++ b/python/quantum-pecos/src/pecos/qeccs/gate_parent_class.py @@ -12,6 +12,7 @@ # specific language governing permissions and limitations under the License. """Contains the parent classes for logical gates.""" + from pecos.qeccs.helper_functions import expected_params, make_hashable_params @@ -31,14 +32,24 @@ def __init__(self, qecc, symbol, **gate_params) -> None: self.params = self.gate_params self.instr_symbols = None self.instr_instances = [] - self.circuits = [] # The circuits of the logical instructions. (Either instr instances or a QuantumCircuit or + self.circuits = ( + [] + ) # The circuits of the logical instructions. (Either instr instances or a QuantumCircuit or # something with the same methods as a QuantumCircuit.) - self.error_free = gate_params.get("error_free", False) # Whether errors should occur for this gate. - self.forced_outcome = gate_params.get("forced_outcome", True) # Whether the measurements are random + self.error_free = gate_params.get( + "error_free", + False, + ) # Whether errors should occur for this gate. + self.forced_outcome = gate_params.get( + "forced_outcome", + True, + ) # Whether the measurements are random # (if True-> force -1) # Can choose 0 or 1. - self.qecc_params_tuple = make_hashable_params(qecc.qecc_params) # Used for hashing. + self.qecc_params_tuple = make_hashable_params( + qecc.qecc_params, + ) # Used for hashing. self.gate_params_tuple = make_hashable_params(gate_params) # Used for hashing. def final_instr(self): @@ -61,7 +72,9 @@ def __hash__(self): # Added so the logical gate can be a key (gate symbol) in a ``QuantumCircuit``. # These uniquely identify the logical and do not change. - return hash(("gate", self.symbol, self.qecc_params_tuple, self.gate_params_tuple)) + return hash( + ("gate", self.symbol, self.qecc_params_tuple, self.gate_params_tuple), + ) def __eq__(self, other): return (self.symbol, self.qecc_params_tuple, self.gate_params_tuple, True) == ( diff --git a/python/pecos/qeccs/helper_functions.py b/python/quantum-pecos/src/pecos/qeccs/helper_functions.py similarity index 100% rename from python/pecos/qeccs/helper_functions.py rename to python/quantum-pecos/src/pecos/qeccs/helper_functions.py diff --git a/python/pecos/qeccs/instruction_parent_class.py b/python/quantum-pecos/src/pecos/qeccs/instruction_parent_class.py similarity index 85% rename from python/pecos/qeccs/instruction_parent_class.py rename to python/quantum-pecos/src/pecos/qeccs/instruction_parent_class.py index 5cc702e3..98338e96 100644 --- a/python/pecos/qeccs/instruction_parent_class.py +++ b/python/quantum-pecos/src/pecos/qeccs/instruction_parent_class.py @@ -12,6 +12,7 @@ # specific language governing permissions and limitations under the License. """Contains the parent classes for logical instructions.""" + from pecos.qeccs.helper_functions import make_hashable_params from pecos.qeccs.plot import plot_instr @@ -32,14 +33,20 @@ def __init__(self, qecc, symbol, **params) -> None: self.symbol = symbol self.qecc = qecc # The QECC object this instruction belongs to. self.params = params - self.gate_params = self.params # Parameters used in defining the logical instruction. + self.gate_params = ( + self.params + ) # Parameters used in defining the logical instruction. # TODO: should this be the same as the gate parameters? self.abstract_circuit = None # Abstract representation of the circuit. self.circuit = None # Compiled circuit. # The following assumes the role of ancilla and data qudits stays fixed during the instruction - self.data_qudit_set = self.qecc.data_qudit_set # set of qudit ids corresponding to data qudits. - self.ancilla_qudit_set = self.qecc.ancilla_qudit_set # set of qudit ids corresponding to ancilla qudits. + self.data_qudit_set = ( + self.qecc.data_qudit_set + ) # set of qudit ids corresponding to data qudits. + self.ancilla_qudit_set = ( + self.qecc.ancilla_qudit_set + ) # set of qudit ids corresponding to ancilla qudits. # The ancilla set may differ from qecc. (might be a subset) self.params["data_qudit_set"] = self.data_qudit_set @@ -86,7 +93,11 @@ def __hash__(self): return hash(("instr", self.symbol, self.params_tuple)) def __eq__(self, other): - return (self.symbol, self.params_tuple, True) == (other.symbol, other.params_tuple, hasattr(other, "circuit")) + return (self.symbol, self.params_tuple, True) == ( + other.symbol, + other.params_tuple, + hasattr(other, "circuit"), + ) def __ne__(self, other): return not (self == other) diff --git a/python/pecos/qeccs/plot.py b/python/quantum-pecos/src/pecos/qeccs/plot.py similarity index 92% rename from python/pecos/qeccs/plot.py rename to python/quantum-pecos/src/pecos/qeccs/plot.py index 1f1f538c..f217f564 100644 --- a/python/pecos/qeccs/plot.py +++ b/python/quantum-pecos/src/pecos/qeccs/plot.py @@ -91,7 +91,13 @@ def plot_qecc( nodes.set_edgecolor("black") # Label ancilla qudits - nx.draw_networkx_labels(g, pos=pos, labels=ancilla_labels, font_size=16, font_color="white") + nx.draw_networkx_labels( + g, + pos=pos, + labels=ancilla_labels, + font_size=16, + font_color="white", + ) # Label data qudits nx.draw_networkx_labels(g, pos=pos, labels=data_labels, font_size=16) @@ -104,7 +110,13 @@ def plot_qecc( ax.set_ylabel("y (arbitrary length units)", size=axis_font_size) ax.invert_yaxis() - plt.legend(labelspacing=2.5, borderpad=1.5, loc="upper left", bbox_to_anchor=(1, 1.01), fontsize=legend_font_size) + plt.legend( + labelspacing=2.5, + borderpad=1.5, + loc="upper left", + bbox_to_anchor=(1, 1.01), + fontsize=legend_font_size, + ) if filename: plt.savefig(filename) @@ -164,7 +176,10 @@ def plot_instr( labels[i] = "$" + str(i) + "$" plt.figure(num=None, figsize=figsize, dpi=dpi, edgecolor="k") - plt.title(f"Logical Instruction: '{instr.symbol}' QECC: {instr.qecc.name}", size=title_font_size) + plt.title( + f"Logical Instruction: '{instr.symbol}' QECC: {instr.qecc.name}", + size=title_font_size, + ) nx.draw_networkx_edges(g, pos=pos, arrowsize=30) nx.draw_networkx_edge_labels(g, pos=pos, edge_labels=edge_labels) @@ -217,7 +232,13 @@ def plot_instr( nx.draw_networkx_edge_labels(g, pos, edge_labels=edge_labels) - plt.legend(labelspacing=2.5, borderpad=1.5, loc="upper left", bbox_to_anchor=(1, 1.01), fontsize=legend_font_size) + plt.legend( + labelspacing=2.5, + borderpad=1.5, + loc="upper left", + bbox_to_anchor=(1, 1.01), + fontsize=legend_font_size, + ) if filename: plt.savefig(filename) diff --git a/python/pecos/qeccs/qecc_parent_class.py b/python/quantum-pecos/src/pecos/qeccs/qecc_parent_class.py similarity index 98% rename from python/pecos/qeccs/qecc_parent_class.py rename to python/quantum-pecos/src/pecos/qeccs/qecc_parent_class.py index ce8f9475..8d71ca61 100644 --- a/python/pecos/qeccs/qecc_parent_class.py +++ b/python/quantum-pecos/src/pecos/qeccs/qecc_parent_class.py @@ -12,6 +12,7 @@ # specific language governing permissions and limitations under the License. """Contains the parent classes for QECCs, logical gates, and logical instructions.""" + from pecos.circuit_converters.checks2circuit import Check2Circuits from pecos.qeccs.plot import plot_qecc @@ -59,7 +60,9 @@ def __init__(self, **qecc_params) -> None: self.layout = {} # A dictionary of qudit id => (x, y, ...) self.position2qudit = {} self.lattice_dimensions = {} # Dimensions of the physical layout - self.sides = {} # Describes the geometry of the qecc so decoders can understand the QECC's shape + self.sides = ( + {} + ) # Describes the geometry of the qecc so decoders can understand the QECC's shape self.sym2gate_class = {} # symbol => logical gate class self.sym2instruction_class = {} # symbol => logical instruction class diff --git a/python/pecos/qeccs/surface_4444/__init__.py b/python/quantum-pecos/src/pecos/qeccs/surface_4444/__init__.py similarity index 100% rename from python/pecos/qeccs/surface_4444/__init__.py rename to python/quantum-pecos/src/pecos/qeccs/surface_4444/__init__.py diff --git a/python/pecos/qeccs/surface_4444/gates.py b/python/quantum-pecos/src/pecos/qeccs/surface_4444/gates.py similarity index 88% rename from python/pecos/qeccs/surface_4444/gates.py rename to python/quantum-pecos/src/pecos/qeccs/surface_4444/gates.py index 79a9d680..c012e92c 100644 --- a/python/pecos/qeccs/surface_4444/gates.py +++ b/python/quantum-pecos/src/pecos/qeccs/surface_4444/gates.py @@ -30,7 +30,10 @@ def __init__(self, qecc, symbol, **gate_params) -> None: """ super().__init__(qecc, symbol, **gate_params) - expected_params(gate_params, {"num_syn_extract", "error_free", "forced_outcome"}) + expected_params( + gate_params, + {"num_syn_extract", "error_free", "forced_outcome"}, + ) self.num_syn_extract = gate_params.get("num_syn_extract", qecc.distance) @@ -50,7 +53,10 @@ def __init__(self, qecc, symbol, **gate_params) -> None: """ super().__init__(qecc, symbol, **gate_params) - expected_params(gate_params, {"num_syn_extract", "error_free", "forced_outcome"}) + expected_params( + gate_params, + {"num_syn_extract", "error_free", "forced_outcome"}, + ) self.num_syn_extract = gate_params.get("num_syn_extract", 0) @@ -72,7 +78,10 @@ def __init__(self, qecc, symbol, **gate_params) -> None: """ super().__init__(qecc, symbol, **gate_params) - expected_params(gate_params, {"num_syn_extract", "error_free", "forced_outcome"}) + expected_params( + gate_params, + {"num_syn_extract", "error_free", "forced_outcome"}, + ) self.num_syn_extract = gate_params.get("num_syn_extract", 0) diff --git a/python/pecos/qeccs/surface_4444/instructions.py b/python/quantum-pecos/src/pecos/qeccs/surface_4444/instructions.py similarity index 97% rename from python/pecos/qeccs/surface_4444/instructions.py rename to python/quantum-pecos/src/pecos/qeccs/surface_4444/instructions.py index 2b6d02ce..f1ee201f 100644 --- a/python/pecos/qeccs/surface_4444/instructions.py +++ b/python/quantum-pecos/src/pecos/qeccs/surface_4444/instructions.py @@ -60,14 +60,20 @@ def __init__(self, qecc, symbol, **params) -> None: logical_ops = [ # Each element in the list corresponds to a logical qubit # The keys label the type of logical operator - {"X": QuantumCircuit([{"X": x_qudits}]), "Z": QuantumCircuit([{"Z": z_qudits}])}, + { + "X": QuantumCircuit([{"X": x_qudits}]), + "Z": QuantumCircuit([{"Z": z_qudits}]), + }, ] self.initial_logical_ops = logical_ops logical_ops = [ # Each element in the list corresponds to a logical qubit # The keys label the type of logical operator - {"X": QuantumCircuit([{"X": x_qudits}]), "Z": QuantumCircuit([{"Z": z_qudits}])}, + { + "X": QuantumCircuit([{"X": x_qudits}]), + "Z": QuantumCircuit([{"Z": z_qudits}]), + }, ] self.final_logical_ops = logical_ops diff --git a/python/pecos/qeccs/surface_4444/surface_4444.py b/python/quantum-pecos/src/pecos/qeccs/surface_4444/surface_4444.py similarity index 95% rename from python/pecos/qeccs/surface_4444/surface_4444.py rename to python/quantum-pecos/src/pecos/qeccs/surface_4444/surface_4444.py index ff674b8b..d7d5a9aa 100644 --- a/python/pecos/qeccs/surface_4444/surface_4444.py +++ b/python/quantum-pecos/src/pecos/qeccs/surface_4444/surface_4444.py @@ -16,10 +16,15 @@ Generates circuits for the repetition code in the Z-Basis. """ + from pecos.circuit_converters.checks2circuit import Check2Circuits from pecos.qeccs.qecc_parent_class import QECC from pecos.qeccs.surface_4444.gates import GateIdentity, GateInitPlus, GateInitZero -from pecos.qeccs.surface_4444.instructions import InstrInitPlus, InstrInitZero, InstrSynExtraction +from pecos.qeccs.surface_4444.instructions import ( + InstrInitPlus, + InstrInitZero, + InstrSynExtraction, +) class Surface4444(QECC): @@ -56,7 +61,9 @@ def __init__(self, distance=None, height=None, width=None, **qecc_params) -> Non self.distance, self.height, self.width = self._get_distance() # n - number of data qubits - self.num_data_qudits = 2 * self.height * self.width - self.height - self.width + 1 + self.num_data_qudits = ( + 2 * self.height * self.width - self.height - self.width + 1 + ) # k - number of logical qubits self.num_logical_qudits = 1 @@ -69,7 +76,9 @@ def __init__(self, distance=None, height=None, width=None, **qecc_params) -> Non # gate circuits implemented by this class. # -------------------------------------------------------------------------------------------------------------- self.circuit_compiler = qecc_params.get("circuit_compiler", Check2Circuits()) - self.num_ancilla_qudits = self.circuit_compiler.get_num_ancillas(self.num_syndromes) + self.num_ancilla_qudits = self.circuit_compiler.get_num_ancillas( + self.num_syndromes, + ) # Total number of qudits. # self.qudit_set, self.data_qudit_set, self.ancilla_qudit_set will be determined when creating the layout. @@ -118,7 +127,9 @@ def _get_distance(self): if width is not None and height is not None: if distance is not None: - msg = "The distance should not be specified if the height and width are." + msg = ( + "The distance should not be specified if the height and width are." + ) raise Exception(msg) distance = min(width, height) diff --git a/python/pecos/qeccs/surface_medial_4444/__init__.py b/python/quantum-pecos/src/pecos/qeccs/surface_medial_4444/__init__.py similarity index 100% rename from python/pecos/qeccs/surface_medial_4444/__init__.py rename to python/quantum-pecos/src/pecos/qeccs/surface_medial_4444/__init__.py diff --git a/python/pecos/qeccs/surface_medial_4444/gates.py b/python/quantum-pecos/src/pecos/qeccs/surface_medial_4444/gates.py similarity index 88% rename from python/pecos/qeccs/surface_medial_4444/gates.py rename to python/quantum-pecos/src/pecos/qeccs/surface_medial_4444/gates.py index 79a9d680..c012e92c 100644 --- a/python/pecos/qeccs/surface_medial_4444/gates.py +++ b/python/quantum-pecos/src/pecos/qeccs/surface_medial_4444/gates.py @@ -30,7 +30,10 @@ def __init__(self, qecc, symbol, **gate_params) -> None: """ super().__init__(qecc, symbol, **gate_params) - expected_params(gate_params, {"num_syn_extract", "error_free", "forced_outcome"}) + expected_params( + gate_params, + {"num_syn_extract", "error_free", "forced_outcome"}, + ) self.num_syn_extract = gate_params.get("num_syn_extract", qecc.distance) @@ -50,7 +53,10 @@ def __init__(self, qecc, symbol, **gate_params) -> None: """ super().__init__(qecc, symbol, **gate_params) - expected_params(gate_params, {"num_syn_extract", "error_free", "forced_outcome"}) + expected_params( + gate_params, + {"num_syn_extract", "error_free", "forced_outcome"}, + ) self.num_syn_extract = gate_params.get("num_syn_extract", 0) @@ -72,7 +78,10 @@ def __init__(self, qecc, symbol, **gate_params) -> None: """ super().__init__(qecc, symbol, **gate_params) - expected_params(gate_params, {"num_syn_extract", "error_free", "forced_outcome"}) + expected_params( + gate_params, + {"num_syn_extract", "error_free", "forced_outcome"}, + ) self.num_syn_extract = gate_params.get("num_syn_extract", 0) diff --git a/python/pecos/qeccs/surface_medial_4444/instructions.py b/python/quantum-pecos/src/pecos/qeccs/surface_medial_4444/instructions.py similarity index 96% rename from python/pecos/qeccs/surface_medial_4444/instructions.py rename to python/quantum-pecos/src/pecos/qeccs/surface_medial_4444/instructions.py index 4b50026f..d2943c9a 100644 --- a/python/pecos/qeccs/surface_medial_4444/instructions.py +++ b/python/quantum-pecos/src/pecos/qeccs/surface_medial_4444/instructions.py @@ -66,14 +66,20 @@ def __init__(self, qecc, symbol, **params) -> None: logical_ops = [ # Each element in the list corresponds to a logical qubit # The keys label the type of logical operator - {"X": QuantumCircuit([{"X": x_qudits}]), "Z": QuantumCircuit([{"Z": z_qudits}])}, + { + "X": QuantumCircuit([{"X": x_qudits}]), + "Z": QuantumCircuit([{"Z": z_qudits}]), + }, ] self.initial_logical_ops = logical_ops logical_ops = [ # Each element in the list corresponds to a logical qubit # The keys label the type of logical operator - {"X": QuantumCircuit([{"X": x_qudits}]), "Z": QuantumCircuit([{"Z": z_qudits}])}, + { + "X": QuantumCircuit([{"X": x_qudits}]), + "Z": QuantumCircuit([{"Z": z_qudits}]), + }, ] self.final_logical_ops = logical_ops @@ -95,7 +101,11 @@ def _create_x_check(self, ancilla, x, y): data_pos = self._data_pos_x_check(x, y) # Get the actual, available data-qubits and their ticks that correspond to the possible data qubit positions - datas, my_data_ticks = self._find_data(position_to_qudit=self.pos2qudit, positions=data_pos, ticks=self.x_ticks) + datas, my_data_ticks = self._find_data( + position_to_qudit=self.pos2qudit, + positions=data_pos, + ticks=self.x_ticks, + ) # Now add the check to the extended circuit locations = set(datas) @@ -118,7 +128,11 @@ def _create_z_check(self, ancilla, x, y): # get where the position of where the data qubits should be relative to the ancilla data_pos = self._data_pos_z_check(x, y) # Get the actual, available data-qubits and their ticks that correspond to the possible data qubit positions - datas, my_data_ticks = self._find_data(position_to_qudit=self.pos2qudit, positions=data_pos, ticks=self.z_ticks) + datas, my_data_ticks = self._find_data( + position_to_qudit=self.pos2qudit, + positions=data_pos, + ticks=self.z_ticks, + ) # Now add the check to the extended circuit locations = set(datas) diff --git a/python/pecos/qeccs/surface_medial_4444/surface_medial_4444.py b/python/quantum-pecos/src/pecos/qeccs/surface_medial_4444/surface_medial_4444.py similarity index 94% rename from python/pecos/qeccs/surface_medial_4444/surface_medial_4444.py rename to python/quantum-pecos/src/pecos/qeccs/surface_medial_4444/surface_medial_4444.py index 6df2b907..ec2ec5c3 100644 --- a/python/pecos/qeccs/surface_medial_4444/surface_medial_4444.py +++ b/python/quantum-pecos/src/pecos/qeccs/surface_medial_4444/surface_medial_4444.py @@ -16,10 +16,19 @@ Generates circuits for the repetition code in the Z-Basis. """ + from pecos.circuit_converters.checks2circuit import Check2Circuits from pecos.qeccs.qecc_parent_class import QECC -from pecos.qeccs.surface_medial_4444.gates import GateIdentity, GateInitPlus, GateInitZero -from pecos.qeccs.surface_medial_4444.instructions import InstrInitPlus, InstrInitZero, InstrSynExtraction +from pecos.qeccs.surface_medial_4444.gates import ( + GateIdentity, + GateInitPlus, + GateInitZero, +) +from pecos.qeccs.surface_medial_4444.instructions import ( + InstrInitPlus, + InstrInitZero, + InstrSynExtraction, +) class SurfaceMedial4444(QECC): @@ -71,7 +80,9 @@ def __init__(self, distance=None, height=None, width=None, **qecc_params) -> Non # gate circuits implemented by this class. # -------------------------------------------------------------------------------------------------------------- self.circuit_compiler = qecc_params.get("circuit_compiler", Check2Circuits()) - self.num_ancilla_qudits = self.circuit_compiler.get_num_ancillas(self.num_syndromes) + self.num_ancilla_qudits = self.circuit_compiler.get_num_ancillas( + self.num_syndromes, + ) # Total number of qudits. # self.qudit_set, self.data_qudit_set, self.ancilla_qudit_set will be determined when creating the layout. @@ -121,7 +132,9 @@ def _get_distance(self): if width is not None and height is not None: if distance is not None: - msg = "The distance should not be specified if the height and width are." + msg = ( + "The distance should not be specified if the height and width are." + ) raise Exception(msg) distance = min(width, height) @@ -163,7 +176,9 @@ def _generate_layout(self): "height": 2 * height, } - xy_iter = self._rotated_orientaition() if self.rotated else self._norm_orientaition() + xy_iter = ( + self._rotated_orientaition() if self.rotated else self._norm_orientaition() + ) # Determine the position of things for x, y in xy_iter: diff --git a/python/pecos/qeclib/__init__.py b/python/quantum-pecos/src/pecos/qeclib/__init__.py similarity index 100% rename from python/pecos/qeclib/__init__.py rename to python/quantum-pecos/src/pecos/qeclib/__init__.py diff --git a/python/pecos/qeclib/generic/__init__.py b/python/quantum-pecos/src/pecos/qeclib/generic/__init__.py similarity index 100% rename from python/pecos/qeclib/generic/__init__.py rename to python/quantum-pecos/src/pecos/qeclib/generic/__init__.py diff --git a/python/pecos/qeclib/generic/check.py b/python/quantum-pecos/src/pecos/qeclib/generic/check.py similarity index 100% rename from python/pecos/qeclib/generic/check.py rename to python/quantum-pecos/src/pecos/qeclib/generic/check.py diff --git a/python/pecos/qeclib/generic/check_1flag.py b/python/quantum-pecos/src/pecos/qeclib/generic/check_1flag.py similarity index 100% rename from python/pecos/qeclib/generic/check_1flag.py rename to python/quantum-pecos/src/pecos/qeclib/generic/check_1flag.py diff --git a/python/pecos/qeclib/qubit/__init__.py b/python/quantum-pecos/src/pecos/qeclib/qubit/__init__.py similarity index 91% rename from python/pecos/qeclib/qubit/__init__.py rename to python/quantum-pecos/src/pecos/qeclib/qubit/__init__.py index d097ac53..16b7097c 100644 --- a/python/pecos/qeclib/qubit/__init__.py +++ b/python/quantum-pecos/src/pecos/qeclib/qubit/__init__.py @@ -17,7 +17,17 @@ from pecos.qeclib.qubit.sq_noncliffords import T, Tdg from pecos.qeclib.qubit.sq_paulis import X, Y, Z from pecos.qeclib.qubit.sq_sqrt_paulis import SX, SY, SZ, SXdg, SYdg, SZdg -from pecos.qeclib.qubit.tq_cliffords import CX, CY, CZ, SXX, SYY, SZZ, SXXdg, SYYdg, SZZdg +from pecos.qeclib.qubit.tq_cliffords import ( + CX, + CY, + CZ, + SXX, + SYY, + SZZ, + SXXdg, + SYYdg, + SZZdg, +) from pecos.qeclib.qubit.tq_noncliffords import CH __all__ = [ diff --git a/python/pecos/qeclib/qubit/measures.py b/python/quantum-pecos/src/pecos/qeclib/qubit/measures.py similarity index 100% rename from python/pecos/qeclib/qubit/measures.py rename to python/quantum-pecos/src/pecos/qeclib/qubit/measures.py diff --git a/python/pecos/qeclib/qubit/preps.py b/python/quantum-pecos/src/pecos/qeclib/qubit/preps.py similarity index 100% rename from python/pecos/qeclib/qubit/preps.py rename to python/quantum-pecos/src/pecos/qeclib/qubit/preps.py diff --git a/python/pecos/qeclib/qubit/qgate_base.py b/python/quantum-pecos/src/pecos/qeclib/qubit/qgate_base.py similarity index 97% rename from python/pecos/qeclib/qubit/qgate_base.py rename to python/quantum-pecos/src/pecos/qeclib/qubit/qgate_base.py index 0fc585ca..0eff7bac 100644 --- a/python/pecos/qeclib/qubit/qgate_base.py +++ b/python/quantum-pecos/src/pecos/qeclib/qubit/qgate_base.py @@ -70,7 +70,7 @@ def __call__(self, *qargs): return g def gen(self, target: object | str): - + # TODO: Get rid of this as much as possible... if isinstance(target, str): if target == "qasm": target = QASMGenerator() diff --git a/python/pecos/qeclib/qubit/rots.py b/python/quantum-pecos/src/pecos/qeclib/qubit/rots.py similarity index 100% rename from python/pecos/qeclib/qubit/rots.py rename to python/quantum-pecos/src/pecos/qeclib/qubit/rots.py diff --git a/python/pecos/qeclib/qubit/sq_face_rots.py b/python/quantum-pecos/src/pecos/qeclib/qubit/sq_face_rots.py similarity index 100% rename from python/pecos/qeclib/qubit/sq_face_rots.py rename to python/quantum-pecos/src/pecos/qeclib/qubit/sq_face_rots.py diff --git a/python/pecos/qeclib/qubit/sq_hadamards.py b/python/quantum-pecos/src/pecos/qeclib/qubit/sq_hadamards.py similarity index 100% rename from python/pecos/qeclib/qubit/sq_hadamards.py rename to python/quantum-pecos/src/pecos/qeclib/qubit/sq_hadamards.py diff --git a/python/pecos/qeclib/qubit/sq_noncliffords.py b/python/quantum-pecos/src/pecos/qeclib/qubit/sq_noncliffords.py similarity index 100% rename from python/pecos/qeclib/qubit/sq_noncliffords.py rename to python/quantum-pecos/src/pecos/qeclib/qubit/sq_noncliffords.py diff --git a/python/pecos/qeclib/qubit/sq_paulis.py b/python/quantum-pecos/src/pecos/qeclib/qubit/sq_paulis.py similarity index 100% rename from python/pecos/qeclib/qubit/sq_paulis.py rename to python/quantum-pecos/src/pecos/qeclib/qubit/sq_paulis.py diff --git a/python/pecos/qeclib/qubit/sq_sqrt_paulis.py b/python/quantum-pecos/src/pecos/qeclib/qubit/sq_sqrt_paulis.py similarity index 100% rename from python/pecos/qeclib/qubit/sq_sqrt_paulis.py rename to python/quantum-pecos/src/pecos/qeclib/qubit/sq_sqrt_paulis.py diff --git a/python/pecos/qeclib/qubit/tq_cliffords.py b/python/quantum-pecos/src/pecos/qeclib/qubit/tq_cliffords.py similarity index 100% rename from python/pecos/qeclib/qubit/tq_cliffords.py rename to python/quantum-pecos/src/pecos/qeclib/qubit/tq_cliffords.py diff --git a/python/pecos/qeclib/qubit/tq_noncliffords.py b/python/quantum-pecos/src/pecos/qeclib/qubit/tq_noncliffords.py similarity index 100% rename from python/pecos/qeclib/qubit/tq_noncliffords.py rename to python/quantum-pecos/src/pecos/qeclib/qubit/tq_noncliffords.py diff --git a/python/pecos/qeclib/steane/__init__.py b/python/quantum-pecos/src/pecos/qeclib/steane/__init__.py similarity index 100% rename from python/pecos/qeclib/steane/__init__.py rename to python/quantum-pecos/src/pecos/qeclib/steane/__init__.py diff --git a/python/pecos/qeclib/steane/decoders/__init__.py b/python/quantum-pecos/src/pecos/qeclib/steane/decoders/__init__.py similarity index 100% rename from python/pecos/qeclib/steane/decoders/__init__.py rename to python/quantum-pecos/src/pecos/qeclib/steane/decoders/__init__.py diff --git a/python/pecos/qeclib/steane/decoders/lookup.py b/python/quantum-pecos/src/pecos/qeclib/steane/decoders/lookup.py similarity index 95% rename from python/pecos/qeclib/steane/decoders/lookup.py rename to python/quantum-pecos/src/pecos/qeclib/steane/decoders/lookup.py index 675de1ce..9d386dc6 100644 --- a/python/pecos/qeclib/steane/decoders/lookup.py +++ b/python/quantum-pecos/src/pecos/qeclib/steane/decoders/lookup.py @@ -89,7 +89,6 @@ def __init__( class FlagLookupQASMActiveCorrectionX(Block): - def __init__( self, qubits: QReg, @@ -144,7 +143,9 @@ def __init__( Comment(), If(scratch[0] == 1).Then(qubit.Z(q[0])), Comment("not possible for X stabilizers V"), - Comment(f"if({scratch[1]} == 1) z {q[1]};"), # If(scratch[2] == 1).Then(qubit.Z(q[1])), + Comment( + f"if({scratch[1]} == 1) z {q[1]};", + ), # If(scratch[2] == 1).Then(qubit.Z(q[1])), If(scratch[2] == 1).Then(qubit.Z(q[2])), If(scratch[3] == 1).Then(qubit.Z(q[3])), If(scratch[4] == 1).Then(qubit.Z(q[4])), @@ -163,7 +164,18 @@ def __init__( class FlagLookupQASMActiveCorrectionZ(Block): - def __init__(self, qubits, syn, syndromes, raw_syn, pf, flag, flags, scratch, pf_bit_copy: Bit = None): + def __init__( + self, + qubits, + syn, + syndromes, + raw_syn, + pf, + flag, + flags, + scratch, + pf_bit_copy: Bit = None, + ): super().__init__() q = qubits diff --git a/python/pecos/qeclib/steane/gates_sq/__init__.py b/python/quantum-pecos/src/pecos/qeclib/steane/gates_sq/__init__.py similarity index 100% rename from python/pecos/qeclib/steane/gates_sq/__init__.py rename to python/quantum-pecos/src/pecos/qeclib/steane/gates_sq/__init__.py diff --git a/python/pecos/qeclib/steane/gates_sq/face_rots.py b/python/quantum-pecos/src/pecos/qeclib/steane/gates_sq/face_rots.py similarity index 100% rename from python/pecos/qeclib/steane/gates_sq/face_rots.py rename to python/quantum-pecos/src/pecos/qeclib/steane/gates_sq/face_rots.py diff --git a/python/pecos/qeclib/steane/gates_sq/hadamards.py b/python/quantum-pecos/src/pecos/qeclib/steane/gates_sq/hadamards.py similarity index 100% rename from python/pecos/qeclib/steane/gates_sq/hadamards.py rename to python/quantum-pecos/src/pecos/qeclib/steane/gates_sq/hadamards.py diff --git a/python/pecos/qeclib/steane/gates_sq/paulis.py b/python/quantum-pecos/src/pecos/qeclib/steane/gates_sq/paulis.py similarity index 100% rename from python/pecos/qeclib/steane/gates_sq/paulis.py rename to python/quantum-pecos/src/pecos/qeclib/steane/gates_sq/paulis.py diff --git a/python/pecos/qeclib/steane/gates_sq/sqrt_paulis.py b/python/quantum-pecos/src/pecos/qeclib/steane/gates_sq/sqrt_paulis.py similarity index 100% rename from python/pecos/qeclib/steane/gates_sq/sqrt_paulis.py rename to python/quantum-pecos/src/pecos/qeclib/steane/gates_sq/sqrt_paulis.py diff --git a/python/pecos/qeclib/steane/gates_tq/__init__.py b/python/quantum-pecos/src/pecos/qeclib/steane/gates_tq/__init__.py similarity index 100% rename from python/pecos/qeclib/steane/gates_tq/__init__.py rename to python/quantum-pecos/src/pecos/qeclib/steane/gates_tq/__init__.py diff --git a/python/pecos/qeclib/steane/gates_tq/transversal_tq.py b/python/quantum-pecos/src/pecos/qeclib/steane/gates_tq/transversal_tq.py similarity index 100% rename from python/pecos/qeclib/steane/gates_tq/transversal_tq.py rename to python/quantum-pecos/src/pecos/qeclib/steane/gates_tq/transversal_tq.py diff --git a/python/pecos/qeclib/steane/meas/__init__.py b/python/quantum-pecos/src/pecos/qeclib/steane/meas/__init__.py similarity index 100% rename from python/pecos/qeclib/steane/meas/__init__.py rename to python/quantum-pecos/src/pecos/qeclib/steane/meas/__init__.py diff --git a/python/pecos/qeclib/steane/meas/destructive_meas.py b/python/quantum-pecos/src/pecos/qeclib/steane/meas/destructive_meas.py similarity index 96% rename from python/pecos/qeclib/steane/meas/destructive_meas.py rename to python/quantum-pecos/src/pecos/qeclib/steane/meas/destructive_meas.py index 0d9620fe..bcb6a357 100644 --- a/python/pecos/qeclib/steane/meas/destructive_meas.py +++ b/python/quantum-pecos/src/pecos/qeclib/steane/meas/destructive_meas.py @@ -28,7 +28,14 @@ class MeasureX(Block): SYdg: X->Z, Y->Y, Z->-X """ - def __init__(self, qubits: QReg, meas_creg: CReg, log_raw: Bit, *, barrier: bool = True): + def __init__( + self, + qubits: QReg, + meas_creg: CReg, + log_raw: Bit, + *, + barrier: bool = True, + ): super().__init__() self.extend( @@ -45,7 +52,14 @@ class MeasureY(Block): SX: X->X, Y->Z, Z->-Y """ - def __init__(self, qubits: QReg, meas_creg: CReg, log_raw: Bit, *, barrier: bool = True): + def __init__( + self, + qubits: QReg, + meas_creg: CReg, + log_raw: Bit, + *, + barrier: bool = True, + ): super().__init__() self.extend( diff --git a/python/pecos/qeclib/steane/meas/measure_x.py b/python/quantum-pecos/src/pecos/qeclib/steane/meas/measure_x.py similarity index 100% rename from python/pecos/qeclib/steane/meas/measure_x.py rename to python/quantum-pecos/src/pecos/qeclib/steane/meas/measure_x.py diff --git a/python/pecos/qeclib/steane/meas/measure_z.py b/python/quantum-pecos/src/pecos/qeclib/steane/meas/measure_z.py similarity index 100% rename from python/pecos/qeclib/steane/meas/measure_z.py rename to python/quantum-pecos/src/pecos/qeclib/steane/meas/measure_z.py diff --git a/python/pecos/qeclib/steane/preps/__init__.py b/python/quantum-pecos/src/pecos/qeclib/steane/preps/__init__.py similarity index 100% rename from python/pecos/qeclib/steane/preps/__init__.py rename to python/quantum-pecos/src/pecos/qeclib/steane/preps/__init__.py diff --git a/python/pecos/qeclib/steane/preps/encoding_circ.py b/python/quantum-pecos/src/pecos/qeclib/steane/preps/encoding_circ.py similarity index 100% rename from python/pecos/qeclib/steane/preps/encoding_circ.py rename to python/quantum-pecos/src/pecos/qeclib/steane/preps/encoding_circ.py diff --git a/python/pecos/qeclib/steane/preps/pauli_states.py b/python/quantum-pecos/src/pecos/qeclib/steane/preps/pauli_states.py similarity index 93% rename from python/pecos/qeclib/steane/preps/pauli_states.py rename to python/quantum-pecos/src/pecos/qeclib/steane/preps/pauli_states.py index 53e711f6..e84e5f08 100644 --- a/python/pecos/qeclib/steane/preps/pauli_states.py +++ b/python/quantum-pecos/src/pecos/qeclib/steane/preps/pauli_states.py @@ -48,7 +48,14 @@ def __init__(self, q: QReg): class PrepZeroVerify(Block): """Verify the initialization of InitEncodingNonFTZero""" - def __init__(self, qubits: QReg, ancilla: Qubit, init_bit: Bit, *, reset_ancilla: bool = True): + def __init__( + self, + qubits: QReg, + ancilla: Qubit, + init_bit: Bit, + *, + reset_ancilla: bool = True, + ): q = qubits a = ancilla c = init_bit @@ -86,7 +93,14 @@ class PrepEncodingFTZero(Block): reset (bool): """ - def __init__(self, data: QReg, ancilla: Qubit, init_bit: Bit, *, reset: bool = True): + def __init__( + self, + data: QReg, + ancilla: Qubit, + init_bit: Bit, + *, + reset: bool = True, + ): q = data a = ancilla diff --git a/python/pecos/qeclib/steane/preps/plus_h_state.py b/python/quantum-pecos/src/pecos/qeclib/steane/preps/plus_h_state.py similarity index 78% rename from python/pecos/qeclib/steane/preps/plus_h_state.py rename to python/quantum-pecos/src/pecos/qeclib/steane/preps/plus_h_state.py index 4fcbc1c4..ea59cecf 100644 --- a/python/pecos/qeclib/steane/preps/plus_h_state.py +++ b/python/quantum-pecos/src/pecos/qeclib/steane/preps/plus_h_state.py @@ -14,7 +14,10 @@ from pecos.qeclib import qubit from pecos.qeclib.generic.check_1flag import Check1Flag from pecos.qeclib.steane.preps.encoding_circ import EncodingCircuit -from pecos.qeclib.steane.syn_extract.three_parallel_flagging import ThreeParallelFlaggingXZZ, ThreeParallelFlaggingZXX +from pecos.qeclib.steane.syn_extract.three_parallel_flagging import ( + ThreeParallelFlaggingXZZ, + ThreeParallelFlaggingZXX, +) from pecos.slr import Bit, Block, Comment, CReg, If, QReg, Repeat @@ -69,18 +72,42 @@ def __init__( # QED self.extend( - ThreeParallelFlaggingXZZ(d, a, flag_x, flag_z, flags, last_raw_syn_x, last_raw_syn_z), + ThreeParallelFlaggingXZZ( + d, + a, + flag_x, + flag_z, + flags, + last_raw_syn_x, + last_raw_syn_z, + ), ) if condition_qed: self.extend( If(flags == 0).Then( - ThreeParallelFlaggingZXX(d, a, flag_x, flag_z, flags, last_raw_syn_x, last_raw_syn_z), + ThreeParallelFlaggingZXX( + d, + a, + flag_x, + flag_z, + flags, + last_raw_syn_x, + last_raw_syn_z, + ), ), ) else: self.extend( - ThreeParallelFlaggingZXX(d, a, flag_x, flag_z, flags, last_raw_syn_x, last_raw_syn_z), + ThreeParallelFlaggingZXX( + d, + a, + flag_x, + flag_z, + flags, + last_raw_syn_x, + last_raw_syn_z, + ), ) self.extend( @@ -115,7 +142,17 @@ def __init__( limit: int, ): super().__init__( - PrepHStateFT(d, a, out, reject, flag_x, flag_z, flags, last_raw_syn_x, last_raw_syn_z), + PrepHStateFT( + d, + a, + out, + reject, + flag_x, + flag_z, + flags, + last_raw_syn_x, + last_raw_syn_z, + ), Repeat(limit - 1).block( If(reject != 0).Then( PrepHStateFT( diff --git a/python/pecos/qeclib/steane/preps/t_plus_state.py b/python/quantum-pecos/src/pecos/qeclib/steane/preps/t_plus_state.py similarity index 86% rename from python/pecos/qeclib/steane/preps/t_plus_state.py rename to python/quantum-pecos/src/pecos/qeclib/steane/preps/t_plus_state.py index 2c6bc315..b713d352 100644 --- a/python/pecos/qeclib/steane/preps/t_plus_state.py +++ b/python/quantum-pecos/src/pecos/qeclib/steane/preps/t_plus_state.py @@ -67,7 +67,17 @@ def __init__( last_raw_syn_z: CReg, ): super().__init__( - PrepHStateFT(d, a, out, reject, flag_x, flag_z, flags, last_raw_syn_x, last_raw_syn_z), + PrepHStateFT( + d, + a, + out, + reject, + flag_x, + flag_z, + flags, + last_raw_syn_x, + last_raw_syn_z, + ), F(d), # |+H> -> T|+X> ) @@ -100,6 +110,17 @@ def __init__( ): # NOTE: For QASM, have to avoid nested If statements super().__init__( - PrepHStateFTRUS(d, a, out, reject, flag_x, flag_z, flags, last_raw_syn_x, last_raw_syn_z, limit), + PrepHStateFTRUS( + d, + a, + out, + reject, + flag_x, + flag_z, + flags, + last_raw_syn_x, + last_raw_syn_z, + limit, + ), F(d), ) diff --git a/python/pecos/qeclib/steane/qec/__init__.py b/python/quantum-pecos/src/pecos/qeclib/steane/qec/__init__.py similarity index 100% rename from python/pecos/qeclib/steane/qec/__init__.py rename to python/quantum-pecos/src/pecos/qeclib/steane/qec/__init__.py diff --git a/python/pecos/qeclib/steane/qec/qec_3parallel.py b/python/quantum-pecos/src/pecos/qeclib/steane/qec/qec_3parallel.py similarity index 56% rename from python/pecos/qeclib/steane/qec/qec_3parallel.py rename to python/quantum-pecos/src/pecos/qeclib/steane/qec/qec_3parallel.py index b9c5e5ca..7f68e2a6 100644 --- a/python/pecos/qeclib/steane/qec/qec_3parallel.py +++ b/python/quantum-pecos/src/pecos/qeclib/steane/qec/qec_3parallel.py @@ -9,9 +9,15 @@ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the # specific language governing permissions and limitations under the License. -from pecos.qeclib.steane.decoders.lookup import FlagLookupQASMActiveCorrectionX, FlagLookupQASMActiveCorrectionZ +from pecos.qeclib.steane.decoders.lookup import ( + FlagLookupQASMActiveCorrectionX, + FlagLookupQASMActiveCorrectionZ, +) from pecos.qeclib.steane.syn_extract.six_check_nonflagging import SixUnflaggedSyn -from pecos.qeclib.steane.syn_extract.three_parallel_flagging import ThreeParallelFlaggingXZZ, ThreeParallelFlaggingZXX +from pecos.qeclib.steane.syn_extract.three_parallel_flagging import ( + ThreeParallelFlaggingXZZ, + ThreeParallelFlaggingZXX, +) from pecos.slr import Bit, Block, CReg, If, QReg @@ -36,15 +42,49 @@ def __init__( ): super().__init__( # flagging XZZ checks - ThreeParallelFlaggingXZZ(q, a, flag_x, flag_z, flags, last_raw_syn_x, last_raw_syn_z), + ThreeParallelFlaggingXZZ( + q, + a, + flag_x, + flag_z, + flags, + last_raw_syn_x, + last_raw_syn_z, + ), # flagging ZXX checks If(flags == 0).Then( - ThreeParallelFlaggingZXX(q, a, flag_x, flag_z, flags, last_raw_syn_x, last_raw_syn_z), + ThreeParallelFlaggingZXX( + q, + a, + flag_x, + flag_z, + flags, + last_raw_syn_x, + last_raw_syn_z, + ), ), # Remeasure all the checks unflagged If(flags != 0).Then( SixUnflaggedSyn(q, a, syn_x, syn_z), ), - FlagLookupQASMActiveCorrectionX(q, syn_x, syndromes, last_raw_syn_x, pf_z, flag_x, flags, scratch), - FlagLookupQASMActiveCorrectionZ(q, syn_z, syndromes, last_raw_syn_z, pf_x, flag_z, flags, scratch), + FlagLookupQASMActiveCorrectionX( + q, + syn_x, + syndromes, + last_raw_syn_x, + pf_z, + flag_x, + flags, + scratch, + ), + FlagLookupQASMActiveCorrectionZ( + q, + syn_z, + syndromes, + last_raw_syn_z, + pf_x, + flag_z, + flags, + scratch, + ), ) diff --git a/python/pecos/qeclib/steane/steane_class.py b/python/quantum-pecos/src/pecos/qeclib/steane/steane_class.py similarity index 97% rename from python/pecos/qeclib/steane/steane_class.py rename to python/quantum-pecos/src/pecos/qeclib/steane/steane_class.py index 66c938d8..d059b506 100644 --- a/python/pecos/qeclib/steane/steane_class.py +++ b/python/quantum-pecos/src/pecos/qeclib/steane/steane_class.py @@ -19,7 +19,10 @@ from pecos.qeclib.steane.gates_tq import transversal_tq from pecos.qeclib.steane.meas.destructive_meas import MeasDecode from pecos.qeclib.steane.preps.pauli_states import PrepRUS -from pecos.qeclib.steane.preps.t_plus_state import PrepEncodeTPlusFTRUS, PrepEncodeTPlusNonFT +from pecos.qeclib.steane.preps.t_plus_state import ( + PrepEncodeTPlusFTRUS, + PrepEncodeTPlusNonFT, +) from pecos.qeclib.steane.qec.qec_3parallel import ParallelFlagQECActiveCorrection from pecos.slr import Block, CReg, If, Permute, QReg, Vars @@ -33,7 +36,12 @@ class Steane(Vars): This represents one particular choice of Steane protocols. For finer control construct your own class or utilize the library of Steane code protocols directly.""" - def __init__(self, name: str, default_rus_limit: int = 3, ancillas: QReg | None = None): + def __init__( + self, + name: str, + default_rus_limit: int = 3, + ancillas: QReg | None = None, + ): super().__init__() self.d = QReg(f"{name}_d", 7) self.a = ancillas or QReg(f"{name}_a", 3) @@ -254,7 +262,7 @@ def prep_tdg_plus_state(self, reject: Bit, rus_limit: int | None = None): return Block( self.prep_t_plus_state(reject=reject, rus_limit=rus_limit), - self.z(), + self.szdg(), ) def x(self): @@ -345,7 +353,8 @@ def nonft_t_tel(self, aux: Steane): T gate via teleportation using non-fault-tolerant initialization of the T|+> state. This version teleports the logical qubit from the original qubit to the auxiliary logical qubit. For - convenience, the qubits are relabeled, so you can continue to use the original Steane code logical qubit.""" + convenience, the qubits are relabeled, so you can continue to use the original Steane code logical qubit. + """ warn("Using experimental feature: nonft_t_tel", stacklevel=2) return Block( aux.nonft_prep_t_plus_state(), @@ -362,7 +371,8 @@ def t_tel(self, aux: Steane, reject: Bit, rus_limit: int | None = None): T gate via teleportation using fault-tolerant initialization of the T|+> state. This version teleports the logical qubit from the original qubit to the auxiliary logical qubit. For - convenience, the qubits are relabeled, so you can continue to use the original Steane code logical qubit.""" + convenience, the qubits are relabeled, so you can continue to use the original Steane code logical qubit. + """ warn("Using experimental feature: t_tel", stacklevel=2) block = Block( aux.prep_t_plus_state(reject=reject, rus_limit=rus_limit), @@ -383,7 +393,8 @@ def nonft_tdg_tel(self, aux: Steane): Tdg gate via teleportation using non-fault-tolerant initialization of the Tdg|+> state. This version teleports the logical qubit from the original qubit to the auxiliary logical qubit. For - convenience, the qubits are relabeled, so you can continue to use the original Steane code logical qubit.""" + convenience, the qubits are relabeled, so you can continue to use the original Steane code logical qubit. + """ warn("Using experimental feature: nonft_tdg_tel", stacklevel=2) return Block( aux.nonft_prep_tdg_plus_state(), @@ -400,7 +411,8 @@ def tdg_tel(self, aux: Steane, reject: Bit, rus_limit: int | None = None): Tdg gate via teleportation using fault-tolerant initialization of the Tdg|+> state. This version teleports the logical qubit from the original qubit to the auxiliary logical qubit. For - convenience, the qubits are relabeled, so you can continue to use the original Steane code logical qubit.""" + convenience, the qubits are relabeled, so you can continue to use the original Steane code logical qubit. + """ warn("Using experimental feature: tdg_tel", stacklevel=2) block = Block( aux.prep_tdg_plus_state(reject=reject, rus_limit=rus_limit), diff --git a/python/pecos/qeclib/steane/syn_extract/__init__.py b/python/quantum-pecos/src/pecos/qeclib/steane/syn_extract/__init__.py similarity index 100% rename from python/pecos/qeclib/steane/syn_extract/__init__.py rename to python/quantum-pecos/src/pecos/qeclib/steane/syn_extract/__init__.py diff --git a/python/pecos/qeclib/steane/syn_extract/six_check_nonflagging.py b/python/quantum-pecos/src/pecos/qeclib/steane/syn_extract/six_check_nonflagging.py similarity index 100% rename from python/pecos/qeclib/steane/syn_extract/six_check_nonflagging.py rename to python/quantum-pecos/src/pecos/qeclib/steane/syn_extract/six_check_nonflagging.py diff --git a/python/pecos/qeclib/steane/syn_extract/three_parallel_flagging.py b/python/quantum-pecos/src/pecos/qeclib/steane/syn_extract/three_parallel_flagging.py similarity index 100% rename from python/pecos/qeclib/steane/syn_extract/three_parallel_flagging.py rename to python/quantum-pecos/src/pecos/qeclib/steane/syn_extract/three_parallel_flagging.py diff --git a/python/pecos/reps/__init__.py b/python/quantum-pecos/src/pecos/reps/__init__.py similarity index 100% rename from python/pecos/reps/__init__.py rename to python/quantum-pecos/src/pecos/reps/__init__.py diff --git a/python/pecos/reps/pypmir/__init__.py b/python/quantum-pecos/src/pecos/reps/pypmir/__init__.py similarity index 100% rename from python/pecos/reps/pypmir/__init__.py rename to python/quantum-pecos/src/pecos/reps/pypmir/__init__.py diff --git a/python/pecos/reps/pypmir/block_types.py b/python/quantum-pecos/src/pecos/reps/pypmir/block_types.py similarity index 100% rename from python/pecos/reps/pypmir/block_types.py rename to python/quantum-pecos/src/pecos/reps/pypmir/block_types.py diff --git a/python/pecos/reps/pypmir/data_types.py b/python/quantum-pecos/src/pecos/reps/pypmir/data_types.py similarity index 85% rename from python/pecos/reps/pypmir/data_types.py rename to python/quantum-pecos/src/pecos/reps/pypmir/data_types.py index c9aa2464..bb4fa5fd 100644 --- a/python/pecos/reps/pypmir/data_types.py +++ b/python/quantum-pecos/src/pecos/reps/pypmir/data_types.py @@ -19,7 +19,12 @@ class Data(Instr): class DefineVar(Data): - def __init__(self, data_type: str | type, variable: str, metadata: dict | None = None) -> None: + def __init__( + self, + data_type: str | type, + variable: str, + metadata: dict | None = None, + ) -> None: super().__init__(metadata=metadata) self.data_type = data_type self.variable = variable @@ -54,7 +59,12 @@ def __init__( class ExportVar(Data): - def __init__(self, variables: list[str], to: list[str] | None = None, metadata: dict | None = None) -> None: + def __init__( + self, + variables: list[str], + to: list[str] | None = None, + metadata: dict | None = None, + ) -> None: super().__init__(metadata=metadata) self.variables = variables self.to = to diff --git a/python/pecos/simulators/cuquantum_old/custatevec/gates_meas.py b/python/quantum-pecos/src/pecos/reps/pypmir/instr_type.py similarity index 67% rename from python/pecos/simulators/cuquantum_old/custatevec/gates_meas.py rename to python/quantum-pecos/src/pecos/reps/pypmir/instr_type.py index bdc591be..484788d2 100644 --- a/python/pecos/simulators/cuquantum_old/custatevec/gates_meas.py +++ b/python/quantum-pecos/src/pecos/reps/pypmir/instr_type.py @@ -1,4 +1,4 @@ -# Copyright 2022 The PECOS Developers +# Copyright 2024 The PECOS Developers # # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with # the License.You may obtain a copy of the License at @@ -9,10 +9,11 @@ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the # specific language governing permissions and limitations under the License. -import numpy as np +from __future__ import annotations -def Measure(state, location, **params): - rn = np.random.uniform() - meas = state.statevec.batch_measure(state.workspace, [location], rn, True) - return meas[0] +class Instr: + """Base type for all PyMIR instructions including QOps, Blocks, MOps, etc.""" + + def __init__(self, metadata: dict | None = None) -> None: + self.metadata = metadata diff --git a/python/pecos/reps/pypmir/list_types.py b/python/quantum-pecos/src/pecos/reps/pypmir/list_types.py similarity index 100% rename from python/pecos/reps/pypmir/list_types.py rename to python/quantum-pecos/src/pecos/reps/pypmir/list_types.py diff --git a/python/pecos/reps/pypmir/name_resolver.py b/python/quantum-pecos/src/pecos/reps/pypmir/name_resolver.py similarity index 64% rename from python/pecos/reps/pypmir/name_resolver.py rename to python/quantum-pecos/src/pecos/reps/pypmir/name_resolver.py index e43433d0..99554126 100644 --- a/python/pecos/reps/pypmir/name_resolver.py +++ b/python/quantum-pecos/src/pecos/reps/pypmir/name_resolver.py @@ -1,3 +1,14 @@ +# Copyright 2024 The PECOS Developers +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with +# the License.You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. + import numpy as np from pecos.reps.pypmir.op_types import QOp diff --git a/python/pecos/reps/pypmir/op_types.py b/python/quantum-pecos/src/pecos/reps/pypmir/op_types.py similarity index 94% rename from python/pecos/reps/pypmir/op_types.py rename to python/quantum-pecos/src/pecos/reps/pypmir/op_types.py index c341c1c1..60c64cd4 100644 --- a/python/pecos/reps/pypmir/op_types.py +++ b/python/quantum-pecos/src/pecos/reps/pypmir/op_types.py @@ -82,7 +82,13 @@ def __str__(self) -> str: class COp(Op): """Classical operation.""" - def __init__(self, name: str, args: list, returns: list | None = None, metadata: dict | None = None) -> None: + def __init__( + self, + name: str, + args: list, + returns: list | None = None, + metadata: dict | None = None, + ) -> None: super().__init__( name=name, args=args, diff --git a/python/pecos/reps/pypmir/pypmir.py b/python/quantum-pecos/src/pecos/reps/pypmir/pypmir.py similarity index 94% rename from python/pecos/reps/pypmir/pypmir.py rename to python/quantum-pecos/src/pecos/reps/pypmir/pypmir.py index 80c87be9..c759dc2a 100644 --- a/python/pecos/reps/pypmir/pypmir.py +++ b/python/quantum-pecos/src/pecos/reps/pypmir/pypmir.py @@ -47,7 +47,11 @@ class PyPMIR: simulations. """ - def __init__(self, metadata: dict | None = None, name_resolver: Callable[[QOp], str] | None = None) -> None: + def __init__( + self, + metadata: dict | None = None, + name_resolver: Callable[[QOp], str] | None = None, + ) -> None: self.ops = [] self.metadata = metadata @@ -66,7 +70,6 @@ def __init__(self, metadata: dict | None = None, name_resolver: Callable[[QOp], @classmethod def handle_op(cls, o: dict | str | int, p: PyPMIR) -> TypeOp | str | list | int: - match o: case int() | str(): # Assume int value or register o: int | str @@ -81,7 +84,6 @@ def handle_op(cls, o: dict | str | int, p: PyPMIR) -> TypeOp | str | list | int: raise ValueError(msg) case dict(): - if "block" in o: if o["block"] == "sequence": ops = [] @@ -129,7 +131,12 @@ def handle_op(cls, o: dict | str | int, p: PyPMIR) -> TypeOp | str | list | int: metadata = {} if o.get("metadata") is None else o["metadata"] if o.get("angles"): - angles = tuple([angle * (pi if o["angles"][1] == "pi" else 1) for angle in o["angles"][0]]) + angles = tuple( + [ + angle * (pi if o["angles"][1] == "pi" else 1) + for angle in o["angles"][0] + ], + ) else: angles = None @@ -184,7 +191,12 @@ def handle_op(cls, o: dict | str | int, p: PyPMIR) -> TypeOp | str | list | int: else: args = None - instr = op.MOp(name=o["mop"], args=args, returns=o.get("returns"), metadata=o.get("metadata")) + instr = op.MOp( + name=o["mop"], + args=args, + returns=o.get("returns"), + metadata=o.get("metadata"), + ) if "duration" in o: if instr.metadata is None: instr.metadata = {} diff --git a/python/pecos/reps/pypmir/types.py b/python/quantum-pecos/src/pecos/reps/pypmir/types.py similarity index 100% rename from python/pecos/reps/pypmir/types.py rename to python/quantum-pecos/src/pecos/reps/pypmir/types.py diff --git a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/test/__init__.py b/python/quantum-pecos/src/pecos/rslib.py similarity index 87% rename from python/pecos/simulators/cuquantum_old/cuquantum_wrapper/test/__init__.py rename to python/quantum-pecos/src/pecos/rslib.py index 2a43c09e..7ec1a4e3 100644 --- a/python/pecos/simulators/cuquantum_old/cuquantum_wrapper/test/__init__.py +++ b/python/quantum-pecos/src/pecos/rslib.py @@ -1,4 +1,4 @@ -# Copyright 2022 The PECOS Developers +# Copyright 2024 The PECOS Developers # # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with # the License.You may obtain a copy of the License at @@ -9,4 +9,4 @@ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the # specific language governing permissions and limitations under the License. -# Initial author: Tyson Lawrence +from pecos_rslib import * # noqa: F403 diff --git a/python/pecos/simulators/__init__.py b/python/quantum-pecos/src/pecos/simulators/__init__.py similarity index 70% rename from python/pecos/simulators/__init__.py rename to python/quantum-pecos/src/pecos/simulators/__init__.py index 591bfae8..655a8d85 100644 --- a/python/pecos/simulators/__init__.py +++ b/python/quantum-pecos/src/pecos/simulators/__init__.py @@ -10,19 +10,34 @@ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the # specific language governing permissions and limitations under the License. +# Rust version of stabilizer sim +from pecos_rslib import SparseSimRs +from pecos_rslib import SparseSimRs as SparseSim + from pecos.simulators import sim_class_types from pecos.simulators.basic_sv.state import BasicSV # Basic numpy statevector simulator -from pecos.simulators.cointoss import CoinToss # Ignores quantum gates, coin toss for measurements +from pecos.simulators.cointoss import ( + CoinToss, +) + +# Ignores quantum gates, coin toss for measurements from pecos.simulators.parent_sim_classes import Simulator -from pecos.simulators.paulifaultprop import PauliFaultProp # Pauli fault propagation sim -from pecos.simulators.sparsesim import SparseSim as pySparseSim # Python sparse stabilizer sim +from pecos.simulators.paulifaultprop import ( + PauliFaultProp, +) + +# Pauli fault propagation sim +from pecos.simulators.sparsesim import ( + SparseSim as SparseSimPy, +) # C++ version of SparseStabSim wrapper try: - from pecos.simulators.cysparsesim import SparseSim - from pecos.simulators.cysparsesim import SparseSim as cySparseSim # Cython wrapped C++ sparse stabilizer sim + from pecos.simulators.cysparsesim import ( + SparseSim as SparseSimCy, + ) except ImportError: - from pecos.simulators.sparsesim import SparseSim + SparseSimCy = None # Attempt to import optional ProjectQ package try: @@ -49,8 +64,14 @@ import cupy import cuquantum - from pecos.simulators.custatevec.state import CuStateVec # wrapper for cuQuantum's cuStateVec - from pecos.simulators.mps_pytket import MPS # MPS implementation from pytket-cutensornet + from pecos.simulators.custatevec.state import ( + CuStateVec, + ) + + # wrapper for cuQuantum's cuStateVec + from pecos.simulators.mps_pytket import ( + MPS, + ) except ImportError: CuStateVec = None MPS = None diff --git a/python/pecos/simulators/basic_sv/__init__.py b/python/quantum-pecos/src/pecos/simulators/basic_sv/__init__.py similarity index 100% rename from python/pecos/simulators/basic_sv/__init__.py rename to python/quantum-pecos/src/pecos/simulators/basic_sv/__init__.py diff --git a/python/pecos/simulators/basic_sv/bindings.py b/python/quantum-pecos/src/pecos/simulators/basic_sv/bindings.py similarity index 73% rename from python/pecos/simulators/basic_sv/bindings.py rename to python/quantum-pecos/src/pecos/simulators/basic_sv/bindings.py index 8bda4052..9b59242a 100644 --- a/python/pecos/simulators/basic_sv/bindings.py +++ b/python/quantum-pecos/src/pecos/simulators/basic_sv/bindings.py @@ -69,4 +69,34 @@ "SqrtZZ": two_q.SZZ, "SZZdg": two_q.SZZdg, "SWAP": two_q.SWAP, + # Additional Cliffords from `circuit_converters/std2chs.py` + "Q": one_q.SX, + "Qd": one_q.SXdg, + "R": one_q.SY, + "Rd": one_q.SYdg, + "S": one_q.SZ, + "Sd": one_q.SZdg, + "H1": one_q.H, + "H2": one_q.H2, + "H3": one_q.H3, + "H4": one_q.H4, + "H5": one_q.H5, + "H6": one_q.H6, + "H+z+x": one_q.H, + "H-z-x": one_q.H2, + "H+y-z": one_q.H3, + "H-y-z": one_q.H4, + "H-x+y": one_q.H5, + "H-x-y": one_q.H6, + "F1": one_q.F, + "F1d": one_q.Fdg, + "F2": one_q.F2, + "F2d": one_q.F2d, + "F3": one_q.F3, + "F3d": one_q.F3d, + "F4": one_q.F4, + "F4d": one_q.F4d, + "CNOT": two_q.CX, + "G": two_q.G, + "II": one_q.identity, } diff --git a/python/pecos/simulators/basic_sv/gates_init.py b/python/quantum-pecos/src/pecos/simulators/basic_sv/gates_init.py similarity index 100% rename from python/pecos/simulators/basic_sv/gates_init.py rename to python/quantum-pecos/src/pecos/simulators/basic_sv/gates_init.py diff --git a/python/pecos/simulators/basic_sv/gates_meas.py b/python/quantum-pecos/src/pecos/simulators/basic_sv/gates_meas.py similarity index 91% rename from python/pecos/simulators/basic_sv/gates_meas.py rename to python/quantum-pecos/src/pecos/simulators/basic_sv/gates_meas.py index 879ef4c6..da0db841 100644 --- a/python/pecos/simulators/basic_sv/gates_meas.py +++ b/python/quantum-pecos/src/pecos/simulators/basic_sv/gates_meas.py @@ -53,7 +53,10 @@ def meas_z(state, qubit: int, **params: Any) -> int: ",", "Qq", # Subscripts for the projector operator, acting on `qubit` q "->", - state.subscript_string((qubit,), ("Q",)), # Resulting vector, with updated Q + state.subscript_string( + (qubit,), + ("Q",), + ), # Resulting vector, with updated Q ], ) # Obtain the projected state where qubit `qubit` is in state |0> diff --git a/python/pecos/simulators/basic_sv/gates_one_qubit.py b/python/quantum-pecos/src/pecos/simulators/basic_sv/gates_one_qubit.py similarity index 78% rename from python/pecos/simulators/basic_sv/gates_one_qubit.py rename to python/quantum-pecos/src/pecos/simulators/basic_sv/gates_one_qubit.py index 40da1f72..f8986716 100644 --- a/python/pecos/simulators/basic_sv/gates_one_qubit.py +++ b/python/quantum-pecos/src/pecos/simulators/basic_sv/gates_one_qubit.py @@ -37,7 +37,10 @@ def _apply_one_qubit_matrix(state, qubit: int, matrix: np.ndarray) -> None: ",", "Qq", # Subscripts for the gate, acting on `qubit` q "->", - state.subscript_string((qubit,), ("Q",)), # Resulting vector, with updated Q + state.subscript_string( + (qubit,), + ("Q",), + ), # Resulting vector, with updated Q ], ) # Update the state by applying the matrix @@ -326,3 +329,78 @@ def Tdg(state, qubit: int, **params: Any) -> None: qubit: The index of the qubit where the gate is applied """ RZ(state, qubit, angles=(-math.pi / 4,)) + + +# The definition of the extra Clifford gates added below come from +# circuit_converters/std2chs.py +def H2(state, qubit: int, **params: Any) -> None: + """'H2': ('S', 'S', 'H', 'S', 'S')""" + Z(state, qubit) + H(state, qubit) + Z(state, qubit) + + +def H3(state, qubit: int, **params: Any) -> None: + """'H3': ('H', 'S', 'S', 'H', 'S',)""" + X(state, qubit) + SZ(state, qubit) + + +def H4(state, qubit: int, **params: Any) -> None: + """'H4': ('H', 'S', 'S', 'H', 'S', 'S', 'S',)""" + X(state, qubit) + SZdg(state, qubit) + + +def H5(state, qubit: int, **params: Any) -> None: + """'H5': ('S', 'S', 'S', 'H', 'S')""" + SZdg(state, qubit) + H(state, qubit) + SZ(state, qubit) + + +def H6(state, qubit: int, **params: Any) -> None: + """'H6': ('S', 'H', 'S', 'S', 'S',)""" + SZ(state, qubit) + H(state, qubit) + SZdg(state, qubit) + + +def F2(state, qubit: int, **params: Any) -> None: + """'F2': ('S', 'S', 'H', 'S')""" + Z(state, qubit) + H(state, qubit) + SZ(state, qubit) + + +def F2d(state, qubit: int, **params: Any) -> None: + """'F2d': ('S', 'S', 'S', 'H', 'S', 'S')""" + SZdg(state, qubit) + H(state, qubit) + Z(state, qubit) + + +def F3(state, qubit: int, **params: Any) -> None: + """'F3': ('S', 'H', 'S', 'S')""" + SZ(state, qubit) + H(state, qubit) + Z(state, qubit) + + +def F3d(state, qubit: int, **params: Any) -> None: + """'F3d': ('S', 'S', 'H', 'S', 'S', 'S')""" + Z(state, qubit) + H(state, qubit) + SZdg(state, qubit) + + +def F4(state, qubit: int, **params: Any) -> None: + """'F4': ('H', 'S', 'S', 'S')""" + H(state, qubit) + SZdg(state, qubit) + + +def F4d(state, qubit: int, **params: Any) -> None: + """'F4d': ('S', 'H')""" + SZ(state, qubit) + H(state, qubit) diff --git a/python/pecos/simulators/basic_sv/gates_two_qubit.py b/python/quantum-pecos/src/pecos/simulators/basic_sv/gates_two_qubit.py similarity index 90% rename from python/pecos/simulators/basic_sv/gates_two_qubit.py rename to python/quantum-pecos/src/pecos/simulators/basic_sv/gates_two_qubit.py index e2a2cc5c..13778254 100644 --- a/python/pecos/simulators/basic_sv/gates_two_qubit.py +++ b/python/quantum-pecos/src/pecos/simulators/basic_sv/gates_two_qubit.py @@ -15,6 +15,8 @@ import numpy as np +from pecos.simulators.basic_sv.gates_one_qubit import H + def _apply_two_qubit_matrix(state, qubits: tuple[int, int], matrix: np.array) -> None: """ @@ -56,7 +58,11 @@ def _apply_two_qubit_matrix(state, qubits: tuple[int, int], matrix: np.array) -> ], ) # Update the state by applying the matrix - state.internal_vector = np.einsum(subscripts, state.internal_vector, reshaped_matrix) + state.internal_vector = np.einsum( + subscripts, + state.internal_vector, + reshaped_matrix, + ) def CX(state, qubits: tuple[int, int], **params: Any) -> None: @@ -194,7 +200,12 @@ def RZZ(state, qubits: tuple[int, int], angles: tuple[float], **params: Any) -> _apply_two_qubit_matrix(state, qubits, matrix) -def R2XXYYZZ(state, qubits: tuple[int, int], angles: tuple[float, float, float], **params: Any) -> None: +def R2XXYYZZ( + state, + qubits: tuple[int, int], + angles: tuple[float, float, float], + **params: Any, +) -> None: """ Apply RXX*RYY*RZZ. @@ -295,3 +306,13 @@ def SWAP(state, qubits: tuple[int, int], **params: Any) -> None: ], ) _apply_two_qubit_matrix(state, qubits, matrix) + + +def G(state, qubits: tuple[int, int], **params: Any) -> None: + """'G': (('I', 'H'), 'CNOT', ('H', 'H'), 'CNOT', ('I', 'H'))""" + H(state, qubits[1]) + CX(state, qubits) + H(state, qubits[0]) + H(state, qubits[1]) + CX(state, qubits) + H(state, qubits[1]) diff --git a/python/pecos/simulators/basic_sv/state.py b/python/quantum-pecos/src/pecos/simulators/basic_sv/state.py similarity index 94% rename from python/pecos/simulators/basic_sv/state.py rename to python/quantum-pecos/src/pecos/simulators/basic_sv/state.py index eecbab8b..12351c15 100644 --- a/python/pecos/simulators/basic_sv/state.py +++ b/python/quantum-pecos/src/pecos/simulators/basic_sv/state.py @@ -106,7 +106,10 @@ def reset(self): self.internal_vector[0] = 1 # Internally use a ndarray representation so that it's easier to apply gates # without needing to apply tensor products. - self.internal_vector = np.reshape(self.internal_vector, newshape=[2] * self.num_qubits) + self.internal_vector = np.reshape( + self.internal_vector, + newshape=[2] * self.num_qubits, + ) return self @property diff --git a/python/pecos/simulators/cointoss/__init__.py b/python/quantum-pecos/src/pecos/simulators/cointoss/__init__.py similarity index 100% rename from python/pecos/simulators/cointoss/__init__.py rename to python/quantum-pecos/src/pecos/simulators/cointoss/__init__.py diff --git a/python/pecos/simulators/cointoss/bindings.py b/python/quantum-pecos/src/pecos/simulators/cointoss/bindings.py similarity index 71% rename from python/pecos/simulators/cointoss/bindings.py rename to python/quantum-pecos/src/pecos/simulators/cointoss/bindings.py index a286f82c..195038e4 100644 --- a/python/pecos/simulators/cointoss/bindings.py +++ b/python/quantum-pecos/src/pecos/simulators/cointoss/bindings.py @@ -68,4 +68,34 @@ "SqrtZZ": ignore_gate, "SZZdg": ignore_gate, "SWAP": ignore_gate, + # Additional Cliffords from `circuit_converters/std2chs.py` + "Q": ignore_gate, + "Qd": ignore_gate, + "R": ignore_gate, + "Rd": ignore_gate, + "S": ignore_gate, + "Sd": ignore_gate, + "H1": ignore_gate, + "H2": ignore_gate, + "H3": ignore_gate, + "H4": ignore_gate, + "H5": ignore_gate, + "H6": ignore_gate, + "H+z+x": ignore_gate, + "H-z-x": ignore_gate, + "H+y-z": ignore_gate, + "H-y-z": ignore_gate, + "H-x+y": ignore_gate, + "H-x-y": ignore_gate, + "F1": ignore_gate, + "F1d": ignore_gate, + "F2": ignore_gate, + "F2d": ignore_gate, + "F3": ignore_gate, + "F3d": ignore_gate, + "F4": ignore_gate, + "F4d": ignore_gate, + "CNOT": ignore_gate, + "G": ignore_gate, + "II": ignore_gate, } diff --git a/python/pecos/simulators/cointoss/gates.py b/python/quantum-pecos/src/pecos/simulators/cointoss/gates.py similarity index 100% rename from python/pecos/simulators/cointoss/gates.py rename to python/quantum-pecos/src/pecos/simulators/cointoss/gates.py diff --git a/python/pecos/simulators/cointoss/state.py b/python/quantum-pecos/src/pecos/simulators/cointoss/state.py similarity index 100% rename from python/pecos/simulators/cointoss/state.py rename to python/quantum-pecos/src/pecos/simulators/cointoss/state.py diff --git a/python/pecos/simulators/compile_cython.py b/python/quantum-pecos/src/pecos/simulators/compile_cython.py similarity index 96% rename from python/pecos/simulators/compile_cython.py rename to python/quantum-pecos/src/pecos/simulators/compile_cython.py index 5184e33c..94acd138 100644 --- a/python/pecos/simulators/compile_cython.py +++ b/python/quantum-pecos/src/pecos/simulators/compile_cython.py @@ -28,9 +28,9 @@ def main(): for d in cython_dirs: path = Path(current_location / d) - p = subprocess.Popen( + p = subprocess.Popen( # noqa: S602 "python setup.py build_ext --inplace", # noqa: S607 - shell=True, # noqa: S602 + shell=True, cwd=path, stderr=subprocess.PIPE, ) diff --git a/python/pecos/simulators/cuquantum_old/__init__.py b/python/quantum-pecos/src/pecos/simulators/custatevec/__init__.py similarity index 100% rename from python/pecos/simulators/cuquantum_old/__init__.py rename to python/quantum-pecos/src/pecos/simulators/custatevec/__init__.py diff --git a/python/pecos/simulators/custatevec/bindings.py b/python/quantum-pecos/src/pecos/simulators/custatevec/bindings.py similarity index 73% rename from python/pecos/simulators/custatevec/bindings.py rename to python/quantum-pecos/src/pecos/simulators/custatevec/bindings.py index d0e1ce5a..c0d7f83e 100644 --- a/python/pecos/simulators/custatevec/bindings.py +++ b/python/quantum-pecos/src/pecos/simulators/custatevec/bindings.py @@ -71,4 +71,34 @@ "SqrtZZ": two_q.SZZ, "SZZdg": two_q.SZZdg, "SWAP": two_q.SWAP, + # Additional Cliffords from `circuit_converters/std2chs.py` + "Q": one_q.SX, + "Qd": one_q.SXdg, + "R": one_q.SY, + "Rd": one_q.SYdg, + "S": one_q.SZ, + "Sd": one_q.SZdg, + "H1": one_q.H, + "H2": one_q.H2, + "H3": one_q.H3, + "H4": one_q.H4, + "H5": one_q.H5, + "H6": one_q.H6, + "H+z+x": one_q.H, + "H-z-x": one_q.H2, + "H+y-z": one_q.H3, + "H-y-z": one_q.H4, + "H-x+y": one_q.H5, + "H-x-y": one_q.H6, + "F1": one_q.F, + "F1d": one_q.Fdg, + "F2": one_q.F2, + "F2d": one_q.F2d, + "F3": one_q.F3, + "F3d": one_q.F3d, + "F4": one_q.F4, + "F4d": one_q.F4d, + "CNOT": two_q.CX, + "G": two_q.G, + "II": one_q.identity, } diff --git a/python/pecos/simulators/custatevec/gates_init.py b/python/quantum-pecos/src/pecos/simulators/custatevec/gates_init.py similarity index 100% rename from python/pecos/simulators/custatevec/gates_init.py rename to python/quantum-pecos/src/pecos/simulators/custatevec/gates_init.py diff --git a/python/pecos/simulators/custatevec/gates_meas.py b/python/quantum-pecos/src/pecos/simulators/custatevec/gates_meas.py similarity index 100% rename from python/pecos/simulators/custatevec/gates_meas.py rename to python/quantum-pecos/src/pecos/simulators/custatevec/gates_meas.py diff --git a/python/pecos/simulators/custatevec/gates_one_qubit.py b/python/quantum-pecos/src/pecos/simulators/custatevec/gates_one_qubit.py similarity index 81% rename from python/pecos/simulators/custatevec/gates_one_qubit.py rename to python/quantum-pecos/src/pecos/simulators/custatevec/gates_one_qubit.py index 326d2918..ca79ca25 100644 --- a/python/pecos/simulators/custatevec/gates_one_qubit.py +++ b/python/quantum-pecos/src/pecos/simulators/custatevec/gates_one_qubit.py @@ -356,3 +356,78 @@ def Tdg(state, qubit: int, **params: Any) -> None: qubit: The index of the qubit where the gate is applied """ RZ(state, qubit, angles=(-math.pi / 4,)) + + +# The definition of the extra Clifford gates added below come from +# circuit_converters/std2chs.py +def H2(state, qubit: int, **params: Any) -> None: + """'H2': ('S', 'S', 'H', 'S', 'S')""" + Z(state, qubit) + H(state, qubit) + Z(state, qubit) + + +def H3(state, qubit: int, **params: Any) -> None: + """'H3': ('H', 'S', 'S', 'H', 'S',)""" + X(state, qubit) + SZ(state, qubit) + + +def H4(state, qubit: int, **params: Any) -> None: + """'H4': ('H', 'S', 'S', 'H', 'S', 'S', 'S',)""" + X(state, qubit) + SZdg(state, qubit) + + +def H5(state, qubit: int, **params: Any) -> None: + """'H5': ('S', 'S', 'S', 'H', 'S')""" + SZdg(state, qubit) + H(state, qubit) + SZ(state, qubit) + + +def H6(state, qubit: int, **params: Any) -> None: + """'H6': ('S', 'H', 'S', 'S', 'S',)""" + SZ(state, qubit) + H(state, qubit) + SZdg(state, qubit) + + +def F2(state, qubit: int, **params: Any) -> None: + """'F2': ('S', 'S', 'H', 'S')""" + Z(state, qubit) + H(state, qubit) + SZ(state, qubit) + + +def F2d(state, qubit: int, **params: Any) -> None: + """'F2d': ('S', 'S', 'S', 'H', 'S', 'S')""" + SZdg(state, qubit) + H(state, qubit) + Z(state, qubit) + + +def F3(state, qubit: int, **params: Any) -> None: + """'F3': ('S', 'H', 'S', 'S')""" + SZ(state, qubit) + H(state, qubit) + Z(state, qubit) + + +def F3d(state, qubit: int, **params: Any) -> None: + """'F3d': ('S', 'S', 'H', 'S', 'S', 'S')""" + Z(state, qubit) + H(state, qubit) + SZdg(state, qubit) + + +def F4(state, qubit: int, **params: Any) -> None: + """'F4': ('H', 'S', 'S', 'S')""" + H(state, qubit) + SZdg(state, qubit) + + +def F4d(state, qubit: int, **params: Any) -> None: + """'F4d': ('S', 'H')""" + SZ(state, qubit) + H(state, qubit) diff --git a/python/pecos/simulators/custatevec/gates_two_qubit.py b/python/quantum-pecos/src/pecos/simulators/custatevec/gates_two_qubit.py similarity index 91% rename from python/pecos/simulators/custatevec/gates_two_qubit.py rename to python/quantum-pecos/src/pecos/simulators/custatevec/gates_two_qubit.py index 70b74784..423f634c 100644 --- a/python/pecos/simulators/custatevec/gates_two_qubit.py +++ b/python/quantum-pecos/src/pecos/simulators/custatevec/gates_two_qubit.py @@ -16,8 +16,15 @@ import cupy as cp from cuquantum import custatevec as cusv +from pecos.simulators.custatevec.gates_one_qubit import H -def _apply_controlled_matrix(state, control: int, target: int, matrix: cp.ndarray) -> None: + +def _apply_controlled_matrix( + state, + control: int, + target: int, + matrix: cp.ndarray, +) -> None: """ Apply the matrix to the state. This should be faster for controlled gates. @@ -275,7 +282,12 @@ def RZZ(state, qubits: tuple[int, int], angles: tuple[float], **params: Any) -> _apply_two_qubit_matrix(state, qubits, matrix) -def R2XXYYZZ(state, qubits: tuple[int, int], angles: tuple[float, float, float], **params: Any) -> None: +def R2XXYYZZ( + state, + qubits: tuple[int, int], + angles: tuple[float, float, float], + **params: Any, +) -> None: """ Apply RXX*RYY*RZZ. @@ -383,7 +395,12 @@ def SWAP(state, qubits: tuple[int, int], **params: Any) -> None: sv=state.cupy_vector.data.ptr, sv_data_type=state.cuda_type, n_index_bits=state.num_qubits, - permutation=[0, 2, 1, 3], # Leave |00> and |11> where they are, swap the other two + permutation=[ + 0, + 2, + 1, + 3, + ], # Leave |00> and |11> where they are, swap the other two diagonals=0, # Don't apply a diagonal gate diagonals_data_type=state.cuda_type, adjoint=0, # Don't use the adjoint @@ -396,3 +413,13 @@ def SWAP(state, qubits: tuple[int, int], **params: Any) -> None: extra_workspace_size_in_bytes=0, # Let cuQuantum use the mempool we configured ) state.stream.synchronize() + + +def G(state, qubits: tuple[int, int], **params: Any) -> None: + """'G': (('I', 'H'), 'CNOT', ('H', 'H'), 'CNOT', ('I', 'H'))""" + H(state, qubits[1]) + CX(state, qubits) + H(state, qubits[0]) + H(state, qubits[1]) + CX(state, qubits) + H(state, qubits[1]) diff --git a/python/pecos/simulators/custatevec/state.py b/python/quantum-pecos/src/pecos/simulators/custatevec/state.py similarity index 100% rename from python/pecos/simulators/custatevec/state.py rename to python/quantum-pecos/src/pecos/simulators/custatevec/state.py diff --git a/python/pecos/simulators/cysparsesim/.gitignore b/python/quantum-pecos/src/pecos/simulators/cysparsesim/.gitignore similarity index 100% rename from python/pecos/simulators/cysparsesim/.gitignore rename to python/quantum-pecos/src/pecos/simulators/cysparsesim/.gitignore diff --git a/python/pecos/simulators/cysparsesim/__init__.py b/python/quantum-pecos/src/pecos/simulators/cysparsesim/__init__.py similarity index 100% rename from python/pecos/simulators/cysparsesim/__init__.py rename to python/quantum-pecos/src/pecos/simulators/cysparsesim/__init__.py diff --git a/python/pecos/simulators/cysparsesim/setup.py b/python/quantum-pecos/src/pecos/simulators/cysparsesim/setup.py similarity index 99% rename from python/pecos/simulators/cysparsesim/setup.py rename to python/quantum-pecos/src/pecos/simulators/cysparsesim/setup.py index c794333e..fc203271 100644 --- a/python/pecos/simulators/cysparsesim/setup.py +++ b/python/quantum-pecos/src/pecos/simulators/cysparsesim/setup.py @@ -22,6 +22,7 @@ python setup.py build_ext --inplace """ + import contextlib import shutil from distutils.core import setup diff --git a/python/pecos/simulators/cysparsesim/src/__init__.py b/python/quantum-pecos/src/pecos/simulators/cysparsesim/src/__init__.py similarity index 100% rename from python/pecos/simulators/cysparsesim/src/__init__.py rename to python/quantum-pecos/src/pecos/simulators/cysparsesim/src/__init__.py diff --git a/python/pecos/simulators/cysparsesim/src/cysparsesim.pyx b/python/quantum-pecos/src/pecos/simulators/cysparsesim/src/cysparsesim.pyx similarity index 95% rename from python/pecos/simulators/cysparsesim/src/cysparsesim.pyx rename to python/quantum-pecos/src/pecos/simulators/cysparsesim/src/cysparsesim.pyx index 8563e044..44ea7d77 100644 --- a/python/pecos/simulators/cysparsesim/src/cysparsesim.pyx +++ b/python/quantum-pecos/src/pecos/simulators/cysparsesim/src/cysparsesim.pyx @@ -92,7 +92,7 @@ cdef class SparseSim: self.num_qubits = self._c_state.num_qubits self.reserve_buckets = self._c_state.reserve_buckets - self.bindings = bindings + self.bindings = dict(bindings) for k, v in alt_symbols.items(): if v in self.bindings: self.bindings[k] = self.bindings[v] @@ -243,36 +243,36 @@ cdef class SparseSim: self._c_state.H5(qubit) return result - cdef void initzero(self, const int_num qubit): + cdef void initzero(self, const int_num qubit, int forced_outcome = -1): cdef unsigned int result - result = self._c_state.measure(qubit, 0, True) + result = self._c_state.measure(qubit, forced_outcome, True) if result == 1: self._c_state.bitflip(qubit) - cdef void initone(self, const int_num qubit): + cdef void initone(self, const int_num qubit, int forced_outcome = -1): cdef unsigned int result - result = self._c_state.measure(qubit, 1, True) + result = self._c_state.measure(qubit, forced_outcome, True) if result == 0: self._c_state.bitflip(qubit) - cdef void initplus(self, const int_num qubit): - self.initzero(qubit) + cdef void initplus(self, const int_num qubit, int forced_outcome = -1): + self.initzero(qubit, forced_outcome) self._c_state.hadamard(qubit) - cdef void initminus(self, const int_num qubit): - self.initone(qubit) + cdef void initminus(self, const int_num qubit, int forced_outcome = -1): + self.initone(qubit, forced_outcome) self._c_state.hadamard(qubit) - cdef void initplusi(self, const int_num qubit): - self.initzero(qubit) + cdef void initplusi(self, const int_num qubit, int forced_outcome = -1): + self.initzero(qubit, forced_outcome) self._c_state.H5(qubit) - cdef void initminusi(self, const int_num qubit): - self.initone(qubit) + cdef void initminusi(self, const int_num qubit, int forced_outcome = -1): + self.initone(qubit, forced_outcome) self._c_state.H6(qubit) def logical_sign(self, logical_op): diff --git a/python/pecos/simulators/cysparsesim/src/cysparsesim_header.pxd b/python/quantum-pecos/src/pecos/simulators/cysparsesim/src/cysparsesim_header.pxd similarity index 100% rename from python/pecos/simulators/cysparsesim/src/cysparsesim_header.pxd rename to python/quantum-pecos/src/pecos/simulators/cysparsesim/src/cysparsesim_header.pxd diff --git a/python/pecos/simulators/cysparsesim/src/logical_sign.py b/python/quantum-pecos/src/pecos/simulators/cysparsesim/src/logical_sign.py similarity index 85% rename from python/pecos/simulators/cysparsesim/src/logical_sign.py rename to python/quantum-pecos/src/pecos/simulators/cysparsesim/src/logical_sign.py index 2c295dd2..8e6bb79a 100644 --- a/python/pecos/simulators/cysparsesim/src/logical_sign.py +++ b/python/quantum-pecos/src/pecos/simulators/cysparsesim/src/logical_sign.py @@ -50,9 +50,14 @@ def find_logical_signs(state, logical_circuit, delogical_circuit=None): logical_xs.update(gate_locations) logical_zs.update(gate_locations) else: - raise Exception('Can not currently handle logical operator with operator "%s"!' % symbol) - - if delogical_circuit: # Check the relationship between logical operator and delogical operator. + raise Exception( + 'Can not currently handle logical operator with operator "%s"!' + % symbol, + ) + + if ( + delogical_circuit + ): # Check the relationship between logical operator and delogical operator. if len(delogical_circuit) != 1: msg = "Delogical operators are expected to only have one tick." raise Exception(msg) @@ -69,12 +74,19 @@ def find_logical_signs(state, logical_circuit, delogical_circuit=None): delogical_xs.update(gate_locations) delogical_zs.update(gate_locations) else: - raise Exception('Can not currently handle logical operator with operator "%s"!' % symbol) + raise Exception( + 'Can not currently handle logical operator with operator "%s"!' + % symbol, + ) # Make sure the logical and delogical anti-commute - anticom_x = len(logical_xs & delogical_zs) % 2 # Number of common elements modulo 2 - anticom_z = len(logical_zs & delogical_xs) % 2 # Number of common elements modulo 2 + anticom_x = ( + len(logical_xs & delogical_zs) % 2 + ) # Number of common elements modulo 2 + anticom_z = ( + len(logical_zs & delogical_xs) % 2 + ) # Number of common elements modulo 2 if not ((anticom_x + anticom_z) % 2): print(f"logical Xs: {logical_xs} logical Zs: {logical_zs}") @@ -96,10 +108,14 @@ def find_logical_signs(state, logical_circuit, delogical_circuit=None): build_stabs = set() for q in logical_xs: # For qubits that have Xs in for the logical operator... - build_stabs ^= destabs["col_z"][q] # Add in stabilizers that anti-commute for the logical operator's Xs + build_stabs ^= destabs["col_z"][ + q + ] # Add in stabilizers that anti-commute for the logical operator's Xs for q in logical_zs: - build_stabs ^= destabs["col_x"][q] # Add in stabilizers that anti-commute for the logical operator's Zs + build_stabs ^= destabs["col_x"][ + q + ] # Add in stabilizers that anti-commute for the logical operator's Zs # If a stabilizer anticommutes an even number of times for the X and/or Z Paulis... it will not appear due to ^= diff --git a/python/pecos/simulators/cysparsesim/src/sparsesim.cpp b/python/quantum-pecos/src/pecos/simulators/cysparsesim/src/sparsesim.cpp similarity index 100% rename from python/pecos/simulators/cysparsesim/src/sparsesim.cpp rename to python/quantum-pecos/src/pecos/simulators/cysparsesim/src/sparsesim.cpp diff --git a/python/pecos/simulators/cysparsesim/src/sparsesim.h b/python/quantum-pecos/src/pecos/simulators/cysparsesim/src/sparsesim.h similarity index 100% rename from python/pecos/simulators/cysparsesim/src/sparsesim.h rename to python/quantum-pecos/src/pecos/simulators/cysparsesim/src/sparsesim.h diff --git a/python/pecos/simulators/cysparsesim_col/.gitignore b/python/quantum-pecos/src/pecos/simulators/cysparsesim_col/.gitignore similarity index 100% rename from python/pecos/simulators/cysparsesim_col/.gitignore rename to python/quantum-pecos/src/pecos/simulators/cysparsesim_col/.gitignore diff --git a/python/pecos/simulators/cysparsesim_col/__init__.py b/python/quantum-pecos/src/pecos/simulators/cysparsesim_col/__init__.py similarity index 100% rename from python/pecos/simulators/cysparsesim_col/__init__.py rename to python/quantum-pecos/src/pecos/simulators/cysparsesim_col/__init__.py diff --git a/python/pecos/simulators/cysparsesim_col/setup.py b/python/quantum-pecos/src/pecos/simulators/cysparsesim_col/setup.py similarity index 99% rename from python/pecos/simulators/cysparsesim_col/setup.py rename to python/quantum-pecos/src/pecos/simulators/cysparsesim_col/setup.py index a8e0cf9d..d2a4cdcb 100644 --- a/python/pecos/simulators/cysparsesim_col/setup.py +++ b/python/quantum-pecos/src/pecos/simulators/cysparsesim_col/setup.py @@ -22,6 +22,7 @@ python setup.py build_ext --inplace """ + import contextlib import shutil from distutils.core import setup diff --git a/python/pecos/simulators/cysparsesim_col/src/__init__.py b/python/quantum-pecos/src/pecos/simulators/cysparsesim_col/src/__init__.py similarity index 100% rename from python/pecos/simulators/cysparsesim_col/src/__init__.py rename to python/quantum-pecos/src/pecos/simulators/cysparsesim_col/src/__init__.py diff --git a/python/pecos/simulators/cysparsesim_col/src/cysparsesim.pyx b/python/quantum-pecos/src/pecos/simulators/cysparsesim_col/src/cysparsesim.pyx similarity index 90% rename from python/pecos/simulators/cysparsesim_col/src/cysparsesim.pyx rename to python/quantum-pecos/src/pecos/simulators/cysparsesim_col/src/cysparsesim.pyx index d2b035a6..e2e3a433 100644 --- a/python/pecos/simulators/cysparsesim_col/src/cysparsesim.pyx +++ b/python/quantum-pecos/src/pecos/simulators/cysparsesim_col/src/cysparsesim.pyx @@ -89,7 +89,7 @@ cdef class State: self._c_state = new s.State(num_qubits) self.num_qubits = self._c_state.num_qubits - self.gate_dict = gate_dict + self.gate_dict = dict(gate_dict) cdef void hadamard(self, int_num qubit): self._c_state.hadamard(qubit) @@ -196,55 +196,55 @@ cdef class State: pass # cpdef unsigned int measure(self, const s.int_num qubit, - def measure(self, const int_num qubit, int random_outcome=0): - return self._c_state.measure(qubit, random_outcome) + def measure(self, const int_num qubit, int forced_outcome = -1): + return self._c_state.measure(qubit, forced_outcome) - def measureX(self, const int_num qubit, int random_outcome=0): + def measureX(self, const int_num qubit, int forced_outcome = -1): cdef unsigned int result self._c_state.hadamard(qubit) - result = self._c_state.measure(qubit, random_outcome) + result = self._c_state.measure(qubit, forced_outcome) self._c_state.hadamard(qubit) return result - def measureY(self, const int_num qubit, int random_outcome=0): + def measureY(self, const int_num qubit, int forced_outcome = -1): cdef unsigned int result self._c_state.H5(qubit) - result = self._c_state.measure(qubit, random_outcome) + result = self._c_state.measure(qubit, forced_outcome) self._c_state.H5(qubit) return result - cdef void initzero(self, const int_num qubit): + cdef void initzero(self, const int_num qubit, int forced_outcome = -1): cdef unsigned int result - result = self._c_state.measure(qubit, force=0) + result = self._c_state.measure(qubit, forced_outcome) if result: self._c_state.bitflip(qubit) - cdef void initone(self, const int_num qubit): + cdef void initone(self, const int_num qubit, int forced_outcome = -1): cdef unsigned int result - result = self._c_state.measure(qubit, force=0) + result = self._c_state.measure(qubit, forced_outcome) if not result: self._c_state.bitflip(qubit) - cdef void initplus(self, const int_num qubit): - self.initzero(qubit) + cdef void initplus(self, const int_num qubit, int forced_outcome = -1): + self.initzero(qubit, forced_outcome) self._c_state.hadamard(qubit) - cdef void initminus(self, const int_num qubit): - self.initone(qubit) + cdef void initminus(self, const int_num qubit, int forced_outcome = -1): + self.initone(qubit, forced_outcome) self._c_state.hadamard(qubit) - cdef void initplusi(self, const int_num qubit): - self.initzero(qubit) + cdef void initplusi(self, const int_num qubit, int forced_outcome = -1): + self.initzero(qubit, forced_outcome) self._c_state.H5(qubit) - cdef void initminusi(self, const int_num qubit): - self.initone(qubit) + cdef void initminusi(self, const int_num qubit, int forced_outcome = -1): + self.initone(qubit, forced_outcome) self._c_state.H5(qubit) def logical_sign(self, logical_op, delogical_op): diff --git a/python/pecos/simulators/cysparsesim_col/src/cysparsesim_header.pxd b/python/quantum-pecos/src/pecos/simulators/cysparsesim_col/src/cysparsesim_header.pxd similarity index 100% rename from python/pecos/simulators/cysparsesim_col/src/cysparsesim_header.pxd rename to python/quantum-pecos/src/pecos/simulators/cysparsesim_col/src/cysparsesim_header.pxd diff --git a/python/pecos/simulators/cysparsesim_col/src/logical_sign.py b/python/quantum-pecos/src/pecos/simulators/cysparsesim_col/src/logical_sign.py similarity index 90% rename from python/pecos/simulators/cysparsesim_col/src/logical_sign.py rename to python/quantum-pecos/src/pecos/simulators/cysparsesim_col/src/logical_sign.py index 2cae5ca3..398b487c 100644 --- a/python/pecos/simulators/cysparsesim_col/src/logical_sign.py +++ b/python/quantum-pecos/src/pecos/simulators/cysparsesim_col/src/logical_sign.py @@ -55,7 +55,10 @@ def find_logical_signs(state, logical_circuit, delogical_circuit): logical_xs.update(gate_locations) logical_zs.update(gate_locations) else: - raise Exception('Can not currently handle logical operator with operator "%s"!' % symbol) + raise Exception( + 'Can not currently handle logical operator with operator "%s"!' + % symbol, + ) for symbol, gate_locations in delogical_circuit.items(params=False): if symbol == "X": @@ -66,7 +69,10 @@ def find_logical_signs(state, logical_circuit, delogical_circuit): delogical_xs.update(gate_locations) delogical_zs.update(gate_locations) else: - raise Exception('Can not currently handle logical operator with operator "%s"!' % symbol) + raise Exception( + 'Can not currently handle logical operator with operator "%s"!' + % symbol, + ) # Make sure the logical and delogical anti-commute @@ -93,10 +99,14 @@ def find_logical_signs(state, logical_circuit, delogical_circuit): build_stabs = set() for q in logical_xs: # For qubits that have Xs in for the logical operator... - build_stabs ^= destabs["col_z"][q] # Add in stabilizers that anti-commute for the logical operator's Xs + build_stabs ^= destabs["col_z"][ + q + ] # Add in stabilizers that anti-commute for the logical operator's Xs for q in logical_zs: - build_stabs ^= destabs["col_x"][q] # Add in stabilizers that anti-commute for the logical operator's Zs + build_stabs ^= destabs["col_x"][ + q + ] # Add in stabilizers that anti-commute for the logical operator's Zs # If a stabilizer anticommutes an even number of times for the X and/or Z Paulis... it will not appear due to ^= diff --git a/python/pecos/simulators/cysparsesim_col/src/sparsesim - Copy.cpp b/python/quantum-pecos/src/pecos/simulators/cysparsesim_col/src/sparsesim - Copy.cpp similarity index 100% rename from python/pecos/simulators/cysparsesim_col/src/sparsesim - Copy.cpp rename to python/quantum-pecos/src/pecos/simulators/cysparsesim_col/src/sparsesim - Copy.cpp diff --git a/python/pecos/simulators/cysparsesim_col/src/sparsesim.cpp b/python/quantum-pecos/src/pecos/simulators/cysparsesim_col/src/sparsesim.cpp similarity index 100% rename from python/pecos/simulators/cysparsesim_col/src/sparsesim.cpp rename to python/quantum-pecos/src/pecos/simulators/cysparsesim_col/src/sparsesim.cpp diff --git a/python/pecos/simulators/cysparsesim_col/src/sparsesim.h b/python/quantum-pecos/src/pecos/simulators/cysparsesim_col/src/sparsesim.h similarity index 100% rename from python/pecos/simulators/cysparsesim_col/src/sparsesim.h rename to python/quantum-pecos/src/pecos/simulators/cysparsesim_col/src/sparsesim.h diff --git a/python/pecos/simulators/cysparsesim_col/src/sparsesim_works.cpp b/python/quantum-pecos/src/pecos/simulators/cysparsesim_col/src/sparsesim_works.cpp similarity index 100% rename from python/pecos/simulators/cysparsesim_col/src/sparsesim_works.cpp rename to python/quantum-pecos/src/pecos/simulators/cysparsesim_col/src/sparsesim_works.cpp diff --git a/python/pecos/simulators/cysparsesim_row/.gitignore b/python/quantum-pecos/src/pecos/simulators/cysparsesim_row/.gitignore similarity index 100% rename from python/pecos/simulators/cysparsesim_row/.gitignore rename to python/quantum-pecos/src/pecos/simulators/cysparsesim_row/.gitignore diff --git a/python/pecos/simulators/cysparsesim_row/__init__.py b/python/quantum-pecos/src/pecos/simulators/cysparsesim_row/__init__.py similarity index 100% rename from python/pecos/simulators/cysparsesim_row/__init__.py rename to python/quantum-pecos/src/pecos/simulators/cysparsesim_row/__init__.py diff --git a/python/pecos/simulators/cysparsesim_row/setup.py b/python/quantum-pecos/src/pecos/simulators/cysparsesim_row/setup.py similarity index 99% rename from python/pecos/simulators/cysparsesim_row/setup.py rename to python/quantum-pecos/src/pecos/simulators/cysparsesim_row/setup.py index a8e0cf9d..d2a4cdcb 100644 --- a/python/pecos/simulators/cysparsesim_row/setup.py +++ b/python/quantum-pecos/src/pecos/simulators/cysparsesim_row/setup.py @@ -22,6 +22,7 @@ python setup.py build_ext --inplace """ + import contextlib import shutil from distutils.core import setup diff --git a/python/pecos/simulators/cysparsesim_row/src/__init__.py b/python/quantum-pecos/src/pecos/simulators/cysparsesim_row/src/__init__.py similarity index 100% rename from python/pecos/simulators/cysparsesim_row/src/__init__.py rename to python/quantum-pecos/src/pecos/simulators/cysparsesim_row/src/__init__.py diff --git a/python/pecos/simulators/cysparsesim_row/src/cysparsesim.pyx b/python/quantum-pecos/src/pecos/simulators/cysparsesim_row/src/cysparsesim.pyx similarity index 90% rename from python/pecos/simulators/cysparsesim_row/src/cysparsesim.pyx rename to python/quantum-pecos/src/pecos/simulators/cysparsesim_row/src/cysparsesim.pyx index e707b9d7..36fc64e1 100644 --- a/python/pecos/simulators/cysparsesim_row/src/cysparsesim.pyx +++ b/python/quantum-pecos/src/pecos/simulators/cysparsesim_row/src/cysparsesim.pyx @@ -90,7 +90,7 @@ cdef class State: self._c_state = new s.State(num_qubits) self.num_qubits = self._c_state.num_qubits - self.gate_dict = gate_dict + self.gate_dict = dict(gate_dict) cdef void hadamard(self, int_num qubit): self._c_state.hadamard(qubit) @@ -197,55 +197,55 @@ cdef class State: pass # cpdef unsigned int measure(self, const s.int_num qubit, - def measure(self, const int_num qubit, int random_outcome=0): - return self._c_state.measure(qubit, random_outcome) + def measure(self, const int_num qubit, int forced_outcome = -1): + return self._c_state.measure(qubit, forced_outcome) - def measureX(self, const int_num qubit, int random_outcome=0): + def measureX(self, const int_num qubit, int forced_outcome = -1): cdef unsigned int result self._c_state.hadamard(qubit) - result = self._c_state.measure(qubit, random_outcome) + result = self._c_state.measure(qubit, forced_outcome) self._c_state.hadamard(qubit) return result - def measureY(self, const int_num qubit, int random_outcome=0): + def measureY(self, const int_num qubit, int forced_outcome = -1): cdef unsigned int result self._c_state.H5(qubit) - result = self._c_state.measure(qubit, random_outcome) + result = self._c_state.measure(qubit, forced_outcome) self._c_state.H5(qubit) return result - cdef void initzero(self, const int_num qubit): + cdef void initzero(self, const int_num qubit, int forced_outcome = -1): cdef unsigned int result - result = self._c_state.measure(qubit, force=0) + result = self._c_state.measure(qubit, forced_outcome) if result: self._c_state.bitflip(qubit) - cdef void initone(self, const int_num qubit): + cdef void initone(self, const int_num qubit, int forced_outcome = -1): cdef unsigned int result - result = self._c_state.measure(qubit, force=0) + result = self._c_state.measure(qubit, forced_outcome) if not result: self._c_state.bitflip(qubit) - cdef void initplus(self, const int_num qubit): + cdef void initplus(self, const int_num qubit, int forced_outcome = -1): self.initzero(qubit) - self._c_state.hadamard(qubit) + self._c_state.hadamard(qubit, forced_outcome) - cdef void initminus(self, const int_num qubit): + cdef void initminus(self, const int_num qubit, int forced_outcome = -1): self.initone(qubit) - self._c_state.hadamard(qubit) + self._c_state.hadamard(qubit, forced_outcome) - cdef void initplusi(self, const int_num qubit): - self.initzero(qubit) + cdef void initplusi(self, const int_num qubit, int forced_outcome = -1): + self.initzero(qubit, forced_outcome) self._c_state.H5(qubit) - cdef void initminusi(self, const int_num qubit): - self.initone(qubit) + cdef void initminusi(self, const int_num qubit, int forced_outcome = -1): + self.initone(qubit, forced_outcome) self._c_state.H5(qubit) def logical_sign(self, logical_op, delogical_op): diff --git a/python/pecos/simulators/cysparsesim_row/src/cysparsesim_header.pxd b/python/quantum-pecos/src/pecos/simulators/cysparsesim_row/src/cysparsesim_header.pxd similarity index 100% rename from python/pecos/simulators/cysparsesim_row/src/cysparsesim_header.pxd rename to python/quantum-pecos/src/pecos/simulators/cysparsesim_row/src/cysparsesim_header.pxd diff --git a/python/pecos/simulators/cysparsesim_row/src/logical_sign.py b/python/quantum-pecos/src/pecos/simulators/cysparsesim_row/src/logical_sign.py similarity index 90% rename from python/pecos/simulators/cysparsesim_row/src/logical_sign.py rename to python/quantum-pecos/src/pecos/simulators/cysparsesim_row/src/logical_sign.py index 2cae5ca3..398b487c 100644 --- a/python/pecos/simulators/cysparsesim_row/src/logical_sign.py +++ b/python/quantum-pecos/src/pecos/simulators/cysparsesim_row/src/logical_sign.py @@ -55,7 +55,10 @@ def find_logical_signs(state, logical_circuit, delogical_circuit): logical_xs.update(gate_locations) logical_zs.update(gate_locations) else: - raise Exception('Can not currently handle logical operator with operator "%s"!' % symbol) + raise Exception( + 'Can not currently handle logical operator with operator "%s"!' + % symbol, + ) for symbol, gate_locations in delogical_circuit.items(params=False): if symbol == "X": @@ -66,7 +69,10 @@ def find_logical_signs(state, logical_circuit, delogical_circuit): delogical_xs.update(gate_locations) delogical_zs.update(gate_locations) else: - raise Exception('Can not currently handle logical operator with operator "%s"!' % symbol) + raise Exception( + 'Can not currently handle logical operator with operator "%s"!' + % symbol, + ) # Make sure the logical and delogical anti-commute @@ -93,10 +99,14 @@ def find_logical_signs(state, logical_circuit, delogical_circuit): build_stabs = set() for q in logical_xs: # For qubits that have Xs in for the logical operator... - build_stabs ^= destabs["col_z"][q] # Add in stabilizers that anti-commute for the logical operator's Xs + build_stabs ^= destabs["col_z"][ + q + ] # Add in stabilizers that anti-commute for the logical operator's Xs for q in logical_zs: - build_stabs ^= destabs["col_x"][q] # Add in stabilizers that anti-commute for the logical operator's Zs + build_stabs ^= destabs["col_x"][ + q + ] # Add in stabilizers that anti-commute for the logical operator's Zs # If a stabilizer anticommutes an even number of times for the X and/or Z Paulis... it will not appear due to ^= diff --git a/python/pecos/simulators/cysparsesim_row/src/sparsesim - Copy.cpp b/python/quantum-pecos/src/pecos/simulators/cysparsesim_row/src/sparsesim - Copy.cpp similarity index 100% rename from python/pecos/simulators/cysparsesim_row/src/sparsesim - Copy.cpp rename to python/quantum-pecos/src/pecos/simulators/cysparsesim_row/src/sparsesim - Copy.cpp diff --git a/python/pecos/simulators/cysparsesim_row/src/sparsesim.cpp b/python/quantum-pecos/src/pecos/simulators/cysparsesim_row/src/sparsesim.cpp similarity index 100% rename from python/pecos/simulators/cysparsesim_row/src/sparsesim.cpp rename to python/quantum-pecos/src/pecos/simulators/cysparsesim_row/src/sparsesim.cpp diff --git a/python/pecos/simulators/cysparsesim_row/src/sparsesim.h b/python/quantum-pecos/src/pecos/simulators/cysparsesim_row/src/sparsesim.h similarity index 100% rename from python/pecos/simulators/cysparsesim_row/src/sparsesim.h rename to python/quantum-pecos/src/pecos/simulators/cysparsesim_row/src/sparsesim.h diff --git a/python/pecos/simulators/gate_syms.py b/python/quantum-pecos/src/pecos/simulators/gate_syms.py similarity index 100% rename from python/pecos/simulators/gate_syms.py rename to python/quantum-pecos/src/pecos/simulators/gate_syms.py diff --git a/python/pecos/simulators/mps_pytket/__init__.py b/python/quantum-pecos/src/pecos/simulators/mps_pytket/__init__.py similarity index 100% rename from python/pecos/simulators/mps_pytket/__init__.py rename to python/quantum-pecos/src/pecos/simulators/mps_pytket/__init__.py diff --git a/python/pecos/simulators/mps_pytket/bindings.py b/python/quantum-pecos/src/pecos/simulators/mps_pytket/bindings.py similarity index 73% rename from python/pecos/simulators/mps_pytket/bindings.py rename to python/quantum-pecos/src/pecos/simulators/mps_pytket/bindings.py index 1a6c174c..af786af3 100644 --- a/python/pecos/simulators/mps_pytket/bindings.py +++ b/python/quantum-pecos/src/pecos/simulators/mps_pytket/bindings.py @@ -71,4 +71,34 @@ "SqrtZZ": two_q.SZZ, "SZZdg": two_q.SZZdg, "SWAP": two_q.SWAP, + # Additional Cliffords from `circuit_converters/std2chs.py` + "Q": one_q.SX, + "Qd": one_q.SXdg, + "R": one_q.SY, + "Rd": one_q.SYdg, + "S": one_q.SZ, + "Sd": one_q.SZdg, + "H1": one_q.H, + "H2": one_q.H2, + "H3": one_q.H3, + "H4": one_q.H4, + "H5": one_q.H5, + "H6": one_q.H6, + "H+z+x": one_q.H, + "H-z-x": one_q.H2, + "H+y-z": one_q.H3, + "H-y-z": one_q.H4, + "H-x+y": one_q.H5, + "H-x-y": one_q.H6, + "F1": one_q.F, + "F1d": one_q.Fdg, + "F2": one_q.F2, + "F2d": one_q.F2d, + "F3": one_q.F3, + "F3d": one_q.F3d, + "F4": one_q.F4, + "F4d": one_q.F4d, + "CNOT": two_q.CX, + "G": two_q.G, + "II": one_q.identity, } diff --git a/python/pecos/simulators/mps_pytket/gates_init.py b/python/quantum-pecos/src/pecos/simulators/mps_pytket/gates_init.py similarity index 100% rename from python/pecos/simulators/mps_pytket/gates_init.py rename to python/quantum-pecos/src/pecos/simulators/mps_pytket/gates_init.py diff --git a/python/pecos/simulators/mps_pytket/gates_meas.py b/python/quantum-pecos/src/pecos/simulators/mps_pytket/gates_meas.py similarity index 100% rename from python/pecos/simulators/mps_pytket/gates_meas.py rename to python/quantum-pecos/src/pecos/simulators/mps_pytket/gates_meas.py diff --git a/python/pecos/simulators/mps_pytket/gates_one_qubit.py b/python/quantum-pecos/src/pecos/simulators/mps_pytket/gates_one_qubit.py similarity index 79% rename from python/pecos/simulators/mps_pytket/gates_one_qubit.py rename to python/quantum-pecos/src/pecos/simulators/mps_pytket/gates_one_qubit.py index 1fa31496..b41a9caa 100644 --- a/python/pecos/simulators/mps_pytket/gates_one_qubit.py +++ b/python/quantum-pecos/src/pecos/simulators/mps_pytket/gates_one_qubit.py @@ -322,3 +322,78 @@ def Tdg(state, qubit: int, **params: Any) -> None: qubit: The index of the qubit where the gate is applied """ RZ(state, qubit, angles=(-math.pi / 4,)) + + +# The definition of the extra Clifford gates added below come from +# circuit_converters/std2chs.py +def H2(state, qubit: int, **params: Any) -> None: + """'H2': ('S', 'S', 'H', 'S', 'S')""" + Z(state, qubit) + H(state, qubit) + Z(state, qubit) + + +def H3(state, qubit: int, **params: Any) -> None: + """'H3': ('H', 'S', 'S', 'H', 'S',)""" + X(state, qubit) + SZ(state, qubit) + + +def H4(state, qubit: int, **params: Any) -> None: + """'H4': ('H', 'S', 'S', 'H', 'S', 'S', 'S',)""" + X(state, qubit) + SZdg(state, qubit) + + +def H5(state, qubit: int, **params: Any) -> None: + """'H5': ('S', 'S', 'S', 'H', 'S')""" + SZdg(state, qubit) + H(state, qubit) + SZ(state, qubit) + + +def H6(state, qubit: int, **params: Any) -> None: + """'H6': ('S', 'H', 'S', 'S', 'S',)""" + SZ(state, qubit) + H(state, qubit) + SZdg(state, qubit) + + +def F2(state, qubit: int, **params: Any) -> None: + """'F2': ('S', 'S', 'H', 'S')""" + Z(state, qubit) + H(state, qubit) + SZ(state, qubit) + + +def F2d(state, qubit: int, **params: Any) -> None: + """'F2d': ('S', 'S', 'S', 'H', 'S', 'S')""" + SZdg(state, qubit) + H(state, qubit) + Z(state, qubit) + + +def F3(state, qubit: int, **params: Any) -> None: + """'F3': ('S', 'H', 'S', 'S')""" + SZ(state, qubit) + H(state, qubit) + Z(state, qubit) + + +def F3d(state, qubit: int, **params: Any) -> None: + """'F3d': ('S', 'S', 'H', 'S', 'S', 'S')""" + Z(state, qubit) + H(state, qubit) + SZdg(state, qubit) + + +def F4(state, qubit: int, **params: Any) -> None: + """'F4': ('H', 'S', 'S', 'S')""" + H(state, qubit) + SZdg(state, qubit) + + +def F4d(state, qubit: int, **params: Any) -> None: + """'F4d': ('S', 'H')""" + SZ(state, qubit) + H(state, qubit) diff --git a/python/pecos/simulators/mps_pytket/gates_two_qubit.py b/python/quantum-pecos/src/pecos/simulators/mps_pytket/gates_two_qubit.py similarity index 91% rename from python/pecos/simulators/mps_pytket/gates_two_qubit.py rename to python/quantum-pecos/src/pecos/simulators/mps_pytket/gates_two_qubit.py index 531d9fc2..f4769f1c 100644 --- a/python/pecos/simulators/mps_pytket/gates_two_qubit.py +++ b/python/quantum-pecos/src/pecos/simulators/mps_pytket/gates_two_qubit.py @@ -16,6 +16,8 @@ import cupy as cp from pytket import Qubit +from pecos.simulators.mps_pytket.gates_one_qubit import H + def _apply_two_qubit_matrix(state, qubits: tuple[int, int], matrix: cp.ndarray) -> None: """ @@ -177,7 +179,12 @@ def RZZ(state, qubits: tuple[int, int], angles: tuple[float], **params: Any) -> _apply_two_qubit_matrix(state, qubits, matrix) -def R2XXYYZZ(state, qubits: tuple[int, int], angles: tuple[float, float, float], **params: Any) -> None: +def R2XXYYZZ( + state, + qubits: tuple[int, int], + angles: tuple[float, float, float], + **params: Any, +) -> None: """ Apply RXX*RYY*RZZ. @@ -279,3 +286,13 @@ def SWAP(state, qubits: tuple[int, int], **params: Any) -> None: dtype=state.dtype, ) _apply_two_qubit_matrix(state, qubits, matrix) + + +def G(state, qubits: tuple[int, int], **params: Any) -> None: + """'G': (('I', 'H'), 'CNOT', ('H', 'H'), 'CNOT', ('I', 'H'))""" + H(state, qubits[1]) + CX(state, qubits) + H(state, qubits[0]) + H(state, qubits[1]) + CX(state, qubits) + H(state, qubits[1]) diff --git a/python/pecos/simulators/mps_pytket/state.py b/python/quantum-pecos/src/pecos/simulators/mps_pytket/state.py similarity index 100% rename from python/pecos/simulators/mps_pytket/state.py rename to python/quantum-pecos/src/pecos/simulators/mps_pytket/state.py diff --git a/python/pecos/simulators/parent_sim_classes.py b/python/quantum-pecos/src/pecos/simulators/parent_sim_classes.py similarity index 81% rename from python/pecos/simulators/parent_sim_classes.py rename to python/quantum-pecos/src/pecos/simulators/parent_sim_classes.py index 4d194c92..3f1558a7 100644 --- a/python/pecos/simulators/parent_sim_classes.py +++ b/python/quantum-pecos/src/pecos/simulators/parent_sim_classes.py @@ -20,7 +20,12 @@ class Simulator: def __init__(self) -> None: self.bindings = {} - def run_gate(self, symbol: str, locations: set[int] | set[tuple[int, ...]], **params: Any): + def run_gate( + self, + symbol: str, + locations: set[int] | set[tuple[int, ...]], + **params: Any, + ): """Args: ---- symbol: @@ -40,7 +45,11 @@ def run_gate(self, symbol: str, locations: set[int] | set[tuple[int, ...]], **pa elif "angle" in params and "angles" not in params: params["angles"] = (params["angle"],) - results = self.bindings[symbol](self, location, **params) + if symbol in self.bindings: + results = self.bindings[symbol](self, location, **params) + else: + msg = f"Gate {symbol} is not supported in this simulator." + raise Exception(msg) # TODO: get params var value ... -> result = {'sym':, 'index':, 'result': result, 'qubit': location} @@ -67,7 +76,11 @@ def run_circuit(self, circuit, removed_locations=None): results = {} for symbol, locations, params in circuit.items(): - gate_results = self.run_gate(symbol, locations - removed_locations, **params) + gate_results = self.run_gate( + symbol, + locations - removed_locations, + **params, + ) results.update(gate_results) return results diff --git a/python/pecos/simulators/paulifaultprop/__init__.py b/python/quantum-pecos/src/pecos/simulators/paulifaultprop/__init__.py similarity index 100% rename from python/pecos/simulators/paulifaultprop/__init__.py rename to python/quantum-pecos/src/pecos/simulators/paulifaultprop/__init__.py diff --git a/python/pecos/simulators/paulifaultprop/bindings.py b/python/quantum-pecos/src/pecos/simulators/paulifaultprop/bindings.py similarity index 95% rename from python/pecos/simulators/paulifaultprop/bindings.py rename to python/quantum-pecos/src/pecos/simulators/paulifaultprop/bindings.py index d8ab2217..d3fa8985 100644 --- a/python/pecos/simulators/paulifaultprop/bindings.py +++ b/python/quantum-pecos/src/pecos/simulators/paulifaultprop/bindings.py @@ -10,7 +10,13 @@ # specific language governing permissions and limitations under the License. """Specifies the symbol and function for each gate.""" -from pecos.simulators.paulifaultprop import gates_init, gates_meas, gates_one_qubit, gates_two_qubit + +from pecos.simulators.paulifaultprop import ( + gates_init, + gates_meas, + gates_one_qubit, + gates_two_qubit, +) gate_dict = { # Initialization diff --git a/python/pecos/simulators/paulifaultprop/gates_init.py b/python/quantum-pecos/src/pecos/simulators/paulifaultprop/gates_init.py similarity index 100% rename from python/pecos/simulators/paulifaultprop/gates_init.py rename to python/quantum-pecos/src/pecos/simulators/paulifaultprop/gates_init.py diff --git a/python/pecos/simulators/paulifaultprop/gates_meas.py b/python/quantum-pecos/src/pecos/simulators/paulifaultprop/gates_meas.py similarity index 100% rename from python/pecos/simulators/paulifaultprop/gates_meas.py rename to python/quantum-pecos/src/pecos/simulators/paulifaultprop/gates_meas.py diff --git a/python/pecos/simulators/paulifaultprop/gates_one_qubit.py b/python/quantum-pecos/src/pecos/simulators/paulifaultprop/gates_one_qubit.py similarity index 100% rename from python/pecos/simulators/paulifaultprop/gates_one_qubit.py rename to python/quantum-pecos/src/pecos/simulators/paulifaultprop/gates_one_qubit.py diff --git a/python/pecos/simulators/paulifaultprop/gates_two_qubit.py b/python/quantum-pecos/src/pecos/simulators/paulifaultprop/gates_two_qubit.py similarity index 100% rename from python/pecos/simulators/paulifaultprop/gates_two_qubit.py rename to python/quantum-pecos/src/pecos/simulators/paulifaultprop/gates_two_qubit.py diff --git a/python/pecos/simulators/paulifaultprop/logical_sign.py b/python/quantum-pecos/src/pecos/simulators/paulifaultprop/logical_sign.py similarity index 91% rename from python/pecos/simulators/paulifaultprop/logical_sign.py rename to python/quantum-pecos/src/pecos/simulators/paulifaultprop/logical_sign.py index b560e048..d50f98a0 100644 --- a/python/pecos/simulators/paulifaultprop/logical_sign.py +++ b/python/quantum-pecos/src/pecos/simulators/paulifaultprop/logical_sign.py @@ -40,7 +40,10 @@ def find_logical_signs(state, logical_circuit: QuantumCircuit) -> int: logical_xs.update(gate_locations) logical_zs.update(gate_locations) else: - raise Exception('Can not currently handle logical operator with operator "%s"!' % symbol) + raise Exception( + 'Can not currently handle logical operator with operator "%s"!' + % symbol, + ) anticom = len(state.faults["X"] & logical_zs) anticom += len(state.faults["Y"] & logical_zs) diff --git a/python/pecos/simulators/paulifaultprop/state.py b/python/quantum-pecos/src/pecos/simulators/paulifaultprop/state.py similarity index 96% rename from python/pecos/simulators/paulifaultprop/state.py rename to python/quantum-pecos/src/pecos/simulators/paulifaultprop/state.py index 75185579..72711db6 100644 --- a/python/pecos/simulators/paulifaultprop/state.py +++ b/python/quantum-pecos/src/pecos/simulators/paulifaultprop/state.py @@ -125,7 +125,12 @@ def run_circuit( # need to return output? - def add_faults(self, circuit: QuantumCircuit | ParamGateCollection, *, minus=False) -> None: + def add_faults( + self, + circuit: QuantumCircuit | ParamGateCollection, + *, + minus=False, + ) -> None: """A methods to add faults to the state. Args: @@ -301,4 +306,8 @@ def fault_wt(self): return wt def __str__(self) -> str: - return "{{'X': {}, 'Y': {}, 'Z': {}}}".format(self.faults["X"], self.faults["Y"], self.faults["Z"]) + return "{{'X': {}, 'Y': {}, 'Z': {}}}".format( + self.faults["X"], + self.faults["Y"], + self.faults["Z"], + ) diff --git a/python/pecos/simulators/projectq/__init__.py b/python/quantum-pecos/src/pecos/simulators/projectq/__init__.py similarity index 100% rename from python/pecos/simulators/projectq/__init__.py rename to python/quantum-pecos/src/pecos/simulators/projectq/__init__.py diff --git a/python/pecos/simulators/projectq/bindings.py b/python/quantum-pecos/src/pecos/simulators/projectq/bindings.py similarity index 92% rename from python/pecos/simulators/projectq/bindings.py rename to python/quantum-pecos/src/pecos/simulators/projectq/bindings.py index 271c2477..bb84a337 100644 --- a/python/pecos/simulators/projectq/bindings.py +++ b/python/quantum-pecos/src/pecos/simulators/projectq/bindings.py @@ -13,7 +13,12 @@ from projectq import ops -from pecos.simulators.projectq import gates_init, gates_meas, gates_one_qubit, gates_two_qubit +from pecos.simulators.projectq import ( + gates_init, + gates_meas, + gates_one_qubit, + gates_two_qubit, +) from pecos.simulators.projectq.helper import MakeFunc # Note: More ProjectQ gates can be added by updating the wrapper's `gate_dict` attribute. @@ -26,12 +31,17 @@ "T": MakeFunc(ops.T).func, # fourth root of Z "Tdg": MakeFunc(ops.Tdag).func, # fourth root of Z dagger "SSWAP": MakeFunc(ops.SqrtSwap).func, - "Entangle": MakeFunc(ops.Entangle).func, # H on first qubit and CNOT to all others... + "Entangle": MakeFunc( + ops.Entangle, + ).func, # H on first qubit and CNOT to all others... "RX": gates_one_qubit.RX, # Rotation about X (takes angle arg) "RY": gates_one_qubit.RY, # Rotation about Y (takes angle arg) "RZ": gates_one_qubit.RZ, # Rotation about Z (takes angle arg) "R1XY": gates_one_qubit.R1XY, - "PhaseRot": MakeFunc(ops.R, angle=True).func, # Phase-shift: Same as Rz but with a 1 in upper left of matrix. + "PhaseRot": MakeFunc( + ops.R, + angle=True, + ).func, # Phase-shift: Same as Rz but with a 1 in upper left of matrix. "TOFFOLI": MakeFunc(ops.Toffoli).func, "CRZ": MakeFunc(ops.CRz, angle=True).func, # Controlled-Rz gate "CRX": MakeFunc(ops.C(ops.Rx, 1), angle=True).func, # Controlled-Rx diff --git a/python/pecos/simulators/projectq/gates_init.py b/python/quantum-pecos/src/pecos/simulators/projectq/gates_init.py similarity index 100% rename from python/pecos/simulators/projectq/gates_init.py rename to python/quantum-pecos/src/pecos/simulators/projectq/gates_init.py diff --git a/python/pecos/simulators/projectq/gates_meas.py b/python/quantum-pecos/src/pecos/simulators/projectq/gates_meas.py similarity index 100% rename from python/pecos/simulators/projectq/gates_meas.py rename to python/quantum-pecos/src/pecos/simulators/projectq/gates_meas.py diff --git a/python/pecos/simulators/projectq/gates_one_qubit.py b/python/quantum-pecos/src/pecos/simulators/projectq/gates_one_qubit.py similarity index 100% rename from python/pecos/simulators/projectq/gates_one_qubit.py rename to python/quantum-pecos/src/pecos/simulators/projectq/gates_one_qubit.py diff --git a/python/pecos/simulators/projectq/gates_two_qubit.py b/python/quantum-pecos/src/pecos/simulators/projectq/gates_two_qubit.py similarity index 100% rename from python/pecos/simulators/projectq/gates_two_qubit.py rename to python/quantum-pecos/src/pecos/simulators/projectq/gates_two_qubit.py diff --git a/python/pecos/simulators/projectq/helper.py b/python/quantum-pecos/src/pecos/simulators/projectq/helper.py similarity index 100% rename from python/pecos/simulators/projectq/helper.py rename to python/quantum-pecos/src/pecos/simulators/projectq/helper.py diff --git a/python/pecos/simulators/projectq/logical_sign.py b/python/quantum-pecos/src/pecos/simulators/projectq/logical_sign.py similarity index 84% rename from python/pecos/simulators/projectq/logical_sign.py rename to python/quantum-pecos/src/pecos/simulators/projectq/logical_sign.py index d712f89a..cc729b36 100644 --- a/python/pecos/simulators/projectq/logical_sign.py +++ b/python/quantum-pecos/src/pecos/simulators/projectq/logical_sign.py @@ -14,7 +14,11 @@ from pecos.circuits import QuantumCircuit -def find_logical_signs(state, logical_circuit: QuantumCircuit, allow_float=False) -> int: +def find_logical_signs( + state, + logical_circuit: QuantumCircuit, + allow_float=False, +) -> int: """Find the sign of the logical operator. Args: @@ -50,11 +54,17 @@ def find_logical_signs(state, logical_circuit: QuantumCircuit, allow_float=False for loc in gate_locations: op_string.append("Y%s" % loc) else: - raise Exception('Can not currently handle logical operator with operator "%s"!' % symbol) + raise Exception( + 'Can not currently handle logical operator with operator "%s"!' + % symbol, + ) op_string = " ".join(op_string) state.eng.flush() - result = state.eng.backend.get_expectation_value(QubitOperator(op_string), state.qureg) + result = state.eng.backend.get_expectation_value( + QubitOperator(op_string), + state.qureg, + ) if not allow_float: result = round(result, 5) diff --git a/python/pecos/simulators/projectq/state.py b/python/quantum-pecos/src/pecos/simulators/projectq/state.py similarity index 100% rename from python/pecos/simulators/projectq/state.py rename to python/quantum-pecos/src/pecos/simulators/projectq/state.py diff --git a/python/pecos/simulators/quantum_simulator.py b/python/quantum-pecos/src/pecos/simulators/quantum_simulator.py similarity index 100% rename from python/pecos/simulators/quantum_simulator.py rename to python/quantum-pecos/src/pecos/simulators/quantum_simulator.py diff --git a/python/pecos/simulators/quest/__init__.py b/python/quantum-pecos/src/pecos/simulators/quest/__init__.py similarity index 100% rename from python/pecos/simulators/quest/__init__.py rename to python/quantum-pecos/src/pecos/simulators/quest/__init__.py diff --git a/python/pecos/simulators/quest/bindings.py b/python/quantum-pecos/src/pecos/simulators/quest/bindings.py similarity index 73% rename from python/pecos/simulators/quest/bindings.py rename to python/quantum-pecos/src/pecos/simulators/quest/bindings.py index b34d9e16..587feaa0 100644 --- a/python/pecos/simulators/quest/bindings.py +++ b/python/quantum-pecos/src/pecos/simulators/quest/bindings.py @@ -71,4 +71,34 @@ "SqrtZZ": two_q.SZZ, "SZZdg": two_q.SZZdg, "SWAP": two_q.SWAP, + # Additional Cliffords from `circuit_converters/std2chs.py` + "Q": one_q.SX, + "Qd": one_q.SXdg, + "R": one_q.SY, + "Rd": one_q.SYdg, + "S": one_q.SZ, + "Sd": one_q.SZdg, + "H1": one_q.H, + "H2": one_q.H2, + "H3": one_q.H3, + "H4": one_q.H4, + "H5": one_q.H5, + "H6": one_q.H6, + "H+z+x": one_q.H, + "H-z-x": one_q.H2, + "H+y-z": one_q.H3, + "H-y-z": one_q.H4, + "H-x+y": one_q.H5, + "H-x-y": one_q.H6, + "F1": one_q.F, + "F1d": one_q.Fdg, + "F2": one_q.F2, + "F2d": one_q.F2d, + "F3": one_q.F3, + "F3d": one_q.F3d, + "F4": one_q.F4, + "F4d": one_q.F4d, + "CNOT": two_q.CX, + "G": two_q.G, + "II": one_q.identity, } diff --git a/python/pecos/simulators/quest/gates_init.py b/python/quantum-pecos/src/pecos/simulators/quest/gates_init.py similarity index 100% rename from python/pecos/simulators/quest/gates_init.py rename to python/quantum-pecos/src/pecos/simulators/quest/gates_init.py diff --git a/python/pecos/simulators/quest/gates_meas.py b/python/quantum-pecos/src/pecos/simulators/quest/gates_meas.py similarity index 100% rename from python/pecos/simulators/quest/gates_meas.py rename to python/quantum-pecos/src/pecos/simulators/quest/gates_meas.py diff --git a/python/pecos/simulators/quest/gates_one_qubit.py b/python/quantum-pecos/src/pecos/simulators/quest/gates_one_qubit.py similarity index 77% rename from python/pecos/simulators/quest/gates_one_qubit.py rename to python/quantum-pecos/src/pecos/simulators/quest/gates_one_qubit.py index 3f1819ed..ed172f00 100644 --- a/python/pecos/simulators/quest/gates_one_qubit.py +++ b/python/quantum-pecos/src/pecos/simulators/quest/gates_one_qubit.py @@ -265,3 +265,78 @@ def Tdg(state, qubit: int, **params: Any) -> None: qubit: The index of the qubit where the gate is applied """ RZ(state, qubit, angles=(-np.pi / 4,)) + + +# The definition of the extra Clifford gates added below come from +# circuit_converters/std2chs.py +def H2(state, qubit: int, **params: Any) -> None: + """'H2': ('S', 'S', 'H', 'S', 'S')""" + Z(state, qubit) + H(state, qubit) + Z(state, qubit) + + +def H3(state, qubit: int, **params: Any) -> None: + """'H3': ('H', 'S', 'S', 'H', 'S',)""" + X(state, qubit) + SZ(state, qubit) + + +def H4(state, qubit: int, **params: Any) -> None: + """'H4': ('H', 'S', 'S', 'H', 'S', 'S', 'S',)""" + X(state, qubit) + SZdg(state, qubit) + + +def H5(state, qubit: int, **params: Any) -> None: + """'H5': ('S', 'S', 'S', 'H', 'S')""" + SZdg(state, qubit) + H(state, qubit) + SZ(state, qubit) + + +def H6(state, qubit: int, **params: Any) -> None: + """'H6': ('S', 'H', 'S', 'S', 'S',)""" + SZ(state, qubit) + H(state, qubit) + SZdg(state, qubit) + + +def F2(state, qubit: int, **params: Any) -> None: + """'F2': ('S', 'S', 'H', 'S')""" + Z(state, qubit) + H(state, qubit) + SZ(state, qubit) + + +def F2d(state, qubit: int, **params: Any) -> None: + """'F2d': ('S', 'S', 'S', 'H', 'S', 'S')""" + SZdg(state, qubit) + H(state, qubit) + Z(state, qubit) + + +def F3(state, qubit: int, **params: Any) -> None: + """'F3': ('S', 'H', 'S', 'S')""" + SZ(state, qubit) + H(state, qubit) + Z(state, qubit) + + +def F3d(state, qubit: int, **params: Any) -> None: + """'F3d': ('S', 'S', 'H', 'S', 'S', 'S')""" + Z(state, qubit) + H(state, qubit) + SZdg(state, qubit) + + +def F4(state, qubit: int, **params: Any) -> None: + """'F4': ('H', 'S', 'S', 'S')""" + H(state, qubit) + SZdg(state, qubit) + + +def F4d(state, qubit: int, **params: Any) -> None: + """'F4d': ('S', 'H')""" + SZ(state, qubit) + H(state, qubit) diff --git a/python/pecos/simulators/quest/gates_two_qubit.py b/python/quantum-pecos/src/pecos/simulators/quest/gates_two_qubit.py similarity index 91% rename from python/pecos/simulators/quest/gates_two_qubit.py rename to python/quantum-pecos/src/pecos/simulators/quest/gates_two_qubit.py index 1cc33776..5d8d6fdd 100644 --- a/python/pecos/simulators/quest/gates_two_qubit.py +++ b/python/quantum-pecos/src/pecos/simulators/quest/gates_two_qubit.py @@ -15,6 +15,8 @@ import numpy as np import pyquest.unitaries as qgate +from pecos.simulators.quest.gates_one_qubit import H + def CX(state, qubits: tuple[int, int], **params: Any) -> None: """ @@ -145,7 +147,12 @@ def RZZ(state, qubits: tuple[int, int], angles: tuple[float], **params: Any) -> state.quest_state.apply_operator(qgate.U(targets=idxs, matrix=matrix)) -def R2XXYYZZ(state, qubits: tuple[int, int], angles: tuple[float, float, float], **params: Any) -> None: +def R2XXYYZZ( + state, + qubits: tuple[int, int], + angles: tuple[float, float, float], + **params: Any, +) -> None: """ Apply RXX*RYY*RZZ. @@ -241,3 +248,13 @@ def SWAP(state, qubits: tuple[int, int], **params: Any) -> None: idxs = [state.num_qubits - q - 1 for q in qubits] state.quest_state.apply_operator(qgate.Swap(targets=idxs)) + + +def G(state, qubits: tuple[int, int], **params: Any) -> None: + """'G': (('I', 'H'), 'CNOT', ('H', 'H'), 'CNOT', ('I', 'H'))""" + H(state, qubits[1]) + CX(state, qubits) + H(state, qubits[0]) + H(state, qubits[1]) + CX(state, qubits) + H(state, qubits[1]) diff --git a/python/pecos/simulators/quest/state.py b/python/quantum-pecos/src/pecos/simulators/quest/state.py similarity index 100% rename from python/pecos/simulators/quest/state.py rename to python/quantum-pecos/src/pecos/simulators/quest/state.py diff --git a/python/pecos/simulators/qulacs/__init__.py b/python/quantum-pecos/src/pecos/simulators/qulacs/__init__.py similarity index 100% rename from python/pecos/simulators/qulacs/__init__.py rename to python/quantum-pecos/src/pecos/simulators/qulacs/__init__.py diff --git a/python/pecos/simulators/qulacs/bindings.py b/python/quantum-pecos/src/pecos/simulators/qulacs/bindings.py similarity index 73% rename from python/pecos/simulators/qulacs/bindings.py rename to python/quantum-pecos/src/pecos/simulators/qulacs/bindings.py index bbcf40d9..7ad2bb5a 100644 --- a/python/pecos/simulators/qulacs/bindings.py +++ b/python/quantum-pecos/src/pecos/simulators/qulacs/bindings.py @@ -71,4 +71,34 @@ "SqrtZZ": two_q.SZZ, "SZZdg": two_q.SZZdg, "SWAP": two_q.SWAP, + # Additional Cliffords from `circuit_converters/std2chs.py` + "Q": one_q.SX, + "Qd": one_q.SXdg, + "R": one_q.SY, + "Rd": one_q.SYdg, + "S": one_q.SZ, + "Sd": one_q.SZdg, + "H1": one_q.H, + "H2": one_q.H2, + "H3": one_q.H3, + "H4": one_q.H4, + "H5": one_q.H5, + "H6": one_q.H6, + "H+z+x": one_q.H, + "H-z-x": one_q.H2, + "H+y-z": one_q.H3, + "H-y-z": one_q.H4, + "H-x+y": one_q.H5, + "H-x-y": one_q.H6, + "F1": one_q.F, + "F1d": one_q.Fdg, + "F2": one_q.F2, + "F2d": one_q.F2d, + "F3": one_q.F3, + "F3d": one_q.F3d, + "F4": one_q.F4, + "F4d": one_q.F4d, + "CNOT": two_q.CX, + "G": two_q.G, + "II": one_q.identity, } diff --git a/python/pecos/simulators/qulacs/gates_init.py b/python/quantum-pecos/src/pecos/simulators/qulacs/gates_init.py similarity index 100% rename from python/pecos/simulators/qulacs/gates_init.py rename to python/quantum-pecos/src/pecos/simulators/qulacs/gates_init.py diff --git a/python/pecos/simulators/qulacs/gates_meas.py b/python/quantum-pecos/src/pecos/simulators/qulacs/gates_meas.py similarity index 100% rename from python/pecos/simulators/qulacs/gates_meas.py rename to python/quantum-pecos/src/pecos/simulators/qulacs/gates_meas.py diff --git a/python/pecos/simulators/qulacs/gates_one_qubit.py b/python/quantum-pecos/src/pecos/simulators/qulacs/gates_one_qubit.py similarity index 78% rename from python/pecos/simulators/qulacs/gates_one_qubit.py rename to python/quantum-pecos/src/pecos/simulators/qulacs/gates_one_qubit.py index c75ca11f..9b115160 100644 --- a/python/pecos/simulators/qulacs/gates_one_qubit.py +++ b/python/quantum-pecos/src/pecos/simulators/qulacs/gates_one_qubit.py @@ -265,3 +265,78 @@ def Tdg(state, qubit: int, **params: Any) -> None: qubit: The index of the qubit where the gate is applied """ RZ(state, qubit, angles=(-np.pi / 4,)) + + +# The definition of the extra Clifford gates added below come from +# circuit_converters/std2chs.py +def H2(state, qubit: int, **params: Any) -> None: + """'H2': ('S', 'S', 'H', 'S', 'S')""" + Z(state, qubit) + H(state, qubit) + Z(state, qubit) + + +def H3(state, qubit: int, **params: Any) -> None: + """'H3': ('H', 'S', 'S', 'H', 'S',)""" + X(state, qubit) + SZ(state, qubit) + + +def H4(state, qubit: int, **params: Any) -> None: + """'H4': ('H', 'S', 'S', 'H', 'S', 'S', 'S',)""" + X(state, qubit) + SZdg(state, qubit) + + +def H5(state, qubit: int, **params: Any) -> None: + """'H5': ('S', 'S', 'S', 'H', 'S')""" + SZdg(state, qubit) + H(state, qubit) + SZ(state, qubit) + + +def H6(state, qubit: int, **params: Any) -> None: + """'H6': ('S', 'H', 'S', 'S', 'S',)""" + SZ(state, qubit) + H(state, qubit) + SZdg(state, qubit) + + +def F2(state, qubit: int, **params: Any) -> None: + """'F2': ('S', 'S', 'H', 'S')""" + Z(state, qubit) + H(state, qubit) + SZ(state, qubit) + + +def F2d(state, qubit: int, **params: Any) -> None: + """'F2d': ('S', 'S', 'S', 'H', 'S', 'S')""" + SZdg(state, qubit) + H(state, qubit) + Z(state, qubit) + + +def F3(state, qubit: int, **params: Any) -> None: + """'F3': ('S', 'H', 'S', 'S')""" + SZ(state, qubit) + H(state, qubit) + Z(state, qubit) + + +def F3d(state, qubit: int, **params: Any) -> None: + """'F3d': ('S', 'S', 'H', 'S', 'S', 'S')""" + Z(state, qubit) + H(state, qubit) + SZdg(state, qubit) + + +def F4(state, qubit: int, **params: Any) -> None: + """'F4': ('H', 'S', 'S', 'S')""" + H(state, qubit) + SZdg(state, qubit) + + +def F4d(state, qubit: int, **params: Any) -> None: + """'F4d': ('S', 'H')""" + SZ(state, qubit) + H(state, qubit) diff --git a/python/pecos/simulators/qulacs/gates_two_qubit.py b/python/quantum-pecos/src/pecos/simulators/qulacs/gates_two_qubit.py similarity index 90% rename from python/pecos/simulators/qulacs/gates_two_qubit.py rename to python/quantum-pecos/src/pecos/simulators/qulacs/gates_two_qubit.py index 4db16fa3..6d79d876 100644 --- a/python/pecos/simulators/qulacs/gates_two_qubit.py +++ b/python/quantum-pecos/src/pecos/simulators/qulacs/gates_two_qubit.py @@ -14,7 +14,7 @@ import numpy as np import qulacs.gate as qgate -from pecos.simulators.qulacs.gates_one_qubit import SZ, SZdg +from pecos.simulators.qulacs.gates_one_qubit import SZ, H, SZdg def CX(state, qubits: tuple[int, int], **params: Any) -> None: @@ -135,7 +135,12 @@ def RZZ(state, qubits: tuple[int, int], angles: tuple[float], **params: Any) -> ).update_quantum_state(state.qulacs_state) -def R2XXYYZZ(state, qubits: tuple[int, int], angles: tuple[float, float, float], **params: Any) -> None: +def R2XXYYZZ( + state, + qubits: tuple[int, int], + angles: tuple[float, float, float], + **params: Any, +) -> None: """ Apply RXX*RYY*RZZ. @@ -231,3 +236,13 @@ def SWAP(state, qubits: tuple[int, int], **params: Any) -> None: idxs = [state.num_qubits - q - 1 for q in qubits] qgate.SWAP(idxs[0], idxs[1]).update_quantum_state(state.qulacs_state) + + +def G(state, qubits: tuple[int, int], **params: Any) -> None: + """'G': (('I', 'H'), 'CNOT', ('H', 'H'), 'CNOT', ('I', 'H'))""" + H(state, qubits[1]) + CX(state, qubits) + H(state, qubits[0]) + H(state, qubits[1]) + CX(state, qubits) + H(state, qubits[1]) diff --git a/python/pecos/simulators/qulacs/state.py b/python/quantum-pecos/src/pecos/simulators/qulacs/state.py similarity index 100% rename from python/pecos/simulators/qulacs/state.py rename to python/quantum-pecos/src/pecos/simulators/qulacs/state.py diff --git a/python/pecos/simulators/sim_class_types.py b/python/quantum-pecos/src/pecos/simulators/sim_class_types.py similarity index 100% rename from python/pecos/simulators/sim_class_types.py rename to python/quantum-pecos/src/pecos/simulators/sim_class_types.py diff --git a/python/pecos/simulators/sparsesim/__init__.py b/python/quantum-pecos/src/pecos/simulators/sparsesim/__init__.py similarity index 100% rename from python/pecos/simulators/sparsesim/__init__.py rename to python/quantum-pecos/src/pecos/simulators/sparsesim/__init__.py diff --git a/python/pecos/simulators/sparsesim/bindings.py b/python/quantum-pecos/src/pecos/simulators/sparsesim/bindings.py similarity index 97% rename from python/pecos/simulators/sparsesim/bindings.py rename to python/quantum-pecos/src/pecos/simulators/sparsesim/bindings.py index 2c5f6ad5..2b441da0 100644 --- a/python/pecos/simulators/sparsesim/bindings.py +++ b/python/quantum-pecos/src/pecos/simulators/sparsesim/bindings.py @@ -74,6 +74,9 @@ "SXX": q2.SXX, # \equiv e^{+i (\pi /4)} * e^{-i (\pi /4) XX } == R(XX, pi/2) "SYY": q2.SYY, "SZZ": q2.SZZ, + "SXXdg": q2.SXXdg, + "SYYdg": q2.SYYdg, + "SZZdg": q2.SZZdg, # Measurements # ============ "Measure +X": qmeas.meas_x, diff --git a/python/pecos/simulators/sparsesim/cmd_init.py b/python/quantum-pecos/src/pecos/simulators/sparsesim/cmd_init.py similarity index 58% rename from python/pecos/simulators/sparsesim/cmd_init.py rename to python/quantum-pecos/src/pecos/simulators/sparsesim/cmd_init.py index b701258d..8a2cdb85 100644 --- a/python/pecos/simulators/sparsesim/cmd_init.py +++ b/python/quantum-pecos/src/pecos/simulators/sparsesim/cmd_init.py @@ -18,88 +18,106 @@ from pecos.simulators.sparsesim.state import SparseSim -def init_zero(state: SparseSim, qubit: int, **params: Any) -> None: +def init_zero( + state: SparseSim, + qubit: int, + forced_outcome: int = -1, + **params: Any, +) -> None: """ Args: state: Instance representing the stabilizer state. qubit: Integer that indexes the qubit being acted on. + forced_outcome: Value for a "random" outcome. Default is -1, which means 0 and 1 are equally probable. **params: - - Returns: None - """ # Measure in the Z basis. (If random outcome, force a 0 outcome). # If outcome is 1 apply an X. - if meas_z(state, qubit, forced_outcome=0): + if meas_z(state, qubit, forced_outcome=forced_outcome): X(state, qubit) -def init_one(state: SparseSim, qubit: int, **params: Any) -> None: +def init_one( + state: SparseSim, + qubit: int, + forced_outcome: int = -1, + **params: Any, +) -> None: """Initialize qubit in state |1>. Args: state (SparseSim): Instance representing the stabilizer state. qubit (int): Integer that indexes the qubit being acted on. - - Returns: None - + forced_outcome: Value for a "random" outcome. Default is -1, which means 0 and 1 are equally probable. """ - if not meas_z(state, qubit, forced_outcome=1): + if not meas_z(state, qubit, forced_outcome=forced_outcome): X(state, qubit) -def init_plus(state: SparseSim, qubit: int, **params: Any) -> None: +def init_plus( + state: SparseSim, + qubit: int, + forced_outcome: int = -1, + **params: Any, +) -> None: """Initialize qubit in state |+>. Args: state (SparseSim): Instance representing the stabilizer state. qubit (int): Integer that indexes the qubit being acted on. - - Returns: None - + forced_outcome: Value for a "random" outcome. Default is -1, which means 0 and 1 are equally probable. """ - init_zero(state, qubit) + init_zero(state, qubit, forced_outcome=forced_outcome) H(state, qubit) -def init_minus(state: SparseSim, qubit: int, **params: Any) -> None: +def init_minus( + state: SparseSim, + qubit: int, + forced_outcome: int = -1, + **params: Any, +) -> None: """Initialize qubit in state |->. Args: state (SparseSim): Instance representing the stabilizer state. qubit (int): Integer that indexes the qubit being acted on. - - Returns: None - + forced_outcome: Value for a "random" outcome. Default is -1, which means 0 and 1 are equally probable. """ - init_zero(state, qubit) + init_zero(state, qubit, forced_outcome=forced_outcome) H2(state, qubit) -def init_plusi(state: SparseSim, qubit: int, **params: Any) -> None: +def init_plusi( + state: SparseSim, + qubit: int, + forced_outcome: int = -1, + **params: Any, +) -> None: """Initialize qubit in state |+i>. Args: state (SparseSim): Instance representing the stabilizer state. qubit (int): Integer that indexes the qubit being acted on. - - Returns: None - + forced_outcome: Value for a "random" outcome. Default is -1, which means 0 and 1 are equally probable. """ - init_zero(state, qubit) + init_zero(state, qubit, forced_outcome=forced_outcome) H5(state, qubit) -def init_minusi(state: SparseSim, qubit: int, **params: Any) -> None: +def init_minusi( + state: SparseSim, + qubit: int, + forced_outcome: int = -1, + **params: Any, +) -> None: """Initialize qubit in state |-i>. Args: state (SparseSim): Instance representing the stabilizer state. qubit (int): Integer that indexes the qubit being acted on. - - Returns: None - + forced_outcome: Value for a "random" outcome. Default is -1, which means 0 and 1 are equally probable. """ - init_zero(state, qubit) + init_zero(state, qubit, forced_outcome=forced_outcome) H6(state, qubit) diff --git a/python/pecos/simulators/sparsesim/cmd_meas.py b/python/quantum-pecos/src/pecos/simulators/sparsesim/cmd_meas.py similarity index 89% rename from python/pecos/simulators/sparsesim/cmd_meas.py rename to python/quantum-pecos/src/pecos/simulators/sparsesim/cmd_meas.py index 0ccc2f30..8665fe0c 100644 --- a/python/pecos/simulators/sparsesim/cmd_meas.py +++ b/python/quantum-pecos/src/pecos/simulators/sparsesim/cmd_meas.py @@ -19,7 +19,14 @@ from pecos.simulators.sparsesim.state import SparseSim -def meas_x(state: SparseSim, qubit: int, *, forced_outcome: int = -1, collapse: bool = True, **params) -> int: +def meas_x( + state: SparseSim, + qubit: int, + *, + forced_outcome: int = -1, + collapse: bool = True, + **params, +) -> int: """Measurement in the X basis. Args: @@ -35,14 +42,26 @@ def meas_x(state: SparseSim, qubit: int, *, forced_outcome: int = -1, collapse: """ H(state, qubit) - meas_outcome = meas_z(state, qubit, forced_outcome=forced_outcome, collapse=collapse) + meas_outcome = meas_z( + state, + qubit, + forced_outcome=forced_outcome, + collapse=collapse, + ) H(state, qubit) return meas_outcome -def meas_y(state: SparseSim, qubit: int, *, forced_outcome: int = -1, collapse: bool = True, **params) -> int: +def meas_y( + state: SparseSim, + qubit: int, + *, + forced_outcome: int = -1, + collapse: bool = True, + **params, +) -> int: """Measurement in the Y basis. Args: @@ -58,14 +77,26 @@ def meas_y(state: SparseSim, qubit: int, *, forced_outcome: int = -1, collapse: """ H5(state, qubit) - meas_outcome = meas_z(state, qubit, forced_outcome=forced_outcome, collapse=collapse) + meas_outcome = meas_z( + state, + qubit, + forced_outcome=forced_outcome, + collapse=collapse, + ) H5(state, qubit) return meas_outcome -def meas_z(state: SparseSim, qubit: int, *, forced_outcome: int = -1, collapse: bool = True, **params) -> int: +def meas_z( + state: SparseSim, + qubit: int, + *, + forced_outcome: int = -1, + collapse: bool = True, + **params, +) -> int: """Args: state (SparseSim): Instance representing the stabilizer state. qubit (int): Integer that indexes the qubit being acted on. @@ -110,14 +141,22 @@ def meas_z(state: SparseSim, qubit: int, *, forced_outcome: int = -1, collapse: else: # There is at least one anti-commuting stabilizer. => indetermined sign if collapse: - return nondeterministic_meas(state, qubit, anticom_stabs_col, anticom_destabs_col, forced_outcome) + return nondeterministic_meas( + state, + qubit, + anticom_stabs_col, + anticom_destabs_col, + forced_outcome, + ) else: if forced_outcome is not None: if forced_outcome in {0, 1}: meas_outcome = forced_outcome else: - raise Exception("forced_outcome can only be 0 or 1 and not %s" % forced_outcome) + raise Exception( + "forced_outcome can only be 0 or 1 and not %s" % forced_outcome, + ) else: meas_outcome = np.random.randint(2) @@ -153,7 +192,9 @@ def nondeterministic_meas( destabs_col_x = state.destabs.col_x destabs_col_z = state.destabs.col_z - anticom_stabs_col = set(anticom_stabs_col) # Stabilizers that anti-commute with the measurement + anticom_stabs_col = set( + anticom_stabs_col, + ) # Stabilizers that anti-commute with the measurement anticom_destabs_col = set(anticom_destabs_col) # Destabilizers that anti-commute smallest_wt = 2 * state.num_qubits + 2 @@ -297,7 +338,12 @@ def nondeterministic_meas( return meas_outcome -def force_output(state: SparseSim, qubit: int, forced_output: int = -1, **params: Any) -> int: +def force_output( + state: SparseSim, + qubit: int, + forced_output: int = -1, + **params: Any, +) -> int: """Outputs value. Used for error generators to generate outputs when replacing measurements. diff --git a/python/pecos/simulators/sparsesim/cmd_one_qubit.py b/python/quantum-pecos/src/pecos/simulators/sparsesim/cmd_one_qubit.py similarity index 100% rename from python/pecos/simulators/sparsesim/cmd_one_qubit.py rename to python/quantum-pecos/src/pecos/simulators/sparsesim/cmd_one_qubit.py diff --git a/python/pecos/simulators/sparsesim/cmd_two_qubit.py b/python/quantum-pecos/src/pecos/simulators/sparsesim/cmd_two_qubit.py similarity index 99% rename from python/pecos/simulators/sparsesim/cmd_two_qubit.py rename to python/quantum-pecos/src/pecos/simulators/sparsesim/cmd_two_qubit.py index 7243544e..12cf1a43 100644 --- a/python/pecos/simulators/sparsesim/cmd_two_qubit.py +++ b/python/quantum-pecos/src/pecos/simulators/sparsesim/cmd_two_qubit.py @@ -189,7 +189,7 @@ def CZ(state: SparseSim, qubits: tuple[int, int], **params: Any) -> None: def CY(state: SparseSim, qubits: tuple[int, int], **params: Any) -> None: """Applies a Controlled-Y gate. - XI -> XY + XI -> -XY IX -> ZX ZI -> ZI IZ -> ZZ @@ -702,6 +702,8 @@ def iSWAP(state: SparseSim, qubits: tuple[int, int], **params: Any) -> None: ZI -> ZI IZ -> IZ + ISWAP is just SZZ... + TODO: verify implementation! Args: diff --git a/python/pecos/simulators/sparsesim/logical_sign.py b/python/quantum-pecos/src/pecos/simulators/sparsesim/logical_sign.py similarity index 88% rename from python/pecos/simulators/sparsesim/logical_sign.py rename to python/quantum-pecos/src/pecos/simulators/sparsesim/logical_sign.py index 34d4b52e..b6a52080 100644 --- a/python/pecos/simulators/sparsesim/logical_sign.py +++ b/python/quantum-pecos/src/pecos/simulators/sparsesim/logical_sign.py @@ -62,9 +62,14 @@ def find_logical_signs( logical_zs.update(gate_locations) logical_ys.update(gate_locations) else: - raise Exception('Can not currently handle logical operator with operator "%s"!' % symbol) - - if delogical_circuit: # Check the relationship between logical operator and delogical operator. + raise Exception( + 'Can not currently handle logical operator with operator "%s"!' + % symbol, + ) + + if ( + delogical_circuit + ): # Check the relationship between logical operator and delogical operator. if len(delogical_circuit) != 1: msg = "Delogical operators are expected to only have one tick." raise Exception(msg) @@ -81,12 +86,19 @@ def find_logical_signs( delogical_xs.update(gate_locations) delogical_zs.update(gate_locations) else: - raise Exception('Can not currently handle logical operator with operator "%s"!' % symbol) + raise Exception( + 'Can not currently handle logical operator with operator "%s"!' + % symbol, + ) # Make sure the logical and delogical anti-commute - anticom_x = len(logical_xs & delogical_zs) % 2 # Number of common elements modulo 2 - anticom_z = len(logical_zs & delogical_xs) % 2 # Number of common elements modulo 2 + anticom_x = ( + len(logical_xs & delogical_zs) % 2 + ) # Number of common elements modulo 2 + anticom_z = ( + len(logical_zs & delogical_xs) % 2 + ) # Number of common elements modulo 2 if not ((anticom_x + anticom_z) % 2): print(f"logical Xs: {logical_xs} logical Zs: {logical_zs}") @@ -108,10 +120,14 @@ def find_logical_signs( build_stabs = set() for q in logical_xs: # For qubits that have Xs in for the logical operator... - build_stabs ^= destabs.col_z[q] # Add in stabilizers that anti-commute for the logical operator's Xs + build_stabs ^= destabs.col_z[ + q + ] # Add in stabilizers that anti-commute for the logical operator's Xs for q in logical_zs: - build_stabs ^= destabs.col_x[q] # Add in stabilizers that anti-commute for the logical operator's Zs + build_stabs ^= destabs.col_x[ + q + ] # Add in stabilizers that anti-commute for the logical operator's Zs # If a stabilizer anticommutes an even number of times for the X and/or Z Paulis... it will not appear due to ^= diff --git a/python/pecos/simulators/sparsesim/refactor.py b/python/quantum-pecos/src/pecos/simulators/sparsesim/refactor.py similarity index 100% rename from python/pecos/simulators/sparsesim/refactor.py rename to python/quantum-pecos/src/pecos/simulators/sparsesim/refactor.py diff --git a/python/pecos/simulators/sparsesim/state.py b/python/quantum-pecos/src/pecos/simulators/sparsesim/state.py similarity index 93% rename from python/pecos/simulators/sparsesim/state.py rename to python/quantum-pecos/src/pecos/simulators/sparsesim/state.py index 8cd4385b..fa560ec5 100644 --- a/python/pecos/simulators/sparsesim/state.py +++ b/python/quantum-pecos/src/pecos/simulators/sparsesim/state.py @@ -77,12 +77,14 @@ def __init__(self, num_qubits: int) -> None: super().__init__() if not isinstance(num_qubits, int): - msg = f"`num_qubits` should be of type `int` but got type: {type(num_qubits)}" + msg = ( + f"`num_qubits` should be of type `int` but got type: {type(num_qubits)}" + ) raise TypeError(msg) self.num_qubits = num_qubits - self.bindings = bindings.gate_dict + self.bindings = dict(bindings.gate_dict) for k, v in alt_symbols.items(): if v in self.bindings: self.bindings[k] = self.bindings[v] @@ -119,13 +121,25 @@ def logical_sign( # delogical_op ) - def refactor(self, xs: set[int], zs: set[int], choose=None, prefer=None, protected=None): + def refactor( + self, + xs: set[int], + zs: set[int], + choose=None, + prefer=None, + protected=None, + ): return refactor_generators(self, xs, zs, choose, prefer, protected) def find_stab(self, xs: set[int], zs: set[int]): return find_stabilizer(self, xs, zs) - def run_direct(self, symbol: str, location: set[int | tuple[int, ...]], **gate_kwargs: Any): + def run_direct( + self, + symbol: str, + location: set[int | tuple[int, ...]], + **gate_kwargs: Any, + ): self.bindings[symbol](self, location, **gate_kwargs) def copy(self): @@ -165,7 +179,14 @@ def _pauli_sign(gen, i_gen: int) -> str: return sign - def col_string(self, gen, num_qubits: int | None = None, *, print_signs: bool = True, print_y: bool = False): + def col_string( + self, + gen, + num_qubits: int | None = None, + *, + print_signs: bool = True, + print_y: bool = False, + ): """Prints out the stabilizers for the column-wise sparse representation. Args: @@ -252,19 +273,37 @@ def col_string(self, gen, num_qubits: int | None = None, *, print_signs: bool = return result - def print_stabs(self, *, verbose: bool = True, print_y: bool = True, print_destabs: bool = False): + def print_stabs( + self, + *, + verbose: bool = True, + print_y: bool = True, + print_destabs: bool = False, + ): str_s = self.print_tableau(self.stabs, verbose=verbose, print_y=print_y) if print_destabs: if verbose: print("-------------------------------") - str_d = self.print_tableau(self.destabs, verbose=verbose, print_signs=False, print_y=print_y) + str_d = self.print_tableau( + self.destabs, + verbose=verbose, + print_signs=False, + print_y=print_y, + ) return str_s, str_d return str_s - def print_tableau(self, gen, *, verbose: bool = True, print_signs: bool = True, print_y: bool = True): + def print_tableau( + self, + gen, + *, + verbose: bool = True, + print_signs: bool = True, + print_y: bool = True, + ): """Prints out the stabilizers. :return: """ diff --git a/python/pecos/slr/__init__.py b/python/quantum-pecos/src/pecos/slr/__init__.py similarity index 100% rename from python/pecos/slr/__init__.py rename to python/quantum-pecos/src/pecos/slr/__init__.py diff --git a/python/pecos/slr/block.py b/python/quantum-pecos/src/pecos/slr/block.py similarity index 90% rename from python/pecos/slr/block.py rename to python/quantum-pecos/src/pecos/slr/block.py index c5fc0d63..882f3c8e 100644 --- a/python/pecos/slr/block.py +++ b/python/quantum-pecos/src/pecos/slr/block.py @@ -62,11 +62,10 @@ def __iter__(self): def iter(self): yield from self.__iter__() - def gen(self, target: object | str): - + def gen(self, target: object | str, add_versions=True): if isinstance(target, str): if target == "qasm": - target = QASMGenerator() + target = QASMGenerator(add_versions=add_versions) else: msg = f"Code gen target '{target}' is not supported." raise NotImplementedError(msg) @@ -74,5 +73,5 @@ def gen(self, target: object | str): target.generate_block(self) return target.get_output() - def qasm(self): - return self.gen("qasm") + def qasm(self, add_versions=True): + return self.gen("qasm", add_versions=add_versions) diff --git a/python/pecos/slr/cond_block.py b/python/quantum-pecos/src/pecos/slr/cond_block.py similarity index 99% rename from python/pecos/slr/cond_block.py rename to python/quantum-pecos/src/pecos/slr/cond_block.py index 4571a07f..969b9bf4 100644 --- a/python/pecos/slr/cond_block.py +++ b/python/quantum-pecos/src/pecos/slr/cond_block.py @@ -14,7 +14,6 @@ class CondBlock(Block): - def __init__(self, *args, cond=None, ops=None): if cond is None and args: if len(args) > 1: @@ -35,7 +34,6 @@ def _extend(self, *ops): class If(CondBlock): - def __init__(self, *args, cond=None, then_block=None, else_block=None): super().__init__(*args, cond=cond, ops=then_block) self.else_block = None if else_block is None else self.Else(else_block) @@ -49,7 +47,6 @@ def Else(self, *args): class Repeat(CondBlock): - def __init__(self, cond=None): if not isinstance(cond, int): msg = f"Condition for Repeat block must be an int! Got type: {type(cond)}" diff --git a/python/pecos/slr/cops.py b/python/quantum-pecos/src/pecos/slr/cops.py similarity index 99% rename from python/pecos/slr/cops.py rename to python/quantum-pecos/src/pecos/slr/cops.py index 171cb0f1..f3758221 100644 --- a/python/pecos/slr/cops.py +++ b/python/quantum-pecos/src/pecos/slr/cops.py @@ -17,7 +17,6 @@ class PyCOp: - def __isub__(self, other): raise NotImplementedError diff --git a/python/pecos/slr/fund.py b/python/quantum-pecos/src/pecos/slr/fund.py similarity index 100% rename from python/pecos/slr/fund.py rename to python/quantum-pecos/src/pecos/slr/fund.py diff --git a/python/pecos/slr/gen_codes/__init__.py b/python/quantum-pecos/src/pecos/slr/gen_codes/__init__.py similarity index 100% rename from python/pecos/slr/gen_codes/__init__.py rename to python/quantum-pecos/src/pecos/slr/gen_codes/__init__.py diff --git a/python/pecos/slr/gen_codes/gen_qasm.py b/python/quantum-pecos/src/pecos/slr/gen_codes/gen_qasm.py similarity index 85% rename from python/pecos/slr/gen_codes/gen_qasm.py rename to python/quantum-pecos/src/pecos/slr/gen_codes/gen_qasm.py index 56c3d1c1..86276cd3 100644 --- a/python/pecos/slr/gen_codes/gen_qasm.py +++ b/python/quantum-pecos/src/pecos/slr/gen_codes/gen_qasm.py @@ -15,11 +15,12 @@ class QASMGenerator: - def __init__(self, includes: list[str] | None = None): + def __init__(self, includes: list[str] | None = None, add_versions=True): self.output = [] self.current_scope = None self.includes = includes self.cond = None + self.add_versions = add_versions def write(self, line): self.output.append(line) @@ -37,8 +38,10 @@ def enter_block(self, block): for inc in self.includes: self.write(f'include "{str(inc)}";') else: + # TODO: dump definitions in for things that are used instead of using includes self.write('include "hqslib1.inc";') - self.write(f"// Generated using: PECOS version {__version__}") + if self.add_versions: + self.write(f"// Generated using: PECOS version {__version__}") for var in block.vars: var_def = self.process_var_def(var) self.write(var_def) @@ -71,7 +74,6 @@ def generate_block(self, block): self.cond = None elif block_name == "Repeat": - for _ in range(block.cond): self.block_op_loop(block) else: @@ -180,7 +182,6 @@ def generate_op(self, op): op_list = op_str.split("\n") op_new = [] for o in op_list: - o = o.strip() if o != "" and not o.startswith("//"): for qi in o.split(";"): @@ -215,22 +216,34 @@ def process_qgate(self, op): op_str = self.qgate_tq_qasm(op) else: - match sym: case "Measure": - op_str = " ".join([f"measure {str(q)} -> {c};" for q, c in zip(op.qargs, op.cout, strict=True)]) + op_str = " ".join( + [ + f"measure {str(q)} -> {c};" + for q, c in zip(op.qargs, op.cout, strict=True) + ], + ) case "F": - op_str = " ".join([f"rx(pi/2) {str(q)};\nrz(pi/2) {str(q)};" for q in op.qargs]) + op_str = " ".join( + [f"rx(pi/2) {str(q)};\nrz(pi/2) {str(q)};" for q in op.qargs], + ) case "Fdg": - op_str = " ".join([f"ry(-pi/2) {str(q)};\nrz(-pi/2) {str(q)};" for q in op.qargs]) + op_str = " ".join( + [f"ry(-pi/2) {str(q)};\nrz(-pi/2) {str(q)};" for q in op.qargs], + ) case "F4": - op_str = " ".join([f"ry(-pi/2) {str(q)};\nrz(pi/2) {str(q)};" for q in op.qargs]) + op_str = " ".join( + [f"ry(-pi/2) {str(q)};\nrz(pi/2) {str(q)};" for q in op.qargs], + ) case "F4dg": - op_str = " ".join([f"rx(-pi/2) {str(q)};\nrz(-pi/2) {str(q)};" for q in op.qargs]) + op_str = " ".join( + [f"rx(-pi/2) {str(q)};\nrz(-pi/2) {str(q)};" for q in op.qargs], + ) case "Prep": op_str = self.qgate_qasm(op, "reset") @@ -316,18 +329,26 @@ def qgate_tq_qasm(self, op, repr_str: str | None = None): return "\n".join(str_list) def process_set(self, op): - right_qasm = op.right.qasm() if hasattr(op.right, "qasm") else self.generate_op(op.right) + right_qasm = ( + op.right.qasm() if hasattr(op.right, "qasm") else self.generate_op(op.right) + ) if right_qasm.startswith("(") and right_qasm.endswith(")"): right_qasm = right_qasm[1:-1] return f"{op.left} = {right_qasm};" def process_general_binary_op(self, op): - left_qasm = op.left.qasm() if hasattr(op.left, "qasm") else self.generate_op(op.left) - right_qasm = op.right.qasm() if hasattr(op.right, "qasm") else self.generate_op(op.right) + left_qasm = ( + op.left.qasm() if hasattr(op.left, "qasm") else self.generate_op(op.left) + ) + right_qasm = ( + op.right.qasm() if hasattr(op.right, "qasm") else self.generate_op(op.right) + ) return f"({left_qasm} {op.symbol} {right_qasm})" def process_general_unary_op(self, op): - right_qasm = op.value.qasm() if hasattr(op.value, "qasm") else self.generate_op(op.vale) + right_qasm = ( + op.value.qasm() if hasattr(op.value, "qasm") else self.generate_op(op.vale) + ) return f"({op.symbol}{right_qasm})" def get_output(self): @@ -350,7 +371,12 @@ def process_permute(op): if set(op.elems_i) != set(op.elems_f): msg = "The set of input elements are not the same as the set of output elements" raise Exception(msg) - if not (len(op.elems_i) == len(set(op.elems_i)) == len(op.elems_f) == len(set(op.elems_f))): + if not ( + len(op.elems_i) + == len(set(op.elems_i)) + == len(op.elems_f) + == len(set(op.elems_f)) + ): msg = "The number of input and output elements are not the same." raise Exception(msg) diff --git a/python/pecos/slr/main.py b/python/quantum-pecos/src/pecos/slr/main.py similarity index 100% rename from python/pecos/slr/main.py rename to python/quantum-pecos/src/pecos/slr/main.py diff --git a/python/pecos/slr/misc.py b/python/quantum-pecos/src/pecos/slr/misc.py similarity index 89% rename from python/pecos/slr/misc.py rename to python/quantum-pecos/src/pecos/slr/misc.py index 912996b3..bab2baf0 100644 --- a/python/pecos/slr/misc.py +++ b/python/quantum-pecos/src/pecos/slr/misc.py @@ -19,7 +19,6 @@ class Barrier(Statement): - def __init__(self, *qregs: QReg | tuple[QReg] | Qubit): self.qregs = qregs @@ -36,7 +35,13 @@ def __init__(self, *txt, space: bool = True, newline: bool = True): class Permute(Statement): """Permutes the indices that the elements of the register so that Reg[i] now refers to Reg[j].""" - def __init__(self, elems_i: list[Elem] | Reg, elems_f: list[Elem] | Reg, *, comment: bool = True): + def __init__( + self, + elems_i: list[Elem] | Reg, + elems_f: list[Elem] | Reg, + *, + comment: bool = True, + ): self.elems_i = elems_i self.elems_f = elems_f self.comment = comment diff --git a/python/pecos/slr/util.py b/python/quantum-pecos/src/pecos/slr/util.py similarity index 100% rename from python/pecos/slr/util.py rename to python/quantum-pecos/src/pecos/slr/util.py diff --git a/python/pecos/slr/vars.py b/python/quantum-pecos/src/pecos/slr/vars.py similarity index 100% rename from python/pecos/slr/vars.py rename to python/quantum-pecos/src/pecos/slr/vars.py diff --git a/python/pecos/tools/__init__.py b/python/quantum-pecos/src/pecos/tools/__init__.py similarity index 100% rename from python/pecos/tools/__init__.py rename to python/quantum-pecos/src/pecos/tools/__init__.py diff --git a/python/pecos/tools/fault_tolerance_checking.py b/python/quantum-pecos/src/pecos/tools/fault_tolerance_checking.py similarity index 90% rename from python/pecos/tools/fault_tolerance_checking.py rename to python/quantum-pecos/src/pecos/tools/fault_tolerance_checking.py index c7288d75..5d4973e3 100644 --- a/python/pecos/tools/fault_tolerance_checking.py +++ b/python/quantum-pecos/src/pecos/tools/fault_tolerance_checking.py @@ -91,11 +91,20 @@ def find_pauli_fault( return failure_circs -def get_all_spacetime(qcirc: QuantumCircuit, initial_qubits: Sequence[int] | None = None): +def get_all_spacetime( + qcirc: QuantumCircuit, + initial_qubits: Sequence[int] | None = None, +): """Determine all the spacetime locations of gates/error events.""" if initial_qubits is not None: for q in initial_qubits: - yield {"tick": -1, "location": (q,), "before": True, "symbol": "init |0>", "metadata": {}} + yield { + "tick": -1, + "location": (q,), + "before": True, + "symbol": "init |0>", + "metadata": {}, + } for gates, tick, _ in qcirc.iter_ticks(): for sym, locations, metadata in gates.items(): @@ -112,7 +121,13 @@ def get_all_spacetime(qcirc: QuantumCircuit, initial_qubits: Sequence[int] | Non } -def get_wt_paulis(circ: QuantumCircuit, wt: int, initial_qubits: Sequence[int] | None = None, *, make_qc: bool = True): +def get_wt_paulis( + circ: QuantumCircuit, + wt: int, + initial_qubits: Sequence[int] | None = None, + *, + make_qc: bool = True, +): """A generator of all combinations of Pauli faults of a given weight. Args: @@ -157,7 +172,13 @@ def get_wt_paulis(circ: QuantumCircuit, wt: int, initial_qubits: Sequence[int] | tick_dict_before = {} cond_dict = {} - for errs, tick, locs, before, cond in zip(pauli_errs, tick_list, loc_list, before_list, cond_list): + for errs, tick, locs, before, cond in zip( + pauli_errs, + tick_list, + loc_list, + before_list, + cond_list, + ): tick_dict = tick_dict_before if before else tick_dict_after gate_dict = tick_dict.setdefault(tick, {}) diff --git a/python/pecos/tools/fault_tolerance_checks.py b/python/quantum-pecos/src/pecos/tools/fault_tolerance_checks.py similarity index 94% rename from python/pecos/tools/fault_tolerance_checks.py rename to python/quantum-pecos/src/pecos/tools/fault_tolerance_checks.py index b0273524..7354836f 100644 --- a/python/pecos/tools/fault_tolerance_checks.py +++ b/python/quantum-pecos/src/pecos/tools/fault_tolerance_checks.py @@ -21,7 +21,7 @@ from pecos.engines.circuit_runners import Standard from pecos.error_models.parent_class_error_gen import ErrorCircuits from pecos.misc.stabilizer_funcs import circ2set, find_stab, op_commutes, remove_stab -from pecos.simulators import pySparseSim +from pecos.simulators import SparseSimPy def powerset(iterable, bound=None): @@ -29,7 +29,9 @@ def powerset(iterable, bound=None): powerlist = list(iterable) if bound is None: bound = len(powerlist) - return it.chain.from_iterable(it.combinations(powerlist, t) for t in range(bound + 1)) + return it.chain.from_iterable( + it.combinations(powerlist, t) for t in range(bound + 1) + ) def t_errors_check( @@ -138,8 +140,8 @@ def t_errors_check( for e, q in zip(error_comb, qubit_comb): error_circ.update(e, {q}) - state_zero = pySparseSim(qecc.num_qudits) - state_plus = pySparseSim(qecc.num_qudits) + state_zero = SparseSimPy(qecc.num_qudits) + state_plus = SparseSimPy(qecc.num_qudits) circ_sim.run(state_zero, initzero) circ_sim.run(state_plus, initplus) @@ -278,8 +280,8 @@ def fault_check( for e, q in zip(error_comb, qubit_comb): error_circ.update(e, {q}) - state_zero = pySparseSim(qecc.num_qudits) - state_plus = pySparseSim(qecc.num_qudits) + state_zero = SparseSimPy(qecc.num_qudits) + state_plus = SparseSimPy(qecc.num_qudits) circ_sim.run(state_zero, initzero) circ_sim.run(state_plus, initplus) @@ -324,7 +326,7 @@ def distance_check(qecc, mode=None, dist_mode=None): qudit_set = qecc.data_qudit_set circ_sim = Standard() - state = pySparseSim(qecc.num_qudits) + state = SparseSimPy(qecc.num_qudits) ideal_initlogic = LogicalCircuit(suppress_warning=True) ideal_initlogic.append(qecc.gate("ideal init |0>")) @@ -364,7 +366,11 @@ def dist_mode_powerset(state, qudit_set): """ for x_errors in powerset(qudit_set): for z_errors in powerset(qudit_set): - if op_commutes(x_errors, z_errors, state.stabs) and not find_stab(state, x_errors, z_errors): + if op_commutes(x_errors, z_errors, state.stabs) and not find_stab( + state, + x_errors, + z_errors, + ): return f"Logical error found: Xs - {x_errors} Zs - {z_errors}" return False @@ -407,7 +413,11 @@ def dist_mode_x(state, qudit_set): """ z_errors = () for x_errors in powerset(qudit_set): - if op_commutes(x_errors, z_errors, state.stabs) and not find_stab(state, x_errors, z_errors): + if op_commutes(x_errors, z_errors, state.stabs) and not find_stab( + state, + x_errors, + z_errors, + ): return f"Logical error found: Xs - {x_errors} Zs - {z_errors}" return False @@ -425,7 +435,11 @@ def dist_mode_z(state, qudit_set): """ x_errors = () for z_errors in powerset(qudit_set): - if op_commutes(x_errors, z_errors, state.stabs) and not find_stab(state, x_errors, z_errors): + if op_commutes(x_errors, z_errors, state.stabs) and not find_stab( + state, + x_errors, + z_errors, + ): return f"Logical error found: Xs - {x_errors} Zs - {z_errors}" return False diff --git a/python/pecos/tools/find_cliffs.py b/python/quantum-pecos/src/pecos/tools/find_cliffs.py similarity index 80% rename from python/pecos/tools/find_cliffs.py rename to python/quantum-pecos/src/pecos/tools/find_cliffs.py index a6108759..015a1405 100644 --- a/python/pecos/tools/find_cliffs.py +++ b/python/quantum-pecos/src/pecos/tools/find_cliffs.py @@ -1,3 +1,14 @@ +# Copyright 2024 The PECOS Developers +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with +# the License.You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. + """Functions to identify Clifford gates.""" from __future__ import annotations @@ -14,11 +25,17 @@ "SX": np.array([[1.0 + 0.0j, 0.0 - 1.0j], [0.0 - 1.0j, 1.0 + 0.0j]], dtype=dtype), "SXdg": np.array([[1.0 + 0.0j, 0.0 + 1.0j], [0.0 + 1.0j, 1.0 + 0.0j]], dtype=dtype), "SY": np.array([[1.0 + 0.0j, -1.0 + 0.0j], [1.0 + 0.0j, 1.0 + 0.0j]], dtype=dtype), - "SYdg": np.array([[1.0 + 0.0j, 1.0 + 0.0j], [-1.0 + 0.0j, 1.0 + 0.0j]], dtype=dtype), + "SYdg": np.array( + [[1.0 + 0.0j, 1.0 + 0.0j], [-1.0 + 0.0j, 1.0 + 0.0j]], + dtype=dtype, + ), "SZ": np.array([[1.0 + 0.0j, 0.0 + 0.0j], [0.0 + 0.0j, 0.0 + 1.0j]], dtype=dtype), "SZdg": np.array([[1.0 + 0.0j, 0.0 + 0.0j], [0.0 + 0.0j, 0.0 - 1.0j]], dtype=dtype), "H": np.array([[1.0 + 0.0j, 1.0 + 0.0j], [1.0 + 0.0j, -1.0 + 0.0j]], dtype=dtype), - "H2": np.array([[1.0 + 0.0j, -1.0 + 0.0j], [-1.0 + 0.0j, -1.0 + 0.0j]], dtype=dtype), + "H2": np.array( + [[1.0 + 0.0j, -1.0 + 0.0j], [-1.0 + 0.0j, -1.0 + 0.0j]], + dtype=dtype, + ), "H3": np.array([[0.0 + 0.0j, 1.0 + 0.0j], [0.0 + 1.0j, 0.0 + 0.0j]], dtype=dtype), "H4": np.array([[0.0 + 0.0j, 1.0 + 0.0j], [0.0 - 1.0j, 0.0 + 0.0j]], dtype=dtype), "H5": np.array([[1.0 + 0.0j, 0.0 - 1.0j], [0.0 + 1.0j, -1.0 + 0.0j]], dtype=dtype), @@ -26,9 +43,15 @@ "F": np.array([[1.0 + 0.0j, 0.0 - 1.0j], [1.0 + 0.0j, 0.0 + 1.0j]], dtype=dtype), "Fdg": np.array([[1.0 + 0.0j, 1.0 + 0.0j], [0.0 + 1.0j, 0.0 - 1.0j]], dtype=dtype), "F2": np.array([[1.0 + 0.0j, -1.0 + 0.0j], [0.0 + 1.0j, 0.0 + 1.0j]], dtype=dtype), - "F2dg": np.array([[1.0 + 0.0j, 0.0 - 1.0j], [-1.0 + 0.0j, 0.0 - 1.0j]], dtype=dtype), + "F2dg": np.array( + [[1.0 + 0.0j, 0.0 - 1.0j], [-1.0 + 0.0j, 0.0 - 1.0j]], + dtype=dtype, + ), "F3": np.array([[1.0 + 0.0j, 0.0 + 1.0j], [-1.0 + 0.0j, 0.0 + 1.0j]], dtype=dtype), - "F3dg": np.array([[1.0 + 0.0j, -1.0 + 0.0j], [0.0 - 1.0j, 0.0 - 1.0j]], dtype=dtype), + "F3dg": np.array( + [[1.0 + 0.0j, -1.0 + 0.0j], [0.0 - 1.0j, 0.0 - 1.0j]], + dtype=dtype, + ), "F4": np.array([[1.0 + 0.0j, 1.0 + 0.0j], [0.0 - 1.0j, 0.0 + 1.0j]], dtype=dtype), "F4dg": np.array([[1.0 + 0.0j, 0.0 + 1.0j], [1.0 + 0.0j, 0.0 - 1.0j]], dtype=dtype), } @@ -117,7 +140,13 @@ def m2cliff(m: np.array, *, atol: float = 1e-12) -> str | bool: return False -def r1xy2cliff(theta: float, phi: float, *, atol: float = 1e-12, use_conv_table: bool = True) -> str | bool: +def r1xy2cliff( + theta: float, + phi: float, + *, + atol: float = 1e-12, + use_conv_table: bool = True, +) -> str | bool: """Identifies (ignoring global phases) a Clifford given the angles of a R1XY gate.""" if use_conv_table: if np.isclose(theta % 2 * np.pi, 0.0, atol=atol): @@ -133,7 +162,12 @@ def r1xy2cliff(theta: float, phi: float, *, atol: float = 1e-12, use_conv_table: return m2cliff(m) -def rz2cliff(theta: float, *, atol: float = 1e-12, use_conv_table: bool = True) -> str | bool: +def rz2cliff( + theta: float, + *, + atol: float = 1e-12, + use_conv_table: bool = True, +) -> str | bool: """Identifies (ignoring global phases) a Clifford given the angles of a RZ gate.""" if use_conv_table: diff --git a/python/pecos/tools/logic_circuit_speed.py b/python/quantum-pecos/src/pecos/tools/logic_circuit_speed.py similarity index 90% rename from python/pecos/tools/logic_circuit_speed.py rename to python/quantum-pecos/src/pecos/tools/logic_circuit_speed.py index 4a9b9935..1e38df4c 100644 --- a/python/pecos/tools/logic_circuit_speed.py +++ b/python/quantum-pecos/src/pecos/tools/logic_circuit_speed.py @@ -15,10 +15,17 @@ from pecos.circuits import QuantumCircuit from pecos.engines.circuit_runners import TimingRunner -from pecos.simulators import pySparseSim +from pecos.simulators import SparseSimPy -def random_circuit_speed(state_sim, num_qubits, circuit_depth, trials=10000, gates=None, seed_start=0): +def random_circuit_speed( + state_sim, + num_qubits, + circuit_depth, + trials=10000, + gates=None, + seed_start=0, +): circuits = generate_circuits(num_qubits, circuit_depth, trials, gates, seed_start) times = [] @@ -26,7 +33,7 @@ def random_circuit_speed(state_sim, num_qubits, circuit_depth, trials=10000, gat circ_sim = TimingRunner() for qc in circuits: - state = pySparseSim(num_qubits) + state = SparseSimPy(num_qubits) meas = circ_sim.run(state, qc) times.append(circ_sim.total_time) measurements.append(meas) @@ -34,7 +41,13 @@ def random_circuit_speed(state_sim, num_qubits, circuit_depth, trials=10000, gat return times, measurements -def generate_circuits(num_qubits, circuit_depth, trials=100000, gates=None, seed_start=0): +def generate_circuits( + num_qubits, + circuit_depth, + trials=100000, + gates=None, + seed_start=0, +): if gates is None: gates = [ "I", diff --git a/python/pecos/tools/pseudo_threshold_tools.py b/python/quantum-pecos/src/pecos/tools/pseudo_threshold_tools.py similarity index 94% rename from python/pecos/tools/pseudo_threshold_tools.py rename to python/quantum-pecos/src/pecos/tools/pseudo_threshold_tools.py index 57f5e0f1..de62304b 100644 --- a/python/pecos/tools/pseudo_threshold_tools.py +++ b/python/quantum-pecos/src/pecos/tools/pseudo_threshold_tools.py @@ -144,7 +144,15 @@ def find_polyfit(ps, plog, deg, verbose=True): return pseudo_thr, popt, pcov -def find_uniscalefit(ps, plog, distance, p0=None, maxfev=1000000, verbose=True, **kwargs): +def find_uniscalefit( + ps, + plog, + distance, + p0=None, + maxfev=1000000, + verbose=True, + **kwargs, +): plist = np.array(ps) dlist = ns2nsfit(distance, len(plist)) @@ -251,7 +259,12 @@ def plot(plist, plog, deg=2, figsize=(10, 10), p_start=None, p_end=None): pseudo_thr = find_pseudo(plist, plog, deg) - popt, _ = np.polyfit(plist, plog, deg, cov=True) # C_z is estimated covariance matrix + popt, _ = np.polyfit( + plist, + plog, + deg, + cov=True, + ) # C_z is estimated covariance matrix axis_start = p_start axis_end = p_end @@ -279,7 +292,13 @@ def plot(plist, plog, deg=2, figsize=(10, 10), p_start=None, p_end=None): plt.ylabel("Logical error rate", size=18) pth = pseudo_thr - plt.axvline(pth, color="green", linewidth=2, linestyle="dashed", label="Pseudo-threshold (%s)" % pth) + plt.axvline( + pth, + color="green", + linewidth=2, + linestyle="dashed", + label="Pseudo-threshold (%s)" % pth, + ) plt.legend(fontsize=16) fg.canvas.draw() diff --git a/python/pecos/tools/random_circuit_speed.py b/python/quantum-pecos/src/pecos/tools/random_circuit_speed.py similarity index 89% rename from python/pecos/tools/random_circuit_speed.py rename to python/quantum-pecos/src/pecos/tools/random_circuit_speed.py index 0abd7bd9..721f8b12 100644 --- a/python/pecos/tools/random_circuit_speed.py +++ b/python/quantum-pecos/src/pecos/tools/random_circuit_speed.py @@ -15,10 +15,18 @@ from pecos.circuits import QuantumCircuit from pecos.engines.circuit_runners import TimingRunner -from pecos.simulators import pySparseSim - - -def random_circuit_speed(state_sim, num_qubits, circuit_depth, trials=10000, gates=None, seed_start=0, converter=None): +from pecos.simulators import SparseSimPy + + +def random_circuit_speed( + state_sim, + num_qubits, + circuit_depth, + trials=10000, + gates=None, + seed_start=0, + converter=None, +): circuits = generate_circuits(num_qubits, circuit_depth, trials, gates, seed_start) times = [] @@ -29,7 +37,7 @@ def random_circuit_speed(state_sim, num_qubits, circuit_depth, trials=10000, gat if converter is not None: qc = converter(qc) - state = pySparseSim(num_qubits) + state = SparseSimPy(num_qubits) circ_sim.reset_time() meas = circ_sim.run(state, qc) times.append(circ_sim.total_time) @@ -38,7 +46,14 @@ def random_circuit_speed(state_sim, num_qubits, circuit_depth, trials=10000, gat return times, measurements, circuits -def generate_circuits(num_qubits, circuit_depth, trials=100000, gates=None, seed_start=0, iterate=False): +def generate_circuits( + num_qubits, + circuit_depth, + trials=100000, + gates=None, + seed_start=0, + iterate=False, +): if gates is None: gates = [ "I", diff --git a/python/pecos/tools/stabilizer_verification.py b/python/quantum-pecos/src/pecos/tools/stabilizer_verification.py similarity index 94% rename from python/pecos/tools/stabilizer_verification.py rename to python/quantum-pecos/src/pecos/tools/stabilizer_verification.py index 3e6bd406..24e8ecbc 100644 --- a/python/pecos/tools/stabilizer_verification.py +++ b/python/quantum-pecos/src/pecos/tools/stabilizer_verification.py @@ -23,7 +23,7 @@ class VerifyStabilizers: """Used to define a stabilizer QECC.""" def __init__(self) -> None: - self.circ_sim = simulators.pySparseSim + self.circ_sim = simulators.SparseSimPy self.checks = [] self.logical_zs = [] @@ -166,7 +166,11 @@ def generators(self, print_y=True, verbose=True): raise Exception(msg) state = self.state - z, x, stab_strings, destab_strings = self.get_info(state, print_y=print_y, verbose=verbose) + z, x, stab_strings, destab_strings = self.get_info( + state, + print_y=print_y, + verbose=verbose, + ) return z, x, stab_strings, destab_strings @@ -314,7 +318,7 @@ def compile(self): # ------------ # Separate the checks, logical stabilizers, and ancilla stabilizers. circuit = self.circuit - state = simulators.pySparseSim(self.num_qubits) + state = simulators.SparseSimPy(self.num_qubits) state.run_circuit(circuit) self.get_info(state, verbose=False) self.state = state @@ -443,7 +447,9 @@ def _verify_checks(self): checks2.append(stab_dict) if checks != checks2: - print("WARNING: PECOS didn't refactor the stabilizers into the checks supplied!") + print( + "WARNING: PECOS didn't refactor the stabilizers into the checks supplied!", + ) return checks != checks2 @@ -543,7 +549,12 @@ def refactor(self, state): zs.add(q) try: - found, stab_id = state.refactor(xs, zs, choose=0, protected=found_stab_ids) + found, stab_id = state.refactor( + xs, + zs, + choose=0, + protected=found_stab_ids, + ) except IndexError: xonly = xs - zs zonly = zs - xs @@ -558,7 +569,12 @@ def refactor(self, state): raise Exception(msg, (ps, qs)) for q in self.ancilla_qubits: - found, stab_id = state.refactor({q}, set(), choose=-1, protected=found_stab_ids) + found, stab_id = state.refactor( + {q}, + set(), + choose=-1, + protected=found_stab_ids, + ) found_stab_ids.add(stab_id) if not found: @@ -593,7 +609,11 @@ def get_info(self, state, stop_search=1000, verbose=True, print_y=False): return Exception("Must run `compile()` first!") self.refactor(state) - stab_strs, destab_strs = state.print_stabs(verbose=False, print_y=print_y, print_destabs=True) + stab_strs, destab_strs = state.print_stabs( + verbose=False, + print_y=print_y, + print_destabs=True, + ) num_ancillas = len(self.ancilla_qubits) @@ -627,7 +647,8 @@ def get_info(self, state, stop_search=1000, verbose=True, print_y=False): notmatched_gens.remove(g) except ValueError: raise Exception( - "list.remove(x): x not in list.\nThe stabilizer %s is likely redundant!" % str(gtuple), + "list.remove(x): x not in list.\nThe stabilizer %s is likely redundant!" + % str(gtuple), ) from ValueError check_gens.append(g) @@ -738,10 +759,14 @@ def distance(self, css=False, verbose=True): xs, zs = found distance = len(xs | zs) - print(f"\nThis is a [[{self.num_data_qubits}, {self.num_logical_qubits()}, {distance}]] code.") + print( + f"\nThis is a [[{self.num_data_qubits}, {self.num_logical_qubits()}, {distance}]] code.", + ) if not found: - print("No logical errors found... Checks might describe a stabilizer state.") + print( + "No logical errors found... Checks might describe a stabilizer state.", + ) return None else: xs, zs = found @@ -913,8 +938,7 @@ def shortest_logicals(self, start_weight=None, delta=0, verbose=True, css=False) qudit_set = self.data_qubits - if end_weight > len(qudit_set): - end_weight = len(qudit_set) + end_weight = min(end_weight, len(qudit_set)) state = self.state found = self._dist_mode_smallest( @@ -945,7 +969,13 @@ def shortest_logicals(self, start_weight=None, delta=0, verbose=True, css=False) op_product = sorted(op_product) - oplist.append({"X": paulis["X"], "Z": paulis["Z"], "equiv_ops": tuple(op_product)}) + oplist.append( + { + "X": paulis["X"], + "Z": paulis["Z"], + "equiv_ops": tuple(op_product), + }, + ) if verbose: print("Reference Logical Operators:") @@ -960,12 +990,22 @@ def shortest_logicals(self, start_weight=None, delta=0, verbose=True, css=False) print("\nLogical Ops Found:\n") for foundop in oplist: - print("X - {} Z - {} Equiv Ops - {}".format(foundop["X"], foundop["Z"], foundop["equiv_ops"])) + print( + "X - {} Z - {} Equiv Ops - {}".format( + foundop["X"], + foundop["Z"], + foundop["equiv_ops"], + ), + ) return oplist, self.logical_xs_reference, self.logical_zs_reference @staticmethod def op_anticommute(op1, op2): return bool( - (len(op1.get("X", set()) & op2.get("Z", set())) + len(op2.get("X", set()) & op1.get("Z", set()))) % 2, + ( + len(op1.get("X", set()) & op2.get("Z", set())) + + len(op2.get("X", set()) & op1.get("Z", set())) + ) + % 2, ) diff --git a/python/pecos/tools/threshold_tools.py b/python/quantum-pecos/src/pecos/tools/threshold_tools.py similarity index 94% rename from python/pecos/tools/threshold_tools.py rename to python/quantum-pecos/src/pecos/tools/threshold_tools.py index 0ab2f3fc..3bbe6b17 100644 --- a/python/pecos/tools/threshold_tools.py +++ b/python/quantum-pecos/src/pecos/tools/threshold_tools.py @@ -22,7 +22,7 @@ from pecos.misc.threshold_curve import func as default_func from pecos.misc.threshold_curve import threshold_fit as default_fit from pecos.qeccs import Surface4444 -from pecos.simulators import pySparseSim +from pecos.simulators import SparseSimPy def threshold_code_capacity( @@ -237,7 +237,13 @@ def threshold_code_capacity_calc( results = threshold_fit(plist, dlist, plog, func, p0) - return {"plist": plist, "dlist": dlist, "plog": plog, "opt": results[0], "std": results[1]} + return { + "plist": plist, + "dlist": dlist, + "plog": plog, + "opt": results[0], + "std": results[1], + } def codecapacity_logical_rate( @@ -315,14 +321,19 @@ def codecapacity_logical_rate( for _ in range(runs): # State - state = pySparseSim(qecc.num_qudits) + state = SparseSimPy(qecc.num_qudits) # Create ideal logical |0> circuit_runner.run(state, initzero) with contextlib.suppress(AttributeError): total_time += circuit_runner.total_time - output, _ = circuit_runner.run(state, syn_extract, error_gen=error_gen, error_params=error_params) + output, _ = circuit_runner.run( + state, + syn_extract, + error_gen=error_gen, + error_params=error_params, + ) with contextlib.suppress(AttributeError): total_time += circuit_runner.total_time @@ -426,7 +437,12 @@ def codecapacity_logical_rate2( with contextlib.suppress(AttributeError): total_time += circuit_runner.total_time - output, error_circuits = circuit_runner.run(state0, syn_extract, error_gen=error_gen, error_params=error_params) + output, error_circuits = circuit_runner.run( + state0, + syn_extract, + error_gen=error_gen, + error_params=error_params, + ) with contextlib.suppress(AttributeError): total_time += circuit_runner.total_time @@ -571,7 +587,12 @@ def codecapacity_logical_rate3( for _duration in range(max_syn_extract): # Run syndrome extraction - output, _ = circuit_runner.run(state, syn_extract, error_gen=error_gen, error_params=error_params) + output, _ = circuit_runner.run( + state, + syn_extract, + error_gen=error_gen, + error_params=error_params, + ) with contextlib.suppress(AttributeError): total_time += circuit_runner.total_time @@ -592,7 +613,9 @@ def codecapacity_logical_rate3( else: raise Exception("Max syndrome extraction (%s) met." % max_syn_extract) - run_durations.append(max_syn_extract) # duration + 1 == number of syndrome extractions. + run_durations.append( + max_syn_extract, + ) # duration + 1 == number of syndrome extractions. if verbose: print("\nTotal number of runs: %s" % sum(run_durations)) diff --git a/python/pecos/tools/tool_anticommute.py b/python/quantum-pecos/src/pecos/tools/tool_anticommute.py similarity index 100% rename from python/pecos/tools/tool_anticommute.py rename to python/quantum-pecos/src/pecos/tools/tool_anticommute.py diff --git a/python/pecos/tools/tool_collection.py b/python/quantum-pecos/src/pecos/tools/tool_collection.py similarity index 83% rename from python/pecos/tools/tool_collection.py rename to python/quantum-pecos/src/pecos/tools/tool_collection.py index 13df730a..86b1cc08 100644 --- a/python/pecos/tools/tool_collection.py +++ b/python/quantum-pecos/src/pecos/tools/tool_collection.py @@ -20,7 +20,7 @@ from pecos import circuits from pecos.circuits import QuantumCircuit from pecos.engines.circuit_runners import Standard -from pecos.simulators import pySparseSim +from pecos.simulators import SparseSimPy def fault_tolerance_check(qecc, decoder): @@ -62,14 +62,30 @@ def fault_tolerance_check(qecc, decoder): # Check input errors for xs, zs in gen_pauli_errors(data_qudits, max_errors=t): err = QuantumCircuit([{"X": xs, "Z": zs}]) - state = pySparseSim(num_qudits) - - sign = _apply_err(state, circ_runner, init_zero, syn_extract, err, decoder, logical_z) + state = SparseSimPy(num_qudits) + + sign = _apply_err( + state, + circ_runner, + init_zero, + syn_extract, + err, + decoder, + logical_z, + ) if sign: raise Exception("Decoder failed to correct error: %s" % err) - sign = _apply_err(state, circ_runner, init_zero, syn_extract, err, decoder, logical_z) + sign = _apply_err( + state, + circ_runner, + init_zero, + syn_extract, + err, + decoder, + logical_z, + ) if sign: raise Exception("Decoder failed to correct error: %s" % err) @@ -81,18 +97,34 @@ def fault_tolerance_check(qecc, decoder): spacetime = set(product(list(range(num_ticks)), qudits)) for xs, zs in gen_pauli_errors(spacetime, max_errors=t): - state = pySparseSim(num_qudits) + state = SparseSimPy(num_qudits) xs = list(xs) zs = list(zs) err_dict = form_errors(xs, zs) - sign = _apply_err_spacetime(state, circ_runner, init_zero, err_dict, decoder, logical_z, qecc) + sign = _apply_err_spacetime( + state, + circ_runner, + init_zero, + err_dict, + decoder, + logical_z, + qecc, + ) if sign: raise Exception("Decoder failed to correct error: %s" % str(spacetime)) - sign = _apply_err_spacetime(state, circ_runner, init_zero, err_dict, decoder, logical_z, qecc) + sign = _apply_err_spacetime( + state, + circ_runner, + init_zero, + err_dict, + decoder, + logical_z, + qecc, + ) if sign: raise Exception("Decoder failed to correct error: %s" % str(spacetime)) @@ -111,7 +143,15 @@ def form_errors(xs, zs): return errors -def _apply_err_spacetime(state, circ_runner, init_circ, err_dict, decoder, logical_op, qecc): +def _apply_err_spacetime( + state, + circ_runner, + init_circ, + err_dict, + decoder, + logical_op, + qecc, +): circ_runner.run(state, init_circ) syn_circ = qecc.instruction("instr_syn_extract", num_syn_extract=1) @@ -162,7 +202,13 @@ def _apply_err(state, circ_runner, init_circ, syn_circ, error, decoder, logical_ return state.logical_sign(logical_op) -def gen_pauli_errors(qubits, *, min_errors: int = 1, max_errors: bool | int = False, css: bool = False): +def gen_pauli_errors( + qubits, + *, + min_errors: int = 1, + max_errors: bool | int = False, + css: bool = False, +): """Args: ---- qubits: diff --git a/python/pecos/typed_list.py b/python/quantum-pecos/src/pecos/typed_list.py similarity index 86% rename from python/pecos/typed_list.py rename to python/quantum-pecos/src/pecos/typed_list.py index 8ed13311..61e348c2 100644 --- a/python/pecos/typed_list.py +++ b/python/quantum-pecos/src/pecos/typed_list.py @@ -1,3 +1,14 @@ +# Copyright 2024 The PECOS Developers +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with +# the License.You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. + from __future__ import annotations from collections.abc import Iterable diff --git a/python/tests/LICENSE b/python/tests/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/python/tests/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/python/tests/NOTICE b/python/tests/NOTICE new file mode 120000 index 00000000..fb376cfa --- /dev/null +++ b/python/tests/NOTICE @@ -0,0 +1 @@ +../../NOTICE \ No newline at end of file diff --git a/tests/end2end/__init__.py b/python/tests/pecos/end2end/__init__.py similarity index 100% rename from tests/end2end/__init__.py rename to python/tests/pecos/end2end/__init__.py diff --git a/tests/integration/example_tests/test_basic_logical_sim.py b/python/tests/pecos/integration/example_tests/test_basic_logical_sim.py similarity index 88% rename from tests/integration/example_tests/test_basic_logical_sim.py rename to python/tests/pecos/integration/example_tests/test_basic_logical_sim.py index 8c74dbf1..51e3fb65 100644 --- a/tests/integration/example_tests/test_basic_logical_sim.py +++ b/python/tests/pecos/integration/example_tests/test_basic_logical_sim.py @@ -37,11 +37,16 @@ def test_surface(): sim = pc.circuit_runners.Standard() - state = pc.simulators.pySparseSim(surface.num_qudits) + state = pc.simulators.SparseSimPy(surface.num_qudits) output1, error_circuits1 = sim.run(state, logic) - output2, error_circuits2 = sim.run(state, logic2, error_gen=depolar, error_params={"p": 0.2}) + output2, error_circuits2 = sim.run( + state, + logic2, + error_gen=depolar, + error_params={"p": 0.2}, + ) # syn = output2.simplified(True) diff --git a/tests/integration/example_tests/test_finding_threshold.py b/python/tests/pecos/integration/example_tests/test_finding_threshold.py similarity index 93% rename from tests/integration/example_tests/test_finding_threshold.py rename to python/tests/pecos/integration/example_tests/test_finding_threshold.py index f2dc7e27..ad3d57a9 100644 --- a/tests/integration/example_tests/test_finding_threshold.py +++ b/python/tests/pecos/integration/example_tests/test_finding_threshold.py @@ -16,7 +16,10 @@ def test_finding_threshold(): - depolar = pc.error_models.DepolarModel(model_level="code_capacity", perp_errors=True) + depolar = pc.error_models.DepolarModel( + model_level="code_capacity", + perp_errors=True, + ) ps = [0.19, 0.17, 0.15, 0.13, 0.11] ds = [5, 7, 9] plist = np.array(ps * len(ds)) diff --git a/tests/integration/example_tests/test_recovery.py b/python/tests/pecos/integration/example_tests/test_recovery.py similarity index 90% rename from tests/integration/example_tests/test_recovery.py rename to python/tests/pecos/integration/example_tests/test_recovery.py index 77d52720..1036f52a 100644 --- a/tests/integration/example_tests/test_recovery.py +++ b/python/tests/pecos/integration/example_tests/test_recovery.py @@ -57,12 +57,12 @@ def recovery_tester(qecc): # Run circuits # ------------ - state_zero = pc.simulators.pySparseSim(qecc.num_qudits) + state_zero = pc.simulators.SparseSimPy(qecc.num_qudits) output_zero, _ = sim.run(state_zero, initzero) assert not output_zero - state_plus = pc.simulators.pySparseSim(qecc.num_qudits) + state_plus = pc.simulators.SparseSimPy(qecc.num_qudits) output_plus, _ = sim.run(state_plus, initplus) assert not output_plus @@ -75,8 +75,17 @@ def recovery_tester(qecc): assert output1 == output2 assert not output1 - output1, error_circuits1 = sim.run(state_zero, syn_ext, error_gen=depolar, error_params={"p": 0.3}) - output2, error_circuits2 = sim.run(state_plus, syn_ext, error_circuits=error_circuits1) + output1, error_circuits1 = sim.run( + state_zero, + syn_ext, + error_gen=depolar, + error_params={"p": 0.3}, + ) + output2, error_circuits2 = sim.run( + state_plus, + syn_ext, + error_circuits=error_circuits1, + ) assert error_circuits1 == error_circuits2 assert output1 == output2 diff --git a/tests/integration/phir/bad_phir.json b/python/tests/pecos/integration/phir/bad_phir.json similarity index 100% rename from tests/integration/phir/bad_phir.json rename to python/tests/pecos/integration/phir/bad_phir.json diff --git a/tests/integration/phir/bell_qparallel.json b/python/tests/pecos/integration/phir/bell_qparallel.json similarity index 100% rename from tests/integration/phir/bell_qparallel.json rename to python/tests/pecos/integration/phir/bell_qparallel.json diff --git a/tests/integration/phir/bell_qparallel_cliff.json b/python/tests/pecos/integration/phir/bell_qparallel_cliff.json similarity index 100% rename from tests/integration/phir/bell_qparallel_cliff.json rename to python/tests/pecos/integration/phir/bell_qparallel_cliff.json diff --git a/tests/integration/phir/bell_qparallel_cliff_barrier.json b/python/tests/pecos/integration/phir/bell_qparallel_cliff_barrier.json similarity index 100% rename from tests/integration/phir/bell_qparallel_cliff_barrier.json rename to python/tests/pecos/integration/phir/bell_qparallel_cliff_barrier.json diff --git a/tests/integration/phir/bell_qparallel_cliff_ifbarrier.json b/python/tests/pecos/integration/phir/bell_qparallel_cliff_ifbarrier.json similarity index 100% rename from tests/integration/phir/bell_qparallel_cliff_ifbarrier.json rename to python/tests/pecos/integration/phir/bell_qparallel_cliff_ifbarrier.json diff --git a/tests/integration/phir/classical_00_11.json b/python/tests/pecos/integration/phir/classical_00_11.json similarity index 100% rename from tests/integration/phir/classical_00_11.json rename to python/tests/pecos/integration/phir/classical_00_11.json diff --git a/tests/integration/phir/example1.json b/python/tests/pecos/integration/phir/example1.json similarity index 100% rename from tests/integration/phir/example1.json rename to python/tests/pecos/integration/phir/example1.json diff --git a/tests/integration/phir/example1_no_wasm.json b/python/tests/pecos/integration/phir/example1_no_wasm.json similarity index 100% rename from tests/integration/phir/example1_no_wasm.json rename to python/tests/pecos/integration/phir/example1_no_wasm.json diff --git a/tests/integration/phir/qparallel.json b/python/tests/pecos/integration/phir/qparallel.json similarity index 100% rename from tests/integration/phir/qparallel.json rename to python/tests/pecos/integration/phir/qparallel.json diff --git a/tests/integration/phir/recording_random_meas.json b/python/tests/pecos/integration/phir/recording_random_meas.json similarity index 100% rename from tests/integration/phir/recording_random_meas.json rename to python/tests/pecos/integration/phir/recording_random_meas.json diff --git a/tests/integration/phir/spec_example.json b/python/tests/pecos/integration/phir/spec_example.json similarity index 100% rename from tests/integration/phir/spec_example.json rename to python/tests/pecos/integration/phir/spec_example.json diff --git a/tests/integration/state_sim_tests/test_cointoss.py b/python/tests/pecos/integration/state_sim_tests/test_cointoss.py similarity index 72% rename from tests/integration/state_sim_tests/test_cointoss.py rename to python/tests/pecos/integration/state_sim_tests/test_cointoss.py index 0708d4a4..50e2d661 100644 --- a/tests/integration/state_sim_tests/test_cointoss.py +++ b/python/tests/pecos/integration/state_sim_tests/test_cointoss.py @@ -70,6 +70,35 @@ def test_all_gate_circ(): qc.append({"SWAP": {(4, 0)}}) qc.append({"Tdg": {3, 1}}) qc.append({"RXX": {(1, 3)}}, angles=(np.pi / 4,)) + qc.append({"Q": {1, 4, 2}}) + qc.append({"Qd": {0, 3}}) + qc.append({"R": {0}}) + qc.append({"Rd": {1, 4, 2}}) + qc.append({"S": {0, 3}}) + qc.append({"Sd": {0}}) + qc.append({"H1": {0, 3}}) + qc.append({"H2": {2, 3}}) + qc.append({"H3": {1, 4, 2}}) + qc.append({"H4": {2, 3}}) + qc.append({"H5": {0, 3}}) + qc.append({"H6": {1, 4, 2}}) + qc.append({"H+z+x": {2, 3}}) + qc.append({"H-z-x": {1, 4, 2}}) + qc.append({"H+y-z": {0, 3}}) + qc.append({"H-y-z": {2, 3}}) + qc.append({"H-x+y": {0, 3}}) + qc.append({"H-x-y": {1, 4, 2}}) + qc.append({"F1": {0, 3}}) + qc.append({"F1d": {2, 3}}) + qc.append({"F2": {1, 4, 2}}) + qc.append({"F2d": {0, 3}}) + qc.append({"F3": {2, 3}}) + qc.append({"F3d": {1, 4, 2}}) + qc.append({"F4": {2, 3}}) + qc.append({"F4d": {0, 3}}) + qc.append({"CNOT": {(0, 1)}}) + qc.append({"G": {(1, 3)}}) + qc.append({"II": {(4, 2)}}) # Measure qc.append({"Measure": {0, 1, 2, 3, 4}}) diff --git a/tests/integration/state_sim_tests/test_gate_init.py b/python/tests/pecos/integration/state_sim_tests/test_stab_sims/test_gate_init.py similarity index 93% rename from tests/integration/state_sim_tests/test_gate_init.py rename to python/tests/pecos/integration/state_sim_tests/test_stab_sims/test_gate_init.py index 309df5bb..35b039e0 100644 --- a/tests/integration/state_sim_tests/test_gate_init.py +++ b/python/tests/pecos/integration/state_sim_tests/test_stab_sims/test_gate_init.py @@ -9,9 +9,12 @@ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the # specific language governing permissions and limitations under the License. -from pecos.simulators import pySparseSim +from pecos.simulators import SparseSimPy, SparseSimRs -states = [pySparseSim] +states = [ + SparseSimPy, + SparseSimRs, +] def test_init_zero(): @@ -110,7 +113,7 @@ def test_init_plus_i(): Test initializing |+i>. stab: +Y - destab: X + destab: X | Z :return: """ @@ -125,7 +128,7 @@ def test_init_plus_i(): # Test destabilizers destab_rep = state.destabs.print_tableau(verbose=False) - assert destab_rep == [" X"] + assert destab_rep in [[" X"], [" Z"]] def test_init_minus_i(): @@ -133,7 +136,7 @@ def test_init_minus_i(): Test initializing |+i>. stab: -Y - destab: Z + destab: X | Z :return: """ @@ -148,4 +151,4 @@ def test_init_minus_i(): # Test destabilizers destab_rep = state.destabs.print_tableau(verbose=False) - assert destab_rep == [" X"] + assert destab_rep in [[" X"], [" Z"]] diff --git a/tests/integration/state_sim_tests/test_gate_one_qubit.py b/python/tests/pecos/integration/state_sim_tests/test_stab_sims/test_gate_one_qubit.py similarity index 98% rename from tests/integration/state_sim_tests/test_gate_one_qubit.py rename to python/tests/pecos/integration/state_sim_tests/test_stab_sims/test_gate_one_qubit.py index 216967f4..1f67a49b 100644 --- a/tests/integration/state_sim_tests/test_gate_one_qubit.py +++ b/python/tests/pecos/integration/state_sim_tests/test_stab_sims/test_gate_one_qubit.py @@ -13,9 +13,12 @@ Test all one-qubit gates. """ -from pecos.simulators import pySparseSim +from pecos.simulators import SparseSimPy, SparseSimRs -states = [pySparseSim] +states = [ + SparseSimPy, + SparseSimRs, +] def gate_test(gate_symbol, stab_dict): diff --git a/tests/integration/state_sim_tests/test_gate_two_qubit.py b/python/tests/pecos/integration/state_sim_tests/test_stab_sims/test_gate_two_qubit.py similarity index 98% rename from tests/integration/state_sim_tests/test_gate_two_qubit.py rename to python/tests/pecos/integration/state_sim_tests/test_stab_sims/test_gate_two_qubit.py index 56ee96ee..38ea6468 100644 --- a/tests/integration/state_sim_tests/test_gate_two_qubit.py +++ b/python/tests/pecos/integration/state_sim_tests/test_stab_sims/test_gate_two_qubit.py @@ -13,9 +13,12 @@ Test all one-qubit gates. """ -from pecos.simulators import pySparseSim +from pecos.simulators import SparseSimPy, SparseSimRs -states = [pySparseSim] +states = [ + SparseSimPy, + SparseSimRs, +] def gate_test(gate_symbol, stab_dict): diff --git a/tests/integration/state_sim_tests/test_statevec.py b/python/tests/pecos/integration/state_sim_tests/test_statevec.py similarity index 78% rename from tests/integration/state_sim_tests/test_statevec.py rename to python/tests/pecos/integration/state_sim_tests/test_statevec.py index f4a58aad..6e4d0888 100644 --- a/tests/integration/state_sim_tests/test_statevec.py +++ b/python/tests/pecos/integration/state_sim_tests/test_statevec.py @@ -56,7 +56,11 @@ def verify(simulator, qc: QuantumCircuit, final_vector: np.ndarray) -> None: assert np.allclose(sim.vector, final_vector) -def check_measurement(simulator, qc: QuantumCircuit, final_results: dict[int, int] | None = None) -> None: +def check_measurement( + simulator, + qc: QuantumCircuit, + final_results: dict[int, int] | None = None, +) -> None: sim = check_dependencies(simulator)(len(qc.qudits)) results = sim.run_circuit(qc) @@ -225,7 +229,6 @@ def test_comp_basis_circ_and_measure(simulator): ], ) def test_all_gate_circ(simulator): - # Generate three different arbitrary states qcs: list[QuantumCircuit] = [] qcs.append(generate_random_state(seed=1234)) @@ -304,6 +307,64 @@ def test_all_gate_circ(simulator): compare_against_basicsv(simulator, qc) qc.append({"RXX": {(1, 3)}}, angles=(np.pi / 4,)) compare_against_basicsv(simulator, qc) + qc.append({"Q": {1, 4, 2}}) + compare_against_basicsv(simulator, qc) + qc.append({"Qd": {0, 3}}) + compare_against_basicsv(simulator, qc) + qc.append({"R": {0}}) + compare_against_basicsv(simulator, qc) + qc.append({"Rd": {1, 4, 2}}) + compare_against_basicsv(simulator, qc) + qc.append({"S": {0, 3}}) + compare_against_basicsv(simulator, qc) + qc.append({"Sd": {0}}) + compare_against_basicsv(simulator, qc) + qc.append({"H1": {0, 3}}) + compare_against_basicsv(simulator, qc) + qc.append({"H2": {2, 3}}) + compare_against_basicsv(simulator, qc) + qc.append({"H3": {1, 4, 2}}) + compare_against_basicsv(simulator, qc) + qc.append({"H4": {2, 3}}) + compare_against_basicsv(simulator, qc) + qc.append({"H5": {0, 3}}) + compare_against_basicsv(simulator, qc) + qc.append({"H6": {1, 4, 2}}) + compare_against_basicsv(simulator, qc) + qc.append({"H+z+x": {2, 3}}) + compare_against_basicsv(simulator, qc) + qc.append({"H-z-x": {1, 4, 2}}) + compare_against_basicsv(simulator, qc) + qc.append({"H+y-z": {0, 3}}) + compare_against_basicsv(simulator, qc) + qc.append({"H-y-z": {2, 3}}) + compare_against_basicsv(simulator, qc) + qc.append({"H-x+y": {0, 3}}) + compare_against_basicsv(simulator, qc) + qc.append({"H-x-y": {1, 4, 2}}) + compare_against_basicsv(simulator, qc) + qc.append({"F1": {0, 3}}) + compare_against_basicsv(simulator, qc) + qc.append({"F1d": {2, 3}}) + compare_against_basicsv(simulator, qc) + qc.append({"F2": {1, 4, 2}}) + compare_against_basicsv(simulator, qc) + qc.append({"F2d": {0, 3}}) + compare_against_basicsv(simulator, qc) + qc.append({"F3": {2, 3}}) + compare_against_basicsv(simulator, qc) + qc.append({"F3d": {1, 4, 2}}) + compare_against_basicsv(simulator, qc) + qc.append({"F4": {2, 3}}) + compare_against_basicsv(simulator, qc) + qc.append({"F4d": {0, 3}}) + compare_against_basicsv(simulator, qc) + qc.append({"CNOT": {(0, 1)}}) + compare_against_basicsv(simulator, qc) + qc.append({"G": {(1, 3)}}) + compare_against_basicsv(simulator, qc) + qc.append({"II": {(4, 2)}}) + compare_against_basicsv(simulator, qc) # Measure qc.append({"Measure": {0, 1, 2, 3, 4}}) diff --git a/tests/integration/test_phir.py b/python/tests/pecos/integration/test_phir.py similarity index 90% rename from tests/integration/test_phir.py rename to python/tests/pecos/integration/test_phir.py index 6f826e76..cbd8bc10 100644 --- a/tests/integration/test_phir.py +++ b/python/tests/pecos/integration/test_phir.py @@ -13,7 +13,9 @@ from pathlib import Path import pytest -from pecos.classical_interpreters.phir_classical_interpreter import PHIRClassicalInterpreter +from pecos.classical_interpreters.phir_classical_interpreter import ( + PHIRClassicalInterpreter, +) from pecos.engines.hybrid_engine import HybridEngine from pecos.error_models.generic_error_model import GenericErrorModel from phir.model import PHIRModel @@ -54,8 +56,8 @@ def is_wasmer_supported(): return WASMER_ERR_MSG != "Wasmer is not available on this system" -@pytest.mark.wasmtime() -@pytest.mark.optional_dependency() +@pytest.mark.wasmtime +@pytest.mark.optional_dependency def test_spec_example_wasmtime(): """A random example showing that various basic aspects of PHIR is runnable by PECOS.""" @@ -67,8 +69,8 @@ def test_spec_example_wasmtime(): ) -@pytest.mark.wasmtime() -@pytest.mark.optional_dependency() +@pytest.mark.wasmtime +@pytest.mark.optional_dependency def test_spec_example_noisy_wasmtime(): """A random example showing that various basic aspects of PHIR is runnable by PECOS, with noise.""" @@ -95,8 +97,8 @@ def test_spec_example_noisy_wasmtime(): ) -@pytest.mark.wasmtime() -@pytest.mark.optional_dependency() +@pytest.mark.wasmtime +@pytest.mark.optional_dependency def test_example1_wasmtime(): """A random example showing that various basic aspects of PHIR is runnable by PECOS.""" @@ -108,8 +110,8 @@ def test_example1_wasmtime(): ) -@pytest.mark.wasmtime() -@pytest.mark.optional_dependency() +@pytest.mark.wasmtime +@pytest.mark.optional_dependency def test_example1_noisy_wasmtime(): """A random example showing that various basic aspects of PHIR is runnable by PECOS, with noise.""" @@ -136,9 +138,12 @@ def test_example1_noisy_wasmtime(): ) -@pytest.mark.skipif(not is_wasmer_supported(), reason="Wasmer is not support on some OS/Python version combinations.") -@pytest.mark.wasmer() -@pytest.mark.optional_dependency() +@pytest.mark.skipif( + not is_wasmer_supported(), + reason="Wasmer is not support on some OS/Python version combinations.", +) +@pytest.mark.wasmer +@pytest.mark.optional_dependency def test_example1_wasmer(): """A random example showing that various basic aspects of PHIR is runnable by PECOS.""" @@ -150,9 +155,12 @@ def test_example1_wasmer(): ) -@pytest.mark.skipif(not is_wasmer_supported(), reason="Wasmer is not support on some OS/Python version combinations.") -@pytest.mark.wasmer() -@pytest.mark.optional_dependency() +@pytest.mark.skipif( + not is_wasmer_supported(), + reason="Wasmer is not support on some OS/Python version combinations.", +) +@pytest.mark.wasmer +@pytest.mark.optional_dependency def test_example1_noisy_wasmer(): """A random example showing that various basic aspects of PHIR is runnable by PECOS, with noise.""" @@ -260,7 +268,7 @@ def test_qparallel(): assert m.count("1111") == len(m) -@pytest.mark.optional_dependency() # uses projectq / state-vector +@pytest.mark.optional_dependency # uses projectq / state-vector def test_bell_qparallel(): """Testing a program creating and measuring a Bell state and using qparallel blocks returns expected results.""" @@ -293,7 +301,9 @@ def test_bell_qparallel_cliff_barrier(): interp = PHIRClassicalInterpreter() results = HybridEngine(qsim="stabilizer", cinterp=interp).run( - program=json.load(Path.open(this_dir / "phir" / "bell_qparallel_cliff_barrier.json")), + program=json.load( + Path.open(this_dir / "phir" / "bell_qparallel_cliff_barrier.json"), + ), shots=20, ) @@ -308,7 +318,9 @@ def test_bell_qparallel_cliff_ifbarrier(): interp = PHIRClassicalInterpreter() results = HybridEngine(qsim="stabilizer", cinterp=interp).run( - program=json.load(Path.open(this_dir / "phir" / "bell_qparallel_cliff_ifbarrier.json")), + program=json.load( + Path.open(this_dir / "phir" / "bell_qparallel_cliff_ifbarrier.json"), + ), shots=20, ) diff --git a/tests/integration/test_phir_64_bit.py b/python/tests/pecos/integration/test_phir_64_bit.py similarity index 80% rename from tests/integration/test_phir_64_bit.py rename to python/tests/pecos/integration/test_phir_64_bit.py index 66ea4929..dc4cf481 100644 --- a/tests/integration/test_phir_64_bit.py +++ b/python/tests/pecos/integration/test_phir_64_bit.py @@ -11,9 +11,19 @@ def test_setting_cvar(): "version": "0.1.0", "ops": [ {"data": "cvar_define", "data_type": "i32", "variable": "var_i32"}, - {"data": "cvar_define", "data_type": "u32", "variable": "var_u32", "size": 32}, + { + "data": "cvar_define", + "data_type": "u32", + "variable": "var_u32", + "size": 32, + }, {"data": "cvar_define", "data_type": "i64", "variable": "var_i64"}, - {"data": "cvar_define", "data_type": "u64", "variable": "var_u64", "size": 64}, + { + "data": "cvar_define", + "data_type": "u64", + "variable": "var_u64", + "size": 64, + }, {"data": "cvar_define", "data_type": "i32", "variable": "var_i32neg"}, {"data": "cvar_define", "data_type": "i64", "variable": "var_i64neg"}, {"cop": "=", "returns": ["var_i32"], "args": [2**31 - 1]}, diff --git a/tests/integration/test_phir_dep.py b/python/tests/pecos/integration/test_phir_dep.py similarity index 100% rename from tests/integration/test_phir_dep.py rename to python/tests/pecos/integration/test_phir_dep.py diff --git a/tests/integration/test_phir_setting_cregs.py b/python/tests/pecos/integration/test_phir_setting_cregs.py similarity index 100% rename from tests/integration/test_phir_setting_cregs.py rename to python/tests/pecos/integration/test_phir_setting_cregs.py diff --git a/tests/integration/test_quantum_circuits.py b/python/tests/pecos/integration/test_quantum_circuits.py similarity index 100% rename from tests/integration/test_quantum_circuits.py rename to python/tests/pecos/integration/test_quantum_circuits.py diff --git a/tests/integration/test_random_circuits.py b/python/tests/pecos/integration/test_random_circuits.py similarity index 83% rename from tests/integration/test_random_circuits.py rename to python/tests/pecos/integration/test_random_circuits.py index 4b8081a4..70504a56 100644 --- a/tests/integration/test_random_circuits.py +++ b/python/tests/pecos/integration/test_random_circuits.py @@ -1,3 +1,4 @@ +# Copyright 2024 The PECOS Developers # Copyright 2018 National Technology & Engineering Solutions of Sandia, LLC (NTESS). Under the terms of Contract # DE-NA0003525 with NTESS, the U.S. Government retains certain rights in this software. # @@ -13,7 +14,7 @@ from __future__ import annotations import numpy as np -from pecos.simulators import SparseSim as StateSparse +from pecos.simulators import SparseSimPy, SparseSimRs def test_random_circuits(): @@ -54,7 +55,8 @@ def test_random_circuits(): except ImportError: pass - state_sims.append(StateSparse) + state_sims.append(SparseSimPy) + state_sims.append(SparseSimRs) assert run_circuit_test(state_sims, num_qubits=10, circuit_depth=50) @@ -114,22 +116,38 @@ def generate_circuit( return circuit -def run_a_circuit(num_qubits: int, state_rep, circuit, verbose: bool = False): # noqa: FBT001 +def run_a_circuit( + num_qubits: int, + state_rep, + circuit, + *, + verbose: bool = False, +): state = state_rep(num_qubits) measurements = [] - gate_dict = state.bindings + + if isinstance(state, SparseSimRs): + state.bindings["measure Z"] = state.bindings["MZForced"] + state.bindings["init |0>"] = state.bindings["PZForced"] for element, q in circuit: m = -1 if element == "measure Z": - m = gate_dict[element](state, q, forced_outcome=0) + m = state.run_gate(element, {q}, forced_outcome=0) + m = m.get(q, 0) measurements.append(m) + elif element == "init |0>": + if isinstance(q, np.ndarray): + q = tuple(q) + + state.run_gate(element, {q}, forced_outcome=0) + else: if isinstance(q, np.ndarray): q = tuple(q) - gate_dict[element](state, q) + state.run_gate(element, {q}) if verbose: print("\ngate", element, q, "->") diff --git a/tests/integration/wat/add.wat b/python/tests/pecos/integration/wat/add.wat similarity index 100% rename from tests/integration/wat/add.wat rename to python/tests/pecos/integration/wat/add.wat diff --git a/tests/integration/wat/add_noinit.wat b/python/tests/pecos/integration/wat/add_noinit.wat similarity index 100% rename from tests/integration/wat/add_noinit.wat rename to python/tests/pecos/integration/wat/add_noinit.wat diff --git a/tests/integration/wat/math.wat b/python/tests/pecos/integration/wat/math.wat similarity index 100% rename from tests/integration/wat/math.wat rename to python/tests/pecos/integration/wat/math.wat diff --git a/tests/regression/test_qasm/conftest.py b/python/tests/pecos/regression/test_qasm/conftest.py similarity index 59% rename from tests/regression/test_qasm/conftest.py rename to python/tests/pecos/regression/test_qasm/conftest.py index 7a227d4c..60e6d62f 100644 --- a/tests/regression/test_qasm/conftest.py +++ b/python/tests/pecos/regression/test_qasm/conftest.py @@ -5,10 +5,14 @@ import pytest -@pytest.fixture() +@pytest.fixture def compare_qasm(): - def _compare_qasm(block, *params, directory: Path | None = None, filename: str | None = None): - + def _compare_qasm( + block, + *params, + directory: Path | None = None, + filename: str | None = None, + ): if directory is None: directory = Path(__file__).parent @@ -28,10 +32,17 @@ def _compare_qasm(block, *params, directory: Path | None = None, filename: str | qasm1 = qasm1.strip() - if hasattr(block, "gen"): + # TODO: Fix this... this is kinda hacky + if ( + hasattr(block, "qargs") + and hasattr(block, "params") + and hasattr(block, "sym") + ): qasm2 = block.gen("qasm").strip() + elif hasattr(block, "gen"): + qasm2 = block.gen("qasm", add_versions=False).strip() else: - qasm2 = block.qasm().strip() + qasm2 = block.qasm(add_versions=False).strip() assert qasm1 == qasm2 diff --git a/tests/regression/test_qasm/examples/test_logical_steane_code_program.py b/python/tests/pecos/regression/test_qasm/examples/test_logical_steane_code_program.py similarity index 89% rename from tests/regression/test_qasm/examples/test_logical_steane_code_program.py rename to python/tests/pecos/regression/test_qasm/examples/test_logical_steane_code_program.py index c7254fb8..545a5cf8 100644 --- a/tests/regression/test_qasm/examples/test_logical_steane_code_program.py +++ b/python/tests/pecos/regression/test_qasm/examples/test_logical_steane_code_program.py @@ -36,11 +36,15 @@ def telep(prep_basis: str, meas_basis: str) -> Main: def test_telep(compare_qasm): - for prep_basis in ["-X", "+X", "+Y", "-Y", "+Z", "-Z"]: for meas_basis in ["X", "Y", "Z"]: prog = telep(prep_basis, meas_basis) - compare_qasm(prog, prep_basis, meas_basis, filename="local_steane_code_program.telep") + compare_qasm( + prog, + prep_basis, + meas_basis, + filename="local_steane_code_program.telep", + ) def t_gate(prep_basis: str, meas_basis: str) -> Main: @@ -88,4 +92,9 @@ def test_t_gate(compare_qasm): for prep_basis in ["-X", "+X", "+Y", "-Y", "+Z", "-Z"]: for meas_basis in ["X", "Y", "Z"]: prog = t_gate(prep_basis, meas_basis) - compare_qasm(prog, prep_basis, meas_basis, filename="local_steane_code_program.t_gate") + compare_qasm( + prog, + prep_basis, + meas_basis, + filename="local_steane_code_program.t_gate", + ) diff --git a/tests/regression/test_qasm/pecos/qeclib/qubit/test_measures.py b/python/tests/pecos/regression/test_qasm/pecos/qeclib/qubit/test_measures.py similarity index 100% rename from tests/regression/test_qasm/pecos/qeclib/qubit/test_measures.py rename to python/tests/pecos/regression/test_qasm/pecos/qeclib/qubit/test_measures.py diff --git a/tests/regression/test_qasm/pecos/qeclib/qubit/test_preps.py b/python/tests/pecos/regression/test_qasm/pecos/qeclib/qubit/test_preps.py similarity index 100% rename from tests/regression/test_qasm/pecos/qeclib/qubit/test_preps.py rename to python/tests/pecos/regression/test_qasm/pecos/qeclib/qubit/test_preps.py diff --git a/tests/regression/test_qasm/pecos/qeclib/qubit/test_rots.py b/python/tests/pecos/regression/test_qasm/pecos/qeclib/qubit/test_rots.py similarity index 100% rename from tests/regression/test_qasm/pecos/qeclib/qubit/test_rots.py rename to python/tests/pecos/regression/test_qasm/pecos/qeclib/qubit/test_rots.py diff --git a/tests/regression/test_qasm/pecos/qeclib/qubit/test_sq_face_rots.py b/python/tests/pecos/regression/test_qasm/pecos/qeclib/qubit/test_sq_face_rots.py similarity index 100% rename from tests/regression/test_qasm/pecos/qeclib/qubit/test_sq_face_rots.py rename to python/tests/pecos/regression/test_qasm/pecos/qeclib/qubit/test_sq_face_rots.py diff --git a/tests/regression/test_qasm/pecos/qeclib/qubit/test_sq_hadamards.py b/python/tests/pecos/regression/test_qasm/pecos/qeclib/qubit/test_sq_hadamards.py similarity index 100% rename from tests/regression/test_qasm/pecos/qeclib/qubit/test_sq_hadamards.py rename to python/tests/pecos/regression/test_qasm/pecos/qeclib/qubit/test_sq_hadamards.py diff --git a/tests/regression/test_qasm/pecos/qeclib/qubit/test_sq_noncliffords.py b/python/tests/pecos/regression/test_qasm/pecos/qeclib/qubit/test_sq_noncliffords.py similarity index 100% rename from tests/regression/test_qasm/pecos/qeclib/qubit/test_sq_noncliffords.py rename to python/tests/pecos/regression/test_qasm/pecos/qeclib/qubit/test_sq_noncliffords.py diff --git a/tests/regression/test_qasm/pecos/qeclib/qubit/test_sq_paulis.py b/python/tests/pecos/regression/test_qasm/pecos/qeclib/qubit/test_sq_paulis.py similarity index 100% rename from tests/regression/test_qasm/pecos/qeclib/qubit/test_sq_paulis.py rename to python/tests/pecos/regression/test_qasm/pecos/qeclib/qubit/test_sq_paulis.py diff --git a/tests/regression/test_qasm/pecos/qeclib/qubit/test_sq_sqrt_paulis.py b/python/tests/pecos/regression/test_qasm/pecos/qeclib/qubit/test_sq_sqrt_paulis.py similarity index 100% rename from tests/regression/test_qasm/pecos/qeclib/qubit/test_sq_sqrt_paulis.py rename to python/tests/pecos/regression/test_qasm/pecos/qeclib/qubit/test_sq_sqrt_paulis.py diff --git a/tests/regression/test_qasm/pecos/qeclib/qubit/test_tq_cliffords.py b/python/tests/pecos/regression/test_qasm/pecos/qeclib/qubit/test_tq_cliffords.py similarity index 100% rename from tests/regression/test_qasm/pecos/qeclib/qubit/test_tq_cliffords.py rename to python/tests/pecos/regression/test_qasm/pecos/qeclib/qubit/test_tq_cliffords.py diff --git a/tests/regression/test_qasm/pecos/qeclib/qubit/test_tq_noncliffords.py b/python/tests/pecos/regression/test_qasm/pecos/qeclib/qubit/test_tq_noncliffords.py similarity index 100% rename from tests/regression/test_qasm/pecos/qeclib/qubit/test_tq_noncliffords.py rename to python/tests/pecos/regression/test_qasm/pecos/qeclib/qubit/test_tq_noncliffords.py diff --git a/tests/regression/test_qasm/pecos/qeclib/steane/decoders/test_lookup.py b/python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/decoders/test_lookup.py similarity index 67% rename from tests/regression/test_qasm/pecos/qeclib/steane/decoders/test_lookup.py rename to python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/decoders/test_lookup.py index 08cc668a..d24fd80c 100644 --- a/tests/regression/test_qasm/pecos/qeclib/steane/decoders/test_lookup.py +++ b/python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/decoders/test_lookup.py @@ -16,7 +16,16 @@ def test_FlagLookupQASM(compare_qasm): scratch = CReg("scratch_test", 32) for basis in ["X", "Y", "Z"]: - block = FlagLookupQASM(basis, syn, syndromes, raw_syn, pf[0], flag, flags, scratch) + block = FlagLookupQASM( + basis, + syn, + syndromes, + raw_syn, + pf[0], + flag, + flags, + scratch, + ) compare_qasm(block, basis) @@ -32,7 +41,17 @@ def test_FlagLookupQASMActiveCorrectionX(compare_qasm): pf_copy = CReg("pf_copy_test", 1) for pf_bit_copy in [None, pf_copy]: - block = FlagLookupQASMActiveCorrectionX(q, syn, syndromes, raw_syn, pf[0], flag, flags, scratch, pf_bit_copy) + block = FlagLookupQASMActiveCorrectionX( + q, + syn, + syndromes, + raw_syn, + pf[0], + flag, + flags, + scratch, + pf_bit_copy, + ) compare_qasm(block, pf_bit_copy) @@ -48,5 +67,15 @@ def test_FlagLookupQASMActiveCorrectionZ(compare_qasm): pf_copy = CReg("pf_copy_test", 1) for pf_bit_copy in [None, pf_copy]: - block = FlagLookupQASMActiveCorrectionZ(q, syn, syndromes, raw_syn, pf[0], flag, flags, scratch, pf_bit_copy) + block = FlagLookupQASMActiveCorrectionZ( + q, + syn, + syndromes, + raw_syn, + pf[0], + flag, + flags, + scratch, + pf_bit_copy, + ) compare_qasm(block, pf_bit_copy) diff --git a/tests/regression/test_qasm/pecos/qeclib/steane/gates_sq/test_face_rots.py b/python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/gates_sq/test_face_rots.py similarity index 100% rename from tests/regression/test_qasm/pecos/qeclib/steane/gates_sq/test_face_rots.py rename to python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/gates_sq/test_face_rots.py diff --git a/tests/regression/test_qasm/pecos/qeclib/steane/gates_sq/test_hadamards.py b/python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/gates_sq/test_hadamards.py similarity index 100% rename from tests/regression/test_qasm/pecos/qeclib/steane/gates_sq/test_hadamards.py rename to python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/gates_sq/test_hadamards.py diff --git a/tests/regression/test_qasm/pecos/qeclib/steane/gates_sq/test_paulis.py b/python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/gates_sq/test_paulis.py similarity index 100% rename from tests/regression/test_qasm/pecos/qeclib/steane/gates_sq/test_paulis.py rename to python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/gates_sq/test_paulis.py diff --git a/tests/regression/test_qasm/pecos/qeclib/steane/gates_sq/test_sqrt_paulis.py b/python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/gates_sq/test_sqrt_paulis.py similarity index 100% rename from tests/regression/test_qasm/pecos/qeclib/steane/gates_sq/test_sqrt_paulis.py rename to python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/gates_sq/test_sqrt_paulis.py diff --git a/tests/regression/test_qasm/pecos/qeclib/steane/gates_tq/test_transversal_tq.py b/python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/gates_tq/test_transversal_tq.py similarity index 100% rename from tests/regression/test_qasm/pecos/qeclib/steane/gates_tq/test_transversal_tq.py rename to python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/gates_tq/test_transversal_tq.py diff --git a/tests/regression/test_qasm/pecos/qeclib/steane/meas/test_destructive_meas.py b/python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/meas/test_destructive_meas.py similarity index 85% rename from tests/regression/test_qasm/pecos/qeclib/steane/meas/test_destructive_meas.py rename to python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/meas/test_destructive_meas.py index 6234d439..b474a99d 100644 --- a/tests/regression/test_qasm/pecos/qeclib/steane/meas/test_destructive_meas.py +++ b/python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/meas/test_destructive_meas.py @@ -1,4 +1,11 @@ -from pecos.qeclib.steane.meas.destructive_meas import MeasDecode, Measure, MeasureX, MeasureY, MeasureZ, ProcessMeas +from pecos.qeclib.steane.meas.destructive_meas import ( + MeasDecode, + Measure, + MeasureX, + MeasureY, + MeasureZ, + ProcessMeas, +) from pecos.slr import CReg, QReg @@ -79,5 +86,16 @@ def test_MeasDecode(compare_qasm): last_raw_syn_z = CReg("last_raw_syn_z_test", 3) for meas_basis in ["X", "Y", "Z"]: - block = MeasDecode(q, meas_basis, meas, log[0], log[1], syn_meas, pf[0], pf[1], last_raw_syn_x, last_raw_syn_z) + block = MeasDecode( + q, + meas_basis, + meas, + log[0], + log[1], + syn_meas, + pf[0], + pf[1], + last_raw_syn_x, + last_raw_syn_z, + ) compare_qasm(block, meas_basis) diff --git a/tests/regression/test_qasm/pecos/qeclib/steane/meas/test_measure_x.py b/python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/meas/test_measure_x.py similarity index 100% rename from tests/regression/test_qasm/pecos/qeclib/steane/meas/test_measure_x.py rename to python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/meas/test_measure_x.py diff --git a/tests/regression/test_qasm/pecos/qeclib/steane/meas/test_measure_z.py b/python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/meas/test_measure_z.py similarity index 100% rename from tests/regression/test_qasm/pecos/qeclib/steane/meas/test_measure_z.py rename to python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/meas/test_measure_z.py diff --git a/tests/regression/test_qasm/pecos/qeclib/steane/preps/test_encoding_circ.py b/python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/preps/test_encoding_circ.py similarity index 100% rename from tests/regression/test_qasm/pecos/qeclib/steane/preps/test_encoding_circ.py rename to python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/preps/test_encoding_circ.py diff --git a/tests/regression/test_qasm/pecos/qeclib/steane/preps/test_pauli_states.py b/python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/preps/test_pauli_states.py similarity index 85% rename from tests/regression/test_qasm/pecos/qeclib/steane/preps/test_pauli_states.py rename to python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/preps/test_pauli_states.py index 32be8a01..5ec32253 100644 --- a/tests/regression/test_qasm/pecos/qeclib/steane/preps/test_pauli_states.py +++ b/python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/preps/test_pauli_states.py @@ -41,7 +41,14 @@ def test_PrepRUS(compare_qasm): for limit in [1, 2, 3]: for state in ["-Z", "+Z", "+X", "-X", "+Y", "-Y"]: for first_round_reset in [True, False]: - block = PrepRUS(q, a[0], init[0], limit, state, first_round_reset=first_round_reset) + block = PrepRUS( + q, + a[0], + init[0], + limit, + state, + first_round_reset=first_round_reset, + ) compare_qasm(block, limit, state, first_round_reset) diff --git a/tests/regression/test_qasm/pecos/qeclib/steane/preps/test_plus_h_state.py b/python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/preps/test_plus_h_state.py similarity index 72% rename from tests/regression/test_qasm/pecos/qeclib/steane/preps/test_plus_h_state.py rename to python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/preps/test_plus_h_state.py index 295d7314..63a3605f 100644 --- a/tests/regression/test_qasm/pecos/qeclib/steane/preps/test_plus_h_state.py +++ b/python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/preps/test_plus_h_state.py @@ -12,5 +12,15 @@ def test_PrepHStateFT(compare_qasm): flags = CReg("flags_test", 3) last_raw_syn_x = CReg("last_raw_syn_x_test", 3) last_raw_syn_z = CReg("last_raw_syn_z_test", 3) - block = PrepHStateFT(q, a, out, reject[0], flag_x, flag_z, flags, last_raw_syn_x, last_raw_syn_z) + block = PrepHStateFT( + q, + a, + out, + reject[0], + flag_x, + flag_z, + flags, + last_raw_syn_x, + last_raw_syn_z, + ) compare_qasm(block) diff --git a/tests/regression/test_qasm/pecos/qeclib/steane/preps/test_t_plus_state.py b/python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/preps/test_t_plus_state.py similarity index 74% rename from tests/regression/test_qasm/pecos/qeclib/steane/preps/test_t_plus_state.py rename to python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/preps/test_t_plus_state.py index 211ad67c..c72defeb 100644 --- a/tests/regression/test_qasm/pecos/qeclib/steane/preps/test_t_plus_state.py +++ b/python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/preps/test_t_plus_state.py @@ -29,7 +29,17 @@ def test_PrepEncodeTPlusFT(compare_qasm): flags = CReg("flags_test", 3) last_raw_syn_x = CReg("last_raw_syn_x_test", 3) last_raw_syn_z = CReg("last_raw_syn_z_test", 3) - block = PrepEncodeTPlusFT(q, a, out, reject[0], flag_x, flag_z, flags, last_raw_syn_x, last_raw_syn_z) + block = PrepEncodeTPlusFT( + q, + a, + out, + reject[0], + flag_x, + flag_z, + flags, + last_raw_syn_x, + last_raw_syn_z, + ) compare_qasm(block) @@ -45,5 +55,16 @@ def test_PrepEncodeTPlusFTRUS(compare_qasm): last_raw_syn_z = CReg("last_raw_syn_z_test", 3) for limit in [1, 2, 3]: - block = PrepEncodeTPlusFTRUS(q, a, out, reject[0], flag_x, flag_z, flags, last_raw_syn_x, last_raw_syn_z, limit) + block = PrepEncodeTPlusFTRUS( + q, + a, + out, + reject[0], + flag_x, + flag_z, + flags, + last_raw_syn_x, + last_raw_syn_z, + limit, + ) compare_qasm(block, limit) diff --git a/tests/regression/test_qasm/pecos/qeclib/steane/qec/test_qec_3parallel.py b/python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/qec/test_qec_3parallel.py similarity index 100% rename from tests/regression/test_qasm/pecos/qeclib/steane/qec/test_qec_3parallel.py rename to python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/qec/test_qec_3parallel.py diff --git a/tests/regression/test_qasm/pecos/qeclib/steane/syn_extract/test_six_check_nonflagging.py b/python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/syn_extract/test_six_check_nonflagging.py similarity index 100% rename from tests/regression/test_qasm/pecos/qeclib/steane/syn_extract/test_six_check_nonflagging.py rename to python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/syn_extract/test_six_check_nonflagging.py diff --git a/tests/regression/test_qasm/pecos/qeclib/steane/syn_extract/test_three_parallel_flagging.py b/python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/syn_extract/test_three_parallel_flagging.py similarity index 66% rename from tests/regression/test_qasm/pecos/qeclib/steane/syn_extract/test_three_parallel_flagging.py rename to python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/syn_extract/test_three_parallel_flagging.py index c4ebdc50..b7b0bd24 100644 --- a/tests/regression/test_qasm/pecos/qeclib/steane/syn_extract/test_three_parallel_flagging.py +++ b/python/tests/pecos/regression/test_qasm/pecos/qeclib/steane/syn_extract/test_three_parallel_flagging.py @@ -1,4 +1,7 @@ -from pecos.qeclib.steane.syn_extract.three_parallel_flagging import ThreeParallelFlaggingXZZ, ThreeParallelFlaggingZXX +from pecos.qeclib.steane.syn_extract.three_parallel_flagging import ( + ThreeParallelFlaggingXZZ, + ThreeParallelFlaggingZXX, +) from pecos.slr import CReg, QReg @@ -11,7 +14,15 @@ def test_ThreeParallelFlaggingXZZ(compare_qasm): last_raw_syn_x = CReg("last_raw_syn_x_test", 3) last_raw_syn_z = CReg("last_raw_syn_z_test", 3) - block = ThreeParallelFlaggingXZZ(q, a, flag_x, flag_z, flags, last_raw_syn_x, last_raw_syn_z) + block = ThreeParallelFlaggingXZZ( + q, + a, + flag_x, + flag_z, + flags, + last_raw_syn_x, + last_raw_syn_z, + ) compare_qasm(block) @@ -24,5 +35,13 @@ def test_ThreeParallelFlaggingZXX(compare_qasm): last_raw_syn_x = CReg("last_raw_syn_x_test", 3) last_raw_syn_z = CReg("last_raw_syn_z_test", 3) - block = ThreeParallelFlaggingZXX(q, a, flag_x, flag_z, flags, last_raw_syn_x, last_raw_syn_z) + block = ThreeParallelFlaggingZXX( + q, + a, + flag_x, + flag_z, + flags, + last_raw_syn_x, + last_raw_syn_z, + ) compare_qasm(block) diff --git a/tests/regression/test_qasm/random_cases/test_control_flow.py b/python/tests/pecos/regression/test_qasm/random_cases/test_control_flow.py similarity index 100% rename from tests/regression/test_qasm/random_cases/test_control_flow.py rename to python/tests/pecos/regression/test_qasm/random_cases/test_control_flow.py diff --git a/tests/regression/test_qasm/random_cases/test_slr_phys.py b/python/tests/pecos/regression/test_qasm/random_cases/test_slr_phys.py similarity index 99% rename from tests/regression/test_qasm/random_cases/test_slr_phys.py rename to python/tests/pecos/regression/test_qasm/random_cases/test_slr_phys.py index 17372cdc..023b9c07 100644 --- a/tests/regression/test_qasm/random_cases/test_slr_phys.py +++ b/python/tests/pecos/regression/test_qasm/random_cases/test_slr_phys.py @@ -34,7 +34,6 @@ def test_if_bell(): """Test that a more complex Bell prep and measure circuit with if statemenscan be created.""" class Bell(Block): - def __init__(self, q0: Qubit, q1: Qubit, m0: Bit, m1: Bit): super().__init__() self.extend( diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+X_X.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+X_X.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+X_X.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+X_X.qasm index c687719f..ac8487e0 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+X_X.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+X_X.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_reject[2]; creg m_t[1]; creg m_out[2]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+X_Y.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+X_Y.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+X_Y.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+X_Y.qasm index a51beeb3..f8a8927f 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+X_Y.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+X_Y.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_reject[2]; creg m_t[1]; creg m_out[2]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+X_Z.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+X_Z.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+X_Z.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+X_Z.qasm index ce1adab7..40482101 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+X_Z.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+X_Z.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_reject[2]; creg m_t[1]; creg m_out[2]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Y_X.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Y_X.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Y_X.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Y_X.qasm index a5cb62c0..45c4c7da 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Y_X.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Y_X.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_reject[2]; creg m_t[1]; creg m_out[2]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Y_Y.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Y_Y.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Y_Y.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Y_Y.qasm index 45c3e6e4..9f91952b 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Y_Y.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Y_Y.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_reject[2]; creg m_t[1]; creg m_out[2]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Y_Z.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Y_Z.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Y_Z.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Y_Z.qasm index 44d474fa..6fee7c8c 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Y_Z.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Y_Z.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_reject[2]; creg m_t[1]; creg m_out[2]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Z_X.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Z_X.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Z_X.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Z_X.qasm index 01ff662d..9199c2e4 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Z_X.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Z_X.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_reject[2]; creg m_t[1]; creg m_out[2]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Z_Y.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Z_Y.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Z_Y.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Z_Y.qasm index 2b4ea03a..344f98e9 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Z_Y.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Z_Y.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_reject[2]; creg m_t[1]; creg m_out[2]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Z_Z.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Z_Z.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Z_Z.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Z_Z.qasm index 95d9175e..80ffb22d 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Z_Z.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_+Z_Z.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_reject[2]; creg m_t[1]; creg m_out[2]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-X_X.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-X_X.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-X_X.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-X_X.qasm index 1a4c7d6d..2d660958 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-X_X.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-X_X.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_reject[2]; creg m_t[1]; creg m_out[2]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-X_Y.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-X_Y.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-X_Y.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-X_Y.qasm index 78efe56e..516e40d2 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-X_Y.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-X_Y.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_reject[2]; creg m_t[1]; creg m_out[2]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-X_Z.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-X_Z.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-X_Z.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-X_Z.qasm index 0acf1edb..345f67c2 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-X_Z.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-X_Z.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_reject[2]; creg m_t[1]; creg m_out[2]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Y_X.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Y_X.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Y_X.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Y_X.qasm index 670077e1..d116f18a 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Y_X.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Y_X.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_reject[2]; creg m_t[1]; creg m_out[2]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Y_Y.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Y_Y.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Y_Y.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Y_Y.qasm index 2e6e3a23..6cda639b 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Y_Y.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Y_Y.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_reject[2]; creg m_t[1]; creg m_out[2]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Y_Z.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Y_Z.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Y_Z.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Y_Z.qasm index 79ab54f7..03100d20 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Y_Z.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Y_Z.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_reject[2]; creg m_t[1]; creg m_out[2]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Z_X.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Z_X.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Z_X.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Z_X.qasm index b5dd8613..97dec00e 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Z_X.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Z_X.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_reject[2]; creg m_t[1]; creg m_out[2]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Z_Y.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Z_Y.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Z_Y.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Z_Y.qasm index cf43d3e8..23abdb1d 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Z_Y.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Z_Y.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_reject[2]; creg m_t[1]; creg m_out[2]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Z_Z.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Z_Z.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Z_Z.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Z_Z.qasm index 9dbc6206..6e70b17a 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Z_Z.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.t_gate_-Z_Z.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_reject[2]; creg m_t[1]; creg m_out[2]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+X_X.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+X_X.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+X_X.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+X_X.qasm index 1d8faf8c..a630dbd0 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+X_X.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+X_X.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_bell[2]; creg m_out[1]; qreg sin_d[7]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+X_Y.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+X_Y.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+X_Y.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+X_Y.qasm index 20585369..535b72b4 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+X_Y.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+X_Y.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_bell[2]; creg m_out[1]; qreg sin_d[7]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+X_Z.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+X_Z.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+X_Z.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+X_Z.qasm index 685a6d7e..268bd4bd 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+X_Z.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+X_Z.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_bell[2]; creg m_out[1]; qreg sin_d[7]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Y_X.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Y_X.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Y_X.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Y_X.qasm index 1737222c..b28faee7 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Y_X.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Y_X.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_bell[2]; creg m_out[1]; qreg sin_d[7]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Y_Y.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Y_Y.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Y_Y.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Y_Y.qasm index d287472f..3b7331e4 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Y_Y.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Y_Y.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_bell[2]; creg m_out[1]; qreg sin_d[7]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Y_Z.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Y_Z.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Y_Z.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Y_Z.qasm index 1e6dbb88..beaf79c4 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Y_Z.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Y_Z.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_bell[2]; creg m_out[1]; qreg sin_d[7]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Z_X.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Z_X.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Z_X.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Z_X.qasm index 65e3440b..5c85469f 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Z_X.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Z_X.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_bell[2]; creg m_out[1]; qreg sin_d[7]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Z_Y.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Z_Y.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Z_Y.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Z_Y.qasm index fac84a8a..bc705a55 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Z_Y.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Z_Y.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_bell[2]; creg m_out[1]; qreg sin_d[7]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Z_Z.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Z_Z.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Z_Z.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Z_Z.qasm index 5eff70b6..d78db533 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Z_Z.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_+Z_Z.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_bell[2]; creg m_out[1]; qreg sin_d[7]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-X_X.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-X_X.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-X_X.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-X_X.qasm index 50f0637b..626c598f 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-X_X.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-X_X.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_bell[2]; creg m_out[1]; qreg sin_d[7]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-X_Y.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-X_Y.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-X_Y.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-X_Y.qasm index 68de1758..e944ab63 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-X_Y.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-X_Y.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_bell[2]; creg m_out[1]; qreg sin_d[7]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-X_Z.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-X_Z.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-X_Z.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-X_Z.qasm index 225f8164..035fb738 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-X_Z.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-X_Z.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_bell[2]; creg m_out[1]; qreg sin_d[7]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Y_X.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Y_X.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Y_X.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Y_X.qasm index 54827d3a..b3b0ee97 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Y_X.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Y_X.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_bell[2]; creg m_out[1]; qreg sin_d[7]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Y_Y.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Y_Y.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Y_Y.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Y_Y.qasm index 687d1631..ebff4202 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Y_Y.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Y_Y.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_bell[2]; creg m_out[1]; qreg sin_d[7]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Y_Z.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Y_Z.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Y_Z.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Y_Z.qasm index 95f3c355..bcfa7342 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Y_Z.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Y_Z.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_bell[2]; creg m_out[1]; qreg sin_d[7]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Z_X.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Z_X.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Z_X.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Z_X.qasm index 4b6242ab..73ea09a2 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Z_X.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Z_X.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_bell[2]; creg m_out[1]; qreg sin_d[7]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Z_Y.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Z_Y.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Z_Y.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Z_Y.qasm index c004b744..21764db0 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Z_Y.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Z_Y.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_bell[2]; creg m_out[1]; qreg sin_d[7]; diff --git a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Z_Z.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Z_Z.qasm similarity index 99% rename from tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Z_Z.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Z_Z.qasm index e2a5299d..d143801b 100644 --- a/tests/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Z_Z.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/local_steane_code_program.telep_-Z_Z.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 creg m_bell[2]; creg m_out[1]; qreg sin_d[7]; diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.measures.Measure.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.measures.Measure.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.measures.Measure.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.measures.Measure.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.preps.Prep.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.preps.Prep.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.preps.Prep.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.preps.Prep.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.rots.RXGate.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.rots.RXGate.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.rots.RXGate.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.rots.RXGate.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.rots.RYGate.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.rots.RYGate.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.rots.RYGate.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.rots.RYGate.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.rots.RZGate.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.rots.RZGate.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.rots.RZGate.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.rots.RZGate.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.rots.RZZGate.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.rots.RZZGate.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.rots.RZZGate.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.rots.RZZGate.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_face_rots.F.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_face_rots.F.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_face_rots.F.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_face_rots.F.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_face_rots.F4.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_face_rots.F4.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_face_rots.F4.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_face_rots.F4.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_face_rots.F4dg.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_face_rots.F4dg.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_face_rots.F4dg.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_face_rots.F4dg.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_face_rots.Fdg.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_face_rots.Fdg.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_face_rots.Fdg.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_face_rots.Fdg.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_hadamards.H.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_hadamards.H.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_hadamards.H.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_hadamards.H.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_noncliffords.T.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_noncliffords.T.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_noncliffords.T.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_noncliffords.T.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_noncliffords.Tdg.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_noncliffords.Tdg.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_noncliffords.Tdg.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_noncliffords.Tdg.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_paulis.X.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_paulis.X.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_paulis.X.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_paulis.X.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_paulis.Y.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_paulis.Y.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_paulis.Y.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_paulis.Y.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_paulis.Z.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_paulis.Z.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_paulis.Z.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_paulis.Z.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_sqrt_paulis.SX.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_sqrt_paulis.SX.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_sqrt_paulis.SX.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_sqrt_paulis.SX.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_sqrt_paulis.SXdg.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_sqrt_paulis.SXdg.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_sqrt_paulis.SXdg.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_sqrt_paulis.SXdg.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_sqrt_paulis.SY.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_sqrt_paulis.SY.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_sqrt_paulis.SY.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_sqrt_paulis.SY.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_sqrt_paulis.SYdg.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_sqrt_paulis.SYdg.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_sqrt_paulis.SYdg.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_sqrt_paulis.SYdg.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_sqrt_paulis.SZ.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_sqrt_paulis.SZ.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_sqrt_paulis.SZ.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_sqrt_paulis.SZ.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_sqrt_paulis.SZdg.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_sqrt_paulis.SZdg.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_sqrt_paulis.SZdg.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.sq_sqrt_paulis.SZdg.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.CX.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.CX.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.CX.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.CX.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.CY.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.CY.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.CY.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.CY.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.CZ.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.CZ.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.CZ.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.CZ.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.SXX.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.SXX.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.SXX.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.SXX.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.SXXdg.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.SXXdg.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.SXXdg.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.SXXdg.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.SYY.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.SYY.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.SYY.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.SYY.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.SYYdg.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.SYYdg.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.SYYdg.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.SYYdg.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.SZZ.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.SZZ.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.SZZ.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.SZZ.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.SZZdg.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.SZZdg.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.SZZdg.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_cliffords.SZZdg.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_noncliffords.CH.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_noncliffords.CH.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_noncliffords.CH.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.qubit.tq_noncliffords.CH.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASMActiveCorrectionX_None.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASMActiveCorrectionX_None.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASMActiveCorrectionX_None.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASMActiveCorrectionX_None.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASMActiveCorrectionX_pf_copy_test.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASMActiveCorrectionX_pf_copy_test.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASMActiveCorrectionX_pf_copy_test.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASMActiveCorrectionX_pf_copy_test.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASMActiveCorrectionZ_None.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASMActiveCorrectionZ_None.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASMActiveCorrectionZ_None.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASMActiveCorrectionZ_None.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASMActiveCorrectionZ_pf_copy_test.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASMActiveCorrectionZ_pf_copy_test.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASMActiveCorrectionZ_pf_copy_test.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASMActiveCorrectionZ_pf_copy_test.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASM_X.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASM_X.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASM_X.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASM_X.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASM_Y.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASM_Y.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASM_Y.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASM_Y.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASM_Z.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASM_Z.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASM_Z.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.decoders.lookup.FlagLookupQASM_Z.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.face_rots.F.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.face_rots.F.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.face_rots.F.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.face_rots.F.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.face_rots.Fdg.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.face_rots.Fdg.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.face_rots.Fdg.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.face_rots.Fdg.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.hadamards.H.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.hadamards.H.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.hadamards.H.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.hadamards.H.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.paulis.X.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.paulis.X.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.paulis.X.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.paulis.X.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.paulis.Y.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.paulis.Y.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.paulis.Y.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.paulis.Y.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.paulis.Z.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.paulis.Z.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.paulis.Z.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.paulis.Z.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.sqrt_paulis.SX.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.sqrt_paulis.SX.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.sqrt_paulis.SX.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.sqrt_paulis.SX.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.sqrt_paulis.SXdg.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.sqrt_paulis.SXdg.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.sqrt_paulis.SXdg.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.sqrt_paulis.SXdg.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.sqrt_paulis.SY.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.sqrt_paulis.SY.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.sqrt_paulis.SY.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.sqrt_paulis.SY.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.sqrt_paulis.SYdg.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.sqrt_paulis.SYdg.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.sqrt_paulis.SYdg.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.sqrt_paulis.SYdg.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.sqrt_paulis.SZ.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.sqrt_paulis.SZ.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.sqrt_paulis.SZ.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.sqrt_paulis.SZ.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.sqrt_paulis.SZdg.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.sqrt_paulis.SZdg.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.sqrt_paulis.SZdg.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_sq.sqrt_paulis.SZdg.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_tq.transversal_tq.CX_False.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_tq.transversal_tq.CX_False.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_tq.transversal_tq.CX_False.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_tq.transversal_tq.CX_False.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_tq.transversal_tq.CX_True.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_tq.transversal_tq.CX_True.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_tq.transversal_tq.CX_True.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_tq.transversal_tq.CX_True.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_tq.transversal_tq.CY.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_tq.transversal_tq.CY.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_tq.transversal_tq.CY.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_tq.transversal_tq.CY.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_tq.transversal_tq.CZ.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_tq.transversal_tq.CZ.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_tq.transversal_tq.CZ.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_tq.transversal_tq.CZ.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_tq.transversal_tq.SZZ.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_tq.transversal_tq.SZZ.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_tq.transversal_tq.SZZ.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.gates_tq.transversal_tq.SZZ.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.MeasureX_False.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.MeasureX_False.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.MeasureX_False.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.MeasureX_False.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.MeasureX_True.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.MeasureX_True.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.MeasureX_True.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.MeasureX_True.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.MeasureY_False.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.MeasureY_False.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.MeasureY_False.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.MeasureY_False.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.MeasureY_True.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.MeasureY_True.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.MeasureY_True.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.MeasureY_True.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.MeasureZ_False.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.MeasureZ_False.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.MeasureZ_False.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.MeasureZ_False.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.MeasureZ_True.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.MeasureZ_True.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.MeasureZ_True.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.MeasureZ_True.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.Measure_X.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.Measure_X.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.Measure_X.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.Measure_X.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.Measure_Y.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.Measure_Y.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.Measure_Y.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.Measure_Y.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.Measure_Z.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.Measure_Z.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.Measure_Z.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.Measure_Z.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_X_xy.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_X_xy.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_X_xy.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_X_xy.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_X_xz.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_X_xz.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_X_xz.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_X_xz.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_X_yz.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_X_yz.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_X_yz.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_X_yz.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_Y_xy.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_Y_xy.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_Y_xy.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_Y_xy.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_Y_xz.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_Y_xz.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_Y_xz.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_Y_xz.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_Y_yz.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_Y_yz.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_Y_yz.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_Y_yz.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_Z_xy.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_Z_xy.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_Z_xy.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_Z_xy.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_Z_xz.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_Z_xz.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_Z_xz.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_Z_xz.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_Z_yz.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_Z_yz.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_Z_yz.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.destructive_meas.ProcessMeas_Z_yz.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.measure_x.NoFlagMeasureX.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.measure_x.NoFlagMeasureX.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.measure_x.NoFlagMeasureX.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.measure_x.NoFlagMeasureX.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.measure_z.NoFlagMeasureZ.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.measure_z.NoFlagMeasureZ.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.measure_z.NoFlagMeasureZ.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.meas.measure_z.NoFlagMeasureZ.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.encoding_circ.EncodingCircuit.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.encoding_circ.EncodingCircuit.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.encoding_circ.EncodingCircuit.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.encoding_circ.EncodingCircuit.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.encoding_circ.EncodingCircuit2.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.encoding_circ.EncodingCircuit2.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.encoding_circ.EncodingCircuit2.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.encoding_circ.EncodingCircuit2.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.LogZeroRot_+X.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.LogZeroRot_+X.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.LogZeroRot_+X.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.LogZeroRot_+X.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.LogZeroRot_+Y.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.LogZeroRot_+Y.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.LogZeroRot_+Y.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.LogZeroRot_+Y.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.LogZeroRot_+Z.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.LogZeroRot_+Z.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.LogZeroRot_+Z.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.LogZeroRot_+Z.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.LogZeroRot_-X.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.LogZeroRot_-X.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.LogZeroRot_-X.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.LogZeroRot_-X.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.LogZeroRot_-Y.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.LogZeroRot_-Y.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.LogZeroRot_-Y.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.LogZeroRot_-Y.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.LogZeroRot_-Z.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.LogZeroRot_-Z.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.LogZeroRot_-Z.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.LogZeroRot_-Z.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepEncodingFTZero_False.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepEncodingFTZero_False.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepEncodingFTZero_False.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepEncodingFTZero_False.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepEncodingFTZero_True.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepEncodingFTZero_True.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepEncodingFTZero_True.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepEncodingFTZero_True.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepEncodingNonFTZero.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepEncodingNonFTZero.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepEncodingNonFTZero.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepEncodingNonFTZero.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_+X_False.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_+X_False.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_+X_False.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_+X_False.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_+X_True.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_+X_True.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_+X_True.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_+X_True.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_+Y_False.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_+Y_False.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_+Y_False.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_+Y_False.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_+Y_True.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_+Y_True.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_+Y_True.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_+Y_True.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_+Z_False.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_+Z_False.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_+Z_False.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_+Z_False.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_+Z_True.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_+Z_True.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_+Z_True.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_+Z_True.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_-X_False.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_-X_False.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_-X_False.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_-X_False.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_-X_True.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_-X_True.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_-X_True.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_-X_True.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_-Y_False.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_-Y_False.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_-Y_False.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_-Y_False.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_-Y_True.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_-Y_True.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_-Y_True.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_-Y_True.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_-Z_False.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_-Z_False.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_-Z_False.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_-Z_False.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_-Z_True.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_-Z_True.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_-Z_True.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_1_-Z_True.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_+X_False.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_+X_False.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_+X_False.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_+X_False.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_+X_True.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_+X_True.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_+X_True.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_+X_True.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_+Y_False.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_+Y_False.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_+Y_False.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_+Y_False.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_+Y_True.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_+Y_True.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_+Y_True.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_+Y_True.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_+Z_False.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_+Z_False.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_+Z_False.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_+Z_False.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_+Z_True.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_+Z_True.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_+Z_True.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_+Z_True.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_-X_False.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_-X_False.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_-X_False.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_-X_False.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_-X_True.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_-X_True.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_-X_True.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_-X_True.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_-Y_False.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_-Y_False.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_-Y_False.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_-Y_False.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_-Y_True.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_-Y_True.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_-Y_True.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_-Y_True.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_-Z_False.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_-Z_False.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_-Z_False.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_-Z_False.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_-Z_True.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_-Z_True.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_-Z_True.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_2_-Z_True.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_+X_False.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_+X_False.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_+X_False.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_+X_False.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_+X_True.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_+X_True.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_+X_True.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_+X_True.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_+Y_False.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_+Y_False.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_+Y_False.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_+Y_False.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_+Y_True.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_+Y_True.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_+Y_True.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_+Y_True.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_+Z_False.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_+Z_False.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_+Z_False.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_+Z_False.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_+Z_True.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_+Z_True.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_+Z_True.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_+Z_True.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_-X_False.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_-X_False.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_-X_False.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_-X_False.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_-X_True.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_-X_True.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_-X_True.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_-X_True.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_-Y_False.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_-Y_False.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_-Y_False.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_-Y_False.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_-Y_True.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_-Y_True.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_-Y_True.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_-Y_True.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_-Z_False.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_-Z_False.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_-Z_False.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_-Z_False.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_-Z_True.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_-Z_True.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_-Z_True.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepRUS_3_-Z_True.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepZeroVerify_False.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepZeroVerify_False.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepZeroVerify_False.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepZeroVerify_False.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepZeroVerify_True.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepZeroVerify_True.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepZeroVerify_True.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.pauli_states.PrepZeroVerify_True.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.plus_h_state.PrepHStateFT.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.plus_h_state.PrepHStateFT.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.plus_h_state.PrepHStateFT.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.plus_h_state.PrepHStateFT.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.t_plus_state.PrepEncodeTDagPlusNonFT.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.t_plus_state.PrepEncodeTDagPlusNonFT.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.t_plus_state.PrepEncodeTDagPlusNonFT.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.t_plus_state.PrepEncodeTDagPlusNonFT.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.t_plus_state.PrepEncodeTPlusFT.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.t_plus_state.PrepEncodeTPlusFT.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.t_plus_state.PrepEncodeTPlusFT.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.t_plus_state.PrepEncodeTPlusFT.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.t_plus_state.PrepEncodeTPlusFTRUS_1.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.t_plus_state.PrepEncodeTPlusFTRUS_1.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.t_plus_state.PrepEncodeTPlusFTRUS_1.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.t_plus_state.PrepEncodeTPlusFTRUS_1.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.t_plus_state.PrepEncodeTPlusFTRUS_2.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.t_plus_state.PrepEncodeTPlusFTRUS_2.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.t_plus_state.PrepEncodeTPlusFTRUS_2.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.t_plus_state.PrepEncodeTPlusFTRUS_2.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.t_plus_state.PrepEncodeTPlusFTRUS_3.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.t_plus_state.PrepEncodeTPlusFTRUS_3.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.t_plus_state.PrepEncodeTPlusFTRUS_3.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.t_plus_state.PrepEncodeTPlusFTRUS_3.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.t_plus_state.PrepEncodeTPlusNonFT.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.t_plus_state.PrepEncodeTPlusNonFT.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.t_plus_state.PrepEncodeTPlusNonFT.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.preps.t_plus_state.PrepEncodeTPlusNonFT.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.qec.qec_3parallel.ParallelFlagQECActiveCorrection.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.qec.qec_3parallel.ParallelFlagQECActiveCorrection.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.qec.qec_3parallel.ParallelFlagQECActiveCorrection.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.qec.qec_3parallel.ParallelFlagQECActiveCorrection.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.syn_extract.six_check_nonflagging.SixUnflaggedSyn.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.syn_extract.six_check_nonflagging.SixUnflaggedSyn.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.syn_extract.six_check_nonflagging.SixUnflaggedSyn.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.syn_extract.six_check_nonflagging.SixUnflaggedSyn.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.syn_extract.three_parallel_flagging.ThreeParallelFlaggingXZZ.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.syn_extract.three_parallel_flagging.ThreeParallelFlaggingXZZ.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.syn_extract.three_parallel_flagging.ThreeParallelFlaggingXZZ.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.syn_extract.three_parallel_flagging.ThreeParallelFlaggingXZZ.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.syn_extract.three_parallel_flagging.ThreeParallelFlaggingZXX.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.syn_extract.three_parallel_flagging.ThreeParallelFlaggingZXX.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.qeclib.steane.syn_extract.three_parallel_flagging.ThreeParallelFlaggingZXX.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.qeclib.steane.syn_extract.three_parallel_flagging.ThreeParallelFlaggingZXX.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.slr.block.Block_X.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.slr.block.Block_X.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.slr.block.Block_X.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.slr.block.Block_X.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.slr.block.Block_Y.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.slr.block.Block_Y.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.slr.block.Block_Y.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.slr.block.Block_Y.qasm diff --git a/tests/regression/test_qasm/regression_qasm/pecos.slr.block.Block_Z.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/pecos.slr.block.Block_Z.qasm similarity index 100% rename from tests/regression/test_qasm/regression_qasm/pecos.slr.block.Block_Z.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/pecos.slr.block.Block_Z.qasm diff --git a/tests/regression/test_qasm/regression_qasm/phys.tele_block_block.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/phys.tele_block_block.qasm similarity index 71% rename from tests/regression/test_qasm/regression_qasm/phys.tele_block_block.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/phys.tele_block_block.qasm index d46beb66..2512fabe 100644 --- a/tests/regression/test_qasm/regression_qasm/phys.tele_block_block.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/phys.tele_block_block.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 qreg q[2]; creg m[2]; h q[0]; diff --git a/tests/regression/test_qasm/regression_qasm/phys.tele_block_telep_block.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/phys.tele_block_telep_block.qasm similarity index 78% rename from tests/regression/test_qasm/regression_qasm/phys.tele_block_telep_block.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/phys.tele_block_telep_block.qasm index 877539ba..014a9b4c 100644 --- a/tests/regression/test_qasm/regression_qasm/phys.tele_block_telep_block.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/phys.tele_block_telep_block.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 qreg q[2]; creg m[2]; creg m2[2]; diff --git a/tests/regression/test_qasm/regression_qasm/phys.tele_if.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/phys.tele_if.qasm similarity index 72% rename from tests/regression/test_qasm/regression_qasm/phys.tele_if.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/phys.tele_if.qasm index 27ea9cba..0a9b93a3 100644 --- a/tests/regression/test_qasm/regression_qasm/phys.tele_if.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/phys.tele_if.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 qreg q[2]; creg m[2]; h q[0]; diff --git a/tests/regression/test_qasm/regression_qasm/phys.tele_if_block_block.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/phys.tele_if_block_block.qasm similarity index 75% rename from tests/regression/test_qasm/regression_qasm/phys.tele_if_block_block.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/phys.tele_if_block_block.qasm index a3c28d3e..52ddbb57 100644 --- a/tests/regression/test_qasm/regression_qasm/phys.tele_if_block_block.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/phys.tele_if_block_block.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 qreg q[2]; creg m[2]; h q[0]; diff --git a/tests/regression/test_qasm/regression_qasm/phys.tele_repeat.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/phys.tele_repeat.qasm similarity index 79% rename from tests/regression/test_qasm/regression_qasm/phys.tele_repeat.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/phys.tele_repeat.qasm index 55bf3962..a352927b 100644 --- a/tests/regression/test_qasm/regression_qasm/phys.tele_repeat.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/phys.tele_repeat.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 qreg q[2]; creg m[2]; h q[0]; diff --git a/tests/regression/test_qasm/regression_qasm/phys.teleport.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/phys.teleport.qasm similarity index 68% rename from tests/regression/test_qasm/regression_qasm/phys.teleport.qasm rename to python/tests/pecos/regression/test_qasm/regression_qasm/phys.teleport.qasm index 38dce771..c4aafe30 100644 --- a/tests/regression/test_qasm/regression_qasm/phys.teleport.qasm +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/phys.teleport.qasm @@ -1,6 +1,5 @@ OPENQASM 2.0; include "hqslib1.inc"; -// Generated using: PECOS version 0.6.0.dev5 qreg q[2]; creg m[2]; h q[0]; diff --git a/tests/unit/reps/pymir/test_name_resolver.py b/python/tests/pecos/unit/reps/pymir/test_name_resolver.py similarity index 100% rename from tests/unit/reps/pymir/test_name_resolver.py rename to python/tests/pecos/unit/reps/pymir/test_name_resolver.py diff --git a/tests/unit/test_binarray.py b/python/tests/pecos/unit/test_binarray.py similarity index 100% rename from tests/unit/test_binarray.py rename to python/tests/pecos/unit/test_binarray.py diff --git a/tests/unit/test_blocks.py b/python/tests/pecos/unit/test_blocks.py similarity index 91% rename from tests/unit/test_blocks.py rename to python/tests/pecos/unit/test_blocks.py index b485cae9..9eceabf5 100644 --- a/tests/unit/test_blocks.py +++ b/python/tests/pecos/unit/test_blocks.py @@ -9,7 +9,10 @@ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the # specific language governing permissions and limitations under the License. """Tests to ensure the sequence of operations are as expected.""" -from pecos.classical_interpreters.phir_classical_interpreter import PHIRClassicalInterpreter + +from pecos.classical_interpreters.phir_classical_interpreter import ( + PHIRClassicalInterpreter, +) def get_seq(program): @@ -50,11 +53,19 @@ def test_seq(): "block": "sequence", "ops": [ {"qop": "R1XY", "angles": [[0.5, 0.5], "pi"], "args": [["q", 0]]}, - {"qop": "Measure", "args": [["q", 0], ["q", 1]], "returns": [["m", 0], ["m", 1]]}, + { + "qop": "Measure", + "args": [["q", 0], ["q", 1]], + "returns": [["m", 0], ["m", 1]], + }, {"qop": "R1XY", "angles": [[0.5, 0.5], "pi"], "args": [["q", 0]]}, ], }, - {"qop": "Measure", "args": [["q", 0], ["q", 1]], "returns": [["m", 0], ["m", 1]]}, + { + "qop": "Measure", + "args": [["q", 0], ["q", 1]], + "returns": [["m", 0], ["m", 1]], + }, {"qop": "X", "args": [["q", 0]]}, ], } @@ -89,11 +100,19 @@ def test_qparallel(): "block": "qparallel", "ops": [ {"qop": "R1XY", "angles": [[0.5, 0.5], "pi"], "args": [["q", 0]]}, - {"qop": "Measure", "args": [["q", 0], ["q", 1]], "returns": [["m", 0], ["m", 1]]}, + { + "qop": "Measure", + "args": [["q", 0], ["q", 1]], + "returns": [["m", 0], ["m", 1]], + }, {"qop": "R1XY", "angles": [[0.5, 0.5], "pi"], "args": [["q", 0]]}, ], }, - {"qop": "Measure", "args": [["q", 0], ["q", 1]], "returns": [["m", 0], ["m", 1]]}, + { + "qop": "Measure", + "args": [["q", 0], ["q", 1]], + "returns": [["m", 0], ["m", 1]], + }, {"qop": "X", "args": [["q", 0]]}, ], } diff --git a/pytest.ini b/python/tests/pytest.ini similarity index 94% rename from pytest.ini rename to python/tests/pytest.ini index 7a24d31d..7a03d542 100644 --- a/pytest.ini +++ b/python/tests/pytest.ini @@ -7,7 +7,7 @@ addopts = # -m not slow and not optional_dependency -m "not optional_dependency" -testpaths = tests +testpaths = . markers = # slow: mark test as slow. optional_dependency: mark a test as using one or more optional dependencies. @@ -20,3 +20,4 @@ markers = filterwarnings = ignore::PendingDeprecationWarning:projectq.ops._gates ignore::DeprecationWarning:dateutil.tz.tz.* + ignore::DeprecationWarning:cuquantum diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index d0d27e16..00000000 --- a/requirements.txt +++ /dev/null @@ -1,34 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.12 -# by the following command: -# -# pip-compile --extra=tests --no-annotate --no-emit-index-url --output-file=requirements.txt --strip-extras pyproject.toml -# -annotated-types==0.6.0 -attrs==23.2.0 -contourpy==1.2.0 -cycler==0.12.1 -fonttools==4.50.0 -hypothesis==6.100.1 -iniconfig==2.0.0 -kiwisolver==1.4.5 -markdown-it-py==3.0.0 -matplotlib==3.8.3 -mdurl==0.1.2 -networkx==2.8.8 -numpy==1.26.4 -packaging==24.0 -phir==0.3.3 -pillow==10.2.0 -pluggy==1.4.0 -pydantic==2.6.4 -pydantic-core==2.16.3 -pygments==2.17.2 -pyparsing==3.1.2 -pytest==8.1.1 -python-dateutil==2.9.0.post0 -rich==13.7.1 -scipy==1.12.0 -six==1.16.0 -sortedcontainers==2.4.0 -typing-extensions==4.10.0 diff --git a/ruff.toml b/ruff.toml index 4df5c982..64e0c883 100644 --- a/ruff.toml +++ b/ruff.toml @@ -3,7 +3,6 @@ target-version = "py39" line-length = 120 -extend-exclude = ["python/pecos/simulators/cuquantum_old/*"] [lint] select = [ @@ -119,20 +118,20 @@ ignore = [ [lint.per-file-ignores] "python/**/__init__.py" = ["F401"] # imported but unused (81) -"tests/**/*.py" = [ +"python/tests/**/*.py" = [ "INP001", # File is part of an implicit namespace package. Add an `__init__.py` (6) "S101", # Use of `assert` detected (78) ] # TODO: comment to work on better typing -"python/pecos/circuit_converters/**/*.py" = ["ANN"] -"python/pecos/circuits/**/*.py" = ["ANN"] -"python/pecos/decoders/**/*.py" = ["ANN"] -"python/pecos/engines/**/*.py" = ["ANN"] -"python/pecos/error_models/**/*.py" = ["ANN"] -"python/pecos/misc/**/*.py" = ["ANN"] -"python/pecos/qeccs/**/*.py" = ["ANN"] -"python/pecos/simulators/**/*.py" = ["ANN"] -"python/pecos/tools/*.py" = ["ANN"] +"python/pecos/src/pecos/circuit_converters/**/*.py" = ["ANN"] +"python/pecos/src/pecos/circuits/**/*.py" = ["ANN"] +"python/pecos/src/pecos/decoders/**/*.py" = ["ANN"] +"python/pecos/src/pecos/engines/**/*.py" = ["ANN"] +"python/pecos/src/pecos/error_models/**/*.py" = ["ANN"] +"python/pecos/src/pecos/misc/**/*.py" = ["ANN"] +"python/pecos/src/pecos/qeccs/**/*.py" = ["ANN"] +"python/pecos/src/pecos/simulators/**/*.py" = ["ANN"] +"python/pecos/src/pecos/tools/*.py" = ["ANN"] [lint.pycodestyle] max-doc-length = 120 diff --git a/tests/integration/__init__.py b/tests/integration/__init__.py deleted file mode 100644 index 80e13cf2..00000000 --- a/tests/integration/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright 2023 The PECOS developers -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -# the License.You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -"""Integration tests""" diff --git a/tests/unit/__init__.py b/tests/unit/__init__.py deleted file mode 100644 index 55b2ec69..00000000 --- a/tests/unit/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright 2023 The PECOS developers -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with -# the License.You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -"""Unit tests""" diff --git a/venv_setup.md b/venv_setup.md new file mode 100644 index 00000000..b7b43ab9 --- /dev/null +++ b/venv_setup.md @@ -0,0 +1,27 @@ +# Development virtual environment setup + +To manually set up a Python virtual environment for develop of this project's code, do the follow: + +On Linux/Mac: + +```sh +python -m venv .venv +source .venv/bin/activate +pip install -U pip setuptools +pip install -r python/quantum-pecos/requirements.txt +make metadeps +pre-commit install +``` + +On Windows: + +```sh +python -m venv .venv +.\venv\Scripts\activate +pip install -U pip setuptools +pip install -r python/quantum-pecos/requirements.txt +make metadeps +pre-commit install +``` + +See `Makefile` for other useful commands.