├── .coveragerc ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── config.yml │ ├── documentation_request.md │ └── feature_request.md ├── dependabot.yml ├── pull_request_template.md └── workflows │ ├── code-freeze.yml │ ├── publish-to-pypi.yml │ ├── python-package.yml │ └── stale_issue.yml ├── .gitignore ├── .readthedocs.yml ├── CHANGELOG.md ├── CODEOWNERS ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── NOTICE ├── README.md ├── TESTING.md ├── doc ├── Makefile ├── conf.py ├── index.rst └── requirements.txt ├── notebooks ├── advanced_algorithms │ ├── Quantum_Computing_Quantum_Monte_Carlo.ipynb │ └── Quantum_Principal_Component_Analysis.ipynb ├── auxiliary_functions │ └── Random_Circuit.ipynb └── textbook │ ├── Bells_Inequality.ipynb │ ├── Bernstein_Vazirani_Algorithm.ipynb │ ├── CHSH_Inequality.ipynb │ ├── Deutsch_Jozsa_Algorithm.ipynb │ ├── Grovers_Search.ipynb │ ├── Quantum_Approximate_Optimization_Algorithm.ipynb │ ├── Quantum_Circuit_Born_Machine.ipynb │ ├── Quantum_Fourier_Transform.ipynb │ ├── Quantum_Phase_Estimation_Algorithm.ipynb │ ├── Quantum_Walk.ipynb │ ├── README.md │ ├── Shors_Algorithm.ipynb │ ├── Simons_Algorithm.ipynb │ ├── Template.ipynb │ ├── notebook_plotting.py │ └── requirements.txt ├── pyproject.toml ├── setup.cfg ├── setup.py ├── src └── braket │ ├── _algos │ └── _version.py │ └── experimental │ ├── __init__.py │ ├── algorithms │ ├── __init__.py │ ├── bells_inequality │ │ ├── __init__.py │ │ ├── bells_inequality.md │ │ └── bells_inequality.py │ ├── bernstein_vazirani │ │ ├── __init__.py │ │ ├── bernstein_vazirani.md │ │ └── bernstein_vazirani.py │ ├── chsh_inequality │ │ ├── __init__.py │ │ ├── chsh_inequality.md │ │ └── chsh_inequality.py │ ├── deutsch_jozsa │ │ ├── __init__.py │ │ ├── deutsch_jozsa.md │ │ └── deutsch_jozsa.py │ ├── grovers_search │ │ ├── __init__.py │ │ ├── grovers_search.md │ │ └── grovers_search.py │ ├── qc_qmc │ │ ├── __init__.py │ │ ├── classical_qmc.py │ │ └── qc_qmc.py │ ├── quantum_approximate_optimization │ │ ├── __init__.py │ │ ├── quantum_approximate_optimization.md │ │ └── quantum_approximate_optimization.py │ ├── quantum_circuit_born_machine │ │ ├── __init__.py │ │ ├── qcbm.py │ │ └── quantum_circuit_born_machine.md │ ├── quantum_fourier_transform │ │ ├── __init__.py │ │ ├── quantum_fourier_transform.md │ │ └── quantum_fourier_transform.py │ ├── quantum_phase_estimation │ │ ├── __init__.py │ │ ├── quantum_phase_estimation.md │ │ └── quantum_phase_estimation.py │ ├── quantum_walk │ │ ├── __init__.py │ │ ├── quantum_walk.md │ │ └── quantum_walk.py │ ├── shors │ │ ├── __init__.py │ │ ├── shors.md │ │ └── shors.py │ └── simons │ │ ├── __init__.py │ │ ├── simons.md │ │ └── simons.py │ └── auxiliary_functions │ ├── __init__.py │ └── random_circuit │ ├── __init__.py │ ├── random_circuit.md │ └── random_circuit.py ├── test ├── integ_tests │ ├── advanced_algorithms │ │ ├── Quantum_Principal_Component_Analysis_mocks.py │ │ └── quantum_pca_results.json │ ├── conftest.py │ ├── default_data │ │ ├── default_capabilities.json │ │ └── default_results.json │ ├── default_mocks │ │ └── default_mocks.py │ ├── mock_utils.py │ ├── record_utils.py │ ├── requirements.txt │ ├── test_all_notebooks.py │ └── textbook │ │ ├── 0_quantum_walk.json │ │ ├── 1_quantum_walk.json │ │ ├── 2_quantum_walk.json │ │ ├── 3_quantum_walk.json │ │ ├── Grovers_Search_mocks.py │ │ ├── Quantum_Phase_Estimation_Algorithm_mocks.py │ │ ├── Quantum_Walk_mocks.py │ │ ├── Shors_Algorithm_mocks.py │ │ ├── Simons_Algorithm_mocks.py │ │ ├── grovers_results.json │ │ ├── quantum_phase_estimation_results.json │ │ ├── shors_results.json │ │ └── simons_results.json └── unit_tests │ └── braket │ └── experimental │ ├── algorithms │ ├── bells_inequality │ │ └── test_bells_inequality.py │ ├── bernstein_varzirani │ │ └── test_bernstien_vazirani.py │ ├── chsh_inequality │ │ └── test_chsh_inequality.py │ ├── deutsch_jozsa │ │ └── test_deutsch_jozsa.py │ ├── grovers_search │ │ └── test_grovers_search.py │ ├── qc_qmc │ │ └── test_qc_qmc.py │ ├── quantum_approximate_optimization │ │ └── test_quantum_approximate_optimization.py │ ├── quantum_circuit_born_machine │ │ └── test_qcbm.py │ ├── quantum_fourier_transform │ │ └── test_quantum_fourier_transform.py │ ├── quantum_phase_estimation │ │ └── test_quantum_phase_estimation.py │ ├── quantum_walk │ │ └── test_quantum_walk.py │ ├── shors │ │ └── test_shors.py │ └── simons │ │ └── test_simons.py │ └── auxiliary_functions │ └── random_circuit │ └── test_random_circuit.py └── tox.ini /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | parallel = True 3 | branch = True 4 | source = braket.experimental 5 | 6 | [paths] 7 | source = 8 | src/braket 9 | .tox/*/lib/python*/site-packages/braket 10 | 11 | [report] 12 | show_missing = True 13 | 14 | [html] 15 | directory = build/coverage 16 | 17 | [xml] 18 | output = build/coverage/coverage.xml 19 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: File a report to help us reproduce and fix the problem 4 | title: '' 5 | labels: 'bug' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To reproduce** 14 | A clear, step-by-step set of instructions to reproduce the bug. 15 | 16 | **Expected behavior** 17 | A clear and concise description of what you expected to happen. 18 | 19 | **Screenshots or logs** 20 | If applicable, add screenshots or logs to help explain your problem. 21 | 22 | **System information** 23 | A description of your system. Please provide: 24 | - **Amazon Braket Python Algorithm Library version**: 25 | - **Amazon Braket Python SDK version**: 26 | - **Amazon Braket Python Schemas version**: 27 | - **Amazon Braket Python Default Simulator version**: 28 | - **Python version**: 29 | 30 | **Additional context** 31 | Add any other context about the problem here. 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Ask a question 4 | url: https://forums.aws.amazon.com/tags/braket 5 | about: Use AWS Developer Forums to ask and answer questions 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/documentation_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Documentation request 3 | about: Request improved documentation 4 | title: '' 5 | labels: 'documentation' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **What did you find confusing? Please describe.** 11 | A clear and concise description of what you found confusing. Ex. I tried to [...] but I didn't understand how to [...] 12 | 13 | **Describe how documentation can be improved** 14 | A clear and concise description of where documentation was lacking and how it can be improved. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the documentation request here. 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest new functionality for this library 4 | title: '' 5 | labels: 'feature' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the feature you'd like** 11 | A clear and concise description of the functionality you want. 12 | 13 | **How would this feature be used? Please describe.** 14 | A clear and concise description of the use case for this feature. Please provide an example, if possible. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # Set update schedule for GitHub Actions 2 | 3 | version: 2 4 | updates: 5 | 6 | - package-ecosystem: "github-actions" 7 | directory: "/" 8 | schedule: 9 | # Check for updates to GitHub Actions every week 10 | interval: "weekly" 11 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | *Issue #, if available:* 2 | 3 | *Description of changes:* 4 | 5 | *Testing done:* 6 | 7 | ## Merge Checklist 8 | 9 | _Put an `x` in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your pull request._ 10 | 11 | #### General 12 | 13 | - [ ] I have read the [CONTRIBUTING](https://github.com/amazon-braket/amazon-braket-algorithm-library/blob/main/CONTRIBUTING.md) doc 14 | - [ ] I used the commit message format described in [CONTRIBUTING](https://github.com/amazon-braket/amazon-braket-algorithm-library/blob/main/CONTRIBUTING.md#commit-your-change) 15 | - [ ] I have updated any necessary documentation, including [READMEs](https://github.com/amazon-braket/amazon-braket-algorithm-library/blob/main/README.md) and [API docs](https://github.com/amazon-braket/amazon-braket-algorithm-library/blob/main/CONTRIBUTING.md#documentation-guidelines) (if appropriate) 16 | 17 | #### Tests 18 | 19 | - [ ] I have added tests that prove my fix is effective or that my feature works (if appropriate) 20 | - [ ] I have checked that my tests are not configured for a specific region or account (if appropriate) 21 | 22 | By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. 23 | -------------------------------------------------------------------------------- /.github/workflows/code-freeze.yml: -------------------------------------------------------------------------------- 1 | name: Code Freeze 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | workflow_dispatch: 8 | 9 | permissions: 10 | contents: read 11 | 12 | env: 13 | FROZEN: ${{ vars.FROZEN }} 14 | UNFROZEN_PREFIX: ${{ vars.UNFROZEN_PREFIX }} 15 | 16 | jobs: 17 | check-pr-frozen-status: 18 | runs-on: ubuntu-latest 19 | steps: 20 | - name: Fetch PR data and check if merge allowed 21 | if: env.FROZEN == 'true' 22 | env: 23 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 24 | run: | 25 | PR_DATA=$(curl -s \ 26 | -H "Authorization: Bearer $GITHUB_TOKEN" \ 27 | -H "Accept: application/vnd.github.v3+json" \ 28 | https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}) 29 | BRANCH_NAME=$(echo $PR_DATA | jq .head.ref -r) 30 | PR_TITLE=$(echo $PR_DATA | jq .title -r) 31 | echo $BRANCH_NAME 32 | echo $PR_TITLE 33 | # if it's not a critical fix 34 | if ! [[ "$PR_TITLE" == fix\(critical\):* ]]; then 35 | # and there's an unfrozen prefix 36 | if ! [[ -z $UNFROZEN_PREFIX ]]; then 37 | # check if the branch matches unfrozen prefix 38 | if [[ "$BRANCH_NAME" != $UNFROZEN_PREFIX* ]]; then 39 | echo "Error: You can only merge from branches that start with '$UNFROZEN_PREFIX', or PRs titled with prefix 'fix(critical): '." 40 | exit 1 41 | fi 42 | # repo is fully frozen 43 | else 44 | echo "Error: You can only merge PRs titled with prefix 'fix(critical): '." 45 | exit 1 46 | fi 47 | fi 48 | -------------------------------------------------------------------------------- /.github/workflows/publish-to-pypi.yml: -------------------------------------------------------------------------------- 1 | name: Publish distribution to PyPI 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | build-and-publish: 9 | name: Build and publish distribution to PyPi 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v4 13 | - name: Set up Python 14 | uses: actions/setup-python@v5 15 | with: 16 | python-version: '3.x' 17 | - name: Install wheel 18 | run: python -m pip install --user --upgrade wheel 19 | - name: Install twine 20 | run: python -m pip install --user --upgrade twine 21 | - name: Install setuptools 22 | run: python -m pip install --user --upgrade setuptools 23 | - name: Build a binary wheel and a source tarball 24 | run: python setup.py sdist bdist_wheel 25 | - name: Publish distribution to PyPI 26 | uses: pypa/gh-action-pypi-publish@master 27 | with: 28 | password: ${{ secrets.pypi_token }} 29 | -------------------------------------------------------------------------------- /.github/workflows/python-package.yml: -------------------------------------------------------------------------------- 1 | # This workflow will install Python dependencies, run tests and lint with a variety of Python versions 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions 3 | 4 | name: Python package 5 | 6 | on: 7 | push: 8 | branches: 9 | - main 10 | pull_request: 11 | branches: 12 | - main 13 | - feature/** 14 | 15 | jobs: 16 | build: 17 | runs-on: ${{ matrix.os }} 18 | strategy: 19 | matrix: 20 | os: [ubuntu-latest, macos-latest, windows-latest] 21 | python-version: ["3.9", "3.10", "3.11"] 22 | 23 | steps: 24 | - uses: actions/checkout@v4 25 | - name: Set up Python ${{ matrix.python-version }} 26 | uses: actions/setup-python@v5 27 | with: 28 | python-version: ${{ matrix.python-version }} 29 | - name: Install dependencies 30 | run: | 31 | pip install tox 32 | - name: Check code format 33 | run: | 34 | # stop the build if there are Python format errors or undefined names 35 | tox -e linters 36 | - name: Run unit tests 37 | run: | 38 | tox -e unit-tests 39 | - name: Run integ tests 40 | run: | 41 | tox -e integ-tests 42 | - name: Upload coverage report to Codecov 43 | uses: codecov/codecov-action@v5 44 | with: 45 | token: ${{ secrets.CODECOV_TOKEN }} 46 | -------------------------------------------------------------------------------- /.github/workflows/stale_issue.yml: -------------------------------------------------------------------------------- 1 | name: "Close stale issues" 2 | 3 | # Controls when the action will run. 4 | # This is every day at 10am 5 | on: 6 | schedule: 7 | - cron: "0 10 * * *" 8 | 9 | jobs: 10 | cleanup: 11 | runs-on: ubuntu-latest 12 | name: Stale issue job 13 | steps: 14 | - uses: aws-actions/stale-issue-cleanup@v6 15 | with: 16 | # Setting messages to an empty string will cause the automation to skip 17 | # that category 18 | ancient-issue-message: Greetings! It looks like this issue hasn’t been active in longer than three years. We encourage you to check if this is still an issue in the latest release. Because it has been longer than three years since the last update on this, and in the absence of more information, we will be closing this issue soon. If you find that this is still a problem, please feel free to provide a comment to prevent automatic closure, or if the issue is already closed, please feel free to reopen it. 19 | stale-issue-message: Greetings! It looks like this issue hasn’t been active in longer than a week. We encourage you to check if this is still an issue in the latest release. Because it has been longer than a week since the last update on this, and in the absence of more information, we will be closing this issue soon. If you find that this is still a problem, please feel free to provide a comment or add an upvote to prevent automatic closure, or if the issue is already closed, please feel free to open a new one. 20 | stale-pr-message: Greetings! It looks like this PR hasn’t been active in longer than a week, add a comment or an upvote to prevent automatic closure, or if the issue is already closed, please feel free to open a new one. 21 | 22 | # These labels are required 23 | stale-issue-label: closing-soon 24 | exempt-issue-label: auto-label-exempt 25 | stale-pr-label: closing-soon 26 | exempt-pr-label: pr/needs-review 27 | response-requested-label: response-requested 28 | 29 | # Don't set closed-for-staleness label to skip closing very old issues 30 | # regardless of label 31 | closed-for-staleness-label: closed-for-staleness 32 | 33 | # Issue timing 34 | days-before-stale: 7 35 | days-before-close: 4 36 | days-before-ancient: 1095 37 | 38 | # If you don't want to mark a issue as being ancient based on a 39 | # threshold of "upvotes", you can set this here. An "upvote" is 40 | # the total number of +1, heart, hooray, and rocket reactions 41 | # on an issue. 42 | minimum-upvotes-to-exempt: 1 43 | 44 | repo-token: ${{ secrets.GITHUB_TOKEN }} 45 | loglevel: DEBUG 46 | # Set dry-run to true to not perform label or close actions. 47 | dry-run: false 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *# 3 | *.swp 4 | .vscode 5 | *.idea 6 | *.iml* 7 | build_files.tar.gz 8 | .DS_Store 9 | 10 | .ycm_extra_conf.py 11 | .tox 12 | .python-version 13 | 14 | __pycache__/ 15 | *.py[cod] 16 | *$py.class 17 | *.egg-info/ 18 | *.ipynb_checkpoints/ 19 | 20 | /.coverage 21 | /.coverage.* 22 | /.cache 23 | /.pytest_cache 24 | /.mypy_cache 25 | /pip-wheel-metadata 26 | 27 | /doc/_apidoc/ 28 | /build 29 | /venv 30 | /dist 31 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Build documentation in the docs/ directory with Sphinx 9 | sphinx: 10 | configuration: doc/conf.py 11 | 12 | # Optionally build your docs in additional formats such as PDF 13 | formats: 14 | - pdf 15 | 16 | # setting up build.os and the python version 17 | build: 18 | os: ubuntu-22.04 19 | tools: 20 | python: "3.9" 21 | 22 | # Optionally set the version of Python and requirements required to build your docs 23 | python: 24 | install: 25 | - method: pip 26 | path: . 27 | - requirements: doc/requirements.txt 28 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners 2 | 3 | # These owners will be the default owners for everything in 4 | # the repo. Unless a later match takes precedence, these accounts 5 | # will be requested for review when someone opens a pull request. 6 | * @amazon-braket/braket-maintainers 7 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | ## Adding a New Algorithm 10 | We expect algorithms to be built on top of the [Amazon Braket SDK](https://github.com/amazon-braket/amazon-braket-sdk-python) to provide a unified user experience and to give us a single contract to test against. 11 | 12 | Please ensure that 13 | 1. Your algorithm is added as functional source code [here](https://github.com/amazon-braket/amazon-braket-algorithm-library/tree/main/src/braket/experimental/algorithms) 14 | 2. Add tests for your new code [here](https://github.com/amazon-braket/amazon-braket-algorithm-library/tree/main/test/unit_tests/braket/experimental/algorithms) 15 | 3. You illustrate use of the algorithm in a simple python notebook [here](https://github.com/amazon-braket/amazon-braket-algorithm-library/tree/main/notebooks) 16 | 17 | ## Reporting Bugs/Feature Requests 18 | 19 | We welcome you to use the [GitHub issue tracker](https://github.com/amazon-braket/amazon-braket-algorithm-library/issues) to report bugs or suggest features. 20 | 21 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already 22 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 23 | 24 | * A reproducible test case or series of steps 25 | * The version of our code being used 26 | * Any modifications you've made relevant to the bug 27 | * Anything unusual about your environment or deployment 28 | 29 | 30 | ## Contributing via Pull Requests 31 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 32 | 33 | 1. You are working against the latest source on the *main* branch. 34 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 35 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 36 | 37 | To send us a pull request, please: 38 | 39 | 1. Fork the repository. 40 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 41 | 3. Ensure local tests pass. 42 | 4. Commit to your fork using clear commit messages. 43 | 5. Send us a pull request, answering any default questions in the pull request interface. 44 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 45 | 46 | GitHub provides additional documentation on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 47 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 48 | 49 | ## Development on Braket Notebook Instances 50 | Braket supports [notebook instances](https://docs.aws.amazon.com/braket/latest/developerguide/braket-get-started-create-notebook.html) that come with an environment with Braket dependencies, examples, and algorithms already installed. 51 | 52 | To test changes made on a notebook requires an amendment to the environment that is installed on the notebook instance. 53 | A contributor can test changes pushed to a remote branch, which will be referred to as ``, or start using the below commands to start development on a notebook instance. 54 | 55 | ``` 56 | # Remove the algorithm library installed from the environment 57 | cd /home/ec2-user/ 58 | source ~/anaconda3/etc/profile.d/conda.sh 59 | conda activate Braket 60 | pip uninstall amazon-braket-algorithm-library -y 61 | 62 | # Download the repo and install the changes that are to be tested 63 | cd SageMaker/ 64 | rm -rf "Braket algorithms" 65 | git clone https://github.com/amazon-braket/amazon-braket-algorithm-library.git 66 | cd amazon-braket-algorithm-library/ 67 | # This command is not needed if a contributor has not published a remote branch already. 68 | git checkout 69 | pip install -e '.' 70 | ``` 71 | 72 | ### Making your changes 73 | 74 | When you make a contribution please ensure that you: 75 | 76 | 1. Follow the existing flow of an example algorithm. This should include providing a circuit definition function a run_() function, and a get__results() function 77 | 2. Provide the following files: 78 | 1. *src/braket/experimental/algorithms//.py* - implements your example algorithm 79 | 2. *src/braket/experimental/algorithms//\_\_init__\.py* - used for testing/packaging 80 | 3. *notebooks/textbook/_Algorithm.ipynb* - provides a notebook that runs an example using your implementation 81 | 4. (optional)*test/unit_tests/braket/experimental/algorithms//test_.py* - unit tests for your python file 82 | 4. (optional)*src/braket/experimental/algorithms//.md* - Markdown file describing your algorithm in the following format. Tags indicate the type of algorithm, for instance "Notebook" or "Advanced": 83 | 84 | *\* 85 | 86 | \ 95 | 3. Only have Open Source licensed dependencies in your example. 96 | 4. Run your algorithm on a simulator and optionally on a QPU in your notebook. 97 | 5. Ensure that your example runs without issues on both a recent Braket Notebook Instance (create a new Braket Notebook Instance or restart one from Amazon Braket [in the console](https://docs.aws.amazon.com/braket/latest/developerguide/braket-get-started-create-notebook.html)) and locally, using our most [recently released Amazon Braket SDK version](https://github.com/amazon-braket/amazon-braket-sdk-python/blob/main/README.md#installing-the-amazon-braket-python-sdk). Run the entire notebook by clicking `Cells > Run All`, either in the console or locally, and confirm that every cell completes without error. 98 | 99 | In addition we encourage re-use of existing examples but it is not required. If you see an opportunity to make use of existing modules, 100 | feel free to do so. For instance if your example implementation requires Quantum Fourier Transform and you can use the existing 101 | Quantum Fourier Transform module instead of re-implementing it, please do so. 102 | 103 | 104 | ## Finding contributions to work on 105 | The goal of the algorithm library is to offer example implementations of quantum algorithms on Amazon Braket, ranging from textbook algorithms 106 | to advanced implementations of recently published research. If you just read a research paper on an algorithm it may be a good candidate. 107 | Also looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub 108 | issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. 109 | 110 | 111 | ## Code of Conduct 112 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 113 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 114 | opensource-codeofconduct@amazon.com with any additional questions or comments. 115 | 116 | 117 | ## Security issue notifications 118 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public GitHub issue. 119 | 120 | 121 | ## Licensing 122 | 123 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 124 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Amazon Braket Algorithm Library 2 | [![Build](https://github.com/amazon-braket/amazon-braket-algorithm-library/actions/workflows/python-package.yml/badge.svg?branch=main)](https://github.com/amazon-braket/amazon-braket-algorithm-library/actions/workflows/python-package.yml) 3 | 4 | The Braket Algorithm Library provides Amazon Braket customers with pre-built implementations of prominent quantum algorithms and experimental workloads as ready-to-run example notebooks. 5 | 6 | --- 7 | ### Braket algorithms 8 | 9 | Currently, Braket algorithms are tested on Linux, Windows, and Mac. 10 | 11 | Running notebooks locally requires additional dependencies located in [notebooks/textbook/requirements.txt](https://github.com/amazon-braket/amazon-braket-algorithm-library/blob/main/notebooks/textbook/requirements.txt). See notebooks/textbook/README.md for more information. 12 | 13 | | Textbook algorithms | Notebook | References | 14 | | ----- | ----- | ----- | 15 | | Bell's Inequality | [Bells_Inequality.ipynb](notebooks/textbook/Bells_Inequality.ipynb) | [Bell1964](https://journals.aps.org/ppf/abstract/10.1103/PhysicsPhysiqueFizika.1.195), [Greenberger1990](https://doi.org/10.1119/1.16243) | 16 | | Bernstein–Vazirani | [Bernstein_Vazirani_Algorithm.ipynb](notebooks/textbook/Bernstein_Vazirani_Algorithm.ipynb) | [Bernstein1997](https://epubs.siam.org/doi/10.1137/S0097539796300921) | 17 | | CHSH Inequality | [CHSH_Inequality.ipynb](notebooks/textbook/CHSH_Inequality.ipynb) | [Clauser1970](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.23.880) | 18 | | Deutsch-Jozsa | [Deutsch_Jozsa_Algorithm.ipynb](notebooks/textbook/Deutsch_Jozsa_Algorithm.ipynb) | [Deutsch1992](https://royalsocietypublishing.org/doi/10.1098/rspa.1992.0167) | 19 | | Grover's Search | [Grovers_Search.ipynb](notebooks/textbook/Grovers_Search.ipynb) | [Figgatt2017](https://www.nature.com/articles/s41467-017-01904-7), [Baker2019](https://arxiv.org/abs/1904.01671) | 20 | | QAOA | [Quantum_Approximate_Optimization_Algorithm.ipynb](notebooks/textbook/Quantum_Approximate_Optimization_Algorithm.ipynb) | [Farhi2014](https://arxiv.org/abs/1411.4028) | 21 | | Quantum Circuit Born Machine | [Quantum_Circuit_Born_Machine.ipynb](notebooks/textbook/Quantum_Circuit_Born_Machine.ipynb) | [Benedetti2019](https://www.nature.com/articles/s41534-019-0157-8), [Liu2018](https://journals.aps.org/pra/abstract/10.1103/PhysRevA.98.062324) | 22 | | QFT | [Quantum_Fourier_Transform.ipynb](notebooks/textbook/Quantum_Fourier_Transform.ipynb) | [Coppersmith2002](https://arxiv.org/abs/quant-ph/0201067) | 23 | | QPE | [Quantum_Phase_Estimation_Algorithm.ipynb](notebooks/textbook/Quantum_Phase_Estimation_Algorithm.ipynb) | [Kitaev1995](https://arxiv.org/abs/quant-ph/9511026) | 24 | | Quantum Walk | [Quantum_Walk.ipynb](notebooks/textbook/Quantum_Walk.ipynb) | [Childs2002](https://arxiv.org/abs/quant-ph/0209131) | 25 | |Shor's| [Shors_Algorithm.ipynb](notebooks/textbook/Shors_Algorithm.ipynb) | [Shor1998](https://arxiv.org/abs/quant-ph/9508027) | 26 | | Simon's | [Simons_Algorithm.ipynb](notebooks/textbook/Simons_Algorithm.ipynb) | [Simon1997](https://epubs.siam.org/doi/10.1137/S0097539796298637) | 27 | 28 | 29 | | Advanced algorithms | Notebook | References | 30 | | ----- | ----- | ----- | 31 | | Quantum PCA | [Quantum_Principal_Component_Analysis.ipynb](notebooks/advanced_algorithms/Quantum_Principal_Component_Analysis.ipynb) | [He2022](https://ieeexplore.ieee.org/document/9669030) | 32 | | QMC | [Quantum_Computing_Quantum_Monte_Carlo.ipynb](notebooks/advanced_algorithms/Quantum_Computing_Quantum_Monte_Carlo.ipynb) | [Motta2018](https://wires.onlinelibrary.wiley.com/doi/10.1002/wcms.1364), [Peruzzo2014](https://www.nature.com/articles/ncomms5213) | 33 | 34 | 35 | | Auxiliary functions | Notebook | 36 | | ----- | ----- | 37 | | Random circuit generator | [Random_Circuit.ipynb](notebooks/auxiliary_functions/Random_Circuit.ipynb) | 38 | 39 | --- 40 | ### Community repos 41 | 42 | > :warning: **The following includes projects that are not provided by Amazon Braket. You are solely responsible for your use of those projects (including compliance with any applicable licenses and fitness of the project for your particular purpose).** 43 | 44 | Quantum algorithm implementations using Braket in other repos: 45 | 46 | | Algorithm | Repo | References | Additional dependencies | 47 | | ----- | ----- | ----- | ----- | 48 | | Quantum Reinforcement Learning | [quantum-computing-exploration-for-drug-discovery-on-aws](https://github.com/awslabs/quantum-computing-exploration-for-drug-discovery-on-aws)| [Learning Retrosynthetic Planning through Simulated Experience(2019)](https://pubs.acs.org/doi/10.1021/acscentsci.9b00055) | [dependencies](https://github.com/awslabs/quantum-computing-exploration-for-drug-discovery-on-aws/blob/main/source/src/notebook/healthcare-and-life-sciences/d-1-retrosynthetic-planning-quantum-reinforcement-learning/requirements.txt) 49 | 50 | [comment]: <> (If you wish to highlight your implementation, append the following content in a new line to the table above : | | | | |) 51 | 52 | --- 53 | ## Installing the Amazon Braket Algorithm Library 54 | The Amazon Braket Algorithm Library can be installed from source by cloning this repository and running a pip install command in the root directory of the repository. 55 | 56 | ```bash 57 | git clone https://github.com/amazon-braket/amazon-braket-algorithm-library.git 58 | cd amazon-braket-algorithm-library 59 | pip install . 60 | ``` 61 | 62 | To run the notebook examples locally on your IDE, first, configure a profile to use your account to interact with AWS. To learn more, see [Configure AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html). 63 | 64 | After you create a profile, use the following command to set the `AWS_PROFILE` so that all future commands can access your AWS account and resources. 65 | 66 | ```bash 67 | export AWS_PROFILE=YOUR_PROFILE_NAME 68 | ``` 69 | 70 | ### Configure your AWS account with the resources necessary for Amazon Braket 71 | If you are new to Amazon Braket, onboard to the service and create the resources necessary to use Amazon Braket using the [AWS console](https://console.aws.amazon.com/braket/home ). 72 | 73 | 74 | ## Support 75 | 76 | ### Issues and Bug Reports 77 | 78 | If you encounter bugs or face issues while using the algorithm library, please let us know by posting 79 | the issue on our [GitHub issue tracker](https://github.com/amazon-braket/amazon-braket-algorithm-library/issues). 80 | For other issues or general questions, please ask on the [Quantum Computing Stack Exchange](https://quantumcomputing.stackexchange.com/questions/ask) and add the tag amazon-braket. 81 | 82 | ### Feedback and Feature Requests 83 | 84 | If you have feedback or features that you would like to see on Amazon Braket, we would love to hear from you! 85 | [GitHub issues](https://github.com/amazon-braket/amazon-braket-algorithm-library/issues) is our preferred mechanism for collecting feedback and feature requests, allowing other users 86 | to engage in the conversation, and +1 issues to help drive priority. 87 | 88 | 89 | ## License 90 | This project is licensed under the Apache-2.0 License. 91 | -------------------------------------------------------------------------------- /TESTING.md: -------------------------------------------------------------------------------- 1 | # Testing 2 | 3 | ## All Mock Testing 4 | 5 | To run the integration tests for these notebooks using mocks to override 6 | calls to AWS, just run: 7 | 8 | ``` 9 | tox -e integ-tests 10 | ``` 11 | 12 | These tests do not require AWS account credentials to run. 13 | 14 | ### How it works 15 | 16 | We use testbook to call each notebook and mock out all calls to the boto3 by 17 | overwriting the boto3.Session class. We then provide default results that would 18 | have been returned by a boto3 client. 19 | 20 | We inject `mock_utils.py` at the beginning of each notebook, then call the 21 | mock setup `def pre_run_inject(mock_utils):` passing in the mock_utils module as 22 | the parameter. This function is where the notebook mocks can choose to 23 | how to override the boto3 session, and what results to return. If the notebook 24 | finishes executing all cells correctly `def post_run(tb):` will be called 25 | for any cleanup and correctness testing (assertions that should be true 26 | at the end of the notebook execution). 27 | 28 | By default, a notebook is run using the `default_mocks/default_mocks.py` which 29 | uses the `default_data/default_capabilities.json` for returning device details 30 | and `default_data/default_results.json` for all task results in the notebook. 31 | This can be changed by adding a path in `test/integ_tests` that is identical 32 | to the notebook being tested, with a file `_mocks.py` in that 33 | directory. The file should specify `def pre_run_inject(mock_utils):` and 34 | `def post_run(tb):`. If this file is found, it will be called instead of the 35 | default mocks. 36 | 37 | ## Least Mock Testing 38 | 39 | To run the integration tests for these notebooks using mocks to override 40 | creation of tasks and jobs, just run: 41 | 42 | ``` 43 | tox -e integ-tests-aws 44 | ``` 45 | 46 | These tests will require valid AWS account credentials to run. 47 | 48 | ### How it works 49 | 50 | These tests work using the same mechanisms and use the same test data as provided 51 | by "All Mock Testing", but only override functions in AwsSession that 52 | create/get/cancel tasks. These tests take longer to run, but test 53 | integration with braket services more thoroughly. 54 | 55 | ## Recording 56 | 57 | It is possible to use our test framework to record some calls that are made 58 | to Braket using the code below. 59 | 60 | Create a code cell at the top of the notebook with the following code: 61 | 62 | ```python 63 | import os 64 | record_path = None 65 | curr_path = ".." 66 | while record_path == None: 67 | files = os.listdir(curr_path) 68 | if "TESTING.md" in files: 69 | record_path = os.path.join(curr_path, "test", "integ_tests", "record_utils.py") 70 | break 71 | curr_path = os.path.join("..", curr_path) 72 | from importlib.machinery import SourceFileLoader 73 | record_utils = SourceFileLoader("notebook_record_utils", record_path).load_module() 74 | ``` 75 | 76 | Running the entire notebook will generate several files, which can then be used 77 | for playback. 78 | 79 | ## Playback 80 | 81 | Simply append the following line to the code cell specified in the Recording section 82 | 83 | ``` 84 | record_utils.playback() 85 | ``` 86 | 87 | Re-running the notebook will use the generated files made during recording. 88 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = python -msphinx 7 | SPHINXPROJ = amazon-braket-algorithm-library 8 | SOURCEDIR = . 9 | BUILDDIR = ../build/documentation 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /doc/conf.py: -------------------------------------------------------------------------------- 1 | """Sphinx configuration.""" 2 | 3 | import datetime 4 | 5 | import pkg_resources 6 | 7 | # Sphinx configuration below. 8 | project = "amazon-braket-algorithm-library" 9 | version = pkg_resources.require(project)[0].version 10 | release = version 11 | copyright = f"{datetime.datetime.now().year}, Amazon.com" 12 | 13 | extensions = [ 14 | "sphinxcontrib.apidoc", 15 | "sphinx.ext.autodoc", 16 | "sphinx.ext.viewcode", 17 | "sphinx.ext.napoleon", 18 | "sphinx.ext.todo", 19 | "sphinx.ext.coverage", 20 | ] 21 | 22 | source_suffix = ".rst" 23 | master_doc = "index" 24 | 25 | autoclass_content = "both" 26 | autodoc_member_order = "bysource" 27 | default_role = "py:obj" 28 | 29 | html_theme = "sphinx_rtd_theme" 30 | htmlhelp_basename = f"{project}doc" 31 | 32 | napoleon_use_rtype = False 33 | 34 | apidoc_module_dir = "../src/braket" 35 | apidoc_output_dir = "_apidoc" 36 | apidoc_excluded_paths = ["../test"] 37 | apidoc_separate_modules = True 38 | apidoc_module_first = True 39 | apidoc_extra_args = ["-f", "--implicit-namespaces", "-H", "API Reference"] 40 | -------------------------------------------------------------------------------- /doc/index.rst: -------------------------------------------------------------------------------- 1 | ############################### 2 | Amazon Braket Algorithm Library 3 | ############################### 4 | 5 | The Braket Algorithm Library provides Amazon Braket customers with pre-built implementations of prominent quantum algorithms and experimental workloads as ready-to-run example notebooks. 6 | 7 | Currently, Braket algorithms are tested on Linux, Windows, and Mac. 8 | 9 | Running notebooks locally requires additional dependencies located in notebooks/textbook/requirements.txt https://github.com/amazon-braket/amazon-braket-algorithm-library/blob/main/notebooks/textbook/requirements.txt. See notebooks/textbook/README.md for more information. 10 | __________________ 11 | 12 | * :doc:`_apidoc/modules` 13 | * :ref:`genindex` 14 | * :ref:`modindex` 15 | * :ref:`search` 16 | -------------------------------------------------------------------------------- /doc/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx 2 | sphinx-rtd-theme 3 | sphinxcontrib-apidoc 4 | -------------------------------------------------------------------------------- /notebooks/auxiliary_functions/Random_Circuit.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "attachments": {}, 5 | "cell_type": "markdown", 6 | "metadata": {}, 7 | "source": [ 8 | "# Random Circuit\n", 9 | "\n", 10 | "Generates random quantum circuits using the Amazon Braket SDK.\n", 11 | "\n", 12 | "### Circuit Generation for Testing\n", 13 | "\n", 14 | "Random quantum circuits allow creation of a diverse set of circuits with a variety of output probability distributions. Users can utilize random circuits to test performance of quantum simulators and QPUs. \n", 15 | "\n", 16 | "### Benchmarking quantum compilation stacks\n", 17 | "\n", 18 | "Random circuits sampled from a fixed gate set (as in the example below) are often used for benchmarking performance of quantum compilation passes, such as circuit mapping, routing, or circuit optimization passes. " 19 | ] 20 | }, 21 | { 22 | "attachments": {}, 23 | "cell_type": "markdown", 24 | "metadata": {}, 25 | "source": [ 26 | "# Run on a local simulator" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": 1, 32 | "metadata": {}, 33 | "outputs": [ 34 | { 35 | "name": "stdout", 36 | "output_type": "stream", 37 | "text": [ 38 | "--Circuit--\n", 39 | "T : │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │ 12 │\n", 40 | " ┌───┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ \n", 41 | "q0 : ───●────────────────┤ X ├──────────────┤ XY(0.19) ├───────┤ Rz(4.77) ├───────┤ Rz(0.58) ├─┤ XY(4.59) ├─┤ XY(0.50) ├───●────┤ Rz(5.37) ├───┤ Rz(1.44) ├───────┤ Rz(1.33) ├────────────────────────────────────\n", 42 | " │ └─┬─┘ └────┬─────┘ └──────────┘ └──────────┘ └────┬─────┘ └────┬─────┘ │ └──────────┘ └──────────┘ └──────────┘ \n", 43 | " │ ┌──────────┐ │ ┌──────────┐ │ ┌───┐ ┌──────────┐ ┌──────────┐ │ │ ┌─┴─┐ ┌─────────────┐ ┌───┐ ┌──────────┐ ┌──────────┐ ┌─────────────┐ \n", 44 | "q1 : ───┼───┤ Rx(0.88) ├───┼───┤ Rx(3.18) ├──────┼───────┤ X ├─┤ XY(2.82) ├───────┤ Rx(6.01) ├──────┼────────────┼───────┤ X ├─┤ PHASE(2.33) ├──────────────┤ X ├─┤ XY(2.90) ├───────┤ XY(4.12) ├─┤ PHASE(1.66) ├─\n", 45 | " │ └──────────┘ │ └──────────┘ │ └─┬─┘ └────┬─────┘ └──────────┘ │ │ └───┘ └──────┬──────┘ └─┬─┘ └────┬─────┘ └────┬─────┘ └──────┬──────┘ \n", 46 | " ┌─┴─┐ │ │ │ │ ┌────┴─────┐ │ ┌───┐ │ ┌──────────┐ │ │ ┌────┴─────┐ │ \n", 47 | "q2 : ─┤ X ├────────────────┼─────────────────────┼─────────┼────────┼─────────●────────────────┤ XY(4.59) ├──────┼───────┤ X ├────────●────────┤ Rx(4.41) ├───┼────────┼─────────●───┤ XY(4.12) ├────────┼────────\n", 48 | " └───┘ │ │ │ │ │ └──────────┘ │ └─┬─┘ └──────────┘ │ │ │ └──────────┘ │ \n", 49 | " │ ┌────┴─────┐ │ ┌────┴─────┐ │ ┌──────────┐ ┌────┴─────┐ │ │ │ ┌─┴─┐ │ \n", 50 | "q3 : ──────────────────────┼────────────────┤ XY(0.19) ├───┼───┤ XY(2.82) ├───┼───┤ Rx(2.14) ├──────────────┤ XY(0.50) ├───●──────────────────────────────────┼────────┼───────┤ X ├─────────────────────●────────\n", 51 | " │ └──────────┘ │ └──────────┘ │ └──────────┘ └──────────┘ │ │ └───┘ \n", 52 | " │ │ ┌─┴─┐ ┌──────────┐ ┌──────────┐ │ ┌────┴─────┐ ┌──────────┐ ┌──────────┐ \n", 53 | "q4 : ──────────────────────●───────────────────────────────●────────────────┤ X ├─┤ Rz(5.56) ├─┤ Rz(1.21) ├───────────────────────────────────────────────────●───┤ XY(2.90) ├───────┤ Rz(1.38) ├──┤ Rx(3.39) ├───\n", 54 | " └───┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ \n", 55 | "T : │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │ 12 │\n", 56 | "\n", 57 | "--Counts--\n", 58 | "Counter({'01011': 34, '00011': 21, '00001': 13, '00111': 10, '01001': 10, '01010': 3, '00000': 2, '00101': 2, '01000': 2, '10000': 1, '00010': 1, '11010': 1})\n" 59 | ] 60 | } 61 | ], 62 | "source": [ 63 | "from braket.circuits.gates import CNot, Rx, Rz, CPhaseShift, XY\n", 64 | "from braket.devices import LocalSimulator\n", 65 | "from braket.experimental.auxiliary_functions import random_circuit\n", 66 | "\n", 67 | "# Code here\n", 68 | "local_simulator = LocalSimulator()\n", 69 | "gate_set = [CNot, Rx, Rz, CPhaseShift, XY]\n", 70 | "circuit = random_circuit(num_qubits=5, num_gates=30, gate_set=gate_set, seed=42)\n", 71 | "task = local_simulator.run(circuit, shots=100)\n", 72 | "result = task.result()\n", 73 | "print(\"--Circuit--\")\n", 74 | "print(circuit)\n", 75 | "print(\"\\n--Counts--\")\n", 76 | "print(result.measurement_counts)" 77 | ] 78 | } 79 | ], 80 | "metadata": { 81 | "kernelspec": { 82 | "display_name": "Python 3 (ipykernel)", 83 | "language": "python", 84 | "name": "python3" 85 | }, 86 | "language_info": { 87 | "codemirror_mode": { 88 | "name": "ipython", 89 | "version": 3 90 | }, 91 | "file_extension": ".py", 92 | "mimetype": "text/x-python", 93 | "name": "python", 94 | "nbconvert_exporter": "python", 95 | "pygments_lexer": "ipython3", 96 | "version": "3.11.4" 97 | }, 98 | "vscode": { 99 | "interpreter": { 100 | "hash": "5904cb9a2089448a2e1aeb5d493d227c9de33e591d7c07e4016fb81e71061a5d" 101 | } 102 | } 103 | }, 104 | "nbformat": 4, 105 | "nbformat_minor": 4 106 | } 107 | -------------------------------------------------------------------------------- /notebooks/textbook/Bells_Inequality.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Bell's Inequality\n", 8 | "\n", 9 | "This tutorial shows how to run a version of Bell's inequality experiment in Braket on a local simulator and a QPU. " 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "## References \n", 17 | "\n", 18 | "[1] Bell, J. S. On the Einstein Podolsky Rosen Paradox. Physics Physique Fizika 1, no. 3 (November 1, 1964): 195–200. https://doi.org/10.1103/PhysicsPhysiqueFizika.1.195. \n", 19 | "\n", 20 | "[2] Greenberger, Daniel M., Michael A. Horne, Abner Shimony, and Anton Zeilinger (1990). Bell’s Theorem without Inequalities. American Journal of Physics 58, no. 12: 1131–43. https://doi.org/10.1119/1.16243. " 21 | ] 22 | }, 23 | { 24 | "cell_type": "markdown", 25 | "metadata": {}, 26 | "source": [ 27 | "# Run on a local simulator" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": 1, 33 | "metadata": {}, 34 | "outputs": [], 35 | "source": [ 36 | "import numpy as np\n", 37 | "from braket.devices import LocalSimulator\n", 38 | "from braket.tracking import Tracker\n", 39 | "\n", 40 | "from braket.experimental.algorithms.bells_inequality import (\n", 41 | " create_bell_inequality_circuits,\n", 42 | " get_bell_inequality_results,\n", 43 | " run_bell_inequality,\n", 44 | ")\n", 45 | "\n", 46 | "tracker = Tracker().start() # to keep track of Braket costs" 47 | ] 48 | }, 49 | { 50 | "cell_type": "markdown", 51 | "metadata": {}, 52 | "source": [ 53 | "Bell's Inequality experiment consists of three circuits acting on two qubits each. " 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": 2, 59 | "metadata": {}, 60 | "outputs": [ 61 | { 62 | "name": "stdout", 63 | "output_type": "stream", 64 | "text": [ 65 | "\n", 66 | "Circuit AB\n", 67 | " T : |0|1|2| 3 |Result Types|\n", 68 | " \n", 69 | "q0 : -X-H-C----------Probability--\n", 70 | " | | \n", 71 | "q1 : -X---X-Rx(1.05)-Probability--\n", 72 | "\n", 73 | "T : |0|1|2| 3 |Result Types|\n", 74 | "\n", 75 | "Circuit AC\n", 76 | " T : |0|1|2| 3 |Result Types|\n", 77 | " \n", 78 | "q0 : -X-H-C----------Probability--\n", 79 | " | | \n", 80 | "q1 : -X---X-Rx(2.09)-Probability--\n", 81 | "\n", 82 | "T : |0|1|2| 3 |Result Types|\n", 83 | "\n", 84 | "Circuit BC\n", 85 | " T : |0|1|2| 3 |Result Types|\n", 86 | " \n", 87 | "q0 : -X-H-C-Rx(1.05)-Probability--\n", 88 | " | | \n", 89 | "q1 : -X---X-Rx(2.09)-Probability--\n", 90 | "\n", 91 | "T : |0|1|2| 3 |Result Types|\n" 92 | ] 93 | } 94 | ], 95 | "source": [ 96 | "circAB, circAC, circBC = create_bell_inequality_circuits(0, 1)\n", 97 | "print(\"\\nCircuit AB\\n\", circAB)\n", 98 | "print(\"\\nCircuit AC\\n\", circAC)\n", 99 | "print(\"\\nCircuit BC\\n\", circBC)" 100 | ] 101 | }, 102 | { 103 | "cell_type": "markdown", 104 | "metadata": {}, 105 | "source": [ 106 | "The three circuits are grouped together in the `run_bell_inequality` function below. To run on a local noise-free simulator, we can call this function. " 107 | ] 108 | }, 109 | { 110 | "cell_type": "code", 111 | "execution_count": 3, 112 | "metadata": {}, 113 | "outputs": [ 114 | { 115 | "name": "stdout", 116 | "output_type": "stream", 117 | "text": [ 118 | "[LocalQuantumTask('id':5b2fd071-176c-4566-820d-e559f7400534), LocalQuantumTask('id':819ede49-79f9-482d-bf16-6a4845cb887e), LocalQuantumTask('id':ea4ce7ff-8d39-4d1d-9339-8a366cace40c)]\n" 119 | ] 120 | } 121 | ], 122 | "source": [ 123 | "local_simulator = LocalSimulator()\n", 124 | "local_tasks = run_bell_inequality([circAB, circAC, circBC], local_simulator, shots=1000)\n", 125 | "print(local_tasks)" 126 | ] 127 | }, 128 | { 129 | "cell_type": "markdown", 130 | "metadata": {}, 131 | "source": [ 132 | "To gather the results of Bell's inequality test, we call the `get_bell_inequality_results` of the tasks from above. " 133 | ] 134 | }, 135 | { 136 | "cell_type": "code", 137 | "execution_count": 4, 138 | "metadata": {}, 139 | "outputs": [ 140 | { 141 | "name": "stdout", 142 | "output_type": "stream", 143 | "text": [ 144 | "P(a,b) = -0.47,P(a,c) = 0.526,P(b,c) = -0.49\n", 145 | "Bell's' inequality: 1.486 ≤ 1\n", 146 | "Bell's inequality is violated!\n" 147 | ] 148 | } 149 | ], 150 | "source": [ 151 | "results, pAB, pAC, pBC = get_bell_inequality_results(local_tasks)" 152 | ] 153 | }, 154 | { 155 | "cell_type": "markdown", 156 | "metadata": {}, 157 | "source": [ 158 | "# Run on a QPU \n", 159 | "\n", 160 | "To run Bell's inequality on a QPU, we replace the LocalSimulator with an AwsDevice. The cost to run this experiment is \\\\$0.3 per task and \\\\$0.00145 per shot on the IQM Garnet device. Since we have three circuits of 1000 shots each, that totals \\$5.25 USD." 161 | ] 162 | }, 163 | { 164 | "cell_type": "code", 165 | "execution_count": 5, 166 | "metadata": {}, 167 | "outputs": [], 168 | "source": [ 169 | "# # Uncomment to run on a QPU\n", 170 | "# from braket.aws import AwsDevice\n", 171 | "# iqm_garnet = AwsDevice(\"arn:aws:braket:eu-north-1::device/qpu/iqm/Garnet\")\n", 172 | "# iqm_tasks = run_bell_inequality([circAB, circAC, circBC], iqm_garnet, shots=1000)\n", 173 | "# results, pAB, pAC, pBC = get_bell_inequality_results(iqm_tasks)\n" 174 | ] 175 | }, 176 | { 177 | "cell_type": "markdown", 178 | "metadata": {}, 179 | "source": [ 180 | "We see that Bell's inequality is violated, so the device is demonstrating quantum behavior." 181 | ] 182 | }, 183 | { 184 | "cell_type": "code", 185 | "execution_count": 6, 186 | "metadata": {}, 187 | "outputs": [ 188 | { 189 | "name": "stdout", 190 | "output_type": "stream", 191 | "text": [ 192 | "Task Summary\n", 193 | "{'arn:aws:braket:eu-north-1::device/qpu/iqm/Garnet': {'shots': 3000, 'tasks': {'COMPLETED': 3}}}\n", 194 | "\n", 195 | "Estimated cost to run this example: 5.25 USD\n" 196 | ] 197 | } 198 | ], 199 | "source": [ 200 | "print(\"Task Summary\")\n", 201 | "print(f\"{tracker.quantum_tasks_statistics()} \\n\")\n", 202 | "print(\n", 203 | " f\"Estimated cost to run this example: {tracker.qpu_tasks_cost() + tracker.simulator_tasks_cost():.2f} USD\"\n", 204 | ")" 205 | ] 206 | }, 207 | { 208 | "cell_type": "markdown", 209 | "metadata": {}, 210 | "source": [ 211 | "Note: Charges shown are estimates based on your Amazon Braket simulator and quantum processing unit (QPU) task usage. Estimated charges shown may differ from your actual charges. Estimated charges do not factor in any discounts or credits, and you may experience additional charges based on your use of other services such as Amazon Elastic Compute Cloud (Amazon EC2)." 212 | ] 213 | } 214 | ], 215 | "metadata": { 216 | "kernelspec": { 217 | "display_name": "Python 3 (ipykernel)", 218 | "language": "python", 219 | "name": "python3" 220 | }, 221 | "language_info": { 222 | "codemirror_mode": { 223 | "name": "ipython", 224 | "version": 3 225 | }, 226 | "file_extension": ".py", 227 | "mimetype": "text/x-python", 228 | "name": "python", 229 | "nbconvert_exporter": "python", 230 | "pygments_lexer": "ipython3", 231 | "version": "3.11.4" 232 | }, 233 | "vscode": { 234 | "interpreter": { 235 | "hash": "5904cb9a2089448a2e1aeb5d493d227c9de33e591d7c07e4016fb81e71061a5d" 236 | } 237 | } 238 | }, 239 | "nbformat": 4, 240 | "nbformat_minor": 4 241 | } 242 | -------------------------------------------------------------------------------- /notebooks/textbook/README.md: -------------------------------------------------------------------------------- 1 | # Amazon Braket Algorithm Library Notebooks 2 | The Braket Algorithm Library Notebooks provide ready-to-run example notebooks of the algorithm implementations in this repo. 3 | 4 | ## Local Setup 5 | Running notebooks locally requires the following steps: 6 | 1. pip install -r requirements.txt 7 | 2. jupyter notebook 8 | -------------------------------------------------------------------------------- /notebooks/textbook/Shors_Algorithm.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Shor's Algorithm\n", 8 | "\n", 9 | "This example provides an implementation of the Shor's algorithm using the Amazon Braket SDK. Shor's algorithm is used to find prime factors of an integer. On a quantum computer, Shor's algorithm runs in polynomial time and is almost exponentially faster than the most efficient known classical factoring algorithm. The efficiency of Shor's algorithm is due to the efficiency of the Quantum Fourier transform, Quantum Phase estimation and modular exponentiation by repeated squarings. In this notebook, you implement the Shor's algorithm in code using the Amazon Braket SDK and run a simple example of factoring 15." 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "# References \n", 17 | "\n", 18 | "[1] Wikipedia: https://en.wikipedia.org/wiki/Shor%27s_algorithm\n", 19 | "\n", 20 | "[2] Nielsen, Michael A., Chuang, Isaac L. (2010). Quantum Computation and Quantum Information (2nd ed.). Cambridge: Cambridge University Press." 21 | ] 22 | }, 23 | { 24 | "cell_type": "code", 25 | "execution_count": 1, 26 | "metadata": {}, 27 | "outputs": [], 28 | "source": [ 29 | "from braket.devices import LocalSimulator\n", 30 | "from braket.aws import AwsDevice\n", 31 | "from braket.experimental.algorithms.shors.shors import (\n", 32 | " shors_algorithm,\n", 33 | " run_shors_algorithm,\n", 34 | " get_factors_from_results,\n", 35 | ")" 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "# Prepare inputs for Shor's Algorithm" 43 | ] 44 | }, 45 | { 46 | "cell_type": "code", 47 | "execution_count": 2, 48 | "metadata": {}, 49 | "outputs": [], 50 | "source": [ 51 | "N = 15 # Integer to factor (currently 15, 21, 35 work)\n", 52 | "a = 7 # Any integer that satisfies 1 < a < N and gcd(a, N) = 1.\n", 53 | "\n", 54 | "\n", 55 | "shors_circuit = shors_algorithm(N, a)" 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "# Run on a local simulator" 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": 3, 68 | "metadata": {}, 69 | "outputs": [ 70 | { 71 | "name": "stdout", 72 | "output_type": "stream", 73 | "text": [ 74 | "Number of Measured phases (s/r) : 4\n", 75 | "\n", 76 | "For phase 0.25 :\n", 77 | "Estimate for r is : 4\n", 78 | "Factors are : 3 and 5\n", 79 | "\n", 80 | "For phase 0.75 :\n", 81 | "Estimate for r is : 4\n", 82 | "Factors are : 3 and 5\n", 83 | "\n", 84 | "For phase 0.0 :\n", 85 | "Estimate for r is : 1\n", 86 | "Factors are : 15 and 1\n", 87 | "\n", 88 | "For phase 0.5 :\n", 89 | "Estimate for r is : 2\n", 90 | "Factors are : 3 and 1\n", 91 | "\n", 92 | "\n", 93 | "Non-trivial factors found are : {3, 5}\n" 94 | ] 95 | } 96 | ], 97 | "source": [ 98 | "local_simulator = LocalSimulator()\n", 99 | "\n", 100 | "output = run_shors_algorithm(shors_circuit, local_simulator)\n", 101 | "\n", 102 | "guessed_factors = get_factors_from_results(output, N, a)" 103 | ] 104 | }, 105 | { 106 | "cell_type": "markdown", 107 | "metadata": {}, 108 | "source": [ 109 | "# Run on a managed simulator\n", 110 | "\n" 111 | ] 112 | }, 113 | { 114 | "cell_type": "code", 115 | "execution_count": 4, 116 | "metadata": {}, 117 | "outputs": [], 118 | "source": [ 119 | "# Use Braket SDK Cost Tracking to estimate the cost to run this example\n", 120 | "from braket.tracking import Tracker\n", 121 | "\n", 122 | "tracker = Tracker().start()" 123 | ] 124 | }, 125 | { 126 | "cell_type": "code", 127 | "execution_count": 5, 128 | "metadata": {}, 129 | "outputs": [ 130 | { 131 | "name": "stdout", 132 | "output_type": "stream", 133 | "text": [ 134 | "Number of Measured phases (s/r) : 4\n", 135 | "\n", 136 | "For phase 0.25 :\n", 137 | "Estimate for r is : 4\n", 138 | "Factors are : 3 and 5\n", 139 | "\n", 140 | "For phase 0.75 :\n", 141 | "Estimate for r is : 4\n", 142 | "Factors are : 3 and 5\n", 143 | "\n", 144 | "For phase 0.0 :\n", 145 | "Estimate for r is : 1\n", 146 | "Factors are : 15 and 1\n", 147 | "\n", 148 | "For phase 0.5 :\n", 149 | "Estimate for r is : 2\n", 150 | "Factors are : 3 and 1\n", 151 | "\n", 152 | "\n", 153 | "Non-trivial factors found are : {3, 5}\n" 154 | ] 155 | } 156 | ], 157 | "source": [ 158 | "managed_sim = AwsDevice(\"arn:aws:braket:::device/quantum-simulator/amazon/sv1\")\n", 159 | "output = run_shors_algorithm(shors_circuit, managed_sim)\n", 160 | "\n", 161 | "guessed_factors = get_factors_from_results(output, N, a)" 162 | ] 163 | }, 164 | { 165 | "cell_type": "code", 166 | "execution_count": 6, 167 | "metadata": {}, 168 | "outputs": [ 169 | { 170 | "name": "stdout", 171 | "output_type": "stream", 172 | "text": [ 173 | "Task Summary\n", 174 | "{'arn:aws:braket:::device/quantum-simulator/amazon/sv1': {'shots': 1000, 'tasks': {'COMPLETED': 1}, 'execution_duration': datetime.timedelta(microseconds=15000), 'billed_execution_duration': datetime.timedelta(seconds=3)}} \n", 175 | "\n", 176 | "Estimated cost to run this example: 0.00 USD\n" 177 | ] 178 | } 179 | ], 180 | "source": [ 181 | "print(\"Task Summary\")\n", 182 | "print(f\"{tracker.quantum_tasks_statistics()} \\n\")\n", 183 | "print(\n", 184 | " f\"Estimated cost to run this example: {tracker.qpu_tasks_cost() + tracker.simulator_tasks_cost():.2f} USD\"\n", 185 | ")" 186 | ] 187 | }, 188 | { 189 | "cell_type": "markdown", 190 | "metadata": {}, 191 | "source": [ 192 | "Note: Charges shown are estimates based on your Amazon Braket simulator and quantum processing unit (QPU) task usage. Estimated charges shown may differ from your actual charges. Estimated charges do not factor in any discounts or credits, and you may experience additional charges based on your use of other services such as Amazon Elastic Compute Cloud (Amazon EC2)." 193 | ] 194 | } 195 | ], 196 | "metadata": { 197 | "kernelspec": { 198 | "display_name": "Python 3 (ipykernel)", 199 | "language": "python", 200 | "name": "python3" 201 | }, 202 | "language_info": { 203 | "codemirror_mode": { 204 | "name": "ipython", 205 | "version": 3 206 | }, 207 | "file_extension": ".py", 208 | "mimetype": "text/x-python", 209 | "name": "python", 210 | "nbconvert_exporter": "python", 211 | "pygments_lexer": "ipython3", 212 | "version": "3.10.8" 213 | }, 214 | "vscode": { 215 | "interpreter": { 216 | "hash": "5904cb9a2089448a2e1aeb5d493d227c9de33e591d7c07e4016fb81e71061a5d" 217 | } 218 | } 219 | }, 220 | "nbformat": 4, 221 | "nbformat_minor": 2 222 | } 223 | -------------------------------------------------------------------------------- /notebooks/textbook/Simons_Algorithm.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Simon's Algorithm\n", 8 | "\n", 9 | "This notebook demonstrates the execution of Simon's algorithm on Amazon Braket. \n", 10 | "\n", 11 | "\n", 12 | "Suppose we’re given a function $f:\\{0,1\\}^n \\rightarrow \\{0,1\\}^n$ that maps bit strings to bit strings along with the promise that\n", 13 | "$$\\forall x,y \\in \\{0,1\\}^n, \\quad f(x) = f(y) \\iff x=y\\oplus s,$$\n", 14 | "for some unknown $n$-bit string $s \\in \\{0,1\\}^n$, and where $\\oplus$ means bitwise addition modulo 2.\n", 15 | "\n", 16 | "The goal of Simon's problem is to determine if $f$ is one-to-one, or two-to-one, or equivalently to find the secret string $s$." 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "# References \n", 24 | "[1] Wikipedia: [Simon's Problem](https://en.wikipedia.org/wiki/Simon%27s_problem)\n", 25 | "\n", 26 | "[2] SIAM: [Original article](https://epubs.siam.org/doi/10.1137/S0097539796298637)\n", 27 | "\n", 28 | "[3] Amazon Braket's GitHub repository: [Detailed example notebook](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/advanced_circuits_algorithms/Simons_Algorithm/Simons_Algorithm.ipynb)" 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "metadata": {}, 34 | "source": [ 35 | "# Run on a local simulator" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": 1, 41 | "metadata": {}, 42 | "outputs": [], 43 | "source": [ 44 | "import numpy.random as npr\n", 45 | "from braket.aws import AwsDevice\n", 46 | "from braket.devices import LocalSimulator\n", 47 | "from braket.tracking import Tracker\n", 48 | "\n", 49 | "from braket.experimental.algorithms.simons import (\n", 50 | " get_simons_algorithm_results,\n", 51 | " run_simons_algorithm,\n", 52 | " simons_algorithm,\n", 53 | " simons_oracle,\n", 54 | ")\n", 55 | "\n", 56 | "tracker = Tracker().start()" 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": 2, 62 | "metadata": {}, 63 | "outputs": [], 64 | "source": [ 65 | "string_length = 5\n", 66 | "string = \"\".join(npr.choice([\"0\", \"1\"], size=string_length))\n", 67 | "\n", 68 | "oracle = simons_oracle(string)" 69 | ] 70 | }, 71 | { 72 | "cell_type": "markdown", 73 | "metadata": {}, 74 | "source": [ 75 | "# Print the circuits" 76 | ] 77 | }, 78 | { 79 | "cell_type": "code", 80 | "execution_count": 3, 81 | "metadata": {}, 82 | "outputs": [ 83 | { 84 | "name": "stdout", 85 | "output_type": "stream", 86 | "text": [ 87 | "T : │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │\n", 88 | " ┌───┐ ┌───┐ \n", 89 | "q0 : ─┤ H ├───●───────────────────────────┤ H ├─────────────────────────\n", 90 | " └───┘ │ └───┘ \n", 91 | " ┌───┐ │ ┌───┐ \n", 92 | "q1 : ─┤ H ├───┼─────●─────────────────────┤ H ├─────────────────────────\n", 93 | " └───┘ │ │ └───┘ \n", 94 | " ┌───┐ │ │ ┌───┐ \n", 95 | "q2 : ─┤ H ├───┼─────┼─────●─────────────────●───────────●─────●───┤ H ├─\n", 96 | " └───┘ │ │ │ │ │ │ └───┘ \n", 97 | " ┌───┐ │ │ │ │ ┌───┐ │ │ \n", 98 | "q3 : ─┤ H ├───┼─────┼─────┼─────●───────────┼───┤ H ├───┼─────┼─────────\n", 99 | " └───┘ │ │ │ │ │ └───┘ │ │ \n", 100 | " ┌───┐ │ │ │ │ │ ┌───┐ │ │ \n", 101 | "q4 : ─┤ H ├───┼─────┼─────┼─────┼─────●─────┼───┤ H ├───┼─────┼─────────\n", 102 | " └───┘ │ │ │ │ │ │ └───┘ │ │ \n", 103 | " ┌─┴─┐ │ │ │ │ │ │ │ \n", 104 | "q5 : ───────┤ X ├───┼─────┼─────┼─────┼─────┼───────────┼─────┼─────────\n", 105 | " └───┘ │ │ │ │ │ │ │ \n", 106 | " ┌─┴─┐ │ │ │ │ │ │ \n", 107 | "q6 : ─────────────┤ X ├───┼─────┼─────┼─────┼───────────┼─────┼─────────\n", 108 | " └───┘ │ │ │ │ │ │ \n", 109 | " ┌─┴─┐ │ │ ┌─┴─┐ │ │ \n", 110 | "q7 : ───────────────────┤ X ├───┼─────┼───┤ X ├─────────┼─────┼─────────\n", 111 | " └───┘ │ │ └───┘ │ │ \n", 112 | " ┌─┴─┐ │ ┌─┴─┐ │ \n", 113 | "q8 : ─────────────────────────┤ X ├───┼───────────────┤ X ├───┼─────────\n", 114 | " └───┘ │ └───┘ │ \n", 115 | " ┌─┴─┐ ┌─┴─┐ \n", 116 | "q9 : ───────────────────────────────┤ X ├───────────────────┤ X ├───────\n", 117 | " └───┘ └───┘ \n", 118 | "T : │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │\n" 119 | ] 120 | } 121 | ], 122 | "source": [ 123 | "print(simons_algorithm(oracle))" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": 4, 129 | "metadata": {}, 130 | "outputs": [], 131 | "source": [ 132 | "local_simulator = LocalSimulator()\n", 133 | "\n", 134 | "task = run_simons_algorithm(oracle, local_simulator)" 135 | ] 136 | }, 137 | { 138 | "cell_type": "code", 139 | "execution_count": 5, 140 | "metadata": {}, 141 | "outputs": [ 142 | { 143 | "name": "stdout", 144 | "output_type": "stream", 145 | "text": [ 146 | "Result string: 00111\n", 147 | "Secret string 00111\n" 148 | ] 149 | } 150 | ], 151 | "source": [ 152 | "processed_results = get_simons_algorithm_results(task)\n", 153 | "print(\"Secret string\", string)" 154 | ] 155 | }, 156 | { 157 | "cell_type": "markdown", 158 | "metadata": {}, 159 | "source": [ 160 | "# Run on a QPU\n", 161 | "\n", 162 | "Here we run Simon's algorithm on the Rigetti Ankaa-2 device." 163 | ] 164 | }, 165 | { 166 | "cell_type": "code", 167 | "execution_count": 6, 168 | "metadata": {}, 169 | "outputs": [], 170 | "source": [ 171 | "ankaa = AwsDevice(\"arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-2\")" 172 | ] 173 | }, 174 | { 175 | "cell_type": "code", 176 | "execution_count": 7, 177 | "metadata": {}, 178 | "outputs": [], 179 | "source": [ 180 | "# run this block to submit the circuit to QPU\n", 181 | "\n", 182 | "task = run_simons_algorithm(oracle, ankaa)" 183 | ] 184 | }, 185 | { 186 | "cell_type": "code", 187 | "execution_count": 8, 188 | "metadata": {}, 189 | "outputs": [ 190 | { 191 | "name": "stdout", 192 | "output_type": "stream", 193 | "text": [ 194 | "Result string: 00000\n", 195 | "Secret string 00111\n" 196 | ] 197 | } 198 | ], 199 | "source": [ 200 | "# run this block to process the results\n", 201 | "\n", 202 | "processed_results = get_simons_algorithm_results(task)\n", 203 | "print(\"Secret string\", string)" 204 | ] 205 | }, 206 | { 207 | "cell_type": "code", 208 | "execution_count": 9, 209 | "metadata": {}, 210 | "outputs": [ 211 | { 212 | "name": "stdout", 213 | "output_type": "stream", 214 | "text": [ 215 | "Task Summary\n", 216 | "{'arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-2': {'shots': 20, 'tasks': {'COMPLETED': 1}}} \n", 217 | "\n", 218 | "Estimated cost to run this example: 0.32 USD\n" 219 | ] 220 | } 221 | ], 222 | "source": [ 223 | "print(\"Task Summary\")\n", 224 | "print(f\"{tracker.quantum_tasks_statistics()} \\n\")\n", 225 | "print(\n", 226 | " f\"Estimated cost to run this example: {tracker.qpu_tasks_cost() + tracker.simulator_tasks_cost():.2f} USD\"\n", 227 | ")" 228 | ] 229 | }, 230 | { 231 | "cell_type": "markdown", 232 | "metadata": {}, 233 | "source": [ 234 | "Note: Charges shown are estimates based on your Amazon Braket simulator and quantum processing unit (QPU) task usage. Estimated charges shown may differ from your actual charges. Estimated charges do not factor in any discounts or credits, and you may experience additional charges based on your use of other services such as Amazon Elastic Compute Cloud (Amazon EC2)." 235 | ] 236 | } 237 | ], 238 | "metadata": { 239 | "kernelspec": { 240 | "display_name": "Python 3.9.6", 241 | "language": "python", 242 | "name": "python3" 243 | }, 244 | "language_info": { 245 | "codemirror_mode": { 246 | "name": "ipython", 247 | "version": 3 248 | }, 249 | "file_extension": ".py", 250 | "mimetype": "text/x-python", 251 | "name": "python", 252 | "nbconvert_exporter": "python", 253 | "pygments_lexer": "ipython3", 254 | "version": "3.10.10" 255 | }, 256 | "orig_nbformat": 4, 257 | "vscode": { 258 | "interpreter": { 259 | "hash": "625f119d7123628dd79ea6440058f262ec370c9df2643d17cf5bcd61bdf8ba1c" 260 | } 261 | } 262 | }, 263 | "nbformat": 4, 264 | "nbformat_minor": 2 265 | } 266 | -------------------------------------------------------------------------------- /notebooks/textbook/Template.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Algorithm Name\n", 8 | "[Brief description of algorithm]" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "metadata": {}, 14 | "source": [ 15 | "# References \n", 16 | "[1] references here with hyperlinkns" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "# [Optional] Print the circuits" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "# Run on a local simulator" 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": 1, 36 | "metadata": {}, 37 | "outputs": [], 38 | "source": [ 39 | "from braket.devices import LocalSimulator\n", 40 | "\n", 41 | "# Code here\n", 42 | "local_simulator = LocalSimulator()\n", 43 | "task = local_simulator.run(circuit, shots=100)\n", 44 | "result = task.result()" 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "metadata": {}, 50 | "source": [ 51 | "# [Optional] Run on a QPU or Managed Simulator\n", 52 | "\n", 53 | "[Include estimated price for running in USD using the [cost tracker](https://docs.aws.amazon.com/braket/latest/developerguide/braket-pricing.html#real-time-cost-tracking).]" 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": 2, 59 | "metadata": {}, 60 | "outputs": [], 61 | "source": [ 62 | "# Use Braket SDK Cost Tracking to estimate the cost to run this example\n", 63 | "from braket.tracking import Tracker\n", 64 | "\n", 65 | "tracker = Tracker().start()" 66 | ] 67 | }, 68 | { 69 | "cell_type": "code", 70 | "execution_count": 3, 71 | "metadata": {}, 72 | "outputs": [], 73 | "source": [ 74 | "from braket.aws import AwsDevice\n", 75 | "\n", 76 | "# Code here\n", 77 | "qpu = AwsDevice(\"quantum_arn\")\n", 78 | "task = qpu.run(circuit, shots=100)\n", 79 | "result = task.result()" 80 | ] 81 | }, 82 | { 83 | "cell_type": "markdown", 84 | "metadata": {}, 85 | "source": [ 86 | "[Print the final costs]" 87 | ] 88 | }, 89 | { 90 | "cell_type": "code", 91 | "execution_count": 4, 92 | "metadata": {}, 93 | "outputs": [], 94 | "source": [ 95 | "print(\"Task Summary\")\n", 96 | "print(f\"{tracker.quantum_tasks_statistics()} \\n\")\n", 97 | "print(\n", 98 | " f\"Estimated cost to run this example: {tracker.qpu_tasks_cost() + tracker.simulator_tasks_cost():.2f} USD\"\n", 99 | ")" 100 | ] 101 | }, 102 | { 103 | "cell_type": "markdown", 104 | "metadata": {}, 105 | "source": [ 106 | "Note: Charges shown are estimates based on your Amazon Braket simulator and quantum processing unit (QPU) task usage. Estimated charges shown may differ from your actual charges. Estimated charges do not factor in any discounts or credits, and you may experience additional charges based on your use of other services such as Amazon Elastic Compute Cloud (Amazon EC2)." 107 | ] 108 | } 109 | ], 110 | "metadata": { 111 | "kernelspec": { 112 | "display_name": "Python 3.9.5 64-bit ('braket')", 113 | "language": "python", 114 | "name": "python3" 115 | }, 116 | "language_info": { 117 | "codemirror_mode": { 118 | "name": "ipython", 119 | "version": 3 120 | }, 121 | "file_extension": ".py", 122 | "mimetype": "text/x-python", 123 | "name": "python", 124 | "nbconvert_exporter": "python", 125 | "pygments_lexer": "ipython3", 126 | "version": "3.9.5" 127 | }, 128 | "orig_nbformat": 4, 129 | "vscode": { 130 | "interpreter": { 131 | "hash": "5904cb9a2089448a2e1aeb5d493d227c9de33e591d7c07e4016fb81e71061a5d" 132 | } 133 | } 134 | }, 135 | "nbformat": 4, 136 | "nbformat_minor": 2 137 | } 138 | -------------------------------------------------------------------------------- /notebooks/textbook/notebook_plotting.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | import math 15 | from typing import Dict, List 16 | 17 | import matplotlib.pyplot as plt 18 | 19 | 20 | # deutsch jozsa 21 | # bernstein vazirani 22 | def plot_bitstrings( 23 | probabilities: Dict[str, float], 24 | title: str = None, 25 | ) -> None: 26 | """Plot the measurement results. 27 | 28 | Args: 29 | probabilities (Dict[str, float]): Measurement probabilities. 30 | title (str): Title for the plot. 31 | xlabel (str): xlabel for the plot. 32 | ylabel (str): ylabel for the plot. 33 | """ 34 | plt.bar(probabilities.keys(), probabilities.values()) 35 | plt.xlabel("bitstrings") 36 | plt.ylabel("probabilities") 37 | plt.title(title) 38 | plt.xticks(rotation=90) 39 | 40 | 41 | # grovers and quantum fourier transform 42 | def plot_bitstrings_formatted(probabilities: List[float]) -> None: 43 | """Format the bistring and plot the measure results. 44 | 45 | Args: 46 | probabilities (List[float]): Probabilities of measuring each bitstring. 47 | """ 48 | num_qubits = int(math.log2(len(probabilities))) 49 | format_bitstring = "{0:0" + str(num_qubits) + "b}" 50 | bitstring_keys = [format_bitstring.format(ii) for ii in range(2**num_qubits)] 51 | 52 | plt.bar(bitstring_keys, probabilities) 53 | plt.xlabel("bitstrings") 54 | plt.ylabel("probability") 55 | plt.xticks(rotation=90) 56 | -------------------------------------------------------------------------------- /notebooks/textbook/requirements.txt: -------------------------------------------------------------------------------- 1 | matplotlib<3.6 2 | jupyter 3 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.ruff] 2 | target-version = "py39" 3 | line-length = 100 4 | lint.isort = { known-first-party = [ 5 | "braket", 6 | ] } 7 | lint.extend-select = ["I", "PERF"] 8 | lint.preview = true 9 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [aliases] 2 | test=pytest 3 | 4 | [tool:pytest] 5 | xfail_strict = true 6 | # removing pytest-xdist config currently since that conflicts with -s option in --mock-level=LEAST tests 7 | addopts = --verbose -n auto --durations=0 --durations-min=1 8 | testpaths = test/unit_tests 9 | 10 | 11 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from setuptools import find_namespace_packages, setup 15 | 16 | with open("README.md", "r", encoding="utf8") as fh: 17 | long_description = fh.read() 18 | 19 | with open("src/braket/_algos/_version.py") as f: 20 | version = f.readlines()[-1].split()[-1].strip("\"'") 21 | 22 | setup( 23 | name="amazon-braket-algorithm-library", 24 | version=version, 25 | license="Apache License 2.0", 26 | python_requires=">= 3.9", 27 | packages=find_namespace_packages(where="src", exclude=("test",)), 28 | package_dir={"": "src"}, 29 | install_requires=[ 30 | "amazon-braket-sdk>=1.35.1", 31 | "numpy", 32 | "openfermion>=1.5.1", 33 | "pennylane>=0.29.1", 34 | "scipy>=1.5.2", 35 | # Sympy 1.13 produces different results for Simon's algorithm 36 | "sympy<1.13", 37 | ], 38 | extras_require={ 39 | "test": [ 40 | "pytest", 41 | "pytest-cov", 42 | "pytest-rerunfailures", 43 | "pytest-xdist", 44 | "ruff", 45 | "sphinx", 46 | "sphinx-rtd-theme", 47 | "sphinxcontrib-apidoc", 48 | "tox", 49 | ] 50 | }, 51 | include_package_data=True, 52 | url="https://github.com/amazon-braket/amazon-braket-algorithm-library", 53 | author="Amazon Web Services", 54 | description=( 55 | "An open source library of quantum computing algorithms implemented on Amazon Braket" 56 | ), 57 | long_description=long_description, 58 | long_description_content_type="text/markdown", 59 | keywords="Amazon AWS Quantum", 60 | classifiers=[ 61 | "Intended Audience :: Developers", 62 | "Natural Language :: English", 63 | "License :: OSI Approved :: Apache Software License", 64 | "Programming Language :: Python", 65 | ], 66 | ) 67 | -------------------------------------------------------------------------------- /src/braket/_algos/_version.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | """Version information. 15 | 16 | Version number (major.minor.patch[-label]) 17 | """ 18 | 19 | __version__ = "1.5.2.dev0" 20 | -------------------------------------------------------------------------------- /src/braket/experimental/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/bells_inequality/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from braket.experimental.algorithms.bells_inequality.bells_inequality import ( # noqa: F401 15 | bell_singlet, 16 | bell_singlet_rotated_basis, 17 | create_bell_inequality_circuits, 18 | get_bell_inequality_results, 19 | run_bell_inequality, 20 | ) 21 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/bells_inequality/bells_inequality.md: -------------------------------------------------------------------------------- 1 | Bell's Inequality shows that certain predictions of quantum mechanics cannot be explained by local interactions and inherent physical properties. Instead, we must give up the assumption of either (1) some pre-existing physical property that the measurement "uncovers" or (2) that the measurements are not causally related. 2 | 3 | 8 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/bells_inequality/bells_inequality.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | from collections import Counter 14 | from typing import List, Tuple 15 | 16 | import numpy as np 17 | 18 | from braket.circuits import Circuit, Qubit, circuit 19 | from braket.devices import Device 20 | from braket.tasks import QuantumTask 21 | 22 | 23 | def create_bell_inequality_circuits( 24 | qubit0: Qubit = 0, 25 | qubit1: Qubit = 1, 26 | angle_A: float = 0, 27 | angle_B: float = np.pi / 3, 28 | angle_C: float = 2 * np.pi / 3, 29 | ) -> List[Circuit]: 30 | """Create the three circuits for Bell's inequality. Default angles will give maximum violation 31 | of Bell's inequality. 32 | 33 | Args: 34 | qubit0 (Qubit): First qubit. 35 | qubit1 (Qubit): Second qubit. 36 | angle_A (float): Angle for the first measurement basis A. Defaults to 0. 37 | angle_B (float): Angle for the second measurement basis B. Defaults to np.pi/3. 38 | angle_C (float): Angle for the third measurement basis C. Defaults to 2*np.pi/3 to give 39 | maximum violation of Bell's inequality. 40 | 41 | Returns: 42 | List[Circuit]: Three circuits circAB, circAC, circBC. 43 | """ 44 | circAB = bell_singlet_rotated_basis(qubit0, qubit1, angle_A, angle_B) 45 | circAC = bell_singlet_rotated_basis(qubit0, qubit1, angle_A, angle_C) 46 | circBC = bell_singlet_rotated_basis(qubit0, qubit1, angle_B, angle_C) 47 | return [circAB, circAC, circBC] 48 | 49 | 50 | def run_bell_inequality( 51 | circuits: List[Circuit], 52 | device: Device, 53 | shots: int = 1_000, 54 | ) -> List[QuantumTask]: 55 | """Submit three Bell circuits to a device. 56 | 57 | Args: 58 | circuits (List[Circuit]): Three Bell inequality circuits in order circAB, circAC, circBC. 59 | device (Device): Quantum device or simulator. 60 | shots (int): Number of shots. Defaults to 1_000. 61 | 62 | Returns: 63 | List[QuantumTask]: List of quantum tasks. 64 | """ 65 | tasks = [device.run(circ, shots=shots) for circ in circuits] 66 | return tasks 67 | 68 | 69 | def get_bell_inequality_results( 70 | tasks: List[QuantumTask], verbose: bool = True 71 | ) -> Tuple[List[Counter], float, float, float]: 72 | """Return Bell task results after post-processing. 73 | 74 | Args: 75 | tasks (List[QuantumTask]): List of quantum tasks. 76 | verbose (bool): Controls printing of the inequality result. Defaults to True. 77 | 78 | Returns: 79 | Tuple[List[Counter], float, float, float]: results, pAB, pAC, pBC 80 | """ 81 | results = [task.result().result_types[0].value for task in tasks] # probability result type 82 | prob_same = np.array([d[0] + d[3] for d in results]) # 00 and 11 states 83 | prob_different = np.array([d[1] + d[2] for d in results]) # 01 and 10 states 84 | 85 | pAB, pAC, pBC = prob_same - prob_different # Bell probabilities 86 | bell_ineqality_lhs = np.abs(pAB - pAC) - pBC 87 | if verbose: 88 | print(f"P(a,b) = {pAB},P(a,c) = {pAC},P(b,c) = {pBC}") 89 | print(f"Bell's' inequality: {bell_ineqality_lhs} ≤ 1") 90 | if bell_ineqality_lhs > 1: 91 | print("Bell's inequality is violated!") 92 | else: 93 | print("Bell's inequality is not violated due to noise.") 94 | return results, pAB, pAC, pBC 95 | 96 | 97 | def bell_singlet_rotated_basis( 98 | qubit0: Qubit, qubit1: Qubit, rotation0: float, rotation1: float 99 | ) -> Circuit: 100 | """Prepare a Bell singlet state in a Rx-rotated meaurement basis. 101 | 102 | Args: 103 | qubit0 (Qubit): First qubit. 104 | qubit1 (Qubit): Second qubit. 105 | rotation0 (float): First qubit Rx rotation angle. 106 | rotation1 (float): Second qubit Rx rotation angle. 107 | 108 | Returns: 109 | Circuit: the Braket circuit that prepares the Bell circuit. 110 | """ 111 | circ = Circuit().bell_singlet(qubit0, qubit1) 112 | if rotation0 != 0: 113 | circ.rx(qubit0, rotation0) 114 | if rotation1 != 0: 115 | circ.rx(qubit1, rotation1) 116 | circ.probability() 117 | return circ 118 | 119 | 120 | @circuit.subroutine(register=True) 121 | def bell_singlet(qubit0: Qubit, qubit1: Qubit) -> Circuit: 122 | """Prepare a Bell singlet state. 123 | 124 | Args: 125 | qubit0 (Qubit): First qubit. 126 | qubit1 (Qubit): Second qubit. 127 | 128 | Returns: 129 | Circuit: the Braket circuit that prepares the Bell single state. 130 | """ 131 | return Circuit().x(qubit0).x(qubit1).h(qubit0).cnot(qubit0, qubit1) 132 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/bernstein_vazirani/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from braket.experimental.algorithms.bernstein_vazirani.bernstein_vazirani import ( # noqa: F401 15 | bernstein_vazirani_circuit, 16 | get_bernstein_vazirani_results, 17 | run_bernstein_vazirani, 18 | ) 19 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/bernstein_vazirani/bernstein_vazirani.md: -------------------------------------------------------------------------------- 1 | The Bernstein-Vazirani algorithm is the first quantum algorithm that solves a problem more efficiently than the best known classical algorithm. It was designed to create an oracle separation between BQP and BPP. 2 | 3 | 8 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/bernstein_vazirani/bernstein_vazirani.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | from typing import Dict 14 | 15 | import numpy as np 16 | 17 | from braket.circuits import Circuit 18 | from braket.devices import Device 19 | from braket.tasks import QuantumTask 20 | 21 | 22 | def bernstein_vazirani_circuit(hidden_string: str) -> Circuit: 23 | """Bernstein–Vazirani circuit on a hidden string. Creates a circuit that finds the hidden 24 | string in a single iteration, using number of qubits equal to the string length. 25 | 26 | Example: 27 | >>> circ = bernstein_vazirani_circuit("011") 28 | >>> print(circ) 29 | T : |0|1| 2 |3|4|Result Types| 30 | q0 : -H---C---H---Probability-- 31 | | | 32 | q1 : -H---|---C-H-Probability-- 33 | | | | 34 | q2 : -H-I-|-H-|---Probability-- 35 | | | 36 | q3 : -H-Z-X---X---------------- 37 | T : |0|1| 2 |3|4|Result Types| 38 | 39 | Args: 40 | hidden_string (str): Hidden bitstring. 41 | 42 | Returns: 43 | Circuit: Bernstein–Vazirani circuit 44 | """ 45 | num_qubits = len(hidden_string) 46 | 47 | bv_circuit = Circuit() 48 | bv_circuit.h(num_qubits) 49 | bv_circuit.z(num_qubits) 50 | bv_circuit.h(range(num_qubits)) 51 | 52 | for q in range(num_qubits): 53 | if hidden_string[q] == "0": 54 | bv_circuit.i(q) 55 | else: 56 | bv_circuit.cnot(q, num_qubits) 57 | 58 | bv_circuit.h(range(num_qubits)) 59 | 60 | bv_circuit.probability(range(num_qubits)) 61 | return bv_circuit 62 | 63 | 64 | def get_bernstein_vazirani_results(task: QuantumTask) -> Dict[str, float]: 65 | """Return the probabilities and corresponding bitstrings. 66 | 67 | Args: 68 | task (QuantumTask): Quantum task to process. 69 | 70 | Returns: 71 | Dict[str, float]: Results as a dictionary of bitstrings 72 | """ 73 | 74 | probabilities = task.result().result_types[0].value 75 | probabilities = np.round(probabilities, 10) # round off floating-point errors 76 | num_qubits = int(np.log2(len(probabilities))) 77 | binary_strings = [format(i, "b").zfill(num_qubits) for i in range(2**num_qubits)] 78 | return dict(zip(binary_strings, probabilities)) 79 | 80 | 81 | def run_bernstein_vazirani( 82 | circuit: Circuit, 83 | device: Device, 84 | shots: int = 1000, 85 | ) -> QuantumTask: 86 | """Function to run Bernstein Vazirani algorithm on a device. 87 | Args: 88 | circuit (Circuit): Bernstein Vazirani circuit 89 | device (Device): Braket device backend 90 | shots (int) : Number of measurement shots (default is 1000). 91 | Returns: 92 | QuantumTask: Task from running Quantum Phase Estimation 93 | """ 94 | 95 | return device.run(circuit, shots=shots) 96 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/chsh_inequality/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from braket.experimental.algorithms.chsh_inequality.chsh_inequality import ( # noqa: F401 15 | create_chsh_inequality_circuits, 16 | get_chsh_results, 17 | run_chsh_inequality, 18 | ) 19 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/chsh_inequality/chsh_inequality.md: -------------------------------------------------------------------------------- 1 | CHSH (Clauser, Horne, Shimony and Holt) inequality is one of the Bell's inequalities which shows that certain predictions of quantum mechanics cannot be explained by local interactions and inherent physical properties. Instead, we must give up the assumption of either (1) some pre-existing physical property that the measurement "uncovers" or (2) that the measurements are not causally related. 2 | 3 | 7 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/chsh_inequality/chsh_inequality.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from collections import Counter 15 | from typing import List, Tuple 16 | 17 | import numpy as np 18 | 19 | from braket.circuits import Circuit, Qubit 20 | from braket.devices import Device 21 | from braket.experimental.algorithms.bells_inequality.bells_inequality import ( 22 | bell_singlet_rotated_basis, 23 | ) 24 | from braket.tasks import QuantumTask 25 | 26 | 27 | def create_chsh_inequality_circuits( 28 | qubit0: Qubit = 0, 29 | qubit1: Qubit = 1, 30 | *, 31 | a1: float = np.pi / 2, 32 | a2: float = 0, 33 | b1: float = np.pi / 4, 34 | b2: float = 3 * np.pi / 4, 35 | ) -> List[Circuit]: 36 | """Create the four circuits for CHSH inequality. Default angles will give maximum violation of 37 | the inequality. 38 | 39 | Args: 40 | qubit0 (Qubit): First qubit. 41 | qubit1 (Qubit): Second qubit. 42 | a1 (float): First basis rotation angle for first qubit. 43 | a2 (float): Second basis rotation angle for first qubit. 44 | b1 (float): First basis rotation angle for second qubit. 45 | b2 (float): Second basis rotation angle for second qubit. 46 | 47 | Returns: 48 | List[Circuit]: List of quantum circuits. 49 | """ 50 | circ_a1b1 = bell_singlet_rotated_basis(qubit0, qubit1, a1, b1) 51 | circ_a1b2 = bell_singlet_rotated_basis(qubit0, qubit1, a1, b2) 52 | circ_a2b1 = bell_singlet_rotated_basis(qubit0, qubit1, a2, b1) 53 | circ_a2b2 = bell_singlet_rotated_basis(qubit0, qubit1, a2, b2) 54 | return [circ_a1b1, circ_a1b2, circ_a2b1, circ_a2b2] 55 | 56 | 57 | def run_chsh_inequality( 58 | circuits: List[Circuit], 59 | device: Device, 60 | shots: int = 1_000, 61 | ) -> List[QuantumTask]: 62 | """Submit four CHSH circuits to a device. 63 | 64 | Args: 65 | circuits (List[Circuit]): Four CHSH inequality circuits to run. 66 | device (Device): Quantum device or simulator. 67 | shots (int): Number of shots. Defaults to 1_000. 68 | 69 | Returns: 70 | List[QuantumTask]: List of quantum tasks. 71 | """ 72 | tasks = [device.run(circ, shots=shots) for circ in circuits] 73 | return tasks 74 | 75 | 76 | def get_chsh_results( 77 | tasks: List[QuantumTask], verbose: bool = True 78 | ) -> Tuple[float, List[Counter], float, float, float]: 79 | """Return CHSH task results after post-processing. 80 | 81 | Args: 82 | tasks (List[QuantumTask]): List of quantum tasks. 83 | verbose (bool): Controls printing of the inequality result. Defaults to True. 84 | 85 | Returns: 86 | Tuple[float, List[Counter], float, float, float]: The chsh_value, list of results, 87 | and the four probabilities: E_a1b1, E_a1b2, E_a2b1, E_a2b2. 88 | """ 89 | results = [task.result().result_types[0].value for task in tasks] 90 | 91 | prob_same = np.array([d[0] + d[3] for d in results]) # 00 and 11 states 92 | prob_different = np.array([d[1] + d[2] for d in results]) # 01 and 10 states 93 | 94 | E_a1b1, E_a1b2, E_a2b1, E_a2b2 = np.array(prob_same) - np.array(prob_different) 95 | 96 | chsh_value = E_a1b1 + E_a1b2 + E_a2b1 - E_a2b2 97 | 98 | if verbose: 99 | print(f"E_a1b1 = {E_a1b1}, E_a1b2 = {E_a1b2}, E_a2b1 = {E_a2b1}, E_a2b2 = {E_a2b2}") 100 | print(f"\nCHSH inequality: {np.abs(chsh_value)} ≤ 2") 101 | 102 | if np.abs(chsh_value) > 2: 103 | print("CHSH inequality is violated!") 104 | print( 105 | "Notice that the quantity may not be exactly as predicted by Quantum theory. " 106 | "This is may be due to finite shots or the effects of noise on the QPU." 107 | ) 108 | else: 109 | print("CHSH inequality is not violated.") 110 | return chsh_value, results, E_a1b1, E_a1b2, E_a2b1, E_a2b2 111 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/deutsch_jozsa/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from braket.experimental.algorithms.deutsch_jozsa.deutsch_jozsa import ( # noqa: F401 15 | balanced_oracle, 16 | constant_oracle, 17 | deutsch_jozsa_circuit, 18 | get_deutsch_jozsa_results, 19 | ) 20 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/deutsch_jozsa/deutsch_jozsa.md: -------------------------------------------------------------------------------- 1 | One of the first quantum algorithm’s developed by pioneers David Deutsch and Richard Jozsa. This algorithm showcases an efficient quantum solution to a problem that cannot be solved classically but instead can be solved using a quantum device. 2 | 3 | 8 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/deutsch_jozsa/deutsch_jozsa.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | from typing import Dict 14 | 15 | import numpy as np 16 | 17 | from braket.circuits import Circuit, circuit 18 | from braket.tasks import QuantumTask 19 | 20 | 21 | def constant_oracle(n_qubits: int) -> Circuit: 22 | """Constant oracle circuit. 23 | 24 | Args: 25 | n_qubits (int): Number of qubits. 26 | 27 | Returns: 28 | Circuit: Constant oracle circuit 29 | """ 30 | if n_qubits < 1: 31 | raise ValueError(f"Number of qubits must be greater than 0. Received {n_qubits}") 32 | 33 | circ = Circuit().i(range(n_qubits)) 34 | rand_output = np.random.randint(0, 2) 35 | if rand_output == 0: 36 | circ.i(n_qubits) 37 | else: 38 | circ.x(n_qubits) 39 | return circ 40 | 41 | 42 | def balanced_oracle(n_qubits: int) -> Circuit: 43 | """Balanced oracle circuit. 44 | 45 | Args: 46 | n_qubits (int): Number of qubits. 47 | 48 | Returns: 49 | Circuit: Balanced oracle circuit 50 | """ 51 | if n_qubits < 1: 52 | raise ValueError(f"Number of qubits must be greater than 0. Received {n_qubits}") 53 | 54 | # generate a random array of 0s and 1s to figure out where to place x gates 55 | random_num = np.random.randint(2, size=n_qubits) 56 | 57 | circ = Circuit() 58 | 59 | # place initial x gates 60 | for qubit in range(n_qubits): 61 | if random_num[qubit] == 1: 62 | circ.x(qubit) 63 | 64 | # place cnot gates 65 | for qubit in range(n_qubits): 66 | circ.cnot(control=qubit, target=n_qubits) 67 | 68 | # place final x gates 69 | for qubit in range(n_qubits): 70 | if random_num[qubit] == 1: 71 | circ.x(qubit) 72 | 73 | return circ 74 | 75 | 76 | def deutsch_jozsa_circuit(oracle: Circuit) -> Circuit: 77 | """Deutsch-Jozsa circuit. 78 | 79 | Args: 80 | oracle (Circuit): Constant or balanced oracle circuit. 81 | 82 | Returns: 83 | Circuit: The Deutsch-Jozsa circuit and result types. 84 | """ 85 | n_qubits = oracle.qubit_count - 1 86 | circ = Circuit() 87 | circ.deutsch_jozsa(oracle) 88 | circ.probability(range(n_qubits)) 89 | return circ 90 | 91 | 92 | @circuit.subroutine(register=True) 93 | def deutsch_jozsa(oracle: Circuit) -> Circuit: 94 | """Deutsch-Jozsa subroutine. 95 | 96 | Args: 97 | oracle (Circuit): Constant or balanced oracle circuit. 98 | 99 | Returns: 100 | Circuit: The Deutsch-Jozsa circuit. 101 | """ 102 | n_qubits = oracle.qubit_count - 1 103 | circ = Circuit() 104 | circ.h(range(n_qubits)) 105 | circ.x(n_qubits) 106 | circ.h(n_qubits) 107 | circ.add_circuit(oracle) 108 | circ.h(range(n_qubits)) 109 | return circ 110 | 111 | 112 | def get_deutsch_jozsa_results(task: QuantumTask) -> Dict[str, float]: 113 | """Return the probabilities and corresponding bitstrings. 114 | 115 | Args: 116 | task (QuantumTask): Quantum task to process. 117 | 118 | Returns: 119 | Dict[str, float]: Results as a dictionary of bitstrings 120 | """ 121 | probabilities = task.result().result_types[0].value 122 | probabilities = np.round(probabilities, 10) # round off floating-point errors 123 | num_qubits = int(np.log2(len(probabilities))) 124 | binary_strings = [format(i, "b").zfill(num_qubits) for i in range(2**num_qubits)] 125 | return dict(zip(binary_strings, probabilities)) 126 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/grovers_search/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from braket.experimental.algorithms.grovers_search.grovers_search import ( # noqa: F401 15 | build_oracle, 16 | grovers_search, 17 | ) 18 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/grovers_search/grovers_search.md: -------------------------------------------------------------------------------- 1 | Grover's algorithm is arguably one of the canonical quantum algorithms that kick-started the field of quantum computing. In the future, it could possibly serve as a hallmark application of quantum computing. Grover's algorithm allows us to find a particular register in an unordered database with N entries in just O(sqrt(N)) steps, compared to the best classical algorithm taking on average N/2 steps, thereby providing a quadratic speedup. For large databases (with a large number of entries, N), a quadratic speedup can provide a significant advantage. For a database with one million entries, a quantum computer running Grover's algorithm would need about 1000 runs, while a classical computer would need, on average, 500,000 runs. 2 | 3 | 8 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/grovers_search/grovers_search.py: -------------------------------------------------------------------------------- 1 | from typing import Tuple 2 | 3 | from braket.circuits import Circuit, circuit 4 | 5 | 6 | def grovers_search( 7 | oracle: Circuit, n_qubits: int, n_reps: int = 1, decompose_ccnot: bool = False 8 | ) -> Circuit: 9 | """Generate Grover's circuit for a target solution and oracle. 10 | 11 | Args: 12 | oracle (Circuit): Oracle circuit for a solution. 13 | n_qubits (int): Number of data qubits. 14 | n_reps (int): Number of repititions for amplification. Defaults to 1. 15 | decompose_ccnot (bool): To decompose CCNOT (Toffoli) gate in the circuit. 16 | 17 | Returns: 18 | Circuit: Grover's circuit 19 | """ 20 | grover_circ = Circuit().h(range(n_qubits)) 21 | for _ in range(n_reps): 22 | grover_circ.add(oracle) 23 | amplification = amplify(n_qubits, decompose_ccnot) 24 | grover_circ.add(amplification) 25 | grover_circ.probability(range(n_qubits)) 26 | return grover_circ 27 | 28 | 29 | def build_oracle(solution: str, decompose_ccnot: bool = False) -> Circuit: 30 | """Oracle circuit of a given solution. 31 | 32 | Args: 33 | solution (str): Target solution (e.g., '010') 34 | decompose_ccnot (bool): Whether to decompose CCNOT (Toffoli) gate in the circuit. 35 | 36 | Returns: 37 | Circuit: Oracle circuit 38 | """ 39 | x_idx = [i for i, s in enumerate(solution) if s == "0"] 40 | 41 | circ = Circuit() 42 | n_qubit = len(solution) 43 | mcz = multi_control_z(n_qubit, decompose_ccnot) 44 | circ.x(x_idx).add_circuit(mcz).x(x_idx) 45 | return circ 46 | 47 | 48 | def amplify(n_qubits: int, decompose_ccnot: bool) -> Circuit: 49 | """Perform a single iteration of amplitude amplification. 50 | 51 | Args: 52 | n_qubits (int): Number of data qubits. 53 | decompose_ccnot (bool): Whether to decompose CCNOT (Toffoli) gate in the circuit. 54 | 55 | Returns: 56 | Circuit: Amplification circuit. 57 | """ 58 | oracle = build_oracle(n_qubits * "0", decompose_ccnot) 59 | circ = Circuit() 60 | circ.h(range(n_qubits)) 61 | circ.add_circuit(oracle) 62 | circ.h(range(n_qubits)) 63 | return circ 64 | 65 | 66 | @circuit.subroutine(register=True) 67 | def ccnot_decomposed(control_1: int, control_2: int, target: int) -> Circuit: 68 | """Build CCNOT (Toffoli gate) from H, CNOT, T, Ti. 69 | 70 | Args: 71 | control_1 (int): control qubit 1 of CCNot gate 72 | control_2 (int): control qubit 2 of CCNot gate 73 | target (int): target qubit of CCNot gate 74 | 75 | Returns: 76 | Circuit: CCNot circuit. 77 | """ 78 | qubit_0, qubit_1 = control_1, control_2 79 | circ = Circuit() 80 | circ.h(target) 81 | circ.cnot(qubit_1, target) 82 | circ.ti(target) 83 | circ.cnot(qubit_0, target) 84 | circ.t(target) 85 | circ.cnot(qubit_1, target) 86 | circ.ti(target) 87 | circ.cnot(qubit_0, target) 88 | circ.t(target) 89 | circ.h(target) 90 | circ.t(qubit_1) 91 | circ.cnot(qubit_0, qubit_1) 92 | circ.t(qubit_0) 93 | circ.ti(qubit_1) 94 | circ.cnot(qubit_0, qubit_1) 95 | return circ 96 | 97 | 98 | def multi_control_not_constructor( 99 | n_qubit: int, 100 | decompose_ccnot: bool, 101 | is_outermost_call: bool = True, 102 | ) -> Tuple[Circuit, int]: 103 | """Recursive constructor of a multi-contol Not circuit (generalized Toffoli gate). 104 | Ref: https://arxiv.org/abs/1904.01671 105 | 106 | Args: 107 | n_qubit (int): Number of qubits. 108 | decompose_ccnot (bool): To decompose CCNOT (Toffoli) gate in the circuit. 109 | is_outermost_call (bool): Whether the call is the outermost call from external functions. 110 | 111 | Returns: 112 | Tuple[Circuit, int]: the multi-contol Not circuit and the number of ancilla in the circuit 113 | """ 114 | if n_qubit == 1: 115 | n_ancilla = 1 116 | circ = Circuit().cnot(0, 1) 117 | return circ, n_ancilla 118 | elif n_qubit == 2: 119 | n_ancilla = 1 120 | if decompose_ccnot: 121 | circ = Circuit().ccnot_decomposed(0, 1, 2) 122 | else: 123 | circ = Circuit().ccnot(0, 1, 2) 124 | return circ, n_ancilla 125 | else: 126 | n_ancilla = 0 127 | nq1 = n_qubit // 2 128 | nq2 = n_qubit - nq1 129 | 130 | circ1, na1 = multi_control_not_constructor(nq1, decompose_ccnot, is_outermost_call=False) 131 | circ2, na2 = multi_control_not_constructor(nq2, decompose_ccnot, is_outermost_call=False) 132 | 133 | circ = Circuit() 134 | 135 | qd1 = list(range(nq1)) 136 | qa1 = list(range(n_qubit + n_ancilla, n_qubit + n_ancilla + na1)) 137 | circ.add_circuit(circ1, target=qd1 + qa1) 138 | n_ancilla += na1 139 | 140 | qd2 = list(range(nq1, nq1 + nq2)) 141 | qa2 = list(range(n_qubit + n_ancilla, n_qubit + n_ancilla + na2)) 142 | circ.add_circuit(circ2, target=qd2 + qa2) 143 | n_ancilla += na2 144 | 145 | q0, q1, q2 = qa1[-1], qa2[-1], n_qubit + n_ancilla 146 | if decompose_ccnot: 147 | circ.ccnot_decomposed(q0, q1, q2) 148 | else: 149 | circ.ccnot(q0, q1, q2) 150 | n_ancilla += 1 151 | 152 | if is_outermost_call: 153 | circ.add_circuit(circ2.adjoint(), target=qd2 + qa2) 154 | circ.add_circuit(circ1.adjoint(), target=qd1 + qa1) 155 | 156 | return circ, n_ancilla 157 | 158 | 159 | def multi_control_not(n_qubit: int, decompose_ccnot: bool) -> Circuit: 160 | """Multi-control Not circuit. 161 | 162 | Args: 163 | n_qubit (int): Number of qubits. 164 | decompose_ccnot (bool): To decompose CCNOT (Toffoli) gate in the circuit. 165 | 166 | Returns: 167 | Circuit: multi-contol Not circuit 168 | """ 169 | mcx_circ, _ = multi_control_not_constructor(n_qubit, decompose_ccnot, is_outermost_call=True) 170 | return mcx_circ 171 | 172 | 173 | def multi_control_z(n_qubit: int, decompose_ccnot: bool) -> Circuit: 174 | """Multi-control Z circuit. 175 | 176 | Args: 177 | n_qubit (int): Number of qubits. 178 | decompose_ccnot (bool): To decompose CCNOT (Toffoli) gate in the circuit. 179 | 180 | Returns: 181 | Circuit: multi-contol Z circuit 182 | """ 183 | mcz_circ = multi_control_not(n_qubit, decompose_ccnot) 184 | z_target = mcz_circ.qubit_count - 1 185 | 186 | circ = Circuit() 187 | circ.x(z_target).h(z_target).add_circuit(mcz_circ).h(z_target).x(z_target) 188 | 189 | return circ 190 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/qc_qmc/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/quantum_approximate_optimization/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from braket.experimental.algorithms.quantum_approximate_optimization.quantum_approximate_optimization import ( # noqa: F401,E501 15 | cost_function, 16 | qaoa, 17 | run_qaoa_circuit, 18 | ) 19 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/quantum_approximate_optimization/quantum_approximate_optimization.md: -------------------------------------------------------------------------------- 1 | The Quantum Approximate Optimization Algorithm (QAOA) belongs to the class of hybrid quantum algorithms (leveraging both classical as well as quantum compute), that are widely believed to be the working horse for the current NISQ (noisy intermediate-scale quantum) era. In this NISQ era QAOA is also an emerging approach for benchmarking quantum devices and is a prime candidate for demonstrating a practical quantum speed-up on near-term NISQ device. 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/quantum_approximate_optimization/quantum_approximate_optimization.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | 15 | from typing import List 16 | 17 | import numpy as np 18 | 19 | from braket.circuits import Circuit, FreeParameter, Observable, circuit 20 | from braket.devices import Device 21 | from braket.tasks import QuantumTask 22 | 23 | 24 | def cost_function( 25 | values: np.ndarray, 26 | device: Device, 27 | circ: Circuit, 28 | coeffs: np.ndarray, 29 | cost_history: List[float], 30 | shots: int = 0, 31 | ) -> float: 32 | """Cost function and append to loss history list. 33 | 34 | Args: 35 | values (ndarray): Values for the parameters. 36 | device (Device): Braket device to run on. 37 | circ (Circuit): QAOA circuit to run. 38 | coeffs (ndarray): The coefficients of the cost Hamiltonian. 39 | cost_history (List[float]): History of cost evaluations. 40 | shots (int): Number of shots. Defaults to 0. 41 | 42 | Returns: 43 | float: The cost function value 44 | """ 45 | task = run_qaoa_circuit(device, circ, values, shots=shots) 46 | cost = get_cost(task, coeffs) 47 | cost_history.append(cost) 48 | return cost 49 | 50 | 51 | def run_qaoa_circuit(device: Device, circ: Circuit, values: np.ndarray, shots: int) -> QuantumTask: 52 | """Evaluate a QAOA circuit with parameters=values. 53 | 54 | Args: 55 | device (Device): Braket device to run on. 56 | circ (Circuit): QAOA circuit to run. 57 | values (np.ndarray): Values for the parameters. 58 | shots (int): Number of shots. 59 | 60 | Returns: 61 | QuantumTask: The Braket task to run. 62 | """ 63 | fixed_circuit = circ.make_bound_circuit( 64 | dict(zip(np.array(list(circ.parameters), dtype=str), values)) 65 | ) 66 | task = device.run(fixed_circuit, shots=shots) 67 | return task 68 | 69 | 70 | def get_cost(task: QuantumTask, coeffs: np.ndarray) -> float: 71 | """Evaluate the cost function from a QAOA task. 72 | 73 | Args: 74 | task (QuantumTask): QAOA task. 75 | coeffs (np.ndarray): The coefficients of the cost Hamiltonian. 76 | 77 | Returns: 78 | float: Loss function value. 79 | """ 80 | exp_vals = task.result().result_types 81 | cost = sum(c * s.value for c, s in zip(coeffs, exp_vals)) 82 | return cost 83 | 84 | 85 | def qaoa(n_qubits: int, n_layers: int, ising: np.ndarray) -> Circuit: 86 | """QAOA template. 87 | 88 | Args: 89 | n_qubits (int): Number of qubits 90 | n_layers (int): Number of layers. Defaults to 1. 91 | ising (ndarray): Ising interaction matrix. 92 | 93 | Returns: 94 | Circuit: The parameteric QAOA Circuit 95 | """ 96 | 97 | gammas = [FreeParameter(f"gamma_{p}") for p in range(n_layers)] 98 | betas = [FreeParameter(f"beta_{p}") for p in range(n_layers)] 99 | 100 | circ = Circuit() 101 | circ.h(range(n_qubits)) # prepare |+> state 102 | for gamma, beta in zip(gammas, betas): 103 | circ.cost_layer(gamma, ising) 104 | circ.driver_layer(beta, n_qubits) 105 | 106 | # add Result types 107 | idx = ising.nonzero() 108 | for qubit_pair in zip(idx[0], idx[1]): 109 | # get interaction strength from Ising matrix 110 | circ.expectation(observable=Observable.Z() @ Observable.Z(), target=qubit_pair) 111 | return circ 112 | 113 | 114 | @circuit.subroutine(register=True) 115 | def driver_layer(beta: float, n_qubits: int) -> Circuit: 116 | """Returns circuit for driver Hamiltonian U(Hb, beta). 117 | 118 | Args: 119 | beta (float): Rotation angle to apply parameterized rotation around x 120 | n_qubits (int): number of qubits to apply rx gate 121 | 122 | Returns: 123 | Circuit: Circuit object that implements evolution with driver Hamiltonian 124 | """ 125 | return Circuit().rx(range(n_qubits), 2 * beta) 126 | 127 | 128 | @circuit.subroutine(register=True) 129 | def cost_layer( 130 | gamma: float, 131 | ising: np.ndarray, 132 | ) -> Circuit: 133 | """Returns circuit for evolution with cost Hamiltonian. 134 | 135 | Args: 136 | gamma (float): Rotation angle to apply parameterized rotation around z 137 | ising (np.ndarray): Ising matrix 138 | 139 | Returns: 140 | Circuit: Circuit for evolution with cost Hamiltonian 141 | """ 142 | circ = Circuit() 143 | # get all non-zero entries (edges) from Ising matrix 144 | idx = ising.nonzero() 145 | edges = list(zip(idx[0], idx[1])) 146 | # apply ZZ gate for every edge (with corresponding interaction strength) 147 | for qubit_pair in edges: 148 | # get interaction strength from Ising matrix 149 | interaction_strength = ising[qubit_pair[0], qubit_pair[1]] 150 | circ.decomposed_zz_gate(qubit_pair[0], qubit_pair[1], gamma * interaction_strength) 151 | return circ 152 | 153 | 154 | @circuit.subroutine(register=True) 155 | def decomposed_zz_gate(qubit0: int, qubit1: int, gamma: float) -> Circuit: 156 | """ 157 | Return a circuit implementing :math:`exp(-i * \\gamma * Z_i * Z_j)` using CNOT gates 158 | if ZZ not supported. 159 | 160 | Args: 161 | qubit0 (int): Index value for the controlling qubit for CNOT gate 162 | qubit1 (int): Index value for the target qubit for CNOT gate 163 | gamma (float): Rotation angle to apply parameterized rotation around z 164 | 165 | Returns: 166 | Circuit: Circuit object that implements ZZ gate using CNOT gates 167 | """ 168 | circ_zz = Circuit() 169 | circ_zz.cnot(qubit0, qubit1).rz(qubit1, gamma).cnot(qubit0, qubit1) 170 | return circ_zz 171 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/quantum_circuit_born_machine/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from braket.experimental.algorithms.quantum_circuit_born_machine.qcbm import ( # noqa F401 15 | QCBM, 16 | mmd_loss, 17 | ) 18 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/quantum_circuit_born_machine/qcbm.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | 15 | from typing import List, Tuple 16 | 17 | import numpy as np 18 | 19 | from braket.circuits import Circuit, FreeParameter, circuit 20 | from braket.devices import Device 21 | 22 | 23 | class QCBM: 24 | """Quantum circuit Born machine. 25 | 26 | Example: n_layers = 1, n_qubits = 2 27 | :: 28 | T : | 0 | 1 | 2 |3|4|Result Types| 29 | 30 | q0 : -Rx(0.667)-Rz(0.783)-Rx(0.257)-C-X-Probability-- 31 | | | | 32 | q1 : -Rx(0.549)-Rz(0.878)-Rx(0.913)-X-C-Probability-- 33 | 34 | T : | 0 | 1 | 2 |3|4|Result Types| 35 | """ 36 | 37 | def __init__( 38 | self, 39 | device: Device, 40 | n_qubits: int, 41 | n_layers: int, 42 | target_probabilities: np.ndarray, 43 | shots: int = 10_000, 44 | ): 45 | """Quantum circuit Born machine. 46 | 47 | Consists of `n_layers`, where each layer is a rotation layer (rx, rz, rx) 48 | followed by an entangling layer of cnot gates. 49 | 50 | Args: 51 | device (Device): Amazon Braket device to use 52 | n_qubits (int): Number of qubits 53 | n_layers (int): Number of layers 54 | target_probabilities (ndarray): Target probabilities. 55 | shots (int): Number of shots. Defaults to 10_000. 56 | """ 57 | if n_qubits <= 1: 58 | raise ValueError("Number of qubits must be greater than 1.") 59 | self.device = device 60 | self.n_qubits = n_qubits 61 | self.n_layers = n_layers 62 | self.neighbors = [(i, (i + 1) % n_qubits) for i in range(n_qubits - 1)] 63 | self.target_probs = target_probabilities 64 | self.shots = shots 65 | self.parameters = [ 66 | [ 67 | [FreeParameter(f"theta_{layer}_{qubit}_{i}") for i in range(3)] 68 | for qubit in range(n_qubits) 69 | ] 70 | for layer in range(n_layers) 71 | ] 72 | self.parametric_circuit = self._create_circuit() 73 | 74 | def _create_circuit(self) -> Circuit: 75 | """Creates a QCBM circuit, and returns the probabilities. 76 | 77 | Returns: 78 | Circuit: Circuit with parameters fixed to `params`. 79 | """ 80 | circ = Circuit() 81 | circ.qcbm_layers(self.neighbors, self.parameters) 82 | circ.probability() 83 | return circ 84 | 85 | def get_probabilities(self, values: np.ndarray) -> np.ndarray: 86 | """Run and get probability results. 87 | 88 | Args: 89 | values (np.ndarray): Values for free parameters. 90 | 91 | Returns: 92 | np.ndarray: Probabilities vector. 93 | """ 94 | qcbm_original_circuit = self.bound_circuit(values) 95 | task = self.device.run(qcbm_original_circuit, shots=self.shots) 96 | qcbm_probs = task.result().values[0] 97 | return qcbm_probs 98 | 99 | def bound_circuit(self, values: np.ndarray) -> np.ndarray: 100 | """Get probabilities from the current parameters. 101 | 102 | Args: 103 | values (ndarray): Parameters for QCBM. 104 | 105 | Returns: 106 | ndarray: Probabilities. 107 | """ 108 | # Need to flatten parameters and also parameter. 109 | flat_values = values.flatten() 110 | flat_parameters = np.array(self.parameters, dtype=str).flatten() 111 | bound_values = dict(zip(flat_parameters, flat_values)) 112 | circ = self.parametric_circuit.make_bound_circuit(bound_values) 113 | return circ 114 | 115 | def gradient(self, params: np.ndarray) -> np.ndarray: 116 | """Gradient for QCBM via: 117 | 118 | Liu, Jin-Guo, and Lei Wang. 119 | “Differentiable Learning of Quantum Circuit Born Machine.” 120 | Physical Review A 98, no. 6 (December 19, 2018): 062324. 121 | https://doi.org/10.1103/PhysRevA.98.062324. 122 | 123 | Args: 124 | params (ndarray): Parameters for the rotation gates in the QCBM 125 | 126 | Returns: 127 | ndarray: Gradient vector 128 | """ 129 | 130 | qcbm_probs = self.get_probabilities(params) 131 | 132 | shift = np.ones_like(params) * np.pi / 2 133 | shifted_params = np.stack([params + np.diag(shift), params - np.diag(shift)]).reshape( 134 | 2 * len(params), len(params) 135 | ) 136 | 137 | probs = [self.get_probabilities(p) for p in shifted_params] 138 | probs = np.array(probs).reshape(2, len(params), 2**self.n_qubits) 139 | 140 | grad = np.zeros(len(params)) 141 | for i in range(len(params)): 142 | grad_pos = _compute_kernel(qcbm_probs, probs[0][i]) - _compute_kernel( 143 | qcbm_probs, probs[1][i] 144 | ) 145 | grad_neg = _compute_kernel(self.target_probs, probs[0][i]) - _compute_kernel( 146 | self.target_probs, probs[1][i] 147 | ) 148 | grad[i] = grad_pos - grad_neg 149 | return grad 150 | 151 | 152 | def _compute_kernel(px: np.ndarray, py: np.ndarray, sigma_list: List[float] = [0.1, 1]) -> float: 153 | r"""Gaussian radial basis function (RBF) kernel. 154 | 155 | .. math:: 156 | K(x, y) = sum_\sigma exp(-|x-y|^2/(2\sigma^2 )) 157 | 158 | Args: 159 | px (ndarray): Probability distribution 160 | py (ndarray): Target probability distribution 161 | sigma_list (List[float]): Standard deviations of distribution. Defaults to [0.1, 1]. 162 | 163 | Returns: 164 | float: Value of the Gaussian RBF function for kernel(px, py). 165 | """ 166 | x = np.arange(len(px)) 167 | y = np.arange(len(py)) 168 | K = sum(np.exp(-(np.abs(x[:, None] - y[None, :]) ** 2) / (2 * s**2)) for s in sigma_list) 169 | kernel = px @ K @ py 170 | return kernel 171 | 172 | 173 | def mmd_loss(px: np.ndarray, py: np.ndarray, sigma_list: List[float] = [0.1, 1]) -> float: 174 | r"""Maximum Mean Discrepancy loss (MMD). 175 | 176 | MMD determines if two distributions are equal by looking at the difference between 177 | their means in feature space. 178 | 179 | .. math:: 180 | MMD(x, y) = | \sum_{j=1}^N \phi(y_j) - \sum_{i=1}^N \phi(x_i) |_2^2 181 | 182 | With a RBF kernel, we apply the kernel trick to expand MMD to 183 | 184 | .. math:: 185 | MMD(x, y) = \sum_{j=1}^N \sum_{j'=1}^N k(y_j, y_{j'}) 186 | + \sum_{i=1}^N \sum_{i'=1}^N k(x_i, x_{i'}) 187 | - 2 \sum_{j=1}^N \sum_{i=1}^N k(y_j, x_i) 188 | 189 | For the RBF kernel, MMD is zero if and only if the distributions are identical. 190 | 191 | Args: 192 | px (ndarray): Probability distribution 193 | py (ndarray): Target probability distribution 194 | sigma_list (List[float]): Standard deviations of distribution. Defaults to [0.1, 1]. 195 | 196 | Returns: 197 | float: Value of the MMD loss 198 | """ 199 | 200 | mmd_xx = _compute_kernel(px, px, sigma_list) 201 | mmd_yy = _compute_kernel(py, py, sigma_list) 202 | mmd_xy = _compute_kernel(px, py, sigma_list) 203 | return mmd_xx + mmd_yy - 2 * mmd_xy 204 | 205 | 206 | @circuit.subroutine(register=True) 207 | def qcbm_layers( 208 | neighbors: List[Tuple[int, int]], parameters: List[List[List[FreeParameter]]] 209 | ) -> Circuit: 210 | """QCBM layers. 211 | 212 | Args: 213 | neighbors (List[Tuple[int,int]]): List of qubit pairs. 214 | parameters (List[List[List[FreeParameter]]]): List of FreeParameters. First index is 215 | n_layers, second is n_qubits, and third is [0,1,2] 216 | 217 | Returns: 218 | Circuit: QCBM circuit. 219 | """ 220 | n_layers = len(parameters) 221 | circ = Circuit() 222 | circ.rotation_layer(parameters[0]) 223 | for L in range(1, n_layers): 224 | circ.entangler(neighbors) 225 | circ.rotation_layer(parameters[L]) 226 | circ.entangler(neighbors) 227 | return circ 228 | 229 | 230 | @circuit.subroutine(register=True) 231 | def entangler(neighbors: List[Tuple[int, int]]) -> Circuit: 232 | """Add CNot gates to circuit. 233 | 234 | Args: 235 | neighbors (List[Tuple[int,int]]): Neighbors for CNots to connect 236 | 237 | Returns: 238 | Circuit: CNot entangling layer 239 | """ 240 | circ = Circuit() 241 | for i, j in neighbors: 242 | circ.cnot(i, j) 243 | return circ 244 | 245 | 246 | @circuit.subroutine(register=True) 247 | def rotation_layer(parameters: List[List[FreeParameter]]) -> Circuit: 248 | """Add rotation layers to circuit. 249 | 250 | Args: 251 | parameters (List[List[FreeParameter]]): Parameters for rotation layers. 252 | 253 | Returns: 254 | Circuit: Rotation layer 255 | """ 256 | circ = Circuit() 257 | n_qubits = len(parameters) 258 | for n in range(n_qubits): 259 | circ.rx(n, parameters[n][0]) 260 | circ.rz(n, parameters[n][1]) 261 | circ.rx(n, parameters[n][2]) 262 | return circ 263 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/quantum_circuit_born_machine/quantum_circuit_born_machine.md: -------------------------------------------------------------------------------- 1 | The quantum circuit Born machine (QCBM) is a variational quantum algorithm used for generative modeling. The QCBM encodes a target probability distribution into the parameters of rotation gates and entangling operations in a quantum circuit. The QCBM allows sampling from a high-dimension distribution according to the Born rule. 2 | 3 | 8 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/quantum_fourier_transform/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from braket.experimental.algorithms.quantum_fourier_transform import ( # noqa: F401 15 | quantum_fourier_transform, 16 | ) 17 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/quantum_fourier_transform/quantum_fourier_transform.md: -------------------------------------------------------------------------------- 1 | The Quantum Fourier Transform (QFT) is an important subroutine to many quantum algorithms, most famously Shor's algorithm for factoring and the quantum phase estimation (QPE) algorithm for estimating the eigenvalues of a unitary operator. The QFT can be performed efficiently on a quantum computer, using only single-qubit Hadamard gates and two-qubit controlled phase shift gates, where is the number of qubits. We first review the basics of the quantum Fourier transform, and its relation to the discrete (classical) Fourier transform. 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/quantum_fourier_transform/quantum_fourier_transform.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | # Quantum Fourier Transform: Amazon Braket Algorithm Library 15 | 16 | import math 17 | 18 | from braket.circuits import Circuit, circuit 19 | from braket.circuits.qubit_set import QubitSetInput 20 | from braket.devices.device import Device 21 | from braket.tasks.gate_model_quantum_task_result import GateModelQuantumTaskResult 22 | 23 | 24 | def quantum_fourier_transform_circuit(num_qubits: int) -> Circuit: 25 | """Construct a circuit object corresponding to the Quantum Fourier Transform (QFT) 26 | algorithm, applied to the argument qubits. Does not use recursion to generate the QFT. 27 | 28 | Args: 29 | num_qubits (int): number of qubits on which to apply the QFT 30 | 31 | Returns: 32 | Circuit: qft circuit 33 | """ 34 | 35 | qft_circ = Circuit() 36 | qubits = list(range(num_qubits)) 37 | 38 | for k in range(num_qubits): 39 | # First add a Hadamard gate 40 | qft_circ.h(qubits[k]) 41 | 42 | # Then apply the controlled rotations, with weights (angles) defined by the distance 43 | # to the control qubit. Start on the qubit after qubit k, and iterate until the end. 44 | # When num_qubits==1, this loop does not run. 45 | for j in range(1, num_qubits - k): 46 | angle = 2 * math.pi / (2 ** (j + 1)) 47 | qft_circ.cphaseshift(qubits[k + j], qubits[k], angle) 48 | 49 | # Then add SWAP gates to reverse the order of the qubits: 50 | for i in range(math.floor(num_qubits / 2)): 51 | qft_circ.swap(qubits[i], qubits[-i - 1]) 52 | 53 | return qft_circ 54 | 55 | 56 | @circuit.subroutine(register=True) 57 | def qft(qubits: QubitSetInput) -> Circuit: 58 | """Add qft circuit to an existing circuit. 59 | 60 | Args: 61 | qubits (QubitSetInput): The list of qubits labels on which to apply the QFT 62 | 63 | Returns: 64 | Circuit: qft circuit 65 | """ 66 | qubit_mapping = {i: q for i, q in enumerate(qubits)} 67 | return Circuit().add_circuit( 68 | quantum_fourier_transform_circuit(len(qubits)), target_mapping=qubit_mapping 69 | ) 70 | 71 | 72 | def inverse_quantum_fourier_transform_circuit(num_qubits: int) -> Circuit: 73 | """Construct a circuit object corresponding to the inverse Quantum Fourier Transform (QFT) 74 | algorithm, applied to the argument qubits. Does not use recursion to generate the circuit. 75 | 76 | Args: 77 | num_qubits (int): number of qubits on which to apply the inverse QFT 78 | 79 | Returns: 80 | Circuit: inverse qft circuit 81 | """ 82 | # instantiate circuit object 83 | qft_circ = Circuit() 84 | qubits = list(range(num_qubits)) 85 | 86 | # First add SWAP gates to reverse the order of the qubits: 87 | for i in range(math.floor(num_qubits / 2)): 88 | qft_circ.swap(qubits[i], qubits[-i - 1]) 89 | 90 | # Start on the last qubit and work to the first. 91 | for k in reversed(range(num_qubits)): 92 | # Apply the controlled rotations, with weights (angles) defined by the distance 93 | # to the control qubit. # These angles are the negative of the angle used in the QFT. 94 | # Start on the last qubit and iterate until the qubit after k. 95 | # When num_qubits==1, this loop does not run. 96 | for j in reversed(range(1, num_qubits - k)): 97 | angle = -2 * math.pi / (2 ** (j + 1)) 98 | qft_circ.cphaseshift(qubits[k + j], qubits[k], angle) 99 | 100 | # Then add a Hadamard gate 101 | qft_circ.h(qubits[k]) 102 | 103 | return qft_circ 104 | 105 | 106 | @circuit.subroutine(register=True) 107 | def iqft(qubits: QubitSetInput) -> Circuit: 108 | """Add inverse qft circuit to an existing circuit. 109 | 110 | Args: 111 | qubits (QubitSetInput): The list of qubits labels on which to apply the IQFT 112 | 113 | Returns: 114 | Circuit: inverse qft circuit 115 | """ 116 | qubit_mapping = {i: q for i, q in enumerate(qubits)} 117 | return Circuit().add_circuit( 118 | inverse_quantum_fourier_transform_circuit(len(qubits)), target_mapping=qubit_mapping 119 | ) 120 | 121 | 122 | def run_quantum_fourier_transform( 123 | qubits: QubitSetInput, 124 | n_shots: int, 125 | device: Device, 126 | state_prep_circ: Circuit = Circuit(), 127 | analysis_circ: Circuit = Circuit(), 128 | inverse: bool = False, 129 | ) -> GateModelQuantumTaskResult: 130 | """Execute QFT algorithm and returns results. 131 | 132 | Args: 133 | qubits (QubitSetInput): qubit indices 134 | n_shots (int): number of shots 135 | device (Device): The requested device (default: LocalSimulator) 136 | state_prep_circ (Circuit): circuit to be run before qft 137 | analysis_circ (Circuit): circuit to be run after qft 138 | inverse (bool): do the inverse qft 139 | 140 | Returns: 141 | GateModelQuantumTaskResult: circuit execution result 142 | 143 | """ 144 | circuit = Circuit() + state_prep_circ 145 | 146 | if inverse: 147 | circuit = circuit.iqft(qubits) 148 | else: 149 | circuit = circuit.qft(qubits) 150 | 151 | circuit = circuit + analysis_circ 152 | circuit.probability() 153 | task = device.run(circuit, shots=n_shots) 154 | 155 | return task 156 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/quantum_phase_estimation/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from braket.experimental.algorithms.quantum_phase_estimation.quantum_phase_estimation import ( # noqa: F401,E501 15 | get_quantum_phase_estimation_results, 16 | quantum_phase_estimation_circuit, 17 | run_quantum_phase_estimation, 18 | ) 19 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/quantum_phase_estimation/quantum_phase_estimation.md: -------------------------------------------------------------------------------- 1 | The Quantum Phase Estimation algorithm is designed to estimate the eigenvalues of a unitary operator. It is a very important subroutine to many quantum algorithms, most famously Shor's algorithm for factoring and the HHL algorithm (named after the physicists Harrow, Hassidim and Lloyd) for solving linear systems of equations on a quantum computer. Moreover, eigenvalue problems can be found across many disciplines and application areas, including (for example) principal component analysis (PCA) as used in machine learning or the solution of differential equations as relevant across mathematics, physics, engineering and chemistry. 2 | 3 | 8 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/quantum_walk/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from braket.experimental.algorithms.quantum_walk.quantum_walk import ( # noqa: F401 15 | qft_conditional_add_1, 16 | quantum_walk, 17 | run_quantum_walk, 18 | ) 19 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/quantum_walk/quantum_walk.md: -------------------------------------------------------------------------------- 1 | The quantum walk is very similar to the classical walk, where a walker observes a random process, such as flipping a coin, followed by deciding its next step conditioned on the outcome of the random process. For quantum walker, it observes a quantum process instead, and the subsequent steps are superpositions of the possible steps that a classical walker would take. 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/quantum_walk/quantum_walk.py: -------------------------------------------------------------------------------- 1 | from typing import Any, Dict 2 | 3 | import numpy as np 4 | 5 | from braket.circuits import Circuit 6 | from braket.devices import Device 7 | 8 | 9 | def qft(num_qubits: int, inverse: bool = False) -> Circuit: 10 | """Creates the quantum Fourier transform circuit and its inverse. 11 | 12 | Args: 13 | num_qubits (int): Number of qubits in the circuit 14 | inverse (bool): If true return the inverse of the circuit. Default is False 15 | 16 | Returns: 17 | Circuit: Circuit object that implements the quantum Fourier transform or its inverse 18 | """ 19 | 20 | qc = Circuit() 21 | N = num_qubits - 1 22 | 23 | if not inverse: 24 | qc.h(N) 25 | for n in range(1, N + 1): 26 | qc.cphaseshift(N - n, N, 2 * np.pi / 2 ** (n + 1)) 27 | 28 | for i in range(1, N): 29 | qc.h(N - i) 30 | for n in range(1, N - i + 1): 31 | qc.cphaseshift(N - (n + i), N - i, 2 * np.pi / 2 ** (n + 1)) 32 | qc.h(0) 33 | 34 | else: # The inverse of the quantum Fourier transform 35 | qc.h(0) 36 | for i in range(N - 1, 0, -1): 37 | for n in range(N - i, 0, -1): 38 | qc.cphaseshift(N - (n + i), N - i, -2 * np.pi / 2 ** (n + 1)) 39 | qc.h(N - i) 40 | 41 | for n in range(N, 0, -1): 42 | qc.cphaseshift(N - n, N, -2 * np.pi / 2 ** (n + 1)) 43 | 44 | qc.h(N) 45 | 46 | return qc 47 | 48 | 49 | def qft_conditional_add_1(num_qubits: int) -> Circuit: 50 | """Creates the quantum circuit that conditionally add +1 or -1 using: 51 | 52 | 1) The first qubit to control if add 1 or subtract 1: when the first qubit is 0, we add 1 from 53 | the number, and when the first qubit is 1, we subtract 1 from the number. 54 | 55 | 2) The second register with `num_qubits` qubits to save the result. 56 | 57 | Args: 58 | num_qubits (int): Number of qubits that saves the result. 59 | 60 | Returns: 61 | Circuit: Circuit object that implements the circuit that conditionally add +1 or -1. 62 | """ 63 | 64 | qc = Circuit() 65 | qc.add(qft(num_qubits), target=range(1, num_qubits + 1)) 66 | 67 | # add \pm 1 with control phase gates 68 | for i in range(num_qubits): 69 | qc.cphaseshift01(control=0, target=num_qubits - i, angle=2 * np.pi / 2 ** (num_qubits - i)) 70 | qc.cphaseshift(control=0, target=num_qubits - i, angle=-2 * np.pi / 2 ** (num_qubits - i)) 71 | 72 | qc.add(qft(num_qubits, inverse=True), target=range(1, num_qubits + 1)) 73 | 74 | return qc 75 | 76 | 77 | def quantum_walk(n_nodes: int, num_steps: int = 1) -> Circuit: 78 | """Creates the quantum random walk circuit. 79 | 80 | Args: 81 | n_nodes (int): The number of nodes in the graph 82 | num_steps (int): The number of steps for the quantum walk. Default is 1 83 | 84 | Returns: 85 | Circuit: Circuit object that implements the quantum random walk algorithm 86 | 87 | Raises: 88 | If `np.log2(n_nodes)` is not an integer, a value error will be raised. 89 | """ 90 | 91 | n = np.log2(n_nodes) # number of qubits for the graph 92 | 93 | if float(n).is_integer(): 94 | n = int(n) 95 | else: 96 | raise ValueError("The number of nodes has to be 2^n for integer n.") 97 | 98 | qc = Circuit() 99 | for _ in range(num_steps): 100 | qc.h(0) 101 | qc.add_circuit(qft_conditional_add_1(n)) 102 | qc.x(0) # flip the coin after the shift 103 | 104 | return qc 105 | 106 | 107 | def run_quantum_walk( 108 | circ: Circuit, 109 | device: Device, 110 | shots: int = 1000, 111 | ) -> Dict[str, Any]: 112 | """Function to run quantum random walk algorithm and return measurement counts. 113 | 114 | Args: 115 | circ (Circuit): Quantum random walk circuit 116 | device (Device): Braket device backend 117 | shots (int): Number of measurement shots. Default is 1000. 118 | 119 | Returns: 120 | Dict[str, Any]: measurements and results from running Quantum Phase Estimation 121 | """ 122 | 123 | # Add results_types 124 | circ.probability() 125 | 126 | # get total number of qubits 127 | num_qubits = circ.qubit_count 128 | 129 | # Run the circuit with all zeros input. 130 | # The query_circuit subcircuit generates the desired input from all zeros. 131 | task = device.run(circ, shots=shots) 132 | 133 | result = task.result() 134 | 135 | # get output probabilities (see result_types above) 136 | probs_values = result.values[0] 137 | 138 | # get measurement results 139 | measurement_counts = result.measurement_counts 140 | 141 | format_bitstring = "{0:0" + str(num_qubits) + "b}" 142 | bitstring_keys = [format_bitstring.format(ii) for ii in range(2**num_qubits)] 143 | 144 | quantum_walk_measurement_counts = {} 145 | for key, val in measurement_counts.items(): 146 | node = int(key[1:][::-1], 2) 147 | if node in quantum_walk_measurement_counts: 148 | quantum_walk_measurement_counts[node] += val / shots 149 | else: 150 | quantum_walk_measurement_counts[node] = val / shots 151 | 152 | output = { 153 | "circuit": circ, 154 | "task_metadata": result.task_metadata, 155 | "measurements": result.measurements, 156 | "measured_qubits": result.measured_qubits, 157 | "measurement_counts": measurement_counts, 158 | "measurement_probabilities": result.measurement_probabilities, 159 | "probs_values": probs_values, 160 | "bitstring_keys": bitstring_keys, 161 | "quantum_walk_measurement_counts": quantum_walk_measurement_counts, 162 | } 163 | 164 | return output 165 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/shors/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from braket.experimental.algorithms.shors.shors import ( # noqa: F401 15 | get_factors_from_results, 16 | run_shors_algorithm, 17 | shors_algorithm, 18 | ) 19 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/shors/shors.md: -------------------------------------------------------------------------------- 1 | Shor's algorithm is used to find prime factors of an integer. On a quantum computer, Shor's algorithm runs in polynomial time and is almost exponentially faster than the most efficient known classical factoring algorithm. 2 | 3 | 8 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/simons/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from braket.experimental.algorithms.simons.simons import ( # noqa: F401 15 | get_simons_algorithm_results, 16 | run_simons_algorithm, 17 | simons_algorithm, 18 | simons_oracle, 19 | ) 20 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/simons/simons.md: -------------------------------------------------------------------------------- 1 | Simon's algorithm solves the problem of given a function f:{0,1}^n→{0,1}^n that maps bit strings to bit strings. We’re also given the promise that the function f either maps each unique input to a unique output, or maps two distinct inputs to one unique output, without knowing which. This means that f is either one-to-one or two-to-one, and that we are given the promise there exists an unknown string s such that, for all input strings x, f(x)=f(x⊕s). When s is non-zero, the function is two-to-one as it maps exactly two inputs to every unique output. When s is the zero string, the function is one-to-one. 2 | 3 | 8 | -------------------------------------------------------------------------------- /src/braket/experimental/algorithms/simons/simons.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from collections import Counter 15 | from typing import Any, Dict, Optional, Tuple 16 | 17 | import numpy as np 18 | from sympy import Matrix 19 | 20 | from braket.circuits import Circuit 21 | from braket.devices import Device 22 | from braket.tasks import QuantumTask 23 | 24 | 25 | def simons_oracle(secret_string: str) -> Circuit: 26 | """Quantum circuit implementing a particular oracle for Simon's problem. 27 | 28 | In the quantum setting, we first copy the input register into some 29 | ancillary qubits: `|x>|0> -> |x>|x>`. 30 | 31 | We then perform the quantum analog of XOR, which means we apply an X gate 32 | to the kth qubit whenever the kth bit of `string` is 1. However, we only 33 | apply this X gate when the flag qubit is also `|1>`. Thus, our X gate becomes 34 | a CNOT gate between the flag qubit on the input register, and the kth qubit 35 | on the output. 36 | 37 | Args: 38 | secret_string (str): the secret string 39 | 40 | Returns: 41 | Circuit: Circuit object that implements the oracle 42 | """ 43 | # Find the index of the first 1 in secret_string, to be used as the flag bit 44 | flag_bit = secret_string.find("1") 45 | 46 | length_string = len(secret_string) 47 | 48 | circ = Circuit() 49 | # First copy the first n qubits, so that |x>|0> -> |x>|x> 50 | for i in range(length_string): 51 | circ.cnot(i, i + length_string) 52 | 53 | # If flag_bit=-1, secret_string is the all-zeros string, and we do nothing else. 54 | if flag_bit != -1: 55 | # Now apply the XOR with secret_string whenever the flag bit is 1. 56 | for index, bit_value in enumerate(secret_string): 57 | if bit_value not in ["0", "1"]: 58 | raise ValueError( 59 | "Incorrect char '" + bit_value + "' in the secret string:" + secret_string 60 | ) 61 | 62 | # XOR with secret_string whenever the flag bit is 1. 63 | # In terms of gates, XOR means we apply an X gate only 64 | # whenever the corresponding bit in secret_string is 1. 65 | # Applying this X only when the flag qubit is 1 means this is a CNOT gate. 66 | if bit_value == "1": 67 | circ.cnot(flag_bit, index + length_string) 68 | return circ 69 | 70 | 71 | def simons_algorithm(oracle: Circuit) -> Circuit: 72 | """Build the circuit associated with Simon's algorithm. 73 | 74 | Args: 75 | oracle (Circuit): The oracle encoding the secret string 76 | 77 | Returns: 78 | Circuit: circuit associated with Simon's algorithm 79 | """ 80 | nb_base_qubits = int(oracle.qubit_count / 2) 81 | return Circuit().h(range(nb_base_qubits)).add(oracle).h(range(nb_base_qubits)) 82 | 83 | 84 | def run_simons_algorithm( 85 | oracle: Circuit, device: Device, shots: Optional[int] = None 86 | ) -> QuantumTask: 87 | """Function to run Simon's algorithm and return the secret string. 88 | 89 | Args: 90 | oracle (Circuit): The oracle encoding the secret string 91 | device (Device): Braket device backend 92 | shots (Optional[int]) : Number of measurement shots (default is None). 93 | The default number of shots is set to twice the arity of the oracle. 94 | shots must be a strictly positive integer. 95 | 96 | Returns: 97 | QuantumTask: Task for Simon's algorithm. 98 | """ 99 | if shots is None: 100 | shots = 2 * oracle.qubit_count 101 | if shots <= 0: 102 | raise ValueError("shots must be a strictly positive integer.") 103 | 104 | circ = simons_algorithm(oracle) 105 | circ.probability() 106 | 107 | task = device.run(circ, shots=shots) 108 | 109 | return task 110 | 111 | 112 | def get_simons_algorithm_results(task: QuantumTask) -> Dict[str, Any]: 113 | """Get and print classically post-processed results from Simon's algorithm execution. 114 | 115 | Args: 116 | task (QuantumTask): Task for Simon's algorithm. 117 | 118 | Returns: 119 | Dict[str, Any]: Dict containing the secret string and marginalized output states 120 | """ 121 | 122 | task_result = task.result() 123 | 124 | results = { 125 | "measurements": task_result.measurements, 126 | "measured_qubits": task_result.measured_qubits, 127 | "measurement_counts": task_result.measurement_counts, 128 | "measurement_probabilities": task_result.measurement_probabilities, 129 | } 130 | result_string, traced_measurement_counts = _get_secret_string(results["measurement_counts"]) 131 | 132 | output = { 133 | "secret_string": result_string, 134 | "traced_measurement_counts": traced_measurement_counts, 135 | } 136 | 137 | print("Result string:", result_string) 138 | 139 | return output 140 | 141 | 142 | def _get_secret_string(measurement_counts: Counter) -> Tuple[str, Counter]: 143 | """Classical post-processing to recover the secret string. 144 | 145 | The measurement counter contains k bitstrings which correspond to k equations: 146 | z_k . s = 0 mod 2 147 | where k.j = k_1*j_1 + ... + k_n*j_n with + the XOR operator 148 | and s the secret string 149 | 150 | Args: 151 | measurement_counts (Counter): Counter with all measured bistrings 152 | 153 | Returns: 154 | Tuple[str, Counter]: the secret string and the marginalized output states 155 | """ 156 | nb_base_qubits = len(list(measurement_counts.keys())[0]) // 2 157 | 158 | traced_results = Counter() 159 | for bitstring, count in measurement_counts.items(): 160 | traced_results.update({bitstring[:nb_base_qubits]: count}) 161 | 162 | if len(traced_results.keys()) < nb_base_qubits: 163 | raise RuntimeError( 164 | "System will be underdetermined. Minimum " 165 | + str(nb_base_qubits) 166 | + " bistrings needed, but only " 167 | + str(len(traced_results.keys())) 168 | + " returned. Please rerun Simon's algorithm." 169 | ) 170 | bitstring_matrix = np.vstack([np.array([*key], dtype=int) for key in traced_results]).T 171 | nb_rows, nb_columns = bitstring_matrix.shape 172 | 173 | # Construct the augmented matrix 174 | augmented_matrix = Matrix(np.hstack([bitstring_matrix, np.eye(nb_rows, dtype=int)])) 175 | 176 | # Perform row reduction, working modulo 2. We use the iszerofunc property of rref 177 | # to perform the Gaussian elimination over the finite field. 178 | reduced_matrix = augmented_matrix.rref(iszerofunc=lambda x: x % 2 == 0) 179 | 180 | # Apply helper function to the matrix to treat fractions as modular inverse: 181 | final_reduced_matrix = reduced_matrix[0].applyfunc(lambda x: x.as_numer_denom()[0] % 2) 182 | 183 | # Extract the kernel of M from the remaining columns of the last row, when s is nonzero. 184 | if all(value == 0 for value in final_reduced_matrix[-1, :nb_columns]): 185 | result_string = "".join(str(e) for e in final_reduced_matrix[-1, nb_columns:]) 186 | else: # Otherwise, the sub-matrix will be full rank, so just set s=0...0 187 | result_string = "0" * nb_rows 188 | 189 | return result_string, traced_results 190 | -------------------------------------------------------------------------------- /src/braket/experimental/auxiliary_functions/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from .random_circuit import random_circuit # noqa: F401 15 | -------------------------------------------------------------------------------- /src/braket/experimental/auxiliary_functions/random_circuit/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from .random_circuit import random_circuit # noqa: F401 15 | -------------------------------------------------------------------------------- /src/braket/experimental/auxiliary_functions/random_circuit/random_circuit.md: -------------------------------------------------------------------------------- 1 | The `random_circuit` function generates a random quantum circuit using the Amazon Braket SDK. 2 | The function creates a diverse set of circuits that can be used for testing Braket SDK functionality and compiler benchmarking. 3 | 8 | -------------------------------------------------------------------------------- /src/braket/experimental/auxiliary_functions/random_circuit/random_circuit.py: -------------------------------------------------------------------------------- 1 | import inspect 2 | import math 3 | import random 4 | from typing import List, Optional 5 | 6 | from braket.circuits import Circuit, Gate, Instruction 7 | from braket.circuits.gates import CNot, H, S, T 8 | 9 | 10 | def random_circuit( 11 | num_qubits: int, 12 | num_gates: int, 13 | gate_set: Optional[List[Gate]] = None, 14 | seed: Optional[int] = None, 15 | ) -> Circuit: 16 | """ 17 | Generates a random quantum circuit. 18 | 19 | Args: 20 | num_qubits (int): Number of qubits in the circuit. 21 | num_gates (int): Number of instructions (gates) in the circuit. 22 | gate_set (Optional[List[Gate]]): List of basis gates for the random circuit 23 | (default is None). 24 | seed (Optional[int]): Random seed for reproducibility (default is None). 25 | 26 | Returns: 27 | Circuit: random quantum circuit. 28 | """ 29 | # Set the seed if provided 30 | if seed is not None: 31 | random.seed(seed) 32 | 33 | # Default gate_set (Clifford + T) if gate_set is None 34 | if not gate_set: 35 | gate_set = [CNot, S, T, H] 36 | 37 | instructions = [] 38 | for _ in range(num_gates): 39 | gate = random.choice(gate_set) 40 | gate_qubits = gate.fixed_qubit_count() 41 | 42 | # Select random qubits for the gate 43 | qubits = random.sample(range(num_qubits), gate_qubits) 44 | 45 | # Get the constructor's signature to determine required parameters 46 | init_signature = inspect.signature(gate.__init__) 47 | 48 | # Calculate the number of parameters (excluding 'self') 49 | num_params = len(init_signature.parameters) - 1 50 | 51 | # Generate random parameters for the gate in the range [0, 2*pi] 52 | params = [random.uniform(0, 2 * math.pi) for _ in range(num_params)] 53 | 54 | # Create the gate instance 55 | g = gate(*params) 56 | 57 | # Add the gate as an instruction 58 | instructions.append(Instruction(g, qubits)) 59 | 60 | # Create a circuit with the list of instructions 61 | circuit = Circuit().add(instructions) 62 | return circuit 63 | -------------------------------------------------------------------------------- /test/integ_tests/advanced_algorithms/Quantum_Principal_Component_Analysis_mocks.py: -------------------------------------------------------------------------------- 1 | def pre_run_inject(mock_utils): 2 | mocker = mock_utils.Mocker() 3 | mock_utils.mock_default_device_calls(mocker) 4 | mocker.set_task_result_return(mock_utils.read_file("quantum_pca_results.json", __file__)) 5 | 6 | 7 | def post_run(tb): 8 | pass 9 | -------------------------------------------------------------------------------- /test/integ_tests/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | def pytest_addoption(parser): 5 | parser.addoption( 6 | "--mock-level", 7 | action="store", 8 | default="ALL", 9 | help="ALL=mock everything, LEAST=mock least possible", 10 | ) 11 | 12 | 13 | @pytest.fixture 14 | def mock_level(request): 15 | return request.config.getoption("--mock-level") 16 | -------------------------------------------------------------------------------- /test/integ_tests/default_data/default_capabilities.json: -------------------------------------------------------------------------------- 1 | { 2 | "braketSchemaHeader": { 3 | "name": "braket.device_schema.rigetti.rigetti_device_capabilities", 4 | "version": "1" 5 | }, 6 | "service": { 7 | "executionWindows": [ 8 | { 9 | "executionDay": "Everyday", 10 | "windowStartHour": "11:00", 11 | "windowEndHour": "12:00" 12 | } 13 | ], 14 | "shotsRange": [1, 10] 15 | }, 16 | "action": { 17 | "braket.ir.jaqcd.program": { 18 | "actionType": "braket.ir.jaqcd.program", 19 | "version": ["1"], 20 | "supportedOperations": [ 21 | "amplitude_damping", 22 | "bit_flip", 23 | "ccnot", 24 | "cnot", 25 | "cphaseshift", 26 | "cphaseshift00", 27 | "cphaseshift01", 28 | "cphaseshift10", 29 | "cswap", 30 | "cy", 31 | "cz", 32 | "depolarizing", 33 | "pauli_channel", 34 | "generalized_amplitude_damping", 35 | "h", 36 | "i", 37 | "iswap", 38 | "kraus", 39 | "phase_flip", 40 | "phase_damping", 41 | "phaseshift", 42 | "pswap", 43 | "rx", 44 | "ry", 45 | "rz", 46 | "s", 47 | "si", 48 | "swap", 49 | "t", 50 | "ti", 51 | "two_qubit_dephasing", 52 | "two_qubit_depolarizing", 53 | "unitary", 54 | "v", 55 | "vi", 56 | "x", 57 | "xx", 58 | "xy", 59 | "y", 60 | "yy", 61 | "z", 62 | "zz" 63 | ] 64 | }, 65 | "braket.ir.openqasm.program": { 66 | "actionType": "braket.ir.openqasm.program", 67 | "version": ["1"], 68 | "supportedOperations": [ 69 | "amplitude_damping", 70 | "bit_flip", 71 | "ccnot", 72 | "cnot", 73 | "cphaseshift", 74 | "cphaseshift00", 75 | "cphaseshift01", 76 | "cphaseshift10", 77 | "cswap", 78 | "cy", 79 | "cz", 80 | "depolarizing", 81 | "pauli_channel", 82 | "generalized_amplitude_damping", 83 | "h", 84 | "i", 85 | "iswap", 86 | "kraus", 87 | "phase_flip", 88 | "phase_damping", 89 | "phaseshift", 90 | "pswap", 91 | "rx", 92 | "ry", 93 | "rz", 94 | "s", 95 | "si", 96 | "swap", 97 | "t", 98 | "ti", 99 | "two_qubit_dephasing", 100 | "two_qubit_depolarizing", 101 | "unitary", 102 | "v", 103 | "vi", 104 | "x", 105 | "xx", 106 | "xy", 107 | "y", 108 | "yy", 109 | "z", 110 | "zz" 111 | ], 112 | "supportedResultTypes": [ 113 | { 114 | "name": "Sample", 115 | "observables": ["x", "y", "z", "h", "i"], 116 | "minShots": 1, 117 | "maxShots": 1000 118 | }, 119 | { 120 | "name": "Expectation", 121 | "observables": ["x", "y", "z", "h", "i"], 122 | "minShots": 1, 123 | "maxShots": 1000 124 | }, 125 | { 126 | "name": "Variance", 127 | "observables": ["x", "y", "z", "h", "i"], 128 | "minShots": 1, 129 | "maxShots": 1000 130 | }, 131 | { 132 | "name": "Probability", 133 | "minShots": 1, 134 | "maxShots": 100000 135 | }, 136 | { 137 | "name": "Amplitude", 138 | "minShots": 0, 139 | "maxShots": 0 140 | } 141 | ] 142 | } 143 | }, 144 | "paradigm": { 145 | "qubitCount": 30, 146 | "nativeGateSet": ["ccnot", "cy"], 147 | "connectivity": { 148 | "fullyConnected": false, 149 | "connectivityGraph": { 150 | "1": ["2", "3"] 151 | } 152 | } 153 | }, 154 | "deviceParameters": {}, 155 | "provider": { 156 | "specs": { 157 | "1Q": { 158 | "0": { 159 | "T1": 2.766141842913683e-5, 160 | "T2": 1.2520845863383872e-5, 161 | "f1QRB": 0.9990014768242277, 162 | "f1QRB_std_err": 8.73150855778037e-5, 163 | "f1Q_simultaneous_RB": 0.9970022479211442, 164 | "f1Q_simultaneous_RB_std_err": 0.0003912205868794068, 165 | "fActiveReset": 0.9990000000000001, 166 | "fRO": 0.964 167 | } 168 | }, 169 | "2Q": { 170 | "0-1": { 171 | "fCPHASE": 0.8710661743452028, 172 | "fCPHASE_std_err": 0.007276963769977784, 173 | "fCZ": 0.8446295075190559, 174 | "fCZ_std_err": 0.009150823348255658, 175 | "fXY": 0.82638351218334, 176 | "fXY_std_err": 0.01638730580261261 177 | }, 178 | "10-11": { 179 | "fCPHASE": 0.8710661743452028, 180 | "fCPHASE_std_err": 0.007276963769977784, 181 | "fCZ": 0.8446295075190559, 182 | "fCZ_std_err": 0.009150823348255658, 183 | "fXY": 0.82638351218334, 184 | "fXY_std_err": 0.01638730580261261 185 | }, 186 | "10-17": { 187 | "fCPHASE": 0.8710661743452028, 188 | "fCPHASE_std_err": 0.007276963769977784, 189 | "fCZ": 0.8446295075190559, 190 | "fCZ_std_err": 0.009150823348255658, 191 | "fXY": 0.82638351218334, 192 | "fXY_std_err": 0.01638730580261261 193 | } 194 | } 195 | } 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /test/integ_tests/default_mocks/default_mocks.py: -------------------------------------------------------------------------------- 1 | def pre_run_inject(mock_utils): 2 | mocker = mock_utils.Mocker() 3 | mock_utils.mock_default_device_calls(mocker) 4 | 5 | 6 | def post_run(tb): 7 | pass 8 | -------------------------------------------------------------------------------- /test/integ_tests/record_utils.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | import boto3 4 | import braket.aws 5 | 6 | recording = True 7 | 8 | 9 | class BraketClientWrapper: 10 | def __init__(self, braket_client): 11 | self.__class__ = type( 12 | braket_client.__class__.__name__, (self.__class__, braket_client.__class__), {} 13 | ) 14 | self.__dict__ = braket_client.__dict__ 15 | self.braket_client = braket_client 16 | self.num_get_device_calls = 0 17 | self.num_create_task_calls = 0 18 | self.num_get_task_calls = 0 19 | 20 | def get_device(self, deviceArn): 21 | if recording: 22 | result = self.braket_client.get_device(deviceArn=deviceArn) 23 | with open(f"get_device_results_{self.num_get_device_calls}.json", "w") as f: 24 | json.dump(result, f, indent=2) 25 | else: 26 | with open(f"get_device_results_{self.num_get_device_calls}.json", "r") as f: 27 | result = json.load(f) 28 | self.num_get_device_calls += 1 29 | return result 30 | 31 | def create_quantum_task(self, **kwargs): 32 | if recording: 33 | result = self.braket_client.create_quantum_task(**kwargs) 34 | with open(f"create_task_results_{self.num_create_task_calls}.json", "w") as f: 35 | json.dump(result, f, indent=2) 36 | else: 37 | with open(f"create_task_results_{self.num_create_task_calls}.json", "r") as f: 38 | result = json.load(f) 39 | self.num_create_task_calls += 1 40 | return result 41 | 42 | def get_quantum_task(self, quantumTaskArn): 43 | if recording: 44 | result = self.braket_client.get_quantum_task(quantumTaskArn=quantumTaskArn) 45 | with open(f"get_task_results_{self.num_get_task_calls}.json", "w") as f: 46 | json.dump(result, f, indent=2, default=str) 47 | if result["status"] in braket.aws.aws_quantum_task.AwsQuantumTask.TERMINAL_STATES: 48 | # There is not need to record every time we poll. 49 | self.num_get_task_calls += 1 50 | else: 51 | with open(f"get_task_results_{self.num_get_task_calls}.json", "r") as f: 52 | result = json.load(f) 53 | self.num_get_task_calls += 1 54 | return result 55 | 56 | 57 | class Recorder(boto3.Session): 58 | def __init__(self, *args, **kwargs): 59 | super().__init__(*args, **kwargs) 60 | 61 | def client(self, *args, **kwargs): 62 | boto_client = super().client(*args, **kwargs) 63 | if ( 64 | args 65 | and args[0] == "braket" 66 | or kwargs 67 | and "service_name" in kwargs 68 | and kwargs["service_name"] == "braket" 69 | ): 70 | return BraketClientWrapper(boto_client) 71 | return boto_client 72 | 73 | 74 | real_retrieve_s3_object_body = braket.aws.aws_session.AwsSession.retrieve_s3_object_body 75 | num_s3_results = 0 76 | 77 | 78 | class AwsSessionWrapper: 79 | def retrieve_s3_object_body(self, s3_bucket, s3_object_key): 80 | global num_s3_results 81 | if recording: 82 | result = real_retrieve_s3_object_body(self, s3_bucket, s3_object_key) 83 | with open(f"from_s3_results_{num_s3_results}.json", "w") as f: 84 | json.dump(json.loads(result), f, indent=2) 85 | else: 86 | with open(f"from_s3_results_{num_s3_results}.json", "r") as f: 87 | result = f.read() 88 | num_s3_results += 1 89 | return result 90 | 91 | 92 | boto3.Session = Recorder 93 | braket.aws.aws_session.AwsSession.retrieve_s3_object_body = ( 94 | AwsSessionWrapper.retrieve_s3_object_body 95 | ) 96 | 97 | 98 | def record(): 99 | global recording 100 | recording = True 101 | 102 | 103 | def playback(): 104 | global recording 105 | recording = False 106 | -------------------------------------------------------------------------------- /test/integ_tests/requirements.txt: -------------------------------------------------------------------------------- 1 | amazon-braket-sdk 2 | amazon-braket-pennylane-plugin 3 | matplotlib 4 | pandas 5 | pennylane 6 | pytest 7 | testbook 8 | jupyter -------------------------------------------------------------------------------- /test/integ_tests/test_all_notebooks.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import os 3 | from importlib.machinery import SourceFileLoader 4 | 5 | import pytest 6 | from testbook import testbook 7 | 8 | # These notebooks have syntax or dependency issues that prevent them from being tested. 9 | EXCLUDED_NOTEBOOKS = [ 10 | # These notebooks have cells that have syntax errors or 11 | # need high processing power and lead to timeouts. 12 | "Quantum_Computing_Quantum_Monte_Carlo.ipynb", 13 | "Template.ipynb", 14 | ] 15 | 16 | logging.basicConfig(level=logging.INFO) 17 | logger = logging.getLogger(__name__) 18 | 19 | if "integ_tests" in os.getcwd(): 20 | os.chdir(os.path.abspath(os.path.join(os.getcwd(), os.pardir, os.pardir))) 21 | 22 | root_path = os.getcwd() 23 | examples_path = "notebooks" 24 | test_notebooks = [] 25 | 26 | for dir_, _, files in os.walk(examples_path): 27 | for file_name in files: 28 | if file_name.endswith(".ipynb") and ".ipynb_checkpoints" not in dir_: 29 | test_notebooks.append((dir_, file_name)) 30 | 31 | 32 | def get_mock_paths(notebook_dir, notebook_file): 33 | mock_file = notebook_file.replace(".ipynb", "_mocks.py") 34 | split_notebook_dir = notebook_dir.split(os.sep) 35 | path_to_root = os.path.abspath(os.path.join(*([".."] * (len(split_notebook_dir))))) 36 | mock_dir = os.path.join(*split_notebook_dir[1:]) 37 | path_to_mocks = os.path.join(path_to_root, "test", "integ_tests", mock_dir, mock_file).replace( 38 | "\\", "/" 39 | ) 40 | if not os.path.exists(path_to_mocks): 41 | path_to_mocks = os.path.abspath( 42 | os.path.join(path_to_root, "test", "integ_tests", "default_mocks", "default_mocks.py") 43 | ).replace("\\", "/") 44 | path_to_utils = os.path.abspath( 45 | os.path.join(path_to_root, "test", "integ_tests", "mock_utils.py") 46 | ).replace("\\", "/") 47 | return path_to_utils, path_to_mocks 48 | 49 | 50 | @pytest.mark.parametrize("notebook_dir, notebook_file", test_notebooks) 51 | def test_all_notebooks(notebook_dir, notebook_file, mock_level): 52 | if notebook_file in EXCLUDED_NOTEBOOKS: 53 | pytest.skip(f"Skipping Notebook: '{notebook_file}'") 54 | 55 | os.chdir(root_path) 56 | os.chdir(notebook_dir) 57 | path_to_utils, path_to_mocks = get_mock_paths(notebook_dir, notebook_file) 58 | with testbook(notebook_file, timeout=600) as tb: 59 | tb.inject( 60 | f""" 61 | from importlib.machinery import SourceFileLoader 62 | mock_utils = SourceFileLoader("notebook_mock_utils","{path_to_utils}").load_module() 63 | mock_utils.set_level("{mock_level}") 64 | test_mocks = SourceFileLoader("notebook_mocks","{path_to_mocks}").load_module() 65 | test_mocks.pre_run_inject(mock_utils) 66 | """, 67 | run=False, 68 | before=0, 69 | ) 70 | tb.execute() 71 | test_mocks = SourceFileLoader("notebook_mocks", path_to_mocks).load_module() 72 | test_mocks.post_run(tb) 73 | 74 | 75 | def test_record(): 76 | # Set the path here to record results. 77 | notebook_file_search = "" 78 | if not notebook_file_search: 79 | return 80 | for dir_, _, files in os.walk(examples_path): 81 | for file_name in files: 82 | if notebook_file_search in file_name: 83 | notebook_file = file_name 84 | notebook_dir = dir_ 85 | break 86 | if not notebook_file or not notebook_dir: 87 | pytest.skip(f"Notebook not found: '{notebook_file_search}'") 88 | os.chdir(root_path) 89 | os.chdir(notebook_dir) 90 | path_to_utils, path_to_mocks = get_mock_paths(notebook_dir, notebook_file) 91 | path_to_utils = path_to_utils.replace("mock_utils.py", "record_utils.py") 92 | with testbook(notebook_file, timeout=600) as tb: 93 | tb.inject( 94 | f""" 95 | from importlib.machinery import SourceFileLoader 96 | mock_utils = SourceFileLoader("notebook_mock_utils","{path_to_utils}").load_module() 97 | """, 98 | run=False, 99 | before=0, 100 | ) 101 | tb.execute() 102 | -------------------------------------------------------------------------------- /test/integ_tests/textbook/Grovers_Search_mocks.py: -------------------------------------------------------------------------------- 1 | def pre_run_inject(mock_utils): 2 | mocker = mock_utils.Mocker() 3 | mock_utils.mock_default_device_calls(mocker) 4 | mocker.set_task_result_return(mock_utils.read_file("grovers_results.json", __file__)) 5 | 6 | 7 | def post_run(tb): 8 | pass 9 | -------------------------------------------------------------------------------- /test/integ_tests/textbook/Quantum_Phase_Estimation_Algorithm_mocks.py: -------------------------------------------------------------------------------- 1 | def pre_run_inject(mock_utils): 2 | mocker = mock_utils.Mocker() 3 | mock_utils.mock_default_device_calls(mocker) 4 | mocker.set_task_result_return( 5 | mock_utils.read_file("quantum_phase_estimation_results.json", __file__) 6 | ) 7 | 8 | 9 | def post_run(tb): 10 | pass 11 | -------------------------------------------------------------------------------- /test/integ_tests/textbook/Quantum_Walk_mocks.py: -------------------------------------------------------------------------------- 1 | def pre_run_inject_2(mock_utils): 2 | pass 3 | 4 | 5 | def pre_run_inject(mock_utils): 6 | mocker = mock_utils.Mocker() 7 | mock_utils.mock_default_device_calls(mocker) 8 | res1 = mock_utils.read_file("0_quantum_walk.json", __file__) 9 | res2 = mock_utils.read_file("1_quantum_walk.json", __file__) 10 | res3 = mock_utils.read_file("2_quantum_walk.json", __file__) 11 | res4 = mock_utils.read_file("3_quantum_walk.json", __file__) 12 | effects = [] 13 | for i in range(3): 14 | effects.append(res1) 15 | for i in range(51): 16 | effects.append(res2) 17 | for i in range(20): 18 | effects.append(res3) 19 | for i in range(20): 20 | effects.append(res4) 21 | mocker.set_task_result_side_effect(effects) 22 | 23 | 24 | def post_run(tb): 25 | pass 26 | -------------------------------------------------------------------------------- /test/integ_tests/textbook/Shors_Algorithm_mocks.py: -------------------------------------------------------------------------------- 1 | def pre_run_inject(mock_utils): 2 | mocker = mock_utils.Mocker() 3 | mock_utils.mock_default_device_calls(mocker) 4 | mocker.set_task_result_return(mock_utils.read_file("shors_results.json", __file__)) 5 | 6 | 7 | def post_run(tb): 8 | pass 9 | -------------------------------------------------------------------------------- /test/integ_tests/textbook/Simons_Algorithm_mocks.py: -------------------------------------------------------------------------------- 1 | def pre_run_inject(mock_utils): 2 | mocker = mock_utils.Mocker() 3 | mock_utils.mock_default_device_calls(mocker) 4 | mocker.set_task_result_return(mock_utils.read_file("simons_results.json", __file__)) 5 | 6 | 7 | def post_run(tb): 8 | pass 9 | -------------------------------------------------------------------------------- /test/unit_tests/braket/experimental/algorithms/bells_inequality/test_bells_inequality.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | 15 | import math 16 | 17 | import numpy as np 18 | from braket.circuits import Circuit 19 | from braket.devices import LocalSimulator 20 | 21 | from braket.experimental.algorithms.bells_inequality import bell_singlet # noqa:F401 22 | from braket.experimental.algorithms.bells_inequality import ( 23 | bell_singlet_rotated_basis, 24 | create_bell_inequality_circuits, 25 | get_bell_inequality_results, 26 | run_bell_inequality, 27 | ) 28 | 29 | 30 | def test_singlet(): 31 | circ = Circuit().bell_singlet(0, 1) 32 | expected = Circuit().x(0).x(1).h(0).cnot(0, 1) 33 | assert circ == expected 34 | 35 | 36 | def test_singlet_rotated_zero(): 37 | circ = bell_singlet_rotated_basis(0, 1, 0, 0) 38 | expected = Circuit().x(0).x(1).h(0).cnot(0, 1).probability() 39 | assert circ == expected 40 | 41 | 42 | def test_singlet_rotated(): 43 | circ = bell_singlet_rotated_basis(0, 1, 0.5, 0.25) 44 | expected = Circuit().x(0).x(1).h(0).cnot(0, 1).rx(0, 0.5).rx(1, 0.25).probability() 45 | assert circ == expected 46 | 47 | 48 | def test_bell_inequality_not_verbose(): 49 | circs = create_bell_inequality_circuits(0, 1) 50 | assert len(circs) == 3 51 | tasks = run_bell_inequality(circs, LocalSimulator(), shots=0) 52 | results, pAB, pAC, pBC = get_bell_inequality_results(tasks, verbose=False) 53 | assert math.isclose(pAB, -0.5) 54 | assert math.isclose(pBC, -0.5) 55 | assert math.isclose(pAC, 0.5) 56 | assert len(results) == 3 57 | 58 | 59 | def test_bell_inequality_shots_0(): 60 | circs = create_bell_inequality_circuits(0, 1) 61 | assert len(circs) == 3 62 | tasks = run_bell_inequality(circs, LocalSimulator(), shots=0) 63 | results, pAB, pAC, pBC = get_bell_inequality_results(tasks) 64 | assert math.isclose(pAB, -0.5) 65 | assert math.isclose(pBC, -0.5) 66 | assert math.isclose(pAC, 0.5) 67 | assert len(results) == 3 68 | 69 | 70 | def test_bell_inequality_not_violated(): 71 | angle_A: float = 1 72 | angle_B: float = 2 * np.pi 73 | angle_C: float = np.pi / 3 74 | circs = create_bell_inequality_circuits(0, 1, angle_A, angle_B, angle_C) 75 | assert len(circs) == 3 76 | tasks = run_bell_inequality(circs, LocalSimulator(), shots=0) 77 | results, pAB, pAC, pBC = get_bell_inequality_results(tasks) 78 | assert len(results) == 3 79 | 80 | 81 | def test_bell_inequality(): 82 | circs = create_bell_inequality_circuits(0, 1) 83 | assert len(circs) == 3 84 | tasks = run_bell_inequality(circs, LocalSimulator(), shots=10) 85 | results, pAB, pAC, pBC = get_bell_inequality_results(tasks) 86 | assert len(tasks) == 3 87 | results, pAB, pAC, pBC = get_bell_inequality_results(tasks) 88 | assert len(results) == 3 89 | -------------------------------------------------------------------------------- /test/unit_tests/braket/experimental/algorithms/bernstein_varzirani/test_bernstien_vazirani.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | import numpy as np 15 | import pytest 16 | from braket.circuits import Circuit 17 | from braket.devices import LocalSimulator 18 | 19 | from braket.experimental.algorithms.bernstein_vazirani.bernstein_vazirani import ( 20 | bernstein_vazirani_circuit, 21 | get_bernstein_vazirani_results, 22 | run_bernstein_vazirani, 23 | ) 24 | 25 | 26 | def test_get_bernstein_vazirani(): 27 | bv_circuit = bernstein_vazirani_circuit("0") 28 | expected = Circuit().h(1).z(1).h(0).i(0).h(0).probability(0) 29 | print(bv_circuit) 30 | print() 31 | print(expected) 32 | assert bv_circuit == expected 33 | 34 | 35 | @pytest.mark.parametrize("hidden_string, shots", [("100", 0), ("11", 10), ("10111", 50)]) 36 | def test_get_bernstein_vazirani_results(hidden_string: str, shots: int): 37 | local_simulator = LocalSimulator() 38 | bv_circuit = bernstein_vazirani_circuit(hidden_string) 39 | task = run_bernstein_vazirani(bv_circuit, local_simulator, shots=shots) 40 | bv_result = get_bernstein_vazirani_results(task) 41 | assert np.isclose(bv_result[hidden_string], 1.0) 42 | -------------------------------------------------------------------------------- /test/unit_tests/braket/experimental/algorithms/chsh_inequality/test_chsh_inequality.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | 15 | import numpy as np 16 | from braket.devices import LocalSimulator 17 | 18 | from braket.experimental.algorithms.chsh_inequality import ( 19 | create_chsh_inequality_circuits, 20 | get_chsh_results, 21 | run_chsh_inequality, 22 | ) 23 | 24 | 25 | def test_chsh_reduces_to_bell(): 26 | circuits = create_chsh_inequality_circuits(0, 1, a1=(np.pi / 3), a2=0, b1=0, b2=(2 * np.pi / 3)) 27 | local_tasks = run_chsh_inequality(circuits, LocalSimulator(), shots=0) 28 | chsh_value, results, E_a1b1, E_a1b2, E_a2b1, E_a2b2 = get_chsh_results(local_tasks) 29 | assert np.isclose(E_a1b1, -0.5) 30 | assert np.isclose(E_a1b2, -0.5) 31 | assert np.isclose(E_a2b1, -1) 32 | assert np.isclose(E_a2b2, 0.5) 33 | assert np.isclose(chsh_value, -2.5) 34 | assert len(results) == 4 35 | 36 | 37 | def test_chsh_reduces_to_bell_not_verbose(): 38 | circuits = create_chsh_inequality_circuits(0, 1, a1=(np.pi / 3), a2=0, b1=0, b2=(2 * np.pi / 3)) 39 | local_tasks = run_chsh_inequality(circuits, LocalSimulator(), shots=0) 40 | chsh_value, results, E_a1b1, E_a1b2, E_a2b1, E_a2b2 = get_chsh_results( 41 | local_tasks, verbose=False 42 | ) 43 | assert np.isclose(E_a1b1, -0.5) 44 | assert np.isclose(E_a1b2, -0.5) 45 | assert np.isclose(E_a2b1, -1) 46 | assert np.isclose(E_a2b2, 0.5) 47 | assert np.isclose(chsh_value, -2.5) 48 | assert len(results) == 4 49 | 50 | 51 | def test_chsh_no_violation(): 52 | circuits = create_chsh_inequality_circuits(0, 1, a1=0, a2=0, b1=0, b2=0) 53 | local_tasks = run_chsh_inequality(circuits, LocalSimulator(), shots=0) 54 | chsh_value, results, E_a1b1, E_a1b2, E_a2b1, E_a2b2 = get_chsh_results(local_tasks) 55 | assert np.isclose(E_a1b1, -1) 56 | assert np.isclose(E_a1b2, -1) 57 | assert np.isclose(E_a2b1, -1) 58 | assert np.isclose(E_a2b2, -1) 59 | assert np.isclose(chsh_value, -2) 60 | assert len(results) == 4 61 | 62 | 63 | def test_max_chsh_violation(): 64 | circuits = create_chsh_inequality_circuits( 65 | 0, 1, a1=(np.pi / 2), a2=0, b1=(np.pi / 4), b2=(3 * np.pi / 4) 66 | ) 67 | local_tasks = run_chsh_inequality(circuits, LocalSimulator(), shots=0) 68 | chsh_value, results, E_a1b1, E_a1b2, E_a2b1, E_a2b2 = get_chsh_results(local_tasks) 69 | assert np.isclose(E_a1b1, -np.sqrt(2) / 2) 70 | assert np.isclose(E_a1b2, -np.sqrt(2) / 2) 71 | assert np.isclose(E_a2b1, -np.sqrt(2) / 2) 72 | assert np.isclose(E_a2b2, np.sqrt(2) / 2) 73 | assert np.isclose(chsh_value, -2 * np.sqrt(2)) 74 | assert len(results) == 4 75 | -------------------------------------------------------------------------------- /test/unit_tests/braket/experimental/algorithms/deutsch_jozsa/test_deutsch_jozsa.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | import numpy as np 15 | import pytest 16 | from braket.circuits import Circuit 17 | from braket.devices import LocalSimulator 18 | 19 | from braket.experimental.algorithms.deutsch_jozsa import ( 20 | balanced_oracle, 21 | constant_oracle, 22 | deutsch_jozsa_circuit, 23 | get_deutsch_jozsa_results, 24 | ) 25 | 26 | 27 | def test_constant_oracle_circuit(): 28 | for i in range(1, 10): 29 | circ = constant_oracle(i) 30 | assert circ.qubit_count == i + 1 31 | 32 | 33 | @pytest.mark.xfail(raises=ValueError) 34 | def test_fail_constant_oracle_circuit(): 35 | constant_oracle(0) 36 | 37 | 38 | def test_balanced_oracle_circuit(): 39 | for i in range(1, 10): 40 | circ = balanced_oracle(i) 41 | assert circ.qubit_count == i + 1 42 | 43 | 44 | @pytest.mark.xfail(raises=ValueError) 45 | def test_fail_balanced_oracle_circuit(): 46 | balanced_oracle(0) 47 | 48 | 49 | def test_dj_circuit(): 50 | dj = deutsch_jozsa_circuit(Circuit().i(0)) 51 | expected = Circuit().x(0).h(0).i(0).probability() 52 | print(dj) 53 | print(expected) 54 | assert dj == expected 55 | 56 | 57 | def test_get_deutsch_jozsa_results_constant(): 58 | device = LocalSimulator() 59 | const_oracle = constant_oracle(3) 60 | dj_circuit = deutsch_jozsa_circuit(const_oracle) 61 | task = device.run(dj_circuit, shots=0) 62 | dj_probabilities = get_deutsch_jozsa_results(task) 63 | print(dj_circuit) 64 | print(dj_probabilities) 65 | assert np.isclose(dj_probabilities["000"], 1.0) 66 | 67 | 68 | def test_get_deutsch_jozsa_results_balanced(): 69 | device = LocalSimulator() 70 | bal_oracle = balanced_oracle(3) 71 | dj_circuit = deutsch_jozsa_circuit(bal_oracle) 72 | task = device.run(dj_circuit, shots=0) 73 | dj_probabilities = get_deutsch_jozsa_results(task) 74 | print(dj_circuit) 75 | print(dj_probabilities) 76 | assert np.isclose(dj_probabilities["111"], 1.0) 77 | -------------------------------------------------------------------------------- /test/unit_tests/braket/experimental/algorithms/grovers_search/test_grovers_search.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pytest 3 | from braket.devices import LocalSimulator 4 | 5 | from braket.experimental.algorithms.grovers_search import build_oracle, grovers_search 6 | 7 | 8 | @pytest.mark.parametrize("solution", ["00", "000", "0000", "00000"]) 9 | def test_grovers_search_solution(solution): 10 | n_qubits = len(solution) 11 | 12 | oracle = build_oracle(solution) 13 | circuit = grovers_search(oracle, n_qubits=n_qubits, n_reps=1) 14 | 15 | local_simulator = LocalSimulator() 16 | task = local_simulator.run(circuit, shots=1000) 17 | result = task.result() 18 | probabilities = result.values[0] 19 | 20 | assert np.argmax(probabilities) == 0 21 | 22 | 23 | @pytest.mark.parametrize("decompose_ccnot", [True, False]) 24 | def test_grovers_search_solution_decompose_ccnot(decompose_ccnot): 25 | solution = "000" 26 | n_qubits = len(solution) 27 | 28 | oracle = build_oracle(solution, decompose_ccnot=decompose_ccnot) 29 | circuit = grovers_search(oracle, n_qubits=n_qubits, n_reps=1, decompose_ccnot=decompose_ccnot) 30 | 31 | local_simulator = LocalSimulator() 32 | task = local_simulator.run(circuit, shots=1000) 33 | result = task.result() 34 | probabilities = result.values[0] 35 | 36 | assert np.argmax(probabilities) == 0 37 | -------------------------------------------------------------------------------- /test/unit_tests/braket/experimental/algorithms/qc_qmc/test_qc_qmc.py: -------------------------------------------------------------------------------- 1 | from unittest.mock import patch 2 | 3 | import pennylane as qml 4 | import pytest 5 | from pennylane import numpy as np 6 | 7 | from braket.experimental.algorithms.qc_qmc.classical_qmc import ( 8 | chemistry_preparation, 9 | classical_qmc, 10 | full_imag_time_evolution_wrapper, 11 | hartree_fock_energy, 12 | ) 13 | from braket.experimental.algorithms.qc_qmc.qc_qmc import q_full_imag_time_evolution_wrapper, qc_qmc 14 | 15 | np.set_printoptions(precision=4, edgeitems=10, linewidth=150, suppress=True) 16 | 17 | 18 | @pytest.fixture 19 | def qmc_data(): 20 | symbols = ["H", "H"] 21 | geometry = np.array([[0.0, 0.0, 0.0], [0.0, 0.0, 1.41729459]], requires_grad=False) 22 | mol = qml.qchem.Molecule(symbols, geometry, basis_name="sto-3g") 23 | trial = np.array([[1, 0], [0, 1], [0, 0], [0, 0]]) 24 | prop = chemistry_preparation(mol, geometry, trial) 25 | dev = qml.device("default.qubit", wires=4) 26 | e_hf = hartree_fock_energy(trial, prop) 27 | return (trial, prop, dev, e_hf) 28 | 29 | 30 | def trial_state_circuit() -> None: 31 | """Define trial_state_circuit through UCCSD circuit.""" 32 | qml.RX(np.pi / 2.0, wires=0) 33 | for i in range(1, 4): 34 | qml.Hadamard(wires=i) 35 | 36 | for i in range(3): 37 | qml.CNOT(wires=[i, i + 1]) 38 | 39 | qml.RZ(0.12, wires=3) 40 | for i in range(3)[::-1]: 41 | qml.CNOT(wires=[i, i + 1]) 42 | 43 | qml.RX(-np.pi / 2.0, wires=0) 44 | for i in range(1, 4): 45 | qml.Hadamard(wires=i) 46 | 47 | 48 | def test_properties(qmc_data): 49 | trial, prop, dev, e_hf = qmc_data 50 | assert np.allclose(prop.h1e, np.array([[-1.2473, -0.0], [-0.0, -0.4813]]), atol=1e-4) 51 | assert np.allclose( 52 | prop.eri, 53 | np.array( 54 | [ 55 | [[[0.6728, 0.0], [0.0, 0.1818]], [[0.0, 0.1818], [0.662, 0.0]]], 56 | [[[0.0, 0.662], [0.1818, 0.0]], [[0.1818, 0.0], [0.0, 0.6958]]], 57 | ], 58 | ), 59 | atol=1e-4, 60 | ) 61 | assert np.allclose( 62 | prop.v_0, 63 | np.array( 64 | [ 65 | [-0.3289 + 0.0j, 0.0 + 0.0j, 0.0 + 0.0j, 0.0 + 0.0j], 66 | [0.0 + 0.0j, -0.3289 + 0.0j, 0.0 + 0.0j, 0.0 + 0.0j], 67 | [0.0 + 0.0j, 0.0 + 0.0j, 0.4039 + 0.0j, 0.0 + 0.0j], 68 | [0.0 + 0.0j, 0.0 + 0.0j, 0.0 + 0.0j, 0.4039 + 0.0j], 69 | ], 70 | ), 71 | atol=1e-4, 72 | ) 73 | 74 | 75 | def test_qc_qmc(qmc_data): 76 | trial, prop, dev, e_hf = qmc_data 77 | num_steps = 5 78 | num_walkers = 15 79 | qe_step_size = 2 80 | 81 | with patch("multiprocessing.pool.Pool.map") as evolution_mock: 82 | energy_data_mock = [1.0 for _ in range(num_steps)] 83 | quantum_data_mock = [0.0 if i % qe_step_size == 0 else 1.0 for i in range(num_steps)] 84 | evolution_mock.return_value = [ 85 | (energy_data_mock, energy_data_mock, quantum_data_mock, quantum_data_mock), 86 | ] * num_walkers 87 | 88 | # Start QC-QMC computation 89 | quantum_energies, energies = qc_qmc( 90 | num_walkers=num_walkers, 91 | num_steps=num_steps, 92 | dtau=1, 93 | quantum_evaluations_every_n_steps=qe_step_size, 94 | trial=trial, 95 | prop=prop, 96 | trial_state_circuit=trial_state_circuit, 97 | dev=dev, 98 | max_pool=2, 99 | ) 100 | assert len(energies) == num_steps 101 | assert len(quantum_energies) == num_steps // qe_step_size 102 | 103 | 104 | def test_q_full_imag_time_evolution(qmc_data): 105 | trial, prop, dev, e_hf = qmc_data 106 | num_steps = 4 107 | qe_step_size = 2 108 | num_walkers = 2 109 | dtau = 1 110 | 111 | walkers = [trial] * num_walkers 112 | weights = [1.0] * num_walkers 113 | inputs = [ 114 | (num_steps, qe_step_size, dtau, trial, prop, e_hf, walker, weight, trial_state_circuit, dev) 115 | for walker, weight in zip(walkers, weights) 116 | ] 117 | 118 | results = [q_full_imag_time_evolution_wrapper(input_arg) for input_arg in inputs] 119 | assert len(results) == num_walkers 120 | assert len(results[0][0]) == num_steps 121 | 122 | 123 | def test_classical_qmc(qmc_data): 124 | trial, prop, dev, e_hf = qmc_data 125 | num_steps = 4 126 | num_walkers = 50 127 | 128 | # Start QMC computation 129 | local_energies, energies = classical_qmc( 130 | num_walkers=num_walkers, 131 | num_steps=num_steps, 132 | dtau=1, 133 | trial=trial, 134 | prop=prop, 135 | max_pool=2, 136 | ) 137 | assert len(energies) == num_steps 138 | assert len(local_energies) == num_walkers 139 | assert len(local_energies[0]) == num_steps 140 | 141 | 142 | def test_full_imag_time_evolution(qmc_data): 143 | trial, prop, dev, e_hf = qmc_data 144 | 145 | num_steps = 4 146 | num_walkers = 2 147 | dtau = 1 148 | 149 | walkers = [trial] * num_walkers 150 | weights = [1.0] * num_walkers 151 | 152 | inputs = [ 153 | (num_steps, dtau, trial, prop, e_hf, walker, weight) 154 | for walker, weight in zip(walkers, weights) 155 | ] 156 | 157 | energy_list, weights = [full_imag_time_evolution_wrapper(input_arg) for input_arg in inputs] 158 | assert len(energy_list) == num_walkers 159 | assert len(weights) == num_walkers 160 | -------------------------------------------------------------------------------- /test/unit_tests/braket/experimental/algorithms/quantum_approximate_optimization/test_quantum_approximate_optimization.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | import numpy as np 15 | from braket.circuits import Circuit, FreeParameter 16 | from braket.devices import LocalSimulator 17 | 18 | from braket.experimental.algorithms.quantum_approximate_optimization import ( 19 | cost_function, 20 | qaoa, 21 | run_qaoa_circuit, 22 | ) 23 | 24 | 25 | def test_qaoa(): 26 | n_qubits = 2 27 | n_layers = 1 28 | coupling_matrix = np.diag(np.ones(n_qubits - 1), 1) 29 | circ = qaoa(n_qubits, n_layers, coupling_matrix) 30 | assert circ.qubit_count == 2 31 | 32 | 33 | def test_qaoa_evaluate_circuit(): 34 | param = FreeParameter("theta") 35 | circ = Circuit().rx(0, param).probability() 36 | device = LocalSimulator() 37 | shots = 0 38 | values = [0] 39 | task = run_qaoa_circuit(device, circ, values, shots) 40 | result = task.result().values[0] 41 | assert np.isclose(result[0], 1) 42 | 43 | 44 | def test_qaoa_cost_function(): 45 | coeffs = [1] 46 | n_qubits = 2 47 | n_layers = 1 48 | coupling_matrix = np.diag(np.ones(n_qubits - 1), 1) 49 | circ = qaoa(n_qubits, n_layers, coupling_matrix) 50 | cost = cost_function(np.ones(2), LocalSimulator(), circ, coeffs, []) 51 | print("loss is", cost) 52 | assert np.isclose(cost, -0.636827341031835, rtol=1e-6) 53 | -------------------------------------------------------------------------------- /test/unit_tests/braket/experimental/algorithms/quantum_circuit_born_machine/test_qcbm.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | import random 15 | 16 | import numpy as np 17 | import pytest 18 | from braket.devices import LocalSimulator 19 | from scipy.optimize import minimize 20 | 21 | from braket.experimental.algorithms.quantum_circuit_born_machine import QCBM, mmd_loss 22 | 23 | 24 | @pytest.fixture(autouse=True) 25 | def set_random_seed(): 26 | random.seed(1234) 27 | 28 | 29 | def test_mmd_loss(): 30 | loss = mmd_loss(np.zeros(4), np.zeros(4)) 31 | assert np.isclose(loss, 0, rtol=1e-5) 32 | 33 | 34 | def test_qcbm(): 35 | n_qubits = 2 36 | n_layers = 2 37 | data = np.ones(3 * n_layers * n_qubits) 38 | device = LocalSimulator() 39 | qcbm = QCBM(device, n_qubits, n_layers, data) 40 | init_params = np.zeros((n_layers, n_qubits, 3)) 41 | probs = qcbm.get_probabilities(init_params) 42 | expected = np.array([1, 0, 0, 0]) 43 | assert np.isclose(probs, expected).all() 44 | 45 | 46 | @pytest.mark.xfail(raises=ValueError) 47 | def test_qcbm_no_qubits(): 48 | n_qubits = 0 49 | n_layers = 1 50 | data = np.ones(3 * n_layers * n_qubits) 51 | device = LocalSimulator() 52 | QCBM(device, n_qubits, n_layers, data) 53 | 54 | 55 | def test_qcbm_gradient(): 56 | n_layers = 1 57 | n_qubits = 2 58 | n_iterations = 1 59 | data = np.ones(3 * n_layers * n_qubits) 60 | device = LocalSimulator() 61 | 62 | init_params = np.random.rand(3 * n_layers * n_qubits) 63 | qcbm = QCBM(device, n_qubits, n_layers, data) 64 | 65 | result = minimize( 66 | lambda x: mmd_loss(qcbm.get_probabilities(x), data), 67 | x0=init_params, 68 | method="L-BFGS-B", 69 | jac=lambda x: qcbm.gradient(x), 70 | options={"maxiter": n_iterations}, 71 | ) 72 | assert result.njev < 4 73 | assert result.nit == 1 74 | assert result.status == 1 75 | -------------------------------------------------------------------------------- /test/unit_tests/braket/experimental/algorithms/quantum_fourier_transform/test_quantum_fourier_transform.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | # Quantum Fourier Transform: Amazon Braket Algorithm Library 15 | 16 | import numpy as np 17 | from braket.circuits import Circuit 18 | from braket.devices import LocalSimulator 19 | 20 | from braket.experimental.algorithms.quantum_fourier_transform import ( 21 | quantum_fourier_transform as qft, 22 | ) 23 | 24 | 25 | def test_qft(): 26 | task = qft.run_quantum_fourier_transform( 27 | qubits=[0, 1], n_shots=100, state_prep_circ=Circuit().h(0).h(1), device=LocalSimulator() 28 | ) 29 | assert np.allclose(task.result().values[0], [1.0, 0.0, 0.0, 0.0]) 30 | 31 | 32 | def test_inverse_qft(): 33 | task = qft.run_quantum_fourier_transform( 34 | qubits=[0, 1], 35 | n_shots=100, 36 | state_prep_circ=Circuit().h(0).h(1), 37 | device=LocalSimulator(), 38 | inverse=True, 39 | ) 40 | assert np.allclose(task.result().values[0], [1.0, 0.0, 0.0, 0.0]) 41 | -------------------------------------------------------------------------------- /test/unit_tests/braket/experimental/algorithms/quantum_phase_estimation/test_quantum_phase_estimation.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | import numpy as np 15 | from braket.circuits import Circuit 16 | from braket.devices import LocalSimulator 17 | 18 | from braket.experimental.algorithms.quantum_phase_estimation import quantum_phase_estimation as qpe 19 | 20 | 21 | # controlled unitary apply function 22 | def controlled_unitary_apply_cnot_func(qpe_circ, control_qubit, query_qubits): 23 | qpe_circ.cnot(control_qubit, query_qubits) 24 | 25 | 26 | # CNOT controlled unitary with 2 precision qubits, and H gate query prep 27 | def test_cnot_qpe_run_2_precision_qubits(): 28 | # prep 29 | precision_qubits = [0, 1] 30 | query_qubits = [2] 31 | 32 | # create circuit and apply query preparation 33 | qpe_circ = Circuit().h(query_qubits) 34 | 35 | # apply qpe 36 | qpe_circ = qpe.quantum_phase_estimation_circuit( 37 | qpe_circ, precision_qubits, query_qubits, controlled_unitary_apply_cnot_func 38 | ) 39 | 40 | assert len(qpe_circ.instructions) == 8 41 | assert qpe_circ.depth == 6 42 | # assert qpe_circ.instructions[3].ascii_symbols == ("C", "X") 43 | 44 | # run QPE 45 | task = qpe.run_quantum_phase_estimation(qpe_circ, LocalSimulator()) 46 | 47 | agg_result = qpe.get_quantum_phase_estimation_results( 48 | task, precision_qubits, query_qubits, verbose=True 49 | ) 50 | 51 | # validate excepted QPE output 52 | assert agg_result["measurement_counts"]["001"] > 300 53 | assert agg_result["measurement_counts"]["000"] > 300 54 | assert len(agg_result["measurement_counts"]) == 2 55 | assert agg_result["phases_decimal"] == [0.0] 56 | assert set(agg_result["eigenvalue_estimates"]) == {1.0 + 0.0j} 57 | 58 | 59 | # 0 shots results in no measurement counts but valid phase estimates 60 | def test_0_shots(): 61 | # prep 62 | precision_qubits = [0, 1] 63 | query_qubits = [2] 64 | 65 | # create circuit and apply query preparation 66 | qpe_circ = Circuit().h(query_qubits) 67 | 68 | # apply qpe 69 | qpe_circ = qpe.quantum_phase_estimation_circuit( 70 | qpe_circ, precision_qubits, query_qubits, controlled_unitary_apply_cnot_func 71 | ) 72 | 73 | # run QPE 74 | task = qpe.run_quantum_phase_estimation(qpe_circ, LocalSimulator(), shots=0) 75 | 76 | agg_result = qpe.get_quantum_phase_estimation_results( 77 | task, precision_qubits, query_qubits, verbose=True 78 | ) 79 | 80 | assert agg_result["measurement_counts"] is None 81 | assert np.isclose(agg_result["phases_decimal"][0], 0.5) 82 | 83 | 84 | # CNOT controlled unitary with 3 precision qubits, and H gate query prep 85 | def test_cnot_qpe_run_3_precision_qubits(): 86 | # prep 87 | precision_qubits = [0, 1, 2] 88 | query_qubits = [3] 89 | 90 | # create circuit and apply query preparation 91 | qpe_circ = Circuit().h(query_qubits) 92 | 93 | # apply qpe 94 | qpe_circ = qpe.quantum_phase_estimation_circuit( 95 | qpe_circ, precision_qubits, query_qubits, controlled_unitary_apply_cnot_func 96 | ) 97 | 98 | print("Circuit: ", qpe_circ) 99 | # run QPE 100 | task = qpe.run_quantum_phase_estimation(qpe_circ, LocalSimulator()) 101 | 102 | agg_result = qpe.get_quantum_phase_estimation_results( 103 | task, precision_qubits, query_qubits, verbose=False 104 | ) 105 | 106 | # validate excepted QPE output 107 | assert agg_result["measurement_counts"]["0001"] > 300 108 | assert agg_result["measurement_counts"]["0000"] > 300 109 | assert len(agg_result["measurement_counts"]) == 2 110 | assert agg_result["phases_decimal"] == [0.0] 111 | assert set(agg_result["eigenvalue_estimates"]) == {1.0 + 0.0j} 112 | 113 | 114 | # CNOT controlled unitary with 2 precision qubits, and HX gate query prep 115 | def test_cnot_qpe_run_HX_eigenstate(): 116 | # prep 117 | precision_qubits = [0, 1] 118 | query_qubits = [2] 119 | 120 | # create circuit and apply query preparation 121 | qpe_circ = Circuit().x(query_qubits).h(query_qubits) 122 | 123 | # apply qpe 124 | qpe_circ = qpe.quantum_phase_estimation_circuit( 125 | qpe_circ, precision_qubits, query_qubits, controlled_unitary_apply_cnot_func 126 | ) 127 | 128 | print("Circuit: ", qpe_circ) 129 | # run QPE 130 | task = qpe.run_quantum_phase_estimation(qpe_circ, LocalSimulator()) 131 | 132 | agg_result = qpe.get_quantum_phase_estimation_results( 133 | task, precision_qubits, query_qubits, verbose=True 134 | ) 135 | 136 | # validate excepted QPE output 137 | assert agg_result["measurement_counts"]["101"] > 300 138 | assert agg_result["measurement_counts"]["100"] > 300 139 | assert len(agg_result["measurement_counts"]) == 2 140 | assert agg_result["phases_decimal"] == [0.5] 141 | assert set(agg_result["eigenvalue_estimates"]) == {-1.0 + 0.0j} 142 | 143 | 144 | # CNOT controlled unitary with 2 precision qubits, and X gate query prep 145 | def test_cnot_qpe_run_X_eigenstate(): 146 | # prep 147 | precision_qubits = [0, 1] 148 | query_qubits = [2] 149 | 150 | # create circuit and apply query preparation 151 | qpe_circ = Circuit().x(query_qubits) 152 | 153 | # apply qpe 154 | qpe_circ = qpe.quantum_phase_estimation_circuit( 155 | qpe_circ, precision_qubits, query_qubits, controlled_unitary_apply_cnot_func 156 | ) 157 | 158 | print("Circuit: ", qpe_circ) 159 | # run QPE 160 | task = qpe.run_quantum_phase_estimation(qpe_circ, LocalSimulator()) 161 | 162 | agg_result = qpe.get_quantum_phase_estimation_results( 163 | task, precision_qubits, query_qubits, verbose=True 164 | ) 165 | 166 | # validate excepted QPE output 167 | assert agg_result["measurement_counts"]["000"] > 100 168 | assert agg_result["measurement_counts"]["100"] > 100 169 | assert agg_result["measurement_counts"]["101"] > 100 170 | assert agg_result["measurement_counts"]["001"] > 100 171 | assert len(agg_result["measurement_counts"]) == 4 172 | assert set(agg_result["phases_decimal"]) == {0.0, 0.5} 173 | assert set(agg_result["eigenvalue_estimates"]) == {1.0 + 0.0j, -1.0 + 0.0j} 174 | 175 | 176 | # inverse QFT circuit validation with 2 input qubits 177 | def test_inverse_qft(): 178 | # prep 179 | qubits = [0, 1] 180 | 181 | # run inverse qft 182 | qft_circ = qpe.inverse_qft(qubits) 183 | 184 | # validate circuit output 185 | assert len(qft_circ.instructions) == 4 186 | assert qft_circ.instructions[2].operator.ascii_symbols == ("C", "PHASE(-1.57)") 187 | -------------------------------------------------------------------------------- /test/unit_tests/braket/experimental/algorithms/quantum_walk/test_quantum_walk.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pytest 3 | from braket.circuits import Circuit 4 | from braket.devices import LocalSimulator 5 | 6 | from braket.experimental.algorithms.quantum_walk import ( 7 | qft_conditional_add_1, 8 | quantum_walk, 9 | run_quantum_walk, 10 | ) 11 | 12 | 13 | def test_quantum_walk_4_nodes_4_steps(): 14 | local_simulator = LocalSimulator() 15 | quantum_walk_circuit = quantum_walk(4, 4) 16 | task = local_simulator.run(quantum_walk_circuit, shots=1000) 17 | result = task.result() 18 | counts = result.measurement_counts 19 | 20 | assert set(counts.keys()) == {"001"} 21 | 22 | assert np.isclose(list(counts.values()), [1000]).all() 23 | 24 | 25 | @pytest.mark.parametrize( 26 | "num_qubits, a, action", 27 | [ 28 | (3, 0, "+"), 29 | (3, 1, "+"), 30 | (3, 2, "+"), 31 | (3, 3, "+"), 32 | (3, 4, "+"), 33 | (3, 5, "+"), 34 | (3, 6, "+"), 35 | (3, 7, "+"), 36 | (3, 0, "-"), 37 | (3, 1, "-"), 38 | (3, 2, "-"), 39 | (3, 3, "-"), 40 | (3, 4, "-"), 41 | (3, 5, "-"), 42 | (3, 6, "-"), 43 | (3, 7, "-"), 44 | ], 45 | ) 46 | def test_qft_conditional_add_1(num_qubits, a, action): 47 | qc = Circuit() 48 | local_simulator = LocalSimulator() 49 | 50 | # Step 0: Do nothing to the 0th qubit to 1 so that we are subtracting 1 51 | if action == "-": 52 | qc.x(0) 53 | 54 | # Step 1: Encode the number a into the circuit 55 | binary_a = bin(abs(a))[2:] 56 | for i, bit in enumerate(reversed(binary_a)): 57 | if bit == "1": 58 | qc.x(1 + i) 59 | 60 | # Step 2: Add or subtract 1 conditionally 61 | qc.add_circuit(qft_conditional_add_1(num_qubits)) 62 | result = local_simulator.run(qc, shots=1000).result() 63 | counts = result.measurement_counts 64 | 65 | # Step 3: Make sure the measurement outcome corresponds to the addition a+b 66 | values = np.asarray([int(v[1:][::-1], 2) for v in counts.keys()]) 67 | counts = np.asarray(list(counts.values())) 68 | c = values[np.argmax(counts)] 69 | 70 | if action == "-": 71 | assert np.mod(a - 1 - c, 2**num_qubits) == 0 72 | else: # action == "+" 73 | assert np.mod(a + 1 - c, 2**num_qubits) == 0 74 | 75 | 76 | @pytest.mark.xfail(raises=ValueError) 77 | def test_value_error_num_nodes(): 78 | quantum_walk(3) 79 | 80 | 81 | def test_run_quantum_walk(): 82 | local_sim = LocalSimulator() 83 | qc = quantum_walk(4, 2) 84 | out = run_quantum_walk(qc, local_sim) 85 | 86 | assert out["circuit"] == qc 87 | -------------------------------------------------------------------------------- /test/unit_tests/braket/experimental/algorithms/shors/test_shors.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | import pytest 15 | 16 | # from braket.circuits import Circuit 17 | from braket.devices import LocalSimulator 18 | 19 | from braket.experimental.algorithms.shors.shors import ( 20 | get_factors_from_results, 21 | run_shors_algorithm, 22 | shors_algorithm, 23 | ) 24 | 25 | local_simulator = LocalSimulator() 26 | 27 | 28 | def test_invalid_a_N(): 29 | with pytest.raises(ValueError): 30 | shors_algorithm(1, 1) 31 | with pytest.raises(ValueError): 32 | shors_algorithm(10, 3) 33 | with pytest.raises(ValueError): 34 | shors_algorithm(17, 30) 35 | with pytest.raises(ValueError): 36 | shors_algorithm(45, 30) 37 | with pytest.raises(ValueError): 38 | shors_algorithm(15, 10) 39 | with pytest.raises(ValueError): 40 | shors_algorithm(15, 1) 41 | 42 | 43 | def test_shors_algorithm(): 44 | integer_N = 15 45 | integer_a = 2 46 | shor = shors_algorithm(integer_N, integer_a) 47 | local_simulator = LocalSimulator() 48 | output = run_shors_algorithm(shor, local_simulator) 49 | aggregate_results = get_factors_from_results(output, integer_N, integer_a, False) 50 | assert aggregate_results["guessed_factors"] == {3, 5} 51 | 52 | 53 | def test_all_valid_a(): 54 | local_simulator = LocalSimulator() 55 | integer_N = 15 56 | for integer_a in [2, 7, 8, 11, 13]: 57 | shor = shors_algorithm(integer_N, integer_a) 58 | output = run_shors_algorithm(shor, local_simulator) 59 | aggregate_results = get_factors_from_results(output, integer_N, integer_a, True) 60 | assert aggregate_results["guessed_factors"] == {3, 5} 61 | 62 | 63 | def test_no_counts(): 64 | with pytest.raises(TypeError): 65 | output = {"measurement_counts": False} 66 | integer_N = 15 67 | integer_a = 7 68 | get_factors_from_results(output, integer_N, integer_a, True) 69 | -------------------------------------------------------------------------------- /test/unit_tests/braket/experimental/algorithms/simons/test_simons.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | import pytest 15 | from braket.devices import LocalSimulator 16 | 17 | from braket.experimental.algorithms.simons import ( 18 | get_simons_algorithm_results, 19 | run_simons_algorithm, 20 | simons_oracle, 21 | ) 22 | 23 | local_simulator = LocalSimulator() 24 | 25 | 26 | @pytest.mark.parametrize("secret", ["00000", "10110"]) 27 | def test_simons_algorithm(secret): 28 | oracle = simons_oracle(secret) 29 | task = run_simons_algorithm(oracle=oracle, device=local_simulator) 30 | processed_results = get_simons_algorithm_results(task) 31 | revelead_secret = processed_results["secret_string"] 32 | assert secret == revelead_secret 33 | 34 | 35 | @pytest.mark.xfail(raises=RuntimeError) 36 | def test_low_shot_number(): 37 | secret_5_qubit = "10110" 38 | oracle = simons_oracle(secret_5_qubit) 39 | task = run_simons_algorithm(oracle=oracle, device=local_simulator, shots=4) 40 | get_simons_algorithm_results(task) 41 | 42 | 43 | @pytest.mark.xfail(raises=ValueError) 44 | def test_bad_string(): 45 | bad_string = "a0110" 46 | simons_oracle(bad_string) 47 | 48 | 49 | @pytest.mark.xfail(raises=ValueError) 50 | def test_zero_shot_number(): 51 | secret_5_qubit = "10110" 52 | oracle = simons_oracle(secret_5_qubit) 53 | run_simons_algorithm(oracle=oracle, device=local_simulator, shots=0) 54 | -------------------------------------------------------------------------------- /test/unit_tests/braket/experimental/auxiliary_functions/random_circuit/test_random_circuit.py: -------------------------------------------------------------------------------- 1 | from braket.circuits import Circuit 2 | from braket.circuits.gates import XY, CNot, CPhaseShift, H, Rx, Ry, Rz, S, T 3 | 4 | from braket.experimental.auxiliary_functions import random_circuit 5 | 6 | 7 | def test_random_circuit_returns_circuit(): 8 | circuit = random_circuit(num_qubits=3, num_gates=5, seed=1) 9 | assert isinstance(circuit, Circuit) 10 | 11 | 12 | def test_random_circuit_instruction_count(): 13 | num_gates = 5 14 | circuit = random_circuit(num_qubits=3, num_gates=num_gates, seed=1) 15 | assert len(circuit.instructions) == num_gates 16 | 17 | 18 | def test_random_circuit_consistency_with_seed(): 19 | circuit1 = random_circuit(num_qubits=3, num_gates=5, seed=1) 20 | circuit2 = random_circuit(num_qubits=3, num_gates=5, seed=1) 21 | assert circuit1 == circuit2 22 | 23 | 24 | def test_random_circuit_variability_without_seed(): 25 | circuit1 = random_circuit(num_qubits=3, num_gates=5) 26 | circuit2 = random_circuit(num_qubits=3, num_gates=5) 27 | assert circuit1 != circuit2 28 | 29 | 30 | def test_custom_gate_set(): 31 | gate_set = [CNot, H, S, T, Rx, Ry, Rz, XY, CPhaseShift] 32 | circuit = random_circuit(num_qubits=3, num_gates=5, gate_set=gate_set, seed=1) 33 | 34 | gate_from_gate_set = [] 35 | for instr in circuit.instructions: 36 | gate_class = instr.operator.__class__ 37 | gate_from_gate_set.append(gate_class in gate_set) 38 | 39 | assert all(gate_from_gate_set) 40 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = linters,docs,unit-tests, integ_tests 3 | 4 | [testenv] 5 | parallel_show_output = true 6 | package = wheel 7 | wheel_build_env = .pkg 8 | 9 | [testenv:unit-tests] 10 | basepython = python3 11 | # {posargs} contains additional arguments specified when invoking tox. e.g. tox -- -s -k test_foo.py 12 | deps = 13 | {[test-deps]deps} 14 | commands = 15 | pytest {posargs} --cov-report term-missing --cov-report html --cov-report xml --cov=braket 16 | extras = test 17 | 18 | 19 | [testenv:integ-tests-aws] 20 | basepython = python3 21 | # {posargs} contains additional arguments specified when invoking tox. e.g. tox -- -s -k test_foo.py 22 | deps = 23 | -r{toxinidir}/test/integ_tests/requirements.txt 24 | passenv = 25 | AWS_PROFILE 26 | commands = 27 | pytest test/integ_tests -s --mock-level=LEAST test/integ_tests 28 | extras = test 29 | 30 | 31 | [testenv:integ-tests] 32 | basepython = python3 33 | # {posargs} contains additional arguments specified when invoking tox. e.g. tox -- -s -k test_foo.py 34 | deps = 35 | -r{toxinidir}/test/integ_tests/requirements.txt 36 | commands = 37 | pytest test/integ_tests 38 | extras = test 39 | 40 | [testenv:linters] 41 | basepython = python3 42 | skip_install = true 43 | deps = 44 | {[testenv:ruff-format]deps} 45 | {[testenv:ruff-check]deps} 46 | commands = 47 | {[testenv:ruff-format]commands} 48 | {[testenv:ruff-check]commands} 49 | 50 | # Read only linter env 51 | [testenv:linters_check] 52 | basepython = python3 53 | skip_install = true 54 | deps = 55 | {[testenv:ruff-check]deps} 56 | commands = 57 | {[testenv:ruff-check]commands} 58 | 59 | [testenv:ruff-check] 60 | basepython = python3 61 | skip_install = true 62 | deps = 63 | ruff 64 | commands = 65 | ruff check src {posargs} 66 | 67 | [testenv:ruff-format] 68 | basepython = python3 69 | skip_install = true 70 | deps = 71 | ruff 72 | commands = 73 | ruff format . {posargs} 74 | 75 | [testenv:docs] 76 | basepython = python3 77 | deps = 78 | {[test-deps]deps} 79 | sphinx 80 | sphinx-rtd-theme 81 | sphinxcontrib-apidoc 82 | commands = 83 | sphinx-build -E -T -b html doc build/documentation/html 84 | 85 | [testenv:serve-docs] 86 | basepython = python3 87 | skip_install = true 88 | changedir = build/documentation/html 89 | commands = 90 | python -m http.server {posargs} 91 | 92 | [testenv:zip-build] 93 | basepython = python3 94 | skip_install = true 95 | commands = 96 | /bin/sh -c 'tar -czvf build_files.tar.gz build/' 97 | 98 | [test-deps] 99 | deps = 100 | # If you need to test on a certain branch, add @ after .git 101 | git+https://github.com/amazon-braket/amazon-braket-sdk-python.git 102 | --------------------------------------------------------------------------------