├── .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 |
6 |
7 |
8 |
9 | [](https://dqapi.turingq.com/)
10 | [](https://pypi.org/project/deepquantum/)
11 | 
12 | [](./LICENSE)
13 | [](https://pypi.org/project/deepquantum/)
14 | [](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 |
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 |
--------------------------------------------------------------------------------