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

update to v1.1.0

上级 3581ccef
# Paddle Quantum (量桨) # 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(量桨)是基于百度飞桨开发的量子机器学习工具集,支持量子神经网络的搭建与训练,提供易用的量子机器学习开发套件与量子优化、量子化学等前沿量子应用工具集,使得百度飞桨也因此成为国内首个目前也是唯一一个支持量子机器学习的深度学习框架。 Paddle Quantum(量桨)是基于百度飞桨开发的量子机器学习工具集,支持量子神经网络的搭建与训练,提供易用的量子机器学习开发套件与量子优化、量子化学等前沿量子应用工具集,使得百度飞桨也因此成为国内首个目前也是唯一一个支持量子机器学习的深度学习框架。
![](https://release-data.cdn.bcebos.com/Paddle%20Quantum.png) ![](https://release-data.cdn.bcebos.com/Paddle%20Quantum.png)
量桨建立起了人工智能与量子计算的桥梁,不但可以快速实现量子神经网络的搭建与训练,还提供易用的量子机器学习开发套件与量子优化、量子化学等前沿量子应用工具集,并提供多项自研量子机器学习应用。通过百度飞桨深度学习平台赋能量子计算,量桨为领域内的科研人员以及开发者便捷地开发量子人工智能的应用提供了强有力的支撑,同时也为广大量子计算爱好者提供了一条可行的学习途径。 量桨建立起了人工智能与量子计算的桥梁,不但可以快速实现量子神经网络的搭建与训练,还提供易用的量子机器学习开发套件与量子优化、量子化学等前沿量子应用工具集,并提供多项自研量子机器学习应用。通过百度飞桨深度学习平台赋能量子计算,量桨为领域内的科研人员以及开发者便捷地开发量子人工智能的应用提供了强有力的支撑,同时也为广大量子计算爱好者提供了一条可行的学习途径。
## 特色 ## 特色
- 易用性:提供简洁的神经网络搭建与丰富的量子机器学习案例。 - 易用性
- 通用性与拓展性:支持常用量子电路模型,提供多项优化工具。 - 高效搭建量子神经网络
- 特色工具集:提供量子优化、量子化学等前沿量子应用工具集,自研多项量子机器学习应用。 - 多种量子神经网络模板
- 丰富量子算法教程(10+用例)
- 可拓展性
- 支持通用量子电路模型
- 高性能模拟器支持20多个量子比特的模拟运算
- 提供多种优化工具和 GPU 加速
- 特色工具集
- 提供组合优化和量子化学等前沿领域的计算工具箱
- 自研多种量子机器学习算法
## 安装步骤 ## 安装步骤
### Install PaddlePaddle ### 安装 PaddlePaddle
请参考 [PaddlePaddle](https://www.paddlepaddle.org.cn/documentation/docs/zh/beginners_guide/index_cn.html) 安装配置页面。此项目需求 PaddlePaddle 1.8.0 或更高版本。
请参考 [PaddlePaddle](https://www.paddlepaddle.org.cn/install/quick) 安装配置页面。此项目需求 PaddlePaddle 1.8.3 或更高版本。
### 下载 Paddle Quantum 并安装 ### 下载 Paddle Quantum 并安装
...@@ -34,30 +55,33 @@ cd quantum ...@@ -34,30 +55,33 @@ cd quantum
pip install -e . pip install -e .
``` ```
### 或使用 requirements.txt 安装依赖包 ### 或使用 requirements.txt 安装依赖包
```bash ```bash
python -m pip install --upgrade -r requirements.txt python -m pip install --upgrade -r requirements.txt
``` ```
### 使用 openfermion 读取xyz 描述文件 (仅可在linux下安装使用) ### 使用 openfermion 读取 xyz 描述文件
VQE中调用 openfermion 读取分子xyz文件并计算,因此需要安装 openfermion 和 openfermionpyscf。
> 仅在 macOS 和 linux 下可以使用 openfermion 读取 xyz 描述文件。
VQE中调用 openfermion 读取分子 xyz 文件并计算,因此需要安装 openfermion 和 openfermionpyscf。
```bash ```bash
pip install openfermion pip install openfermion
pip install openfermionpyscf pip install openfermionpyscf
``` ```
### 运行 ### 运行
现在,可以试着运行一段程序来验证量桨是否已安装成功。这里我们运行量桨提供的量子近似优化算法 (QAOA) 的例子。
```bash ```bash
cd paddle_quantum/QAOA/example cd paddle_quantum/QAOA/example
python main.py python main.py
``` ```
> 关于 QAOA 的介绍可以参考我们的 [QAOA 教程](./tutorial/QAOA)。
## 入门与开发 ## 入门与开发
...@@ -65,65 +89,93 @@ python main.py ...@@ -65,65 +89,93 @@ python main.py
量子计算是由量子力学与计算理论交叉而成的全新计算模型,具有强大的信息处理优势和广阔的应用前景,被视作未来计算技术的心脏。量子计算的相关介绍与入门知识可以参考 [1-3]。 量子计算是由量子力学与计算理论交叉而成的全新计算模型,具有强大的信息处理优势和广阔的应用前景,被视作未来计算技术的心脏。量子计算的相关介绍与入门知识可以参考 [1-3]。
量子机器学习是一门结合量子计算与机器学习的交叉学科,一方面利用量子计算的信息处理优势促进人工智能的发展,另一方面也利用现有的人工智能的技术突破量子计算的研发瓶颈。关于量子机器学习的入门资料可以参考 [4-6]。Paddle Quantum(量桨)建立起了人工智能与量子计算的桥梁,为量子机器学习领域的研发提供强有力的支撑,也提供了丰富的案例供开发者学习。 量子机器学习是一门结合量子计算与机器学习的交叉学科,一方面利用量子计算的信息处理优势促进人工智能的发展,另一方面也利用现有的人工智能的技术突破量子计算的研发瓶颈。关于量子机器学习的入门资料可以参考 [4-6]。
这里,我们提供了一份[**入门手册**](./introduction)方便用户快速上手 Paddle Quantum。目前支持 PDF 阅读和运行 Jupyter Notebook 两种方式。内容上,该手册包括以下几个方面:
- Paddle Quantum 的详细安装教程
- 量子计算的基础知识介绍
- Paddle Quantum 的使用介绍
- PaddlePaddle 飞桨优化器使用教程
- 具体的量子机器学习案例—VQE
### 案例入门 ### 案例入门
特别的,我们提供了涵盖量子优化、量子化学、量子机器学习等多个领域的案例供大家学习。比如: Paddle Quantum(量桨)建立起了人工智能与量子计算的桥梁,为量子机器学习领域的研发提供强有力的支撑,也提供了丰富的案例供开发者学习。
- 量子近似优化(QAOA),完成安装步骤后打开 tutorial\QAOA.ipynb 即可进行研究学习。
```bash 在这里,我们提供了涵盖量子优化、量子化学、量子机器学习等多个领域的案例供大家学习。与[入门手册](./introduction)类似,每个教程目前支持 PDF 阅读和运行 Jupyter Notebook 两种方式。我们推荐用户下载 Notebook 后,本地运行进行实践。
cd tutorial
jupyter notebook QAOA.ipynb
```
- 量子特征求解器(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)
``` 此外,Paddle Quantum 也支持在 GPU 上进行量子机器学习的训练,具体的方法请参考案例:[在 GPU 上使用 Paddle Quantum](./tutorial/GPU)
cd tutorial
jupyter notebook VQE.ipynb
```
### 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 ## 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)] [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 \ 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"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
...@@ -16,8 +16,9 @@ ...@@ -16,8 +16,9 @@
HGenerator HGenerator
""" """
from numpy import array, kron, trace
import scipy import scipy
from numpy import trace as np_trace
from paddle_quantum.utils import pauli_str_to_matrix
__all__ = ["H_generator", ] __all__ = ["H_generator", ]
...@@ -27,16 +28,18 @@ def H_generator(): ...@@ -27,16 +28,18 @@ def H_generator():
Generate a Hamiltonian with trivial descriptions Generate a Hamiltonian with trivial descriptions
Returns: A Hamiltonian 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]]) N_SYS_B = 3 # 用于生成吉布斯态的子系统B的量子比特数
sigma_Z = array([[1, 0], [0, -1]]) hamiltonian = pauli_str_to_matrix(H, N_SYS_B)
H = (-kron(kron(sigma_Z, sigma_Z), sigma_I) - kron( # 生成理想情况下的目标吉布斯态 rho
kron(sigma_I, sigma_Z), sigma_Z) - kron( beta = 1.5 # 设置逆温度参数 beta
kron(sigma_Z, sigma_I), sigma_Z)) rho_G = scipy.linalg.expm(-1 * beta * hamiltonian) / np_trace(scipy.linalg.expm(-1 * beta * hamiltonian))
rho = scipy.linalg.expm(-1 * beta * # 设置成 Paddle quantum 所支持的数据类型
H) / trace(scipy.linalg.expm(-1 * beta * H)) hamiltonian = hamiltonian.astype("complex128")
rho_G = rho_G.astype("complex128")
return H.astype("complex64"), rho.astype("complex64") 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"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
...@@ -16,17 +16,18 @@ ...@@ -16,17 +16,18 @@
Paddle_GIBBS Paddle_GIBBS
""" """
from numpy import concatenate, zeros import scipy
from numpy import pi as PI from numpy import pi as PI
from paddle import fluid 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.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 from paddle_quantum.GIBBS.HGenerator import H_generator
SEED = 1 SEED = 14 # 固定随机种子
__all__ = [ __all__ = [
"U_theta", "U_theta",
...@@ -35,29 +36,25 @@ __all__ = [ ...@@ -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: Quantum Neural Network
:param input_state:
:return:
""" """
cir = UAnsatz(N, input_state=input_state) # 按照量子比特数量/网络宽度初始化量子神经网络
for i in range(N): cir = UAnsatz(N)
cir.rx(theta=theta[0][0][i], which_qubit=i + 1)
cir.ry(theta=theta[0][1][i], which_qubit=i + 1) # 内置的 {R_y + CNOT} 电路模板
cir.rx(theta=theta[0][2][i], which_qubit=i + 1) cir.real_entangled_layer(theta[:D], D)
for repeat in range(D): # 铺上最后一列 R_y 旋转门
for i in range(1, N): for i in range(N):
cir.cnot(control=[i, i + 1]) 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) final_state = cir.run_density_matrix(initial_state)
# cir.ry(theta=theta[repeat][1][i], which_qubit=i + 1)
# cir.ry(theta=theta[repeat][2][i], which_qubit=i + 1)
return cir.state return final_state
class Net(fluid.dygraph.Layer): class Net(fluid.dygraph.Layer):
...@@ -65,96 +62,83 @@ class Net(fluid.dygraph.Layer): ...@@ -65,96 +62,83 @@ class Net(fluid.dygraph.Layer):
Construct the model net Construct the model net
""" """
def __init__(self, def __init__(self, N, shape, param_attr=fluid.initializer.Uniform(low=0.0, high=2 * PI, seed=SEED),
shape, dtype='float64'):
param_attr=fluid.initializer.Uniform(
low=0.0, high=PI, seed=SEED),
dtype='float32'):
super(Net, self).__init__() super(Net, self).__init__()
self.theta = self.create_parameter( # 初始化 theta 参数列表,并用 [0, 2*pi] 的均匀分布来填充初始值
shape=shape, attr=param_attr, dtype=dtype, is_bias=False) 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): # 初始化 rho = |0..0><0..0| 的密度矩阵
""" self.initial_state = fluid.dygraph.to_variable(density_op(N))
Args:
input_state: The initial state with default |0..> # 定义损失函数和前向传播机制
H: The target Hamiltonian def forward(self, H, N, N_SYS_B, beta, D):
Returns: # 施加量子神经网络
The loss. rho_AB = U_theta(self.initial_state, self.theta, N, D)
"""
# 计算偏迹 partial trace 来获得子系统B所处的量子态 rho_B
out_state = U_theta(self.theta, input_state, N, D) rho_B = partial_trace(rho_AB, 2 ** (N - N_SYS_B), 2 ** (N_SYS_B), 1)
# 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)
rho_B_squre = matmul(rho_B, rho_B) rho_B_squre = matmul(rho_B, rho_B)
loss1 = (trace(matmul(rho_B, H))).real loss1 = (trace(matmul(rho_B, H))).real
loss2 = (trace(rho_B_squre)).real * 2 loss2 = (trace(rho_B_squre)).real * 2 / beta
loss3 = -(trace(matmul(rho_B_squre, rho_B))).real / 2 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 return loss, rho_B
# print('loss_iminary_part: ', loss.numpy()[1])
return loss - 3 / 2, 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 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(): with fluid.dygraph.guard():
# initial state preparing # 我们需要将 Numpy array 转换成 Paddle 动态图模式中支持的 variable
_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
H = fluid.dygraph.to_variable(hamiltonian) H = fluid.dygraph.to_variable(hamiltonian)
# net # 确定网络的参数维度
net = Net(shape=[D + 1, 3, N]) net = Net(N, shape=[D + 1, N, 1])
# optimizer # 一般来说,我们利用Adam优化器来获得相对好的收敛,当然你可以改成SGD或者是RMS prop.
opt = fluid.optimizer.AdamOptimizer( opt = fluid.optimizer.AdamOptimizer(learning_rate=LR, parameter_list=net.parameters())
learning_rate=LR, parameter_list=net.parameters())
# gradient descent loop # 优化循环
for itr in range(1, ITR + 1): 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() loss.backward()
opt.minimize(loss) opt.minimize(loss)
net.clear_gradients() net.clear_gradients()
# 转换成 Numpy array 用以计算量子态的保真度 F(rho_B, rho_G)
rho_B = rho_B.numpy() rho_B = rho_B.numpy()
fid = state_fidelity(rho_B, rho_G)
if rho is not None: # 打印训练结果
fid = compute_fid(rho_B, rho) if itr % 5 == 0:
print('iter:', itr, 'loss:', '%.4f' % loss.numpy(), 'fid:', print('iter:', itr, 'loss:', '%.4f' % loss.numpy(), 'fid:', '%.4f' % fid)
'%.4f' % fid)
return rho_B return rho_B
def main(): def main():
"""
main
"""
# gibbs Hamiltonian preparing # gibbs Hamiltonian preparing
hamiltonian, rho = H_generator() hamiltonian, rho_G = H_generator()
rho_B = Paddle_GIBBS(hamiltonian, rho) rho_B = Paddle_GIBBS(hamiltonian, rho_G)
print(rho_B) 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"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
...@@ -16,13 +16,29 @@ ...@@ -16,13 +16,29 @@
main 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 from paddle_quantum.GIBBS.Paddle_GIBBS import Paddle_GIBBS
def main(): 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) 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"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with 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 ...@@ -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. you could check the corresponding Jupyter notebook under the Tutorial folder.
""" """
import os
from paddle import fluid 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.circuit import UAnsatz
from paddle_quantum.utils import pauli_str_to_matrix
from paddle_quantum.QAOA.QAOA_Prefunc import generate_graph, H_generator 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 # Random seed for optimizer
SEED = 1 SEED = 1024
__all__ = [ __all__ = [
"circuit_QAOA", "circuit_QAOA",
...@@ -39,48 +39,46 @@ __all__ = [ ...@@ -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: 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, one block is 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 and the other is 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. acting on each qubit. It outputs the final state of the QAOA circuit.
Args: Args:
theta: parameters to be optimized in the QAOA circuit 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 adjacency_matrix: the adjacency matrix of the graph encoding the classical problem
in the computational basis $|0\rangle, |1\rangle$ N: number of qubits, or equivalently, the number of parameters in the original classical problem
adjacency_matrix: the adjacency matrix of the graph encoding the classical problem P: number of layers of two blocks in the QAOA circuit
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
Returns: Returns:
the final state of the QAOA circuit: cir.state the QAOA circuit
""" """
cir = UAnsatz(N, input_state=input_state) cir = UAnsatz(N)
# 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()
# This loop defines the QAOA circuit with P layers of two blocks
for layer in range(P): for layer in range(P):
# The second and third loops aim to construct the first block U_theta[layer][0] which involves # The second and third loops construct the first block which involves two-qubit operation
# two-qubit operation e^{-i\beta Z_iZ_j} acting on a pair of qubits or nodes i and j in the circuit. # 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 row in range(N):
for col in range(N): for col in range(N):
if abs(adjacency_matrix[row, col]) and row < col: if adjacency_matrix[row, col] and row < col:
cir.cnot([row + 1, col + 1]) cir.cnot([row, col])
cir.rz( cir.rz(theta[layer][0], col)
theta=theta[layer][0] * adjacency_matrix[row, col], cir.cnot([row, col])
which_qubit=col + 1, ) # This loop constructs the second block only involving the single-qubit operation e^{-i\beta X}.
cir.cnot([row + 1, col + 1]) for i in range(N):
# This loops constructs the second block U_theta only involving the single-qubit operation e^{-i\beta X}. cir.rx(theta[layer][1], i)
for i in range(1, N + 1):
cir.rx(theta=theta[layer][1], which_qubit=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. from the driving Hamiltonian describing the rotation around an arbitrary direction on each qubit.
Args: Args:
...@@ -91,35 +89,29 @@ def circuit_extend_QAOA(theta, input_state, adjacency_matrix, N, P): ...@@ -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 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 P: number of layers of two blocks in the QAOA circuit
Returns: 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 Note:
in the Net function defined below from the Net(shape=[D, 2]) for U_theta function to Net(shape=[D, 4]) If this circuit_extend_QAOA function is used to construct QAOA circuit, then we need to change the parameter layer
because the number of parameters doubles in each layer in this QAOA circuit. 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) # prepare the input state in the uniform superposition of 2^N bit-strings in the computational basis
cir.superposition_layer()
# The first loop defines the QAOA circuit with P layers of two blocks
for layer in range(P): 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 row in range(N):
for col in range(N): for col in range(N):
if abs(adjacency_matrix[row, col]) and row < col: if adjacency_matrix[row, col] and row < col:
cir.cnot([row + 1, col + 1]) cir.cnot([row, col])
cir.rz( cir.rz(theta[layer][0], col)
theta=theta[layer][0] * adjacency_matrix[row, col], cir.cnot([row, col])
which_qubit=col + 1, )
cir.cnot([row + 1, col + 1]) for i in range(N):
# This loops constructs the second block U_theta[layer][1]-[3] composed of three single-qubit operation cir.u3(*theta[layer][1:], i)
# 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): return cir
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
class Net(fluid.dygraph.Layer): class Net(fluid.dygraph.Layer):
...@@ -132,72 +124,48 @@ class Net(fluid.dygraph.Layer): ...@@ -132,72 +124,48 @@ class Net(fluid.dygraph.Layer):
def __init__( def __init__(
self, self,
shape, shape,
param_attr=fluid.initializer.Uniform( param_attr=fluid.initializer.Uniform(low=0.0, high=np.pi, seed=SEED),
low=0.0, high=PI, seed=SEED), dtype="float64",
dtype="float32", ): ):
super(Net, self).__init__() super(Net, self).__init__()
self.theta = self.create_parameter( 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, def forward(self, adjacency_matrix, N, P, METHOD):
METHOD):
""" """
This function constructs the loss function for the QAOA circuit. This function constructs the loss function for the QAOA circuit.
Args: 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 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 N: number of qubits
P: number of layers P: number of layers
METHOD: which version of QAOA is chosen to solve the problem, i.e., standard version labeled by 1 or METHOD: which version of QAOA is chosen to solve the problem, i.e., standard version labeled by 1 or
extended version by 2. extended version by 2.
Returns: 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 # Generate the problem_based quantum Hamiltonian H_problem based on the classical problem in paddle
H, _ = H_generator(N, adjacency_matrix) H_problem = H_generator(N, adjacency_matrix)
H_problem = fluid.dygraph.to_variable(H)
# The standard QAOA circuit: the function circuit_QAOA is used to construct the circuit, indexed by METHOD 1. # The standard QAOA circuit: the function circuit_QAOA is used to construct the circuit, indexed by METHOD 1.
if METHOD == 1: if METHOD == 1:
out_state = circuit_QAOA(self.theta, input_state, adjacency_matrix, cir = circuit_QAOA(self.theta, adjacency_matrix, N, P)
N, P)
# The extended QAOA circuit: the function circuit_extend_QAOA is used to construct the net, indexed by METHOD 2. # The extended QAOA circuit: the function circuit_extend_QAOA is used to construct the net, indexed by METHOD 2.
elif METHOD == 2: elif METHOD == 2:
out_state = circuit_extend_QAOA(self.theta, input_state, cir = circuit_extend_QAOA(self.theta, adjacency_matrix, N, P)
adjacency_matrix, N, P)
else: else:
raise ValueError("Wrong method called!") raise ValueError("Wrong method called!")
out_state_store.append(out_state.numpy()) cir.run_state_vector()
loss = pp_matmul( loss = cir.expecval(H_problem)
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.
""" return loss, cir
# Generate the adjacency matrix from the description of the problem-based graph
_, classical_graph_adjacency = generate_graph(N, 1)
Paddle_QAOA(classical_graph_adjacency)
def Paddle_QAOA(classical_graph_adjacency, N=4, P=4, METHOD=1, ITR=120, def Paddle_QAOA(classical_graph_adjacency, N, P, METHOD, ITR, LR):
LR=0.1):
""" """
This is the core function to run QAOA. 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, ...@@ -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) 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) LR: learning rate for the gradient-based optimization method (default value LR=0.1)
Returns: 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(): 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 # Construct the net or QAOA circuits based on the standard modules
if METHOD == 1: if METHOD == 1:
net = Net(shape=[P, 2]) net = Net(shape=[P, 2])
...@@ -228,41 +190,109 @@ def Paddle_QAOA(classical_graph_adjacency, N=4, P=4, METHOD=1, ITR=120, ...@@ -228,41 +190,109 @@ def Paddle_QAOA(classical_graph_adjacency, N=4, P=4, METHOD=1, ITR=120,
raise ValueError("Wrong method called!") raise ValueError("Wrong method called!")
# Classical optimizer # Classical optimizer
opt = fluid.optimizer.AdamOptimizer( opt = fluid.optimizer.AdamOptimizer(learning_rate=LR, parameter_list=net.parameters())
learning_rate=LR, parameter_list=net.parameters())
# Gradient descent loop # Gradient descent loop
summary_iter, summary_loss = [], [] summary_iter, summary_loss = [], []
for itr in range(1, ITR + 1): for itr in range(1, ITR + 1):
loss = net(initial_state, classical_graph_adjacency, loss, cir = net(
out_state_store, N, P, METHOD) classical_graph_adjacency, N, P, METHOD
)
loss.backward() loss.backward()
opt.minimize(loss) opt.minimize(loss)
net.clear_gradients() 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_loss.append(loss[0][0].numpy())
summary_iter.append(itr) summary_iter.append(itr)
theta_opt = net.parameters()[0].numpy() theta_opt = net.parameters()[0].numpy()
print(theta_opt) print("Optmized parameters theta:\n", theta_opt)
os.makedirs("output", exist_ok=True) 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. H_diag = np.diag(H_matrix).real
prob_measure = zeros([1, 2**N]).astype("complex") H_max = np.max(H_diag)
H_min = np.min(H_diag)
rho_out = out_state_store[-1] print(H_diag)
rho_out = np_matmul(conjugate(rho_out).T, rho_out).astype("complex") print('H_max:', H_max, ' H_min:', H_min)
for index in range(0, 2**N): pos = nx.circular_layout(classical_graph)
comput_basis = zeros([1, 2**N]) nx.draw(classical_graph, pos, width=4, with_labels=True, font_weight='bold')
comput_basis[0][index] = 1 plt.show()
prob_measure[0][index] = real(
np_matmul(np_matmul(comput_basis, rho_out), comput_basis.T))
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__": 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"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
...@@ -16,21 +16,15 @@ ...@@ -16,21 +16,15 @@
Aid func Aid func
""" """
from matplotlib import pyplot from matplotlib import pyplot
import numpy as np
from numpy import abs, array, binary_repr, diag, kron, max, ones, real, where, zeros from numpy import abs, array, binary_repr, diag, kron, max, ones, real, where, zeros
import networkx import networkx
__all__ = [
"plot_graph",
"generate_graph",
"H_generator",
]
def plot_graph(measure_prob_distribution, graph, N): 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 This function plots the graph encoding the combinatorial problem such as Max-Cut and the final graph encoding the
approximate solution obtained from QAOA approximate solution obtained from QAOA
Args: Args:
measure_prob_distribution: the measurement probability distribution which is sampled from the output state measure_prob_distribution: the measurement probability distribution which is sampled from the output state
of optimized QAOA circuit. of optimized QAOA circuit.
...@@ -93,68 +87,63 @@ def plot_graph(measure_prob_distribution, graph, N): ...@@ -93,68 +87,63 @@ def plot_graph(measure_prob_distribution, graph, N):
def generate_graph(N, GRAPHMETHOD): 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: Args:
N: number of nodes (vertices) in the graph, which is also the number of qubits N: number of nodes (vertices) in the graph
GRAPHMETHOD: which method to generate a graph METHOD: choose which method to generate a graph
Return: Returns:
graph description and its adjacency matrix 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 # Method 1 generates a graph by self-definition
# could be attributed to weights additionally. If no specific rules are given, then all weights are set to 1.
if GRAPHMETHOD == 1: if GRAPHMETHOD == 1:
print( print("Method 1 generates the graph from self-definition using EDGE description")
"Method 1 generates the graph from self-definition using EDGE description"
)
graph = networkx.Graph() graph = networkx.Graph()
graph_nodelist = range(N) graph_nodelist = range(N)
graph.add_edges_from([(0, 1), (1, 2), (2, 3), (3, 0)]) graph.add_edges_from([(0, 1), (1, 2), (2, 3), (3, 0)])
graph_adjacency = networkx.to_numpy_matrix( graph_adjacency = networkx.to_numpy_matrix(graph, nodelist=graph_nodelist)
graph, nodelist=graph_nodelist)
# Method 2 generates a graph by using its adjacency matrix directly # Method 2 generates a graph by using its adjacency matrix directly
elif GRAPHMETHOD == 2: elif GRAPHMETHOD == 2:
print( print("Method 2 generates the graph from networks using adjacency matrix")
"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_adjacency = array(
[[0, 1, 0, 1], [1, 0, 1, 0], [0, 1, 0, 1], [1, 0, 1, 0]])
graph = networkx.Graph(graph_adjacency) graph = networkx.Graph(graph_adjacency)
else: else:
print("Method doesn't exist ") print("Method doesn't exist ")
output_graph = graph return graph, graph_adjacency
output_graph_adjacency = graph_adjacency
return output_graph, output_graph_adjacency
def H_generator(N, adjacency_matrix): 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: Args:
N: number of qubits, or number of nodes in the graph, or number of parameters in the classical problem 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 adjacency_matrix: the adjacency matrix generated from the graph encoding the classical problem
Return: Returns:
H_graph: the problem-based Hamiltonian H generated from the graph_adjacency matrix for the given graph the problem-based Hmiltonian H's list form generated from the graph_adjacency matrix for the given graph
H_graph_diag: the real part of the problem-based Hamiltonian H_graph
""" """
H_list = []
sigma_Z = array([[1, 0], [0, -1]]) # Generate the Hamiltonian H_c from the graph via its adjacency matrix
H = zeros([2**N, 2**N])
for row in range(N): for row in range(N):
for col in range(N): for col in range(N):
if abs(adjacency_matrix[N - row - 1, N - col - 1]) and row < col: if adjacency_matrix[row, col] and row < col:
identity_1 = diag(ones([2**row])) # Construct the Hamiltonian in the list form for the calculation of expectation value
identity_2 = diag(ones([2**(col - row - 1)])) H_list.append([1.0, 'z' + str(row) + ',z' + str(col)])
identity_3 = diag(ones([2**(N - col - 1)]))
H += adjacency_matrix[N - row - 1, N - col - 1] * kron( return H_list
kron(
kron(kron(identity_1, sigma_Z), identity_2), sigma_Z),
identity_3, ) def main():
# number of qubits or number of nodes in the graph
H_graph = H.astype("complex64") N = 4
H_graph_diag = diag(H_graph).real classical_graph, classical_graph_adjacency = generate_graph(N, GRAPHMETHOD=1)
print(classical_graph_adjacency)
return H_graph, H_graph_diag
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"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
...@@ -16,7 +16,8 @@ ...@@ -16,7 +16,8 @@
Benchmark Benchmark
""" """
from matplotlib import pyplot 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 from paddle_quantum.QAOA.QAOA_Prefunc import generate_graph, H_generator
...@@ -25,24 +26,25 @@ def benchmark_QAOA(classical_graph_adjacency=None, N=None): ...@@ -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 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 from QAOA with predetermined parameters, such as iteration step = 120 and learning rate = 0.1, to the exact solution
to the classical problem. to the classical problem.
""" """
# Generate the graph and its adjacency matrix from the classical problem, such as the Max-Cut 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)): if all(var is None for var in (classical_graph_adjacency, N)):
N = 4 N = 4
_, classical_graph_adjacency = generate_graph(N, 1) _, 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 # 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) print('H_max:', H_max, ' H_min:', H_min)
H_graph_min = min(H_problem_diag)
print('H_max:', H_graph_max, ' H_min:', H_graph_min)
# Load the data of QAOA # Load the data of QAOA
x1 = load('./output/summary_data.npz') 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 # Plot it
pyplot.figure(1) 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"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
...@@ -16,27 +16,96 @@ ...@@ -16,27 +16,96 @@
main main
""" """
from paddle_quantum.QAOA.Paddle_QAOA import Paddle_QAOA from paddle import fluid
from paddle_quantum.QAOA.QAOA_Prefunc import plot_graph, generate_graph
import os
import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
# Random seed for optimizer from paddle_quantum.utils import pauli_str_to_matrix
SEED = 1 from paddle_quantum.QAOA.Paddle_QAOA import Paddle_QAOA
from paddle_quantum.QAOA.QAOA_Prefunc import generate_graph, H_generator
def main(N=4): def main(N=4):
""" # number of qubits or number of nodes in the graph
QAOA Main 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) classical_graph, classical_graph_adjacency = generate_graph(N, 1)
print(classical_graph_adjacency)
prob_measure = Paddle_QAOA(classical_graph_adjacency)
# Flatten array[[]] to [] opt_cir = Paddle_QAOA(classical_graph_adjacency, N=4, P=4, METHOD=1, ITR=120, LR=0.1)
prob_measure = prob_measure.flatten()
# Plot it! # Load the data of QAOA
plot_graph(prob_measure, classical_graph, N) 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() 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"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
...@@ -16,22 +16,20 @@ ...@@ -16,22 +16,20 @@
HGenerator HGenerator
""" """
from numpy import array, kron from paddle_quantum.utils import random_pauli_str_generator, pauli_str_to_matrix
__all__ = ["H_generator"] __all__ = ["H_generator"]
def H_generator(): def H_generator(N):
""" """
Generate a Hamiltonian with trivial descriptions Generate a Hamiltonian with trivial descriptions
Returns: A Hamiltonian Returns: A Hamiltonian
""" """
sigma_I = array([[1, 0], [0, 1]]) # 生成用泡利字符串表示的随机哈密顿量
sigma_X = array([[0, 1], [1, 0]]) hamiltonian = random_pauli_str_generator(N, terms=10)
sigma_Y = array([[0, -1j], [1j, 0]]) print("Random Hamiltonian in Pauli string format = \n", hamiltonian)
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 = pauli_str_to_matrix(hamiltonian, N)
# H = numpy.diag([0.1, 0.2, 0.3, 0.4]) return H
return H.astype('complex64')
# 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"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
...@@ -16,12 +16,16 @@ ...@@ -16,12 +16,16 @@
Paddle_SSVQE: To learn more about the functions and properties of this application, Paddle_SSVQE: To learn more about the functions and properties of this application,
you could check the corresponding Jupyter notebook under the Tutorial folder. you could check the corresponding Jupyter notebook under the Tutorial folder.
""" """
import numpy import numpy
from paddle.complex import matmul, transpose
from paddle.complex import matmul
from paddle import fluid from paddle import fluid
from paddle_quantum.circuit import UAnsatz 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__ = [ __all__ = [
"U_theta", "U_theta",
...@@ -30,35 +34,19 @@ __all__ = [ ...@@ -30,35 +34,19 @@ __all__ = [
] ]
# definition of U_theta
def U_theta(theta, N): def U_theta(theta, N):
""" """
U_theta Quantum Neural Network
""" """
# 按照量子比特数量/网络宽度初始化量子神经网络
cir = UAnsatz(N) cir = UAnsatz(N)
# ============== D1=2 ==============
cir.ry(theta[0], 2) # 调用内置的量子神经网络模板
cir.rz(theta[1], 2) cir.universal_2_qubit_gate(theta)
cir.cnot([2, 1])
cir.ry(theta[2], 2) # 返回量子神经网络所模拟的酉矩阵 U
cir.rz(theta[3], 2) return cir.U
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
class Net(fluid.dygraph.Layer): class Net(fluid.dygraph.Layer):
...@@ -66,68 +54,91 @@ class Net(fluid.dygraph.Layer): ...@@ -66,68 +54,91 @@ class Net(fluid.dygraph.Layer):
Construct the model net Construct the model net
""" """
def __init__(self, def __init__(self, shape, param_attr=fluid.initializer.Uniform(low=0.0, high=2 * numpy.pi, seed=SEED),
shape, dtype='float64'):
param_attr=fluid.initializer.Uniform(
low=0.0, high=2 * numpy.pi, seed=SEED),
dtype='float32'):
super(Net, self).__init__() super(Net, self).__init__()
self.theta = self.create_parameter( # 初始化 theta 参数列表,并用 [0, 2*pi] 的均匀分布来填充初始值
shape=shape, attr=param_attr, dtype=dtype, is_bias=False) self.theta = self.create_parameter(shape=shape, attr=param_attr, dtype=dtype, is_bias=False)
# 定义损失函数和前向传播机制
def forward(self, H, N): def forward(self, H, N):
""" # 施加量子神经网络
Args: U = U_theta(self.theta, N)
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
# 计算损失函数
loss_struct = matmul(matmul(hermitian(U), H), U).real
# 输入计算基去计算每个子期望值,相当于取 U^dagger*H*U 的对角元
loss_components = [ 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_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 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(): with fluid.dygraph.guard():
# Harmiltonian preparing # 我们需要将 Numpy array 转换成 Paddle 动态图模式中支持的 variable
H = fluid.dygraph.to_variable(H) hamiltonian = fluid.dygraph.to_variable(H)
# net # 确定网络的参数维度
net = Net(shape=[THETA_SIZE]) net = Net(shape=[THETA_SIZE])
# optimizer # 一般来说,我们利用Adam优化器来获得相对好的收敛,当然你可以改成SGD或者是RMS prop.
opt = fluid.optimizer.AdagradOptimizer( opt = fluid.optimizer.AdagradOptimizer(learning_rate=LR, parameter_list=net.parameters())
learning_rate=LR, parameter_list=net.parameters())
# gradient descent loop # 优化循环
for itr in range(1, ITR + 1): for itr in range(1, ITR + 1):
loss, loss_components = net(H, N)
# 前向传播计算损失函数并返回估计的能谱
loss, loss_components = net(hamiltonian, N)
# 在动态图机制下,反向传播极小化损失函数
loss.backward() loss.backward()
opt.minimize(loss) opt.minimize(loss)
net.clear_gradients() 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"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
...@@ -17,32 +17,28 @@ main ...@@ -17,32 +17,28 @@ main
""" """
import numpy import numpy
from paddle_quantum.SSVQE.HGenerator import H_generator from paddle_quantum.SSVQE.HGenerator import H_generator
from paddle_quantum.SSVQE.Paddle_SSVQE import Paddle_SSVQE from paddle_quantum.SSVQE.Paddle_SSVQE import Paddle_SSVQE
def main(): def main():
""" N = 2
main H = H_generator(N)
"""
hamiltonian = H_generator() loss_components = Paddle_SSVQE(H)
loss_components = Paddle_SSVQE(hamiltonian)
print('The estimated ground state energy is: ', loss_components[0].numpy()) print('The estimated ground state energy is: ', loss_components[0].numpy())
print('The estimated 1st excited state energy is: ', print('The theoretical ground state energy: ', numpy.linalg.eigh(H)[0][0])
loss_components[1].numpy())
print('The estimated 2nd excited state energy is: ', print('The estimated 1st excited state energy is: ', loss_components[1].numpy())
loss_components[2].numpy()) print('The theoretical 1st excited state energy: ', numpy.linalg.eigh(H)[0][1])
print('The estimated 3rd excited state energy is: ',
loss_components[3].numpy()) print('The estimated 2nd excited state energy is: ', loss_components[2].numpy())
print('The theoretical ground state energy: ', print('The theoretical 2nd excited state energy: ', numpy.linalg.eigh(H)[0][2])
numpy.linalg.eigh(hamiltonian)[0][0])
print('The theoretical 1st excited state energy: ', print('The estimated 3rd excited state energy is: ', loss_components[3].numpy())
numpy.linalg.eigh(hamiltonian)[0][1]) print('The theoretical 3rd excited state energy: ', numpy.linalg.eigh(H)[0][3])
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__': 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"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with 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. ...@@ -18,14 +18,15 @@ you could check the corresponding Jupyter notebook under the Tutorial folder.
""" """
import os import os
import platform
from numpy import concatenate
from numpy import pi as PI from numpy import pi as PI
from numpy import savez, zeros from numpy import savez
from paddle import fluid from paddle import fluid
from paddle.complex import matmul, transpose
from paddle_quantum.circuit import UAnsatz from paddle_quantum.circuit import UAnsatz
from paddle_quantum.VQE.benchmark import benchmark_result
from paddle_quantum.VQE.chemistrysub import H2_generator
__all__ = [ __all__ = [
"U_theta", "U_theta",
...@@ -34,27 +35,28 @@ __all__ = [ ...@@ -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): for i in range(N):
cir.rz(theta=theta[0][0][i], which_qubit=i + 1) cir.ry(theta=theta[D][i][0], which_qubit=i)
cir.ry(theta=theta[0][1][i], which_qubit=i + 1)
cir.rz(theta=theta[0][2][i], which_qubit=i + 1)
for repeat in range(D): # 量子神经网络作用在默认的初始态 |0000>上
for i in range(1, N): cir.run_state_vector()
cir.cnot(control=[i, i + 1])
for i in range(N): # 计算给定哈密顿量的期望值
cir.ry(theta=theta[repeat][0][i], which_qubit=i + 1) expectation_val = cir.expecval(Hamiltonian)
cir.ry(theta=theta[repeat][1][i], which_qubit=i + 1)
cir.rz(theta=theta[repeat][2][i], which_qubit=i + 1)
return cir.state return expectation_val
class StateNet(fluid.dygraph.Layer): class StateNet(fluid.dygraph.Layer):
...@@ -62,85 +64,92 @@ class StateNet(fluid.dygraph.Layer): ...@@ -62,85 +64,92 @@ class StateNet(fluid.dygraph.Layer):
Construct the model net Construct the model net
""" """
def __init__( def __init__(self, shape, param_attr=fluid.initializer.Uniform(low=0.0, high=2 * PI), dtype="float64"):
self,
shape,
param_attr=fluid.initializer.Uniform(
low=0.0, high=2 * PI),
dtype="float32", ):
super(StateNet, self).__init__() 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): # 初始化 theta 参数列表,并用 [0, 2*pi] 的均匀分布来填充初始值
""" self.theta = self.create_parameter(shape=shape, attr=param_attr, dtype=dtype, is_bias=False)
:param input_state: The initial state with default |0..>, 'mat'
:param H: The target Hamiltonian, 'mat'
:return: The loss, 'float'
"""
out_state = U_theta(self.theta, input_state, N, D) # 定义损失函数和前向传播机制
loss = matmul( def forward(self, Hamiltonian, N, D):
matmul(out_state, H), # 计算损失函数/期望值
transpose( loss = U_theta(self.theta, Hamiltonian, N, D)
fluid.framework.ComplexVariable(out_state.real,
-out_state.imag),
perm=[1, 0], ), )
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 # 初始化paddle动态图机制
H = fluid.dygraph.to_variable(Hamiltonian) with fluid.dygraph.guard():
# 确定网络的参数维度
# net net = StateNet(shape=[D + 1, N, 1])
net = StateNet(shape=[D + 1, 3, N])
# optimizer # 一般来说,我们利用Adam优化器来获得相对好的收敛,当然你可以改成SGD或者是RMS prop.
opt = fluid.optimizer.AdamOptimizer( opt = fluid.optimizer.AdamOptimizer(learning_rate=LR, parameter_list=net.parameters())
learning_rate=LR, parameter_list=net.parameters())
# gradient descent loop # 记录优化结果
summary_iter, summary_loss = [], [] summary_iter, summary_loss = [], []
# 优化循环
for itr in range(1, ITR + 1): 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() loss.backward()
# using gradients to update the variable theta
opt.minimize(loss) opt.minimize(loss)
# clear gradients
net.clear_gradients() net.clear_gradients()
summary_loss.append(loss[0][0].numpy()) # 更新优化结果
summary_loss.append(loss.numpy())
summary_iter.append(itr) summary_iter.append(itr)
print("iter:", itr, "loss:", "%.4f" % loss.numpy()) # 打印结果
print("iter:", itr, "Ground state energy:", if itr % 20 == 0:
"%.4f Ha" % loss.numpy()) print("iter:", itr, "loss:", "%.4f" % loss.numpy())
# print('theta:', net.parameters()[0].numpy()) print("iter:", itr, "Ground state energy:", "%.4f Ha" % loss.numpy())
# 储存训练结果到 output 文件夹
os.makedirs("output", exist_ok=True) os.makedirs("output", exist_ok=True)
savez("./output/summary_data", iter=summary_iter, energy=summary_loss) savez("./output/summary_data", iter=summary_iter, energy=summary_loss)
def main(): def main():
""" # Read data from built-in function or xyz file depending on OS
:return: 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() 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"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
...@@ -16,24 +16,26 @@ ...@@ -16,24 +16,26 @@
benchmark the result benchmark the result
""" """
import platform import platform
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import numpy import numpy
from paddle_quantum.utils import pauli_str_to_matrix
from paddle_quantum.VQE.chemistrysub import H2_generator 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 # Read H and calc using numpy
sysStr = platform.system() sysStr = platform.system()
if sysStr == 'Windows': if sysStr == 'Windows':
# Windows does not support SCF, using H2_generator instead # Windows does not support SCF, using H2_generator instead
print('Molecule data will be read from built-in function') print('Molecule data will be read from built-in function')
_H, _, _ = H2_generator() Hamiltonian, N = H2_generator()
print('Read Process Finished') print('Read Process Finished')
elif sysStr == 'Linux' or sysStr == 'Darwin': elif sysStr == 'Linux' or sysStr == 'Darwin':
# for linux only # for linux only
...@@ -41,51 +43,32 @@ def benchmark_result(): ...@@ -41,51 +43,32 @@ def benchmark_result():
# Harmiltonian and cnot module preparing, must be executed under Linux # Harmiltonian and cnot module preparing, must be executed under Linux
# Read the H2 molecule data # Read the H2 molecule data
print('Molecule data will be read from h2.xyz') 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') print('Read Process Finished')
else: else:
print("Don't support this os.") print("Don't support this os.")
# plot result = numpy.load('./output/summary_data.npz')
x1 = numpy.load('./output/summary_data.npz')
eig_val, eig_state = numpy.linalg.eig(_H) eig_val, eig_state = numpy.linalg.eig(pauli_str_to_matrix(Hamiltonian, N))
min_eig_H = numpy.min(eig_val) min_eig_H = numpy.min(eig_val.real)
min_loss = numpy.ones([len(x1['iter'])]) * min_eig_H min_loss = numpy.ones([len(result['iter'])]) * min_eig_H
plt.figure(1) plt.figure(1)
func1, = plt.plot( func1, = plt.plot(result['iter'], result['energy'], alpha=0.7, marker='', linestyle="-", color='r')
x1['iter'], func_min, = plt.plot(result['iter'], min_loss, alpha=0.7, marker='', linestyle=":", color='b')
x1['energy'],
alpha=0.7,
marker='',
linestyle="--",
color='m')
func_min, = plt.plot(
x1['iter'], min_loss, alpha=0.7, marker='', linestyle=":", color='b')
plt.xlabel('Number of iteration') plt.xlabel('Number of iteration')
plt.ylabel('Energy (Ha)') plt.ylabel('Energy (Ha)')
plt.legend( plt.legend(handles=[
handles=[func1, func_min], func1,
func_min
],
labels=[ labels=[
r'$\left\langle {\psi \left( {\bf{\theta }} \right)} ' r'$\left\langle {\psi \left( {\theta } \right)} '
r'\right|H\left| {\psi \left( {\bf{\theta }} \right)} \right\rangle $', r'\right|H\left| {\psi \left( {\theta } \right)} \right\rangle $',
'Minimum energy', 'Ground-state energy',
], ], loc='best')
loc='best')
# output the picture # plt.savefig("vqe.png", bbox_inches='tight', dpi=300)
plt.show() 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"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
...@@ -28,6 +28,32 @@ __all__ = [ ...@@ -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): def calc_H_rho_from_qubit_operator(qubit_op, n_qubits):
""" """
Generate a Hamiltonian from QubitOperator Generate a Hamiltonian from QubitOperator
...@@ -63,8 +89,8 @@ def calc_H_rho_from_qubit_operator(qubit_op, n_qubits): ...@@ -63,8 +89,8 @@ def calc_H_rho_from_qubit_operator(qubit_op, n_qubits):
rho = scipy.linalg.expm(-1 * beta * rho = scipy.linalg.expm(-1 * beta *
H) / trace(scipy.linalg.expm(-1 * beta * H)) H) / trace(scipy.linalg.expm(-1 * beta * H))
return H.astype('complex64'), rho.astype( return H.astype('complex128'), rho.astype(
'complex64') # the returned dic will have 2 ** n value 'complex128') # the returned dic will have 2 ** n value
def read_calc_H(geo_fn, multiplicity=1, charge=0): def read_calc_H(geo_fn, multiplicity=1, charge=0):
...@@ -91,7 +117,6 @@ 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) charge)
openfermionpyscf.run_pyscf(mol) openfermionpyscf.run_pyscf(mol)
terms_molecular_hamiltonian = mol.get_molecular_hamiltonian( terms_molecular_hamiltonian = mol.get_molecular_hamiltonian(
) )
fermionic_hamiltonian = openfermion.transforms.get_fermion_operator( fermionic_hamiltonian = openfermion.transforms.get_fermion_operator(
...@@ -99,10 +124,9 @@ def read_calc_H(geo_fn, multiplicity=1, charge=0): ...@@ -99,10 +124,9 @@ def read_calc_H(geo_fn, multiplicity=1, charge=0):
qubit_op = openfermion.transforms.jordan_wigner( qubit_op = openfermion.transforms.jordan_wigner(
fermionic_hamiltonian) fermionic_hamiltonian)
# calc H
# calc H, rho Hamiltonian = Hamiltonian_str_convert(qubit_op)
H, rho = calc_H_rho_from_qubit_operator(qubit_op, mol.n_qubits) return Hamiltonian, mol.n_qubits
return H, rho, mol.n_qubits
def main(): def main():
...@@ -112,10 +136,8 @@ def main(): ...@@ -112,10 +136,8 @@ def main():
""" """
filename = 'h2.xyz' filename = 'h2.xyz'
H, rho, N = read_calc_H(geo_fn=filename) H, N = read_calc_H(geo_fn=filename)
print('H', H) print('H', H)
print("-------------------------- ")
print('rho', rho)
if __name__ == '__main__': 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"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
...@@ -42,7 +42,7 @@ def H_generator(): ...@@ -42,7 +42,7 @@ def H_generator():
sigma_I, sigma_Z) + 0.2 * kron(sigma_X, sigma_X) sigma_I, sigma_Z) + 0.2 * kron(sigma_X, sigma_X)
rho = scipy.linalg.expm(-1 * beta * rho = scipy.linalg.expm(-1 * beta *
H) / trace(scipy.linalg.expm(-1 * beta * H)) 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(): def H2_generator():
...@@ -56,22 +56,39 @@ def H2_generator(): ...@@ -56,22 +56,39 @@ def H2_generator():
sigma_Z = array([[1, 0], [0, -1]]) sigma_Z = array([[1, 0], [0, -1]])
sigma_X = array([[0, 1], [1, 0]]) sigma_X = array([[0, 1], [1, 0]])
sigma_Y = array([[0, -1j], [1j, 0]]) sigma_Y = array([[0, -1j], [1j, 0]])
H = (-0.04207897647782276) * kron(kron(kron(sigma_I, sigma_I), sigma_I), sigma_I) \ # 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.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.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_Z), sigma_I) \
+ (-0.24274280513140462) * kron(kron(kron(sigma_I, sigma_I), sigma_I), sigma_Z) \ # + (-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.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_X), sigma_X), sigma_Y) \
+ (-0.04475014401535161) * kron(kron(kron(sigma_Y, sigma_Y), sigma_X), sigma_X) \ # + (-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_X), sigma_Y), sigma_Y) \
+ (0.04475014401535161) * kron(kron(kron(sigma_X, sigma_Y), sigma_Y), sigma_X) \ # + (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.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_Z, sigma_I), sigma_I), sigma_Z) \
+ (0.1676831945771896) * kron(kron(kron(sigma_I, sigma_Z), sigma_Z), sigma_I) \ # + (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.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) # + (0.17627640804319591) * kron(kron(kron(sigma_I, sigma_I), sigma_Z), sigma_Z)
rho = scipy.linalg.expm(-1 * beta * H = [
H) / trace(scipy.linalg.expm(-1 * beta * 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 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"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
...@@ -28,28 +28,28 @@ def main(): ...@@ -28,28 +28,28 @@ def main():
Main Learning network using dynamic graph Main Learning network using dynamic graph
:return: Plot or No return :return: Plot or No return
""" """
# Read data from built-in function or xyz file depending on OS # Read data from built-in function or xyz file depending on OS
sysStr = platform.system() sysStr = platform.system()
if sysStr == 'Windows': if sysStr == 'Windows':
# Windows does not support SCF, using H2_generator instead # Windows does not support SCF, using H2_generator instead
print('Molecule data will be read from built-in function') print('Molecule data will be read from built-in function')
_H, _, N = H2_generator() hamiltonian, N = H2_generator()
print('Read Process Finished') print('Read Process Finished')
elif sysStr in ('Linux', 'Darwin'): elif sysStr in ('Linux', 'Darwin'):
# for linux only # for linux only
from paddle_quantum.VQE.chemistrygen import read_calc_H 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 # Read the H2 molecule data
print('Molecule data will be read from h2.xyz') 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') print('Read Process Finished')
else: else:
print("Don't support this OS.") print("Don't support this OS.")
Paddle_VQE(_H, N) Paddle_VQE(hamiltonian, N)
benchmark_result() 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"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
...@@ -12,6 +12,6 @@ ...@@ -12,6 +12,6 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
""" r"""
Paddle Quantum Library Paddle Quantum Library
""" """
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
paddlepaddle>=1.8.0 paddlepaddle>=1.8.3
networkx networkx>=2.4
matplotlib matplotlib>=3.3.0
\ No newline at end of file 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.
先完成此消息的编辑!
想要评论请 注册