提交 100686b4 编写于 作者: Q Quleaf

update to v1.1.0

上级 3581ccef
# Paddle Quantum (量桨)
- [特色](#特色)
- [安装步骤](#安装步骤)
- [安装 PaddlePaddle](#安装-paddlepaddle)
- [下载 Paddle Quantum 并安装](#下载-paddle-quantum-并安装)
- [或使用 requirements.txt 安装依赖包](#或使用-requirementstxt-安装依赖包)
- [使用 openfermion 读取 xyz 描述文件](#使用-openfermion-读取-xyz-描述文件)
- [运行](#运行)
- [入门与开发](#入门与开发)
- [教程入门](#教程入门)
- [案例入门](#案例入门)
- [API 文档](#api-文档)
- [开发](#开发)
- [交流与反馈](#交流与反馈)
- [使用 Paddle Quantum 的工作](#使用-paddle-quantum-的工作)
- [FAQ](#faq)
- [Copyright and License](#copyright-and-license)
- [References](#references)
Paddle Quantum(量桨)是基于百度飞桨开发的量子机器学习工具集,支持量子神经网络的搭建与训练,提供易用的量子机器学习开发套件与量子优化、量子化学等前沿量子应用工具集,使得百度飞桨也因此成为国内首个目前也是唯一一个支持量子机器学习的深度学习框架。
![](https://release-data.cdn.bcebos.com/Paddle%20Quantum.png)
量桨建立起了人工智能与量子计算的桥梁,不但可以快速实现量子神经网络的搭建与训练,还提供易用的量子机器学习开发套件与量子优化、量子化学等前沿量子应用工具集,并提供多项自研量子机器学习应用。通过百度飞桨深度学习平台赋能量子计算,量桨为领域内的科研人员以及开发者便捷地开发量子人工智能的应用提供了强有力的支撑,同时也为广大量子计算爱好者提供了一条可行的学习途径。
## 特色
- 易用性:提供简洁的神经网络搭建与丰富的量子机器学习案例。
- 通用性与拓展性:支持常用量子电路模型,提供多项优化工具。
- 特色工具集:提供量子优化、量子化学等前沿量子应用工具集,自研多项量子机器学习应用。
- 易用性
- 高效搭建量子神经网络
- 多种量子神经网络模板
- 丰富量子算法教程(10+用例)
- 可拓展性
- 支持通用量子电路模型
- 高性能模拟器支持20多个量子比特的模拟运算
- 提供多种优化工具和 GPU 加速
- 特色工具集
- 提供组合优化和量子化学等前沿领域的计算工具箱
- 自研多种量子机器学习算法
## 安装步骤
### Install PaddlePaddle
请参考 [PaddlePaddle](https://www.paddlepaddle.org.cn/documentation/docs/zh/beginners_guide/index_cn.html) 安装配置页面。此项目需求 PaddlePaddle 1.8.0 或更高版本。
### 安装 PaddlePaddle
请参考 [PaddlePaddle](https://www.paddlepaddle.org.cn/install/quick) 安装配置页面。此项目需求 PaddlePaddle 1.8.3 或更高版本。
### 下载 Paddle Quantum 并安装
......@@ -34,30 +55,33 @@ cd quantum
pip install -e .
```
### 或使用 requirements.txt 安装依赖包
```bash
python -m pip install --upgrade -r requirements.txt
```
### 使用 openfermion 读取xyz 描述文件 (仅可在linux下安装使用)
VQE中调用 openfermion 读取分子xyz文件并计算,因此需要安装 openfermion 和 openfermionpyscf。
### 使用 openfermion 读取 xyz 描述文件
> 仅在 macOS 和 linux 下可以使用 openfermion 读取 xyz 描述文件。
VQE中调用 openfermion 读取分子 xyz 文件并计算,因此需要安装 openfermion 和 openfermionpyscf。
```bash
pip install openfermion
pip install openfermionpyscf
```
### 运行
现在,可以试着运行一段程序来验证量桨是否已安装成功。这里我们运行量桨提供的量子近似优化算法 (QAOA) 的例子。
```bash
cd paddle_quantum/QAOA/example
python main.py
```
> 关于 QAOA 的介绍可以参考我们的 [QAOA 教程](./tutorial/QAOA)。
## 入门与开发
......@@ -65,65 +89,93 @@ python main.py
量子计算是由量子力学与计算理论交叉而成的全新计算模型,具有强大的信息处理优势和广阔的应用前景,被视作未来计算技术的心脏。量子计算的相关介绍与入门知识可以参考 [1-3]。
量子机器学习是一门结合量子计算与机器学习的交叉学科,一方面利用量子计算的信息处理优势促进人工智能的发展,另一方面也利用现有的人工智能的技术突破量子计算的研发瓶颈。关于量子机器学习的入门资料可以参考 [4-6]。Paddle Quantum(量桨)建立起了人工智能与量子计算的桥梁,为量子机器学习领域的研发提供强有力的支撑,也提供了丰富的案例供开发者学习。
量子机器学习是一门结合量子计算与机器学习的交叉学科,一方面利用量子计算的信息处理优势促进人工智能的发展,另一方面也利用现有的人工智能的技术突破量子计算的研发瓶颈。关于量子机器学习的入门资料可以参考 [4-6]。
这里,我们提供了一份[**入门手册**](./introduction)方便用户快速上手 Paddle Quantum。目前支持 PDF 阅读和运行 Jupyter Notebook 两种方式。内容上,该手册包括以下几个方面:
- Paddle Quantum 的详细安装教程
- 量子计算的基础知识介绍
- Paddle Quantum 的使用介绍
- PaddlePaddle 飞桨优化器使用教程
- 具体的量子机器学习案例—VQE
### 案例入门
特别的,我们提供了涵盖量子优化、量子化学、量子机器学习等多个领域的案例供大家学习。比如:
- 量子近似优化(QAOA),完成安装步骤后打开 tutorial\QAOA.ipynb 即可进行研究学习。
Paddle Quantum(量桨)建立起了人工智能与量子计算的桥梁,为量子机器学习领域的研发提供强有力的支撑,也提供了丰富的案例供开发者学习。
```bash
cd tutorial
jupyter notebook QAOA.ipynb
```
在这里,我们提供了涵盖量子优化、量子化学、量子机器学习等多个领域的案例供大家学习。与[入门手册](./introduction)类似,每个教程目前支持 PDF 阅读和运行 Jupyter Notebook 两种方式。我们推荐用户下载 Notebook 后,本地运行进行实践。
- 量子特征求解器(VQE),完成安装步骤后打开 tutorial\VQE.ipynb 即可进行研究学习。
- [量子近似优化算法 (QAOA)](./tutorial/QAOA)
- [变分量子特征求解器 (VQE)](./tutorial/VQE)
- [量子神经网络的贫瘠高原效应 (Barren Plateaus)](./tutorial/Barren)
- [量子分类器 (Quantum Classifier)](./tutorial/Q-Classifier)
- [量子变分自编码器 (Quantum Autoencoder)](./tutorial/Q-Autoencoder)
- [量子生成对抗网络 (Quantum GAN)](./tutorial/Q-GAN)
- [子空间搜索 - 量子变分特征求解器 (SSVQE)](./tutorial/SSVQE)
- [变分量子态对角化算法 (VQSD)](./tutorial/VQSD)
- [吉布斯态的制备 (Gibbs State Preparation)](./tutorial/Gibbs)
- [变分量子奇异值分解 (VQSVD)](./tutorial/VQSVD)
```
cd tutorial
jupyter notebook VQE.ipynb
```
此外,Paddle Quantum 也支持在 GPU 上进行量子机器学习的训练,具体的方法请参考案例:[在 GPU 上使用 Paddle Quantum](./tutorial/GPU)
### API 文档
我们为 Paddle Quantum 提供了独立的 [API 文档页面](https://paddle-quantum.readthedocs.io/zh_CN/latest/),包含了供用户使用的所有函数和类的详细说明与用法。
### 开发
Paddle Quantum 使用 setuptools 的develop 模式进行安装,相关代码修改可以直接进入`paddle_quantum` 文件夹进行修改。python 文件携带了自说明注释。
Paddle Quantum 使用 setuptools 的 develop 模式进行安装,相关代码修改可以直接进入`paddle_quantum` 文件夹进行修改。python 文件携带了自说明注释。
## 交流与反馈
- 我们非常欢迎您通过 [Github Issues](https://github.com/PaddlePaddle/Quantum/issues) 来提交问题、报告与建议。
## 交流与反馈
- 技术交流QQ群:1076223166
- 我们非常欢迎您欢迎您通过[Github Issues](https://github.com/PaddlePaddle/Quantum/issues)来提交问题、报告与建议。
## 使用 Paddle Quantum 的工作
- QQ技术交流群: 1076223166
我们非常欢迎开发者使用 Paddle Quantum 进行量子机器学习的研发,如果您的工作有使用 Paddle Quantum,也非常欢迎联系我们。目前使用 Paddle Quantum 的代表性工作包括了吉布斯态的制备和变分量子奇异值分解:
## 使用Paddle Quantum的工作
[1] Wang, Y., Li, G. & Wang, X. Variational quantum Gibbs state preparation with a truncated Taylor series. arXiv:2005.08797 (2020). [[pdf](https://arxiv.org/pdf/2005.08797.pdf)]
我们非常欢迎开发者使用Paddle Quantum进行量子机器学习的研发,如果您的工作有使用Paddle Quantum,也非常欢迎联系我们。目前使用 Paddle Quantum 的代表性工作关于 Gibbs 态制备如下:
[2] Wang, X., Song, Z. & Wang, Y. Variational Quantum Singular Value Decomposition. arXiv:2006.02336 (2020). [[pdf](https://arxiv.org/pdf/2006.02336.pdf)]
[1] Youle Wang, Guangxi Li, and Xin Wang. 2020. Variational quantum Gibbs state preparation with a truncated Taylor series. arXiv2005.08797. [[pdf](https://arxiv.org/pdf/2005.08797.pdf)]
## FAQ
1. 问:**研究量子机器学习有什么意义?它有哪些应用场景?**
## Copyright and License
答:量子机器学习是将量子计算与机器学习相结合的一门学科,它一方面可以利用现有人工智能技术突破量子计算的研发瓶颈,另一方面也能利用量子计算的信息处理优势促进传统人工智能的发展。量子机器学习不仅适用于量子化学模拟(如[变分量子特征求解器 (VQE)](./tutorial/VQE))等量子问题,也可以用来解决一些经典问题(如[量子近似优化算法 (QAOA)](./tutorial/QAOA))。
2. 问:**想做量子机器学习,但对量子计算不是很了解,该如何入门?**
Paddle Quantum 使用 [Apache-2.0 license](LICENSE)许可证
答:Nielsen 和 Chuang 所著的《量子计算与量子信息》是量子计算领域公认的经典入门教材。建议读者首先学习这本书的第一、二、四章,介绍了量子计算中的基本概念、数学和物理基础、以及量子电路模型。读者也可以阅读量桨的[入门手册](./introduction),其中包含了对量子计算的简单介绍,并有互动性的例子供读者尝试。对量子计算有了大致了解后,读者可以尝试学习量桨提供的一些前沿[量子机器学习案例](./tutorial)
3. 问:**现阶段没有规模化的量子硬件,怎么开发量子应用?**
答:使用量桨,用户可以方便地在经典计算机上模拟量子算法,进行量子应用的开发与验证,为未来使用规模化的量子硬件做技术积累。
4. 问:**量桨有哪些优势?**
答:量桨是基于百度飞桨开发的量子机器学习工具集。飞桨作为国内首个开源开放的产业级深度学习平台,技术领先且功能完备。拥有飞桨的技术支持,特别是其强大的动态图机制,量桨可以方便地进行机器学习的优化以及 GPU 的加速。同时,基于百度量子计算研究所研发的高性能量子模拟器,量桨在个人笔记本电脑上也能支持20多个量子比特的运算。另外,量桨还有丰富的[量子机器学习案例](./tutorial)供大家参考和学习。
5. 问:**非常想试用量桨,该怎么入门呢?**
答:建议新用户首先阅读量桨的[入门手册](./introduction),它包含量桨详细的安装步骤以及入门教程。另外,量桨提供了丰富的[量子机器学习案例](./tutorial),以 Jupyter Notebook 和 PDF 的方式呈现,方便用户学习和实践。如在学习和使用过程中遇到任何问题,欢迎用户通过 [Github Issues](https://github.com/PaddlePaddle/Quantum/issues) 以及技术交流QQ群(1076223166)与我们交流。
## Copyright and License
Paddle Quantum 使用 [Apache-2.0 license](LICENSE) 许可证。
## References
[1] [量子计算 - 百度百科](https://baike.baidu.com/item/量子计算/11035661?fr=aladdin)
[1] [量子计算 - 百度百科](https://baike.baidu.com/item/%E9%87%8F%E5%AD%90%E8%AE%A1%E7%AE%97/11035661)
[2] Michael A Nielsen and Isaac L Chuang. 2010. Quantum computation and quantum information. Cambridge university press.
[2] Nielsen, M. A. & Chuang, I. L. Quantum computation and quantum information. (Cambridge university press, 2010).
[3] Phillip Kaye, Raymond Laflamme, and Michele Mosca. 2007. An Introduction to Quantum Computing.
[3] Phillip Kaye, Laflamme, R. & Mosca, M. An Introduction to Quantum Computing. (2007).
[4] Jacob Biamonte, Peter Wittek, Nicola Pancotti, Patrick Rebentrost, Nathan Wiebe, and Seth Lloyd. 2017. Quantum machine learning. Nature 549, 7671, 195–202. [[pdf](https://arxiv.org/pdf/1611.09347)]
[4] [Biamonte, J. et al. Quantum machine learning. Nature 549, 195–202 (2017).](https://www.nature.com/articles/nature23474)
[5] Maria Schuld, Ilya Sinayskiy, and Francesco Petruccione. 2015. An introduction to quantum machine learning. Contemp. Phys. 56, 2, 172–185. [[pdf](https://arxiv.org/pdf/1409.3097)]
[5] [Schuld, M., Sinayskiy, I. & Petruccione, F. An introduction to quantum machine learning. Contemp. Phys. 56, 172–185 (2015).](https://www.tandfonline.com/doi/abs/10.1080/00107514.2014.964942)
[6] Marcello Benedetti, Erika Lloyd, Stefan Sack, and Mattia Fiorentini. 2019. Parameterized quantum circuits as machine learning models. Quantum Sci. Technol. 4, 4, 043001. [[pdf](https://arxiv.org/pdf/1906.07682)]
\ No newline at end of file
[6] [Benedetti, M., Lloyd, E., Sack, S. & Fiorentini, M. Parameterized quantum circuits as machine learning models. Quantum Sci. Technol. 4, 043001 (2019).](https://iopscience.iop.org/article/10.1088/2058-9565/ab4eb5)
\ No newline at end of file
此差异已折叠。
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = source
BUILDDIR = build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=source
set BUILDDIR=build
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
:end
popd
paddlepaddle>=1.8.3
networkx>=2.4
matplotlib>=3.3.0
interval>=1.0.0
progressbar>=2.5
sphinx
sphinx-rtd-theme
PyStemmer
readthedocs-sphinx-search
jieba
\ No newline at end of file
# -*- coding: utf-8 -*-
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
import sys
sys.path.insert(0, os.path.abspath('../..'))
# -- Project information -----------------------------------------------------
project = 'Paddle Quantum'
copyright = u'2020, Institute for Quantum Computing, Baidu Inc.'
author = u'Institute for Quantum Computing, Baidu Inc.'
# The full version, including alpha/beta/rc tags
release = '1.1.0'
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.napoleon',
'sphinx.ext.mathjax',
'sphinx_search.extension',
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = 'zh_CN'
html_search_language = 'zh'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = []
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_logo = '_static/logo.png'
master_doc = 'index'
# Autodoc
autodoc_member_order = 'bysource'
.. Paddle Quantum documentation master file, created by
sphinx-quickstart on Fri Aug 21 10:54:43 2020.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to Paddle Quantum's documentation!
==========================================
.. toctree::
:maxdepth: 2
:caption: Paddle Quantum 入门
introduction
tutorial
.. toctree::
:maxdepth: 4
:caption: API 文档
modules
.. _header-n0:
Paddle Quantum (量桨)
=======================
`Paddle Quantum(量桨) <https://github.com/PaddlePaddle/Quantum>`__\ 是基于百度飞桨开发的量子机器学习工具集,支持量子神经网络的搭建与训练,提供易用的量子机器学习开发套件与量子优化、量子化学等前沿量子应用工具集,使得百度飞桨也因此成为国内首个目前也是唯一一个支持量子机器学习的深度学习框架。
.. figure:: https://release-data.cdn.bcebos.com/Paddle%20Quantum.png
:target: https://github.com/PaddlePaddle/Quantum
量桨建立起了人工智能与量子计算的桥梁,不但可以快速实现量子神经网络的搭建与训练,还提供易用的量子机器学习开发套件与量子优化、量子化学等前沿量子应用工具集,并提供多项自研量子机器学习应用。通过百度飞桨深度学习平台赋能量子计算,量桨为领域内的科研人员以及开发者便捷地开发量子人工智能的应用提供了强有力的支撑,同时也为广大量子计算爱好者提供了一条可行的学习途径。
关于量桨的更多内容可以查看 GitHub 页面:https://github.com/PaddlePaddle/Quantum
.. _header-n6:
特色
----
- 易用性
- 高效搭建量子神经网络
- 多种量子神经网络模板
- 丰富量子算法教程(10+用例)
- 可拓展性
- 支持通用量子电路模型
- 高性能模拟器支持20多个量子比特的模拟运算
- 提供多种优化工具和 GPU 加速
- 特色工具集
- 提供组合优化和量子化学等前沿领域的计算工具箱
- 自研多种量子机器学习算法
.. _header-n15:
安装步骤
--------
.. _header-n16:
安装 PaddlePaddle
~~~~~~~~~~~~~~~~~
请参考
`PaddlePaddle <https://www.paddlepaddle.org.cn/install/quick>`__
安装配置页面。此项目需求 PaddlePaddle 1.8.3 或更高版本。
.. _header-n19:
下载 Paddle Quantum 并安装
~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: shell
git clone http://github.com/PaddlePaddle/quantum
.. code:: shell
cd quantum
pip install -e .
.. _header-n23:
或使用 requirements.txt 安装依赖包
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: shell
python -m pip install --upgrade -r requirements.txt
.. _header-n25:
使用 openfermion 读取 xyz 描述文件
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. note:: 仅在 macOS 和 linux 下可以使用 openfermion 读取 xyz 描述文件。
VQE中调用 openfermion 读取分子 xyz 文件并计算,因此需要安装 openfermion 和
openfermionpyscf。
.. code:: shell
pip install openfermion
pip install openfermionpyscf
.. _header-n29:
运行
~~~~
现在,可以试着运行一段程序来验证量桨是否已安装成功。这里我们运行量桨提供的量子近似优化算法
(QAOA) 的例子。
.. code:: shell
cd paddle_quantum/QAOA/example
python main.py
..
.. note:: 关于 QAOA 的介绍可以参考我们的 `QAOA 教程 <https://github.com/PaddlePaddle/Quantum/blob/master/tutorial/QAOA>`__。
.. _header-n51:
交流与反馈
----------
- 我们非常欢迎您通过 `Github
Issues <https://github.com/PaddlePaddle/Quantum/issues>`__
来提交问题、报告与建议。
- 技术交流QQ群:1076223166
.. _header-n118:
Copyright and License
---------------------
Paddle Quantum 使用 `Apache-2.0 license <https://github.com/PaddlePaddle/Quantum/blob/master/LICENSE>`__ 许可证。
paddle_quantum
==============
.. toctree::
:maxdepth: 4
paddle_quantum
paddle\_quantum.circuit module
==============================
.. automodule:: paddle_quantum.circuit
:members:
:undoc-members:
:show-inheritance:
paddle\_quantum package
=======================
.. automodule:: paddle_quantum
:members:
:undoc-members:
:show-inheritance:
Submodules
----------
.. toctree::
:maxdepth: 4
paddle_quantum.circuit
paddle_quantum.state
paddle_quantum.utils
paddle\_quantum.state module
============================
.. automodule:: paddle_quantum.state
:members:
:undoc-members:
:show-inheritance:
paddle\_quantum.utils module
============================
.. automodule:: paddle_quantum.utils
:members:
:undoc-members:
:show-inheritance:
教程与案例
=======================
我们准备了入门教程和入门案例,来帮助用户快速学会如何使用量桨(Paddle Quantum)。
.. _header-n33:
入门教程
--------
我们提供了一份 `Paddle Quantum 入门手册 <https://github.com/PaddlePaddle/Quantum/blob/master/introduction>`__\ 来方便用户快速上手
Paddle Quantum。目前支持 PDF 阅读和运行 Jupyter Notebook
两种方式。内容上,该手册包括以下几个方面:
- Paddle Quantum 的详细安装教程
- 量子计算的基础知识介绍
- Paddle Quantum 的使用介绍
- PaddlePaddle 飞桨优化器使用教程
- 具体的量子机器学习案例—VQE
入门案例
--------
我们提供了涵盖量子优化、量子化学、量子机器学习等多个领域的案例供大家学习。与\ `入门手册 <https://github.com/PaddlePaddle/Quantum/blob/master/introduction>`__\ 类似,每个教程目前支持
PDF 阅读和运行 Jupyter Notebook 两种方式。我们推荐用户下载 Notebook
后,本地运行进行实践。
1. `量子近似优化算法 (QAOA) <https://github.com/PaddlePaddle/Quantum/blob/master/tutorial/QAOA>`__
2. `变分量子特征求解器 (VQE) <https://github.com/PaddlePaddle/Quantum/blob/master/tutorial/VQE>`__
3. `量子神经网络的贫瘠高原效应 (Barren Plateaus) <https://github.com/PaddlePaddle/Quantum/blob/master/tutorial/Barren>`__
4. `量子分类器 (Quantum Classifier) <https://github.com/PaddlePaddle/Quantum/blob/master/tutorial/Q-Classifier>`__
5. `量子变分自编码器 (Quantum Autoencoder) <https://github.com/PaddlePaddle/Quantum/blob/master/tutorial/Q-Autoencoder>`__
6. `量子生成对抗网络 (Quantum GAN) <https://github.com/PaddlePaddle/Quantum/blob/master/tutorial/Q-GAN>`__
7. `子空间搜索 - 量子变分特征求解器 (SSVQE) <https://github.com/PaddlePaddle/Quantum/blob/master/tutorial/SSVQE>`__
8. `变分量子态对角化算法 (VQSD) <https://github.com/PaddlePaddle/Quantum/blob/master/tutorial/VQSD>`__
9. `吉布斯态的制备 (Gibbs State Preparation) <https://github.com/PaddlePaddle/Quantum/blob/master/tutorial/Gibbs>`__
10. `变分量子奇异值分解 (VQSVD) <https://github.com/PaddlePaddle/Quantum/blob/master/tutorial/VQSVD>`__
此外,Paddle Quantum 也支持在 GPU
上进行量子机器学习的训练,具体的方法请参考案例:`在 GPU 上使用 Paddle
Quantum <https://github.com/PaddlePaddle/Quantum/blob/master/tutorial/GPU>`__。
此差异已折叠。
# Copyright (c) 2020 Paddle Quantum Authors. All Rights Reserved.
# Copyright (c) 2020 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -16,8 +16,9 @@
HGenerator
"""
from numpy import array, kron, trace
import scipy
from numpy import trace as np_trace
from paddle_quantum.utils import pauli_str_to_matrix
__all__ = ["H_generator", ]
......@@ -27,16 +28,18 @@ def H_generator():
Generate a Hamiltonian with trivial descriptions
Returns: A Hamiltonian
"""
# 生成用泡利字符串表示的特定的哈密顿量
H = [[-1.0, 'z0,z1'], [-1.0, 'z1,z2'], [-1.0, 'z0,z2']]
beta = 1
sigma_I = array([[1, 0], [0, 1]])
sigma_Z = array([[1, 0], [0, -1]])
# 生成哈密顿量的矩阵信息
N_SYS_B = 3 # 用于生成吉布斯态的子系统B的量子比特数
hamiltonian = pauli_str_to_matrix(H, N_SYS_B)
H = (-kron(kron(sigma_Z, sigma_Z), sigma_I) - kron(
kron(sigma_I, sigma_Z), sigma_Z) - kron(
kron(sigma_Z, sigma_I), sigma_Z))
# 生成理想情况下的目标吉布斯态 rho
beta = 1.5 # 设置逆温度参数 beta
rho_G = scipy.linalg.expm(-1 * beta * hamiltonian) / np_trace(scipy.linalg.expm(-1 * beta * hamiltonian))
rho = scipy.linalg.expm(-1 * beta *
H) / trace(scipy.linalg.expm(-1 * beta * H))
return H.astype("complex64"), rho.astype("complex64")
# 设置成 Paddle quantum 所支持的数据类型
hamiltonian = hamiltonian.astype("complex128")
rho_G = rho_G.astype("complex128")
return hamiltonian, rho_G
\ No newline at end of file
# Copyright (c) 2020 Paddle Quantum Authors. All Rights Reserved.
# Copyright (c) 2020 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -16,17 +16,18 @@
Paddle_GIBBS
"""
from numpy import concatenate, zeros
import scipy
from numpy import pi as PI
from paddle import fluid
from paddle.complex import matmul, transpose, trace
from paddle.complex import matmul, trace
from paddle_quantum.circuit import UAnsatz
from paddle_quantum.utils import compute_fid, partial_trace
from paddle_quantum.state import density_op
from paddle_quantum.utils import state_fidelity, partial_trace
from paddle_quantum.GIBBS.HGenerator import H_generator
SEED = 1
SEED = 14 # 固定随机种子
__all__ = [
"U_theta",
......@@ -35,29 +36,25 @@ __all__ = [
]
def U_theta(theta, input_state, N, D): # definition of U_theta
def U_theta(initial_state, theta, N, D):
"""
:param theta:
:param input_state:
:return:
Quantum Neural Network
"""
cir = UAnsatz(N, input_state=input_state)
for i in range(N):
cir.rx(theta=theta[0][0][i], which_qubit=i + 1)
cir.ry(theta=theta[0][1][i], which_qubit=i + 1)
cir.rx(theta=theta[0][2][i], which_qubit=i + 1)
# 按照量子比特数量/网络宽度初始化量子神经网络
cir = UAnsatz(N)
# 内置的 {R_y + CNOT} 电路模板
cir.real_entangled_layer(theta[:D], D)
for repeat in range(D):
for i in range(1, N):
cir.cnot(control=[i, i + 1])
# 铺上最后一列 R_y 旋转门
for i in range(N):
cir.ry(theta=theta[D][i][0], which_qubit=i)
for i in range(N):
cir.ry(theta=theta[repeat][0][i], which_qubit=i + 1)
# cir.ry(theta=theta[repeat][1][i], which_qubit=i + 1)
# cir.ry(theta=theta[repeat][2][i], which_qubit=i + 1)
# 量子神经网络作用在给定的初始态上
final_state = cir.run_density_matrix(initial_state)
return cir.state
return final_state
class Net(fluid.dygraph.Layer):
......@@ -65,96 +62,83 @@ class Net(fluid.dygraph.Layer):
Construct the model net
"""
def __init__(self,
shape,
param_attr=fluid.initializer.Uniform(
low=0.0, high=PI, seed=SEED),
dtype='float32'):
def __init__(self, N, shape, param_attr=fluid.initializer.Uniform(low=0.0, high=2 * PI, seed=SEED),
dtype='float64'):
super(Net, self).__init__()
self.theta = self.create_parameter(
shape=shape, attr=param_attr, dtype=dtype, is_bias=False)
def forward(self, input_state, H, N, N_SYS_B, D):
"""
Args:
input_state: The initial state with default |0..>
H: The target Hamiltonian
Returns:
The loss.
"""
out_state = U_theta(self.theta, input_state, N, D)
# rho_AB = utils.matmul(utils.matrix_conjugate_transpose(out_state), out_state)
rho_AB = matmul(
transpose(
fluid.framework.ComplexVariable(out_state.real,
-out_state.imag),
perm=[1, 0]),
out_state)
# compute the partial trace and three losses
rho_B = partial_trace(rho_AB, 2**(N - N_SYS_B), 2**(N_SYS_B), 1)
# 初始化 theta 参数列表,并用 [0, 2*pi] 的均匀分布来填充初始值
self.theta = self.create_parameter(shape=shape, attr=param_attr, dtype=dtype, is_bias=False)
# 初始化 rho = |0..0><0..0| 的密度矩阵
self.initial_state = fluid.dygraph.to_variable(density_op(N))
# 定义损失函数和前向传播机制
def forward(self, H, N, N_SYS_B, beta, D):
# 施加量子神经网络
rho_AB = U_theta(self.initial_state, self.theta, N, D)
# 计算偏迹 partial trace 来获得子系统B所处的量子态 rho_B
rho_B = partial_trace(rho_AB, 2 ** (N - N_SYS_B), 2 ** (N_SYS_B), 1)
# 计算三个子损失函数
rho_B_squre = matmul(rho_B, rho_B)
loss1 = (trace(matmul(rho_B, H))).real
loss2 = (trace(rho_B_squre)).real * 2
loss3 = -(trace(matmul(rho_B_squre, rho_B))).real / 2
loss2 = (trace(rho_B_squre)).real * 2 / beta
loss3 = - ((trace(matmul(rho_B_squre, rho_B))).real + 3) / (2 * beta)
loss = loss1 + loss2 + loss3 # 损失函数
# 最终的损失函数
loss = loss1 + loss2 + loss3
# option: if you want to check whether the imaginary part is 0, uncomment the following
# print('loss_iminary_part: ', loss.numpy()[1])
return loss - 3 / 2, rho_B
return loss, rho_B
def Paddle_GIBBS(hamiltonian, rho=None, N=5, N_SYS_B=3, D=1, ITR=100, LR=0.5):
"""
def Paddle_GIBBS(hamiltonian, rho_G, N=4, N_SYS_B=3, beta=1.5, D=1, ITR=50, LR=0.5):
r"""
Paddle_GIBBS
:param hamiltonian: 哈密顿量
:param rho_G: 目标吉布斯态 rho
:param N: 量子神经网络的宽度
:param N_SYS_B: 用于生成吉布斯态的子系统B的量子比特数
:param D: 设置量子神经网络中重复计算模块的深度 Depth
:param ITR: 设置训练的总迭代次数
:param LR: 设置学习速率
:return: todo
"""
# 初始化paddle动态图机制
with fluid.dygraph.guard():
# initial state preparing
_initial_state_np = concatenate(
([[1.]], zeros([1, 2**N - 1])), axis=1).astype('complex64')
initial_state = fluid.dygraph.to_variable(_initial_state_np)
# gibbs Hamiltonian preparing
# 我们需要将 Numpy array 转换成 Paddle 动态图模式中支持的 variable
H = fluid.dygraph.to_variable(hamiltonian)
# net
net = Net(shape=[D + 1, 3, N])
# 确定网络的参数维度
net = Net(N, shape=[D + 1, N, 1])
# optimizer
opt = fluid.optimizer.AdamOptimizer(
learning_rate=LR, parameter_list=net.parameters())
# 一般来说,我们利用Adam优化器来获得相对好的收敛,当然你可以改成SGD或者是RMS prop.
opt = fluid.optimizer.AdamOptimizer(learning_rate=LR, parameter_list=net.parameters())
# gradient descent loop
# 优化循环
for itr in range(1, ITR + 1):
loss, rho_B = net(initial_state, H, N, N_SYS_B, D)
# 前向传播计算损失函数并返回生成的量子态 rho_B
loss, rho_B = net(H, N, N_SYS_B, beta, D)
# 在动态图机制下,反向传播极小化损失函数
loss.backward()
opt.minimize(loss)
net.clear_gradients()
# 转换成 Numpy array 用以计算量子态的保真度 F(rho_B, rho_G)
rho_B = rho_B.numpy()
fid = state_fidelity(rho_B, rho_G)
if rho is not None:
fid = compute_fid(rho_B, rho)
print('iter:', itr, 'loss:', '%.4f' % loss.numpy(), 'fid:',
'%.4f' % fid)
# 打印训练结果
if itr % 5 == 0:
print('iter:', itr, 'loss:', '%.4f' % loss.numpy(), 'fid:', '%.4f' % fid)
return rho_B
def main():
"""
main
"""
# gibbs Hamiltonian preparing
hamiltonian, rho = H_generator()
rho_B = Paddle_GIBBS(hamiltonian, rho)
hamiltonian, rho_G = H_generator()
rho_B = Paddle_GIBBS(hamiltonian, rho_G)
print(rho_B)
......
# Copyright (c) 2020 Paddle Quantum Authors. All Rights Reserved.
# Copyright (c) 2020 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -16,13 +16,29 @@
main
"""
from paddle_quantum.GIBBS.HGenerator import H_generator
import scipy
from numpy import trace as np_trace
from paddle_quantum.utils import pauli_str_to_matrix
from paddle_quantum.GIBBS.Paddle_GIBBS import Paddle_GIBBS
def main():
hamiltonian, rho = H_generator()
rho_B = Paddle_GIBBS(hamiltonian, rho)
# 生成用泡利字符串表示的特定的哈密顿量
H = [[-1.0, 'z0,z1'], [-1.0, 'z1,z2'], [-1.0, 'z0,z2']]
# 生成哈密顿量的矩阵信息
N_SYS_B = 3 # 用于生成吉布斯态的子系统B的量子比特数
hamiltonian = pauli_str_to_matrix(H, N_SYS_B)
# 生成理想情况下的目标吉布斯态 rho
beta = 1.5 # 设置逆温度参数 beta
rho_G = scipy.linalg.expm(-1 * beta * hamiltonian) / np_trace(scipy.linalg.expm(-1 * beta * hamiltonian))
# 设置成 Paddle quantum 所支持的数据类型
hamiltonian = hamiltonian.astype("complex128")
rho_G = rho_G.astype("complex128")
rho_B = Paddle_GIBBS(hamiltonian, rho_G)
print(rho_B)
......
# Copyright (c) 2020 Paddle Quantum Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
main
"""
from paddle_quantum.GIBBS.HGenerator import H_generator
from paddle_quantum.GIBBS.Paddle_GIBBS import Paddle_GIBBS
def main():
# gibbs Hamiltonian preparing
hamiltonian, rho = H_generator()
rho_B = Paddle_GIBBS(hamiltonian, rho)
print(rho_B)
if __name__ == '__main__':
main()
# Copyright (c) 2020 Paddle Quantum Authors. All Rights Reserved.
# Copyright (c) 2020 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -17,19 +17,19 @@ Paddle_QAOA: To learn more about the functions and properties of this applicatio
you could check the corresponding Jupyter notebook under the Tutorial folder.
"""
import os
from paddle import fluid
from paddle.complex import matmul as pp_matmul
from paddle.complex import transpose
import os
import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
from paddle_quantum.circuit import UAnsatz
from paddle_quantum.utils import pauli_str_to_matrix
from paddle_quantum.QAOA.QAOA_Prefunc import generate_graph, H_generator
from numpy import ones, abs, conjugate, real, savez, sqrt, zeros
from numpy import matmul as np_matmul
from numpy import pi as PI
# Random seed for optimizer
SEED = 1
SEED = 1024
__all__ = [
"circuit_QAOA",
......@@ -39,48 +39,46 @@ __all__ = [
]
def circuit_QAOA(theta, input_state, adjacency_matrix, N, P):
def circuit_QAOA(theta, adjacency_matrix, N, P):
"""
This function constructs the parameterized QAOA circuit which is composed of P layers of two blocks:
one block is U_theta[layer][0] based on the problem Hamiltonian H which encodes the classical problem,
and the other is U_theta[layer][1] constructed from the driving Hamiltonian describing the rotation around Pauli X
acting on each qubit. It finally outputs the final state of the QAOA circuit.
one block is based on the problem Hamiltonian H which encodes the classical problem,
and the other is constructed from the driving Hamiltonian describing the rotation around Pauli X
acting on each qubit. It outputs the final state of the QAOA circuit.
Args:
theta: parameters to be optimized in the QAOA circuit
input_state: initial state of the QAOA circuit which usually is the uniform superposition of 2^N bit-strings
in the computational basis $|0\rangle, |1\rangle$
adjacency_matrix: the adjacency matrix of the graph encoding the classical problem
N: number of qubits, or equivalently, the number of nodes in the given graph
P: number of layers of two blocks in the QAOA circuit
theta: parameters to be optimized in the QAOA circuit
adjacency_matrix: the adjacency matrix of the graph encoding the classical problem
N: number of qubits, or equivalently, the number of parameters in the original classical problem
P: number of layers of two blocks in the QAOA circuit
Returns:
the final state of the QAOA circuit: cir.state
the QAOA circuit
"""
cir = UAnsatz(N, input_state=input_state)
# The first loop defines the QAOA circuit with P layers of two blocks
cir = UAnsatz(N)
# prepare the input state in the uniform superposition of 2^N bit-strings in the computational basis
cir.superposition_layer()
# This loop defines the QAOA circuit with P layers of two blocks
for layer in range(P):
# The second and third loops aim to construct the first block U_theta[layer][0] which involves
# two-qubit operation e^{-i\beta Z_iZ_j} acting on a pair of qubits or nodes i and j in the circuit.
# The second and third loops construct the first block which involves two-qubit operation
# e^{-i\gamma Z_iZ_j} acting on a pair of qubits or nodes i and j in the circuit in each layer.
for row in range(N):
for col in range(N):
if abs(adjacency_matrix[row, col]) and row < col:
cir.cnot([row + 1, col + 1])
cir.rz(
theta=theta[layer][0] * adjacency_matrix[row, col],
which_qubit=col + 1, )
cir.cnot([row + 1, col + 1])
# This loops constructs the second block U_theta only involving the single-qubit operation e^{-i\beta X}.
for i in range(1, N + 1):
cir.rx(theta=theta[layer][1], which_qubit=i)
if adjacency_matrix[row, col] and row < col:
cir.cnot([row, col])
cir.rz(theta[layer][0], col)
cir.cnot([row, col])
# This loop constructs the second block only involving the single-qubit operation e^{-i\beta X}.
for i in range(N):
cir.rx(theta[layer][1], i)
return cir.state
return cir
def circuit_extend_QAOA(theta, input_state, adjacency_matrix, N, P):
def circuit_extend_QAOA(theta, adjacency_matrix, N, P):
"""
This is an extended version of the QAOA circuit, and the main difference is U_theta[layer]([1]-[3]) constructed
This is an extended version of the QAOA circuit, and the main difference is the block constructed
from the driving Hamiltonian describing the rotation around an arbitrary direction on each qubit.
Args:
......@@ -91,35 +89,29 @@ def circuit_extend_QAOA(theta, input_state, adjacency_matrix, N, P):
N: number of qubits, or equivalently, the number of parameters in the original classical problem
P: number of layers of two blocks in the QAOA circuit
Returns:
final state of the QAOA circuit: cir.state
the extended QAOA circuit
Note: If this U_extend_theta function is used to construct QAOA circuit, then we need to change the parameter layer
in the Net function defined below from the Net(shape=[D, 2]) for U_theta function to Net(shape=[D, 4])
because the number of parameters doubles in each layer in this QAOA circuit.
Note:
If this circuit_extend_QAOA function is used to construct QAOA circuit, then we need to change the parameter layer
in the Net function defined below from the Net(shape=[D, 2]) for circuit_QAOA function to Net(shape=[D, 4])
because the number of parameters doubles in each layer in this QAOA circuit.
"""
cir = UAnsatz(N)
cir = UAnsatz(N, input_state=input_state)
# The first loop defines the QAOA circuit with P layers of two blocks
# prepare the input state in the uniform superposition of 2^N bit-strings in the computational basis
cir.superposition_layer()
for layer in range(P):
# The second and third loops aim to construct the first block U_theta[layer][0] which involves
# two-qubit operation e^{-i\beta Z_iZ_j} acting on a pair of qubits or nodes i and j in the circuit.
for row in range(N):
for col in range(N):
if abs(adjacency_matrix[row, col]) and row < col:
cir.cnot([row + 1, col + 1])
cir.rz(
theta=theta[layer][0] * adjacency_matrix[row, col],
which_qubit=col + 1, )
cir.cnot([row + 1, col + 1])
# This loops constructs the second block U_theta[layer][1]-[3] composed of three single-qubit operation
# e^{-i\beta[1] Z}e^{-i\beta[2] X}e^{-i\beta[3] X} sequentially acting on single qubits.
for i in range(1, N + 1):
cir.rz(theta=theta[layer][1], which_qubit=i)
cir.rx(theta=theta[layer][2], which_qubit=i)
cir.rz(theta=theta[layer][3], which_qubit=i)
return cir.state
if adjacency_matrix[row, col] and row < col:
cir.cnot([row, col])
cir.rz(theta[layer][0], col)
cir.cnot([row, col])
for i in range(N):
cir.u3(*theta[layer][1:], i)
return cir
class Net(fluid.dygraph.Layer):
......@@ -132,72 +124,48 @@ class Net(fluid.dygraph.Layer):
def __init__(
self,
shape,
param_attr=fluid.initializer.Uniform(
low=0.0, high=PI, seed=SEED),
dtype="float32", ):
param_attr=fluid.initializer.Uniform(low=0.0, high=np.pi, seed=SEED),
dtype="float64",
):
super(Net, self).__init__()
self.theta = self.create_parameter(
shape=shape, attr=param_attr, dtype=dtype, is_bias=False)
shape=shape, attr=param_attr, dtype=dtype, is_bias=False
)
def forward(self, input_state, adjacency_matrix, out_state_store, N, P,
METHOD):
def forward(self, adjacency_matrix, N, P, METHOD):
"""
This function constructs the loss function for the QAOA circuit.
Args:
self: the free parameters to be optimized in the QAOA circuit and defined in the above function
input_state: initial state of the QAOA circuit which usually is the uniform superposition of 2^N bit-strings
in the computational basis $|0\rangle, |1\rangle$
adjacency_matrix: the adjacency matrix generated from the graph encoding the classical problem
out_state_store: the output state of the QAOA circuit
N: number of qubits
P: number of layers
METHOD: which version of QAOA is chosen to solve the problem, i.e., standard version labeled by 1 or
extended version by 2.
Returns:
The loss function for the parameterized QAOA circuit.
the loss function for the parameterized QAOA circuit and the circuit itself
"""
# Generate the problem_based quantum Hamiltonian H_problem based on the classical problem in paddle
H, _ = H_generator(N, adjacency_matrix)
H_problem = fluid.dygraph.to_variable(H)
H_problem = H_generator(N, adjacency_matrix)
# The standard QAOA circuit: the function circuit_QAOA is used to construct the circuit, indexed by METHOD 1.
if METHOD == 1:
out_state = circuit_QAOA(self.theta, input_state, adjacency_matrix,
N, P)
cir = circuit_QAOA(self.theta, adjacency_matrix, N, P)
# The extended QAOA circuit: the function circuit_extend_QAOA is used to construct the net, indexed by METHOD 2.
elif METHOD == 2:
out_state = circuit_extend_QAOA(self.theta, input_state,
adjacency_matrix, N, P)
cir = circuit_extend_QAOA(self.theta, adjacency_matrix, N, P)
else:
raise ValueError("Wrong method called!")
out_state_store.append(out_state.numpy())
loss = pp_matmul(
pp_matmul(out_state, H_problem),
transpose(
fluid.framework.ComplexVariable(out_state.real,
-out_state.imag),
perm=[1, 0], ), )
return loss.real
def main(N=4):
"""
This is the main function which maps the classical problem to the quantum version solved by QAOA and outputs
the quantum solution and its corresponding classical ones. Here, N=4 is a 4-qubit example to show how QAOA works.
cir.run_state_vector()
loss = cir.expecval(H_problem)
"""
# Generate the adjacency matrix from the description of the problem-based graph
_, classical_graph_adjacency = generate_graph(N, 1)
Paddle_QAOA(classical_graph_adjacency)
return loss, cir
def Paddle_QAOA(classical_graph_adjacency, N=4, P=4, METHOD=1, ITR=120,
LR=0.1):
def Paddle_QAOA(classical_graph_adjacency, N, P, METHOD, ITR, LR):
"""
This is the core function to run QAOA.
......@@ -209,15 +177,9 @@ def Paddle_QAOA(classical_graph_adjacency, N=4, P=4, METHOD=1, ITR=120,
ITR: number of iteration steps for QAOA (default value ITR=120)
LR: learning rate for the gradient-based optimization method (default value LR=0.1)
Returns:
optimized parameters theta and the bitstrings sampled from the output state with maximal probability
the optimized QAOA circuit
"""
out_state_store = []
with fluid.dygraph.guard():
# Preparing the initial state
_initial_state = ones([1, 2**N]).astype("complex64") / sqrt(2**N)
initial_state = fluid.dygraph.to_variable(_initial_state)
# Construct the net or QAOA circuits based on the standard modules
if METHOD == 1:
net = Net(shape=[P, 2])
......@@ -228,41 +190,109 @@ def Paddle_QAOA(classical_graph_adjacency, N=4, P=4, METHOD=1, ITR=120,
raise ValueError("Wrong method called!")
# Classical optimizer
opt = fluid.optimizer.AdamOptimizer(
learning_rate=LR, parameter_list=net.parameters())
opt = fluid.optimizer.AdamOptimizer(learning_rate=LR, parameter_list=net.parameters())
# Gradient descent loop
summary_iter, summary_loss = [], []
for itr in range(1, ITR + 1):
loss = net(initial_state, classical_graph_adjacency,
out_state_store, N, P, METHOD)
loss, cir = net(
classical_graph_adjacency, N, P, METHOD
)
loss.backward()
opt.minimize(loss)
net.clear_gradients()
print("iter:", itr, " loss:", "%.4f" % loss.numpy())
if itr % 10 == 0:
print("iter:", itr, " loss:", "%.4f" % loss.numpy())
summary_loss.append(loss[0][0].numpy())
summary_iter.append(itr)
theta_opt = net.parameters()[0].numpy()
print(theta_opt)
print("Optmized parameters theta:\n", theta_opt)
os.makedirs("output", exist_ok=True)
savez("./output/summary_data", iter=summary_iter, energy=summary_loss)
np.savez("./output/summary_data", iter=summary_iter, energy=summary_loss)
return cir
def main(N=4):
# number of qubits or number of nodes in the graph
N = 4
classical_graph, classical_graph_adjacency = generate_graph(N, GRAPHMETHOD=1)
print(classical_graph_adjacency)
# Convert the Hamiltonian's list form to matrix form
H_matrix = pauli_str_to_matrix(H_generator(N, classical_graph_adjacency), N)
# Output the measurement probability distribution sampled from the output state of optimized QAOA circuit.
prob_measure = zeros([1, 2**N]).astype("complex")
H_diag = np.diag(H_matrix).real
H_max = np.max(H_diag)
H_min = np.min(H_diag)
rho_out = out_state_store[-1]
rho_out = np_matmul(conjugate(rho_out).T, rho_out).astype("complex")
print(H_diag)
print('H_max:', H_max, ' H_min:', H_min)
for index in range(0, 2**N):
comput_basis = zeros([1, 2**N])
comput_basis[0][index] = 1
prob_measure[0][index] = real(
np_matmul(np_matmul(comput_basis, rho_out), comput_basis.T))
pos = nx.circular_layout(classical_graph)
nx.draw(classical_graph, pos, width=4, with_labels=True, font_weight='bold')
plt.show()
return prob_measure
classical_graph, classical_graph_adjacency = generate_graph(N, 1)
opt_cir = Paddle_QAOA(classical_graph_adjacency, N=4, P=4, METHOD=1, ITR=120, LR=0.1)
# Load the data of QAOA
x1 = np.load('./output/summary_data.npz')
H_min = np.ones([len(x1['iter'])]) * H_min
# Plot loss
loss_QAOA, = plt.plot(x1['iter'], x1['energy'], alpha=0.7, marker='', linestyle="--", linewidth=2, color='m')
benchmark, = plt.plot(x1['iter'], H_min, alpha=0.7, marker='', linestyle=":", linewidth=2, color='b')
plt.xlabel('Number of iteration')
plt.ylabel('Performance of the loss function for QAOA')
plt.legend(handles=[
loss_QAOA,
benchmark
],
labels=[
r'Loss function $\left\langle {\psi \left( {\bf{\theta }} \right)} '
r'\right|H\left| {\psi \left( {\bf{\theta }} \right)} \right\rangle $',
'The benchmark result',
], loc='best')
# Show the plot
plt.show()
with fluid.dygraph.guard():
# Measure the output state of the QAOA circuit for 1024 shots by default
prob_measure = opt_cir.measure(plot=True)
# Find the max value in measured probability of bitstrings
max_prob = max(prob_measure.values())
# Find the bitstring with max probability
solution_list = [result[0] for result in prob_measure.items() if result[1] == max_prob]
print("The output bitstring:", solution_list)
# Draw the graph representing the first bitstring in the solution_list to the MaxCut-like problem
head_bitstring = solution_list[0]
node_cut = ["blue" if head_bitstring[node] == "1" else "red" for node in classical_graph]
edge_cut = [
"solid" if head_bitstring[node_row] == head_bitstring[node_col] else "dashed"
for node_row, node_col in classical_graph.edges()
]
nx.draw(
classical_graph,
pos,
node_color=node_cut,
style=edge_cut,
width=4,
with_labels=True,
font_weight="bold",
)
plt.show()
if __name__ == "__main__":
......
# Copyright (c) 2020 Paddle Quantum Authors. All Rights Reserved.
# Copyright (c) 2020 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -16,21 +16,15 @@
Aid func
"""
from matplotlib import pyplot
import numpy as np
from numpy import abs, array, binary_repr, diag, kron, max, ones, real, where, zeros
import networkx
__all__ = [
"plot_graph",
"generate_graph",
"H_generator",
]
def plot_graph(measure_prob_distribution, graph, N):
"""
This function plots the graph encoding the combinatorial problem such as Max-Cut and the final graph encoding the
approximate solution obtained from QAOA
Args:
measure_prob_distribution: the measurement probability distribution which is sampled from the output state
of optimized QAOA circuit.
......@@ -93,68 +87,63 @@ def plot_graph(measure_prob_distribution, graph, N):
def generate_graph(N, GRAPHMETHOD):
"""
This function offers two methods to generate a graph.
It plots an N-node graph which is specified by Method 1 or 2.
Args:
N: number of nodes (vertices) in the graph, which is also the number of qubits
GRAPHMETHOD: which method to generate a graph
Return:
graph description and its adjacency matrix
N: number of nodes (vertices) in the graph
METHOD: choose which method to generate a graph
Returns:
the specific graph and its adjacency matrix
"""
# Method 1 generates a graph by self-definition. Note that the node label starts from 0 to N-1, while the edges
# could be attributed to weights additionally. If no specific rules are given, then all weights are set to 1.
# Method 1 generates a graph by self-definition
if GRAPHMETHOD == 1:
print(
"Method 1 generates the graph from self-definition using EDGE description"
)
print("Method 1 generates the graph from self-definition using EDGE description")
graph = networkx.Graph()
graph_nodelist = range(N)
graph.add_edges_from([(0, 1), (1, 2), (2, 3), (3, 0)])
graph_adjacency = networkx.to_numpy_matrix(
graph, nodelist=graph_nodelist)
graph_adjacency = networkx.to_numpy_matrix(graph, nodelist=graph_nodelist)
# Method 2 generates a graph by using its adjacency matrix directly
elif GRAPHMETHOD == 2:
print(
"Method 2 generates the graph from networks using adjacency matrix")
graph_adjacency = array(
[[0, 1, 0, 1], [1, 0, 1, 0], [0, 1, 0, 1], [1, 0, 1, 0]])
print("Method 2 generates the graph from networks using adjacency matrix")
graph_adjacency = np.array([[0, 1, 0, 1], [1, 0, 1, 0], [0, 1, 0, 1], [1, 0, 1, 0]])
graph = networkx.Graph(graph_adjacency)
else:
print("Method doesn't exist ")
output_graph = graph
output_graph_adjacency = graph_adjacency
return output_graph, output_graph_adjacency
return graph, graph_adjacency
def H_generator(N, adjacency_matrix):
"""
This function generates the problem-based Hamiltonian, given the graph with its adjacency matrix description.
This function maps the given graph via its adjacency matrix to the corresponding Hamiltiona H_c.
Args:
N: number of qubits, or number of nodes in the graph, or number of parameters in the classical problem
adjacency_matrix: the adjacency matrix generated from the graph encoding the classical problem
Return:
H_graph: the problem-based Hamiltonian H generated from the graph_adjacency matrix for the given graph
H_graph_diag: the real part of the problem-based Hamiltonian H_graph
Returns:
the problem-based Hmiltonian H's list form generated from the graph_adjacency matrix for the given graph
"""
sigma_Z = array([[1, 0], [0, -1]])
H = zeros([2**N, 2**N])
H_list = []
# Generate the Hamiltonian H_c from the graph via its adjacency matrix
for row in range(N):
for col in range(N):
if abs(adjacency_matrix[N - row - 1, N - col - 1]) and row < col:
identity_1 = diag(ones([2**row]))
identity_2 = diag(ones([2**(col - row - 1)]))
identity_3 = diag(ones([2**(N - col - 1)]))
H += adjacency_matrix[N - row - 1, N - col - 1] * kron(
kron(
kron(kron(identity_1, sigma_Z), identity_2), sigma_Z),
identity_3, )
H_graph = H.astype("complex64")
H_graph_diag = diag(H_graph).real
return H_graph, H_graph_diag
if adjacency_matrix[row, col] and row < col:
# Construct the Hamiltonian in the list form for the calculation of expectation value
H_list.append([1.0, 'z' + str(row) + ',z' + str(col)])
return H_list
def main():
# number of qubits or number of nodes in the graph
N = 4
classical_graph, classical_graph_adjacency = generate_graph(N, GRAPHMETHOD=1)
print(classical_graph_adjacency)
pos = networkx.circular_layout(classical_graph)
networkx.draw(classical_graph, pos, width=4, with_labels=True, font_weight='bold')
pyplot.show()
if __name__ == "__main__":
main()
# Copyright (c) 2020 Paddle Quantum Authors. All Rights Reserved.
# Copyright (c) 2020 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -16,7 +16,8 @@
Benchmark
"""
from matplotlib import pyplot
from numpy import max, min, load, ones
from numpy import diag, max, min, load, ones
from paddle_quantum.utils import pauli_str_to_matrix
from paddle_quantum.QAOA.QAOA_Prefunc import generate_graph, H_generator
......@@ -25,24 +26,25 @@ def benchmark_QAOA(classical_graph_adjacency=None, N=None):
This function benchmarks the performance of QAOA. Indeed, it compares its approximate solution obtained
from QAOA with predetermined parameters, such as iteration step = 120 and learning rate = 0.1, to the exact solution
to the classical problem.
"""
# Generate the graph and its adjacency matrix from the classical problem, such as the Max-Cut problem
if all(var is None for var in (classical_graph_adjacency, N)):
N = 4
_, classical_graph_adjacency = generate_graph(N, 1)
# Convert the Hamiltonian's list form to matrix form
H_matrix = pauli_str_to_matrix(H_generator(N, classical_graph_adjacency), N)
H_diag = diag(H_matrix).real
# Compute the exact solution of the original problem to benchmark the performance of QAOA
_, H_problem_diag = H_generator(N, classical_graph_adjacency)
H_max = max(H_diag)
H_min = min(H_diag)
H_graph_max = max(H_problem_diag)
H_graph_min = min(H_problem_diag)
print('H_max:', H_graph_max, ' H_min:', H_graph_min)
print('H_max:', H_max, ' H_min:', H_min)
# Load the data of QAOA
x1 = load('./output/summary_data.npz')
H_min = ones([len(x1['iter'])]) * H_graph_min
H_min = ones([len(x1['iter'])]) * H_min
# Plot it
pyplot.figure(1)
......
# Copyright (c) 2020 Paddle Quantum Authors. All Rights Reserved.
# Copyright (c) 2020 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -16,27 +16,96 @@
main
"""
from paddle_quantum.QAOA.Paddle_QAOA import Paddle_QAOA
from paddle_quantum.QAOA.QAOA_Prefunc import plot_graph, generate_graph
from paddle import fluid
import os
import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
# Random seed for optimizer
SEED = 1
from paddle_quantum.utils import pauli_str_to_matrix
from paddle_quantum.QAOA.Paddle_QAOA import Paddle_QAOA
from paddle_quantum.QAOA.QAOA_Prefunc import generate_graph, H_generator
def main(N=4):
"""
QAOA Main
"""
# number of qubits or number of nodes in the graph
N = 4
classical_graph, classical_graph_adjacency = generate_graph(N, GRAPHMETHOD=1)
print(classical_graph_adjacency)
# Convert the Hamiltonian's list form to matrix form
H_matrix = pauli_str_to_matrix(H_generator(N, classical_graph_adjacency), N)
H_diag = np.diag(H_matrix).real
H_max = np.max(H_diag)
H_min = np.min(H_diag)
print(H_diag)
print('H_max:', H_max, ' H_min:', H_min)
pos = nx.circular_layout(classical_graph)
nx.draw(classical_graph, pos, width=4, with_labels=True, font_weight='bold')
plt.show()
classical_graph, classical_graph_adjacency = generate_graph(N, 1)
print(classical_graph_adjacency)
prob_measure = Paddle_QAOA(classical_graph_adjacency)
# Flatten array[[]] to []
prob_measure = prob_measure.flatten()
# Plot it!
plot_graph(prob_measure, classical_graph, N)
opt_cir = Paddle_QAOA(classical_graph_adjacency, N=4, P=4, METHOD=1, ITR=120, LR=0.1)
# Load the data of QAOA
x1 = np.load('./output/summary_data.npz')
H_min = np.ones([len(x1['iter'])]) * H_min
# Plot loss
loss_QAOA, = plt.plot(x1['iter'], x1['energy'], alpha=0.7, marker='', linestyle="--", linewidth=2, color='m')
benchmark, = plt.plot(x1['iter'], H_min, alpha=0.7, marker='', linestyle=":", linewidth=2, color='b')
plt.xlabel('Number of iteration')
plt.ylabel('Performance of the loss function for QAOA')
plt.legend(handles=[
loss_QAOA,
benchmark
],
labels=[
r'Loss function $\left\langle {\psi \left( {\bf{\theta }} \right)} '
r'\right|H\left| {\psi \left( {\bf{\theta }} \right)} \right\rangle $',
'The benchmark result',
], loc='best')
# Show the plot
plt.show()
with fluid.dygraph.guard():
# Measure the output state of the QAOA circuit for 1024 shots by default
prob_measure = opt_cir.measure(plot=True)
# Find the max value in measured probability of bitstrings
max_prob = max(prob_measure.values())
# Find the bitstring with max probability
solution_list = [result[0] for result in prob_measure.items() if result[1] == max_prob]
print("The output bitstring:", solution_list)
# Draw the graph representing the first bitstring in the solution_list to the MaxCut-like problem
head_bitstring = solution_list[0]
node_cut = ["blue" if head_bitstring[node] == "1" else "red" for node in classical_graph]
edge_cut = [
"solid" if head_bitstring[node_row] == head_bitstring[node_col] else "dashed"
for node_row, node_col in classical_graph.edges()
]
nx.draw(
classical_graph,
pos,
node_color=node_cut,
style=edge_cut,
width=4,
with_labels=True,
font_weight="bold",
)
plt.show()
if __name__ == '__main__':
if __name__ == "__main__":
main()
# Copyright (c) 2020 Paddle Quantum Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
main
"""
from paddle_quantum.QAOA.Paddle_QAOA import Paddle_QAOA
from paddle_quantum.QAOA.QAOA_Prefunc import plot_graph, generate_graph
# Random seed for optimizer
SEED = 1
def main(N=4):
"""
QAOA Main
"""
classical_graph, classical_graph_adjacency = generate_graph(N, 1)
print(classical_graph_adjacency)
prob_measure = Paddle_QAOA(classical_graph_adjacency)
# Flatten array[[]] to []
prob_measure = prob_measure.flatten()
# Plot it!
plot_graph(prob_measure, classical_graph, N)
if __name__ == '__main__':
main()
# Copyright (c) 2020 Paddle Quantum Authors. All Rights Reserved.
# Copyright (c) 2020 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -16,22 +16,20 @@
HGenerator
"""
from numpy import array, kron
from paddle_quantum.utils import random_pauli_str_generator, pauli_str_to_matrix
__all__ = ["H_generator"]
def H_generator():
def H_generator(N):
"""
Generate a Hamiltonian with trivial descriptions
Returns: A Hamiltonian
"""
sigma_I = array([[1, 0], [0, 1]])
sigma_X = array([[0, 1], [1, 0]])
sigma_Y = array([[0, -1j], [1j, 0]])
sigma_Z = array([[1, 0], [0, -1]])
H = 0.4 * kron(sigma_Z, sigma_I) + 0.4 * kron(
sigma_I, sigma_Z) + 0.2 * kron(sigma_X, sigma_X)
# H = numpy.diag([0.1, 0.2, 0.3, 0.4])
return H.astype('complex64')
# 生成用泡利字符串表示的随机哈密顿量
hamiltonian = random_pauli_str_generator(N, terms=10)
print("Random Hamiltonian in Pauli string format = \n", hamiltonian)
# 生成哈密顿量的矩阵信息
H = pauli_str_to_matrix(hamiltonian, N)
return H
# Copyright (c) 2020 Paddle Quantum Authors. All Rights Reserved.
# Copyright (c) 2020 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -16,12 +16,16 @@
Paddle_SSVQE: To learn more about the functions and properties of this application,
you could check the corresponding Jupyter notebook under the Tutorial folder.
"""
import numpy
from paddle.complex import matmul, transpose
from paddle.complex import matmul
from paddle import fluid
from paddle_quantum.circuit import UAnsatz
from paddle_quantum.utils import hermitian
from paddle_quantum.SSVQE.HGenerator import H_generator
SEED = 1
SEED = 14 # 固定随机种子
__all__ = [
"U_theta",
......@@ -30,35 +34,19 @@ __all__ = [
]
# definition of U_theta
def U_theta(theta, N):
"""
U_theta
Quantum Neural Network
"""
# 按照量子比特数量/网络宽度初始化量子神经网络
cir = UAnsatz(N)
# ============== D1=2 ==============
cir.ry(theta[0], 2)
cir.rz(theta[1], 2)
cir.cnot([2, 1])
cir.ry(theta[2], 2)
cir.rz(theta[3], 2)
cir.cnot([2, 1])
# ============== D2=2 ==============
cir.ry(theta[4], 1)
cir.ry(theta[5], 2)
cir.rz(theta[6], 1)
cir.rz(theta[7], 2)
cir.cnot([1, 2])
cir.ry(theta[8], 1)
cir.ry(theta[9], 2)
cir.rz(theta[10], 1)
cir.rz(theta[11], 2)
cir.cnot([1, 2])
return cir.state
# 调用内置的量子神经网络模板
cir.universal_2_qubit_gate(theta)
# 返回量子神经网络所模拟的酉矩阵 U
return cir.U
class Net(fluid.dygraph.Layer):
......@@ -66,68 +54,91 @@ class Net(fluid.dygraph.Layer):
Construct the model net
"""
def __init__(self,
shape,
param_attr=fluid.initializer.Uniform(
low=0.0, high=2 * numpy.pi, seed=SEED),
dtype='float32'):
def __init__(self, shape, param_attr=fluid.initializer.Uniform(low=0.0, high=2 * numpy.pi, seed=SEED),
dtype='float64'):
super(Net, self).__init__()
self.theta = self.create_parameter(
shape=shape, attr=param_attr, dtype=dtype, is_bias=False)
# 初始化 theta 参数列表,并用 [0, 2*pi] 的均匀分布来填充初始值
self.theta = self.create_parameter(shape=shape, attr=param_attr, dtype=dtype, is_bias=False)
# 定义损失函数和前向传播机制
def forward(self, H, N):
"""
Args:
input_state: The initial state with default |0..>
H: The target Hamiltonian
Returns:
The loss.
"""
out_state = U_theta(self.theta, N)
loss_struct = matmul(
matmul(
transpose(
fluid.framework.ComplexVariable(out_state.real,
-out_state.imag),
perm=[1, 0]),
H),
out_state).real
# 施加量子神经网络
U = U_theta(self.theta, N)
# 计算损失函数
loss_struct = matmul(matmul(hermitian(U), H), U).real
# 输入计算基去计算每个子期望值,相当于取 U^dagger*H*U 的对角元
loss_components = [
loss_struct[0][0], loss_struct[1][1], loss_struct[2][2],
loss_struct[0][0],
loss_struct[1][1],
loss_struct[2][2],
loss_struct[3][3]
]
loss = 4 * loss_components[0] + 3 * loss_components[
1] + 2 * loss_components[2] + 1 * loss_components[3]
# 最终加权求和后的损失函数
loss = 4 * loss_components[0] + 3 * loss_components[1] + 2 * loss_components[2] + 1 * loss_components[3]
return loss, loss_components
def Paddle_SSVQE(H, N=2, THETA_SIZE=12, ITR=60, LR=0.2):
def Paddle_SSVQE(H, N=2, THETA_SIZE=15, ITR=50, LR=0.3):
r"""
Paddle_SSVQE
:param H: 哈密顿量
:param N: 量子比特数/量子神经网络的宽度
:param THETA_SIZE: 量子神经网络中参数的数量
:param ITR: 设置训练的总迭代次数
:param LR: 设置学习速率
:return: 哈密顿量的前几个最小特征值
"""
main
"""
# 初始化paddle动态图机制
with fluid.dygraph.guard():
# Harmiltonian preparing
H = fluid.dygraph.to_variable(H)
# 我们需要将 Numpy array 转换成 Paddle 动态图模式中支持的 variable
hamiltonian = fluid.dygraph.to_variable(H)
# net
# 确定网络的参数维度
net = Net(shape=[THETA_SIZE])
# optimizer
opt = fluid.optimizer.AdagradOptimizer(
learning_rate=LR, parameter_list=net.parameters())
# 一般来说,我们利用Adam优化器来获得相对好的收敛,当然你可以改成SGD或者是RMS prop.
opt = fluid.optimizer.AdagradOptimizer(learning_rate=LR, parameter_list=net.parameters())
# gradient descent loop
# 优化循环
for itr in range(1, ITR + 1):
loss, loss_components = net(H, N)
# 前向传播计算损失函数并返回估计的能谱
loss, loss_components = net(hamiltonian, N)
# 在动态图机制下,反向传播极小化损失函数
loss.backward()
opt.minimize(loss)
net.clear_gradients()
print('iter:', itr, 'loss:', '%.4f' % loss.numpy()[0])
# 打印训练结果
if itr % 10 == 0:
print('iter:', itr, 'loss:', '%.4f' % loss.numpy()[0])
return loss_components
def main():
N = 2
H = H_generator(N)
loss_components = Paddle_SSVQE(H)
print('The estimated ground state energy is: ', loss_components[0].numpy())
print('The theoretical ground state energy: ', numpy.linalg.eigh(H)[0][0])
print('The estimated 1st excited state energy is: ', loss_components[1].numpy())
print('The theoretical 1st excited state energy: ', numpy.linalg.eigh(H)[0][1])
print('The estimated 2nd excited state energy is: ', loss_components[2].numpy())
print('The theoretical 2nd excited state energy: ', numpy.linalg.eigh(H)[0][2])
print('The estimated 3rd excited state energy is: ', loss_components[3].numpy())
print('The theoretical 3rd excited state energy: ', numpy.linalg.eigh(H)[0][3])
return loss_components
if __name__ == '__main__':
main()
# Copyright (c) 2020 Paddle Quantum Authors. All Rights Reserved.
# Copyright (c) 2020 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -17,32 +17,28 @@ main
"""
import numpy
from paddle_quantum.SSVQE.HGenerator import H_generator
from paddle_quantum.SSVQE.Paddle_SSVQE import Paddle_SSVQE
def main():
"""
main
"""
hamiltonian = H_generator()
loss_components = Paddle_SSVQE(hamiltonian)
N = 2
H = H_generator(N)
loss_components = Paddle_SSVQE(H)
print('The estimated ground state energy is: ', loss_components[0].numpy())
print('The estimated 1st excited state energy is: ',
loss_components[1].numpy())
print('The estimated 2nd excited state energy is: ',
loss_components[2].numpy())
print('The estimated 3rd excited state energy is: ',
loss_components[3].numpy())
print('The theoretical ground state energy: ',
numpy.linalg.eigh(hamiltonian)[0][0])
print('The theoretical 1st excited state energy: ',
numpy.linalg.eigh(hamiltonian)[0][1])
print('The theoretical 2nd excited state energy: ',
numpy.linalg.eigh(hamiltonian)[0][2])
print('The theoretical 3rd excited state energy: ',
numpy.linalg.eigh(hamiltonian)[0][3])
print('The theoretical ground state energy: ', numpy.linalg.eigh(H)[0][0])
print('The estimated 1st excited state energy is: ', loss_components[1].numpy())
print('The theoretical 1st excited state energy: ', numpy.linalg.eigh(H)[0][1])
print('The estimated 2nd excited state energy is: ', loss_components[2].numpy())
print('The theoretical 2nd excited state energy: ', numpy.linalg.eigh(H)[0][2])
print('The estimated 3rd excited state energy is: ', loss_components[3].numpy())
print('The theoretical 3rd excited state energy: ', numpy.linalg.eigh(H)[0][3])
if __name__ == '__main__':
......
# Copyright (c) 2020 Paddle Quantum Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
main
"""
import numpy
from paddle_quantum.SSVQE.HGenerator import H_generator
from paddle_quantum.SSVQE.Paddle_SSVQE import Paddle_SSVQE
def main():
"""
main
"""
hamiltonian = H_generator()
loss_components = Paddle_SSVQE(hamiltonian)
print('The estimated ground state energy is: ', loss_components[0].numpy())
print('The estimated 1st excited state energy is: ',
loss_components[1].numpy())
print('The estimated 2nd excited state energy is: ',
loss_components[2].numpy())
print('The estimated 3rd excited state energy is: ',
loss_components[3].numpy())
print('The theoretical ground state energy: ',
numpy.linalg.eigh(hamiltonian)[0][0])
print('The theoretical 1st excited state energy: ',
numpy.linalg.eigh(hamiltonian)[0][1])
print('The theoretical 2nd excited state energy: ',
numpy.linalg.eigh(hamiltonian)[0][2])
print('The theoretical 3rd excited state energy: ',
numpy.linalg.eigh(hamiltonian)[0][3])
if __name__ == '__main__':
main()
# Copyright (c) 2020 Paddle Quantum Authors. All Rights Reserved.
# Copyright (c) 2020 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -18,14 +18,15 @@ you could check the corresponding Jupyter notebook under the Tutorial folder.
"""
import os
import platform
from numpy import concatenate
from numpy import pi as PI
from numpy import savez, zeros
from numpy import savez
from paddle import fluid
from paddle.complex import matmul, transpose
from paddle_quantum.circuit import UAnsatz
from paddle_quantum.VQE.benchmark import benchmark_result
from paddle_quantum.VQE.chemistrysub import H2_generator
__all__ = [
"U_theta",
......@@ -34,27 +35,28 @@ __all__ = [
]
def U_theta(theta, input_state, N, D):
def U_theta(theta, Hamiltonian, N, D):
"""
Circuit
Quantum Neural Network
"""
cir = UAnsatz(N, input_state=input_state)
# 按照量子比特数量/网络宽度初始化量子神经网络
cir = UAnsatz(N)
# 内置的 {R_y + CNOT} 电路模板
cir.real_entangled_layer(theta[:D], D)
# 铺上最后一列 R_y 旋转门
for i in range(N):
cir.rz(theta=theta[0][0][i], which_qubit=i + 1)
cir.ry(theta=theta[0][1][i], which_qubit=i + 1)
cir.rz(theta=theta[0][2][i], which_qubit=i + 1)
cir.ry(theta=theta[D][i][0], which_qubit=i)
for repeat in range(D):
for i in range(1, N):
cir.cnot(control=[i, i + 1])
# 量子神经网络作用在默认的初始态 |0000>上
cir.run_state_vector()
for i in range(N):
cir.ry(theta=theta[repeat][0][i], which_qubit=i + 1)
cir.ry(theta=theta[repeat][1][i], which_qubit=i + 1)
cir.rz(theta=theta[repeat][2][i], which_qubit=i + 1)
# 计算给定哈密顿量的期望值
expectation_val = cir.expecval(Hamiltonian)
return cir.state
return expectation_val
class StateNet(fluid.dygraph.Layer):
......@@ -62,85 +64,92 @@ class StateNet(fluid.dygraph.Layer):
Construct the model net
"""
def __init__(
self,
shape,
param_attr=fluid.initializer.Uniform(
low=0.0, high=2 * PI),
dtype="float32", ):
def __init__(self, shape, param_attr=fluid.initializer.Uniform(low=0.0, high=2 * PI), dtype="float64"):
super(StateNet, self).__init__()
self.theta = self.create_parameter(
shape=shape, attr=param_attr, dtype=dtype, is_bias=False)
def forward(self, input_state, H, N, D):
"""
:param input_state: The initial state with default |0..>, 'mat'
:param H: The target Hamiltonian, 'mat'
:return: The loss, 'float'
"""
# 初始化 theta 参数列表,并用 [0, 2*pi] 的均匀分布来填充初始值
self.theta = self.create_parameter(shape=shape, attr=param_attr, dtype=dtype, is_bias=False)
out_state = U_theta(self.theta, input_state, N, D)
loss = matmul(
matmul(out_state, H),
transpose(
fluid.framework.ComplexVariable(out_state.real,
-out_state.imag),
perm=[1, 0], ), )
# 定义损失函数和前向传播机制
def forward(self, Hamiltonian, N, D):
# 计算损失函数/期望值
loss = U_theta(self.theta, Hamiltonian, N, D)
return loss.real
return loss
def Paddle_VQE(Hamiltonian, N, D=1, ITR=120, LR=0.15):
def Paddle_VQE(Hamiltonian, N, D=2, ITR=80, LR=0.2):
r"""
Main Learning network using dynamic graph
:param Hamiltonian:
:param N:
:param D: 设置量子神经网络中重复计算模块的深度 Depth
:param ITR: 设置训练的总迭代次数
:param LR: 设置学习速率
:return: return: Plot or No return
"""
Main Learning network using dynamic graph
:return: Plot or No return
"""
with fluid.dygraph.guard():
# initial state preparing
_initial_state_np = concatenate(
([[1.0]], zeros([1, 2**N - 1])), axis=1).astype("complex64")
initial_state = fluid.dygraph.to_variable(_initial_state_np)
# Store H
H = fluid.dygraph.to_variable(Hamiltonian)
# net
net = StateNet(shape=[D + 1, 3, N])
# 初始化paddle动态图机制
with fluid.dygraph.guard():
# 确定网络的参数维度
net = StateNet(shape=[D + 1, N, 1])
# optimizer
opt = fluid.optimizer.AdamOptimizer(
learning_rate=LR, parameter_list=net.parameters())
# 一般来说,我们利用Adam优化器来获得相对好的收敛,当然你可以改成SGD或者是RMS prop.
opt = fluid.optimizer.AdamOptimizer(learning_rate=LR, parameter_list=net.parameters())
# gradient descent loop
# 记录优化结果
summary_iter, summary_loss = [], []
# 优化循环
for itr in range(1, ITR + 1):
# forward calc, loss
loss = net(initial_state, H, N, D)
# backward calculation for gradient value
# 前向传播计算损失函数
loss = net(Hamiltonian, N, D)
# 在动态图机制下,反向传播极小化损失函数
loss.backward()
# using gradients to update the variable theta
opt.minimize(loss)
# clear gradients
net.clear_gradients()
summary_loss.append(loss[0][0].numpy())
# 更新优化结果
summary_loss.append(loss.numpy())
summary_iter.append(itr)
print("iter:", itr, "loss:", "%.4f" % loss.numpy())
print("iter:", itr, "Ground state energy:",
"%.4f Ha" % loss.numpy())
# print('theta:', net.parameters()[0].numpy())
# 打印结果
if itr % 20 == 0:
print("iter:", itr, "loss:", "%.4f" % loss.numpy())
print("iter:", itr, "Ground state energy:", "%.4f Ha" % loss.numpy())
# 储存训练结果到 output 文件夹
os.makedirs("output", exist_ok=True)
savez("./output/summary_data", iter=summary_iter, energy=summary_loss)
def main():
"""
:return:
"""
# Read data from built-in function or xyz file depending on OS
sysStr = platform.system()
if sysStr == 'Windows':
# Windows does not support SCF, using H2_generator instead
print('Molecule data will be read from built-in function')
hamiltonian, N = H2_generator()
print('Read Process Finished')
elif sysStr in ('Linux', 'Darwin'):
# for linux only
from paddle_quantum.VQE.chemistrygen import read_calc_H
# Hamiltonian and cnot module preparing, must be executed under Linux
# Read the H2 molecule data
print('Molecule data will be read from h2.xyz')
hamiltonian, N = read_calc_H(geo_fn='h2.xyz')
print('Read Process Finished')
else:
print("Don't support this OS.")
Paddle_VQE(hamiltonian, N)
benchmark_result()
if __name__ == "__main__":
if __name__ == '__main__':
main()
# Copyright (c) 2020 Paddle Quantum Authors. All Rights Reserved.
# Copyright (c) 2020 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -16,24 +16,26 @@
benchmark the result
"""
import platform
import matplotlib.pyplot as plt
import numpy
from paddle_quantum.utils import pauli_str_to_matrix
from paddle_quantum.VQE.chemistrysub import H2_generator
__all__ = [
"benchmark_result",
]
def benchmark_result():
"""
benchmark using numpy
"""
def benchmark_result():
# Read H and calc using numpy
sysStr = platform.system()
if sysStr == 'Windows':
# Windows does not support SCF, using H2_generator instead
print('Molecule data will be read from built-in function')
_H, _, _ = H2_generator()
Hamiltonian, N = H2_generator()
print('Read Process Finished')
elif sysStr == 'Linux' or sysStr == 'Darwin':
# for linux only
......@@ -41,51 +43,32 @@ def benchmark_result():
# Harmiltonian and cnot module preparing, must be executed under Linux
# Read the H2 molecule data
print('Molecule data will be read from h2.xyz')
_H, _, _ = read_calc_H(geo_fn='h2.xyz')
Hamiltonian, N = read_calc_H(geo_fn='h2.xyz')
print('Read Process Finished')
else:
print("Don't support this os.")
# plot
x1 = numpy.load('./output/summary_data.npz')
result = numpy.load('./output/summary_data.npz')
eig_val, eig_state = numpy.linalg.eig(_H)
min_eig_H = numpy.min(eig_val)
min_loss = numpy.ones([len(x1['iter'])]) * min_eig_H
eig_val, eig_state = numpy.linalg.eig(pauli_str_to_matrix(Hamiltonian, N))
min_eig_H = numpy.min(eig_val.real)
min_loss = numpy.ones([len(result['iter'])]) * min_eig_H
plt.figure(1)
func1, = plt.plot(
x1['iter'],
x1['energy'],
alpha=0.7,
marker='',
linestyle="--",
color='m')
func_min, = plt.plot(
x1['iter'], min_loss, alpha=0.7, marker='', linestyle=":", color='b')
func1, = plt.plot(result['iter'], result['energy'], alpha=0.7, marker='', linestyle="-", color='r')
func_min, = plt.plot(result['iter'], min_loss, alpha=0.7, marker='', linestyle=":", color='b')
plt.xlabel('Number of iteration')
plt.ylabel('Energy (Ha)')
plt.legend(
handles=[func1, func_min],
plt.legend(handles=[
func1,
func_min
],
labels=[
r'$\left\langle {\psi \left( {\bf{\theta }} \right)} '
r'\right|H\left| {\psi \left( {\bf{\theta }} \right)} \right\rangle $',
'Minimum energy',
],
loc='best')
r'$\left\langle {\psi \left( {\theta } \right)} '
r'\right|H\left| {\psi \left( {\theta } \right)} \right\rangle $',
'Ground-state energy',
], loc='best')
# output the picture
# plt.savefig("vqe.png", bbox_inches='tight', dpi=300)
plt.show()
def main():
"""
Call the real benchmark function
"""
benchmark_result()
if __name__ == '__main__':
main()
# Copyright (c) 2020 Paddle Quantum Authors. All Rights Reserved.
# Copyright (c) 2020 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -28,6 +28,32 @@ __all__ = [
]
# todo
def Hamiltonian_str_convert(qubit_op):
'''
转换提供的哈密顿量信息成为我们熟悉的泡利字符串
'''
info_dic = qubit_op.terms
def process_tuple(tup):
if len(tup) == 0:
return 'i0'
else:
res = ''
for ele in tup:
res += ele[1].lower()
res += str(ele[0])
res += ','
return res[:-1]
H_info = []
for key, value in qubit_op.terms.items():
H_info.append([value.real, process_tuple(key)])
return H_info
def calc_H_rho_from_qubit_operator(qubit_op, n_qubits):
"""
Generate a Hamiltonian from QubitOperator
......@@ -63,8 +89,8 @@ def calc_H_rho_from_qubit_operator(qubit_op, n_qubits):
rho = scipy.linalg.expm(-1 * beta *
H) / trace(scipy.linalg.expm(-1 * beta * H))
return H.astype('complex64'), rho.astype(
'complex64') # the returned dic will have 2 ** n value
return H.astype('complex128'), rho.astype(
'complex128') # the returned dic will have 2 ** n value
def read_calc_H(geo_fn, multiplicity=1, charge=0):
......@@ -91,7 +117,6 @@ def read_calc_H(geo_fn, multiplicity=1, charge=0):
charge)
openfermionpyscf.run_pyscf(mol)
terms_molecular_hamiltonian = mol.get_molecular_hamiltonian(
)
fermionic_hamiltonian = openfermion.transforms.get_fermion_operator(
......@@ -99,10 +124,9 @@ def read_calc_H(geo_fn, multiplicity=1, charge=0):
qubit_op = openfermion.transforms.jordan_wigner(
fermionic_hamiltonian)
# calc H, rho
H, rho = calc_H_rho_from_qubit_operator(qubit_op, mol.n_qubits)
return H, rho, mol.n_qubits
# calc H
Hamiltonian = Hamiltonian_str_convert(qubit_op)
return Hamiltonian, mol.n_qubits
def main():
......@@ -112,10 +136,8 @@ def main():
"""
filename = 'h2.xyz'
H, rho, N = read_calc_H(geo_fn=filename)
H, N = read_calc_H(geo_fn=filename)
print('H', H)
print("-------------------------- ")
print('rho', rho)
if __name__ == '__main__':
......
# Copyright (c) 2020 Paddle Quantum Authors. All Rights Reserved.
# Copyright (c) 2020 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -42,7 +42,7 @@ def H_generator():
sigma_I, sigma_Z) + 0.2 * kron(sigma_X, sigma_X)
rho = scipy.linalg.expm(-1 * beta *
H) / trace(scipy.linalg.expm(-1 * beta * H))
return H.astype('complex64'), rho.astype('complex64')
return H.astype('complex128'), rho.astype('complex128')
def H2_generator():
......@@ -56,22 +56,39 @@ def H2_generator():
sigma_Z = array([[1, 0], [0, -1]])
sigma_X = array([[0, 1], [1, 0]])
sigma_Y = array([[0, -1j], [1j, 0]])
H = (-0.04207897647782276) * kron(kron(kron(sigma_I, sigma_I), sigma_I), sigma_I) \
+ (0.17771287465139946) * kron(kron(kron(sigma_Z, sigma_I), sigma_I), sigma_I) \
+ (0.1777128746513994) * kron(kron(kron(sigma_I, sigma_Z), sigma_I), sigma_I) \
+ (-0.24274280513140462) * kron(kron(kron(sigma_I, sigma_I), sigma_Z), sigma_I) \
+ (-0.24274280513140462) * kron(kron(kron(sigma_I, sigma_I), sigma_I), sigma_Z) \
+ (0.17059738328801052) * kron(kron(kron(sigma_Z, sigma_Z), sigma_I), sigma_I) \
+ (0.04475014401535161) * kron(kron(kron(sigma_Y, sigma_X), sigma_X), sigma_Y) \
+ (-0.04475014401535161) * kron(kron(kron(sigma_Y, sigma_Y), sigma_X), sigma_X) \
+ (-0.04475014401535161) * kron(kron(kron(sigma_X, sigma_X), sigma_Y), sigma_Y) \
+ (0.04475014401535161) * kron(kron(kron(sigma_X, sigma_Y), sigma_Y), sigma_X) \
+ (0.12293305056183798) * kron(kron(kron(sigma_Z, sigma_I), sigma_Z), sigma_I) \
+ (0.1676831945771896) * kron(kron(kron(sigma_Z, sigma_I), sigma_I), sigma_Z) \
+ (0.1676831945771896) * kron(kron(kron(sigma_I, sigma_Z), sigma_Z), sigma_I) \
+ (0.12293305056183798) * kron(kron(kron(sigma_I, sigma_Z), sigma_I), sigma_Z) \
+ (0.17627640804319591) * kron(kron(kron(sigma_I, sigma_I), sigma_Z), sigma_Z)
rho = scipy.linalg.expm(-1 * beta *
H) / trace(scipy.linalg.expm(-1 * beta * H))
# H = (-0.04207897647782276) * kron(kron(kron(sigma_I, sigma_I), sigma_I), sigma_I) \
# + (0.17771287465139946) * kron(kron(kron(sigma_Z, sigma_I), sigma_I), sigma_I) \
# + (0.1777128746513994) * kron(kron(kron(sigma_I, sigma_Z), sigma_I), sigma_I) \
# + (-0.24274280513140462) * kron(kron(kron(sigma_I, sigma_I), sigma_Z), sigma_I) \
# + (-0.24274280513140462) * kron(kron(kron(sigma_I, sigma_I), sigma_I), sigma_Z) \
# + (0.17059738328801052) * kron(kron(kron(sigma_Z, sigma_Z), sigma_I), sigma_I) \
# + (0.04475014401535161) * kron(kron(kron(sigma_Y, sigma_X), sigma_X), sigma_Y) \
# + (-0.04475014401535161) * kron(kron(kron(sigma_Y, sigma_Y), sigma_X), sigma_X) \
# + (-0.04475014401535161) * kron(kron(kron(sigma_X, sigma_X), sigma_Y), sigma_Y) \
# + (0.04475014401535161) * kron(kron(kron(sigma_X, sigma_Y), sigma_Y), sigma_X) \
# + (0.12293305056183798) * kron(kron(kron(sigma_Z, sigma_I), sigma_Z), sigma_I) \
# + (0.1676831945771896) * kron(kron(kron(sigma_Z, sigma_I), sigma_I), sigma_Z) \
# + (0.1676831945771896) * kron(kron(kron(sigma_I, sigma_Z), sigma_Z), sigma_I) \
# + (0.12293305056183798) * kron(kron(kron(sigma_I, sigma_Z), sigma_I), sigma_Z) \
# + (0.17627640804319591) * kron(kron(kron(sigma_I, sigma_I), sigma_Z), sigma_Z)
H = [
[-0.04207897647782277, 'i0'],
[0.17771287465139946, 'z0'],
[0.1777128746513994, 'z1'],
[-0.2427428051314046, 'z2'],
[-0.24274280513140462, 'z3'],
[0.17059738328801055, 'z0,z1'],
[0.04475014401535163, 'y0,x1,x2,y3'],
[-0.04475014401535163, 'y0,y1,x2,x3'],
[-0.04475014401535163, 'x0,x1,y2,y3'],
[0.04475014401535163, 'x0,y1,y2,x3'],
[0.12293305056183797, 'z0,z2'],
[0.1676831945771896, 'z0,z3'],
[0.1676831945771896, 'z1,z2'],
[0.12293305056183797, 'z1,z3'],
[0.1762764080431959, 'z2,z3']
]
# rho = scipy.linalg.expm(-1 * beta *
# H) / trace(scipy.linalg.expm(-1 * beta * H))
N = 4
return H.astype('complex64'), rho.astype('complex64'), N
return H, N
# Copyright (c) 2020 Paddle Quantum Authors. All Rights Reserved.
# Copyright (c) 2020 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -28,28 +28,28 @@ def main():
Main Learning network using dynamic graph
:return: Plot or No return
"""
# Read data from built-in function or xyz file depending on OS
sysStr = platform.system()
if sysStr == 'Windows':
# Windows does not support SCF, using H2_generator instead
print('Molecule data will be read from built-in function')
_H, _, N = H2_generator()
hamiltonian, N = H2_generator()
print('Read Process Finished')
elif sysStr in ('Linux', 'Darwin'):
# for linux only
from paddle_quantum.VQE.chemistrygen import read_calc_H
# Harmiltonian and cnot module preparing, must be executed under Linux
# Hamiltonian and cnot module preparing, must be executed under Linux
# Read the H2 molecule data
print('Molecule data will be read from h2.xyz')
_H, _, N = read_calc_H(geo_fn='h2.xyz')
hamiltonian, N = read_calc_H(geo_fn='h2.xyz')
print('Read Process Finished')
else:
print("Don't support this OS.")
Paddle_VQE(_H, N)
Paddle_VQE(hamiltonian, N)
benchmark_result()
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
# Copyright (c) 2020 Paddle Quantum Authors. All Rights Reserved.
# Copyright (c) 2020 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -12,6 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""
r"""
Paddle Quantum Library
"""
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
paddlepaddle>=1.8.0
networkx
matplotlib
\ No newline at end of file
paddlepaddle>=1.8.3
networkx>=2.4
matplotlib>=3.3.0
interval>=1.0.0
progressbar>=2.5
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册