├── .github └── workflows │ └── publish-to-pypi-github-release.yml ├── .gitignore ├── LICENSE ├── README.md ├── docs ├── assets │ ├── deepquantum_architecture.png │ └── deepquantum_logo_light_v1.png ├── basics.ipynb ├── mbqc_basics.ipynb ├── photonic_basics.ipynb ├── sphinx_doc │ ├── .gitignore │ ├── Makefile │ ├── README.md │ ├── _static │ │ └── es5 │ │ │ ├── input │ │ │ └── tex │ │ │ │ └── extensions │ │ │ │ └── braket.js │ │ │ ├── output │ │ │ └── chtml │ │ │ │ └── fonts │ │ │ │ └── woff-v2 │ │ │ │ ├── MathJax_Main-Regular.woff │ │ │ │ ├── MathJax_Math-Italic.woff │ │ │ │ ├── MathJax_Size1-Regular.woff │ │ │ │ ├── MathJax_Size3-Regular.woff │ │ │ │ ├── MathJax_Size4-Regular.woff │ │ │ │ └── MathJax_Zero.woff │ │ │ └── tex-mml-chtml.js │ ├── conf.py │ ├── deepquantum.photonic.rst │ ├── deepquantum.rst │ ├── images │ │ ├── 3.3_Gradient_benchmarks.png │ │ ├── 3.3_Hessian_benchmarks.png │ │ └── grad_benchmark_vqnet_dq.png │ ├── index.rst │ ├── intro.md │ ├── make.bat │ ├── modules.rst │ ├── requirements.txt │ ├── 基础使用指南.md │ ├── 引言和概述.md │ └── 案例.md ├── sphinx_doc_en │ ├── .gitignore │ ├── Application_Cases.md │ ├── Basic_Usage_Guide.md │ ├── Introduction_and_Overview.md │ ├── Makefile │ ├── _static │ │ └── es5 │ │ │ ├── input │ │ │ └── tex │ │ │ │ └── extensions │ │ │ │ └── braket.js │ │ │ ├── output │ │ │ └── chtml │ │ │ │ └── fonts │ │ │ │ └── woff-v2 │ │ │ │ ├── MathJax_Main-Regular.woff │ │ │ │ ├── MathJax_Math-Italic.woff │ │ │ │ ├── MathJax_Size1-Regular.woff │ │ │ │ ├── MathJax_Size3-Regular.woff │ │ │ │ ├── MathJax_Size4-Regular.woff │ │ │ │ └── MathJax_Zero.woff │ │ │ └── tex-mml-chtml.js │ ├── conf.py │ ├── deepquantum.photonic.rst │ ├── deepquantum.rst │ ├── images │ │ ├── 3.3_Gradient_benchmarks.png │ │ ├── 3.3_Hessian_benchmarks.png │ │ └── grad_benchmark_vqnet_dq.png │ ├── index.rst │ └── make.bat └── unitary_mapper.ipynb ├── examples ├── basic_gate_MBQC.ipynb ├── benchmarks │ └── gradient_benchmark.py ├── bosonic │ └── breeding_cat │ │ ├── bosonic_breeding.ipynb │ │ └── fig │ │ ├── graph1.png │ │ ├── graph2.png │ │ ├── graph3.png │ │ └── graph4.png ├── figure │ └── basic_gate_MBQC │ │ ├── CNOT.jpg │ │ ├── RZ.jpg │ │ └── Single.jpg ├── gbs │ ├── boson_sampling │ │ ├── boson_sampling.ipynb │ │ └── fig │ │ │ ├── bs.png │ │ │ ├── f1.png │ │ │ ├── f2.png │ │ │ ├── f3.png │ │ │ └── f4.png │ ├── dense_graph │ │ ├── GBS_dense_graph_problem.ipynb │ │ ├── data │ │ │ ├── densegraph_adj.npy │ │ │ └── densegraph_sample.pkl.gz │ │ └── fig │ │ │ ├── f3.png │ │ │ ├── f4.png │ │ │ ├── f5.png │ │ │ ├── f6.png │ │ │ ├── f7.png │ │ │ ├── f8.png │ │ │ ├── f9.png │ │ │ ├── gbs.png │ │ │ ├── graph.png │ │ │ ├── haf.png │ │ │ ├── per.png │ │ │ └── s.png │ ├── gaussian_boson_sampling │ │ ├── fig │ │ │ ├── f3.png │ │ │ ├── f4.png │ │ │ ├── f5.png │ │ │ ├── f6.png │ │ │ ├── f7.png │ │ │ ├── f8.png │ │ │ ├── f9.png │ │ │ ├── gbs.png │ │ │ ├── graph.png │ │ │ ├── haf.png │ │ │ ├── per.png │ │ │ └── s.png │ │ └── gaussian_boson_sampling.ipynb │ ├── gbs_clustering │ │ ├── GBS_clustering.ipynb │ │ ├── data │ │ │ ├── clustering.npy │ │ │ └── clustering.pkl.gz │ │ └── fig │ │ │ ├── 12.png │ │ │ ├── f1.png │ │ │ ├── f2.png │ │ │ ├── f3.png │ │ │ ├── f4.png │ │ │ ├── f5.png │ │ │ └── fig2.png │ ├── homodyne_tomography │ │ ├── Homodyne_Tomography.ipynb │ │ └── fig │ │ │ ├── hd1.png │ │ │ ├── mt1.jpg │ │ │ └── mt2.jpg │ ├── max_clique │ │ ├── GBS_max_clique.ipynb │ │ ├── data │ │ │ ├── clique_adj.npy │ │ │ └── clique_sample.pkl.gz │ │ └── fig │ │ │ └── clique.png │ ├── similar_graph │ │ ├── data │ │ │ ├── gbs_dg.npy │ │ │ ├── mutag_1_adj.npy │ │ │ ├── mutag_1_sample.pkl.gz │ │ │ ├── mutag_2_adj.npy │ │ │ ├── mutag_2_sample.pkl.gz │ │ │ ├── mutag_3_adj.npy │ │ │ ├── mutag_3_sample.pkl.gz │ │ │ ├── mutag_4_adj.npy │ │ │ └── mutag_4_sample.pkl.gz │ │ ├── fig │ │ │ ├── 1.png │ │ │ ├── 2.png │ │ │ ├── 3.png │ │ │ ├── 4.png │ │ │ └── 5.png │ │ └── similar_graph.ipynb │ ├── variational_gbs │ │ └── variational_gbs.ipynb │ ├── vibronic_excitations │ │ ├── data │ │ │ ├── formic_lf.csv │ │ │ ├── formic_li.csv │ │ │ ├── formic_omega.csv │ │ │ ├── formic_omegap.csv │ │ │ ├── formic_rf.csv │ │ │ └── formic_ri.csv │ │ └── vibronic_excitations.ipynb │ ├── vibronic_spectra │ │ ├── data │ │ │ ├── formic_lf.csv │ │ │ ├── formic_li.csv │ │ │ ├── formic_omega.csv │ │ │ ├── formic_omegap.csv │ │ │ ├── formic_rf.csv │ │ │ └── formic_ri.csv │ │ ├── fig │ │ │ ├── Franck_Condon_Diagram.png │ │ │ └── formic_spec.png │ │ └── vibronic_spectra.ipynb │ ├── vqe_ground_energy_for_H2_alg │ │ ├── boson_coeff2.mat │ │ ├── fig │ │ │ ├── bs.png │ │ │ └── bs_circuit2.png │ │ ├── openfermion_h2_fci.npy │ │ ├── openfermion_h2_v3.npy │ │ └── vqe_ground_energy_h2.ipynb │ └── vqe_ground_energy_for_H2_hardware │ │ ├── VQE_H2_ground_energy.ipynb │ │ ├── boson_coeff2.mat │ │ ├── fig │ │ ├── subset_expressive_ability.png │ │ ├── vqa_deterministic.png │ │ └── vqa_random_circuit.png │ │ ├── openfermion_h2_fci.npy │ │ └── openfermion_h2_v3.npy ├── hhl.ipynb ├── qaoa.ipynb ├── qresnets.ipynb ├── quantum_state_transfer_1d.ipynb ├── tdm │ ├── advanced_cluster_state │ │ ├── fig │ │ │ ├── entangle_1.png │ │ │ ├── entangle_2_1.png │ │ │ └── entangle_2_2.png │ │ └── 复杂纠缠态的制备.ipynb │ └── simple_cluster_state │ │ ├── fig │ │ ├── 1.png │ │ ├── EPR.jpg │ │ ├── EPR2.jpg │ │ ├── GHZ.png │ │ └── delay.jpg │ │ └── 一维纠缠态的制备.ipynb ├── test_for_onchip_optimizer.ipynb └── vqe_for_CRW.ipynb ├── pylintrc ├── pyproject.toml ├── src └── deepquantum │ ├── __init__.py │ ├── adjoint.py │ ├── ansatz.py │ ├── bitmath.py │ ├── channel.py │ ├── circuit.py │ ├── communication.py │ ├── distributed.py │ ├── gate.py │ ├── layer.py │ ├── mbqc │ ├── __init__.py │ ├── command.py │ ├── operation.py │ ├── pattern.py │ └── state.py │ ├── operation.py │ ├── optimizer.py │ ├── photonic │ ├── __init__.py │ ├── ansatz.py │ ├── cache │ │ ├── Idx_2qb_6mode_aux_00.pickle │ │ ├── Idx_2qb_6mode_aux_00.pt │ │ ├── Idx_2qb_6mode_aux_10.pickle │ │ ├── Idx_2qb_6mode_aux_10.pt │ │ ├── Idx_3qb_8mode_aux_00.pickle │ │ ├── Idx_3qb_8mode_aux_00.pt │ │ ├── Idx_3qb_8mode_aux_10.pickle │ │ ├── Idx_3qb_8mode_aux_10.pt │ │ ├── Idx_4qb_10mode_aux_00.pickle │ │ └── Idx_4qb_10mode_aux_00.pt │ ├── channel.py │ ├── circuit.py │ ├── decompose.py │ ├── draw.py │ ├── gate.py │ ├── hafnian_.py │ ├── mapper.py │ ├── measurement.py │ ├── operation.py │ ├── qmath.py │ ├── state.py │ ├── tdm.py │ ├── torontonian_.py │ └── utils.py │ ├── qmath.py │ ├── state.py │ └── utils.py └── tests ├── test_ansatz.py ├── test_auto_grad.py ├── test_channel.py ├── test_circuit.py ├── test_get_amplitude.py ├── test_mapper.py ├── test_mbqc_transpile.py ├── test_mps.py ├── test_photonic_batch_shape.py ├── test_photonic_bosonic.py ├── test_photonic_fock.py ├── test_photonic_gate.py ├── test_photonic_qmath.py ├── test_photonic_random_circuit.py ├── test_with_graphix.py ├── test_with_perceval.py ├── test_with_xanadu.py ├── test_with_xanadu_gate.py └── test_with_xanadu_loss.py /.github/workflows/publish-to-pypi-github-release.yml: -------------------------------------------------------------------------------- 1 | name: Publish Python 🐍 distribution 📦 to PyPI and TestPyPI 2 | 3 | run-name: ${{ github.actor }} triggered ${{ github.event_name }} on ${{ github.ref_name }} 4 | 5 | on: 6 | push: 7 | tags: 8 | - 'v*' 9 | 10 | jobs: 11 | build: 12 | name: Build distribution 📦 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v4 17 | with: 18 | fetch-depth: 0 19 | - name: Check if tag is on latest main 20 | run: | 21 | LATEST_MAIN=$(git rev-parse origin/main) 22 | TAG_COMMIT=$(git rev-list -n 1 ${{ github.ref }}) 23 | if [[ "$LATEST_MAIN" == "$TAG_COMMIT" ]]; then 24 | echo "This tag is on the latest commit of the main branch" 25 | else 26 | echo "This tag is not on the latest commit of the main branch" 27 | exit 1 28 | fi 29 | - name: Set up Python 30 | uses: actions/setup-python@v5 31 | with: 32 | python-version: "3.x" 33 | - name: Install pypa/build 34 | run: >- 35 | python3 -m 36 | pip install 37 | build 38 | --user 39 | - name: Build a binary wheel and a source tarball 40 | run: python3 -m build 41 | - name: Store the distribution packages 42 | uses: actions/upload-artifact@v4 43 | with: 44 | name: python-package-distributions 45 | path: dist/ 46 | 47 | publish-to-pypi: 48 | name: >- 49 | Publish Python 🐍 distribution 📦 to PyPI 50 | needs: 51 | - build 52 | runs-on: ubuntu-latest 53 | environment: 54 | name: pypi 55 | url: https://pypi.org/p/deepquantum 56 | permissions: 57 | id-token: write # IMPORTANT: mandatory for trusted publishing 58 | 59 | steps: 60 | - name: Download all the dists 61 | uses: actions/download-artifact@v4 62 | with: 63 | name: python-package-distributions 64 | path: dist/ 65 | - name: Publish distribution 📦 to PyPI 66 | uses: pypa/gh-action-pypi-publish@release/v1 67 | 68 | github-release: 69 | name: >- 70 | Sign the Python 🐍 distribution 📦 with Sigstore 71 | and upload them to GitHub Release 72 | needs: 73 | - publish-to-pypi 74 | runs-on: ubuntu-latest 75 | 76 | permissions: 77 | contents: write # IMPORTANT: mandatory for making GitHub Releases 78 | id-token: write # IMPORTANT: mandatory for sigstore 79 | 80 | steps: 81 | - name: Download all the dists 82 | uses: actions/download-artifact@v4 83 | with: 84 | name: python-package-distributions 85 | path: dist/ 86 | - name: Sign the dists with Sigstore 87 | uses: sigstore/gh-action-sigstore-python@v3.0.0 88 | with: 89 | inputs: >- 90 | ./dist/*.tar.gz 91 | ./dist/*.whl 92 | - name: Create GitHub Release 93 | env: 94 | GITHUB_TOKEN: ${{ github.token }} 95 | run: >- 96 | gh release create 97 | '${{ github.ref_name }}' 98 | --repo '${{ github.repository }}' 99 | --notes "" 100 | - name: Upload artifact signatures to GitHub Release 101 | env: 102 | GITHUB_TOKEN: ${{ github.token }} 103 | # Upload to GitHub Release using the `gh` CLI. 104 | # `dist/` contains the built packages, and the 105 | # sigstore-produced signatures and certificates. 106 | run: >- 107 | gh release upload 108 | '${{ github.ref_name }}' dist/** 109 | --repo '${{ github.repository }}' 110 | 111 | publish-to-testpypi: 112 | name: Publish Python 🐍 distribution 📦 to TestPyPI 113 | needs: 114 | - build 115 | runs-on: ubuntu-latest 116 | 117 | environment: 118 | name: testpypi 119 | url: https://test.pypi.org/p/deepquantum 120 | 121 | permissions: 122 | id-token: write # IMPORTANT: mandatory for trusted publishing 123 | 124 | steps: 125 | - name: Download all the dists 126 | uses: actions/download-artifact@v4 127 | with: 128 | name: python-package-distributions 129 | path: dist/ 130 | - name: Publish distribution 📦 to TestPyPI 131 | uses: pypa/gh-action-pypi-publish@release/v1 132 | with: 133 | repository-url: https://test.pypi.org/legacy/ 134 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | .vscode 5 | 6 | # Byte-compiled / optimized / DLL files 7 | __pycache__/ 8 | *.py[cod] 9 | *$py.class 10 | 11 | # C extensions 12 | *.so 13 | .DS_Store 14 | *.pyc 15 | .gitkeep 16 | 17 | # Distribution / packaging 18 | .Python 19 | build/ 20 | develop-eggs/ 21 | dist/ 22 | downloads/ 23 | eggs/ 24 | .eggs/ 25 | lib/ 26 | lib64/ 27 | parts/ 28 | sdist/ 29 | var/ 30 | wheels/ 31 | share/python-wheels/ 32 | *.egg-info/ 33 | .installed.cfg 34 | *.egg 35 | MANIFEST 36 | algo/test/Functions_test.py 37 | 38 | # PyInstaller 39 | # Usually these files are written by a python script from a template 40 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 41 | *.manifest 42 | *.spec 43 | 44 | # Installer logs 45 | pip-log.txt 46 | pip-delete-this-directory.txt 47 | 48 | # Unit test / coverage reports 49 | htmlcov/ 50 | .tox/ 51 | .nox/ 52 | .coverage 53 | .coverage.* 54 | .cache 55 | nosetests.xml 56 | coverage.xml 57 | *.cover 58 | .hypothesis/ 59 | .pytest_cache/ 60 | 61 | # Translations 62 | *.mo 63 | *.pot 64 | 65 | # Django stuff: 66 | *.log 67 | local_settings.py 68 | db.sqlite3 69 | 70 | # Flask stuff: 71 | instance/ 72 | .webassets-cache 73 | 74 | # Scrapy stuff: 75 | .scrapy 76 | 77 | # Sphinx documentation 78 | docs/_build/ 79 | 80 | # PyBuilder 81 | target/ 82 | 83 | # Jupyter Notebook 84 | .ipynb_checkpoints 85 | 86 | # IPython 87 | profile_default/ 88 | ipython_config.py 89 | 90 | # pyenv 91 | .python-version 92 | 93 | # celery beat schedule file 94 | celerybeat-schedule 95 | 96 | # SageMath parsed files 97 | *.sage.py 98 | 99 | # Environments 100 | .env 101 | .venv 102 | env/ 103 | venv/ 104 | ENV/ 105 | env.bak/ 106 | venv.bak/ 107 | 108 | # Spyder project settings 109 | .spyderproject 110 | .spyproject 111 | 112 | # Rope project settings 113 | .ropeproject 114 | 115 | # mkdocs documentation 116 | /site 117 | 118 | # mypy 119 | .mypy_cache/ 120 | .dmypy.json 121 | dmypy.json 122 | 123 | # Pyre type checker 124 | .pyre/ 125 | # IntelliJ project files 126 | .idea 127 | *.iml 128 | out 129 | gen 130 | ################### 131 | **/mvnw 132 | **/mvnw.cmd 133 | **/.mvn 134 | **/target/ 135 | *.h5 136 | **/__pycache__ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DeepQuantum 2 | 3 |

4 | 5 | DeepQuantum logo 6 | 7 |

8 | 9 | [![docs](https://img.shields.io/badge/docs-link-blue.svg)](https://dqapi.turingq.com/) 10 | [![PyPI](https://img.shields.io/pypi/v/deepquantum.svg?logo=pypi)](https://pypi.org/project/deepquantum/) 11 | ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/deepquantum) 12 | [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg?logo=apache)](./LICENSE) 13 | [![Downloads](https://img.shields.io/pypi/dm/deepquantum.svg)](https://pypi.org/project/deepquantum/) 14 | [![Downloads](https://static.pepy.tech/badge/deepquantum)](https://pepy.tech/project/deepquantum) 15 | 16 | DeepQuantum is a platform that integrates artificial intelligence (AI) and quantum computing (QC). It is an efficient programming framework designed for quantum machine learning and photonic quantum computing. By leveraging the PyTorch deep learning platform for QC, DeepQuantum provides a powerful and easy-to-use tool for creating and simulating quantum circuits and photonic quantum circuits. This makes it ideal for developers to quickly get started and explore the field in depth. It also serves as a valuable learning platform for quantum computing enthusiasts. 17 | 18 | # Key Features 19 | 20 |

21 | 22 | DeepQuantum architecture 23 | 24 |

25 | 26 | - **AI-Enhanced Quantum Computing Framework**: Seamlessly integrated with PyTorch, it utilizes technologies such as automatic differentiation, vectorized parallelism, and GPU acceleration for efficiency. It facilitates the easy construction of hybrid quantum-classical models, enabling end-to-end training and inference. 27 | - **User-Friendly API Design**: The API is designed to be simple and intuitive, making it easy to initialize quantum neural networks and providing flexibility in data encoding. 28 | - **Photonic Quantum Computing Simulation**: The Photonic module includes Fock, Gaussian and Bosonic backends, catering to different simulation needs in photonic quantum computing. It comes with built-in optimizers to support on-chip training of photonic quantum circuits. 29 | - **Large-Scale Quantum Circuit Simulation**: Based on tensor networks, it enables the simulation of 100+ qubits on a laptop, leading the industry in both simulation efficiency and scale. 30 | - **Advanced Architecture for Cutting-Edge Algorithm Exploration**: The first framework to support algorithm design and mapping for time-domain-multiplexed photonic quantum circuits, and the first to realize closed-loop integration of quantum circuits, photonic quantum circuits, and MBQC, enabling robust support for both specialized and universal photonic quantum algorithm design. 31 | 32 | # Installation 33 | 34 | Before installing DeepQuantum, we recommend first manually installing PyTorch 2. 35 | If the latest version of PyTorch is not compatible with your CUDA version, manually install a compatible PyTorch 2 version. 36 | 37 | The PyTorch installation instructions currently recommend: 38 | 1. Install [Miniconda](https://docs.anaconda.com/miniconda/) or [Anaconda](https://www.anaconda.com/download). 39 | 2. Setup conda environment. For example, run `conda create -n python=3.10` and `conda activate `. 40 | 3. Install PyTorch following the [PyTorch installation instructions](https://pytorch.org/get-started/locally/). 41 | Currently, this suggests running `conda install pytorch -c pytorch`. 42 | 43 | If you want to customize your installation, please follow the [PyTorch installation instructions](https://pytorch.org/get-started/locally/) to build from source. 44 | 45 | To install DeepQuantum with `pip`, run 46 | 47 | ```bash 48 | pip install deepquantum 49 | # or for developers 50 | pip install deepquantum[dev] 51 | # or use tsinghua source 52 | pip install deepquantum -i https://pypi.tuna.tsinghua.edu.cn/simple 53 | ``` 54 | 55 | Alternatively, to install DeepQuantum from source, run 56 | 57 | ```bash 58 | git clone https://github.com/TuringQ/deepquantum.git 59 | cd deepquantum 60 | pip install -e . 61 | # or use tsinghua source 62 | pip install -e . -i https://pypi.tuna.tsinghua.edu.cn/simple 63 | ``` 64 | 65 | # Getting Started 66 | 67 | To begin, please start with the tutorials (CN) on [basics](./docs/basics.ipynb) and [photonic basics](./docs/photonic_basics.ipynb). 68 | 69 | Below are some minimal demos to help you get started. 70 | 71 | - Quantum circuit 72 | 73 | ```python 74 | import deepquantum as dq 75 | cir = dq.QubitCircuit(2) 76 | cir.h(0) 77 | cir.cnot(0, 1) 78 | cir.rx(1, 0.2) 79 | cir.observable(0) 80 | print(cir()) 81 | print(cir.expectation()) 82 | ``` 83 | 84 | - Quantum circuit based on matrix product state 85 | 86 | You can simply set `mps=True` in `QubitCircuit` and adjust the bond dimension `chi` to control the complexity. 87 | 88 | ```python 89 | cir = dq.QubitCircuit(2, mps=True, chi=4) 90 | cir.h(0) 91 | cir.cnot(0, 1) 92 | cir.rx(1, 0.2) 93 | cir.observable(0) 94 | print(cir()) 95 | print(cir.expectation()) 96 | ``` 97 | 98 | - Photonic quantum circuit with the Fock backend, based on Fock basis state 99 | 100 | ```python 101 | cir = dq.QumodeCircuit(2, [1,1]) 102 | cir.dc([0,1]) 103 | cir.ps(0, 0.1) 104 | cir.bs([0,1], [0.2,0.3]) 105 | print(cir()) 106 | print(cir.measure()) 107 | ``` 108 | 109 | - Photonic quantum circuit with the Fock backend, based on Fock state tensor 110 | 111 | ```python 112 | cir = dq.QumodeCircuit(2, [(1, [1,1])], basis=False) 113 | cir.dc([0,1]) 114 | cir.ps(0, 0.1) 115 | cir.bs([0,1], [0.2,0.3]) 116 | print(cir()) 117 | print(cir.measure()) 118 | ``` 119 | 120 | - Photonic quantum circuit with the Gaussian backend 121 | 122 | ```python 123 | cir = dq.QumodeCircuit(2, 'vac', cutoff=10, backend='gaussian') 124 | cir.s(0, 0.1) 125 | cir.d(1, 0.1) 126 | cir.bs([0,1], [0.2,0.3]) 127 | print(cir()) 128 | print(cir.measure()) 129 | print(cir.photon_number_mean_var(wires=0)) 130 | print(cir.measure_homodyne(wires=1)) 131 | ``` 132 | 133 | - Photonic quantum circuit with the Bosonic backend 134 | 135 | ```python 136 | cir = dq.QumodeCircuit(2, 'vac', backend='bosonic') 137 | cir.cat(0, 0.5, 0.0) 138 | cir.gkp(1, 0.5, 0.5) 139 | cir.bs([0,1], [0.2,0.3]) 140 | print(cir()) 141 | print(cir.photon_number_mean_var(wires=0)) 142 | print(cir.measure_homodyne(wires=1)) 143 | ``` 144 | 145 | - Pattern of measurement-based quantum computation 146 | 147 | ```python 148 | pattern = dq.Pattern(2) 149 | # Hadamard gate on qubit 1 150 | pattern.n(2) 151 | pattern.e(1, 2) 152 | pattern.m(1) 153 | pattern.x(2, domain=1) 154 | # CNOT 155 | pattern.n([3,4]) 156 | pattern.e(2, 3) 157 | pattern.e(0, 3) 158 | pattern.e(3, 4) 159 | pattern.m(2) 160 | pattern.m(3) 161 | pattern.x(4, domain=3) 162 | pattern.z(4, domain=2) 163 | pattern.z(0, domain=2) 164 | print(abs(pattern().full_state)) 165 | ``` 166 | 167 | - Transpile quantum circuit to MBQC pattern 168 | 169 | ```python 170 | cir = dq.QubitCircuit(2) 171 | cir.h(0) 172 | cir.cnot(0, 1) 173 | cir.rx(1, 0.2) 174 | pattern = cir.pattern() 175 | print(cir()) 176 | print(pattern().full_state) 177 | print(cir() / pattern().full_state) 178 | ``` 179 | 180 | # License 181 | 182 | DeepQuantum is open source, released under the Apache License, Version 2.0. -------------------------------------------------------------------------------- /docs/assets/deepquantum_architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/docs/assets/deepquantum_architecture.png -------------------------------------------------------------------------------- /docs/assets/deepquantum_logo_light_v1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/docs/assets/deepquantum_logo_light_v1.png -------------------------------------------------------------------------------- /docs/sphinx_doc/.gitignore: -------------------------------------------------------------------------------- 1 | _build/ -------------------------------------------------------------------------------- /docs/sphinx_doc/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 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 | -------------------------------------------------------------------------------- /docs/sphinx_doc/README.md: -------------------------------------------------------------------------------- 1 | 本目录用于构建 API 文档 2 | 3 | ## 依赖 4 | 5 | Python >= 3.8 6 | 7 | `pip install -r sphinx_doc/requirements.txt` 8 | 9 | 10 | ## 构建 11 | 12 | `make html` 13 | -------------------------------------------------------------------------------- /docs/sphinx_doc/_static/es5/input/tex/extensions/braket.js: -------------------------------------------------------------------------------- 1 | !function(){"use strict";var t,e,a,r,o,n={667:function(t,e){e.q=void 0,e.q="3.2.2"},243:function(t,e,a){var r;Object.defineProperty(e,"__esModule",{value:!0}),e.BraketConfiguration=void 0;var o=a(251),n=a(519);a(299),e.BraketConfiguration=o.Configuration.create("braket",{handler:{character:["Braket-characters"],macro:["Braket-macros"]},items:(r={},r[n.BraketItem.prototype.kind]=n.BraketItem,r)})},519:function(t,e,a){var r,o=this&&this.__extends||(r=function(t,e){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var a in e)Object.prototype.hasOwnProperty.call(e,a)&&(t[a]=e[a])},r(t,e)},function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Class extends value "+String(e)+" is not a constructor or null");function a(){this.constructor=t}r(t,e),t.prototype=null===e?Object.create(e):(a.prototype=e.prototype,new a)}),n=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(e,"__esModule",{value:!0}),e.BraketItem=void 0;var i=a(76),l=a(801),c=n(a(398)),s=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return o(e,t),Object.defineProperty(e.prototype,"kind",{get:function(){return"braket"},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"isOpen",{get:function(){return!0},enumerable:!1,configurable:!0}),e.prototype.checkItem=function(e){return e.isKind("close")?[[this.factory.create("mml",this.toMml())],!0]:e.isKind("mml")?(this.Push(e.toMml()),this.getProperty("single")?[[this.toMml()],!0]:i.BaseItem.fail):t.prototype.checkItem.call(this,e)},e.prototype.toMml=function(){var e=t.prototype.toMml.call(this),a=this.getProperty("open"),r=this.getProperty("close");if(this.getProperty("stretchy"))return c.default.fenced(this.factory.configuration,a,e,r);var o={fence:!0,stretchy:!1,symmetric:!0,texClass:l.TEXCLASS.OPEN},n=this.create("token","mo",o,a);o.texClass=l.TEXCLASS.CLOSE;var i=this.create("token","mo",o,r);return this.create("node","mrow",[n,e,i],{open:a,close:r,texClass:l.TEXCLASS.INNER})},e}(i.BaseItem);e.BraketItem=s},299:function(t,e,a){var r=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(e,"__esModule",{value:!0});var o=a(871),n=r(a(277));new o.CommandMap("Braket-macros",{bra:["Macro","{\\langle {#1} \\vert}",1],ket:["Macro","{\\vert {#1} \\rangle}",1],braket:["Braket","\u27e8","\u27e9",!1,1/0],set:["Braket","{","}",!1,1],Bra:["Macro","{\\left\\langle {#1} \\right\\vert}",1],Ket:["Macro","{\\left\\vert {#1} \\right\\rangle}",1],Braket:["Braket","\u27e8","\u27e9",!0,1/0],Set:["Braket","{","}",!0,1],ketbra:["Macro","{\\vert {#1} \\rangle\\langle {#2} \\vert}",2],Ketbra:["Macro","{\\left\\vert {#1} \\right\\rangle\\left\\langle {#2} \\right\\vert}",2],"|":"Bar"},n.default),new o.MacroMap("Braket-characters",{"|":"Bar"},n.default)},277:function(t,e,a){var r=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(e,"__esModule",{value:!0});var o=r(a(360)),n=a(801),i=r(a(402)),l={};l.Macro=o.default.Macro,l.Braket=function(t,e,a,r,o,n){var l=t.GetNext();if(""===l)throw new i.default("MissingArgFor","Missing argument for %1",t.currentCS);var c=!0;"{"===l&&(t.i++,c=!1),t.Push(t.itemFactory.create("braket").setProperties({barmax:n,barcount:0,open:a,close:r,stretchy:o,single:c}))},l.Bar=function(t,e){var a="|"===e?"|":"\u2225",r=t.stack.Top();if("braket"!==r.kind||r.getProperty("barcount")>=r.getProperty("barmax")){var o=t.create("token","mo",{texClass:n.TEXCLASS.ORD,stretchy:!1},a);t.Push(o)}else{if("|"===a&&"|"===t.GetNext()&&(t.i++,a="\u2225"),r.getProperty("stretchy")){var i=t.create("node","TeXAtom",[],{texClass:n.TEXCLASS.CLOSE});t.Push(i),r.setProperty("barcount",r.getProperty("barcount")+1),i=t.create("token","mo",{stretchy:!0,braketbar:!0},a),t.Push(i),i=t.create("node","TeXAtom",[],{texClass:n.TEXCLASS.OPEN}),t.Push(i)}else{var l=t.create("token","mo",{stretchy:!1,braketbar:!0},a);t.Push(l)}}},e.default=l},955:function(t,e){MathJax._.components.global.isObject,MathJax._.components.global.combineConfig,MathJax._.components.global.combineDefaults,e.r8=MathJax._.components.global.combineWithMathJax,MathJax._.components.global.MathJax},801:function(t,e){Object.defineProperty(e,"__esModule",{value:!0}),e.TEXCLASS=MathJax._.core.MmlTree.MmlNode.TEXCLASS,e.TEXCLASSNAMES=MathJax._.core.MmlTree.MmlNode.TEXCLASSNAMES,e.indentAttributes=MathJax._.core.MmlTree.MmlNode.indentAttributes,e.AbstractMmlNode=MathJax._.core.MmlTree.MmlNode.AbstractMmlNode,e.AbstractMmlTokenNode=MathJax._.core.MmlTree.MmlNode.AbstractMmlTokenNode,e.AbstractMmlLayoutNode=MathJax._.core.MmlTree.MmlNode.AbstractMmlLayoutNode,e.AbstractMmlBaseNode=MathJax._.core.MmlTree.MmlNode.AbstractMmlBaseNode,e.AbstractMmlEmptyNode=MathJax._.core.MmlTree.MmlNode.AbstractMmlEmptyNode,e.TextNode=MathJax._.core.MmlTree.MmlNode.TextNode,e.XMLNode=MathJax._.core.MmlTree.MmlNode.XMLNode},251:function(t,e){Object.defineProperty(e,"__esModule",{value:!0}),e.Configuration=MathJax._.input.tex.Configuration.Configuration,e.ConfigurationHandler=MathJax._.input.tex.Configuration.ConfigurationHandler,e.ParserConfiguration=MathJax._.input.tex.Configuration.ParserConfiguration},398:function(t,e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=MathJax._.input.tex.ParseUtil.default},76:function(t,e){Object.defineProperty(e,"__esModule",{value:!0}),e.MmlStack=MathJax._.input.tex.StackItem.MmlStack,e.BaseItem=MathJax._.input.tex.StackItem.BaseItem},871:function(t,e){Object.defineProperty(e,"__esModule",{value:!0}),e.parseResult=MathJax._.input.tex.SymbolMap.parseResult,e.AbstractSymbolMap=MathJax._.input.tex.SymbolMap.AbstractSymbolMap,e.RegExpMap=MathJax._.input.tex.SymbolMap.RegExpMap,e.AbstractParseMap=MathJax._.input.tex.SymbolMap.AbstractParseMap,e.CharacterMap=MathJax._.input.tex.SymbolMap.CharacterMap,e.DelimiterMap=MathJax._.input.tex.SymbolMap.DelimiterMap,e.MacroMap=MathJax._.input.tex.SymbolMap.MacroMap,e.CommandMap=MathJax._.input.tex.SymbolMap.CommandMap,e.EnvironmentMap=MathJax._.input.tex.SymbolMap.EnvironmentMap},402:function(t,e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=MathJax._.input.tex.TexError.default},360:function(t,e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=MathJax._.input.tex.base.BaseMethods.default}},i={};function l(t){var e=i[t];if(void 0!==e)return e.exports;var a=i[t]={exports:{}};return n[t].call(a.exports,a,a.exports,l),a.exports}t=l(955),e=l(667),a=l(243),r=l(519),o=l(277),MathJax.loader&&MathJax.loader.checkVersion("[tex]/braket",e.q,"tex-extension"),(0,t.r8)({_:{input:{tex:{braket:{BraketConfiguration:a,BraketItems:r,BraketMethods:o}}}}})}(); -------------------------------------------------------------------------------- /docs/sphinx_doc/_static/es5/output/chtml/fonts/woff-v2/MathJax_Main-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/docs/sphinx_doc/_static/es5/output/chtml/fonts/woff-v2/MathJax_Main-Regular.woff -------------------------------------------------------------------------------- /docs/sphinx_doc/_static/es5/output/chtml/fonts/woff-v2/MathJax_Math-Italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/docs/sphinx_doc/_static/es5/output/chtml/fonts/woff-v2/MathJax_Math-Italic.woff -------------------------------------------------------------------------------- /docs/sphinx_doc/_static/es5/output/chtml/fonts/woff-v2/MathJax_Size1-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/docs/sphinx_doc/_static/es5/output/chtml/fonts/woff-v2/MathJax_Size1-Regular.woff -------------------------------------------------------------------------------- /docs/sphinx_doc/_static/es5/output/chtml/fonts/woff-v2/MathJax_Size3-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/docs/sphinx_doc/_static/es5/output/chtml/fonts/woff-v2/MathJax_Size3-Regular.woff -------------------------------------------------------------------------------- /docs/sphinx_doc/_static/es5/output/chtml/fonts/woff-v2/MathJax_Size4-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/docs/sphinx_doc/_static/es5/output/chtml/fonts/woff-v2/MathJax_Size4-Regular.woff -------------------------------------------------------------------------------- /docs/sphinx_doc/_static/es5/output/chtml/fonts/woff-v2/MathJax_Zero.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/docs/sphinx_doc/_static/es5/output/chtml/fonts/woff-v2/MathJax_Zero.woff -------------------------------------------------------------------------------- /docs/sphinx_doc/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # For the full list of built-in configuration values, see the documentation: 4 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 5 | 6 | # -- Project information ----------------------------------------------------- 7 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information 8 | import sys 9 | sys.path.insert(0, '/opt/deepquantum/src') 10 | import deepquantum 11 | 12 | 13 | project = 'DeepQuantum' 14 | copyright = '2024, TuringQ' 15 | author = 'TuringQ' 16 | release = f'v{deepquantum.__version__}' 17 | language = 'zh_CN' 18 | 19 | # -- General configuration --------------------------------------------------- 20 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration 21 | 22 | extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon', 'myst_parser'] 23 | 24 | myst_enable_extensions = [ 25 | "amsmath", 26 | "attrs_inline", 27 | "colon_fence", 28 | "deflist", 29 | "dollarmath", 30 | "fieldlist", 31 | "html_admonition", 32 | "html_image", 33 | # "linkify", 34 | "replacements", 35 | "smartquotes", 36 | "strikethrough", 37 | "substitution", 38 | "tasklist", 39 | ] 40 | 41 | napoleon_google_docstring = True 42 | napoleon_numpy_docstring = True 43 | napoleon_include_init_with_doc = False 44 | napoleon_include_private_with_doc = False 45 | napoleon_include_special_with_doc = False 46 | napoleon_use_admonition_for_examples = False 47 | napoleon_use_admonition_for_notes = False 48 | napoleon_use_admonition_for_references = False 49 | napoleon_use_ivar = False 50 | napoleon_use_param = True 51 | napoleon_use_rtype = True 52 | 53 | templates_path = ['_templates'] 54 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 55 | 56 | autodoc_default_options = { 57 | 'exclude-members': 'training, extra_repr', 58 | 'member-order': 'bysource' 59 | } 60 | 61 | mathjax_path = 'es5/tex-mml-chtml.js' 62 | # mathjax_local_fonts = True 63 | 64 | # -- Options for HTML output ------------------------------------------------- 65 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output 66 | 67 | # html_theme = 'sphinx_rtd_theme' 68 | html_theme = 'pydata_sphinx_theme' 69 | html_static_path = ['_static'] 70 | html_show_sphinx = False 71 | html_show_sourcelink = False 72 | html_copy_source = False 73 | html_theme_options = { 74 | 'footer_end': [], 75 | } 76 | html_sidebars = { 77 | "**": [] 78 | } 79 | 80 | html_title = f'DeepQuantum v{deepquantum.__version__}' 81 | -------------------------------------------------------------------------------- /docs/sphinx_doc/deepquantum.photonic.rst: -------------------------------------------------------------------------------- 1 | deepquantum.photonic package 2 | ============================ 3 | 4 | Submodules 5 | ---------- 6 | 7 | deepquantum.photonic.ansatz module 8 | ---------------------------------- 9 | 10 | .. automodule:: deepquantum.photonic.ansatz 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | deepquantum.photonic.circuit module 16 | ----------------------------------- 17 | 18 | .. automodule:: deepquantum.photonic.circuit 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | deepquantum.photonic.decompose module 24 | ------------------------------------- 25 | 26 | .. automodule:: deepquantum.photonic.decompose 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | deepquantum.photonic.draw module 32 | -------------------------------- 33 | 34 | .. automodule:: deepquantum.photonic.draw 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | deepquantum.photonic.gate module 40 | -------------------------------- 41 | 42 | .. automodule:: deepquantum.photonic.gate 43 | :members: 44 | :undoc-members: 45 | :show-inheritance: 46 | 47 | deepquantum.photonic.mapper module 48 | ---------------------------------- 49 | 50 | .. automodule:: deepquantum.photonic.mapper 51 | :members: 52 | :undoc-members: 53 | :show-inheritance: 54 | 55 | deepquantum.photonic.operation module 56 | ------------------------------------- 57 | 58 | .. automodule:: deepquantum.photonic.operation 59 | :members: 60 | :undoc-members: 61 | :show-inheritance: 62 | 63 | deepquantum.photonic.qmath module 64 | --------------------------------- 65 | 66 | .. automodule:: deepquantum.photonic.qmath 67 | :members: 68 | :undoc-members: 69 | :show-inheritance: 70 | 71 | deepquantum.photonic.state module 72 | --------------------------------- 73 | 74 | .. automodule:: deepquantum.photonic.state 75 | :members: 76 | :undoc-members: 77 | :show-inheritance: 78 | 79 | deepquantum.photonic.utils module 80 | --------------------------------- 81 | 82 | .. automodule:: deepquantum.photonic.utils 83 | :members: 84 | :undoc-members: 85 | :show-inheritance: 86 | 87 | Module contents 88 | --------------- 89 | 90 | .. automodule:: deepquantum.photonic 91 | :members: 92 | :undoc-members: 93 | :show-inheritance: 94 | -------------------------------------------------------------------------------- /docs/sphinx_doc/deepquantum.rst: -------------------------------------------------------------------------------- 1 | API 2 | =================== 3 | 4 | Photonic 5 | ----------- 6 | 7 | .. toctree:: 8 | :maxdepth: 4 9 | 10 | deepquantum.photonic 11 | 12 | Submodules 13 | ---------- 14 | 15 | deepquantum.ansatz module 16 | ------------------------- 17 | 18 | .. automodule:: deepquantum.ansatz 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | deepquantum.circuit module 24 | -------------------------- 25 | 26 | .. automodule:: deepquantum.circuit 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | deepquantum.gate module 32 | ----------------------- 33 | 34 | .. automodule:: deepquantum.gate 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | deepquantum.layer module 40 | ------------------------ 41 | 42 | .. automodule:: deepquantum.layer 43 | :members: 44 | :undoc-members: 45 | :show-inheritance: 46 | 47 | deepquantum.operation module 48 | ---------------------------- 49 | 50 | .. automodule:: deepquantum.operation 51 | :members: 52 | :undoc-members: 53 | :show-inheritance: 54 | 55 | deepquantum.optimizer module 56 | ---------------------------- 57 | 58 | .. automodule:: deepquantum.optimizer 59 | :members: 60 | :undoc-members: 61 | :show-inheritance: 62 | 63 | deepquantum.qmath module 64 | ------------------------ 65 | 66 | .. automodule:: deepquantum.qmath 67 | :members: 68 | :undoc-members: 69 | :show-inheritance: 70 | 71 | deepquantum.state module 72 | ------------------------ 73 | 74 | .. automodule:: deepquantum.state 75 | :members: 76 | :undoc-members: 77 | :show-inheritance: 78 | 79 | deepquantum.utils module 80 | ------------------------ 81 | 82 | .. automodule:: deepquantum.utils 83 | :members: 84 | :undoc-members: 85 | :show-inheritance: 86 | 87 | Module contents 88 | --------------- 89 | 90 | .. automodule:: deepquantum 91 | :members: 92 | :undoc-members: 93 | :show-inheritance: 94 | -------------------------------------------------------------------------------- /docs/sphinx_doc/images/3.3_Gradient_benchmarks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/docs/sphinx_doc/images/3.3_Gradient_benchmarks.png -------------------------------------------------------------------------------- /docs/sphinx_doc/images/3.3_Hessian_benchmarks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/docs/sphinx_doc/images/3.3_Hessian_benchmarks.png -------------------------------------------------------------------------------- /docs/sphinx_doc/images/grad_benchmark_vqnet_dq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/docs/sphinx_doc/images/grad_benchmark_vqnet_dq.png -------------------------------------------------------------------------------- /docs/sphinx_doc/index.rst: -------------------------------------------------------------------------------- 1 | .. DeepQuantum documentation master file, created by 2 | sphinx-quickstart on Mon Aug 21 07:35:47 2023. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to DeepQuantum's documentation! 7 | ======================================= 8 | 9 | 10 | .. toctree:: 11 | :maxdepth: 2 12 | 13 | 引言和概述 14 | 基础使用指南 15 | 案例 16 | deepquantum 17 | 18 | 19 | Indices and tables 20 | ================== 21 | 22 | * :ref:`genindex` 23 | * :ref:`modindex` 24 | * :ref:`search` 25 | -------------------------------------------------------------------------------- /docs/sphinx_doc/intro.md: -------------------------------------------------------------------------------- 1 | # deepquantum 使用说明 2 | 3 | ## 1.引言和概述 4 | 5 | 6 | 量子计算是一个蓬勃发展的领域,有望为未来巨大的算力需求提供解决方案,而结合了机器学习(深度学习)的量子机器学习(量子深度学习)也有望 7 | 产生巨大的价值。 在目前的NISQ时代,由于真实的量子计算资源过于昂贵而无法获得或难以获得,对于量子机器学习的研究在很大程度上需要借助经 8 | 典计算机对量子线路进行模拟。 因此,基于这个领域在未来的无限可能,在真正的容错通用量子计算机落地前,国内外各家相关公司早已在编程框架 9 | 、软件服务方面进行了布局,以利用先发优势吸引和培养潜在用户。 10 | 11 | 在深度学习时代,一个量子计算框架所能支持的模拟规模、是否能够利用GPU的算力来提升效率、与机器学习/深度学习库结合的紧密程度以及其易用性 12 | 、便捷性都是重要的考量。 同时,具有影响力的量子计算框架往往也肩负着通过云平台为用户提供真实量子计算资源的使命。 13 | 14 | DeepQuantum是一款基于PyTorch的轻量级的量子编程框架,用于量子计算、量子神经网络和混合量子-经典算法的编程和模拟。因此可以很自然地与 15 | PyTorch做到无缝衔接,编程风格也十分接近PyTorch本身的用法。 对于计算机背景出身、熟悉或接触过PyTorch的开发者来说更加友好,学习门槛低 16 | ,很容易上手,更加适合相关开发者从机器学习(深度学习)进入到量子机器学习(量子深度学习)。 经过精心的设计,DeepQuantum在初始化量子 17 | 神经网络时更加便捷,进行数据编码时更加灵活。 同时,DeepQuantum中也实现了张量网络算法,支持基于矩阵乘积态的大规模量子线路模拟。 18 | 19 | ## 2.基础使用指南 20 | 21 | 导入DeepQuantum以及相关库 22 | 23 | ``` python 24 | import deepquantum as dq 25 | import torch 26 | import torch.nn as nn 27 | ``` 28 | -------------------------------------------------------------------------------- /docs/sphinx_doc/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | %SPHINXBUILD% >NUL 2>NUL 14 | if errorlevel 9009 ( 15 | echo. 16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 17 | echo.installed, then set the SPHINXBUILD environment variable to point 18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 19 | echo.may add the Sphinx directory to PATH. 20 | echo. 21 | echo.If you don't have Sphinx installed, grab it from 22 | echo.https://www.sphinx-doc.org/ 23 | exit /b 1 24 | ) 25 | 26 | if "%1" == "" goto help 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/sphinx_doc/modules.rst: -------------------------------------------------------------------------------- 1 | deepquantum 2 | =========== 3 | 4 | .. toctree:: 5 | :maxdepth: 4 6 | 7 | deepquantum 8 | -------------------------------------------------------------------------------- /docs/sphinx_doc/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx==6.2.1 2 | myst-parser==2.0.0 3 | # sphinx-rtd-theme 4 | pydata-sphinx-theme -------------------------------------------------------------------------------- /docs/sphinx_doc/基础使用指南.md: -------------------------------------------------------------------------------- 1 | # 基础使用指南 2 | 3 | 导入DeepQuantum以及相关库 4 | 5 | ```python 6 | import deepquantum as dq 7 | import deepquantum.photonic as dqp 8 | import torch 9 | import torch.nn as nn 10 | ``` 11 | 12 | ## 量子线路对象 13 | 14 | DeepQuantum的基本对象是QubitCircuit和QumodeCircuit。 15 | QubitCircuit用量子比特数(n)来初始化量子线路,即cir=dq.QubitCircuit(n)。 16 | QumodeCircuit用模式数(n)来初始化光量子线路,即cir=dq.QumodeCircuit(n)。 17 | DeepQuantum可以帮助用户很方便地实现参数化量子线路,从而进行量子机器学习。 18 | 19 | ## QubitCircuit基础使用说明 20 | 21 | ### 量子态 22 | 23 | QubitState是表示量子态的类。 24 | 比如,我们可以利用QubitState准备一个单比特量子态,其数据是torch的tensor,存在属性state中。 25 | 便捷地将经典数据编码为一个量子态 26 | 27 | ```python 28 | qstate = dq.QubitState(nqubit=1, state=[0,1]) 29 | print(qstate.state) 30 | ``` 31 | 32 | 此外,还可以调用一些内置的量子态。 33 | 默认初始化为全零态 34 | 35 | ```python 36 | qstate = dq.QubitState(nqubit=2, state='zeros') 37 | print(qstate.state) 38 | ``` 39 | 40 | 初始化为等权叠加态 41 | 42 | ```python 43 | qstate = dq.QubitState(nqubit=2, state='equal') 44 | print(qstate.state) 45 | ``` 46 | 47 | 初始化为GHZ态 48 | 49 | ```python 50 | qstate = dq.QubitState(nqubit=3, state='ghz') 51 | print(qstate.state) 52 | ``` 53 | 54 | ### 基本的量子门 55 | 56 | 我们可以将各种量子门作用在QubitCircuit上。 57 | 例如,我们可以将Hadamard门作用于1号量子比特:cir.h(1);将Rx门作用于2号量子比特:cir.rx(2, inputs=0.2);多量子比特门也一样:cir.cnot(0, 1)。 58 | 同时,我们还可以一次性在量子线路上放置一层量子门,如cir.rxlayer()。 59 | 如果量子门没有指定输入参数,则会自动初始化变分参数。 60 | 61 | ```python 62 | cir = dq.QubitCircuit(4) 63 | ``` 64 | 65 | 第一个参数wires指定放置的线路,自动初始化内部的变分参数 66 | 67 | ```python 68 | cir.rxlayer(wires=[0,2]) 69 | ``` 70 | 71 | 我们也可以手动初始化参数,具体如下所示。 72 | 利用inputs手动初始化固定参数 73 | 74 | ```python 75 | cir.rxlayer(wires=[0, 1, 2, ...], inputs=[theta_0, theta_1, ...]) 76 | ``` 77 | 78 | 如果要求参数是可训练的,可以参考以下示例 79 | 80 | ```python 81 | class MyCircuit(nn.Module): 82 | def __init__(self, nqubit): 83 | super().__init__() 84 | # 手动初始化变分参数为1 85 | self.params = nn.Parameter(torch.ones(nqubit)) 86 | self.cir = self.circuit(nqubit) 87 | 88 | def circuit(self, nqubit): 89 | cir = dq.QubitCircuit(nqubit) 90 | cir.hlayer() 91 | # 利用encode,指定变分参数编码到量子线路中的位置 92 | cir.rylayer(encode=True) 93 | cir.cnot_ring() 94 | for i in range(nqubit): 95 | cir.observable(i) 96 | return cir 97 | 98 | def forward(self): 99 | # 在前向过程中,变分参数作为data加入量子线路 100 | self.cir(data=self.params) 101 | return self.cir.expectation().mean() 102 | ``` 103 | 104 | DeepQuantum支持灵活地使用多控制位的量子门(即控制位均为1时,受控的量子门才起作用),具体如下所示。 105 | 106 | ```python 107 | cir = dq.QubitCircuit(4) 108 | cir.toffoli(0, 1, 2) # 按顺序指定控制位和目标位 109 | cir.fredkin(0, 1, 2) 110 | # 一般的量子门都可以通过controls参数来指定任意控制位 111 | cir.x(3, controls=[0,1,2]) 112 | cir.crx(0, 1) 113 | cir.crxx(0, 1, 2) 114 | cir.u3(2, controls=[0,1,3]) 115 | cir.draw() 116 | ``` 117 | 118 | ### 测量与期望 119 | 120 | #### 测量 121 | 122 | 测量是量子计算的核心操作之一。 123 | 我们以对GHZ态进行测量作为例子。 124 | 125 | ```python 126 | cir = dq.QubitCircuit(3) 127 | cir.h(0) 128 | cir.cnot(0, 1) 129 | cir.cnot(0, 2) 130 | cir.barrier() 131 | cir() 132 | # 对QubitCircuit中的末态进行测量,返回的结果是字典或者字典的列表 133 | # 字典的key是比特串,value是对应测量到的次数 134 | # 测量总数shots默认为1024 135 | # 比特串从左到右对应于线路从小到大 136 | # 即第一个qubit在最高位,最后一个qubit在最低位 137 | print(cir.measure()) 138 | # 我们也可以设定采样次数、进行部分测量以及显示理想的概率。 139 | print(cir.measure(shots=100, wires=[1,2], with_prob=True)) 140 | ``` 141 | 142 | #### 期望 143 | 144 | 使用参数化量子线路进行变分量子算法时,往往涉及对末态求某个力学量的期望值,下面我们就用最简单的量子线路演示一下。 145 | 146 | ```python 147 | cir = dq.QubitCircuit(4) 148 | cir.xlayer([0,2]) 149 | # 可以添加多个observable,各个期望值的结果会自动拼接起来 150 | # 还可以使用列表形式的组合来灵活地指定测量线路和测量基底 151 | # 如wires=[0,1,2]、basis='xyz' 152 | # 即表示0、1、2号线路上分别对应Pauli-X、Pauli-Y、Pauli-Z的力学量 153 | for i in range(4): 154 | cir.observable(i) 155 | cir() # 线路演化后才能得到期望值 156 | print(cir.expectation()) 157 | ``` 158 | 159 | #### 条件测量 160 | 161 | 使用condition参数可以实现条件测量,此时条件测量的位置由控制位controls决定。 162 | 163 | ```python 164 | cir = dq.QubitCircuit(3) 165 | cir.h(0) 166 | cir.x(1, controls=0, condition=True) 167 | cir.x(2, controls=1, condition=True) 168 | print(cir()) 169 | # 然后可以进行随机的延迟测量 170 | state, measure_rst, prob = cir.defer_measure(with_prob=True) 171 | print(state) 172 | # 也可以选择特定的测量结果 173 | print(cir.post_select(measure_rst)) 174 | cir.draw() 175 | ``` 176 | 177 | 注意,defer_measure和post_select并不改变QubitCircuit所保存的末态state,因此measure和expectation目前并不兼容条件测量。 178 | 179 | ## QumodeCircuit基础使用说明 180 | 181 | ### Fock后端的使用 182 | 183 | 使用Fock后端可以构建基于离散变量的光量子线路,basis=True对应着量子态用Fock基矢态表示,basis=False对应着量子态用Fock态张量表示。 184 | 185 | #### 量子态 186 | 187 | Fock基矢态表示只支持单一的量子态输入,Fock态张量表示支持叠加态输入。 188 | 189 | ```python 190 | qstate1 = dq.FockState(state=[1,0,1,0], basis=True) 191 | qstate2 = dq.FockState(state=[(0.6, [1,0,1,0]), (0.8, [1,1,0,0])], basis=False) 192 | print(qstate1, qstate2) 193 | ``` 194 | 195 | #### 基本量子门 196 | 197 | 我们可以将各种量子门作用在QumodeCircuit上。 198 | 例如,我们可以将移相器作用于第1个mode:cir.ps(0);将分束器作用于第1、2个mode:cir.bs([0,1])。 199 | 如果量子门没有指定输入参数,则会自动初始化变分参数。 200 | 201 | ```python 202 | init_state = [1,0] 203 | cir = dq.QumodeCircuit(nmode=2, init_state=init_state, cutoff=3, backend='fock', basis=True) 204 | cir.ps(0, torch.pi) 205 | cir.ps(1, torch.pi) 206 | cir.bs([0,1], [torch.pi/4, torch.pi/4]) 207 | cir.mzi([0,1], [torch.pi/4, torch.pi/4]) 208 | ``` 209 | 210 | #### 线路演化和测量 211 | 212 | ```python 213 | state = cir() 214 | sample = cir.measure() 215 | print(state, sample) 216 | ``` 217 | 218 | #### 线路可视化 219 | 220 | 通过cir.draw()可以将搭建的光量子线路可视化并保存 221 | 222 | ```python 223 | cir.draw(filename='circuit.svg') 224 | ``` 225 | 226 | ### Clements 的使用 227 | 228 | 构建基于Clements架构的光量子线路,可以通过Clements架构实现任意的光量子酉矩阵线路映射,下面是一个简单CNOT门的例子。 229 | 这里使用6模线路来实现一个1/9成功率的CNOT门,第1、2个mode对应控制比特,第3、4个mode对应目标比特,第5、6个mode为辅助mode。 230 | 231 | ```python 232 | u6x6 = torch.tensor([[1, 0, 1, -1, 0, 0], 233 | [0, 1, 0, 0, 0, 2 ** 0.5], 234 | [1, 0, 0, 1, 1, 0], 235 | [-1, 0, 1, 0, 1, 0], 236 | [0, 0, 1, 1, -1, 0], 237 | [0, 2 ** 0.5, 0, 0, 0, -1]]) / 3 ** 0.5 238 | # 将酉矩阵分解成Clements对应的参数 239 | ud = dq.UnitaryDecomposer(u6x6) 240 | angle_dict = ud.decomp()[2] 241 | clements = dq.Clements(nmode=6, init_state=[1,0,1,0,0,0], cutoff=3) 242 | data = clements.dict2data(angle_dict) # 将线路参数编码到6x6的Clements架构中 243 | state = clements(data=data) 244 | clements.draw() 245 | ``` 246 | 247 | 通过后选择挑选出对应的量子态,后选择规则是第1、2个mode探测到光子数之和为1,同时第3、4个mode探测到光子数之和也为1,挑选出的结果为|101000>,对应的概率为1/9。 248 | 249 | ### Gaussian后端的使用 250 | 251 | 使用Gaussian后端可以构建基于连续变量的光量子线路,量子态通过正交算符 $\hat{x}$ 和 $\hat{p}$ 的协方差矩阵和平均值矢量来表示。 252 | 253 | #### 量子态 254 | 255 | 高斯态通过协方差矩阵cov和平均值矢量mean来表示,'vac'对应真空态,也可以设置cov和mean。 256 | 257 | ```python 258 | qstate1 = dq.GaussianState(nmode=2, state='vac') 259 | cov = torch.eye(4) 260 | mean = torch.zeros(4) 261 | qstate2 = dq.GaussianState(nmode=2, state=[cov, mean]) 262 | print(qstate1, qstate2) 263 | ``` 264 | 265 | #### 基本量子门 266 | 267 | 高斯操作对应的量子门有单模压缩门s、位移门d、旋转门r和分束器bs等。 268 | 269 | ```python 270 | cir = dq.QumodeCircuit(nmode=2, init_state='vac', cutoff=3, backend='gaussian') 271 | cir.s(0, r=0.1) 272 | cir.s(1, r=0.2) 273 | cir.d(0, r=0.3) 274 | cir.d(1, r=0.4) 275 | cir.bs([0,1], [torch.pi/4, torch.pi/4]) 276 | #线路可视化 277 | cir.draw() 278 | ``` 279 | 280 | 上面的压缩门和位移门具有r和theta两个参数。 281 | 当用户只指定r时,theta默认为0。 282 | 当用户只指定theta时,r默认随机初始化。 283 | 284 | #### 线路演化和测量 285 | 286 | 这里measure_homodyne测量对应的物理量是正交算符 $\hat{x}$ 和 $\hat{p}$ 的值,photon_number_mean_var对应的是每个mode的光子数的平均值和方差。 287 | 288 | ```python 289 | state = cir() 290 | sample = cir.measure_homodyne() 291 | photon_number = cir.photon_number_mean_var() 292 | print(sample, photon_number) 293 | ``` 294 | 295 | ### 高斯玻色采样(GBS) 296 | 297 | 通过压缩门和线性光学器件构造高斯玻色采样的线路。 298 | 这里采用6个节点的图演示简单的高斯玻色采样。 299 | 300 | ```python 301 | adj_mat = torch.tensor([[0., 1., 1., 0., 0., 0.], 302 | [1., 0., 0., 1., 0., 1.], 303 | [1., 0., 0., 0., 0., 0.], 304 | [0., 1., 0., 0., 1., 1.], 305 | [0., 0., 0., 1., 0., 0.], 306 | [0., 1., 0., 1., 0., 0.]]) 307 | gbs = dqp.GBS_Graph(adj_mat=adj_mat, cutoff=2) 308 | state = gbs() 309 | sample = gbs.measure() # 高斯玻色采样 310 | print(sample) 311 | ``` 312 | 313 | 通过gbs.draw()可以可视化高斯玻色采样线路。 314 | 315 | ```python 316 | gbs.draw() 317 | ``` 318 | -------------------------------------------------------------------------------- /docs/sphinx_doc/引言和概述.md: -------------------------------------------------------------------------------- 1 | # 引言和概述 2 | 3 | 量子计算是一个蓬勃发展的领域,有望为未来巨大的算力需求提供解决方案,而结合了机器学习(深度学习)的量子机器学习(量子深度学习)也有望产生巨大的价值。 在目前的NISQ时代,由于真实的量子计算资源过于昂贵而无法获得或难以获得,对于量子机器学习的研究在很大程度上需要借助经典计算机对量子线路进行模拟。 因此,基于这个领域在未来的无限可能,在真正的容错通用量子计算机落地前,国内外各家相关公司早已在编程框架、软件服务方面进行了布局,以利用先发优势吸引和培养潜在用户。 4 | 5 | 在深度学习时代,一个量子计算框架所能支持的模拟规模、是否能够利用GPU的算力来提升效率、与机器学习/深度学习库结合的紧密程度以及其易用性、便捷性都是重要的考量。 同时,具有影响力的量子计算框架往往也肩负着通过云平台为用户提供真实量子计算资源的使命。 6 | 7 | DeepQuantum是一款基于PyTorch的轻量级的量子编程框架,用于量子计算、量子神经网络和混合量子-经典算法的编程和模拟。因此可以很自然地与PyTorch做到无缝衔接,编程风格也十分接近PyTorch本身的用法。 对于计算机背景出身、熟悉或接触过PyTorch的开发者来说更加友好,学习门槛低,很容易上手,更加适合相关开发者从机器学习(深度学习)进入到量子机器学习(量子深度学习)。 经过精心的设计,DeepQuantum在初始化量子神经网络时更加便捷,进行数据编码时更加灵活。 同时,DeepQuantum中也实现了张量网络算法,支持基于矩阵乘积态的大规模量子线路模拟。 -------------------------------------------------------------------------------- /docs/sphinx_doc_en/.gitignore: -------------------------------------------------------------------------------- 1 | _build/ -------------------------------------------------------------------------------- /docs/sphinx_doc_en/Basic_Usage_Guide.md: -------------------------------------------------------------------------------- 1 | # Basic Usage Guide 2 | 3 | Import DeepQuantum and related libraries. 4 | 5 | ```python 6 | import deepquantum as dq 7 | import torch 8 | import torch.nn as nn 9 | ``` 10 | 11 | ## Quantum Circuit Object 12 | 13 | The fundamental object in DeepQuantum is QubitCircuit. 14 | Initialize a quantum circuit with the number of qubits (n), i.e., cir=dq.QubitCircuit(n). 15 | DeepQuantum can help users to easily implement parameterized quantum circuits for quantum machine learning. 16 | 17 | ## Quantum State 18 | 19 | QubitState is a class representing quantum states. For example, we can use QubitState to prepare a single-qubit quantum state, with its data being a torch tensor, stored in the attribute state. 20 | 21 | Conveniently encode classical data into a quantum state 22 | 23 | ```python 24 | qstate = dq.QubitState(nqubit=1, state=[0,1]) 25 | print(qstate.state) 26 | ``` 27 | Additionally, some built-in quantum states can be invoked. 28 | 29 | Initialize to all-zero state by default 30 | 31 | ```python 32 | qstate = dq.QubitState(nqubit=2, state='zeros') 33 | print(qstate.state) 34 | ``` 35 | 36 | Initialize to equal-weighted superposition state 37 | 38 | ```python 39 | qstate = dq.QubitState(nqubit=2, state='equal') 40 | print(qstate.state) 41 | ``` 42 | 43 | Initialize to GHZ state 44 | 45 | ```python 46 | qstate = dq.QubitState(nqubit=3, state='ghz') 47 | print(qstate.state) 48 | ``` 49 | 50 | ## Basic Quantum Gates 51 | 52 | We can act various quantum gates on the QubitCircuit. For example, we can act the Hadamard gate on qubit 1: cir.h(1) or act the Rx gate on qubit 2: cir.rx(2, inputs=0.2), and it is similar for multi-qubit gates: cir.cnot(0, 1). 53 | Also, we can place a layer of quantum gates on the quantum circuit using one line, i.e., cir.rxlayer(). If the quantum gate does not have specified input parameters, variational parameters will be initialized automatically. 54 | 55 | ```python 56 | cir = dq.QubitCircuit(4) 57 | ``` 58 | 59 | The first parameter 'wires' specifies where to place the gates. 60 | The internal variational parameters are automatically initialized. 61 | 62 | ```python 63 | cir.rxlayer(wires=[0,2]) 64 | ``` 65 | 66 | We can also manually initialize the parameters, as shown below. 67 | 68 | Use 'inputs' to manually initialize fixed parameters 69 | 70 | ```python 71 | cir.rxlayer(wires=[0, 1, 2, ...], inputs=[theta_0, theta_1, ...]) 72 | ``` 73 | 74 | If the parameters are required to be trainable, see the following example 75 | 76 | ```python 77 | class MyCircuit(nn.Module): 78 | def __init__(self, nqubit): 79 | super().__init__() 80 | # Manually initialize the variational parameter to 1 81 | self.params = nn.Parameter(torch.ones(nqubit)) 82 | self.cir = self.circuit(nqubit) 83 | 84 | def circuit(self, nqubit): 85 | cir = dq.QubitCircuit(nqubit) 86 | cir.hlayer() 87 | # Using 'encode', specify where the variational parameters 88 | # are encoded into the quantum circuit 89 | cir.rylayer(encode=True) 90 | cir.cnot_ring() 91 | for i in range(nqubit): 92 | cir.observable(i) 93 | return cir 94 | 95 | def forward(self): 96 | # During the forward process, variational parameters are 97 | # added to the quantum circuit as 'data' 98 | self.cir(data=self.params) 99 | return self.cir.expectation().mean() 100 | ``` 101 | DeepQuantum supports the flexible use of multi-controlled quantum gates (i.e., the controlled quantum gate activates only when all control bits are 1), as illustrated below. 102 | 103 | ```python 104 | cir = dq.QubitCircuit(4) 105 | cir.toffoli(0, 1, 2) # Specify control bits and target bits in sequence 106 | cir.fredkin(0, 1, 2) 107 | # General quantum gates can specify any control bits using the 'controls' parameter 108 | cir.x(3, controls=[0,1,2]) 109 | cir.crx(0, 1) 110 | cir.crxx(0, 1, 2) 111 | cir.u3(2, controls=[0,1,3]) 112 | cir.draw() 113 | ``` 114 | 115 | ## Measurement and Expectation 116 | 117 | ### Measurement 118 | 119 | Measurement is one of the core operations in quantum computing. We take the measurement of a GHZ state as an example. 120 | 121 | ```python 122 | cir = dq.QubitCircuit(3) 123 | cir.h(0) 124 | cir.cnot(0, 1) 125 | cir.cnot(0, 2) 126 | cir.barrier() 127 | cir() 128 | # Measure the final state in QubitCircuit, and the returned result 129 | # is a dictionary or a list of dictionaries. 130 | # The dictionary uses bit strings as keys and their measured counts as values. 131 | # The default value of 'shots' is 1024. 132 | # The bit string from left to right corresponds to the order of wires, which means 133 | # the first qubit is at the top, and the last qubit is at the bottom. 134 | print(cir.measure()) 135 | # We can also set the sampling number, perform partial measurements, 136 | # and display ideal probabilities. 137 | print(cir.measure(shots=100, wires=[1,2], with_prob=True)) 138 | ``` 139 | 140 | ### Expectation 141 | 142 | When employing parameterized quantum circuits in variational quantum algorithms, it often involves calculating the expectation value of an observable for the final state. Here, we'll demonstrate this with the simplest quantum circuit. 143 | 144 | ```python 145 | cir = dq.QubitCircuit(4) 146 | cir.xlayer([0,2]) 147 | # Multiple observables can be added, and the results of 148 | # each expectation value will be automatically concatenated 149 | # Flexibly specify measurement wires and bases using a list-based combination 150 | # e.g., wires=[0,1,2]、basis='xyz' representing the observable whose 151 | # wires 0, 1, and 2 corresponds to Pauli-X, Pauli-Y, and Pauli-Z, respectively 152 | for i in range(4): 153 | cir.observable(i) 154 | cir() # Expectation value can be obtained after running the circuit 155 | print(cir.expectation()) 156 | ``` 157 | 158 | ### Conditional Measurement 159 | 160 | The condition parameter allows conditional measurement, and the related wires are determined by control bits controls. 161 | 162 | ```python 163 | cir = dq.QubitCircuit(3) 164 | cir.h(0) 165 | cir.x(1, controls=0, condition=True) 166 | cir.x(2, controls=1, condition=True) 167 | print(cir()) 168 | # Conduct random delay measurements 169 | state, measure_rst, prob = cir.defer_measure(with_prob=True) 170 | print(state) 171 | # Choose specific measurement results 172 | print(cir.post_select(measure_rst)) 173 | cir.draw() 174 | ``` 175 | 176 | Note: defer_measure and post_select do not alter the final state state stored by QubitCircuit, making them incompatible with measure and expectation for conditional measurement. -------------------------------------------------------------------------------- /docs/sphinx_doc_en/Introduction_and_Overview.md: -------------------------------------------------------------------------------- 1 | # Introduction and Overview 2 | 3 | Quantum computing is a rapidly growing field, poised to address the enormous computational power demands of the future. The integration of machine learning (deep learning) into quantum machine learning (quantum deep learning) also holds the potential for significant value. In the current Noisy Intermediate-Scale Quantum (NISQ) era, due to the prohibitive cost and limited accessibility of real quantum computing resources, research in QML largely depends on classical computers to simulate quantum circuits. Therefore, with the boundless potential of this field, both domestic and international companies have already laid the groundwork in programming frameworks and software services, capitalizing on early-mover advantages to attract and cultivate potential users, even before the advent of fault-tolerant universal quantum computers. 4 | 5 | In the era of deep learning, important considerations for a quantum computing framework include its simulation scale, the ability to leverage GPU power for efficiency, the degree of integration with machine learning/deep learning libraries, and its user-friendliness and convenience. Influential quantum computing frameworks often aim to provide real quantum computing resources to users through cloud platforms. 6 | 7 | DeepQuantum is a lightweight quantum programming framework based on PyTorch, designed for programming and simulating quantum computing, quantum neural networks, and hybrid quantum-classical algorithms. It naturally integrates with PyTorch, offering a programming style closely aligned with PyTorch's own. This makes it more accessible to developers with a computer science background and those familiar with or exposed to PyTorch, lowering the learning curve and easing the transition from machine learning (deep learning) to quantum machine learning (quantum deep learning). DeepQuantum is meticulously designed for convenient initialization of quantum neural networks and flexible data encoding. It also implements tensor network algorithms, supporting large-scale quantum circuit simulations based on matrix product states. -------------------------------------------------------------------------------- /docs/sphinx_doc_en/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 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 | -------------------------------------------------------------------------------- /docs/sphinx_doc_en/_static/es5/input/tex/extensions/braket.js: -------------------------------------------------------------------------------- 1 | !function(){"use strict";var t,e,a,r,o,n={667:function(t,e){e.q=void 0,e.q="3.2.2"},243:function(t,e,a){var r;Object.defineProperty(e,"__esModule",{value:!0}),e.BraketConfiguration=void 0;var o=a(251),n=a(519);a(299),e.BraketConfiguration=o.Configuration.create("braket",{handler:{character:["Braket-characters"],macro:["Braket-macros"]},items:(r={},r[n.BraketItem.prototype.kind]=n.BraketItem,r)})},519:function(t,e,a){var r,o=this&&this.__extends||(r=function(t,e){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var a in e)Object.prototype.hasOwnProperty.call(e,a)&&(t[a]=e[a])},r(t,e)},function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Class extends value "+String(e)+" is not a constructor or null");function a(){this.constructor=t}r(t,e),t.prototype=null===e?Object.create(e):(a.prototype=e.prototype,new a)}),n=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(e,"__esModule",{value:!0}),e.BraketItem=void 0;var i=a(76),l=a(801),c=n(a(398)),s=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return o(e,t),Object.defineProperty(e.prototype,"kind",{get:function(){return"braket"},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"isOpen",{get:function(){return!0},enumerable:!1,configurable:!0}),e.prototype.checkItem=function(e){return e.isKind("close")?[[this.factory.create("mml",this.toMml())],!0]:e.isKind("mml")?(this.Push(e.toMml()),this.getProperty("single")?[[this.toMml()],!0]:i.BaseItem.fail):t.prototype.checkItem.call(this,e)},e.prototype.toMml=function(){var e=t.prototype.toMml.call(this),a=this.getProperty("open"),r=this.getProperty("close");if(this.getProperty("stretchy"))return c.default.fenced(this.factory.configuration,a,e,r);var o={fence:!0,stretchy:!1,symmetric:!0,texClass:l.TEXCLASS.OPEN},n=this.create("token","mo",o,a);o.texClass=l.TEXCLASS.CLOSE;var i=this.create("token","mo",o,r);return this.create("node","mrow",[n,e,i],{open:a,close:r,texClass:l.TEXCLASS.INNER})},e}(i.BaseItem);e.BraketItem=s},299:function(t,e,a){var r=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(e,"__esModule",{value:!0});var o=a(871),n=r(a(277));new o.CommandMap("Braket-macros",{bra:["Macro","{\\langle {#1} \\vert}",1],ket:["Macro","{\\vert {#1} \\rangle}",1],braket:["Braket","\u27e8","\u27e9",!1,1/0],set:["Braket","{","}",!1,1],Bra:["Macro","{\\left\\langle {#1} \\right\\vert}",1],Ket:["Macro","{\\left\\vert {#1} \\right\\rangle}",1],Braket:["Braket","\u27e8","\u27e9",!0,1/0],Set:["Braket","{","}",!0,1],ketbra:["Macro","{\\vert {#1} \\rangle\\langle {#2} \\vert}",2],Ketbra:["Macro","{\\left\\vert {#1} \\right\\rangle\\left\\langle {#2} \\right\\vert}",2],"|":"Bar"},n.default),new o.MacroMap("Braket-characters",{"|":"Bar"},n.default)},277:function(t,e,a){var r=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(e,"__esModule",{value:!0});var o=r(a(360)),n=a(801),i=r(a(402)),l={};l.Macro=o.default.Macro,l.Braket=function(t,e,a,r,o,n){var l=t.GetNext();if(""===l)throw new i.default("MissingArgFor","Missing argument for %1",t.currentCS);var c=!0;"{"===l&&(t.i++,c=!1),t.Push(t.itemFactory.create("braket").setProperties({barmax:n,barcount:0,open:a,close:r,stretchy:o,single:c}))},l.Bar=function(t,e){var a="|"===e?"|":"\u2225",r=t.stack.Top();if("braket"!==r.kind||r.getProperty("barcount")>=r.getProperty("barmax")){var o=t.create("token","mo",{texClass:n.TEXCLASS.ORD,stretchy:!1},a);t.Push(o)}else{if("|"===a&&"|"===t.GetNext()&&(t.i++,a="\u2225"),r.getProperty("stretchy")){var i=t.create("node","TeXAtom",[],{texClass:n.TEXCLASS.CLOSE});t.Push(i),r.setProperty("barcount",r.getProperty("barcount")+1),i=t.create("token","mo",{stretchy:!0,braketbar:!0},a),t.Push(i),i=t.create("node","TeXAtom",[],{texClass:n.TEXCLASS.OPEN}),t.Push(i)}else{var l=t.create("token","mo",{stretchy:!1,braketbar:!0},a);t.Push(l)}}},e.default=l},955:function(t,e){MathJax._.components.global.isObject,MathJax._.components.global.combineConfig,MathJax._.components.global.combineDefaults,e.r8=MathJax._.components.global.combineWithMathJax,MathJax._.components.global.MathJax},801:function(t,e){Object.defineProperty(e,"__esModule",{value:!0}),e.TEXCLASS=MathJax._.core.MmlTree.MmlNode.TEXCLASS,e.TEXCLASSNAMES=MathJax._.core.MmlTree.MmlNode.TEXCLASSNAMES,e.indentAttributes=MathJax._.core.MmlTree.MmlNode.indentAttributes,e.AbstractMmlNode=MathJax._.core.MmlTree.MmlNode.AbstractMmlNode,e.AbstractMmlTokenNode=MathJax._.core.MmlTree.MmlNode.AbstractMmlTokenNode,e.AbstractMmlLayoutNode=MathJax._.core.MmlTree.MmlNode.AbstractMmlLayoutNode,e.AbstractMmlBaseNode=MathJax._.core.MmlTree.MmlNode.AbstractMmlBaseNode,e.AbstractMmlEmptyNode=MathJax._.core.MmlTree.MmlNode.AbstractMmlEmptyNode,e.TextNode=MathJax._.core.MmlTree.MmlNode.TextNode,e.XMLNode=MathJax._.core.MmlTree.MmlNode.XMLNode},251:function(t,e){Object.defineProperty(e,"__esModule",{value:!0}),e.Configuration=MathJax._.input.tex.Configuration.Configuration,e.ConfigurationHandler=MathJax._.input.tex.Configuration.ConfigurationHandler,e.ParserConfiguration=MathJax._.input.tex.Configuration.ParserConfiguration},398:function(t,e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=MathJax._.input.tex.ParseUtil.default},76:function(t,e){Object.defineProperty(e,"__esModule",{value:!0}),e.MmlStack=MathJax._.input.tex.StackItem.MmlStack,e.BaseItem=MathJax._.input.tex.StackItem.BaseItem},871:function(t,e){Object.defineProperty(e,"__esModule",{value:!0}),e.parseResult=MathJax._.input.tex.SymbolMap.parseResult,e.AbstractSymbolMap=MathJax._.input.tex.SymbolMap.AbstractSymbolMap,e.RegExpMap=MathJax._.input.tex.SymbolMap.RegExpMap,e.AbstractParseMap=MathJax._.input.tex.SymbolMap.AbstractParseMap,e.CharacterMap=MathJax._.input.tex.SymbolMap.CharacterMap,e.DelimiterMap=MathJax._.input.tex.SymbolMap.DelimiterMap,e.MacroMap=MathJax._.input.tex.SymbolMap.MacroMap,e.CommandMap=MathJax._.input.tex.SymbolMap.CommandMap,e.EnvironmentMap=MathJax._.input.tex.SymbolMap.EnvironmentMap},402:function(t,e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=MathJax._.input.tex.TexError.default},360:function(t,e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=MathJax._.input.tex.base.BaseMethods.default}},i={};function l(t){var e=i[t];if(void 0!==e)return e.exports;var a=i[t]={exports:{}};return n[t].call(a.exports,a,a.exports,l),a.exports}t=l(955),e=l(667),a=l(243),r=l(519),o=l(277),MathJax.loader&&MathJax.loader.checkVersion("[tex]/braket",e.q,"tex-extension"),(0,t.r8)({_:{input:{tex:{braket:{BraketConfiguration:a,BraketItems:r,BraketMethods:o}}}}})}(); -------------------------------------------------------------------------------- /docs/sphinx_doc_en/_static/es5/output/chtml/fonts/woff-v2/MathJax_Main-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/docs/sphinx_doc_en/_static/es5/output/chtml/fonts/woff-v2/MathJax_Main-Regular.woff -------------------------------------------------------------------------------- /docs/sphinx_doc_en/_static/es5/output/chtml/fonts/woff-v2/MathJax_Math-Italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/docs/sphinx_doc_en/_static/es5/output/chtml/fonts/woff-v2/MathJax_Math-Italic.woff -------------------------------------------------------------------------------- /docs/sphinx_doc_en/_static/es5/output/chtml/fonts/woff-v2/MathJax_Size1-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/docs/sphinx_doc_en/_static/es5/output/chtml/fonts/woff-v2/MathJax_Size1-Regular.woff -------------------------------------------------------------------------------- /docs/sphinx_doc_en/_static/es5/output/chtml/fonts/woff-v2/MathJax_Size3-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/docs/sphinx_doc_en/_static/es5/output/chtml/fonts/woff-v2/MathJax_Size3-Regular.woff -------------------------------------------------------------------------------- /docs/sphinx_doc_en/_static/es5/output/chtml/fonts/woff-v2/MathJax_Size4-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/docs/sphinx_doc_en/_static/es5/output/chtml/fonts/woff-v2/MathJax_Size4-Regular.woff -------------------------------------------------------------------------------- /docs/sphinx_doc_en/_static/es5/output/chtml/fonts/woff-v2/MathJax_Zero.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/docs/sphinx_doc_en/_static/es5/output/chtml/fonts/woff-v2/MathJax_Zero.woff -------------------------------------------------------------------------------- /docs/sphinx_doc_en/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # For the full list of built-in configuration values, see the documentation: 4 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 5 | 6 | # -- Project information ----------------------------------------------------- 7 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information 8 | import sys 9 | sys.path.insert(0, '/opt/deepquantum/src') 10 | import deepquantum 11 | 12 | 13 | project = 'DeepQuantum' 14 | copyright = '2024, TuringQ' 15 | author = 'TuringQ' 16 | release = f'v{deepquantum.__version__}' 17 | language = 'en_US' 18 | 19 | # -- General configuration --------------------------------------------------- 20 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration 21 | 22 | extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon', 'myst_parser'] 23 | 24 | myst_enable_extensions = [ 25 | "amsmath", 26 | "attrs_inline", 27 | "colon_fence", 28 | "deflist", 29 | "dollarmath", 30 | "fieldlist", 31 | "html_admonition", 32 | "html_image", 33 | # "linkify", 34 | "replacements", 35 | "smartquotes", 36 | "strikethrough", 37 | "substitution", 38 | "tasklist", 39 | ] 40 | 41 | napoleon_google_docstring = True 42 | napoleon_numpy_docstring = True 43 | napoleon_include_init_with_doc = False 44 | napoleon_include_private_with_doc = False 45 | napoleon_include_special_with_doc = False 46 | napoleon_use_admonition_for_examples = False 47 | napoleon_use_admonition_for_notes = False 48 | napoleon_use_admonition_for_references = False 49 | napoleon_use_ivar = False 50 | napoleon_use_param = True 51 | napoleon_use_rtype = True 52 | 53 | templates_path = ['_templates'] 54 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 55 | 56 | autodoc_default_options = { 57 | 'exclude-members': 'training, extra_repr', 58 | 'member-order': 'bysource' 59 | } 60 | 61 | mathjax_path = 'es5/tex-mml-chtml.js' 62 | # mathjax_local_fonts = True 63 | 64 | # -- Options for HTML output ------------------------------------------------- 65 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output 66 | 67 | # html_theme = 'sphinx_rtd_theme' 68 | html_theme = 'pydata_sphinx_theme' 69 | html_static_path = ['_static'] 70 | html_show_sphinx = False 71 | html_show_sourcelink = False 72 | html_copy_source = False 73 | html_theme_options = { 74 | 'footer_end': [], 75 | } 76 | html_sidebars = { 77 | "**": [] 78 | } 79 | 80 | html_title = f'DeepQuantum v{deepquantum.__version__}' 81 | -------------------------------------------------------------------------------- /docs/sphinx_doc_en/deepquantum.photonic.rst: -------------------------------------------------------------------------------- 1 | deepquantum.photonic package 2 | ============================ 3 | 4 | Submodules 5 | ---------- 6 | 7 | deepquantum.photonic.ansatz module 8 | ---------------------------------- 9 | 10 | .. automodule:: deepquantum.photonic.ansatz 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | deepquantum.photonic.circuit module 16 | ----------------------------------- 17 | 18 | .. automodule:: deepquantum.photonic.circuit 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | deepquantum.photonic.decompose module 24 | ------------------------------------- 25 | 26 | .. automodule:: deepquantum.photonic.decompose 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | deepquantum.photonic.draw module 32 | -------------------------------- 33 | 34 | .. automodule:: deepquantum.photonic.draw 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | deepquantum.photonic.gate module 40 | -------------------------------- 41 | 42 | .. automodule:: deepquantum.photonic.gate 43 | :members: 44 | :undoc-members: 45 | :show-inheritance: 46 | 47 | deepquantum.photonic.mapper module 48 | ---------------------------------- 49 | 50 | .. automodule:: deepquantum.photonic.mapper 51 | :members: 52 | :undoc-members: 53 | :show-inheritance: 54 | 55 | deepquantum.photonic.operation module 56 | ------------------------------------- 57 | 58 | .. automodule:: deepquantum.photonic.operation 59 | :members: 60 | :undoc-members: 61 | :show-inheritance: 62 | 63 | deepquantum.photonic.qmath module 64 | --------------------------------- 65 | 66 | .. automodule:: deepquantum.photonic.qmath 67 | :members: 68 | :undoc-members: 69 | :show-inheritance: 70 | 71 | deepquantum.photonic.state module 72 | --------------------------------- 73 | 74 | .. automodule:: deepquantum.photonic.state 75 | :members: 76 | :undoc-members: 77 | :show-inheritance: 78 | 79 | deepquantum.photonic.utils module 80 | --------------------------------- 81 | 82 | .. automodule:: deepquantum.photonic.utils 83 | :members: 84 | :undoc-members: 85 | :show-inheritance: 86 | 87 | Module contents 88 | --------------- 89 | 90 | .. automodule:: deepquantum.photonic 91 | :members: 92 | :undoc-members: 93 | :show-inheritance: 94 | -------------------------------------------------------------------------------- /docs/sphinx_doc_en/deepquantum.rst: -------------------------------------------------------------------------------- 1 | API 2 | =================== 3 | 4 | Photonic 5 | ----------- 6 | 7 | .. toctree:: 8 | :maxdepth: 4 9 | 10 | deepquantum.photonic 11 | 12 | Submodules 13 | ---------- 14 | 15 | deepquantum.ansatz module 16 | ------------------------- 17 | 18 | .. automodule:: deepquantum.ansatz 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | deepquantum.circuit module 24 | -------------------------- 25 | 26 | .. automodule:: deepquantum.circuit 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | deepquantum.gate module 32 | ----------------------- 33 | 34 | .. automodule:: deepquantum.gate 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | deepquantum.layer module 40 | ------------------------ 41 | 42 | .. automodule:: deepquantum.layer 43 | :members: 44 | :undoc-members: 45 | :show-inheritance: 46 | 47 | deepquantum.operation module 48 | ---------------------------- 49 | 50 | .. automodule:: deepquantum.operation 51 | :members: 52 | :undoc-members: 53 | :show-inheritance: 54 | 55 | deepquantum.optimizer module 56 | ---------------------------- 57 | 58 | .. automodule:: deepquantum.optimizer 59 | :members: 60 | :undoc-members: 61 | :show-inheritance: 62 | 63 | deepquantum.qmath module 64 | ------------------------ 65 | 66 | .. automodule:: deepquantum.qmath 67 | :members: 68 | :undoc-members: 69 | :show-inheritance: 70 | 71 | deepquantum.state module 72 | ------------------------ 73 | 74 | .. automodule:: deepquantum.state 75 | :members: 76 | :undoc-members: 77 | :show-inheritance: 78 | 79 | deepquantum.utils module 80 | ------------------------ 81 | 82 | .. automodule:: deepquantum.utils 83 | :members: 84 | :undoc-members: 85 | :show-inheritance: 86 | 87 | Module contents 88 | --------------- 89 | 90 | .. automodule:: deepquantum 91 | :members: 92 | :undoc-members: 93 | :show-inheritance: 94 | -------------------------------------------------------------------------------- /docs/sphinx_doc_en/images/3.3_Gradient_benchmarks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/docs/sphinx_doc_en/images/3.3_Gradient_benchmarks.png -------------------------------------------------------------------------------- /docs/sphinx_doc_en/images/3.3_Hessian_benchmarks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/docs/sphinx_doc_en/images/3.3_Hessian_benchmarks.png -------------------------------------------------------------------------------- /docs/sphinx_doc_en/images/grad_benchmark_vqnet_dq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/docs/sphinx_doc_en/images/grad_benchmark_vqnet_dq.png -------------------------------------------------------------------------------- /docs/sphinx_doc_en/index.rst: -------------------------------------------------------------------------------- 1 | .. DeepQuantum documentation master file, created by 2 | sphinx-quickstart on Mon Aug 21 07:35:47 2023. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to DeepQuantum's documentation! 7 | ======================================= 8 | 9 | 10 | .. toctree:: 11 | :maxdepth: 2 12 | 13 | Introduction_and_Overview 14 | Basic_Usage_Guide 15 | Application_Cases 16 | deepquantum 17 | 18 | 19 | Indices and tables 20 | ================== 21 | 22 | * :ref:`genindex` 23 | * :ref:`modindex` 24 | * :ref:`search` 25 | -------------------------------------------------------------------------------- /docs/sphinx_doc_en/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | %SPHINXBUILD% >NUL 2>NUL 14 | if errorlevel 9009 ( 15 | echo. 16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 17 | echo.installed, then set the SPHINXBUILD environment variable to point 18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 19 | echo.may add the Sphinx directory to PATH. 20 | echo. 21 | echo.If you don't have Sphinx installed, grab it from 22 | echo.https://www.sphinx-doc.org/ 23 | exit /b 1 24 | ) 25 | 26 | if "%1" == "" goto help 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /examples/benchmarks/gradient_benchmark.py: -------------------------------------------------------------------------------- 1 | """ 2 | Gradient evaluation comparison between qiskit, tensorcircuit and deepquantum 3 | Modified from the implementation of tensorcircuit 4 | """ 5 | 6 | import time 7 | import json 8 | from functools import reduce 9 | from operator import xor 10 | import numpy as np 11 | 12 | from qiskit.opflow import X, StateFn 13 | from qiskit.circuit import QuantumCircuit, ParameterVector 14 | from qiskit.opflow.gradients import Gradient, Hessian 15 | 16 | import tensorcircuit as tc 17 | 18 | import torch 19 | from torch.autograd.functional import hessian 20 | import deepquantum as dq 21 | 22 | from pyvqnet.qnn import grad 23 | from pyvqnet.qnn.measure import expval 24 | import pyqpanda as pq 25 | 26 | 27 | def benchmark(f, *args, trials=10): 28 | time0 = time.time() 29 | r = f(*args) 30 | time1 = time.time() 31 | for _ in range(trials): 32 | r = f(*args) 33 | time2 = time.time() 34 | if trials > 0: 35 | time21 = (time2 - time1) / trials 36 | else: 37 | time21 = 0 38 | ts = (time1 - time0, time21) 39 | print('staging time: %.6f s' % ts[0]) 40 | if trials > 0: 41 | print('running time: %.6f s' % ts[1]) 42 | return r, ts 43 | 44 | 45 | def grad_qiskit(n, l, trials=2): 46 | hamiltonian = reduce(xor, [X for _ in range(n)]) 47 | wavefunction = QuantumCircuit(n) 48 | params = ParameterVector('theta', length=3 * n * l) 49 | for j in range(l): 50 | for i in range(n - 1): 51 | wavefunction.cnot(i, i + 1) 52 | for i in range(n): 53 | wavefunction.rx(params[3 * n * j + i], i) 54 | for i in range(n): 55 | wavefunction.rz(params[3 * n * j + i + n], i) 56 | for i in range(n): 57 | wavefunction.rx(params[3 * n * j + i + 2 * n], i) 58 | 59 | # Define the expectation value corresponding to the energy 60 | op = ~StateFn(hamiltonian) @ StateFn(wavefunction) 61 | grad = Gradient().convert(operator=op, params=params) 62 | 63 | def get_grad_qiskit(values): 64 | value_dict = {params: values} 65 | grad_result = grad.assign_parameters(value_dict).eval() 66 | return grad_result 67 | 68 | return benchmark(get_grad_qiskit, np.ones([3 * n * l]), trials=trials) 69 | 70 | 71 | def hessian_qiskit(n, l, trials=0): 72 | hamiltonian = reduce(xor, [X for _ in range(n)]) 73 | wavefunction = QuantumCircuit(n) 74 | params = ParameterVector("theta", length=3 * n * l) 75 | for j in range(l): 76 | for i in range(n - 1): 77 | wavefunction.cnot(i, i + 1) 78 | for i in range(n): 79 | wavefunction.rx(params[3 * n * j + i], i) 80 | for i in range(n): 81 | wavefunction.rz(params[3 * n * j + i + n], i) 82 | for i in range(n): 83 | wavefunction.rx(params[3 * n * j + i + 2 * n], i) 84 | 85 | # Define the expectation value corresponding to the energy 86 | op = ~StateFn(hamiltonian) @ StateFn(wavefunction) 87 | grad = Hessian().convert(operator=op, params=params) 88 | 89 | def get_hs_qiskit(values): 90 | value_dict = {params: values} 91 | grad_result = grad.assign_parameters(value_dict).eval() 92 | return grad_result 93 | 94 | return benchmark(get_hs_qiskit, np.ones([3 * n * l]), trials=trials) 95 | 96 | 97 | def grad_tc(n, l, trials=10): 98 | def f(params): 99 | c = tc.Circuit(n) 100 | for j in range(l): 101 | for i in range(n - 1): 102 | c.cnot(i, i + 1) 103 | for i in range(n): 104 | c.rx(i, theta=params[3 * n * j + i]) 105 | for i in range(n): 106 | c.rz(i, theta=params[3 * n * j + i + n]) 107 | for i in range(n): 108 | c.rx(i, theta=params[3 * n * j + i + 2 * n]) 109 | return tc.backend.real(c.expectation(*[[tc.gates.x(), [i]] for i in range(n)])) 110 | 111 | get_grad_tc = tc.backend.jit(tc.backend.grad(f)) 112 | return benchmark(get_grad_tc, tc.backend.ones([3 * n * l], dtype='float32')) 113 | 114 | 115 | def hessian_tc(n, l, trials=10): 116 | def f(params): 117 | c = tc.Circuit(n) 118 | for j in range(l): 119 | for i in range(n - 1): 120 | c.cnot(i, i + 1) 121 | for i in range(n): 122 | c.rx(i, theta=params[3 * n * j + i]) 123 | for i in range(n): 124 | c.rz(i, theta=params[3 * n * j + i + n]) 125 | for i in range(n): 126 | c.rx(i, theta=params[3 * n * j + i + 2 * n]) 127 | return tc.backend.real(c.expectation(*[[tc.gates.x(), [i]] for i in range(n)])) 128 | 129 | get_hs_tc = tc.backend.jit(tc.backend.hessian(f)) 130 | return benchmark(get_hs_tc, tc.backend.ones([3 * n * l], dtype='float32')) 131 | 132 | 133 | def grad_dq(n, l, trials=10): 134 | def get_grad_dq(params): 135 | if params.grad != None: 136 | params.grad.zero_() 137 | cir = dq.QubitCircuit(n) 138 | for j in range(l): 139 | for i in range(n - 1): 140 | cir.cnot(i, i + 1) 141 | cir.rxlayer(encode=True) 142 | cir.rzlayer(encode=True) 143 | cir.rxlayer(encode=True) 144 | cir.observable(basis='x') 145 | cir(data=params) 146 | exp = cir.expectation() 147 | exp.backward() 148 | return params.grad 149 | 150 | return benchmark(get_grad_dq, torch.ones([3 * n * l], requires_grad=True)) 151 | 152 | 153 | def hessian_dq(n, l, trials=10): 154 | def f(params): 155 | cir = dq.QubitCircuit(n) 156 | for j in range(l): 157 | for i in range(n - 1): 158 | cir.cnot(i, i + 1) 159 | cir.rxlayer(encode=True) 160 | cir.rzlayer(encode=True) 161 | cir.rxlayer(encode=True) 162 | cir.observable(basis='x') 163 | cir(data=params) 164 | return cir.expectation() 165 | 166 | def get_hs_dq(x): 167 | return hessian(f, x) 168 | 169 | return benchmark(get_hs_dq, torch.ones([3 * n * l])) 170 | 171 | 172 | def grad_pyvqnet(n, l ,trials=10): 173 | def pqctest(param): 174 | machine = pq.CPUQVM() 175 | machine.init_qvm() 176 | qubits = machine.qAlloc_many(n) 177 | circuit = pq.QCircuit() 178 | for j in range(l): 179 | for i in range(n - 1): 180 | circuit.insert(pq.CNOT(qubits[i], qubits[i + 1])) 181 | for i in range(n): 182 | circuit.insert(pq.RX(qubits[i], param[3 * n * j + i])) 183 | circuit.insert(pq.RZ(qubits[i], param[3 * n * j + i + n])) 184 | circuit.insert(pq.RX(qubits[i], param[3 * n * j + i + 2 * n])) 185 | prog = pq.QProg() 186 | prog.insert(circuit) 187 | Xn_string = ', '.join([f'X{i}' for i in range(n)]) 188 | pauli_dict = {Xn_string:1.} 189 | exp = expval(machine, prog, pauli_dict, qubits) 190 | return exp 191 | 192 | def get_grad(values): 193 | return grad(pqctest, values) 194 | 195 | return benchmark(get_grad, np.ones([3 * n * l]), trials=trials) 196 | 197 | results = {} 198 | 199 | for n in [4, 6, 8, 10, 12]: 200 | for l in [2, 4, 6]: 201 | _, ts = grad_qiskit(n, l) 202 | results[str(n) + '-' + str(l) + '-' + 'grad' + '-qiskit'] = ts 203 | _, ts = hessian_qiskit(n, l) 204 | results[str(n) + '-' + str(l) + '-' + 'hs' + '-qiskit'] = ts 205 | with tc.runtime_backend('tensorflow'): 206 | _, ts = grad_tc(n, l) 207 | results[str(n) + '-' + str(l) + '-' + 'grad' + '-tc-tf'] = ts 208 | _, ts = hessian_tc(n, l) 209 | results[str(n) + '-' + str(l) + '-' + 'hs' + '-tc-tf'] = ts 210 | with tc.runtime_backend('jax'): 211 | _, ts = grad_tc(n, l) 212 | results[str(n) + '-' + str(l) + '-' + 'grad' + '-tc-jax'] = ts 213 | _, ts = hessian_tc(n, l) 214 | results[str(n) + '-' + str(l) + '-' + 'hs' + '-tc-jax'] = ts 215 | with tc.runtime_backend('pytorch'): 216 | _, ts = grad_tc(n, l) 217 | results[str(n) + '-' + str(l) + '-' + 'grad' + '-tc-pytorch'] = ts 218 | # _, ts = hessian_tc(n, l) 219 | # results[str(n) + '-' + str(l) + '-' + 'hs' + '-tc-pytorch'] = ts 220 | _, ts = grad_dq(n, l) 221 | results[str(n) + '-' + str(l) + '-' + 'grad' + '-dq'] = ts 222 | _, ts = hessian_dq(n, l) 223 | results[str(n) + '-' + str(l) + '-' + 'hs' + '-dq'] = ts 224 | _, ts = grad_pyvqnet(n, l) 225 | results[str(n) + '-' + str(l) + '-' + 'grad' + '-pyvqnet'] = ts 226 | 227 | # print(results) 228 | 229 | with open('gradient_results.data', 'w') as f: 230 | json.dump(results, f) 231 | 232 | with open('gradient_results.data', 'r') as f: 233 | print(json.load(f)) 234 | -------------------------------------------------------------------------------- /examples/bosonic/breeding_cat/fig/graph1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/bosonic/breeding_cat/fig/graph1.png -------------------------------------------------------------------------------- /examples/bosonic/breeding_cat/fig/graph2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/bosonic/breeding_cat/fig/graph2.png -------------------------------------------------------------------------------- /examples/bosonic/breeding_cat/fig/graph3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/bosonic/breeding_cat/fig/graph3.png -------------------------------------------------------------------------------- /examples/bosonic/breeding_cat/fig/graph4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/bosonic/breeding_cat/fig/graph4.png -------------------------------------------------------------------------------- /examples/figure/basic_gate_MBQC/CNOT.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/figure/basic_gate_MBQC/CNOT.jpg -------------------------------------------------------------------------------- /examples/figure/basic_gate_MBQC/RZ.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/figure/basic_gate_MBQC/RZ.jpg -------------------------------------------------------------------------------- /examples/figure/basic_gate_MBQC/Single.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/figure/basic_gate_MBQC/Single.jpg -------------------------------------------------------------------------------- /examples/gbs/boson_sampling/fig/bs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/boson_sampling/fig/bs.png -------------------------------------------------------------------------------- /examples/gbs/boson_sampling/fig/f1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/boson_sampling/fig/f1.png -------------------------------------------------------------------------------- /examples/gbs/boson_sampling/fig/f2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/boson_sampling/fig/f2.png -------------------------------------------------------------------------------- /examples/gbs/boson_sampling/fig/f3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/boson_sampling/fig/f3.png -------------------------------------------------------------------------------- /examples/gbs/boson_sampling/fig/f4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/boson_sampling/fig/f4.png -------------------------------------------------------------------------------- /examples/gbs/dense_graph/data/densegraph_adj.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/dense_graph/data/densegraph_adj.npy -------------------------------------------------------------------------------- /examples/gbs/dense_graph/data/densegraph_sample.pkl.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/dense_graph/data/densegraph_sample.pkl.gz -------------------------------------------------------------------------------- /examples/gbs/dense_graph/fig/f3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/dense_graph/fig/f3.png -------------------------------------------------------------------------------- /examples/gbs/dense_graph/fig/f4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/dense_graph/fig/f4.png -------------------------------------------------------------------------------- /examples/gbs/dense_graph/fig/f5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/dense_graph/fig/f5.png -------------------------------------------------------------------------------- /examples/gbs/dense_graph/fig/f6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/dense_graph/fig/f6.png -------------------------------------------------------------------------------- /examples/gbs/dense_graph/fig/f7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/dense_graph/fig/f7.png -------------------------------------------------------------------------------- /examples/gbs/dense_graph/fig/f8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/dense_graph/fig/f8.png -------------------------------------------------------------------------------- /examples/gbs/dense_graph/fig/f9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/dense_graph/fig/f9.png -------------------------------------------------------------------------------- /examples/gbs/dense_graph/fig/gbs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/dense_graph/fig/gbs.png -------------------------------------------------------------------------------- /examples/gbs/dense_graph/fig/graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/dense_graph/fig/graph.png -------------------------------------------------------------------------------- /examples/gbs/dense_graph/fig/haf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/dense_graph/fig/haf.png -------------------------------------------------------------------------------- /examples/gbs/dense_graph/fig/per.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/dense_graph/fig/per.png -------------------------------------------------------------------------------- /examples/gbs/dense_graph/fig/s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/dense_graph/fig/s.png -------------------------------------------------------------------------------- /examples/gbs/gaussian_boson_sampling/fig/f3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/gaussian_boson_sampling/fig/f3.png -------------------------------------------------------------------------------- /examples/gbs/gaussian_boson_sampling/fig/f4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/gaussian_boson_sampling/fig/f4.png -------------------------------------------------------------------------------- /examples/gbs/gaussian_boson_sampling/fig/f5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/gaussian_boson_sampling/fig/f5.png -------------------------------------------------------------------------------- /examples/gbs/gaussian_boson_sampling/fig/f6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/gaussian_boson_sampling/fig/f6.png -------------------------------------------------------------------------------- /examples/gbs/gaussian_boson_sampling/fig/f7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/gaussian_boson_sampling/fig/f7.png -------------------------------------------------------------------------------- /examples/gbs/gaussian_boson_sampling/fig/f8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/gaussian_boson_sampling/fig/f8.png -------------------------------------------------------------------------------- /examples/gbs/gaussian_boson_sampling/fig/f9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/gaussian_boson_sampling/fig/f9.png -------------------------------------------------------------------------------- /examples/gbs/gaussian_boson_sampling/fig/gbs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/gaussian_boson_sampling/fig/gbs.png -------------------------------------------------------------------------------- /examples/gbs/gaussian_boson_sampling/fig/graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/gaussian_boson_sampling/fig/graph.png -------------------------------------------------------------------------------- /examples/gbs/gaussian_boson_sampling/fig/haf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/gaussian_boson_sampling/fig/haf.png -------------------------------------------------------------------------------- /examples/gbs/gaussian_boson_sampling/fig/per.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/gaussian_boson_sampling/fig/per.png -------------------------------------------------------------------------------- /examples/gbs/gaussian_boson_sampling/fig/s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/gaussian_boson_sampling/fig/s.png -------------------------------------------------------------------------------- /examples/gbs/gbs_clustering/data/clustering.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/gbs_clustering/data/clustering.npy -------------------------------------------------------------------------------- /examples/gbs/gbs_clustering/data/clustering.pkl.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/gbs_clustering/data/clustering.pkl.gz -------------------------------------------------------------------------------- /examples/gbs/gbs_clustering/fig/12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/gbs_clustering/fig/12.png -------------------------------------------------------------------------------- /examples/gbs/gbs_clustering/fig/f1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/gbs_clustering/fig/f1.png -------------------------------------------------------------------------------- /examples/gbs/gbs_clustering/fig/f2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/gbs_clustering/fig/f2.png -------------------------------------------------------------------------------- /examples/gbs/gbs_clustering/fig/f3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/gbs_clustering/fig/f3.png -------------------------------------------------------------------------------- /examples/gbs/gbs_clustering/fig/f4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/gbs_clustering/fig/f4.png -------------------------------------------------------------------------------- /examples/gbs/gbs_clustering/fig/f5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/gbs_clustering/fig/f5.png -------------------------------------------------------------------------------- /examples/gbs/gbs_clustering/fig/fig2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/gbs_clustering/fig/fig2.png -------------------------------------------------------------------------------- /examples/gbs/homodyne_tomography/fig/hd1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/homodyne_tomography/fig/hd1.png -------------------------------------------------------------------------------- /examples/gbs/homodyne_tomography/fig/mt1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/homodyne_tomography/fig/mt1.jpg -------------------------------------------------------------------------------- /examples/gbs/homodyne_tomography/fig/mt2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/homodyne_tomography/fig/mt2.jpg -------------------------------------------------------------------------------- /examples/gbs/max_clique/data/clique_adj.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/max_clique/data/clique_adj.npy -------------------------------------------------------------------------------- /examples/gbs/max_clique/data/clique_sample.pkl.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/max_clique/data/clique_sample.pkl.gz -------------------------------------------------------------------------------- /examples/gbs/max_clique/fig/clique.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/max_clique/fig/clique.png -------------------------------------------------------------------------------- /examples/gbs/similar_graph/data/gbs_dg.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/similar_graph/data/gbs_dg.npy -------------------------------------------------------------------------------- /examples/gbs/similar_graph/data/mutag_1_adj.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/similar_graph/data/mutag_1_adj.npy -------------------------------------------------------------------------------- /examples/gbs/similar_graph/data/mutag_1_sample.pkl.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/similar_graph/data/mutag_1_sample.pkl.gz -------------------------------------------------------------------------------- /examples/gbs/similar_graph/data/mutag_2_adj.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/similar_graph/data/mutag_2_adj.npy -------------------------------------------------------------------------------- /examples/gbs/similar_graph/data/mutag_2_sample.pkl.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/similar_graph/data/mutag_2_sample.pkl.gz -------------------------------------------------------------------------------- /examples/gbs/similar_graph/data/mutag_3_adj.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/similar_graph/data/mutag_3_adj.npy -------------------------------------------------------------------------------- /examples/gbs/similar_graph/data/mutag_3_sample.pkl.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/similar_graph/data/mutag_3_sample.pkl.gz -------------------------------------------------------------------------------- /examples/gbs/similar_graph/data/mutag_4_adj.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/similar_graph/data/mutag_4_adj.npy -------------------------------------------------------------------------------- /examples/gbs/similar_graph/data/mutag_4_sample.pkl.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/similar_graph/data/mutag_4_sample.pkl.gz -------------------------------------------------------------------------------- /examples/gbs/similar_graph/fig/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/similar_graph/fig/1.png -------------------------------------------------------------------------------- /examples/gbs/similar_graph/fig/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/similar_graph/fig/2.png -------------------------------------------------------------------------------- /examples/gbs/similar_graph/fig/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/similar_graph/fig/3.png -------------------------------------------------------------------------------- /examples/gbs/similar_graph/fig/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/similar_graph/fig/4.png -------------------------------------------------------------------------------- /examples/gbs/similar_graph/fig/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/similar_graph/fig/5.png -------------------------------------------------------------------------------- /examples/gbs/vibronic_excitations/data/formic_lf.csv: -------------------------------------------------------------------------------- 1 | -0.470781330260, -0.000000000000, -0.261004968238, 0.507500074804, 0.000000000000, -0.291081081609, -0.040975462419, 0.000000000000, 0.466527996777, -0.136105510765, -0.000000000000, 0.324641908735, -0.097947192715, -0.000000000000, -0.122958252310 2 | 0.003690797054, -0.000000000000, -0.041706769117, 0.064647465817, 0.000000000000, -0.007470073116, -0.225471744674, -0.000000000000, 0.326393260243, 0.344245656793, 0.000000000000, -0.602156425487, 0.283710176585, 0.000000000000, -0.524454822978 3 | -0.279619358268, -0.000000000000, -0.228526968961, 0.021927699337, 0.000000000000, 0.600971344681, 0.208061946672, -0.000000000000, -0.327180535016, -0.118929879680, 0.000000000000, 0.216157001354, 0.167557502860, 0.000000000000, -0.518324704590 4 | -0.474322937131, 0.000000000000, -0.164203170748, -0.014432814932, 0.000000000000, 0.170633563269, 0.426070840837, 0.000000000000, -0.007849987854, 0.356952589467, -0.000000000000, -0.412883051799, -0.360127509375, -0.000000000000, 0.330988789308 5 | -0.375988319209, -0.000000000000, 0.735969894381, 0.026146328501, 0.000000000000, -0.349289182953, 0.264612091133, 0.000000000000, -0.229839384693, 0.031147973266, -0.000000000000, 0.009928286185, 0.107921705634, 0.000000000000, -0.242348862964 6 | -0.255262972959, -0.000000000000, -0.113194969204, -0.006921791812, 0.000000000000, -0.005534670215, 0.015778767816, 0.000000000000, -0.010012183672, 0.003647200248, 0.000000000000, -0.008712229842, 0.841883609803, 0.000000000000, 0.461240435128 7 | -0.003643822719, -0.00000000000, 0.002584954956, 0.000176716472, 0.000000000000, 0.003626759849, 0.213502224042, 0.000000000000, 0.118398790331, -0.834065418908, -0.000000000000, -0.494650187349, -0.004614776258, 0.000000000000, -0.000394593812 8 | -------------------------------------------------------------------------------- /examples/gbs/vibronic_excitations/data/formic_li.csv: -------------------------------------------------------------------------------- 1 | 0.346372298558, 0.000000000000, 0.2631111152510, -0.493658667529, -0.000000000000, 0.327414301266, 0.098662461441, -0.000000000000, -0.462252955875, 0.246333278135, 0.000000000000, -0.397083067673, 0.132052877724, 0.000000000000, 0.026356812146 2 | -0.444625056728, -0.000000000000, 0.080168001111, -0.018859412917, 0.000000000000, 0.251820745157, 0.518739820669, 0.000000000000, -0.453329233659, -0.223754673634, -0.000000000000, 0.348345269256, -0.233436094247, -0.000000000000, 0.177794541706 3 | 0.593971152137, 0.000000000000, -0.071987172463, -0.152948582597, -0.000000000000, 0.018357607414, -0.245702482980, -0.000000000000, -0.144802186197, -0.466216201213, 0.000000000000, 0.511560802299, 0.004793322320, -0.000000000000, 0.240569089515 4 | -0.084314734669, -0.000000000000, 0.004015733012, 0.084279675543, 0.000000000000, 0.284032988235, -0.083154709293, -0.000000000000, -0.149424766279, -0.196507206220, 0.000000000000, 0.200695579553, 0.482963575635, 0.000000000000, -0.750804247255 5 | -0.052155158728, -0.000000000000, 0.766420080547, -0.004154639323, 0.000000000000, -0.588604467722, 0.024765474746, 0.000000000000, -0.094635201935, -0.088074758632, -0.000000000000, 0.103921509331, 0.185932933483, 0.000000000000, -0.026656518038 6 | -0.233306320362, -0.000000000000, -0.174313133901, 0.002377559300, 0.000000000000, 0.016799030948, 0.003294485757, -0.000000000000, 0.004098291519, -0.008800579848, 0.000000000000, -0.018748022663, 0.791255472099, 0.000000000000, 0.536985494854 7 | 0.012253894558, -0.000000000000, 0.006509376315, -0.001784903400, 0.000000000000, 0.002144736121, 0.188826270863, 0.000000000000, 0.141726785623, -0.775693237165, -0.000000000000, -0.584897833374, -0.011725222119, -0.000000000000, -0.010718557687 8 | -------------------------------------------------------------------------------- /examples/gbs/vibronic_excitations/data/formic_omega.csv: -------------------------------------------------------------------------------- 1 | 629.7144, 1137.049, 1326.4684, 1416.9512, 1825.1799, 3088.1826, 3765.2386 2 | -------------------------------------------------------------------------------- /examples/gbs/vibronic_excitations/data/formic_omegap.csv: -------------------------------------------------------------------------------- 1 | 496.2845, 1190.9077, 1215.3421, 1399.6554, 1566.4602, 3064.9143, 3629.9472 2 | -------------------------------------------------------------------------------- /examples/gbs/vibronic_excitations/data/formic_rf.csv: -------------------------------------------------------------------------------- 1 | -0.378273366690, 0.000000000000, -0.177008746015, -0.407810607443, 0.000000000000, 1.082699011492, 0.681283434588, 0.000000000000, -0.883483538075, 1.515733391145, 0.000000000000, -0.369460742916, -1.351908993533, 0.000000000000, -0.684614463950 2 | -------------------------------------------------------------------------------- /examples/gbs/vibronic_excitations/data/formic_ri.csv: -------------------------------------------------------------------------------- 1 | -0.404602332345, 0.000000000000, -0.131611937331, -0.404602332345, 0.000000000000, 1.070534062669, 0.698430667655, 0.000000000000, -0.904960937331, 1.452952667655, 0.000000000000, -0.297631937331, -1.298690332345, 0.000000000000, -0.763046937331 2 | -------------------------------------------------------------------------------- /examples/gbs/vibronic_spectra/data/formic_lf.csv: -------------------------------------------------------------------------------- 1 | -0.470781330260, -0.000000000000, -0.261004968238, 0.507500074804, 0.000000000000, -0.291081081609, -0.040975462419, 0.000000000000, 0.466527996777, -0.136105510765, -0.000000000000, 0.324641908735, -0.097947192715, -0.000000000000, -0.122958252310 2 | 0.003690797054, -0.000000000000, -0.041706769117, 0.064647465817, 0.000000000000, -0.007470073116, -0.225471744674, -0.000000000000, 0.326393260243, 0.344245656793, 0.000000000000, -0.602156425487, 0.283710176585, 0.000000000000, -0.524454822978 3 | -0.279619358268, -0.000000000000, -0.228526968961, 0.021927699337, 0.000000000000, 0.600971344681, 0.208061946672, -0.000000000000, -0.327180535016, -0.118929879680, 0.000000000000, 0.216157001354, 0.167557502860, 0.000000000000, -0.518324704590 4 | -0.474322937131, 0.000000000000, -0.164203170748, -0.014432814932, 0.000000000000, 0.170633563269, 0.426070840837, 0.000000000000, -0.007849987854, 0.356952589467, -0.000000000000, -0.412883051799, -0.360127509375, -0.000000000000, 0.330988789308 5 | -0.375988319209, -0.000000000000, 0.735969894381, 0.026146328501, 0.000000000000, -0.349289182953, 0.264612091133, 0.000000000000, -0.229839384693, 0.031147973266, -0.000000000000, 0.009928286185, 0.107921705634, 0.000000000000, -0.242348862964 6 | -0.255262972959, -0.000000000000, -0.113194969204, -0.006921791812, 0.000000000000, -0.005534670215, 0.015778767816, 0.000000000000, -0.010012183672, 0.003647200248, 0.000000000000, -0.008712229842, 0.841883609803, 0.000000000000, 0.461240435128 7 | -0.003643822719, -0.00000000000, 0.002584954956, 0.000176716472, 0.000000000000, 0.003626759849, 0.213502224042, 0.000000000000, 0.118398790331, -0.834065418908, -0.000000000000, -0.494650187349, -0.004614776258, 0.000000000000, -0.000394593812 8 | -------------------------------------------------------------------------------- /examples/gbs/vibronic_spectra/data/formic_li.csv: -------------------------------------------------------------------------------- 1 | 0.346372298558, 0.000000000000, 0.2631111152510, -0.493658667529, -0.000000000000, 0.327414301266, 0.098662461441, -0.000000000000, -0.462252955875, 0.246333278135, 0.000000000000, -0.397083067673, 0.132052877724, 0.000000000000, 0.026356812146 2 | -0.444625056728, -0.000000000000, 0.080168001111, -0.018859412917, 0.000000000000, 0.251820745157, 0.518739820669, 0.000000000000, -0.453329233659, -0.223754673634, -0.000000000000, 0.348345269256, -0.233436094247, -0.000000000000, 0.177794541706 3 | 0.593971152137, 0.000000000000, -0.071987172463, -0.152948582597, -0.000000000000, 0.018357607414, -0.245702482980, -0.000000000000, -0.144802186197, -0.466216201213, 0.000000000000, 0.511560802299, 0.004793322320, -0.000000000000, 0.240569089515 4 | -0.084314734669, -0.000000000000, 0.004015733012, 0.084279675543, 0.000000000000, 0.284032988235, -0.083154709293, -0.000000000000, -0.149424766279, -0.196507206220, 0.000000000000, 0.200695579553, 0.482963575635, 0.000000000000, -0.750804247255 5 | -0.052155158728, -0.000000000000, 0.766420080547, -0.004154639323, 0.000000000000, -0.588604467722, 0.024765474746, 0.000000000000, -0.094635201935, -0.088074758632, -0.000000000000, 0.103921509331, 0.185932933483, 0.000000000000, -0.026656518038 6 | -0.233306320362, -0.000000000000, -0.174313133901, 0.002377559300, 0.000000000000, 0.016799030948, 0.003294485757, -0.000000000000, 0.004098291519, -0.008800579848, 0.000000000000, -0.018748022663, 0.791255472099, 0.000000000000, 0.536985494854 7 | 0.012253894558, -0.000000000000, 0.006509376315, -0.001784903400, 0.000000000000, 0.002144736121, 0.188826270863, 0.000000000000, 0.141726785623, -0.775693237165, -0.000000000000, -0.584897833374, -0.011725222119, -0.000000000000, -0.010718557687 8 | -------------------------------------------------------------------------------- /examples/gbs/vibronic_spectra/data/formic_omega.csv: -------------------------------------------------------------------------------- 1 | 629.7144, 1137.049, 1326.4684, 1416.9512, 1825.1799, 3088.1826, 3765.2386 2 | -------------------------------------------------------------------------------- /examples/gbs/vibronic_spectra/data/formic_omegap.csv: -------------------------------------------------------------------------------- 1 | 496.2845, 1190.9077, 1215.3421, 1399.6554, 1566.4602, 3064.9143, 3629.9472 2 | -------------------------------------------------------------------------------- /examples/gbs/vibronic_spectra/data/formic_rf.csv: -------------------------------------------------------------------------------- 1 | -0.378273366690, 0.000000000000, -0.177008746015, -0.407810607443, 0.000000000000, 1.082699011492, 0.681283434588, 0.000000000000, -0.883483538075, 1.515733391145, 0.000000000000, -0.369460742916, -1.351908993533, 0.000000000000, -0.684614463950 2 | -------------------------------------------------------------------------------- /examples/gbs/vibronic_spectra/data/formic_ri.csv: -------------------------------------------------------------------------------- 1 | -0.404602332345, 0.000000000000, -0.131611937331, -0.404602332345, 0.000000000000, 1.070534062669, 0.698430667655, 0.000000000000, -0.904960937331, 1.452952667655, 0.000000000000, -0.297631937331, -1.298690332345, 0.000000000000, -0.763046937331 2 | -------------------------------------------------------------------------------- /examples/gbs/vibronic_spectra/fig/Franck_Condon_Diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/vibronic_spectra/fig/Franck_Condon_Diagram.png -------------------------------------------------------------------------------- /examples/gbs/vibronic_spectra/fig/formic_spec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/vibronic_spectra/fig/formic_spec.png -------------------------------------------------------------------------------- /examples/gbs/vqe_ground_energy_for_H2_alg/boson_coeff2.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/vqe_ground_energy_for_H2_alg/boson_coeff2.mat -------------------------------------------------------------------------------- /examples/gbs/vqe_ground_energy_for_H2_alg/fig/bs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/vqe_ground_energy_for_H2_alg/fig/bs.png -------------------------------------------------------------------------------- /examples/gbs/vqe_ground_energy_for_H2_alg/fig/bs_circuit2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/vqe_ground_energy_for_H2_alg/fig/bs_circuit2.png -------------------------------------------------------------------------------- /examples/gbs/vqe_ground_energy_for_H2_alg/openfermion_h2_fci.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/vqe_ground_energy_for_H2_alg/openfermion_h2_fci.npy -------------------------------------------------------------------------------- /examples/gbs/vqe_ground_energy_for_H2_alg/openfermion_h2_v3.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/vqe_ground_energy_for_H2_alg/openfermion_h2_v3.npy -------------------------------------------------------------------------------- /examples/gbs/vqe_ground_energy_for_H2_hardware/boson_coeff2.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/vqe_ground_energy_for_H2_hardware/boson_coeff2.mat -------------------------------------------------------------------------------- /examples/gbs/vqe_ground_energy_for_H2_hardware/fig/subset_expressive_ability.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/vqe_ground_energy_for_H2_hardware/fig/subset_expressive_ability.png -------------------------------------------------------------------------------- /examples/gbs/vqe_ground_energy_for_H2_hardware/fig/vqa_deterministic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/vqe_ground_energy_for_H2_hardware/fig/vqa_deterministic.png -------------------------------------------------------------------------------- /examples/gbs/vqe_ground_energy_for_H2_hardware/fig/vqa_random_circuit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/vqe_ground_energy_for_H2_hardware/fig/vqa_random_circuit.png -------------------------------------------------------------------------------- /examples/gbs/vqe_ground_energy_for_H2_hardware/openfermion_h2_fci.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/vqe_ground_energy_for_H2_hardware/openfermion_h2_fci.npy -------------------------------------------------------------------------------- /examples/gbs/vqe_ground_energy_for_H2_hardware/openfermion_h2_v3.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/gbs/vqe_ground_energy_for_H2_hardware/openfermion_h2_v3.npy -------------------------------------------------------------------------------- /examples/tdm/advanced_cluster_state/fig/entangle_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/tdm/advanced_cluster_state/fig/entangle_1.png -------------------------------------------------------------------------------- /examples/tdm/advanced_cluster_state/fig/entangle_2_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/tdm/advanced_cluster_state/fig/entangle_2_1.png -------------------------------------------------------------------------------- /examples/tdm/advanced_cluster_state/fig/entangle_2_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/tdm/advanced_cluster_state/fig/entangle_2_2.png -------------------------------------------------------------------------------- /examples/tdm/simple_cluster_state/fig/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/tdm/simple_cluster_state/fig/1.png -------------------------------------------------------------------------------- /examples/tdm/simple_cluster_state/fig/EPR.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/tdm/simple_cluster_state/fig/EPR.jpg -------------------------------------------------------------------------------- /examples/tdm/simple_cluster_state/fig/EPR2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/tdm/simple_cluster_state/fig/EPR2.jpg -------------------------------------------------------------------------------- /examples/tdm/simple_cluster_state/fig/GHZ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/tdm/simple_cluster_state/fig/GHZ.png -------------------------------------------------------------------------------- /examples/tdm/simple_cluster_state/fig/delay.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/examples/tdm/simple_cluster_state/fig/delay.jpg -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ['setuptools >= 69.0', 'wheel'] 3 | build-backend = 'setuptools.build_meta' 4 | 5 | [project] 6 | name = 'deepquantum' 7 | dynamic = ['version'] 8 | dependencies = [ 9 | 'torch>=2.0.0', 10 | 'numpy<2', 11 | 'matplotlib', 12 | 'qiskit', 13 | 'pylatexenc', 14 | 'scipy==1.13.1', 15 | 'sympy', 16 | 'svgwrite', 17 | 'bayesian-optimization<2', 18 | 'networkx', 19 | 'tqdm', 20 | 'psutil' 21 | ] 22 | requires-python = '>=3.8' 23 | authors = [ 24 | {name = 'TuringQ', email = 'Algorithms-Applications@turingq.com'}, 25 | {name = 'Junjie He', email = 'hejunjie@turingq.com'}, 26 | {name = 'Keming Hu', email = 'hukeming@turingq.com'}, 27 | {name = 'Yuze Zhu', email = 'zhuyuze@turingq.com'} 28 | ] 29 | maintainers = [ 30 | {name = 'Junjie He', email = 'hejunjie@turingq.com'} 31 | ] 32 | description = 'DeepQuantum for quantum computing' 33 | readme = 'README.md' 34 | keywords = ['quantum computing', 'quantum machine learning', 'photonic quantum computing'] 35 | classifiers = [ 36 | 'Development Status :: 4 - Beta', 37 | 'Intended Audience :: Developers', 38 | 'Intended Audience :: Science/Research', 39 | 'Programming Language :: Python :: 3', 40 | 'Programming Language :: Python :: 3.8', 41 | 'Programming Language :: Python :: 3.9', 42 | 'Programming Language :: Python :: 3.10', 43 | 'Programming Language :: Python :: 3.11', 44 | 'License :: OSI Approved :: Apache Software License', 45 | 'Operating System :: OS Independent' 46 | ] 47 | 48 | [project.optional-dependencies] 49 | dev = ['pytest', 'perceval-quandela', 'strawberryfields', 'thewalrus'] 50 | 51 | [project.urls] 52 | Homepage = 'https://deepquantum.turingq.com/' 53 | Documentation = 'https://dqapi.turingq.com/' 54 | Repository = 'https://github.com/TuringQ/deepquantum.git' 55 | Issues = 'https://github.com/TuringQ/deepquantum/issues' 56 | 57 | [tool.setuptools.dynamic] 58 | version = {attr = 'deepquantum.__version__'} 59 | 60 | [tool.setuptools.package-data] 61 | 'deepquantum.photonic' = ['cache/*'] 62 | -------------------------------------------------------------------------------- /src/deepquantum/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | This is the top level module from which all basic functions and classes of 3 | DeepQuantum can be directly imported. 4 | """ 5 | 6 | __version__ = '4.2.0' 7 | 8 | 9 | from . import adjoint 10 | from . import ansatz 11 | from . import bitmath 12 | from . import channel 13 | from . import circuit 14 | from . import communication 15 | from . import distributed 16 | from . import gate 17 | from . import layer 18 | from . import operation 19 | from . import optimizer 20 | from . import qmath 21 | from . import state 22 | from . import utils 23 | 24 | from . import mbqc 25 | from . import photonic 26 | 27 | from .ansatz import ( 28 | Ansatz, 29 | ControlledMultiplier, 30 | ControlledUa, 31 | HHL, 32 | NumberEncoder, 33 | PhiAdder, 34 | PhiModularAdder, 35 | QuantumConvolutionalNeuralNetwork, 36 | QuantumFourierTransform, 37 | QuantumPhaseEstimationSingleQubit, 38 | RandomCircuitG3, 39 | ShorCircuit, 40 | ShorCircuitFor15 41 | ) 42 | from .channel import BitFlip, PhaseFlip, Depolarizing, Pauli, AmplitudeDamping, PhaseDamping 43 | from .channel import GeneralizedAmplitudeDamping 44 | from .circuit import QubitCircuit, DistritubutedQubitCircuit 45 | from .gate import U3Gate, PhaseShift, Identity, PauliX, PauliY, PauliZ, Hadamard 46 | from .gate import SGate, SDaggerGate, TGate, TDaggerGate 47 | from .gate import Rx, Ry, Rz, ProjectionJ, CombinedSingleGate 48 | from .gate import CNOT, Swap, Rxx, Ryy, Rzz, Rxy, ReconfigurableBeamSplitter, Toffoli, Fredkin 49 | from .gate import UAnyGate, LatentGate, HamiltonianGate, Barrier 50 | from .layer import Observable, U3Layer, XLayer, YLayer, ZLayer, HLayer, RxLayer, RyLayer, RzLayer 51 | from .layer import CnotLayer, CnotRing 52 | from .qmath import multi_kron, partial_trace, amplitude_encoding, measure, expectation 53 | from .qmath import meyer_wallach_measure 54 | from .state import QubitState, MatrixProductState, DistributedQubitState 55 | 56 | from .mbqc import SubGraphState, GraphState 57 | from .mbqc import Pattern 58 | 59 | from .photonic import permanent, takagi, hafnian, torontonian 60 | from .photonic import FockState, GaussianState, BosonicState, CatState, GKPState, FockStateBosonic 61 | from .photonic import QumodeCircuit, QumodeCircuitTDM, Clements, GaussianBosonSampling 62 | from .photonic import UnitaryMapper, UnitaryDecomposer, DrawClements 63 | -------------------------------------------------------------------------------- /src/deepquantum/adjoint.py: -------------------------------------------------------------------------------- 1 | """ 2 | Adjoint differentiation 3 | """ 4 | 5 | from copy import deepcopy 6 | from typing import Tuple 7 | from typing import TYPE_CHECKING 8 | 9 | import torch 10 | from torch import nn 11 | from torch.autograd import Function 12 | 13 | from .distributed import dist_one_targ_gate, dist_many_ctrl_one_targ_gate, dist_many_targ_gate, inner_product_dist 14 | from .gate import SingleGate, CombinedSingleGate 15 | from .operation import Gate, Layer 16 | from .state import DistributedQubitState 17 | 18 | if TYPE_CHECKING: 19 | from .layer import Observable 20 | 21 | 22 | class AdjointExpectation(Function): 23 | """Adjoint differentiation 24 | 25 | See https://arxiv.org/pdf/2009.02823 26 | 27 | Args: 28 | state (DistributedQubitState): The final quantum state. 29 | operators (nn.Sequential): The quantum operations. 30 | observable (Observable): The observable. 31 | *parameters (torch.Tensor): The parameters of the quantum circuit. 32 | """ 33 | @staticmethod 34 | def forward( 35 | ctx, 36 | state: DistributedQubitState, 37 | operators: nn.Sequential, 38 | observable: 'Observable', 39 | *parameters: torch.Tensor 40 | ) -> torch.Tensor: 41 | ctx.state_phi = state 42 | ctx.operators = operators 43 | ctx.observable = observable 44 | ctx.state_lambda = observable(deepcopy(state)) 45 | ctx.save_for_backward(*parameters) 46 | return inner_product_dist(ctx.state_lambda, ctx.state_phi).real 47 | 48 | @staticmethod 49 | def backward(ctx, grad_out: torch.Tensor) -> Tuple[None, ...]: 50 | parameters = [*ctx.saved_tensors] 51 | grads = [] 52 | idx = 1 53 | for op in ctx.operators[::-1]: 54 | if isinstance(op, (Layer, CombinedSingleGate)): 55 | gates = op.gates 56 | elif isinstance(op, Gate): 57 | gates = [op] 58 | for gate in gates[::-1]: 59 | if gate.npara > 0: 60 | gate.init_para(parameters[-idx]) 61 | gate_dagger = gate.inverse() 62 | ctx.state_phi = gate_dagger(ctx.state_phi) 63 | if gate.npara > 0: 64 | if parameters[-idx].requires_grad: 65 | du_dx = gate.get_derivative(parameters[-idx]).unsqueeze(0).flatten(0, -3) # (npara, 2**n, 2**n) 66 | wires = gate.controls + gate.wires 67 | targets = [gate.nqubit - wire - 1 for wire in wires] 68 | grads_gate = [] 69 | for mat in du_dx: 70 | state_mu = deepcopy(ctx.state_phi) 71 | if isinstance(gate, SingleGate): 72 | if len(gate.controls) == 0: 73 | state_mu = dist_one_targ_gate(state_mu, targets[0], mat) 74 | else: 75 | state_mu = dist_many_ctrl_one_targ_gate(state_mu, targets[:-1], targets[-1], mat, 76 | True) 77 | else: 78 | zeros = mat.new_zeros(2 ** len(wires) - 2 ** len(gate.wires)).diag_embed() 79 | matrix = torch.block_diag(zeros, mat) 80 | state_mu = dist_many_targ_gate(state_mu, targets, matrix) 81 | grad = grad_out * 2 * inner_product_dist(ctx.state_lambda, state_mu).real 82 | grads_gate.append(grad) 83 | grads.append(torch.stack(grads_gate).reshape(parameters[-idx].shape)) 84 | else: 85 | grads.append(None) 86 | idx += 1 87 | ctx.state_lambda = gate_dagger(ctx.state_lambda) 88 | return None, None, None, *grads[::-1] 89 | -------------------------------------------------------------------------------- /src/deepquantum/bitmath.py: -------------------------------------------------------------------------------- 1 | """ 2 | Bit-twiddling functions of unsigned integers 3 | """ 4 | 5 | from typing import List, Union 6 | 7 | import torch 8 | 9 | 10 | def power_of_2(exp: int) -> int: 11 | return 1 << exp 12 | 13 | 14 | def is_power_of_2(number: int) -> bool: 15 | return (number > 0) and (number & (number - 1) == 0) 16 | 17 | 18 | def log_base2(number: int) -> int: 19 | assert is_power_of_2(number) 20 | return number.bit_length() - 1 21 | 22 | 23 | # See https://arxiv.org/abs/2311.01512 Alg.1 24 | def get_bit(number: Union[int, torch.Tensor], bit_index: int) -> Union[int, torch.Tensor]: 25 | return (number >> bit_index) & 1 26 | 27 | 28 | def flip_bit(number: Union[int, torch.Tensor], bit_index: int) -> Union[int, torch.Tensor]: 29 | return number ^ (1 << bit_index) 30 | 31 | 32 | def flip_bits(number: Union[int, torch.Tensor], bit_indices: List[int]) -> Union[int, torch.Tensor]: 33 | for bit_index in bit_indices: 34 | number = flip_bit(number, bit_index) 35 | return number 36 | 37 | 38 | def insert_bit(number: Union[int, torch.Tensor], bit_index: int, bit_value: int) -> Union[int, torch.Tensor]: 39 | left = (number >> bit_index) << (bit_index + 1) 40 | middle = bit_value << bit_index 41 | right = number & ((1 << bit_index) - 1) 42 | return left | middle | right 43 | 44 | 45 | def all_bits_are_one(number: int, bit_indices: List[int]) -> bool: 46 | for i in bit_indices: 47 | if not get_bit(number, i): 48 | return False 49 | return True 50 | 51 | 52 | def get_bit_mask(bit_indices: List[int]) -> int: 53 | return flip_bits(0, bit_indices) 54 | -------------------------------------------------------------------------------- /src/deepquantum/communication.py: -------------------------------------------------------------------------------- 1 | """ 2 | Communication utilities 3 | """ 4 | 5 | import os 6 | from typing import Optional, Tuple 7 | 8 | import torch 9 | import torch.distributed as dist 10 | 11 | 12 | def setup_distributed(port = '29500', backend = 'nccl') -> Tuple[int, int, int]: 13 | """Initialize torch.distributed.""" 14 | try: 15 | # These should be set by the launch script (e.g., torchrun) 16 | rank = int(os.environ['RANK']) 17 | world_size = int(os.environ['WORLD_SIZE']) 18 | local_rank = int(os.environ['LOCAL_RANK']) # GPU id on the current node 19 | except KeyError: 20 | print('RANK, WORLD_SIZE, and LOCAL_RANK env vars must be set.') 21 | # Fallback for single-process testing (optional) 22 | rank = 0 23 | world_size = 1 24 | local_rank = 0 25 | os.environ['MASTER_ADDR'] = 'localhost' 26 | os.environ['MASTER_PORT'] = port 27 | 28 | print(f'Initializing distributed setup: Rank {rank}/{world_size}, Local Rank (GPU): {local_rank}') 29 | 30 | # Initialize the process group 31 | dist.init_process_group(backend, world_size=world_size, rank=rank) 32 | 33 | # Pin the current process to a specific GPU 34 | torch.cuda.set_device(local_rank) 35 | 36 | print(f'Rank {rank} initialized, using GPU {local_rank}.') 37 | return rank, world_size, local_rank 38 | 39 | 40 | def cleanup_distributed() -> None: 41 | """Clean up the distributed environment.""" 42 | dist.destroy_process_group() 43 | print('Distributed environment cleaned up.') 44 | 45 | 46 | def comm_get_rank() -> int: 47 | if not dist.is_initialized(): 48 | return 0 49 | return dist.get_rank() 50 | 51 | 52 | def comm_get_world_size() -> int: 53 | if not dist.is_initialized(): 54 | return 1 55 | return dist.get_world_size() 56 | 57 | 58 | def comm_exchange_arrays(send_data: torch.Tensor, recv_data: torch.Tensor, pair_rank: Optional[int]) -> None: 59 | """Simulate a point-to-point exchange using dist.all_to_all_single 60 | with output_split_sizes and input_split_sizes to minimize memory. 61 | If pair_rank is None, this rank participates in the collective call 62 | but sends/receives no actual data to/from other specific ranks in this logical P2P. 63 | 64 | Args: 65 | send_data (torch.Tensor): The data this rank wants to send to pair_rank. 66 | If pair_rank is None, this can be an empty tensor with correct dtype and device. 67 | recv_data (torch.Tensor): The Tensor where data received from pair_rank will be stored. 68 | It MUST already be allocated with the correct size if pair_rank is not None. 69 | If pair_rank is None, this can be an empty tensor. 70 | pair_rank (int or None): The rank of the process to exchange data with, or None. 71 | """ 72 | world_size = comm_get_world_size() 73 | rank = comm_get_rank() 74 | 75 | if not dist.is_initialized() or world_size <= 1: 76 | return 77 | if world_size == 1 and pair_rank is not None and rank == pair_rank: 78 | if send_data.numel() > 0 and recv_data.numel() > 0: 79 | recv_data.copy_(send_data) 80 | return 81 | 82 | is_valid = (pair_rank is not None) and (0 <= pair_rank < world_size) 83 | io_sizes = [0] * world_size 84 | if is_valid: 85 | assert send_data.shape == recv_data.shape, 'Send/Recv shape must match for active P2P' 86 | assert send_data.dtype == recv_data.dtype, 'Send/Recv dtype must match for active P2P' 87 | io_sizes[pair_rank] = send_data.numel() 88 | else: 89 | send_data = send_data.new_empty(0) 90 | recv_data = recv_data.new_empty(0) 91 | 92 | dist.all_to_all_single(output=recv_data, input=send_data, output_split_sizes=io_sizes, input_split_sizes=io_sizes) 93 | -------------------------------------------------------------------------------- /src/deepquantum/mbqc/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | MBQC Module 3 | """ 4 | 5 | from . import command 6 | from . import operation 7 | from . import pattern 8 | from . import state 9 | 10 | from .command import Node, Entanglement, Measurement, Correction 11 | from .pattern import Pattern 12 | from .state import SubGraphState, GraphState 13 | -------------------------------------------------------------------------------- /src/deepquantum/mbqc/operation.py: -------------------------------------------------------------------------------- 1 | """ 2 | Base classes 3 | """ 4 | 5 | from typing import List, Optional, Union 6 | 7 | from torch import nn 8 | 9 | from .state import GraphState 10 | 11 | 12 | class Operation(nn.Module): 13 | """A base class for quantum operations. 14 | 15 | Args: 16 | name (str or None, optional): The name of the quantum operation. Default: ``None`` 17 | nodes (int, List[int] or None, optional): The indices of the nodes that the quantum operation acts on. 18 | Default: ``None`` 19 | """ 20 | def __init__( 21 | self, 22 | name: Optional[str] = None, 23 | nodes: Union[int, List[int], None] = None 24 | ) -> None: 25 | super().__init__() 26 | self.name = name 27 | self.nodes = nodes 28 | self.npara = 0 29 | 30 | def _convert_indices(self, indices: Union[int, List[int]]) -> List[int]: 31 | """Convert and check the indices of the modes.""" 32 | if isinstance(indices, int): 33 | indices = [indices] 34 | assert isinstance(indices, list), 'Invalid input type' 35 | assert all(isinstance(i, int) for i in indices), 'Invalid input type' 36 | assert len(set(indices)) == len(indices), 'Invalid input' 37 | return indices 38 | 39 | 40 | class Command(Operation): 41 | """A base class for MBQC commands. 42 | 43 | Args: 44 | name (str): The name of the command. 45 | nodes (int or List[int]): The indices of the nodes that the command acts on. 46 | """ 47 | def __init__( 48 | self, 49 | name: str, 50 | nodes: Union[int, List[int]] 51 | ) -> None: 52 | nodes = self._convert_indices(nodes) 53 | super().__init__(name=name, nodes=nodes) 54 | 55 | def forward(self, x: GraphState) -> GraphState: 56 | """Perform a forward pass.""" 57 | measure_dict = x.measure_dict 58 | for node in self.nodes: 59 | assert node not in measure_dict, f'Node {node} already measured' 60 | return x 61 | 62 | def extra_repr(self) -> str: 63 | return f'nodes={self.nodes}' 64 | -------------------------------------------------------------------------------- /src/deepquantum/photonic/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Photonic Module 3 | """ 4 | 5 | from . import ansatz 6 | from . import channel 7 | from . import circuit 8 | from . import decompose 9 | from . import draw 10 | from . import gate 11 | from . import hafnian_ 12 | from . import mapper 13 | from . import measurement 14 | from . import operation 15 | from . import qmath 16 | from . import state 17 | from . import tdm 18 | from . import torontonian_ 19 | from . import utils 20 | 21 | from .ansatz import Clements, GaussianBosonSampling, GBS_Graph 22 | from .channel import PhotonLoss 23 | from .circuit import QumodeCircuit 24 | from .decompose import UnitaryDecomposer 25 | from .draw import DrawClements 26 | from .gate import PhaseShift, BeamSplitter, MZI, BeamSplitterTheta, BeamSplitterPhi, BeamSplitterSingle, UAnyGate 27 | from .gate import Squeezing, Squeezing2, Displacement, DisplacementPosition, DisplacementMomentum 28 | from .gate import QuadraticPhase, ControlledX, ControlledZ, CubicPhase, Kerr, CrossKerr, DelayBS, DelayMZI 29 | from .hafnian_ import hafnian 30 | from .mapper import UnitaryMapper 31 | from .measurement import Generaldyne, Homodyne, GeneralBosonic, PhotonNumberResolvingBosonic 32 | from .qmath import permanent, takagi, xxpp_to_xpxp, xpxp_to_xxpp, quadrature_to_ladder, ladder_to_quadrature 33 | from .state import FockState, GaussianState, BosonicState, CatState, GKPState, FockStateBosonic 34 | from .tdm import QumodeCircuitTDM 35 | from .torontonian_ import torontonian 36 | from .utils import set_hbar, set_kappa, set_perm_chunksize 37 | 38 | hbar = 2 39 | kappa = 2 ** (-0.5) 40 | 41 | perm_chunksize_dict = {} 42 | -------------------------------------------------------------------------------- /src/deepquantum/photonic/ansatz.py: -------------------------------------------------------------------------------- 1 | """ 2 | Ansatze: various photonic quantum circuits 3 | """ 4 | 5 | from typing import Any, Dict, List, Optional 6 | 7 | import copy 8 | import networkx as nx 9 | import numpy as np 10 | import torch 11 | from scipy.optimize import root 12 | 13 | from ..qmath import is_unitary 14 | from .circuit import QumodeCircuit 15 | from .qmath import sort_dict_fock_basis, takagi 16 | from .state import FockState 17 | 18 | 19 | class Clements(QumodeCircuit): 20 | """Clements circuit.""" 21 | def __init__( 22 | self, 23 | nmode: int, 24 | init_state: Any, 25 | cutoff: Optional[int] = None, 26 | basis: bool = True, 27 | phi_first: bool = True, 28 | noise: bool = False, 29 | mu: float = 0, 30 | sigma: float = 0.1 31 | ) -> None: 32 | super().__init__(nmode=nmode, init_state=init_state, cutoff=cutoff, basis=basis, name='Clements', 33 | noise=noise, mu=mu, sigma=sigma) 34 | self.phi_first = phi_first 35 | wires1 = self.wires[1::2] 36 | wires2 = self.wires[2::2] 37 | if not phi_first: 38 | for wire in self.wires: 39 | self.ps(wire, encode=True) 40 | for i in range(nmode): 41 | if i % 2 == 0: 42 | for j in range(len(wires1)): 43 | self.mzi([wires1[j] - 1, wires1[j]], phi_first=phi_first, encode=True) 44 | else: 45 | for j in range(len(wires2)): 46 | self.mzi([wires2[j] - 1, wires2[j]], phi_first=phi_first, encode=True) 47 | if phi_first: 48 | for wire in self.wires: 49 | self.ps(wire, encode=True) 50 | 51 | def dict2data(self, angle_dict: Dict, dtype = torch.float) -> torch.Tensor: 52 | """Convert the dictionary of angles to the input data for the circuit.""" 53 | angle_dict = angle_dict.copy() 54 | for key in angle_dict.keys(): 55 | angle = angle_dict[key] 56 | if not isinstance(angle, torch.Tensor): 57 | angle = torch.tensor(angle) 58 | angle_dict[key] = angle.reshape(-1) 59 | data = [] 60 | columns = np.array([0] * self.nmode) 61 | wires1 = self.wires[1::2] 62 | wires2 = self.wires[2::2] 63 | if not self.phi_first: 64 | for i in range(self.nmode): 65 | data.append(angle_dict[(i, columns[i])]) 66 | columns[i] += 1 67 | for i in range(self.nmode): 68 | if i % 2 == 0: 69 | for j in range(len(wires1)): 70 | wire = wires1[j] - 1 71 | if self.phi_first: 72 | phi = angle_dict[(wire, columns[wire])] 73 | theta = angle_dict[(wire, columns[wire] + 1)] 74 | else: 75 | theta = angle_dict[(wire, columns[wire])] 76 | phi = angle_dict[(wire, columns[wire] + 1)] 77 | data.append(theta) 78 | data.append(phi) 79 | columns[wire] += 2 80 | else: 81 | for j in range(len(wires2)): 82 | wire = wires2[j] - 1 83 | if self.phi_first: 84 | phi = angle_dict[(wire, columns[wire])] 85 | theta = angle_dict[(wire, columns[wire] + 1)] 86 | else: 87 | theta = angle_dict[(wire, columns[wire])] 88 | phi = angle_dict[(wire, columns[wire] + 1)] 89 | data.append(theta) 90 | data.append(phi) 91 | columns[wire] += 2 92 | if self.phi_first: 93 | for i in range(self.nmode): 94 | data.append(angle_dict[(i, columns[i])]) 95 | columns[i] += 1 96 | return torch.cat(data).to(dtype) 97 | 98 | 99 | class GaussianBosonSampling(QumodeCircuit): 100 | """Gaussian Boson Sampling circuit.""" 101 | def __init__( 102 | self, 103 | nmode: int, 104 | squeezing: Any, 105 | unitary: Any, 106 | cutoff: Optional[int] = None, 107 | backend: str = 'gaussian', 108 | basis: bool = True, 109 | detector: str = 'pnrd', 110 | noise: bool = False, 111 | mu: float = 0, 112 | sigma: float = 0.1 113 | ) -> None: 114 | if not isinstance(squeezing, torch.Tensor): 115 | squeezing = torch.tensor(squeezing).reshape(-1) 116 | if not isinstance(unitary, torch.Tensor): 117 | unitary = torch.tensor(unitary, dtype=torch.cfloat).reshape(-1, nmode) 118 | assert unitary.dtype in (torch.cfloat, torch.cdouble) 119 | assert unitary.shape[-1] == unitary.shape[-2] == nmode 120 | assert is_unitary(unitary) 121 | if cutoff is None: 122 | cutoff = 3 123 | super().__init__(nmode=nmode, init_state='vac', cutoff=cutoff, backend=backend, basis=basis, 124 | detector=detector, name='GBS', noise=noise, mu=mu, sigma=sigma) 125 | for i in range(self.nmode): 126 | self.s(i, squeezing[i]) 127 | self.clements(unitary) 128 | 129 | 130 | class GBS_Graph(GaussianBosonSampling): 131 | """Simulate Gaussian Boson Sampling for graph problems.""" 132 | def __init__( 133 | self, 134 | adj_mat: Any, 135 | cutoff: Optional[int] = None, 136 | mean_photon_num: Optional[int] = None, 137 | detector: str = 'pnrd', 138 | noise: bool = False, 139 | mu: float = 0, 140 | sigma: float = 0.1 141 | ) -> None: 142 | if not isinstance(adj_mat, torch.Tensor): 143 | adj_mat = torch.tensor(adj_mat) 144 | assert torch.allclose(adj_mat, adj_mat.mT) 145 | self.adj_mat = adj_mat 146 | nmode = self.adj_mat.size()[-1] 147 | if mean_photon_num is None: 148 | mean_photon_num = nmode 149 | unitary, lambd = takagi(adj_mat) 150 | c = self.norm_factor_c(mean_photon_num, lambd)[0] 151 | lambda_c = lambd * c 152 | squeezing = np.arctanh(lambda_c) 153 | super().__init__(nmode=nmode, squeezing=squeezing, unitary=unitary, cutoff=cutoff, backend='gaussian', 154 | basis=False, detector=detector, noise=noise, mu=mu, sigma=sigma) 155 | self.name = 'GBS_Graph' 156 | self.to(adj_mat.dtype) 157 | 158 | @staticmethod 159 | def norm_factor_c(n_num, lambd, trials=20): 160 | """Get the normalization factor c of squeezing parameters for given total mean photon numbers.""" 161 | lambd = np.array(lambd) 162 | 163 | def f(c, lambd, n_num): 164 | ave_n = (lambd * c) ** 2 / (1 - (lambd * c) ** 2) 165 | return sum(ave_n) - n_num 166 | 167 | sol_re = [] 168 | for _ in range(trials): 169 | x_0 = np.random.uniform(0, 1 / max(lambd), 1)[0] 170 | re = root(f, x_0, (lambd, n_num)) 171 | if 0 < re.x < 1 / max(lambd): 172 | sol_re.append(re.x[0]) 173 | return sol_re 174 | 175 | @staticmethod 176 | def postselect(samples: Dict, nodes_list: List) -> List: 177 | """Postselect the results with the fixed node subgraph.""" 178 | dic_list = [{} for _ in range(len(nodes_list))] 179 | for key in samples.keys(): 180 | if isinstance(key, FockState): 181 | temp = sum(key.state.tolist()) 182 | else: 183 | temp = sum(key) 184 | if temp in nodes_list: 185 | temp_idx = nodes_list.index(temp) 186 | dic_list[temp_idx][key] = samples[key] 187 | return dic_list 188 | 189 | @staticmethod 190 | def graph_density(graph: nx.Graph, samples: Dict) -> Dict: 191 | """Get all subgraph densities.""" 192 | samples_ = copy.deepcopy(samples) 193 | for key in samples_.keys(): 194 | temp_prob = copy.deepcopy(samples_[key]) 195 | if isinstance(key, FockState): 196 | idx = torch.nonzero(key.state).squeeze() 197 | else: 198 | idx = torch.nonzero(torch.tensor(key)).squeeze() 199 | density = nx.density(graph.subgraph(idx.tolist())) 200 | samples_[key] = [temp_prob, density] 201 | sort_samples = sort_dict_fock_basis(samples_, 1) 202 | return sort_samples 203 | -------------------------------------------------------------------------------- /src/deepquantum/photonic/cache/Idx_2qb_6mode_aux_00.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/src/deepquantum/photonic/cache/Idx_2qb_6mode_aux_00.pickle -------------------------------------------------------------------------------- /src/deepquantum/photonic/cache/Idx_2qb_6mode_aux_00.pt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/src/deepquantum/photonic/cache/Idx_2qb_6mode_aux_00.pt -------------------------------------------------------------------------------- /src/deepquantum/photonic/cache/Idx_2qb_6mode_aux_10.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/src/deepquantum/photonic/cache/Idx_2qb_6mode_aux_10.pickle -------------------------------------------------------------------------------- /src/deepquantum/photonic/cache/Idx_2qb_6mode_aux_10.pt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/src/deepquantum/photonic/cache/Idx_2qb_6mode_aux_10.pt -------------------------------------------------------------------------------- /src/deepquantum/photonic/cache/Idx_3qb_8mode_aux_00.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/src/deepquantum/photonic/cache/Idx_3qb_8mode_aux_00.pickle -------------------------------------------------------------------------------- /src/deepquantum/photonic/cache/Idx_3qb_8mode_aux_00.pt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/src/deepquantum/photonic/cache/Idx_3qb_8mode_aux_00.pt -------------------------------------------------------------------------------- /src/deepquantum/photonic/cache/Idx_3qb_8mode_aux_10.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/src/deepquantum/photonic/cache/Idx_3qb_8mode_aux_10.pickle -------------------------------------------------------------------------------- /src/deepquantum/photonic/cache/Idx_3qb_8mode_aux_10.pt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/src/deepquantum/photonic/cache/Idx_3qb_8mode_aux_10.pt -------------------------------------------------------------------------------- /src/deepquantum/photonic/cache/Idx_4qb_10mode_aux_00.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/src/deepquantum/photonic/cache/Idx_4qb_10mode_aux_00.pickle -------------------------------------------------------------------------------- /src/deepquantum/photonic/cache/Idx_4qb_10mode_aux_00.pt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TuringQ/deepquantum/908b49cc4714a569060caf77317931065c765097/src/deepquantum/photonic/cache/Idx_4qb_10mode_aux_00.pt -------------------------------------------------------------------------------- /src/deepquantum/photonic/channel.py: -------------------------------------------------------------------------------- 1 | """ 2 | Photonic quantum channels 3 | """ 4 | 5 | from typing import Any, List, Optional, Tuple, Union 6 | 7 | import torch 8 | 9 | import deepquantum.photonic as dqp 10 | from .gate import BeamSplitterSingle 11 | from .operation import Channel 12 | 13 | 14 | class PhotonLoss(Channel): 15 | r"""Photon loss channel on single mode. 16 | 17 | This channel couples the target mode $\hat{a}$ to the vacuum mode $\hat{b}$ using 18 | following transformation: 19 | 20 | .. math:: 21 | 22 | \hat{a}_{\text{out}} = \sqrt{T}\hat{a}_{\text{in}} + \sqrt{1-T}\hat{b}_{\text{vac}} 23 | 24 | Args: 25 | inputs (Any, optional): The parameter of the channel. Default: ``None`` 26 | nmode (int, optional): The number of modes that the quantum operation acts on. Default: 1 27 | wires (int, List[int] or None, optional): The indices of the modes that the quantum operation acts on. 28 | Default: ``None`` 29 | cutoff (int or None, optional): The Fock space truncation. Default: ``None`` 30 | requires_grad (bool, optional): Whether the parameter is ``nn.Parameter`` or ``buffer``. 31 | Default: ``False`` (which means ``buffer``) 32 | """ 33 | def __init__( 34 | self, 35 | inputs: Any = None, 36 | nmode: int = 1, 37 | wires: Union[int, List[int], None] = None, 38 | cutoff: Optional[int] = None, 39 | requires_grad: bool = False 40 | ) -> None: 41 | super().__init__(name='PhotonLoss', nmode=nmode, wires=wires, cutoff=cutoff) 42 | self.requires_grad = requires_grad 43 | self.gate = BeamSplitterSingle(inputs=inputs, nmode=self.nmode + 1, wires=self.wires + [self.nmode], 44 | cutoff=cutoff, den_mat=True, convention='h', requires_grad=requires_grad, noise=False) 45 | self.npara = 1 46 | 47 | @property 48 | def theta(self): 49 | return self.gate.theta 50 | 51 | @property 52 | def t(self): 53 | """Transmittance.""" 54 | return torch.cos(self.theta / 2) ** 2 55 | 56 | def update_matrix_state(self) -> torch.Tensor: 57 | """Update the local Kraus matrices acting on Fock state density matrices.""" 58 | return self.get_matrix_state(self.theta) 59 | 60 | def get_matrix_state(self, theta: Any) -> torch.Tensor: 61 | """Get the local Kraus matrices acting on Fock state density matrices. 62 | 63 | See https://arxiv.org/pdf/1012.4266 Eq.(2.4) 64 | """ 65 | matrix = self.gate.get_matrix_state(self.gate.get_matrix(theta)) 66 | return matrix[..., 0].permute([1, 0, 2]) 67 | 68 | def init_para(self, inputs: Any = None) -> None: 69 | """Initialize the parameters.""" 70 | self.gate.init_para(inputs) 71 | 72 | def update_transform_xy(self) -> Tuple[torch.Tensor, torch.Tensor]: 73 | """Update the local transformation matrices X and Y acting on Gaussian states. 74 | 75 | See https://arxiv.org/pdf/quant-ph/0503237 Eq.(4.19), Eq.(4.20) 76 | """ 77 | g_t_sqrt = self.theta.new_ones(2).diag() * torch.cos(self.theta / 2) 78 | g_t = self.theta.new_ones(2).diag() * torch.cos(self.theta / 2) ** 2 79 | identity = self.theta.new_ones(2).diag() 80 | sigma_h = self.theta.new_ones(2).diag() * dqp.hbar / (4 * dqp.kappa ** 2) 81 | matrix_x = g_t_sqrt 82 | matrix_y = (identity - g_t) @ sigma_h 83 | self.matrix_x = matrix_x.detach() 84 | self.matrix_y = matrix_y.detach() 85 | return matrix_x, matrix_y 86 | 87 | def extra_repr(self) -> str: 88 | return f'wires={self.wires}, transmittance={self.t.item()}' 89 | -------------------------------------------------------------------------------- /src/deepquantum/photonic/hafnian_.py: -------------------------------------------------------------------------------- 1 | """ 2 | functions for hafnian 3 | """ 4 | 5 | from collections import Counter 6 | from functools import lru_cache 7 | from typing import List, Union 8 | 9 | import numpy as np 10 | import torch 11 | from scipy.special import factorial 12 | 13 | from .qmath import get_powerset 14 | 15 | 16 | @lru_cache(maxsize=None) 17 | def integer_partition(remaining: int, max_num: int) -> List: 18 | """Generate all unique integer partitions of m using integers up to n.""" 19 | if remaining == 0: 20 | return [[]] 21 | if remaining < 0 or max_num == 0: 22 | return [] 23 | result = [] 24 | if remaining >= max_num: 25 | for part in integer_partition(remaining - max_num, max_num): 26 | result.append([max_num] + part) 27 | result.extend(integer_partition(remaining, max_num - 1)) 28 | return result 29 | 30 | 31 | def count_unique_permutations(nums: Union[List, np.array]) -> np.float64: 32 | """Count the number of unique permutations of a list of numbers.""" 33 | total_permutations = factorial(len(nums)) 34 | num_counts = Counter(nums) 35 | repetitions = 1 36 | for count in num_counts.values(): 37 | repetitions *= factorial(count) 38 | unique_permutations = total_permutations // repetitions 39 | return unique_permutations 40 | 41 | 42 | def get_submat_haf(a: torch.Tensor, z: torch.Tensor) -> torch.Tensor: 43 | """Get the sub-matrix for hafnian calculation. 44 | 45 | See https://arxiv.org/abs/1805.12498 paragraph after Eq.(3.20) 46 | """ 47 | idx1 = 2 * z 48 | idx2 = idx1 + 1 49 | idx = torch.cat([idx1, idx2]) 50 | idx = torch.sort(idx)[0] 51 | submat = a[idx][:, idx] 52 | return submat 53 | 54 | 55 | def poly_lambda(submat: torch.Tensor, int_partition: List, power: int, loop: bool = False) -> torch.Tensor: 56 | """Get the coefficient of the polynomial.""" 57 | size = submat.shape[-1] 58 | identity = torch.eye(size, dtype=submat.dtype, device=submat.device) 59 | x_mat = identity.reshape(size // 2, 2, size).flip(1).reshape(size, size) 60 | xaz = x_mat @ submat 61 | eigen = torch.linalg.eigvals(xaz) # eigen decomposition 62 | trace_list = torch.stack([(eigen ** i).sum() for i in range(0, power + 1)]) 63 | coeff = 0 64 | if loop: # loop hafnian case 65 | v = torch.diag(submat) 66 | diag_term = torch.stack([v @ torch.linalg.matrix_power(xaz, i - 1) @ x_mat @ v / 2 for i in range(1, power+1)]) 67 | for orders in int_partition: 68 | ncount = count_unique_permutations(orders) 69 | orders = torch.tensor(orders, device=submat.device) 70 | poly_list = trace_list[orders] / (2 * orders) 71 | if loop: 72 | poly_list += diag_term[orders - 1] 73 | poly_prod = poly_list.prod() 74 | coeff += ncount / factorial(len(orders)) * poly_prod 75 | return coeff 76 | 77 | 78 | def hafnian(matrix: torch.Tensor, loop: bool = False) -> torch.Tensor: 79 | """Calculate the hafnian for symmetric matrix, using the eigenvalue-trace method. 80 | 81 | See https://arxiv.org/abs/2108.01622 Eq.(B3) 82 | """ 83 | size = matrix.shape[-1] 84 | if size % 2 == 1: 85 | if loop: 86 | matrix = torch.block_diag(torch.tensor(1, dtype=matrix.dtype, device=matrix.device), matrix) 87 | size = matrix.shape[-1] 88 | else: 89 | return torch.tensor(0, dtype=matrix.dtype, device=matrix.device) 90 | if size == 0: 91 | return torch.tensor(1, dtype=matrix.dtype, device=matrix.device) 92 | if size == 2: 93 | if loop: 94 | return matrix[0, 1] + matrix[0, 0] * matrix[1, 1] 95 | else: 96 | return matrix[0, 1] 97 | power = size // 2 98 | haf = 0 99 | powerset = get_powerset(power) 100 | int_partition = integer_partition(power, power) 101 | for i in range(1, len(powerset)): 102 | z_sets = torch.tensor(powerset[i], device=matrix.device) 103 | num_z = len(z_sets[0]) 104 | submats = torch.vmap(get_submat_haf, in_dims=(None, 0))(matrix, z_sets) 105 | coeff = torch.vmap(poly_lambda, in_dims=(0, None, None, None))(submats, int_partition, power, loop) 106 | coeff_sum = (-1) ** (power - num_z) * coeff.sum() 107 | haf += coeff_sum 108 | return haf 109 | 110 | 111 | def hafnian_batch(matrix: torch.Tensor, loop: bool = False) -> torch.Tensor: 112 | """Calculate the batch hafnian.""" 113 | assert matrix.dim() == 3, 'Input tensor should be in batched size' 114 | batch = matrix.shape[0] 115 | for i in range(batch): 116 | assert torch.allclose(matrix[i], matrix[i].mT) 117 | hafs = torch.vmap(hafnian, in_dims=(0, None))(matrix, loop) 118 | return hafs 119 | -------------------------------------------------------------------------------- /src/deepquantum/photonic/tdm.py: -------------------------------------------------------------------------------- 1 | """ 2 | Time domain multiplexing 3 | """ 4 | 5 | from typing import Any, List, Optional, Union 6 | 7 | import torch 8 | 9 | from .circuit import QumodeCircuit 10 | 11 | 12 | class QumodeCircuitTDM(QumodeCircuit): 13 | r"""Time-domain-multiplexed photonic quantum circuit. 14 | 15 | Note: 16 | When using large squeezing parameters, we recommend using a double data type and a smaller ``eps`` for Homodyne 17 | to avoid issues with non-positive definiteness of the covariance matrix. 18 | 19 | Args: 20 | nmode (int): The number of spatial modes in the circuit. 21 | init_state (Any): The initial state of the circuit. It can be a vacuum state with ``'vac'``. 22 | For Gaussian backend, it can be arbitrary Gaussian states with ``[cov, mean]``. 23 | Use ``xxpp`` convention and :math:`\hbar=2` by default. 24 | cutoff (int or None, optional): The Fock space truncation. Default: ``None`` 25 | backend (str, optional): Use ``'gaussian'`` for Gaussian backend or ``'bosonic'`` for Bosonic backend. 26 | Default: ``'gaussian'`` 27 | name (str or None, optional): The name of the circuit. Default: ``None`` 28 | noise (bool, optional): Whether to introduce Gaussian noise. Default: ``False`` 29 | mu (float, optional): The mean of Gaussian noise. Default: 0 30 | sigma (float, optional): The standard deviation of Gaussian noise. Default: 0.1 31 | """ 32 | def __init__( 33 | self, 34 | nmode: int, 35 | init_state: Any, 36 | cutoff: Optional[int] = None, 37 | backend: str = 'gaussian', 38 | name: Optional[str] = None, 39 | noise: bool = False, 40 | mu: float = 0, 41 | sigma: float = 0.1 42 | ) -> None: 43 | assert backend in ('gaussian', 'bosonic') 44 | super().__init__(nmode=nmode, init_state=init_state, cutoff=cutoff, backend=backend, basis=False, 45 | detector='pnrd', name=name, mps=False, chi=None, noise=noise, mu=mu, sigma=sigma) 46 | self.samples = None 47 | 48 | def forward( 49 | self, 50 | data: Optional[torch.Tensor] = None, 51 | state: Any = None, 52 | nstep: Optional[int] = None 53 | ) -> List[torch.Tensor]: 54 | r"""Perform a forward pass of the TDM photonic quantum circuit and return the final state. 55 | 56 | Args: 57 | data (torch.Tensor or None, optional): The input data for the ``encoders`` with the shape of 58 | :math:`(\text{batch}, \text{ntimes}, \text{nfeat})`. Default: ``None`` 59 | state (Any, optional): The initial state for the photonic quantum circuit. Default: ``None`` 60 | nstep (int or None, optional): The number of the evolved time steps. Default: ``None`` 61 | 62 | Returns: 63 | List[torch.Tensor]: The covariance matrix and displacement vector of the measured final state. 64 | """ 65 | assert self._if_delayloop, 'No delay loop.' 66 | for i in range(self.nmode): 67 | assert i in self.wires_homodyne 68 | if data is None: 69 | if nstep is None: 70 | nstep = 1 71 | else: 72 | size = data.size() 73 | assert data.ndim == 3 74 | if nstep is None: 75 | nstep = size[1] 76 | self.state = state 77 | samples = [] 78 | for i in range(nstep): 79 | if data is None: 80 | self.state = super().forward(state=self.state) 81 | else: 82 | data_i = data[:, i % size[1], :] 83 | self.state = super().forward(data_i, self.state) 84 | samples.append(self.measure_homodyne(shots=1)) 85 | self.state = self.state_measured 86 | self.samples = torch.stack(samples, dim=-1) # (batch, nwire, nstep) 87 | return self.state 88 | 89 | def get_samples(self, wires: Union[int, List[int], None] = None) -> torch.Tensor: 90 | """Get the measured samples according to the given ``wires``.""" 91 | if wires is None: 92 | wires = self.wires 93 | wires = sorted(self._convert_indices(wires)) 94 | return self.samples[..., wires, :] 95 | -------------------------------------------------------------------------------- /src/deepquantum/photonic/torontonian_.py: -------------------------------------------------------------------------------- 1 | """ 2 | functions for torontonian 3 | """ 4 | 5 | from typing import Optional 6 | 7 | import torch 8 | 9 | from .qmath import get_powerset 10 | 11 | 12 | def get_submat_tor(a: torch.Tensor, z: torch.Tensor) -> torch.Tensor: 13 | """Get the sub-matrix for torontonian calculation.""" 14 | idx1 = z 15 | idx2 = idx1 + a.shape[-1] // 2 16 | idx = torch.cat([idx1, idx2]) 17 | idx = torch.sort(idx)[0] 18 | if a.dim() == 1: 19 | return a[idx] 20 | if a.dim() == 2: 21 | return a[idx][:, idx] 22 | 23 | 24 | def _tor_helper(submat: torch.Tensor, sub_gamma: torch.Tensor) -> torch.Tensor: 25 | size = submat.shape[-1] 26 | cov_q_inv = torch.eye(size, dtype=submat.dtype, device=submat.device) - submat 27 | exp_term = sub_gamma @ torch.linalg.solve(cov_q_inv, sub_gamma.conj()) / 2 28 | return torch.exp(exp_term) / torch.sqrt(torch.linalg.det(cov_q_inv)) 29 | 30 | 31 | def torontonian(o_mat: torch.Tensor, gamma: Optional[torch.Tensor] = None) -> torch.Tensor: 32 | """Calculate the torontonian function for the given matrix. 33 | 34 | See https://research-information.bris.ac.uk/ws/portalfiles/portal/329011096/thesis.pdf Eq.(3.54) 35 | """ 36 | size = o_mat.shape[-1] 37 | if gamma is None: 38 | gamma = torch.zeros(size, dtype=o_mat.dtype, device=o_mat.device) 39 | m = size // 2 40 | powerset = get_powerset(m) 41 | tor = (-1) ** m 42 | for i in range(1, len(powerset)): 43 | y_sets = torch.tensor(powerset[i], device=o_mat.device) 44 | num_y = len(y_sets[0]) 45 | sub_mats = torch.vmap(get_submat_tor, in_dims=(None, 0))(o_mat, y_sets) 46 | sub_gammas = torch.vmap(get_submat_tor, in_dims=(None, 0))(gamma, y_sets) 47 | coeff = torch.vmap(_tor_helper)(sub_mats, sub_gammas) 48 | coeff_sum = (-1) ** (m - num_y) * coeff.sum() 49 | tor += coeff_sum 50 | return tor 51 | 52 | 53 | def torontonian_batch(o_mat: torch.Tensor, gamma: Optional[torch.Tensor] = None) -> torch.Tensor: 54 | """Calculate the batch torontonian.""" 55 | assert o_mat.dim() == 3, 'Input tensor should be in batched size' 56 | assert o_mat.shape[-2] == o_mat.shape[-1] 57 | assert o_mat.shape[-1] % 2 == 0, 'Input matrix dimension should be even' 58 | if gamma is None: # torontonian case 59 | tors = torch.vmap(torontonian, in_dims=(0, None))(o_mat, gamma) 60 | else: # loop torontonian case 61 | tors = torch.vmap(torontonian, in_dims=(0, 0))(o_mat, gamma) 62 | return tors 63 | -------------------------------------------------------------------------------- /src/deepquantum/photonic/utils.py: -------------------------------------------------------------------------------- 1 | """ 2 | Utilities 3 | """ 4 | 5 | import gzip 6 | import pickle 7 | from typing import Optional 8 | 9 | import numpy as np 10 | import psutil 11 | import torch 12 | 13 | import deepquantum.photonic as dqp 14 | 15 | 16 | def set_hbar(hbar: float) -> None: 17 | """Set the global reduced Planck constant.""" 18 | dqp.hbar = hbar 19 | 20 | def set_kappa(kappa: float) -> None: 21 | """Set the global kappa.""" 22 | dqp.kappa = kappa 23 | 24 | def load_sample(filename): 25 | """load the sample data with the given filename""" 26 | with gzip.open('./data/' + filename + '.pkl.gz','rb') as f: 27 | sample = pickle.load(f) 28 | return sample 29 | 30 | def save_sample(filename, data): 31 | """save the sample data with the given filename""" 32 | with gzip.open('./data/' + filename + '.pkl.gz','wb') as f: 33 | pickle.dump(data, f) 34 | return 35 | 36 | def load_adj(filename): 37 | """load the adjacent matrix with the given filename""" 38 | mat = np.load('./data/' + filename + '.npy') 39 | return mat 40 | 41 | def save_adj(filename, data): 42 | """save the adjacent matrix with the given filename""" 43 | np.save('./data/' + filename + '.npy', data) 44 | return 45 | 46 | def mem_to_chunksize(device: torch.device, dtype: torch.dtype) -> Optional[int]: 47 | """Return the chunk size of vmap according to device free memory and dtype. 48 | 49 | Note: Currently only optimized for permanent and complex dtype. 50 | """ 51 | if (device, dtype) in dqp.perm_chunksize_dict: 52 | return dqp.perm_chunksize_dict[device, dtype] 53 | if device == torch.device('cpu'): 54 | mem_free_gb = psutil.virtual_memory().free / 1024**3 55 | else: 56 | mem_free_gb = torch.cuda.mem_get_info(device=device)[0] / 1024**3 57 | if dtype == torch.cfloat: 58 | if mem_free_gb > 80: 59 | # requires checking when we have such GPUs:) 60 | chunksize = int(5e6) 61 | elif mem_free_gb > 60: 62 | chunksize = int(2e6) 63 | elif mem_free_gb > 20: 64 | chunksize = int(6e5) 65 | elif mem_free_gb > 8: 66 | chunksize = int(2e5) 67 | elif mem_free_gb > 5: 68 | chunksize = int(1.25e5) 69 | else: 70 | chunksize = int(2e4) 71 | elif dtype == torch.cdouble: 72 | if mem_free_gb > 80: 73 | chunksize = int(2e6) 74 | elif mem_free_gb > 60: 75 | chunksize = int(1e6) 76 | elif mem_free_gb > 20: 77 | chunksize = int(3e5) 78 | elif mem_free_gb > 8: 79 | chunksize = int(1e5) 80 | elif mem_free_gb > 5: 81 | chunksize = int(6e4) 82 | else: 83 | chunksize = int(1e4) 84 | else: 85 | chunksize = None 86 | dqp.perm_chunksize_dict[device, dtype] = chunksize 87 | return chunksize 88 | 89 | def set_perm_chunksize(device: torch.device, dtype: torch.dtype, chunksize: Optional[int]) -> None: 90 | """Set the global chunk size for permanent calculations.""" 91 | dqp.perm_chunksize_dict[device, dtype] = chunksize 92 | -------------------------------------------------------------------------------- /src/deepquantum/utils.py: -------------------------------------------------------------------------------- 1 | """ 2 | Utilities 3 | """ 4 | 5 | import time 6 | from functools import wraps 7 | from typing import Callable 8 | 9 | 10 | def record_time(func: Callable) -> Callable: 11 | """A decorator that records the running time of a function.""" 12 | @wraps(func) 13 | def wrapped_function(*args, **kwargs): 14 | t1 = time.time() 15 | rst = func(*args, **kwargs) 16 | t2 = time.time() 17 | print(f'running time of "{func.__name__}": {t2 - t1}') 18 | return rst 19 | return wrapped_function 20 | 21 | 22 | class Time(object): 23 | """A decorator that records the running time of a function.""" 24 | def __init__(self) -> None: 25 | pass 26 | 27 | def __call__(self, func: Callable) -> Callable: 28 | @wraps(func) 29 | def wrapped_function(*args, **kwargs): 30 | t1 = time.time() 31 | rst = func(*args, **kwargs) 32 | t2 = time.time() 33 | print(f'running time of "{func.__name__}": {t2 - t1}') 34 | return rst 35 | return wrapped_function 36 | -------------------------------------------------------------------------------- /tests/test_ansatz.py: -------------------------------------------------------------------------------- 1 | import math 2 | from fractions import Fraction 3 | 4 | import deepquantum as dq 5 | import pytest 6 | 7 | 8 | def test_quantum_phase_estimation_single_qubit(): 9 | t = 3 10 | phase = 1 / 8 11 | qpe = dq.QuantumPhaseEstimationSingleQubit(t, phase) 12 | qpe() 13 | res = qpe.measure(wires=list(range(t))) 14 | max_key = max(res, key=res.get) 15 | phase_est = int(max_key, 2) / 2 ** t 16 | assert phase_est == phase 17 | 18 | 19 | def test_phi_adder(): 20 | nqubit = 5 21 | n1 = 1 22 | n2 = 8 23 | enc = dq.NumberEncoder(nqubit, n1) 24 | qft = dq.QuantumFourierTransform(nqubit, reverse=True) 25 | phiadd = dq.PhiAdder(nqubit, n2) 26 | iqft = qft.inverse() 27 | cir = enc + qft + phiadd + iqft 28 | cir() 29 | res = cir.measure() 30 | max_key = max(res, key=res.get) 31 | assert int(max_key, 2) == n1 + n2 32 | 33 | 34 | def test_phi_modular_adder(): 35 | n1 = 5 36 | n2 = 1 37 | mod = 8 38 | assert n1 < mod and n1 + n2 < 2 * mod 39 | nqubit = len(bin(mod)) 40 | minmax = [0, nqubit - 2] 41 | ancilla = [nqubit - 1] 42 | enc = dq.NumberEncoder(nqubit, n1, minmax) 43 | qft = dq.QuantumFourierTransform(nqubit, minmax, reverse=True) 44 | pma = dq.PhiModularAdder(nqubit, n2, mod, minmax, ancilla) 45 | iqft = qft.inverse() 46 | cir = enc + qft + pma + iqft 47 | cir() 48 | res = cir.measure(wires=list(range(minmax[0], minmax[1] + 1))) 49 | max_key = max(res, key=res.get) 50 | assert int(max_key, 2) == (n1 + n2) % mod 51 | 52 | 53 | def test_controlled_multiplier(): 54 | n1 = 1 55 | n2 = 2 56 | n3 = 14 57 | mod = 15 58 | assert n1 < mod and n1 + n2 * n3 < 2 * mod 59 | nx = len(bin(n3)) - 2 60 | nb = len(bin(mod)) - 1 61 | nqubit = nx + nb + 1 62 | minmax1 = [0, nx - 1] 63 | minmax2 = [nx, nqubit - 2] 64 | ancilla = [nqubit -1] 65 | enc1 = dq.NumberEncoder(nqubit, n3, minmax1) 66 | enc2 = dq.NumberEncoder(nqubit, n1, minmax2) 67 | cmult = dq.ControlledMultiplier(nqubit, n2, mod, [0, nqubit - 2], nx, ancilla) 68 | cir = enc1 + enc2 + cmult 69 | cir() 70 | res = cir.measure(wires=list(range(minmax2[0], minmax2[1] + 1))) 71 | max_key = max(res, key=res.get) 72 | assert int(max_key, 2) == (n1 + n2 * n3) % mod 73 | 74 | 75 | def test_controlled_ua(): 76 | mod = 15 77 | a = 8 78 | x = 3 79 | assert a < mod and x < mod 80 | assert math.gcd(a, mod) == 1 81 | nreg = len(bin(mod)) - 2 82 | nqubit = 2 * nreg + 2 83 | minmax = [0, nreg - 1] 84 | ancilla = list(range(minmax[1] + 1, minmax[1] + 1 + nreg + 2)) 85 | enc = dq.NumberEncoder(nqubit, x, minmax) 86 | ua = dq.ControlledUa(nqubit, a, mod, minmax, ancilla) 87 | cir = enc + ua 88 | cir() 89 | res = cir.measure(wires=list(range(minmax[0], minmax[1] + 1))) 90 | max_key = max(res, key=res.get) 91 | assert int(max_key, 2) == (a * x) % mod 92 | res = cir.measure(wires=ancilla) 93 | max_key = max(res, key=res.get) 94 | assert int(max_key, 2) == 0 95 | 96 | 97 | def test_shor_general(): 98 | a = 7 99 | mod = 15 100 | ncount = 8 101 | found = False 102 | trial = 0 103 | while not found: 104 | trial += 1 105 | print(f'\ntrial {trial}:') 106 | cir = dq.ShorCircuit(mod, ncount, a) 107 | cir() 108 | res = cir.measure(wires=list(range(ncount)), shots=1) 109 | max_key = max(res, key=res.get) 110 | phase = int(max_key, 2) / 2 ** ncount 111 | frac = Fraction(phase).limit_denominator(mod) 112 | r = frac.denominator 113 | print(f'Result: r = {r}') 114 | if phase != 0: 115 | guesses = [math.gcd(a ** (r // 2) - 1, mod), math.gcd(a ** (r // 2) + 1, mod)] 116 | print(f'Guessed Factors: {guesses[0]} and {guesses[1]}') 117 | for guess in guesses: 118 | if guess not in [1, mod] and (mod % guess) == 0: 119 | print(f'*** Non-trivial factor found: {guess} ***') 120 | found = True 121 | assert guess in [3, 5] 122 | 123 | 124 | def test_shor_special(): 125 | a = 7 126 | mod = 15 127 | ncount = 8 128 | found = False 129 | trial = 0 130 | while not found: 131 | trial += 1 132 | print(f'\ntrial {trial}:') 133 | cir = dq.ShorCircuitFor15(ncount, a) 134 | cir() 135 | res = cir.measure(wires=list(range(ncount)), shots=1) 136 | max_key = max(res, key=res.get) 137 | phase = int(max_key, 2) / 2 ** ncount 138 | frac = Fraction(phase).limit_denominator(mod) 139 | r = frac.denominator 140 | print(f'Result: r = {r}') 141 | if phase != 0: 142 | guesses = [math.gcd(a ** (r // 2) - 1, mod), math.gcd(a ** (r // 2) + 1, mod)] 143 | print(f'Guessed Factors: {guesses[0]} and {guesses[1]}') 144 | for guess in guesses: 145 | if guess not in [1, mod] and (mod % guess) == 0: 146 | print(f'*** Non-trivial factor found: {guess} ***') 147 | found = True 148 | assert guess in [3, 5] 149 | -------------------------------------------------------------------------------- /tests/test_auto_grad.py: -------------------------------------------------------------------------------- 1 | import deepquantum as dq 2 | import pytest 3 | import torch 4 | 5 | 6 | def test_gaussian_backend_auto_grad(): 7 | def get_vac_prob(paras): 8 | nmode = 2 9 | cir = dq.QumodeCircuit(nmode=nmode, init_state='vac', cutoff=3, backend='gaussian') 10 | cir.s(wires=0, r=paras[0]) 11 | cir.s(wires=1, r=paras[1]) 12 | cir.d(wires=0, r=paras[2]) 13 | cir.d(wires=1, r=paras[3]) 14 | cir.bs(wires=[0,1], inputs=[paras[4], paras[5]]) 15 | 16 | state = cir(is_prob=True) 17 | target_state = dq.FockState([0,0]) 18 | vac_prob = state[target_state] 19 | return vac_prob 20 | 21 | r_s1 = torch.tensor([1.], requires_grad=True) 22 | r_s2 = torch.tensor([1.], requires_grad=True) 23 | r_d1 = torch.tensor([1.], requires_grad=True) 24 | r_d2 = torch.tensor([1.], requires_grad=True) 25 | theta = torch.tensor([0.1], requires_grad=True) 26 | phi = torch.tensor([0.1], requires_grad=True) 27 | para_ini = [r_s1, r_s2, r_d1, r_d2, theta, phi] 28 | 29 | target_prob = 0.5 # set vacuum state prob 30 | optimizer = torch.optim.Adam(para_ini, lr=0.05) 31 | best_para = [] 32 | for _ in range(500): 33 | optimizer.zero_grad() 34 | vac_prob = get_vac_prob(para_ini) # forward 35 | loss = abs(target_prob - vac_prob) 36 | if loss < 1e-4: 37 | best_para.append([i.detach().clone() for i in para_ini]) 38 | loss.backward() # backpropagation 39 | optimizer.step() # update parameters 40 | best_result = get_vac_prob(best_para[0]) 41 | assert abs(best_result - target_prob) < 1e-4 42 | -------------------------------------------------------------------------------- /tests/test_channel.py: -------------------------------------------------------------------------------- 1 | import deepquantum as dq 2 | import pytest 3 | import torch 4 | 5 | 6 | def test_qubit_channel(): 7 | cir = dq.QubitCircuit(2, den_mat=True) 8 | cir.hlayer() 9 | cir.bit_flip(0) 10 | cir.phase_flip(1) 11 | cir.depolarizing(0) 12 | cir.pauli(1) 13 | cir.amp_damp(0) 14 | cir.phase_damp(1) 15 | cir.gen_amp_damp(0) 16 | assert torch.allclose(torch.trace(cir()), torch.tensor(1.) + 0j) 17 | -------------------------------------------------------------------------------- /tests/test_circuit.py: -------------------------------------------------------------------------------- 1 | import deepquantum as dq 2 | import pytest 3 | import torch 4 | 5 | 6 | def test_qubit_mps(): 7 | nqubit = 3 8 | cir = dq.QubitCircuit(nqubit, mps=True, chi=64) 9 | cir.rx(0, 0.1) 10 | cir.cnot(0, 1) 11 | cir.ry(1, 0.2) 12 | cir.cnot(1, 2) 13 | state1 = dq.MatrixProductState(3, cir()).full_tensor().reshape(-1) 14 | 15 | cir = dq.QubitCircuit(nqubit) 16 | cir.rx(0, 0.1) 17 | cir.cnot(0, 1) 18 | cir.ry(1, 0.2) 19 | cir.cnot(1, 2) 20 | state2 = cir().reshape(-1) 21 | assert torch.allclose(state1, state2, rtol=1e-5, atol=1e-5) 22 | 23 | 24 | def test_fock_mps(): 25 | nmode = 3 26 | cutoff = 8 27 | cir = dq.QumodeCircuit(nmode, init_state='zeros', cutoff=cutoff, backend='fock', basis=False, mps=True, chi=64) 28 | cir.s(0, 0.1) 29 | cir.s(1, 0.2) 30 | cir.s(2, 0.3) 31 | cir.bs([0,1], [0.1,0.2]) 32 | cir.bs([1,2], [0.3,0.4]) 33 | state1 = dq.MatrixProductState(nmode, cir()).full_tensor().reshape(-1) 34 | 35 | cir = dq.QumodeCircuit(nmode, init_state='zeros', cutoff=cutoff, backend='fock', basis=False) 36 | cir.s(0, 0.1) 37 | cir.s(1, 0.2) 38 | cir.s(2, 0.3) 39 | cir.bs([0,1], [0.1,0.2]) 40 | cir.bs([1,2], [0.3,0.4]) 41 | state2 = cir().reshape(-1) 42 | assert torch.allclose(state1, state2, rtol=1e-5, atol=1e-5) 43 | 44 | 45 | def test_qubit_dist(): 46 | data = torch.randn(10) 47 | cir = dq.DistritubutedQubitCircuit(4, reupload=True) 48 | cir.rxlayer(encode=True) 49 | cir.rylayer(encode=True) 50 | cir.rzlayer(encode=True) 51 | cir.u3layer(encode=True) 52 | cir.hlayer() 53 | cir.cnot_ring() 54 | cir.toffoli(0,1,2) 55 | cir.fredkin(2,1,0) 56 | cir.rx(0, controls=[1,2,3], encode=True) 57 | cir.ry(1, controls=[0,2,3], encode=True) 58 | cir.rz(2, controls=[0,1,3], encode=True) 59 | cir.rxx([0,1], controls=[2,3], encode=True) 60 | cir.ryy([1,2], controls=[0,3], encode=True) 61 | cir.rzz([2,3], controls=[0,1], encode=True) 62 | cir.rxy([3,0], controls=[1,2], encode=True) 63 | state1 = cir(data=data).amps 64 | 65 | cir = dq.QubitCircuit(4, reupload=True) 66 | cir.rxlayer(encode=True) 67 | cir.rylayer(encode=True) 68 | cir.rzlayer(encode=True) 69 | cir.u3layer(encode=True) 70 | cir.hlayer() 71 | cir.cnot_ring() 72 | cir.toffoli(0,1,2) 73 | cir.fredkin(2,1,0) 74 | cir.rx(0, controls=[1,2,3], encode=True) 75 | cir.ry(1, controls=[0,2,3], encode=True) 76 | cir.rz(2, controls=[0,1,3], encode=True) 77 | cir.rxx([0,1], controls=[2,3], encode=True) 78 | cir.ryy([1,2], controls=[0,3], encode=True) 79 | cir.rzz([2,3], controls=[0,1], encode=True) 80 | cir.rxy([3,0], controls=[1,2], encode=True) 81 | state2 = cir(data=data).reshape(-1) 82 | assert torch.allclose(state1, state2) 83 | 84 | 85 | def test_qubit_expectation_and_differentiation_dist(): 86 | data1 = torch.arange(10, dtype=torch.float, requires_grad=True) 87 | cir1 = dq.DistritubutedQubitCircuit(4, reupload=True) 88 | cir1.rxlayer(encode=True) 89 | cir1.rylayer(encode=True) 90 | cir1.rzlayer(encode=True) 91 | cir1.u3layer(encode=True) 92 | cir1.hlayer() 93 | cir1.cnot_ring() 94 | cir1.toffoli(0,1,2) 95 | cir1.fredkin(2,1,0) 96 | cir1.rx(0, controls=[1,2,3], encode=True) 97 | cir1.ry(1, controls=[0,2,3], encode=True) 98 | cir1.rz(2, controls=[0,1,3], encode=True) 99 | cir1.rxx([0,1], controls=[2,3], encode=True) 100 | cir1.ryy([1,2], controls=[0,3], encode=True) 101 | cir1.rzz([2,3], controls=[0,1], encode=True) 102 | cir1.rxy([3,0], controls=[1,2], encode=True) 103 | cir1.observable(0) 104 | cir1.observable(1, 'x') 105 | cir1.observable([2,3], 'xy') 106 | cir1(data=data1) 107 | exp1 = cir1.expectation().sum() 108 | exp1.backward() 109 | 110 | data2 = torch.arange(10, dtype=torch.float, requires_grad=True) 111 | cir2 = dq.QubitCircuit(4, reupload=True) 112 | cir2.rxlayer(encode=True) 113 | cir2.rylayer(encode=True) 114 | cir2.rzlayer(encode=True) 115 | cir2.u3layer(encode=True) 116 | cir2.hlayer() 117 | cir2.cnot_ring() 118 | cir2.toffoli(0,1,2) 119 | cir2.fredkin(2,1,0) 120 | cir2.rx(0, controls=[1,2,3], encode=True) 121 | cir2.ry(1, controls=[0,2,3], encode=True) 122 | cir2.rz(2, controls=[0,1,3], encode=True) 123 | cir2.rxx([0,1], controls=[2,3], encode=True) 124 | cir2.ryy([1,2], controls=[0,3], encode=True) 125 | cir2.rzz([2,3], controls=[0,1], encode=True) 126 | cir2.rxy([3,0], controls=[1,2], encode=True) 127 | cir2.observable(0) 128 | cir2.observable(1, 'x') 129 | cir2.observable([2,3], 'xy') 130 | cir2(data=data2) 131 | exp2 = cir2.expectation().sum() 132 | exp2.backward() 133 | 134 | assert torch.allclose(exp1, exp2) 135 | assert torch.allclose(data1.grad, data2.grad) 136 | -------------------------------------------------------------------------------- /tests/test_get_amplitude.py: -------------------------------------------------------------------------------- 1 | import deepquantum as dq 2 | import pytest 3 | import torch 4 | 5 | 6 | def test_get_amplitude(): 7 | n = 10 8 | data = torch.randn(4, 3 * n) 9 | bits = '0101010101' 10 | 11 | cir1 = dq.QubitCircuit(nqubit=n, mps=False) 12 | for i in range(n): 13 | cir1.h(i) 14 | cir1.rx(i, encode=True) 15 | cir1.ry(i, encode=True) 16 | cir1.rz(i, encode=True) 17 | cir1.cnot_ring() 18 | cir1(data=data) 19 | amp1 = cir1.get_amplitude(bits) 20 | 21 | cir2 = dq.QubitCircuit(nqubit=n, mps=True, chi=8) 22 | for i in range(n): 23 | cir2.h(i) 24 | cir2.rx(i, encode=True) 25 | cir2.ry(i, encode=True) 26 | cir2.rz(i, encode=True) 27 | cir2.cnot_ring() 28 | cir2(data=data) 29 | amp2 = cir2.get_amplitude(bits) 30 | assert abs(amp1 - amp2).max() < 1e-5 31 | -------------------------------------------------------------------------------- /tests/test_mapper.py: -------------------------------------------------------------------------------- 1 | import deepquantum as dq 2 | import numpy as np 3 | import pytest 4 | import torch 5 | 6 | 7 | def test_mapper(): 8 | cnot = np.array([[1,0,0,0], 9 | [0,1,0,0], 10 | [0,0,0,1], 11 | [0,0,1,0]]) 12 | nqubit = 2 13 | nmode = 6 14 | ugate = cnot 15 | aux = [0, 0] 16 | aux_pos = [4, 5] 17 | success = 1 / 3 18 | umap = dq.UnitaryMapper(nqubit=nqubit, nmode=nmode, ugate=ugate, 19 | success=success, aux=aux, aux_pos=aux_pos) 20 | basis = umap.basis 21 | Re3 = umap.solve_eqs_real(total_trials=1, trials=10, precision=1e-5) # for real solution 22 | # check the result 23 | cnot_test = Re3[0][0][0] 24 | init_state = [1,0,1,0,0,0] 25 | test_circuit = dq.QumodeCircuit(nmode=6, init_state=init_state, basis=True) 26 | test_circuit.any(cnot_test, list(range(6))) 27 | temp_cnot = torch.zeros((4, 4), dtype=torch.cdouble) 28 | for i in range(4): 29 | temp_re = test_circuit(state=basis[i], is_prob=False) 30 | for j in range(4): 31 | out_state = dq.FockState(basis[j]) 32 | temp_cnot[i][j] = temp_re[out_state] 33 | assert torch.allclose(temp_cnot, torch.tensor(cnot * success) + 0j) 34 | -------------------------------------------------------------------------------- /tests/test_mps.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | import deepquantum as dq 4 | import pytest 5 | import torch 6 | from deepquantum.qmath import slice_state_vector, get_prob_mps 7 | 8 | 9 | def test_cir_get_prob(): 10 | n = 10 11 | data = torch.randn(3 * n) 12 | num_bits = random.randint(1, n) 13 | bits_value = random.randint(0, 2**num_bits - 1) 14 | bits = bin(bits_value)[2:].zfill(num_bits) 15 | wires = random.sample(range(n), k=num_bits) 16 | wires.sort() 17 | 18 | cir1 = dq.QubitCircuit(nqubit=n, mps=False) 19 | cir1.hlayer() 20 | cir1.rxlayer(encode=True) 21 | cir1.rylayer(encode=True) 22 | cir1.rzlayer(encode=True) 23 | cir1.cnot_ring() 24 | cir1(data=data) 25 | prob1 = cir1.get_prob(bits, wires) 26 | 27 | cir2 = dq.QubitCircuit(nqubit=n, mps=True) 28 | cir2.hlayer() 29 | cir2.rxlayer(encode=True) 30 | cir2.rylayer(encode=True) 31 | cir2.rzlayer(encode=True) 32 | cir2.cnot_ring() 33 | cir2(data=data) 34 | prob2 = cir2.get_prob(bits, wires) 35 | 36 | assert torch.allclose(prob1, prob2) 37 | 38 | 39 | def test_get_prob_mps(): 40 | n = 10 41 | data = torch.randn(2 * n) 42 | num_bits = random.randint(1, n) 43 | bits_value = random.randint(0, 2**num_bits - 1) 44 | bits = bin(bits_value)[2:].zfill(num_bits) 45 | wires = random.sample(range(n), k=num_bits) 46 | wires.sort() 47 | 48 | cir = dq.QubitCircuit(n, mps=True) 49 | cir.rylayer(encode=True) 50 | cir.cnot_ring() 51 | cir.rxlayer(encode=True) 52 | mps = cir(data=data) 53 | 54 | cir2 = dq.QubitCircuit(n) 55 | cir2.rylayer(encode=True) 56 | cir2.cnot_ring() 57 | cir2.rxlayer(encode=True) 58 | sv = cir2(data=data).reshape([2] * n) 59 | 60 | offset = 0 61 | for i, b in zip(wires, bits): 62 | prob0_sv = (slice_state_vector(sv, n - offset, [i - offset], '0', False).abs() ** 2).sum() 63 | prob1_sv = (slice_state_vector(sv, n - offset, [i - offset], '1', False).abs() ** 2).sum() 64 | probs_mps = get_prob_mps(mps, i) 65 | assert torch.allclose(prob0_sv, probs_mps[0]) 66 | assert torch.allclose(prob1_sv, probs_mps[1]) 67 | sv = slice_state_vector(sv, n - offset, [i - offset], b, False) 68 | mps[i] = mps[i][:, [int(b)], :] 69 | offset += 1 70 | -------------------------------------------------------------------------------- /tests/test_photonic_batch_shape.py: -------------------------------------------------------------------------------- 1 | import deepquantum as dq 2 | import pytest 3 | import torch 4 | 5 | 6 | def test_gaussian_shape(): 7 | cir = dq.QumodeCircuit(nmode=1, init_state='vac', cutoff=3, backend='gaussian') 8 | cir.s(0, 0., encode=True) 9 | 10 | data2 = torch.tensor([[0,0], [0,1]]) 11 | state = cir() 12 | assert tuple(state[0].shape) == (1, 2, 2) and tuple(state[1].shape) == (1, 2, 1) 13 | state = cir(data=data2) 14 | assert tuple(state[0].shape) == (2, 2, 2) and tuple(state[1].shape) == (2, 2, 1) 15 | 16 | def test_gaussian_batch_shape(): 17 | batch = torch.randint(1, 10, size=[1])[0] 18 | covs = torch.stack([torch.eye(2)] * batch) 19 | means = torch.tensor([[0, 0]] * batch) 20 | cir = dq.QumodeCircuit(nmode=1, init_state=[covs, means], cutoff=3, backend='gaussian') 21 | cir.s(0, 0., encode=True) 22 | 23 | data2 = torch.tensor([[0,0]] * batch) 24 | state = cir() 25 | assert tuple(state[0].shape) == (batch, 2, 2) and tuple(state[1].shape) == (batch, 2, 1) 26 | state = cir(data=data2) 27 | assert tuple(state[0].shape) == (batch, 2, 2) and tuple(state[1].shape) == (batch, 2, 1) 28 | 29 | def test_bosonic_shape(): 30 | cir = dq.QumodeCircuit(nmode=2, init_state='vac', cutoff=3, backend='bosonic') 31 | cir.cat(0, r=1, theta=0.) 32 | cir.gkp(1, theta=0., phi=0.) 33 | cir.s(0, 0., encode=True) 34 | 35 | data2 = torch.tensor([[0,0], [0,1]]) 36 | state = cir() 37 | assert (tuple(state[0].shape) == (1, 1, 4, 4) and 38 | tuple(state[1].shape) == (1, 356, 4, 1) and 39 | tuple(state[2].shape) == (1, 356)) 40 | state = cir(data=data2) 41 | assert (tuple(state[0].shape) == (2, 1, 4, 4) and 42 | tuple(state[1].shape) == (2, 356, 4, 1) and 43 | tuple(state[2].shape) == (1, 356)) 44 | 45 | def test_bosonic_batch_shape(): 46 | batch = torch.randint(1, 10, size=[1])[0] 47 | cat = dq.CatState(r=1., theta=0., p=1) 48 | cov_in = cat.cov.expand(batch, 1, 2, 2) 49 | mean_in = cat.mean.expand(batch, 4, 2, 1) 50 | weight_in = cat.weight.expand(batch, 4) 51 | cir = dq.QumodeCircuit(nmode=1, init_state=[cov_in, mean_in, weight_in], cutoff=3, backend='bosonic') 52 | cir.s(0, 0., encode=True) 53 | 54 | data2 = torch.tensor([[0,0]] * batch) 55 | state = cir() 56 | assert (tuple(state[0].shape) == (batch, 1, 2, 2) and 57 | tuple(state[1].shape) == (batch, 4, 2, 1) and 58 | tuple(state[2].shape) == (batch, 4)) 59 | state = cir(data=data2) 60 | assert (tuple(state[0].shape) == (batch, 1, 2, 2) and 61 | tuple(state[1].shape) == (batch, 4, 2, 1) and 62 | tuple(state[2].shape) == (batch, 4)) 63 | -------------------------------------------------------------------------------- /tests/test_photonic_bosonic.py: -------------------------------------------------------------------------------- 1 | import deepquantum as dq 2 | import numpy as np 3 | import pytest 4 | import strawberryfields as sf 5 | import torch 6 | from deepquantum.photonic import xxpp_to_xpxp 7 | 8 | 9 | def test_catstate(): 10 | r = np.random.rand(1)[0] 11 | theta = 2 * np.pi * np.random.rand(1)[0] 12 | nmodes = 1 13 | prog_cat_bosonic = sf.Program(nmodes) 14 | hbar = 2 15 | with prog_cat_bosonic.context as q: 16 | sf.ops.Catstate(a=r, phi=theta, p=1) | q[0] # superposition of 4 states 17 | eng = sf.Engine("bosonic", backend_options={"hbar": hbar}) # xpxp order 18 | state = eng.run(prog_cat_bosonic).state 19 | means_sf = state.means() 20 | covs_sf = state.covs() 21 | weights_sf = state.weights() 22 | 23 | cat = dq.CatState(r=r, theta=theta, p=1) 24 | err1 = abs(cat.cov - covs_sf).sum() 25 | err2 = abs(cat.mean[0].squeeze() - means_sf).sum() 26 | err3 = abs(cat.weight - weights_sf).sum() / abs(weights_sf).sum() # relative error 27 | assert err1 + err2 + err3 < 3e-4 28 | 29 | 30 | def test_forward_cov_mean(): 31 | r = np.random.rand(1)[0] 32 | theta = 2 * np.pi * np.random.rand(1)[0] 33 | cat = dq.CatState(r=r, theta=theta, p=1) 34 | vac = dq.BosonicState(state='vac', nmode=1) 35 | cir = dq.QumodeCircuit(nmode=2, init_state=[cat, vac], backend='bosonic') 36 | angles = 2 * np.pi * np.random.rand(2) 37 | cir.s(1, r=2.) 38 | cir.bs([0,1], angles) 39 | test = cir() 40 | 41 | nmodes = 2 42 | prog_cat_bosonic = sf.Program(nmodes) 43 | hbar = 2 44 | with prog_cat_bosonic.context as q: 45 | sf.ops.Catstate(a=r, phi=theta, p=1) | q[0] # superposition of 4 states 46 | # sf.ops.Squeezed(r=1) | q[0] # catstate 不能加压缩门 47 | sf.ops.Squeezed(r=2) | q[1] 48 | sf.ops.BSgate(angles[0], angles[1]) | [q[0], q[1]] 49 | eng = sf.Engine("bosonic", backend_options={"hbar": hbar}) # xpxp order 50 | state = eng.run(prog_cat_bosonic).state 51 | means_sf = state.means() 52 | covs_sf = state.covs() 53 | weights_sf = state.weights() 54 | err1 = abs(xxpp_to_xpxp(test[0][0]) - covs_sf).sum() 55 | err2 = abs(xxpp_to_xpxp(test[1][0]).squeeze() - means_sf).sum() 56 | err3 = abs(test[2] - weights_sf).sum() / abs(weights_sf).sum() # relative error 57 | assert err1 + err2 + err3 < 3e-4 58 | 59 | 60 | def test_photon_number_mean_var(): 61 | r = np.random.rand(1)[0] 62 | theta = 2 * np.pi * np.random.rand(1)[0] 63 | nmodes = 1 64 | prog_cat_bosonic = sf.Program(nmodes) 65 | hbar = 2 66 | with prog_cat_bosonic.context as q: 67 | sf.ops.Catstate(a=r, phi=theta, p=1) | q[0] # superposition of 4 states 68 | eng = sf.Engine("bosonic", backend_options={"hbar": hbar}) # xpxp order 69 | state = eng.run(prog_cat_bosonic).state 70 | 71 | cir = dq.QumodeCircuit(nmode=1, init_state='vac', backend='bosonic') 72 | cir.cat(wires=0, r=r, theta=theta, p=1) 73 | cir.s(0, r=0) 74 | cir.to(torch.float) 75 | cir() 76 | test1 = cir.photon_number_mean_var() 77 | test2 = state.mean_photon(0) 78 | err = abs(torch.tensor(test1) - np.array(test2)).sum() 79 | assert err < 1e-4 80 | 81 | 82 | def test_wigner(): 83 | qrange = 5 84 | prange = 5 85 | npoints = 200 86 | theta = 2 * np.pi * np.random.rand(1)[0] 87 | phi = 2 * np.pi * np.random.rand(1)[0] 88 | gkp = dq.GKPState(theta=theta, phi=phi, amp_cutoff=0.01, epsilon=0.05) 89 | 90 | nmodes = 1 91 | prog_cat_bosonic = sf.Program(nmodes) 92 | with prog_cat_bosonic.context as q: 93 | sf.ops.GKP(state=[theta, phi], epsilon=0.05, ampl_cutoff=0.01) | q[0] # superposition of 4 states 94 | eng = sf.Engine("bosonic", backend_options={"hbar": 2}) # xpxp order 95 | state = eng.run(prog_cat_bosonic).state 96 | qvec = torch.linspace(-qrange, qrange, npoints) 97 | pvec = torch.linspace(-prange, prange, npoints) 98 | w = state.wigner(0, qvec, pvec) 99 | test = gkp.wigner(wire=0, qrange=qrange, prange=qrange, plot=False) 100 | err = abs(test[0].mT - w).max() 101 | assert err < 1e-5 102 | -------------------------------------------------------------------------------- /tests/test_photonic_fock.py: -------------------------------------------------------------------------------- 1 | import deepquantum as dq 2 | import pytest 3 | import torch 4 | 5 | 6 | def test_batched_fock_basis_states(): 7 | batch = 3 8 | # set nphoton = max_photon_in_one_mode + 1 9 | nphoton = 3 10 | init_state = torch.randint(nphoton, (batch, 3)) 11 | data = torch.randn(8) 12 | 13 | cir = dq.QumodeCircuit(nmode=3, init_state=init_state, basis=True) 14 | cir.ps([0], encode=True) 15 | cir.ps([1], encode=True) 16 | cir.ps([2], encode=True) 17 | cir.bs_theta([0, 1], encode=True) 18 | cir.bs_theta([1, 2], encode=True) 19 | cir.ps([0], encode=True) 20 | cir.ps([1], encode=True) 21 | cir.ps([2], encode=True) 22 | 23 | re1 = cir(data=data, state=init_state, is_prob=None) 24 | re2 = cir(data=data, state=init_state, is_prob=False) 25 | re3 = cir(data=data, state=init_state, is_prob=True) 26 | 27 | for i in range(init_state.shape[0]): 28 | res1 = cir(data=data, state=init_state[i], is_prob=None) 29 | res2 = cir(data=data, state=init_state[i], is_prob=False) 30 | res3 = cir(data=data, state=init_state[i], is_prob=True) 31 | 32 | # test is_prob=None 33 | assert torch.equal(res1, re1[i]) 34 | 35 | for key in res2.keys(): 36 | # test is_prob=False 37 | assert torch.allclose(res2[key], re2[key][i], atol=1e-6) 38 | 39 | for key in res3.keys(): 40 | # test is prob = True 41 | assert torch.allclose(res3[key], re3[key][i], atol=1e-6) 42 | 43 | 44 | def test_batched_fock_basis_states_and_data(): 45 | batch = 3 46 | # set nphoton = max_photon_in_one_mode + 1 47 | nphoton = 3 48 | init_state = torch.randint(nphoton, (batch, 3)) 49 | data = torch.randn(batch * 8).reshape(batch, 8) 50 | 51 | cir = dq.QumodeCircuit(nmode=3, init_state=init_state, basis=True) 52 | cir.ps([0], encode=True) 53 | cir.ps([1], encode=True) 54 | cir.ps([2], encode=True) 55 | cir.bs_theta([0, 1], encode=True) 56 | cir.bs_theta([1, 2], encode=True) 57 | cir.ps([0], encode=True) 58 | cir.ps([1], encode=True) 59 | cir.ps([2], encode=True) 60 | 61 | re1 = cir(data=data, state=init_state, is_prob=None) 62 | re2 = cir(data=data, state=init_state, is_prob=False) 63 | re3 = cir(data=data, state=init_state, is_prob=True) 64 | 65 | for i in range(init_state.shape[0]): 66 | res1 = cir(data=data[i], state=init_state[i], is_prob=None) 67 | res2 = cir(data=data[i], state=init_state[i], is_prob=False) 68 | res3 = cir(data=data[i], state=init_state[i], is_prob=True) 69 | 70 | # test is_prob=None 71 | assert torch.allclose(res1, re1[i], atol=1e-6) 72 | 73 | for key in res2.keys(): 74 | # test is_prob=False 75 | assert torch.allclose(res2[key], re2[key][i], atol=1e-5) 76 | 77 | for key in res3.keys(): 78 | # test is_prob=True 79 | assert torch.allclose(res3[key], re3[key][i], atol=1e-6) 80 | 81 | 82 | def test_loss_batched_fock_basis_states(): 83 | batch = 3 84 | # set nphoton = max_photon_in_one_mode + 1 85 | nphoton = 3 86 | init_state = torch.randint(nphoton, (batch, 3)) 87 | data = torch.randn(8) 88 | transmittance = torch.rand(6) 89 | 90 | cir = dq.QumodeCircuit(nmode=3, init_state=init_state, basis=True) 91 | cir.loss([0], transmittance[0]) 92 | cir.ps([0], encode=True) 93 | cir.ps([1], encode=True) 94 | cir.ps([2], encode=True) 95 | cir.bs_theta([0, 1], encode=True) 96 | cir.loss([0], transmittance[1]) 97 | cir.loss([1], transmittance[2]) 98 | cir.bs_theta([1, 2], encode=True) 99 | cir.ps([0], encode=True) 100 | cir.ps([1], encode=True) 101 | cir.ps([2], encode=True) 102 | cir.loss(0, transmittance[3]) 103 | cir.loss(1, transmittance[4]) 104 | cir.loss(2, transmittance[5]) 105 | 106 | re1 = cir(data=data, state=init_state, is_prob=None) 107 | re2 = cir(data=data, state=init_state, is_prob=True) 108 | 109 | for i in range(init_state.shape[0]): 110 | res1 = cir(data=data, state=init_state[i], is_prob=None) 111 | res2 = cir(data=data, state=init_state[i], is_prob=True) 112 | 113 | # test is_prob=None 114 | assert torch.equal(res1, re1[i]) 115 | 116 | for key in res2.keys(): 117 | # test is prob = True 118 | assert torch.allclose(res2[key], re2[key][i], atol=1e-6) 119 | -------------------------------------------------------------------------------- /tests/test_photonic_gate.py: -------------------------------------------------------------------------------- 1 | import deepquantum as dq 2 | import pytest 3 | import torch 4 | 5 | 6 | def test_2_mode_squeezing_gate(): 7 | r = torch.rand(1)[0] 8 | theta = torch.rand(1)[0] * 2 * torch.pi 9 | cutoff = 5 10 | cir1 = dq.QumodeCircuit(nmode=2, init_state='vac', cutoff=cutoff, backend='gaussian') 11 | cir1.s2([0,1], r, theta) 12 | cov1, mean1 = cir1() 13 | sym1 = cir1.get_symplectic() 14 | 15 | cir2 = dq.QumodeCircuit(nmode=2, init_state='vac', cutoff=cutoff, backend='gaussian') 16 | cir2.bs([0,1], [torch.pi / 4, 0]) 17 | cir2.s(0, r, theta) 18 | cir2.s(1, -r, theta) 19 | cir2.bs([0,1], [-torch.pi / 4, 0]) 20 | cov2, mean2 = cir2() 21 | sym2 = cir2.get_symplectic() 22 | assert torch.allclose(cov1, cov2, atol=1e-6) 23 | assert torch.allclose(mean1, mean2, atol=1e-6) 24 | assert torch.allclose(sym1, sym2, atol=1e-6) 25 | 26 | 27 | def test_squeezing_gate_numerical_stability(): 28 | cutoff = 128 29 | r = 1 30 | cir1 = dq.QumodeCircuit(nmode=2, init_state='vac', cutoff=cutoff, backend='fock', basis=False) 31 | cir1.s(0, r=r) 32 | cir1.s(0, r=r) 33 | cir1.to(torch.double) 34 | state1 = cir1() 35 | 36 | cir2 = dq.QumodeCircuit(nmode=2, init_state='vac', cutoff=cutoff, backend='fock', basis=False) 37 | cir2.s(0, r=2 * r) 38 | cir2.to(torch.double) 39 | state2 = cir2() 40 | assert torch.allclose(state1, state2) 41 | 42 | 43 | def test_2_mode_squeezing_gate_numerical_stability(): 44 | cutoff = 64 45 | r = 1 46 | cir1 = dq.QumodeCircuit(nmode=2, init_state='vac', cutoff=cutoff, backend='fock', basis=False) 47 | cir1.s2([0,1], r=r) 48 | cir1.s2([0,1], r=r) 49 | cir1.to(torch.double) 50 | state1 = cir1() 51 | 52 | cir2 = dq.QumodeCircuit(nmode=2, init_state='vac', cutoff=cutoff, backend='fock', basis=False) 53 | cir2.s2([0,1], r=2 * r) 54 | cir2.to(torch.double) 55 | state2 = cir2() 56 | assert torch.allclose(state1, state2) 57 | -------------------------------------------------------------------------------- /tests/test_photonic_qmath.py: -------------------------------------------------------------------------------- 1 | import networkx as nx 2 | import pytest 3 | import torch 4 | from deepquantum.photonic import Squeezing2 5 | from deepquantum.photonic import xxpp_to_xpxp, xpxp_to_xxpp, quadrature_to_ladder, ladder_to_quadrature, takagi 6 | 7 | 8 | def test_quadrature_ladder_transform(): 9 | batch = 2 10 | nmode = 4 11 | vector = torch.randn(batch, 2 * nmode, 1) 12 | matrix = torch.randn(batch, 2 * nmode, 2 * nmode) 13 | vector2 = ladder_to_quadrature(quadrature_to_ladder(vector)) 14 | matrix2 = ladder_to_quadrature(quadrature_to_ladder(matrix)) 15 | assert torch.allclose(vector, vector2, atol=1e-5) 16 | assert torch.allclose(matrix, matrix2, atol=1e-5) 17 | 18 | 19 | def test_gaussian_ordering(): 20 | batch = 2 21 | nmode = 4 22 | vector = torch.randn(batch, 2 * nmode, 1) 23 | matrix = torch.randn(batch, 2 * nmode, 2 * nmode) 24 | vector2 = xpxp_to_xxpp(xxpp_to_xpxp(vector)) 25 | matrix2 = xpxp_to_xxpp(xxpp_to_xpxp(matrix)) 26 | assert torch.allclose(vector, vector2) 27 | assert torch.allclose(matrix, matrix2) 28 | 29 | 30 | def test_takagi(): 31 | size = 8 32 | for _ in range(10): 33 | graph = nx.erdos_renyi_graph(size, 0.5) 34 | a = torch.tensor(nx.to_numpy_array(graph), dtype=torch.float) 35 | u, diag = takagi(a) 36 | s_diag = torch.diag(diag).to(u.dtype) 37 | assert torch.allclose(u @ u.mH, torch.eye(size) + 0j, rtol=1e-5, atol=1e-5) 38 | assert torch.allclose(u @ s_diag @ u.mT, a + 0j, rtol=1e-5, atol=1e-5) 39 | 40 | 41 | def test_quadrature_ladder_transform(): 42 | gate = Squeezing2() 43 | mat_ladder = gate.update_matrix() 44 | mat_xxpp = gate.update_transform_xp()[0] 45 | assert torch.allclose(ladder_to_quadrature(mat_ladder, True), mat_xxpp) 46 | assert torch.allclose(quadrature_to_ladder(mat_xxpp, True), mat_ladder) 47 | -------------------------------------------------------------------------------- /tests/test_photonic_random_circuit.py: -------------------------------------------------------------------------------- 1 | import deepquantum as dq 2 | import numpy as np 3 | import pytest 4 | 5 | 6 | def test_random_circuit_two_approaches(): 7 | """Compare two approaches for the photonic quantum circuit.""" 8 | nmode = np.random.randint(2, 7) 9 | ndevice = np.random.randint(10, 100) 10 | ini_state_pre = np.random.randn(nmode) 11 | ini_state_pre = ini_state_pre - ini_state_pre.min() 12 | ini_state_pre = np.round(ini_state_pre / ini_state_pre.sum() * nmode) 13 | ini_state_pre[ini_state_pre < 0] = 0 14 | if ini_state_pre.sum() != nmode: 15 | ini_state_pre[ini_state_pre.argmax()] += nmode - ini_state_pre.sum() 16 | ini_state_1 = [int(i) for i in ini_state_pre] 17 | ini_state_2 = [(1, ini_state_1)] 18 | 19 | dq_gate_1 = dq.QumodeCircuit(nmode=nmode, init_state=ini_state_1, basis=True) 20 | dq_gate_2 = dq.QumodeCircuit(nmode=nmode, init_state=ini_state_2, basis=False) 21 | 22 | for _ in range(ndevice): # take the random circuit 23 | j = np.random.uniform(-2, 5) 24 | if j > 4: 25 | temp_1 = int(np.random.choice(np.arange(nmode))) 26 | angle_1 = np.random.uniform(0, 2 * np.pi) 27 | dq_gate_1.ps([temp_1], angle_1) 28 | dq_gate_2.ps([temp_1], angle_1) 29 | if 3 < j < 4: 30 | k = int(np.random.choice(np.arange(nmode - 1))) 31 | angle_1 = np.random.uniform(0, 2 * np.pi) 32 | dq_gate_1.bs_theta([k, k+1], angle_1) 33 | dq_gate_2.bs_theta([k, k+1], angle_1) 34 | if 2 < j < 3: 35 | k = int(np.random.choice(np.arange(nmode - 1))) 36 | angle_1 = np.random.uniform(0, 2 * np.pi) 37 | dq_gate_1.bs_rx([k, k+1], angle_1) 38 | dq_gate_2.bs_rx([k, k+1], angle_1) 39 | if 1 < j < 2: 40 | k = int(np.random.choice(np.arange(nmode - 1))) 41 | angle_1 = np.random.uniform(0, 2 * np.pi) 42 | dq_gate_1.bs_ry([k, k+1], angle_1) 43 | dq_gate_2.bs_ry([k, k+1], angle_1) 44 | if 0 < j < 1: 45 | k = int(np.random.choice(np.arange(nmode - 1))) 46 | angle_1 = np.random.uniform(0, 2 * np.pi) 47 | dq_gate_1.bs_h([k, k+1], angle_1) 48 | dq_gate_2.bs_h([k, k+1], angle_1) 49 | if j < 0: 50 | k = int(np.random.choice(np.arange(nmode - 1))) 51 | angle_1 = np.random.uniform(0, 2 * np.pi, 2) 52 | dq_gate_1.mzi([k, k+1], angle_1) 53 | dq_gate_2.mzi([k, k+1], angle_1) 54 | re1 = dq_gate_1(is_prob=False) 55 | re2 = dq_gate_2() 56 | max_error = -1.0 57 | for key, value in re1.items(): 58 | temp = key.state.tolist() 59 | tmp_error = abs(re2[0][tuple(temp)] - value) 60 | if tmp_error > max_error: 61 | max_error = tmp_error 62 | assert max_error < 1e-4 63 | -------------------------------------------------------------------------------- /tests/test_with_perceval.py: -------------------------------------------------------------------------------- 1 | import deepquantum as dq 2 | import numpy as np 3 | import perceval as pcvl 4 | import perceval.components as comp 5 | import pytest 6 | import torch 7 | from perceval.components import BS 8 | 9 | 10 | def test_random_circuit(): 11 | """Compare with Perceval.""" 12 | max_mode = 7 13 | max_device = 100 14 | nmode = np.random.randint(2, max_mode) 15 | ndevice = np.random.randint(10, max_device) 16 | ini_state_pre = np.random.randn(nmode) 17 | ini_state_pre = ini_state_pre - ini_state_pre.min() 18 | ini_state_pre = np.round(ini_state_pre / ini_state_pre.sum() * nmode) 19 | ini_state_pre[ini_state_pre < 0] = 0 20 | if ini_state_pre.sum() != nmode: 21 | ini_state_pre[ini_state_pre.argmax()] += nmode - ini_state_pre.sum() 22 | ini_state = [int(i) for i in ini_state_pre] 23 | assert np.sum(ini_state_pre) == nmode 24 | test_gate = pcvl.Circuit(nmode, name='test1') 25 | dq_gate = dq.QumodeCircuit(nmode=nmode, init_state=ini_state, name='test', 26 | cutoff=sum(ini_state)+1, basis=True) 27 | encode = True 28 | for _ in range(ndevice): # take the random circuit 29 | j = np.random.uniform(-1, 5) 30 | if 4 < j < 5: # add H 31 | k = int(np.random.choice(np.arange(nmode - 1))) 32 | angle_1 = np.random.uniform(0, 2 * np.pi) 33 | test_gate.add([k, k+1], BS.H(angle_1)) 34 | dq_gate.bs_h([k, k+1], angle_1) 35 | if 2 < j < 3: # add Rx 36 | k = int(np.random.choice(np.arange(nmode - 1))) 37 | angle_1 = np.random.uniform(0, 2 * np.pi) 38 | test_gate.add([k, k+1], BS.Rx(angle_1)) 39 | dq_gate.bs_rx([k, k+1], angle_1) 40 | if 1 < j < 2: # add Ry 41 | k = int(np.random.choice(np.arange(nmode - 1))) 42 | angle_1 = np.random.uniform(0, 2 * np.pi) 43 | test_gate.add([k, k+1], BS.Ry(angle_1)) 44 | dq_gate.bs_ry([k, k+1], angle_1) 45 | if 0 < j < 1: 46 | temp_1 = int(np.random.choice(np.arange(nmode))) 47 | angle_1 = np.random.uniform(0, 2 * np.pi) 48 | test_gate.add((temp_1), comp.PS(angle_1)) 49 | dq_gate.ps([temp_1], angle_1, encode=encode) 50 | else: 51 | k = int(np.random.choice(np.arange(nmode - 1))) 52 | angle_2 = np.random.uniform(0, 2 * np.pi) 53 | test_gate.add((k, k+1), BS.Rx(angle_2)) 54 | dq_gate.bs_theta([k, k+1], angle_2 / 2, encode=encode) 55 | backend = pcvl.BackendFactory().get_backend('Naive') 56 | backend.set_circuit(test_gate) 57 | input_state = pcvl.BasicState(ini_state) 58 | backend.set_input_state(input_state) 59 | re1 = backend.evolve() 60 | re2 = dq_gate(is_prob=False) 61 | # calculating the difference for two simu approach 62 | max_error = -1.0 63 | for key in re1.keys(): 64 | key2 = list(key) 65 | key3 = dq.FockState(key2) 66 | tmp_error = abs(re2[key3] - re1[key]) 67 | # tmp_error = abs(re2[tuple(key2)] - re1[(key)]) 68 | if tmp_error > max_error: 69 | max_error = tmp_error 70 | assert max_error < 1e-4 71 | 72 | 73 | def test_loss_fock_basis_True(): 74 | n = 3 75 | angles = np.random.rand(6) * np.pi 76 | transmittance = np.random.rand(6) 77 | 78 | cir = pcvl.Processor("SLOS",n) 79 | cir.add(0, pcvl.LC(loss=1 - transmittance[0])) 80 | cir.add(0, pcvl.PS(phi=angles[0])) 81 | cir.add(1, pcvl.PS(phi=angles[1])) 82 | cir.add((0,1), pcvl.BS(theta=angles[2])) 83 | cir.add(0, pcvl.LC(loss=1 - transmittance[1])) 84 | cir.add(2, pcvl.LC(loss=1 - transmittance[2])) 85 | cir.add((1,2), pcvl.BS(theta=angles[3])) 86 | cir.add(0, pcvl.LC(loss=1 - transmittance[3])) 87 | cir.add(1, pcvl.LC(loss=1 - transmittance[4])) 88 | cir.add(2, pcvl.LC(loss=1 - transmittance[5])) 89 | 90 | cir.with_input(pcvl.BasicState([1, 1, 1])) 91 | cir.min_detected_photons_filter(0) 92 | 93 | imperfect_sampler = pcvl.algorithm.Sampler(cir) 94 | output = imperfect_sampler.probs()["results"] 95 | 96 | nmode = n 97 | cir = dq.QumodeCircuit(nmode=nmode, init_state=[1,1,1], backend='fock', basis=True) 98 | cir.loss_t(0, transmittance[0]) 99 | cir.ps(0, angles[0]) 100 | cir.ps(1, angles[1]) 101 | cir.bs_rx([0,1], [angles[2]]) 102 | cir.loss_t(0, transmittance[1]) 103 | cir.loss_t(2, transmittance[2]) 104 | cir.bs_rx([1,2], [angles[3]]) 105 | cir.loss_t(0, transmittance[3]) 106 | cir.loss_t(1, transmittance[4]) 107 | cir.loss_t(2, transmittance[5]) 108 | cir.to(torch.float64) 109 | state = cir(is_prob=True) 110 | for key in state.keys(): 111 | dq_prob = state[key] 112 | fock_lst = key.state.tolist() 113 | pcvl_prob = output[pcvl.BasicState(fock_lst)] 114 | err = abs(dq_prob - pcvl_prob) 115 | assert err < 1e-4,f'key={key},dq_prob={dq_prob},pcvl_prob={pcvl_prob}' 116 | -------------------------------------------------------------------------------- /tests/test_with_xanadu.py: -------------------------------------------------------------------------------- 1 | import deepquantum as dq 2 | import numpy as np 3 | import pytest 4 | import strawberryfields as sf 5 | import thewalrus 6 | import torch 7 | from deepquantum.photonic import quadrature_to_ladder, hafnian, torontonian 8 | from strawberryfields.ops import Sgate, BSgate, Rgate, MeasureHomodyne, Dgate, Fock 9 | 10 | 11 | def test_hafnian(): 12 | n = 12 13 | temp = np.random.rand(n, n) 14 | mat = temp + temp.transpose() 15 | haf1 = thewalrus.hafnian(mat, loop=False) 16 | mat = torch.tensor(mat) 17 | haf2 = hafnian(mat, loop=False) 18 | assert abs(haf1 - haf2) < 1e-6 19 | 20 | 21 | def test_hafnian_loop(): 22 | n = 12 23 | temp = np.random.rand(n, n) 24 | mat = temp + temp.transpose() 25 | haf1 = thewalrus.hafnian(mat, loop=True) 26 | mat = torch.tensor(mat) 27 | haf2 = hafnian(mat, loop=True) 28 | assert abs(haf1 - haf2) < 1e-6 29 | 30 | 31 | def test_torontonian(): 32 | nmode = 15 33 | cir = dq.QumodeCircuit(nmode=nmode, init_state='vac', cutoff=5, backend='gaussian') 34 | for i in range(nmode): 35 | cir.s(wires=i) 36 | cir.d(wires=i) 37 | for i in range(nmode - 1): 38 | cir.bs(wires=[i,i+1]) 39 | cir.to(torch.double) 40 | 41 | covs, means = cir() 42 | cov_ladder = quadrature_to_ladder(covs[0]) 43 | mean_ladder = quadrature_to_ladder(means[0]) 44 | q = cov_ladder + torch.eye(2 * nmode) / 2 45 | o_mat = torch.eye(2 * nmode) - torch.inverse(q) 46 | tor1 = torontonian(o_mat) 47 | tor2 = thewalrus.tor(o_mat.detach().numpy()) 48 | assert abs(tor1 - tor2) < 1e-6 49 | 50 | 51 | def test_torontonian_loop(): 52 | nmode = 10 53 | cir = dq.QumodeCircuit(nmode=nmode, init_state='vac', cutoff=5, backend='gaussian') 54 | for i in range(nmode): 55 | cir.s(wires=i) 56 | cir.d(wires=i) 57 | for i in range(nmode - 1): 58 | cir.bs(wires=[i,i+1]) 59 | cir.to(torch.double) 60 | 61 | covs, means = cir() 62 | cov_ladder = quadrature_to_ladder(covs[0]) 63 | mean_ladder = quadrature_to_ladder(means[0]) 64 | q = cov_ladder + torch.eye(2 * nmode) / 2 65 | gamma = mean_ladder.conj().mT @ torch.inverse(q) 66 | gamma = gamma.squeeze() 67 | o_mat = torch.eye(2 * nmode) - torch.inverse(q) 68 | tor1 = torontonian(o_mat, gamma) 69 | tor2 = thewalrus.ltor(o_mat.detach().numpy(), gamma.detach().numpy()) 70 | assert abs(tor1 - tor2) < 1e-6 71 | 72 | 73 | def test_gaussian_prob_random_circuit(): 74 | para_r = np.random.uniform(0, 1, [1, 4])[0] 75 | para_theta = np.random.uniform(0, 2 * np.pi, [1, 6])[0] 76 | 77 | cir = dq.QumodeCircuit(nmode=2, init_state='vac', cutoff=5, backend='gaussian') 78 | cir.s(0, para_r[0], para_theta[0]) 79 | cir.s(1, para_r[1], para_theta[1]) 80 | cir.d(0, para_r[2], para_theta[2]) 81 | cir.d(1, para_r[3], para_theta[3]) 82 | cir.bs([0,1], [para_theta[4], para_theta[5]]) 83 | 84 | cir.to(torch.double) 85 | cov, mean = cir(is_prob=False) 86 | state = cir(is_prob=True) 87 | 88 | test_prob = thewalrus.quantum.probabilities(mu=mean[0].squeeze().numpy(), cov=cov[0].numpy(), cutoff=5) 89 | error = [] 90 | for i in state.keys(): 91 | idx = i.state.tolist() 92 | error.append(abs(test_prob[tuple(idx)] - state[i].item())) 93 | assert sum(error) < 1e-10 94 | 95 | 96 | def test_measure_homodyne(): 97 | n = 3 98 | r1 = np.random.rand(1) 99 | r2 = np.random.rand(1) 100 | r3 = np.random.rand(1) 101 | bs1 = np.random.rand(2) 102 | bs2 = np.random.rand(2) 103 | phi = np.random.rand(2) 104 | 105 | prog = sf.Program(n) 106 | with prog.context as q: 107 | Sgate(r1) | q[0] 108 | Dgate(r2) | q[1] 109 | Sgate(r3) | q[1] 110 | BSgate(*bs1) | (q[0], q[1]) 111 | BSgate(*bs2) | (q[1], q[2]) 112 | MeasureHomodyne(phi[0]) | q[0] 113 | MeasureHomodyne(phi[1]) | q[1] 114 | eng = sf.Engine('gaussian') 115 | result = eng.run(prog) 116 | 117 | cir = dq.QumodeCircuit(nmode=n, init_state='vac', cutoff=3, backend='gaussian') 118 | cir.s(0, r=r1) 119 | cir.d(1, r=r2) 120 | cir.s(1, r=r3) 121 | cir.bs([0,1], inputs=bs1) 122 | cir.bs([1,2], inputs=bs2) 123 | cir.homodyne(wires=0, phi=phi[0]) 124 | cir.homodyne(wires=1, phi=phi[1]) 125 | cir.to(torch.double) 126 | cir() 127 | sample = cir.measure_homodyne() 128 | state = cir.state_measured 129 | err = abs(state[0] - result.state.cov()).max() # compare the covariance matrix after the measurement 130 | assert err < 1e-6 131 | 132 | 133 | def test_non_adjacent_bs_fock(): 134 | n = 3 135 | angles = np.random.rand(6) 136 | prog = sf.Program(n) 137 | with prog.context as q: 138 | Fock(1) | q[0] 139 | Fock(1) | q[1] 140 | Fock(1) | q[2] 141 | Rgate(angles[0]) | q[0] 142 | Rgate(angles[1]) | q[1] 143 | BSgate(angles[2], angles[3]) | (q[0], q[2]) 144 | BSgate(angles[4], angles[5]) | (q[1], q[2]) 145 | eng = sf.Engine('fock', backend_options={'cutoff_dim': 4}) 146 | result = eng.run(prog) 147 | 148 | nmode = n 149 | cir = dq.QumodeCircuit(nmode=nmode, init_state=[1,1,1], cutoff=4, backend='fock', basis=True) 150 | cir.ps(0, angles[0]) 151 | cir.ps(1, angles[1]) 152 | cir.bs([0,2], [angles[2], angles[3]]) 153 | cir.bs([1,2], [angles[4], angles[5]]) 154 | state = cir(is_prob=True) 155 | err = 0 156 | for key in state.keys(): 157 | dq_prob = state[key] 158 | fock_st = key.state.tolist() 159 | sf_prob = result.state.fock_prob(fock_st) 160 | err = err + abs(dq_prob - sf_prob) 161 | assert err < 1e-6 162 | 163 | 164 | def test_non_adjacent_bs_gaussian(): 165 | n = 4 166 | angles = np.random.rand(12) 167 | prog = sf.Program(n) 168 | with prog.context as q: 169 | Sgate(angles[0]) | q[0] 170 | Sgate(angles[1]) | q[1] 171 | Sgate(angles[2]) | q[2] 172 | Sgate(angles[3]) | q[3] 173 | Dgate(angles[4]) | q[0] 174 | Dgate(angles[5]) | q[1] 175 | Dgate(angles[6]) | q[2] 176 | Dgate(angles[7]) | q[3] 177 | BSgate(angles[8], angles[9]) | (q[0], q[2]) 178 | BSgate(angles[10], angles[11]) | (q[1], q[3]) 179 | eng = sf.Engine('gaussian') 180 | result = eng.run(prog) 181 | cov_sf = result.state.cov() 182 | mean_sf = result.state.means() 183 | 184 | nmode = n 185 | cir = dq.QumodeCircuit(nmode=nmode, init_state='vac', cutoff=3, backend='gaussian') 186 | cir.s(0, r=angles[0]) 187 | cir.s(1, r=angles[1]) 188 | cir.s(2, r=angles[2]) 189 | cir.s(3, r=angles[3]) 190 | cir.d(0, r=angles[4]) 191 | cir.d(1, r=angles[5]) 192 | cir.d(2, r=angles[6]) 193 | cir.d(3, r=angles[7]) 194 | 195 | cir.bs([0,2], [angles[8], angles[9]]) 196 | cir.bs([1,3], [angles[10], angles[11]]) 197 | 198 | state = cir() 199 | err = abs(state[0].squeeze() - cov_sf).sum() + abs(state[1].squeeze() - mean_sf).sum() 200 | assert err < 1e-5 201 | -------------------------------------------------------------------------------- /tests/test_with_xanadu_gate.py: -------------------------------------------------------------------------------- 1 | import deepquantum as dq 2 | import numpy as np 3 | import strawberryfields as sf 4 | import torch 5 | from strawberryfields.ops import Pgate, CXgate, CZgate, Vgate, Kgate, CKgate 6 | 7 | 8 | def test_quadratic_phase_gate(): 9 | nmode = 1 10 | cutoff = 10 11 | params = np.random.rand(1) 12 | 13 | prog = sf.Program(nmode) 14 | with prog.context as q: 15 | Pgate(params[0]) | q[0] 16 | eng = sf.Engine('fock', backend_options={'cutoff_dim': cutoff}) 17 | result = eng.run(prog) 18 | 19 | cir = dq.QumodeCircuit(nmode=nmode, init_state='vac', cutoff=cutoff, backend='fock', basis=False) 20 | cir.qp(0, params[0]) 21 | cir.to(torch.double) 22 | state = cir() 23 | 24 | assert np.allclose(result.state.data, state.numpy()) 25 | 26 | 27 | def test_cx_gate(): 28 | nmode = 2 29 | cutoff = 10 30 | params = np.random.rand(1) 31 | 32 | prog = sf.Program(nmode) 33 | with prog.context as q: 34 | CXgate(params[0]) | (q[0], q[1]) 35 | eng = sf.Engine('fock', backend_options={'cutoff_dim': cutoff}) 36 | result = eng.run(prog) 37 | 38 | cir = dq.QumodeCircuit(nmode=nmode, init_state='vac', cutoff=cutoff, backend='fock', basis=False) 39 | cir.cx([0,1], params[0]) 40 | cir.to(torch.double) 41 | state = cir() 42 | 43 | assert np.allclose(result.state.data, state.numpy()) 44 | 45 | 46 | def test_cz_gate(): 47 | nmode = 2 48 | cutoff = 10 49 | params = np.random.rand(1) 50 | 51 | prog = sf.Program(nmode) 52 | with prog.context as q: 53 | CZgate(params[0]) | (q[0], q[1]) 54 | eng = sf.Engine('fock', backend_options={'cutoff_dim': cutoff}) 55 | result = eng.run(prog) 56 | 57 | cir = dq.QumodeCircuit(nmode=nmode, init_state='vac', cutoff=cutoff, backend='fock', basis=False) 58 | cir.cz([0,1], params[0]) 59 | cir.to(torch.double) 60 | state = cir() 61 | 62 | assert np.allclose(result.state.data, state.numpy()) 63 | 64 | 65 | def test_cubic_phase_gate(): 66 | nmode = 1 67 | cutoff = 10 68 | params = np.random.rand(1) 69 | 70 | prog = sf.Program(nmode) 71 | with prog.context as q: 72 | Vgate(params[0]) | q[0] 73 | eng = sf.Engine('fock', backend_options={'cutoff_dim': cutoff}) 74 | result = eng.run(prog) 75 | 76 | cir = dq.QumodeCircuit(nmode=nmode, init_state='vac', cutoff=cutoff, backend='fock', basis=False) 77 | cir.cp(0, params[0]) 78 | cir.to(torch.double) 79 | state = cir() 80 | 81 | assert np.allclose(result.state.data, state.numpy()) 82 | 83 | 84 | def test_kerr_gate(): 85 | nmode = 1 86 | cutoff = 10 87 | params = np.random.rand(1) 88 | 89 | prog = sf.Program(nmode) 90 | with prog.context as q: 91 | Kgate(params[0]) | q[0] 92 | eng = sf.Engine('fock', backend_options={'cutoff_dim': cutoff}) 93 | result = eng.run(prog) 94 | 95 | cir = dq.QumodeCircuit(nmode=nmode, init_state='vac', cutoff=cutoff, backend='fock', basis=False) 96 | cir.k(0, params[0]) 97 | cir.to(torch.double) 98 | state = cir() 99 | 100 | assert np.allclose(result.state.data, state.numpy()) 101 | 102 | 103 | def test_cross_kerr_gate(): 104 | nmode = 2 105 | cutoff = 10 106 | params = np.random.rand(1) 107 | 108 | prog = sf.Program(nmode) 109 | with prog.context as q: 110 | CKgate(params[0]) | (q[0], q[1]) 111 | eng = sf.Engine('fock', backend_options={'cutoff_dim': cutoff}) 112 | result = eng.run(prog) 113 | 114 | cir = dq.QumodeCircuit(nmode=nmode, init_state='vac', cutoff=cutoff, backend='fock', basis=False) 115 | cir.ck([0,1], params[0]) 116 | cir.to(torch.double) 117 | state = cir() 118 | 119 | assert np.allclose(result.state.data, state.numpy()) 120 | -------------------------------------------------------------------------------- /tests/test_with_xanadu_loss.py: -------------------------------------------------------------------------------- 1 | import itertools 2 | 3 | import deepquantum as dq 4 | import numpy as np 5 | import strawberryfields as sf 6 | import torch 7 | from strawberryfields.ops import Fock, Rgate, BSgate, LossChannel 8 | 9 | 10 | def test_loss_fock_basis_True(): 11 | n = 3 12 | angles = np.random.rand(6) * np.pi 13 | transmittance = np.random.rand(6) 14 | prog = sf.Program(n) 15 | with prog.context as q: 16 | Fock(1) | q[0] 17 | Fock(1) | q[1] 18 | Fock(1) | q[2] 19 | LossChannel(transmittance[0]) | q[0] 20 | Rgate(angles[0]) | q[0] 21 | Rgate(angles[1]) | q[1] 22 | BSgate(angles[2], angles[3]) | (q[0], q[2]) 23 | LossChannel(transmittance[1]) | q[0] 24 | LossChannel(transmittance[2]) | q[2] 25 | BSgate(angles[4], angles[5]) | (q[1], q[2]) 26 | LossChannel(transmittance[3]) | q[0] 27 | LossChannel(transmittance[4]) | q[1] 28 | LossChannel(transmittance[5]) | q[2] 29 | eng = sf.Engine('fock', backend_options={'cutoff_dim': 4}) 30 | result = eng.run(prog) 31 | 32 | nmode = n 33 | cir = dq.QumodeCircuit(nmode=nmode, init_state=[1,1,1], cutoff=4, backend='fock', basis=True) 34 | cir.loss_t(0, transmittance[0]) 35 | cir.ps(0, angles[0]) 36 | cir.ps(1, angles[1]) 37 | cir.bs([0,2], [angles[2], angles[3]]) 38 | cir.loss_t(0, transmittance[1]) 39 | cir.loss_t(2, transmittance[2]) 40 | cir.bs([1,2], [angles[4], angles[5]]) 41 | cir.loss_t(0, transmittance[3]) 42 | cir.loss_t(1, transmittance[4]) 43 | cir.loss_t(2, transmittance[5]) 44 | # cir.to(torch.float64) 45 | state = cir(is_prob=True) 46 | err = 0 47 | for key in state.keys(): 48 | dq_prob = state[key] 49 | fock_st = key.state.tolist() 50 | sf_prob = result.state.fock_prob(fock_st) 51 | err += abs(dq_prob - sf_prob) 52 | assert err < 1e-6 53 | 54 | 55 | def test_loss_fock_basis_False(): 56 | n = 3 57 | angles = np.random.rand(6) * np.pi 58 | transmittance = np.random.rand(6) 59 | prog = sf.Program(n) 60 | with prog.context as q: 61 | Fock(1) | q[0] 62 | Fock(1) | q[1] 63 | Fock(1) | q[2] 64 | LossChannel(transmittance[0]) | q[0] 65 | Rgate(angles[0]) | q[0] 66 | Rgate(angles[1]) | q[1] 67 | BSgate(angles[2], angles[3]) | (q[0], q[2]) 68 | LossChannel(transmittance[1]) | q[0] 69 | LossChannel(transmittance[2]) | q[2] 70 | BSgate(angles[4], angles[5]) | (q[1], q[2]) 71 | LossChannel(transmittance[3]) | q[0] 72 | LossChannel(transmittance[4]) | q[1] 73 | LossChannel(transmittance[5]) | q[2] 74 | eng = sf.Engine('fock', backend_options={'cutoff_dim': 4}) 75 | result = eng.run(prog) 76 | 77 | nmode = n 78 | cir = dq.QumodeCircuit(nmode=nmode, init_state=[(1, [1,1,1])], cutoff=4, backend='fock', basis=False, den_mat=True) 79 | cir.loss_t(0, transmittance[0]) 80 | cir.ps(0, angles[0]) 81 | cir.ps(1, angles[1]) 82 | cir.bs([0,2], [angles[2], angles[3]]) 83 | cir.loss_t(0, transmittance[1]) 84 | cir.loss_t(2, transmittance[2]) 85 | cir.bs([1,2], [angles[4], angles[5]]) 86 | cir.loss_t(0, transmittance[3]) 87 | cir.loss_t(1, transmittance[4]) 88 | cir.loss_t(2, transmittance[5]) 89 | cir.to(torch.float64) 90 | state = cir(is_prob=True) 91 | err = 0 92 | for key in itertools.product(range(4), repeat=3): 93 | dq_prob = state[0][key] 94 | sf_prob = result.state.fock_prob(key) 95 | err += abs(dq_prob - sf_prob) 96 | assert err < 1e-6 97 | 98 | 99 | def test_loss_gaussian(): 100 | n = 3 101 | angles = np.random.rand(6) * np.pi 102 | transmittance = np.random.rand(6) 103 | prog = sf.Program(n) 104 | with prog.context as q: 105 | LossChannel(transmittance[0]) | q[0] 106 | Rgate(angles[0]) | q[0] 107 | Rgate(angles[1]) | q[1] 108 | BSgate(angles[2], angles[3]) | (q[0], q[1]) 109 | LossChannel(transmittance[1]) | q[0] 110 | LossChannel(transmittance[2]) | q[2] 111 | BSgate(angles[4], angles[5]) | (q[1], q[2]) 112 | LossChannel(transmittance[3]) | q[0] 113 | LossChannel(transmittance[4]) | q[1] 114 | LossChannel(transmittance[5]) | q[2] 115 | eng = sf.Engine('gaussian') 116 | result = eng.run(prog) 117 | sf_cov = result.state.cov() 118 | sf_mean = result.state.means() 119 | 120 | nmode = n 121 | cir = dq.QumodeCircuit(nmode=nmode, init_state='vac', cutoff=4, backend='gaussian') 122 | cir.loss_t(0, transmittance[0]) 123 | cir.ps(0, angles[0]) 124 | cir.ps(1, angles[1]) 125 | cir.bs([0,1], [angles[2], angles[3]]) # only support adjacent wires for gaussian loss channel 126 | cir.loss_t(0, transmittance[1]) 127 | cir.loss_t(2, transmittance[2]) 128 | cir.bs([1,2], [angles[4], angles[5]]) 129 | cir.loss_t(0, transmittance[3]) 130 | cir.loss_t(1, transmittance[4]) 131 | cir.loss_t(2, transmittance[5]) 132 | cir.to(torch.float64) 133 | state = cir() 134 | cov, mean = state 135 | err = (abs(cov[0] - sf_cov).flatten()).sum() + (abs(mean[0].flatten() - sf_mean).flatten()).sum() 136 | assert err < 1e-6 137 | --------------------------------------------------------------------------------