提交 195b41b7 编写于 作者: Q Quleaf

update to v2.3.0

上级 ca62f24a

要显示的变更太多。

To preserve performance only 1000 of 1000+ files are displayed.
......@@ -33,7 +33,7 @@ English | [简体中文](README_CN.md)
</a>
<!-- PyPI -->
<a href="https://pypi.org/project/paddle-quantum/">
<img src="https://img.shields.io/badge/pypi-v2.2.2-orange.svg?style=flat-square&logo=pypi"/>
<img src="https://img.shields.io/badge/pypi-v2.3.0-orange.svg?style=flat-square&logo=pypi"/>
</a>
<!-- Python -->
<a href="https://www.python.org/">
......@@ -90,22 +90,19 @@ pip install -e .
### Environment setup for Quantum Chemistry module
Our `qchem` module is based on `Psi4`, so before executing quantum chemistry, we have to install this Python package.
Currently, our `qchem` module uses `PySCF` as its backend to compute molecular integrals, so before executing quantum chemistry, we have to install this Python package.
> It is recommended that `Psi4` is installed in a Python 3.8 environment.
> It is recommended that `PySCF` is installed in a Python environment whose Python version >=3.6.
We highly recommend you to install `Psi4` via conda. **MacOS/Linux** user can use the command:
We highly recommend you to install `PySCF` via conda. **MacOS/Linux** user can use the command:
```bash
conda install psi4 -c psi4
conda install -c pyscf pyscf
```
For **Windows** user, the command is:
> NOTE: For **Windows** user, if your operating system is Windows10, you can install `PySCF` in Ubuntu subsystem provided by Windows 10's App Store. `PySCF` can't run directly in Windows, so we are working hard to develop more quantum chemistry backends. Our support for Windows will be improved in the coming release of Paddle Quantum.
```bash
conda install psi4 -c psi4 -c conda-forge
```
**Note:** Please refer to [Psi4](https://psicode.org/installs/v14/) for more download options.
**Note:** Please refer to [PySCF](https://pyscf.org/install.html) for more download options.
### Run example
......
......@@ -34,7 +34,7 @@
</a>
<!-- PyPI -->
<a href="https://pypi.org/project/paddle-quantum/">
<img src="https://img.shields.io/badge/pypi-v2.2.2-orange.svg?style=flat-square&logo=pypi"/>
<img src="https://img.shields.io/badge/pypi-v2.3.0-orange.svg?style=flat-square&logo=pypi"/>
</a>
<!-- Python -->
<a href="https://www.python.org/">
......@@ -91,23 +91,19 @@ pip install -e .
### 量子化学模块的环境设置
我们的量子化学模块是基于 `Psi4` 进行开发的,所以在运行量子化学模块之前需要先行安装该 Python 包。
当前我们的量子化学模块在后端使用 `PySCF` 来计算各类分子积分,所以在运行量子化学模块之前需要先行安装该 Python 包。
> 推荐在 Python3.8 环境中安装。
> 推荐在 Python>=3.6 环境中安装。
在安装 `psi4` 时,我们建议您使用 conda。对于 **MacOS/Linux** 的用户,可以使用如下指令。
在安装 `PySCF` 时,我们建议您使用 conda。对于 **MacOS/Linux** 的用户,可以使用如下指令。
```bash
conda install psi4 -c psi4
conda install -c pyscf pyscf
```
对于 **Windows** 用户,请使用
> 注:对于 **Windows** 用户,如果操作系统为 Windows10,可以在其应用商店提供的 Ubuntu 子系统中利用上述命令安装 `PySCF`。`PySCF` 并不支持直接在 Windows 下运行,我们正在努力开发更多的量子化学后端,在量桨的下一版本中将会有对 Windows 更好的支持。
```bash
conda install psi4 -c psi4 -c conda-forge
```
**注意:** 更多的下载方法请参考 [Psi4](https://psicode.org/installs/v14/)
**注意:** 更多的下载方法请参考 [PySCF](https://pyscf.org/install.html)
### 运行
......@@ -217,7 +213,7 @@ Paddle Quantum 使用 setuptools 的 develop 模式进行安装,相关代码
## 交流与反馈
- 我们非常欢迎您通过 [Github Issues](https://github.com/PaddlePaddle/Quantum/issues) 来提交问题、报告与建议。
- 我们非常欢迎您通过 [GitHub Issues](https://github.com/PaddlePaddle/Quantum/issues) 来提交问题、报告与建议。
- 技术交流QQ群:1076223166
......
# Quantum Application Model Library
- [Features](#features)
- [Installation](#installation)
- [How to Use](#how-to-use)
- [Application List](#application-list)
**Q**uantum **A**pplication **M**odel Library (QAML) is a collection of out-of-box practical quantum algorithms, it is developed by [Institute for Quantum Computing at Baidu](https://quantum.baidu.com/), and aims to be a "supermarket" of quantum solutions for industry users. Currently, models in QAML have covered popular areas listed below:
- Artificial Intelligence
- Medicine and Pharmaceuticals
- Material Simulation
- Financial Technology
- Manufacturing
- Data Analysis
QAML is implemented on Paddle Quantum, a quantum machine learning platform, which can be found at https://qml.baidu.com and https://github.com/PaddlePaddle/Quantum.
## Features
- Industrialization: 10 models closely follow the 6 major industrial directions, covering hot topics such as artificial intelligence, chemical materials, manufacturing, finance, etc.
- End-to-end: Linking the whole process from application scenarios to quantum computing and solving the last mile of quantum applications.
- Out-of-box: No special configuration is required, the model is called directly by the Paddle Quantum, eliminating the tedious installation process.
## Installation
QAML depends on the `paddle-quantum` package. Users can install it by pip.
```shell
pip install paddle-quantum
```
For those who are using old versions of Paddle Quantum, simply run `pip install --upgrade paddle-quantum` to install the latest package.
QAML locates in Paddle Quantum's GitHub repository, you can download the zip file contains QAML source code by clicking [this link](https://github.com/PaddlePaddle/Quantum/archive/refs/heads/master.zip). After unzipping the package, you will find all the models in the `applications` folder in the extracted folder.
You can also use git to get the QAML source code.
```shell
git clone https://github.com/PaddlePaddle/Quantum.git
cd Quantum/applications
```
You can check your installation by going to the `handwritten_digits_classification` folder under `applications` and running
```shell
python vsql_classification.py --example.toml
```
The installation is successful once the program terminates without errors.
## How to Use
In each application model, we provide Python scripts that can be run directly and the corresponding configuration files. The user can modify the configuration file to implement the corresponding requirements.
Take handwritten digit classification as an example, it can be used by executing `python vsql_classification.py --example.toml` in the `handwritten_digits_classification` folder. We provide tutorials for each application model, which allows users to quickly understand and use it.
## Application List
*Continue update*
Below we list instructions for all applications available in QAML, newly developed applications will be continuously integrated into QAML.
1. [Handwritten digits classification](./handwritten_digits_classification/introduction_en.ipynb)
2. [Molecular ground state energy & dipole moment calculation](./lithium_ion_battery/introduction_en.ipynb)
3. [Text classification](./text_classification/introduction_en.ipynb)
4. [Protein folding](./protein_folding/introduction_en.ipynb)
5. [Medical image classification](./medical_image_classification/introduction_en.ipynb)
6. [Quality detection](./quality_detection/introduction_en.ipynb)
7. [Option pricing](./option_pricing/introduction_en.ipynb)
8. [Quantum portfolio optimization](./portfolio_optimization/introduction_en.ipynb)
9. [Regression](./regression/introduction_en.ipynb)
10. [Quantum linear equation solver](./linear_solver/introduction_en.ipynb)
# 量子应用模型库
- [特色](#特色)
- [安装](#安装)
- [如何使用](#如何使用)
- [应用列表](#应用列表)
量子应用模型库(**Q**uantum **A**pplication **M**odel **L**ibrary, QAML)是一个开箱即用的实用量子应用模型集合,它由[百度量子计算研究所](https://quantum.baidu.com/)研发,旨在成为企业用户的量子解决方案“超市”。目前,QAML 中的模型已经覆盖了以下领域:
- 人工智能
- 医学制药
- 材料模拟
- 金融科技
- 汽车制造
- 数据分析
QAML 基于量桨这一量子机器学习平台实现,关于量桨的内容可以参考 https://qml.baidu.com 和 https://github.com/PaddlePaddle/Quantum 。
## 特色
- 产业化:10 大应用模型紧贴 6 大产业方向,涵盖人工智能、化工材料、汽车制造、金融套利等热点话题。
- 端到端:打通应用场景到量子算法的全流程,解决量子应用的最后一公里问题。
- 开箱即用:无需特殊配置,通过量桨直接完成模型调用,省去繁琐安装环节。
## 安装
QAML 依赖于量桨( `paddle-quantum` )软件包。用户可以通过 pip 来安装:
```shell
pip install paddle-quantum
```
对于那些使用旧版量桨的用户,只需运行 `pip install --upgrade paddle-quantum` 即可安装最新版量桨。
QAML 的内容在 Paddle Quantum 的 GitHub 仓库中,用户可以通过点击[此链接](https://github.com/PaddlePaddle/Quantum/archive/refs/heads/master.zip)下载包含 QAML 源代码的压缩包。QAML 的所有模型都在解压后的文件夹中的 `applications` 文件夹里。
用户也可以使用 git 来获取 QAML 的源码文件。
```shell
git clone https://github.com/PaddlePaddle/Quantum.git
cd Quantum/applications
```
用户可以进入到 `applications` 下的 `handwritten_digits_classification` 文件夹中,然后运行以下代码来检查安装是否成功。
```shell
python vsql_classification.py --example.toml
```
如果上面的程序没有报错、成功运行的话,则说明安装成功了。
## 如何使用
在每个应用模型中,我们都提供了可以直接运行的Python脚本和相应的配置文件。用户可以修改配置文件来实现对应的要求。
以手写数字识别为例,用户可以通过执行 `handwritten_digits_classification` 中的 `python vsql_classification.py --example.toml` 命令来快速使用。我们为每个应用模型提供了教程,方便用户快速理解和上手使用。
## 应用列表
*持续更新中*
我们列出了目前 QAML 的所有应用案例的教程,新开发的应用案例也会持续添加进来。
1. [手写数字识别](./handwritten_digits_classification/introduction_cn.ipynb)
2. [分子基态能量 & 偶极矩计算](./lithium_ion_battery/introduction_cn.ipynb)
3. [中文文本分类](./text_classification/introduction_cn.ipynb)
4. [蛋白质折叠](./protein_folding/introduction_cn.ipynb)
5. [医学影像判别](./medical_image_classification/introduction_cn.ipynb)
6. [材料表面质量检测](./quality_detection/introduction_cn.ipynb)
7. [量子期权定价](./option_pricing/introduction_cn.ipynb)
8. [投资组合优化](./portfolio_optimization/introduction_cn.ipynb)
9. [回归分析](./regression/introduction_cn.ipynb)
10. [线性方程组求解](./linear_solver/introduction_cn.ipynb)
task = 'test'
image_path = 'data_0.png'
is_dir = false
model_path = 'vsql.pdparams'
num_qubits = 10
num_shadow = 2
depth = 1
classes = [0, 1]
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 手写数字识别简介\n",
"\n",
"*Copyright (c) 2022 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.*\n",
"\n",
"计算机视觉(Computer Vision, CV)是指让计算机能够从图像、视频或其它视觉输入中获取有意义的信息。它是人工智能领域中的一个非常基础且重要的组成部分。在 CV 中,手写数字识别(handwritten digit classification)是一个较为基础的任务。它在 MNIST 数据集\\[1\\]上进行训练和测试,用来验证模型是否拥有 CV 方面的基础能力。\n",
"\n",
"MNIST 数据集中包含如下图所示的手写数字。MNIST 共包含 0-9 这 10 个类别,每个数字为 28\\*28 像素的灰度图片。其中,训练集有 60000 张图片,测试集有 10000 张图片。假设我们设计了一个可以用来进行图像分类的模型,那么我们可以在 MNIST 数据集上测试该模型的分类能力。\n",
"\n",
"![mnist-example](mnist_example.png)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 使用 VSQL 模型实现 MNIST 分类\n",
"\n",
"### 数据编码\n",
"\n",
"在手写数字识别问题中,输入是一张手写数字图片,输出是该图片对应的类别(即数字 0-9)。而由于量子计算机处理的输入是量子态,因此,我们需要将图片编码为量子态。在这里,我们首先使用一个二维矩阵表示一张图片。然后将该矩阵展开为一维向量,并通过补充 0 将向量长度补充到 2 的整数次幂。再对向量进行归一化,即可得到一个量子计算机可以处理的量子态。\n",
"\n",
"### VSQL 模型简介\n",
"\n",
"变分影子量子学习(variational shadow quantum learning, VSQL)是一个在监督学习框架下的量子–经典混合算法。它使用了参数化量子电路(parameterized quantum circuit, PQC)和经典影子(classical shadow),和通常使用的变分量子算法(variational quantum algorithm, VQA)不同的是,VSQL 只从子空间获取局部特征,而不是从量子态形成的整个希尔伯特空间获取特征。\n",
"\n",
"VSQL 的模型原理图如下:\n",
"\n",
"![vsql-model](vsql_model.png)\n",
"\n",
"VSQL 处理的输入是一个量子态。对于输入的量子态,迭代地作用一个局部参数化量子电路并进行测量,得到局部的影子特征。然后将得到的所有影子特征使用经典神经网络进行计算并得到预测标签。\n",
"\n",
"### 工作流\n",
"\n",
"根据以上原理,我们只需要使用 MNIST 数据集对 VSQL 模型进行训练。得到收敛后的模型。使用该模型即可进行手写数字的分类。模型的训练流程如下图:\n",
"\n",
"\n",
"![vsql-pipeline](vsql_pipeline_cn.png)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 如何使用\n",
"\n",
"### 使用模型进行预测\n",
"\n",
"这里,我们已经给出了一个训练好的模型,可以直接用于 0 和 1 的图片的预测。只需要在 `example.toml` 这个配置文件中进行对应的配置,然后输入命令 `python vsql_classification.py --config example.toml` 即可使用训练好的 VSQL 模型对输入的图片进行测试。\n",
"\n",
"### 在线演示\n",
"\n",
"这里,我们给出一个在线演示的版本,可以在线进行测试。首先定义配置文件的内容:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"test_toml = r\"\"\"\n",
"# 模型的整体配置文件。\n",
"# 输入当前的任务,可以是 'train' 或者 'test',分别代表训练和预测。这里我们使用 test,表示我们要进行预测。\n",
"task = 'test'\n",
"# 要预测的图片的文件路径。\n",
"image_path = 'data_0.png'\n",
"# 上面的图片路径是否是文件夹。对于文件夹路径,我们会对文件夹里面的所有图片文件进行预测。这种方式可以一次测试多个图片。\n",
"is_dir = false\n",
"# 训练好的模型参数文件的文件路径。\n",
"model_path = 'vsql.pdparams'\n",
"# 量子电路所包含的量子比特的数量。\n",
"num_qubits = 10\n",
"# 影子电路所包含的量子比特的数量。\n",
"num_shadow = 2\n",
"# 电路深度。\n",
"depth = 1\n",
"# 我们要预测的类别。这里我们对 0 和 1 进行分类。\n",
"classes = [0, 1]\n",
"\"\"\""
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"接下来是预测部分的代码:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"对于输入的图片,模型有 89.22% 的信心认为它是 0,和 10.78% 的信心认为它是 1。\n"
]
}
],
"source": [
"import os\n",
"import warnings\n",
"\n",
"warnings.filterwarnings('ignore')\n",
"os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'python'\n",
"\n",
"import toml\n",
"from paddle_quantum.qml.vsql import train, inference\n",
"\n",
"config = toml.loads(test_toml)\n",
"task = config.pop('task')\n",
"if task == 'train':\n",
" train(**config)\n",
"elif task == 'test':\n",
" prediction, prob = inference(**config)\n",
" if config['is_dir']:\n",
" print(f\"对输入图片的预测结果分别是 {str(prediction)[1:-1]}。\")\n",
" else:\n",
" prob = prob[0]\n",
" msg = '对于输入的图片,模型有'\n",
" for idx, item in enumerate(prob):\n",
" if idx == len(prob) - 1:\n",
" msg += '和'\n",
" label = config['classes'][idx]\n",
" msg += f' {item:3.2%} 的信心认为它是 {label:d}'\n",
" msg += '。' if idx == len(prob) - 1 else ','\n",
" print(msg)\n",
"else:\n",
" raise ValueError(\"未知的任务,它可以是'train'或'test'。\")"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"在这里,我们只需要修改要配置文件中的图片路径,再运行整个代码,就可以快速对其它图片进行测试。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 注意事项\n",
"\n",
"我们提供的模型为二分类模型,仅可以用来分辨手写数字 0 和 1。对于其它分类任务,需要重新进行训练。\n",
"\n",
"### 数据集结构\n",
"\n",
"如果想要使用自定义数据集进行训练,只需要按照规则来准备数据集即可。在数据集文件夹中准备 `train.txt` 和 `test.txt`,如果需要验证集的话还有 `dev.txt`。每个文件里使用一行代表一条数据。每行内容包含图片的文件路径和标签,使用制表符隔开。\n",
"\n",
"### 配置文件介绍\n",
"\n",
"在 `test.toml` 里有测试所需要的完整的配置文件内容参考。在 `train.toml` 里有训练所需要的完整的配置文件内容参考。使用配置文件的方式即可快速进行模型的训练和预测。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 6. 引用信息\n",
"\n",
"```tex\n",
"@inproceedings{li2021vsql,\n",
" title={VSQL: Variational shadow quantum learning for classification},\n",
" author={Li, Guangxi and Song, Zhixin and Wang, Xin},\n",
" booktitle={Proceedings of the AAAI Conference on Artificial Intelligence},\n",
" volume={35},\n",
" number={9},\n",
" pages={8357--8365},\n",
" year={2021}\n",
"}\n",
"```\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "py37",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.15 (default, Nov 10 2022, 12:46:26) \n[Clang 14.0.6 ]"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "49b49097121cb1ab3a8a640b71467d7eda4aacc01fc9ff84d52fcb3bd4007bf1"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Introduction to Handwritten Digit Classification\n",
"\n",
"*Copyright (c) 2022 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.*\n",
"\n",
"Computer Vision (CV) refers to enabling computers to obtain meaningful information from images, videos, or other visual inputs. It is a fundamental and important field in artificial intelligence. In CV, handwritten digit classification is a relatively basic task. It is trained and tested on the MNIST dataset \\[1\\] to verify whether the model has the basic ability of CV.\n",
"\n",
"The MNIST dataset contains handwritten digits as shown in the figure below. MNIST contains a total of 10 categories from 0-9, and each digit is a grayscale image of 28\\*28 pixels. There are 60,000 images in the training set and 10,000 images in the test set. Suppose we design a model that can be used for image classification, then we can test the classification ability of the model on the MNIST dataset.\n",
"\n",
"![mnist-example](mnist_example.png)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## MNIST Classification Using VSQL Model\n",
"\n",
"### Data Encoding\n",
"\n",
"In the handwritten digit classification problem, the input is a picture of a handwritten digit and the output is the category corresponding to the picture (i.e., the digits 0-9). And since quantum computers deal with inputs that are quantum states, we need to encode the picture into a quantum state. Here, we first represent a picture using a two-dimensional matrix. This matrix is then expanded into a 1D vector, and the length of the vector is padded to an integer power of 2 by padding with zeros. The vector is then normalized to obtain a quantum state that can be processed by a quantum computer.\n",
"\n",
"\n",
"### Introduction to the VSQL Model\n",
"\n",
"Variational shadow quantum learning (VSQL) is a hybrid quantum-classical algorithm under the framework of supervised learning. It uses the parameterized quantum circuit (PQC) and the classical shadow. Unlike the common variational quantum algorithm (VQA), VSQL only obtains local features from the subspace rather than from the whole Hilbert space where the quantum states are formed.\n",
"\n",
"The schematic diagram of the VSQL model is as follows.\n",
"\n",
"![vsql-model](vsql_model.png)\n",
"\n",
"The input to the VSQL process is a quantum state. For the input quantum state, a local parameterized quantum circuit is iteratively applied and measured to obtain local shadow features. Then all the obtained shadow features are calculated using the classical neural network and the predicted labels are obtained.\n",
"\n",
"### Workflow\n",
"\n",
"Based on the above principles, we only need to train the VSQL model using the MNIST dataset to obtain a converged model. The model can be used to classify handwritten digits. The training process of the model is as follows.\n",
"\n",
"![vsql-pipeline](vsql_pipeline_en.png)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## How to Use\n",
"\n",
"### Predict Using the Model\n",
"\n",
"Here, we have given a trained model that can be used directly for the prediction of 0 and 1 images. Just make the corresponding configuration in the `example.toml` configuration file and enter the command `python vsql_classification.py --config example.toml` to test the input images with the trained VSQL model.\n",
"\n",
"### Online Demo\n",
"\n",
"Here, we give a version of the online demo that can be tested online. First define the contents of the configuration file."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"test_toml = r\"\"\"\n",
"# The overall configuration file of the model.\n",
"# Enter the current task, which can be 'train' or 'test', representing training and prediction respectively. Here we use test, indicating that we want to make a prediction.\n",
"task = 'test'\n",
"# The file path of the image to be predicted.\n",
"image_path = 'data_0.png'\n",
"# Whether the image path above is a folder or not. For folder paths, we will predict all image files inside the folder. This way you can test multiple images at once.\n",
"is_dir = false\n",
"# The file path of the trained model parameter file.\n",
"model_path = 'vsql.pdparams'\n",
"# The number of qubits that the quantum circuit contains.\n",
"num_qubits = 10\n",
"# The number of qubits that the shadow circuit contains.\n",
"num_shadow = 2\n",
"# Circuit depth.\n",
"depth = 1\n",
"# The class to be predicted by the model. Here, 0 and 1 are classified.\n",
"classes = [0, 1]\n",
"\"\"\"\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Next is the code for the prediction section."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"For the input image, the model has 89.22% confidence that it is 0, and 10.78% confidence that it is 1.\n"
]
}
],
"source": [
"import os\n",
"import warnings\n",
"\n",
"warnings.filterwarnings('ignore')\n",
"os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'python'\n",
"\n",
"import toml\n",
"from paddle_quantum.qml.vsql import train, inference\n",
"\n",
"config = toml.loads(test_toml)\n",
"task = config.pop('task')\n",
"if task == 'train':\n",
" train(**config)\n",
"elif task == 'test':\n",
" prediction, prob = inference(**config)\n",
" if config['is_dir']:\n",
" print(f\"The prediction results of the input pictures are {str(prediction)[1:-1]} respectively.\")\n",
" else:\n",
" prob = prob[0]\n",
" msg = 'For the input image, the model has'\n",
" for idx, item in enumerate(prob):\n",
" if idx == len(prob) - 1:\n",
" msg += 'and'\n",
" label = config['classes'][idx]\n",
" msg += f' {item:3.2%} confidence that it is {label:d}'\n",
" msg += '.' if idx == len(prob) - 1 else ', '\n",
" print(msg)\n",
"else:\n",
" raise ValueError(\"Unknown task, it can be train or test.\")"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Here, we only need to modify the image path in the configuration file, and then run the entire code to quickly test other images."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Note\n",
"\n",
"The model we provide is a binary classification model that can only be used to distinguish handwritten digits 0 and 1. For other classification tasks, it needs to be retrained.\n",
"\n",
"### Dataset Structure\n",
"\n",
"If you want to use a custom dataset for training, you just need to prepare the dataset according to the rules. Prepare `train.txt` and `test.txt` in the dataset folder, and `dev.txt` if a validation set is needed. Use one line in each file to represent one piece of data. Each line contains the file path and label of the image, separated by tabs.\n",
"\n",
"### Introduction to the Configuration File\n",
"\n",
"In `test.toml`, there is a complete reference to the configuration files needed for testing. In `train.toml`, there is a complete reference to the configuration files needed for training. You can use the configuration file to quickly use the model to train and test."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Citation\n",
"\n",
"```tex\n",
"@inproceedings{li2021vsql,\n",
" title={VSQL: Variational shadow quantum learning for classification},\n",
" author={Li, Guangxi and Song, Zhixin and Wang, Xin},\n",
" booktitle={Proceedings of the AAAI Conference on Artificial Intelligence},\n",
" volume={35},\n",
" number={9},\n",
" pages={8357--8365},\n",
" year={2021}\n",
"}\n",
"```\n",
"\n",
"## Reference\n",
"\n",
"\\[1\\] \"THE MNIST DATABASE of handwritten digits\". Yann LeCun, Courant Institute, NYU Corinna Cortes, Google Labs, New York Christopher J.C. Burges, Microsoft Research, Redmond."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "py37",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.15 (default, Nov 10 2022, 12:46:26) \n[Clang 14.0.6 ]"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "49b49097121cb1ab3a8a640b71467d7eda4aacc01fc9ff84d52fcb3bd4007bf1"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}
# The full config for testing the VSQL model.
# The task of this config. Available values: 'train' | 'test'.
task = 'test'
# The path of the input images.
image_path = 'data_0.png'
# Whether the image_path is a directory. Available values: true | false.
# The value true means the path is a directory and all the images there will be predicted.
is_dir = false
# The path of the trained model, which will be loaded.
model_path = 'vsql.pdparams'
# The number of qubits which the quantum circuit contains.
num_qubits = 10
# The number of qubits which the shadow circuit contains.
num_shadow = 2
# The depth of the quantum circuit. Default to 1.
depth = 1
# The classes of handwrite digits to be predicted.
# It will use all labels if the value is not provided.
classes = [0, 1]
# The full config for training the VSQL model.
# The task of this config. Available values: 'train' | 'test'.
task = 'train'
# The name of the model, which is used to save the model.
model_name = 'vsql-model'
# The path to save the model. Both relative and absolute paths are allowed.
# It saves the model to the current path by default.
# saved_path = './'
# The number of qubits which the quantum circuit contains.
num_qubits = 10
# The number of qubits which the shadow circuit contains.
num_shadow = 2
# The depth of the quantum circuit, default to 1.
# depth = 1
# The size of the batch samplers.
batch_size = 16
# The number of epochs to train the model.
num_epochs = 10
# The learning rate used to update the parameters, default to 0.01.
# learning_rate = 0.01
# The path of the dataset. It defaults to MNIST, which is a built-in dataset.
dataset = 'MNIST'
# The classes of handwrite digits to be predicted.
# It will use all labels if the value is not provided.
classes = [0, 1]
# Whether use the validation.
# It is true means the dataset contains training, validation and test datasets.
# It is false means the dataset only contains training datasets and test datasets.
using_validation = false
# The number of the data in the training dataset.
# The value defaults to 0 which means using all data.
# num_train = 0
# The number of the data in the validation dataset.
# The value defaults to 0 which means using all data.
# num_dev = 0
# The number of the data in the test dataset.
# The value defaults to 0 which means using all data.
# num_test = 0
# Number of epochs with no improvement after which training will be stopped.
# early_stopping = 1000
# The number of subprocess to load data, 0 for no subprocess used and loading data in main process, defaults to 0.
# num_workers = 0
# !/usr/bin/env python3
# Copyright (c) 2022 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.
# 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.
import os
import warnings
warnings.filterwarnings('ignore')
os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'python'
import argparse
import toml
from paddle_quantum.qml.vsql import train, inference
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Classify the handwritten digits by the VSQL model.")
parser.add_argument("--config", type=str, help="Input the config file with toml format.")
args = parser.parse_args()
config = toml.load(args.config)
task = config.pop('task')
if task == 'train':
train(**config)
elif task == 'test':
prediction, prob = inference(**config)
if config['is_dir']:
print(f"The prediction results of the input pictures are {str(prediction)[1:-1]} respectively.")
else:
prob = prob[0]
msg = 'For the input image, the model has'
for idx, item in enumerate(prob):
if idx == len(prob) - 1:
msg += 'and'
label = config['classes'][idx]
msg += f' {item:3.2%} confidence that it is {label:d}'
msg += '.' if idx == len(prob) - 1 else ', '
print(msg)
else:
raise ValueError("Unknown task, it can be train or test.")
# The path of the input matrix A. It should be a .npy file.
A_dir = './A.npy'
# The path of the input vector b. It should be a .npy file.
b_dir = './b.npy'
# The depth of the quantum ansatz circuit.
depth = 4
# Number optimization cycls. Use 100 as a starting point and adjust depend on how low the loss function reaches.
# Ideally, you want to reach 0.0001
iterations = 100
# The learning rate of the optimizer.
LR = 0.1
# Threshold for loss value to end optimization early, default is 0.
gamma = 0
\ No newline at end of file
A_dir = './A.npy'
b_dir = './b.npy'
depth = 4
iterations = 100
LR = 0.1
gamma = 0
\ No newline at end of file
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"# 变分量子线性求解器\n",
"*Copyright (c) 2022 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.*\n",
"## 背景介绍\n",
"\n",
"线性方程组是数学中一个基本但非常有用的工具。 一个例子是,在经济学中,可以使用线性方程对经济进行建模。 此外,它还为非线性的大型系统提供了简单的估计。 因此求解线性方程组是一项重要的任务。\n",
"\n",
"变分量子线性求解器(Variational quantum linear solver, VQLS)是一种求解线性方程组的变分量子算法,采用了经典-量子混合的方案,可以在近期的含噪中等规模量子计算机上运行。具体来说,对于一个矩阵 $A$ 和一个向量 $\\boldsymbol{b}$,我们的目标是找到一个向量 $\\boldsymbol{x}$ 使得 $A \\boldsymbol{x} = \\boldsymbol{b}$. 使用 VQLS 算法可以得到一个与 $\\boldsymbol{x}$ 成比例的量子态,即一个归一化的向量 $|x\\rangle = \\frac{\\boldsymbol{x}}{\\lVert \\boldsymbol{x} \\rVert_2}$。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 模型原理\n",
"\n",
"量子场景的线性方程求解问题和通常的设定略有不同,因为量子计算需要将酉算子应用到量子态上。对于输入的矩阵 $A$,我们需要将其分解成酉算子的线性组合 $A = \\sum_n c_n A_n$,其中每个 $A_n$ 都是酉算子,可以在量子线路上运行。对于输入的向量 $\\boldsymbol{b}$,我们需要假设它是一个能够被某个酉算子 $U$ 制备的量子态 $|b\\rangle$,即 $U|0\\rangle = |b\\rangle$。我们可以用下面这张图来概括 VQLS 算法的整体架构:\n",
"\n",
"![VQLS](vqls.png)\n",
"\n",
"可以看到,VQLS 算法是一种混合优化算法,可以分为经典和量子两部分,需要在量子计算机上准备参数化量子电路 $V(\\alpha)$ 并计算损失函数 $C(\\alpha)$,然后在经典计算机上对参数 $\\alpha$ 进行优化从而最小化损失函数,直到损失低于某个阈值,最后输出目标量子态 $|x\\rangle$。其中参数化电路 $V(\\alpha)$ 可以生成一个量子态 $|\\psi(\\alpha)\\rangle$,电路 $F(A)$ 可以计算 $A|\\psi(\\alpha)\\rangle$ 与 $|b\\rangle$ 的近似程度,即损失函数 $C(\\alpha)$。当量子态 $A|\\psi(\\alpha)\\rangle$ 与 $|b\\rangle$ 足够接近时,这就意味着量子态 $|\\psi(\\alpha)\\rangle$ 与目标态 $|x\\rangle$ 足够接近,我们可以输出量子态 $|\\psi(\\alpha)\\rangle$ 作为目标态 $|x\\rangle$ 的近似。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 量桨实现\n",
"\n",
"我们使用量桨中的 `Circuit` 类结合飞桨优化器来实现 VQLS 算法,其中量子部分中参数化量子电路 $V(\\alpha)$ 为 `Circuit` 中内置的 `complex_entangled_layer` 模板,损失函数计算电路 $F(A)$ 由 Hadamard Test 或 Hadamard-Overlap Test 组成,主要使用了量桨中的 `oracle` 量子门来实现控制 $A_n$ 门,在经典优化部分中我们使用 Adam 优化器来最小化损失函数。\n",
"\n",
"用户可以使用 toml 文件指定算法的输入,矩阵 $A$ 和向量 $\\boldsymbol{b}$,分别以 `.npy` 文件形式存储。用户可以使用以下代码,通过改变$n$的值随机生成一个 $n\\times n$ 的矩阵 $A$ 以及向量 $\\boldsymbol{b}$。"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"这是一个随机生成的A:\n",
"[[4.1702199e+00+7.203245j 1.1437482e-03+3.0233257j\n",
" 1.4675589e+00+0.9233859j 1.8626021e+00+3.4556072j\n",
" 3.9676747e+00+5.3881674j ]\n",
" [2.0445225e+00+8.781175j 2.7387592e-01+6.704675j\n",
" 4.1730480e+00+5.5868983j 1.4038694e+00+1.9810148j\n",
" 8.0074453e+00+9.682616j ]\n",
" [8.7638912e+00+8.946067j 8.5044211e-01+0.39054784j\n",
" 1.6983042e+00+8.781425j 9.8346835e-01+4.2110763j\n",
" 9.5788956e+00+5.3316526j ]\n",
" [6.8650093e+00+8.346256j 1.8288277e-01+7.5014434j\n",
" 9.8886108e+00+7.4816566j 2.8044400e+00+7.892793j\n",
" 1.0322601e+00+4.4789352j ]\n",
" [2.8777535e+00+1.3002857j 1.9366957e-01+6.7883554j\n",
" 2.1162813e+00+2.6554666j 4.9157314e+00+0.5336254j\n",
" 5.7411761e+00+1.4672858j ]]\n",
"这是一个随机生成的b:\n",
"[4.191945 +6.852195j 3.1342418+6.9232264j 6.9187713+3.1551564j\n",
" 9.085955 +2.9361415j 5.8930554+6.9975834j]\n"
]
}
],
"source": [
"n = 5\n",
"\n",
"import numpy as np\n",
"\n",
"\n",
"np.random.seed(1)\n",
"A = np.zeros([n, n], dtype=\"complex64\")\n",
"b = np.zeros(n, dtype=\"complex64\")\n",
"for i in range(n):\n",
" for j in range(n):\n",
" x = np.random.rand() * 10\n",
" y = np.random.rand() * 10\n",
" A[i][j] = complex(x, y)\n",
" x = np.random.rand() * 10\n",
" y = np.random.rand() * 10\n",
" b[i] = complex(x, y)\n",
"np.save(\"./A.npy\", A)\n",
"np.save(\"./b.npy\", b)\n",
"print(\"这是一个随机生成的A:\")\n",
"print(A)\n",
"print(\"这是一个随机生成的b:\")\n",
"print(b)\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"用户可以在 toml 文件中指定 VQLS 算法的参数 `depth`,`iterations`,`LR` 以及 `gamma`,分别对应参数化量子电路 $V(\\alpha)$ 的层数,优化器的迭代次数,优化器的学习率,和损失函数的阈值。在命令行输入 `python vqls.py --config config.toml` 即可完成线性方程组求解。这里我们给出一个在线演示的例子,首先定义配置文件的内容如下,用户可以自行更改 `test_toml` 中的参数:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"test_toml = r\"\"\"\n",
"# 存储矩阵A的.npy文件的路径。\n",
"A_dir = './A.npy'\n",
"# 存储向量b的.npy文件的路径。\n",
"b_dir = './b.npy'\n",
"# 参数化量子电路的层数。\n",
"depth = 4\n",
"# 优化器迭代次数。\n",
"iterations = 200\n",
"# 优化器的学习率。\n",
"LR = 0.1\n",
"# 损失函数的阈值。默认为0。\n",
"gamma = 0\n",
"\"\"\""
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"运行 VQLS 算法如下:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"c:\\Users\\yuzhan01\\Miniconda3\\envs\\pq_model\\lib\\site-packages\\paddle\\tensor\\creation.py:125: DeprecationWarning: `np.object` is a deprecated alias for the builtin `object`. To silence this warning, use `object` by itself. Doing this will not modify any behavior and is safe. \n",
"Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations\n",
" if data.dtype == np.object:\n",
" 88%|████████▊ | 176/200 [02:04<00:16, 1.42it/s]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Threshold value gamma reached, ending optimization\n",
"这是求解Ax=b的x: [ 1.3475237 -0.7860472j 0.22970617-0.88826376j -0.35111237-0.31225887j\n",
" 0.07606918+1.2138402j -0.729564 +0.48393282j]\n",
"实际b的值: [4.191945 +6.852195j 3.1342418+6.9232264j 6.9187713+3.1551564j\n",
" 9.085955 +2.9361415j 5.8930554+6.9975834j]\n",
"算法得到的Ax的值: [4.185339 +6.8523855j 3.1297188+6.923625j 6.924285 +3.1467872j\n",
" 9.092921 +2.932943j 5.8879805+6.999589j ]\n",
"相对误差: 0.0008446976\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"\n"
]
}
],
"source": [
"import argparse\n",
"import os\n",
"import warnings\n",
"\n",
"warnings.filterwarnings(\"ignore\")\n",
"os.environ[\"PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION\"] = \"python\"\n",
"\n",
"import toml\n",
"import numpy as np\n",
"import paddle\n",
"from paddle_quantum.data_analysis.vqls import compute\n",
"\n",
"paddle.seed(0)\n",
"\n",
"if __name__ == \"__main__\":\n",
" config = toml.loads(test_toml)\n",
" A_dir = config.pop(\"A_dir\")\n",
" A = np.load(A_dir)\n",
" b_dir = config.pop(\"b_dir\")\n",
" b = np.load(b_dir)\n",
" result = compute(A, b, **config)\n",
"\n",
" print(\"求解 Ax=b 的x:\", result)\n",
" print(\"实际 b 的值:\", b)\n",
" print(\"算法得到的 Ax 的值:\", np.matmul(A, result))\n",
" relative_error = np.linalg.norm(b - np.matmul(A, result)) / np.linalg.norm(b)\n",
" print(\"相对误差: \", relative_error)\n",
" np.save(\"./answer.npy\", result)\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 引用信息\n",
"\n",
"```\n",
"@misc{bravo-prieto2020variational,\n",
" title = {Variational {{Quantum Linear Solver}}},\n",
" author = {{Bravo-Prieto}, Carlos and LaRose, Ryan and Cerezo, M. and Subasi, Yigit and Cincio, Lukasz and Coles, Patrick J.},\n",
" year = {2020},\n",
" month = jun,\n",
" number = {arXiv:1909.05820},\n",
" eprint = {1909.05820},\n",
" eprinttype = {arxiv},\n",
" doi = {10.48550/arXiv.1909.05820}\n",
"}\n",
"```\n",
"\n",
"## 参考文献\n",
"\n",
"[1] “Variational Quantum Linear Solver: A Hybrid Algorithm for Linear Systems.” Carlos Bravo-Prieto, Ryan LaRose, Marco Cerezo, Yigit Subasi, Lukasz Cincio, Patrick J. Coles. arXiv:1909.05820, 2019."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "pq-dev",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.15 (default, Nov 10 2022, 13:17:42) \n[Clang 14.0.6 ]"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "5fea01cac43c34394d065c23bb8c1e536fdb97a765a18633fd0c4eb359001810"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"# Variational Quantum Linear Solver\n",
"*Copyright (c) 2022 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.*\n",
"## Background\n",
"\n",
"System of linear equations is a basic yet extremely useful tool in mathematics. An example is that in economics, you can model the economy using linear equations. Also, it provides simple estimation for large system of non-linear systems. Hence solving system of linear equations is an important task.\n",
"\n",
"Variational Quantum Linear Solver (VQLS) is a variational quantum algorithm for solving system of linear equations. It's a classical-quantum hybrid algorithm that can run on recent Noisy Intermediate-Scale Quantum (NISQ) devices. To be more specific, given a matrix $A$ and a vector $\\boldsymbol{b}$, our goal is to find a vector $\\boldsymbol{x}$ so that $A \\boldsymbol{x} = \\boldsymbol{b}$. Using VQLS, we can obtain a quantum state that is proportional to $\\boldsymbol{x}$, i.e. a normalised vector $|x\\rangle = \\frac{\\boldsymbol{x}}{\\lVert \\boldsymbol{x} \\rVert_2}$."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Model Principle\n",
"\n",
"Solving linear equations in the quantum setting is different to the general setting due to the requirement in quantum computing that we can only apply unitary operators to a quantum state. For the input matrix $A$, we need to decompose it to a linear combination of unitary operators $A = \\sum_n c_n A_n$ where each $A_n$ is a unitary operator. For the input vector $\\boldsymbol{b}$, we need to assume that it's a quantum state that can be prepared by unitary operator $U$, i.e. $U|0\\rangle = |b\\rangle$.\n",
"\n",
"![VQLS](vqls.png)\n",
"\n",
"We can see that the algorithm consists of two parts. On a quantum computer, we prepare a parameterized quantum circuit (PQC) $V(\\alpha)$ and compute the loss function $C(\\alpha)$, then on a classical computer, we minimize parameters $\\alpha$ until the loss function is below a certain threshold, denoted as $\\gamma$. At the end, we output the target quantum state $|x\\rangle$. The main idea behind the algorithm is that PQC $V(\\alpha)$ gives us a quantum state $|\\psi(\\alpha)\\rangle$, circuit $F(A)$ then computes how similar $A|\\psi(\\alpha)\\rangle$ and $|b\\rangle$ are, which is what the loss function $C(\\alpha)$ is measuring. When the loss is small, $A|\\psi(\\alpha)\\rangle$ and $|b\\rangle$ are very close, it means $|\\psi(\\alpha)\\rangle$ and the target $|x\\rangle$ are very close, so we output $|\\psi(\\alpha)\\rangle$ as an approximation to $|x\\rangle$."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Paddle Quantum Implementation\n",
"\n",
"We use the `Circuit` class in Paddle Quantum and optimizer in Paddle Paddle to implement VQLS. For the quantum part, we use built-in `complex_entangled_layer` ansatz to build our PQC $V(\\alpha)$. To compute the loss function, we use Hadamard Test and Hadamard-Overlap Test which utilizes `oracle` gate to implement the controlled-$A_n$ gates. For the classical optimization part, we used Adam optimizer to minimize the loss function.\n",
"\n",
"User can use toml file to specify the input to the algorithm, matrix $A$ and vector $\\boldsymbol{b}$, stored as '.npy' files. You can run the following code to randomly generate a $n\\times n$ matrix $A$ and vector $\\boldsymbol{b}$:"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Here is a randomly generated A:\n",
"[[4.1702199e+00+7.203245j 1.1437482e-03+3.0233257j\n",
" 1.4675589e+00+0.9233859j 1.8626021e+00+3.4556072j\n",
" 3.9676747e+00+5.3881674j ]\n",
" [2.0445225e+00+8.781175j 2.7387592e-01+6.704675j\n",
" 4.1730480e+00+5.5868983j 1.4038694e+00+1.9810148j\n",
" 8.0074453e+00+9.682616j ]\n",
" [8.7638912e+00+8.946067j 8.5044211e-01+0.39054784j\n",
" 1.6983042e+00+8.781425j 9.8346835e-01+4.2110763j\n",
" 9.5788956e+00+5.3316526j ]\n",
" [6.8650093e+00+8.346256j 1.8288277e-01+7.5014434j\n",
" 9.8886108e+00+7.4816566j 2.8044400e+00+7.892793j\n",
" 1.0322601e+00+4.4789352j ]\n",
" [2.8777535e+00+1.3002857j 1.9366957e-01+6.7883554j\n",
" 2.1162813e+00+2.6554666j 4.9157314e+00+0.5336254j\n",
" 5.7411761e+00+1.4672858j ]]\n",
"Here is a randomly generated b:\n",
"[4.191945 +6.852195j 3.1342418+6.9232264j 6.9187713+3.1551564j\n",
" 9.085955 +2.9361415j 5.8930554+6.9975834j]\n"
]
}
],
"source": [
"n = 5\n",
"\n",
"import numpy as np\n",
"\n",
"\n",
"np.random.seed(1)\n",
"A = np.zeros([n, n], dtype=\"complex64\")\n",
"b = np.zeros(n, dtype=\"complex64\")\n",
"for i in range(n):\n",
" for j in range(n):\n",
" x = np.random.rand() * 10\n",
" y = np.random.rand() * 10\n",
" A[i][j] = complex(x, y)\n",
" x = np.random.rand() * 10\n",
" y = np.random.rand() * 10\n",
" b[i] = complex(x, y)\n",
"np.save(\"./A.npy\", A)\n",
"np.save(\"./b.npy\", b)\n",
"print(\"Here is a randomly generated A:\")\n",
"print(A)\n",
"print(\"Here is a randomly generated b:\")\n",
"print(b)\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"User can specify the parameters of the VQLS in the toml file. They are `depth`, `iterations`, `LR` and `gamma`, which correspond to the number of layer in the PQC $V(\\alpha)$, number of iterations of the optimizer, learning rate of the optimizer and threshold of the loss function to end optimization early. By entering `python vqls.py --config config.toml` one could solve the linear system. Here we present an example of an online demo. First, define the content of the configuration file as follows, user can try out different settings by changing the parameters of `test_toml`:"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [],
"source": [
"test_toml = r\"\"\"\n",
"# The path of the input matrix A. It should be a .npy file.\n",
"A_dir = './A.npy'\n",
"# The path of the input vector b. It should be a .npy file.\n",
"b_dir = './b.npy'\n",
"# The depth of the quantum ansatz circuit.\n",
"depth = 4\n",
"# Number optimization cycles.\n",
"iterations = 200\n",
"# The learning rate of the optimizer.\n",
"LR = 0.1\n",
"# Threshold for loss value to end optimization early, default is 0.\n",
"gamma = 0\n",
"\"\"\""
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Then we run the VQLS:"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
" 88%|████████▊ | 176/200 [02:03<00:16, 1.43it/s]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Threshold value gamma reached, ending optimization\n",
"Here is x that solves Ax=b: [ 1.3475237 -0.7860472j 0.22970617-0.88826376j -0.35111237-0.31225887j\n",
" 0.07606918+1.2138402j -0.729564 +0.48393282j]\n",
"This is actual b: [4.191945 +6.852195j 3.1342418+6.9232264j 6.9187713+3.1551564j\n",
" 9.085955 +2.9361415j 5.8930554+6.9975834j]\n",
"This is Ax using estimated x: [4.185339 +6.8523855j 3.1297188+6.923625j 6.924285 +3.1467872j\n",
" 9.092921 +2.932943j 5.8879805+6.999589j ]\n",
"Relative error: 0.0008446976\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"\n"
]
}
],
"source": [
"import argparse\n",
"import os\n",
"import warnings\n",
"\n",
"warnings.filterwarnings(\"ignore\")\n",
"os.environ[\"PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION\"] = \"python\"\n",
"\n",
"import toml\n",
"import numpy as np\n",
"import paddle\n",
"from paddle_quantum.data_analysis.vqls import compute\n",
"\n",
"paddle.seed(0)\n",
"\n",
"if __name__ == \"__main__\":\n",
" config = toml.loads(test_toml)\n",
" A_dir = config.pop(\"A_dir\")\n",
" A = np.load(A_dir)\n",
" b_dir = config.pop(\"b_dir\")\n",
" b = np.load(b_dir)\n",
" result = compute(A, b, **config)\n",
"\n",
" print(\"Here is x that solves Ax=b:\", result)\n",
" print(\"This is actual b:\", b)\n",
" print(\"This is Ax using estimated x:\", np.matmul(A, result))\n",
" relative_error = np.linalg.norm(b - np.matmul(A, result)) / np.linalg.norm(b)\n",
" print(\"Relative error: \", relative_error)\n",
" np.save(\"./answer.npy\", result)\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Citation\n",
"\n",
"```\n",
"@misc{bravo-prieto2020variational,\n",
" title = {Variational {{Quantum Linear Solver}}},\n",
" author = {{Bravo-Prieto}, Carlos and LaRose, Ryan and Cerezo, M. and Subasi, Yigit and Cincio, Lukasz and Coles, Patrick J.},\n",
" year = {2020},\n",
" month = jun,\n",
" number = {arXiv:1909.05820},\n",
" eprint = {1909.05820},\n",
" eprinttype = {arxiv},\n",
" doi = {10.48550/arXiv.1909.05820}\n",
"}\n",
"```\n",
"\n",
"## References\n",
"\n",
"[1] “Variational Quantum Linear Solver: A Hybrid Algorithm for Linear Systems.” Carlos Bravo-Prieto, Ryan LaRose, Marco Cerezo, Yigit Subasi, Lukasz Cincio, Patrick J. Coles. arXiv:1909.05820, 2019."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "pq-dev",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.15 (default, Nov 10 2022, 13:17:42) \n[Clang 14.0.6 ]"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "5fea01cac43c34394d065c23bb8c1e536fdb97a765a18633fd0c4eb359001810"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}
# !/usr/bin/env python3
# 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.
# 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.
r"""
Variational Quantum Linear Solver
"""
import argparse
import os
import warnings
warnings.filterwarnings('ignore')
os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'python'
import toml
import logging
import numpy as np
from paddle_quantum.data_analysis.vqls import compute
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Solve system of linear equations.")
parser.add_argument("--config", type=str, help="Input the config file with toml format.")
args = parser.parse_args()
config = toml.load(args.config)
A_dir = config.pop('A_dir')
A = np.load(A_dir)
b_dir = config.pop('b_dir')
b = np.load(b_dir)
result = compute(A, b, **config)
print('Here is x that solves Ax=b:', result)
relative_error = np.linalg.norm(b- np.matmul(A,result))/np.linalg.norm(b)
print('Relative error: ', relative_error)
logging.basicConfig(
filename='./linear_solver.log',
filemode='w',
format='%(asctime)s %(levelname)s %(message)s',
level=logging.INFO
)
msg = f"Relative error: {relative_error}"
logging.info(msg)
np.save('./answer.npy', result)
\ No newline at end of file
# A description of the task of this configuration file, this is optional. "GroundState" stands for calculate the ground state energy of the molecule.
task = 'GroundState'
# This field stores information related to the molecule is provided.
[molecule]
# Symbols of atoms inside the molecule.
symbols = ['H', 'H']
# The cartesian coordinates of each atom inside the molecule.
coords = [ [ 0.0, 0.0, 0.0 ], [ 0.0, 0.0, 0.7 ] ]
# Quantum chemistry basis set used in the computation, see here for more information of the basis set, https://baike.baidu.com/item/%E5%9F%BA%E7%BB%84/6445527?fr=aladdin, Default is "sto-3g".
basis = 'sto-3g'
# Which unit system is used in the `coords` provided above.
# If set to `true` will use Angstrom.
# If set to `false` will use Bohr.
use_angstrom = true
# This field specifies configurations of classical quantum chemistry driver used to calculate the molecular integrals. NOTE: Classical quantum chemistry package needs to be preinstalled.
[driver]
# If set to `pyscf`, means PySCF is used (currently only support `pyscf` driver, will add more classical driver in the future).
name = 'pyscf'
# This field specifies configurations related to the quantum circuit in VQE is specified.
# NOTE: currently only support HardwareEfficient ansatz, more ansatz will come later!
[ansatz.HardwareEfficient]
# The depth of the HardwareEfficient ansatz. NOTE: on a personal laptop, we suggest the depth of the circuit should no more than 10.
depth = 2
# This field stores configurations of the variational quantum eigensolver (VQE) method.
[VQE]
# Number of optimization cycles, default is 100.
num_iterations = 100
# The convergence criteria for the VQE optimization, default is 1e-5.
tol = 1e-5
# The number of optimization steps after which we record the loss value.
save_every = 10
# This field specifies the optimizer used in the VQE method, default is `Adam`, see here for available optimizers https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/optimizer/Overview_cn.html
[optimizer.Adam]
# The learning rate of the optimizer, see here for more details https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/optimizer/Adam_cn.html, default is 0.4.
learning_rate = 0.4
# !/usr/bin/env python3
# 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.
# 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.
from typing import Dict
import time
import logging
import argparse
import toml
import paddle.optimizer as optim
from paddle_quantum import qchem
from paddle_quantum.qchem import Molecule
from paddle_quantum.qchem import PySCFDriver
from paddle_quantum.qchem import GroundStateSolver
from paddle_quantum.qchem import energy, dipole_moment
#BUG: basicConfig changed in python3.7
logging.basicConfig(filename="log", filemode="w", format="%(message)s", level=logging.INFO)
def main(args):
time_start = time.strftime("%Y%m%d-%H:%M:%S", time.localtime())
logging.info(f"Job start at {time_start:s}")
parsed_configs: Dict = toml.load(args.config)
# create molecule
atom_symbols = parsed_configs["molecule"]["symbols"]
basis = parsed_configs["molecule"].get("basis", "sto-3g")
multiplicity = parsed_configs["molecule"].get("multiplicity")
charge = parsed_configs["molecule"].get("charge")
use_angstrom = parsed_configs["molecule"].get("use_angstrom", True)
if parsed_configs.get("driver") is None or parsed_configs["driver"]["name"] == "pyscf":
driver = PySCFDriver()
else:
raise NotImplementedError("Drivers other than PySCFDriver are not implemented yet.")
if isinstance(atom_symbols, str):
raise NotImplementedError("`load_geometry` function is not implemented yet.")
elif isinstance(atom_symbols, list):
atom_coords = parsed_configs["molecule"]["coords"]
geometry = list(zip(atom_symbols, atom_coords))
mol = Molecule(geometry, basis, multiplicity, charge, use_angstrom=use_angstrom, driver=driver)
else:
raise ValueError("Symbols can only be string or list, e.g. 'LiH' or ['H', 'Li']")
mol.build()
# create ansatz
num_qubits = mol.num_qubits
ansatz_settings = parsed_configs["ansatz"]
ansatz_name = list(ansatz_settings.keys())[0]
ansatz_class = getattr(qchem, ansatz_name)
ansatz = ansatz_class(num_qubits, **ansatz_settings[ansatz_name])
# load optimizer
if parsed_configs.get("optimizer") is None:
optimizer_name = "Adam"
optimizer_settings = {
"Adam": {
"learning_rate": 0.4
}
}
optimizer = optim.Adam
else:
optimizer_settings = parsed_configs["optimizer"]
optimizer_name = list(optimizer_settings.keys())[0]
optimizer = getattr(optim, optimizer_name)
# calculate properties
if parsed_configs.get("VQE") is None:
vqe_settings = {
"num_iterations": 100,
"tol": 1e-5,
"save_every": 10
}
else:
vqe_settings = parsed_configs["VQE"]
solver = GroundStateSolver(optimizer, **vqe_settings)
_, psi = solver.solve(mol, ansatz, **optimizer_settings[optimizer_name])
e = energy(psi, mol)
d = dipole_moment(psi, mol)
logging.info("\n#######################################\nSummary\n#######################################")
logging.info(f"Ground state energy={e:.5f}")
logging.info(f"dipole moment=({d[0]:.5f}, {d[1]:.5f}, {d[2]:.5f}).")
time_stop = time.strftime("%Y%m%d-%H:%M:%S", time.localtime())
logging.info(f"\nJob end at {time_stop:s}\n")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Quantum chemistry task with paddle quantum.")
parser.add_argument("--config", type=str, help="Input the config file with toml format.")
main(parser.parse_args())
[molecule]
symbols = ['H', 'H']
coords = [ [ 0.0, 0.0, 0.0 ], [ 0.0, 0.0, 0.74 ] ]
# NOTE: currently only support HardwareEfficient ansatz, more ansatz will come later!
# NOTE: on a personal laptop, we suggest the depth of the circuit should no more than 10.
[ansatz.HardwareEfficient]
depth = 2
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import warnings\n",
"\n",
"warnings.filterwarnings('ignore')"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"# 锂电池材料计算简介\n",
"\n",
"*Copyright (c) 2022 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.*\n",
"\n",
"锂电池是一种高效、长寿命的电池,广泛用于各种消费类电子产品、工业设备和汽车动力系统中。锂电池的发展促进了电动汽车的普及,也为可再生能源储存提供了重要支撑。由于锂电池具有轻量、高能量密度和环保等优点,其应用前景广阔,且行业发展前景好。目前,锂电池行业正在经历快速发展,并不断创新和推广新技术。\n",
"\n",
"在锂电池中,能量主要通过电池正负极物质之间的电化学反应产生,\n",
"$$\n",
"LiC_6+CoO_2\\stackrel{放电}{\\underset{\\text{充电}}{\\rightleftarrows}}6C+LiCoO_2.\n",
"$$\n",
"\n",
"根据热力学规律,这个能量等于放电反应前后正负极物质自由能\\[1\\]的变化量,在多数情况下,它可以通过反应前后物质的基态能量差进行估计\\[2\\]\n",
"$$\n",
"\\Delta G=G_{\\text{LiCoO}_2}+6G_{\\text{C}}-G_{\\text{CoO}_2}-G_{\\text{LiC}_6}.\n",
"$$\n",
"\n",
"综上,由于化学反应的能量与反应方程式两侧分子/物质的能量有紧密联系,我们在衡量锂电池释放的总能量时就需要对相关分子/物质的基态能量有比较精确的估计。同时,反应中锂离子通过电解液在正负极之间迁移的过程也会涉及到离子在分子和材料表面的吸附,这会受到分子电极化情况的影响。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 利用量子计算化学方法计算分子基态性质\n",
"### 构建分子哈密顿量\n",
"分子哈密顿量由分子的几何结构和组成的原子决定,利用 `paddle_quantum` 的 `qchem` 模块,用户可以很方便地完成从分子的结构到哈密顿量的计算过程。"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"from paddle_quantum.qchem import Molecule, PySCFDriver\n",
"\n",
"mol = Molecule(\n",
" geometry = [(\"H\", [0.0, 0.0, 0.0]), (\"H\", [0.0, 0.0, 0.7])],\n",
" driver = PySCFDriver()\n",
")"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"由此,我们就新建了一个氢分子模型。在上面的代码中,`driver` 是用来计算哈密顿量中分子积分所使用的经典量子化学计算工具。"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"converged SCF energy = -1.11734903499028\n",
"-0.04207897647782183 I\n",
"0.17771287465139923 Z0\n",
"0.17771287465139923 Z1\n",
"-0.24274280513140506 Z2\n",
"-0.24274280513140506 Z3\n",
"0.17059738328801052 Z0, Z1\n",
"0.12293305056183806 Z0, Z2\n",
"0.16768319457718972 Z0, Z3\n",
"0.16768319457718972 Z1, Z2\n",
"0.12293305056183806 Z1, Z3\n",
"0.1762764080431961 Z2, Z3\n",
"-0.044750144015351656 X0, X1, Y2, Y3\n",
"0.044750144015351656 X0, Y1, Y2, X3\n",
"0.044750144015351656 Y0, X1, X2, Y3\n",
"-0.044750144015351656 Y0, Y1, X2, X3\n"
]
}
],
"source": [
"h = mol.get_molecular_hamiltonian()\n",
"print(h)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"这样就构造了一个氢分子在 `STO-3G` 基组下的哈密顿量。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### 搭建用于变分量子算法(VQE)的量子线路\n",
"变分量子算法通过使用经典优化器对量子算法中的可调参数进行优化的方式完成经典-量子混合计算,相比于经典算法,它可以在某些情况下更快地求解具有高维特征的优化问题。接下来,我们按照\\[2\\]中给出的方法构建如下图所示的量子线路。"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"converged SCF energy = -1.11734903499028\n"
]
},
{
"data": {
"image/png": "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",
"text/plain": [
"<Figure size 534x220 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from paddle_quantum.qchem import HardwareEfficient\n",
"\n",
"mol.build()\n",
"cir = HardwareEfficient(mol.num_qubits, depth=2)\n",
"cir.plot()"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### 计算氢分子势能面\n",
"下面我们通过计算氢分子势能面的任务来展示一下 VQE 方法的使用。分子势能面刻画了分子的能量随着分子内部原子的空间位置变化的规律,它在物理和化学中有很广泛的应用,经常被用于寻找分子的最优几何结构以及计算化学反应速率。对于氢分子来说,因为内部只有一个空间自由度(两个氢原子之间的距离),它的势能面实际上是一条曲线。"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"converged SCF energy = 2.71588739329275\n",
"converged SCF energy = -0.593827758535727\n",
"converged SCF energy = -1.04299627454009\n",
"converged SCF energy = -1.11675930739643\n",
"converged SCF energy = -1.09191404102006\n",
"converged SCF energy = -1.06610864931794\n",
"converged SCF energy = -0.910873554594387\n",
"converged SCF energy = -0.783792654277353\n"
]
}
],
"source": [
"import numpy as np\n",
"import paddle\n",
"from paddle.optimizer import Adam\n",
"from paddle_quantum.qchem import GroundStateSolver\n",
"from paddle_quantum.qchem import dipole_moment\n",
"\n",
"paddle.seed(124)\n",
"\n",
"cir_depth = 2\n",
"bond_lengthes = [0.1, 0.3, 0.5, 0.74, 0.9, 1.0, 1.5, 2.0]\n",
"energies = []\n",
"dipole_moments = []\n",
"for bond_len in bond_lengthes:\n",
" mol = Molecule(\n",
" geometry = [(\"H\", [0.0, 0.0, 0.0]), (\"H\", [0.0, 0.0, bond_len])],\n",
" driver = PySCFDriver()\n",
" )\n",
" mol.build()\n",
" \n",
" cir = HardwareEfficient(mol.num_qubits, cir_depth)\n",
"\n",
" solver = GroundStateSolver(Adam, num_iterations=100, tol=1e-5)\n",
" e, psi = solver.solve(mol, cir, learning_rate=0.5)\n",
" energies.append(e)\n",
"\n",
" # calculate dipole moments\n",
" d = dipole_moment(psi, mol)\n",
" dipole_moments.append(np.linalg.norm(d))"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"我们画出计算结果,可以看出氢分子的基态能量随着两个氢原子之间的距离增大先下降后上升,能量最低点对应的键长(也即平衡位置)为 0.74 埃。氢分子是一个非极性的分子,不管键长如何变化,它的偶极矩始终为零。"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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fvlFo31Xq1YNW7duxfbt29GwYUMsX74c06dPB/Dyqz+5XI4JEyaozletWrXwww8/AABcXV0xZ84cBAUFwcnJCQEBAQUey9XVFXv37sXp06fh7e2NcePGYdSoUfjss8+0Oh/52bRpE9566y24u7u/9r6Iyjq2uWxz2eaWDRKRs7+bSI917doVzs7O+Pnnn0tk/x9//DESExOxcuXKEtl/TgsWLMCKFSvw4MGDEj9WccjIyEDNmjWxceNGtGnTRtfhEFEpYJurO2xzX+LNXqSXUlNTsWLFCvj4+MDAwACbNm3CoUOHcPDgwRI75vTp0/HDDz9AoVC89ldCuf3www9o3rw5KlWqhBMnTuCrr74q9FN+WXP//n18+umnFb5BJSqv2OaWLWxzX2KPLOml58+fo3fv3jh//jzS0tLg5eWFzz77DO+8846uQyuSjz76CJs3b0ZcXByqVq2K9957D9OmTYOhIT9rEpHusc2lsoqJLBERERHpJd7sRURERER6iYksEREREeklJrJEREREpJeYyBIRERGRXmIiS0RERER6iYksEREREeklJrJEREREpJeYyBIRERGRXmIiS0RERER66f8llUqVQXVHtgAAAABJRU5ErkJggg==",
"text/plain": [
"<Figure size 700x300 with 2 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import matplotlib.pyplot as plt\n",
"\n",
"fig = plt.figure(figsize=(7, 3), )\n",
"ax1 = fig.add_subplot(121)\n",
"ax1.plot(bond_lengthes, energies)\n",
"ax1.set_xlabel(\"Bond length (Angstrom)\")\n",
"ax1.set_ylabel(\"Energy (Hartree)\")\n",
"ax1.set_title(\"Potential energy curve\")\n",
"\n",
"ax2 = fig.add_subplot(122)\n",
"ax2.plot(bond_lengthes, dipole_moments)\n",
"ax2.set_xlabel(\"Bond length (Angstrom)\")\n",
"ax2.set_ylabel(\"Dipole moment\")\n",
"ax2.set_title(\"Dipole moment variation\")\n",
"ax2.set_ylim(-0.5, 0.5)\n",
"fig.tight_layout()"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 如何使用\n",
"用户可以通过编辑配置文件`config.toml`对计算任务进行自定义,其中用户需要设置的参数如下:\n",
"```toml\n",
"# A description of the task of this configuration file, this is optional. \"GroundState\" stands for calculate the ground state energy of the molecule.\n",
"\n",
"# This field stores information related to the molecule is provided.\n",
"[molecule]\n",
"# Symbols of atoms inside the molecule.\n",
"symbols = ['H', 'H']\n",
"# The cartesian coordinates of each atom inside the molecule.\n",
"coords = [ [ 0.0, 0.0, 0.0 ], [ 0.0, 0.0, 0.7 ] ]\n",
"\n",
"# This field specifies configurations related to the quantum circuit in VQE is specified.\n",
"[ansatz.HardwareEfficient]\n",
"# The depth of the HardwareEfficient ansatz.\n",
"depth = 2\n",
"\n",
"# This field stores configurations of the variational quantum eigensolver (VQE) method. \n",
"[VQE]\n",
"# Number of optimization cycles, default is 100.\n",
"num_iterations = 100\n",
"```\n",
"用户可以通过在命令行中运行\n",
"```shell\n",
"python energy_material.py --config example.toml\n",
"```\n",
"的方式来完成量子化学计算任务。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 参考文献\n",
"\\[1\\] [百度百科-自由能](https://baike.baidu.com/item/%E8%87%AA%E7%94%B1%E8%83%BD/813477?fr=aladdin)\n",
"\n",
"\\[2\\] Aydinol, M. K., et al. \"Ab initio study of lithium intercalation in metal oxides and metal dichalcogenides.\" Physical Review B 56.3 (1997): 1354.\n",
"\n",
"\\[3\\] Kandala, Abhinav, et al. \"Hardware-efficient variational quantum eigensolver for small molecules and quantum magnets.\" Nature 549.7671 (2017): 242-246."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "pq-dev",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.15 (default, Nov 10 2022, 13:17:42) \n[Clang 14.0.6 ]"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "5fea01cac43c34394d065c23bb8c1e536fdb97a765a18633fd0c4eb359001810"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import warnings\n",
"\n",
"warnings.filterwarnings('ignore')"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"# Introduction to computational study of lithium ion battery\n",
"*Copyright (c) 2022 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.*\n",
"\n",
"Lithium ion battery is an efficient and long-lasting battery, it has been widely used in various consumer electronics, industrial devices and automotive power systems. The development of lithium ion battery has promoted the popularization of electric vehicles and provided strong support for storage of renewable energy. Due to the advantages of lithium batteries, such as being lightweight, having high energy density, and being environmentally friendly, they have a wide range of applications and a good industry development prospect. Currently, the industry of lithium ion battery is under rapid development and is continuously innovating and promoting new technologies.\n",
"\n",
"The energy of lithium ion battery is generated by the electron-chemical interaction between its cathode and anode materials.\n",
"$$\n",
"LiC_6+CoO_2\\stackrel{Discharge}{\\underset{\\text{Charge}}{\\rightleftarrows}}6C+LiCoO_2.\n",
"$$\n",
"\n",
"According to the thermodynamics, this energy equals the difference of free energy \\[1\\] between materials in cathode and anode, which can be approximated by their ground state energy difference\\[2\\].\n",
"$$\n",
"\\Delta G=G_{\\text{LiCoO}_2}+6G_{\\text{C}}-G_{\\text{CoO}_2}-G_{\\text{LiC}_6}.\n",
"$$\n",
"\n",
"Since the energy emitted during the chemical reaction is closely related to the molecules/materials occur in above formula, we have to obtain the accurate ground state energy of these molecules/materials once we want to estimate the total energy of the lithium ion battery. Meanwhile, the transport of lithium ion between the cathode and anode involves ion adsorption, which can be affected by the polarizability of related molecules."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Calculate ground state properties of molecule by quantum computational chemistry\n",
"### Build molecular Hamiltonian\n",
"The Hamiltonian of molecule is determined by its geometry and composition. Though the underlying procedure is a little complicated, users can easily achieve it by using `paddle_quantum`'s `qchem` module."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"from paddle_quantum.qchem import Molecule, PySCFDriver\n",
"\n",
"mol = Molecule(\n",
" geometry = [(\"H\", [0.0, 0.0, 0.0]), (\"H\", [0.0, 0.0, 0.7])],\n",
" driver = PySCFDriver()\n",
")"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we have built a hydrogen molecule model. In the code above, the `driver` is used to specify the classical quantum chemistry tool used in calculation of molecular integrals."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"converged SCF energy = -1.11734903499028\n",
"-0.04207897647782183 I\n",
"0.17771287465139923 Z0\n",
"0.17771287465139923 Z1\n",
"-0.24274280513140506 Z2\n",
"-0.24274280513140506 Z3\n",
"0.17059738328801052 Z0, Z1\n",
"0.12293305056183806 Z0, Z2\n",
"0.16768319457718972 Z0, Z3\n",
"0.16768319457718972 Z1, Z2\n",
"0.12293305056183806 Z1, Z3\n",
"0.1762764080431961 Z2, Z3\n",
"-0.044750144015351656 X0, X1, Y2, Y3\n",
"0.044750144015351656 X0, Y1, Y2, X3\n",
"0.044750144015351656 Y0, X1, X2, Y3\n",
"-0.044750144015351656 Y0, Y1, X2, X3\n"
]
}
],
"source": [
"h = mol.get_molecular_hamiltonian()\n",
"print(h)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"At this step, we have built a Hamiltonian for hydrogen molecule under `STO-3G` basis."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### Construct quantum circuit used in variational quantum eigensolver (VQE)\n",
"Variational quantum algorithm (VQE) performs hybrid classical-quantum computation by optimizing parameters in quantum circuit on a classical optimizer. Compared to its classical counterpart, VQE can efficiently solve optimization problem in high dimensional space in some situations. Let's now construct a quantum circuit for our VQE task from \\[3\\]."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"converged SCF energy = -1.11734903499028\n"
]
},
{
"data": {
"image/png": "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",
"text/plain": [
"<Figure size 534x220 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from paddle_quantum.qchem import HardwareEfficient\n",
"\n",
"mol.build()\n",
"cir = HardwareEfficient(mol.num_qubits, depth=2)\n",
"cir.plot()"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### Computing potential energy curve for hydrogen molecule\n",
"Next we will demostrate the usage of VQE method by calculating the potential energy curve of hydrogen molecule. Potential energy surface depicts the variation of molecular energy with respect to the position of inner atoms, it is widely used in physics and chemistry to find the optimal molecular structure or calculate the chemical reaction rate. For hydrogen molecule, the potential energy surface becomes a curve since hydrogen molecule only has one spatial degree of freedom (the distance between two hydrogen atoms)."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"converged SCF energy = 2.71588739329275\n",
"converged SCF energy = -0.593827758535727\n",
"converged SCF energy = -1.04299627454009\n",
"converged SCF energy = -1.11675930739643\n",
"converged SCF energy = -1.09191404102006\n",
"converged SCF energy = -1.06610864931794\n",
"converged SCF energy = -0.910873554594387\n",
"converged SCF energy = -0.783792654277353\n"
]
}
],
"source": [
"import numpy as np\n",
"import paddle\n",
"from paddle.optimizer import Adam\n",
"from paddle_quantum.qchem import GroundStateSolver\n",
"from paddle_quantum.qchem import dipole_moment\n",
"\n",
"paddle.seed(124)\n",
"\n",
"cir_depth = 2\n",
"bond_lengthes = [0.1, 0.3, 0.5, 0.74, 0.9, 1.0, 1.5, 2.0]\n",
"energies = []\n",
"dipole_moments = []\n",
"for bond_len in bond_lengthes:\n",
" mol = Molecule(\n",
" geometry = [(\"H\", [0.0, 0.0, 0.0]), (\"H\", [0.0, 0.0, bond_len])],\n",
" driver = PySCFDriver()\n",
" )\n",
" mol.build()\n",
" \n",
" cir = HardwareEfficient(mol.num_qubits, cir_depth)\n",
"\n",
" solver = GroundStateSolver(Adam, num_iterations=100, tol=1e-5)\n",
" e, psi = solver.solve(mol, cir, learning_rate=0.5)\n",
" energies.append(e)\n",
"\n",
" # calculate dipole moments\n",
" d = dipole_moment(psi, mol)\n",
" dipole_moments.append(np.linalg.norm(d))"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"In the first plot, we can see that the ground state energy of hydrogen molecule first decrease with the growth of the extension of two hydrogen atoms and then increase, the lowest ground state energy occurs at bond length equal to 0.74 Angstrom. In the second plot, we can see that hydrogen molecule is unpolarized, its dipole moment is approximately zero no matter how bond length varies."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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fvlFo31Xq1YNW7duxfbt29GwYUMsX74c06dPB/Dyqz+5XI4JEyaozletWrXwww8/AABcXV0xZ84cBAUFwcnJCQEBAQUey9XVFXv37sXp06fh7e2NcePGYdSoUfjss8+0Oh/52bRpE9566y24u7u/9r6Iyjq2uWxz2eaWDRKRs7+bSI917doVzs7O+Pnnn0tk/x9//DESExOxcuXKEtl/TgsWLMCKFSvw4MGDEj9WccjIyEDNmjWxceNGtGnTRtfhEFEpYJurO2xzX+LNXqSXUlNTsWLFCvj4+MDAwACbNm3CoUOHcPDgwRI75vTp0/HDDz9AoVC89ldCuf3www9o3rw5KlWqhBMnTuCrr74q9FN+WXP//n18+umnFb5BJSqv2OaWLWxzX2KPLOml58+fo3fv3jh//jzS0tLg5eWFzz77DO+8846uQyuSjz76CJs3b0ZcXByqVq2K9957D9OmTYOhIT9rEpHusc2lsoqJLBERERHpJd7sRURERER6iYksEREREeklJrJEREREpJeYyBIRERGRXmIiS0RERER6iYksEREREeklJrJEREREpJeYyBIRERGRXmIiS0RERER66f8llUqVQXVHtgAAAABJRU5ErkJggg==",
"text/plain": [
"<Figure size 700x300 with 2 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import matplotlib.pyplot as plt\n",
"\n",
"fig = plt.figure(figsize=(7, 3), )\n",
"ax1 = fig.add_subplot(121)\n",
"ax1.plot(bond_lengthes, energies)\n",
"ax1.set_xlabel(\"Bond length (Angstrom)\")\n",
"ax1.set_ylabel(\"Energy (Hartree)\")\n",
"ax1.set_title(\"Potential energy curve\")\n",
"\n",
"ax2 = fig.add_subplot(122)\n",
"ax2.plot(bond_lengthes, dipole_moments)\n",
"ax2.set_xlabel(\"Bond length (Angstrom)\")\n",
"ax2.set_ylabel(\"Dipole moment\")\n",
"ax2.set_title(\"Dipole moment variation\")\n",
"ax2.set_ylim(-0.5, 0.5)\n",
"fig.tight_layout()"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## How to use\n",
"Users can edit the configuration file `config.toml` to customize the task, and the required settings are listed below.\n",
"\n",
"```toml\n",
"# A description of the task of this configuration file, this is optional. \"GroundState\" stands for calculate the ground state energy of the molecule.\n",
"\n",
"# This field stores information related to the molecule is provided.\n",
"[molecule]\n",
"# Symbols of atoms inside the molecule.\n",
"symbols = ['H', 'H']\n",
"# The cartesian coordinates of each atom inside the molecule.\n",
"coords = [ [ 0.0, 0.0, 0.0 ], [ 0.0, 0.0, 0.7 ] ]\n",
"\n",
"# This field specifies configurations related to the quantum circuit in VQE is specified.\n",
"[ansatz.HardwareEfficient]\n",
"# The depth of the HardwareEfficient ansatz.\n",
"depth = 2\n",
"\n",
"# This field stores configurations of the variational quantum eigensolver (VQE) method. \n",
"[VQE]\n",
"# Number of optimization cycles, default is 100.\n",
"num_iterations = 100\n",
"```\n",
"After setup the configuration file, user can run the following command to perform the quantum chemistry task.\n",
"```shell\n",
"python energy_material.py --config example.toml\n",
"```"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Reference \n",
"\\[1\\] [Thermaldynamic free energy](https://en.wikipedia.org/wiki/Thermodynamic_free_energy)\n",
"\n",
"\\[2\\] Aydinol, M. K., et al. \"Ab initio study of lithium intercalation in metal oxides and metal dichalcogenides.\" Physical Review B 56.3 (1997): 1354.\n",
"\n",
"\\[3\\] Kandala, Abhinav, et al. \"Hardware-efficient variational quantum eigensolver for small molecules and quantum magnets.\" Nature 549.7671 (2017): 242-246."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "pq-dev",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.15 (default, Nov 10 2022, 13:17:42) \n[Clang 14.0.6 ]"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "5fea01cac43c34394d065c23bb8c1e536fdb97a765a18633fd0c4eb359001810"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}
task = 'test'
image_path = 'pneumoniamnist'
num_samples = 10
model_path = 'qnnmic.pdparams'
num_qubits = [8, 8]
num_depths = [2, 2]
observables = [['Z0', 'Z1', 'Z2', 'Z3'], ['X0', 'X1', 'X2', 'X3']]
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 医学图像分类简介\n",
"\n",
"*Copyright (c) 2022 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.*\n",
"\n",
"医学图像分类(Medical image classification)是计算机辅助诊断系统的关键技术。医学图像分类问题主要是如何从图像中提取特征并进行分类,从而识别和了解人体的哪些部位受到特定疾病的影响。在这里我们主要使用量子神经网络对公开数据集 MedMNIST 中的胸腔数据进行分类。其中数据形式如下图所示:\n",
"\n",
"<img src=\"./med_image_example.png\" width=\"20%\" height=\"20%\"/>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 使用 QNNMIC 模型进行医学图像分类\n",
"\n",
"### QNNMIC 模型简介\n",
"QNNMIC 模型是一个可以用于医学图像分类的量子机器学习模型(Quantum Machine Learning,QML)。我们具体称其为一种量子神经网络 (Quantum Neural Network, QNN),它结合了参数化量子电路(Parameterized Quantum Circuit, PQC)和经典神经网络。对于医学图像数据,QNNMIC 可以达到 85% 以上的分类准确率。模型主要分为量子和经典两部分,结构图如下:\n",
"\n",
"<img src=\"./qnnmic_model_cn.png\" width=\"60%\" height=\"60%\"/>\n",
"\n",
"\n",
"注:\n",
"- 通常我们使用主成分分析将图片数据进行降维处理,使其更容易通过编码电路将经典数据编码为量子态。\n",
"- 参数化电路的作用是特征提取,其电路参数可以在训练中调整。\n",
"- 量子测量由一组测量算子表示,是将量子态转化为经典数据的过程,我们可以对得到的经典数据做进一步处理。\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 如何使用\n",
"\n",
"### 使用模型进行预测\n",
"\n",
"这里,我们已经给出了一个训练好的模型,可以直接用于医学图片的预测。只需要在 `test.toml` 这个配置文件中进行对应的配置,然后输入命令 `python qnn_medical_image.py --config test.toml` 即可使用训练好的医学图片分类模型对输入的图片进行测试。\n",
"\n",
"### 在线演示\n",
"\n",
"这里,我们给出一个在线演示的版本,可以在线进行测试。首先定义配置文件的内容对测试集中图片进行预测:\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import toml\n",
"\n",
"test_toml = r\"\"\"\n",
"# 模型的整体配置文件。\n",
"# 图片的文件路径。\n",
"image_path = 'pneumoniamnist'\n",
"\n",
"# 训练集中的数据个数,默认值为 -1 即使用全部数据。\n",
"num_samples = 20\n",
"\n",
"# 训练好的模型参数文件的文件路径。\n",
"model_path = 'qnnmic.pdparams'\n",
"\n",
"# 量子电路所包含的量子比特的数量。\n",
"num_qubits = [8, 8]\n",
"\n",
"# 每一层量子电路中的电路深度。\n",
"num_depths = [2, 2]\n",
"\n",
"# 量子电路中可观测量的设置。\n",
"observables = [['Z0', 'Z1', 'Z2', 'Z3'], ['X0', 'X1', 'X2', 'X3']]\n",
"\"\"\"\n",
"\n",
"config = toml.loads(test_toml)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"图片的预测结果分别为 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0\n",
"图片的实际标签分别为 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0\n"
]
}
],
"source": [
"from paddle_quantum.qml.qnnmic import inference\n",
"\n",
"prediction, prob, label = inference(**config)\n",
"print(f\"图片的预测结果分别为 {str(prediction)[1:-1]}\")\n",
"print(f\"图片的实际标签分别为 {str(label)[1:-1]}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"其中标签 0 代表肺部异常,标签 1 代表正常。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"在 `test_toml` 配置文件中:\n",
"- `model_path`: 为训练好的模型,这里固定为 `qnnmic.pdparams`;\n",
"- `num_qubits`、`num_depths`、`observables` 三个参数应与训练好的模型 ``qnnmic.pdparams`` 相匹配。`num_qubits = [8,8]` 表示量子部分一共两层电路;每层电路为 8 的量子比特;`num_depths = [2,2]` 表示每层参数化电路深度为 2;`observables` 表示每层测量算子的具体形式。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"对于数据集中的某张肺部异常的图片:\n",
"\n",
"<img src=\"./medical_image/image_label_0.png\" width=\"20%\" height=\"20%\"/>"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"对于上述输入的图片,模型有 98.30% 的置信度检测出肺部异常。\n"
]
}
],
"source": [
"# 使用模型进行预测并得到对应概率值\n",
"msg = f'对于上述输入的图片,模型有 {prob[10][1]:3.2%} 的置信度检测出肺部异常。'\n",
"print(msg)\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 注意事项\n",
"\n",
"我们通常考虑调整 `num_qubits`,`num_depths`,`observables` 三个主要超参数,对模型的影响较大。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 引用信息\n",
"\n",
"```\n",
"@article{medmnistv2,\n",
" title={MedMNIST v2: A Large-Scale Lightweight Benchmark for 2D and 3D Biomedical Image Classification},\n",
" author={Yang, Jiancheng and Shi, Rui and Wei, Donglai and Liu, Zequan and Zhao, Lin and Ke, Bilian and Pfister, Hanspeter and Ni, Bingbing},\n",
" journal={arXiv preprint arXiv:2110.14795},\n",
" year={2021}\n",
"}\n",
"```\n",
"\n",
"## 参考文献\n",
"\\[1\\] Yang, Jiancheng, et al. \"Medmnist v2: A large-scale lightweight benchmark for 2d and 3d biomedical image classification.\" arXiv preprint arXiv:2110.14795 (2021)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "modellib",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.15 (default, Nov 24 2022, 18:44:54) [MSC v.1916 64 bit (AMD64)]"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "dfa0523b1e359b8fd3ea126fa0459d0c86d49956d91b464930b80cba21582eac"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Medical image classification\n",
"\n",
"*Copyright (c) 2022 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.*\n",
"\n",
"Medical image classification is the key technology of computer-aided diagnosis systems. The problem of medical image classification is how to extract features from images and classify them, so as to identify and understand which parts of the human body are affected by specific diseases. Here, we mainly use a quantum neural network to classify the chest data in the open data set MedMNIST, which has the following form\n",
"\n",
"<img src=\"./med_image_example.png\" width=\"20%\" height=\"20%\"/>\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## QNNMIC model for medical image classification\n",
"\n",
"### Introduction of QNNMIC\n",
"QNNMIC model is a quantum machine learning (QML) model that can be used for medical image classification. We specifically call it a quantum neural network (QNN), which combines parameterized quantum circuit (PQC) and a classical neural network. For medical image data, QNNMIC can achieve more than 85% classification accuracy. The model is mainly divided into quantum and classical parts. The structure diagram is as follows:\n",
"\n",
"<img src=\"./qnnmic_model_en.png\" width=\"60%\" height=\"60%\"/>\n",
"\n",
"\n",
"Remarks:\n",
"- In general, we use principal component analysis (PCA) to reduce the dimension of the image data, making it easier to encode classical data into quantum states through coding circuits.\n",
"- The parameterized circuit is used for feature extraction, and its circuit parameters can be adjusted during training.\n",
"- Quantum measurement, represented by a set of measurement operators, is the process of converting quantum states into classical data, which can be further processed.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Quick start\n",
"\n",
"### Use the model to make predictions\n",
"\n",
"Here, we have given a trained model saved in the format `qnnmic.pdparams` which can be directly used to distinguish medical images. One only needs to do the corresponding configuration in this file `test.toml`, and enter the command `python qnn_medical_image.py --config test.toml` to predict the input images.\n",
"\n",
"### Online Test\n",
"\n",
"The following shows how to configure the test file `test_toml` to make medical image prediction."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"import toml\n",
"\n",
"test_toml = r\"\"\"\n",
"# The config for testing the QNNMIC model.\n",
"\n",
"# The path of the input image.\n",
"image_path = 'pneumoniamnist'\n",
"\n",
"# The number of data in the test dataset.\n",
"# The value defaults to -1 which means using all data.\n",
"num_samples = 20\n",
"\n",
"# The path of the trained model, which will be loaded.\n",
"model_path = 'qnnmic.pdparams'\n",
"\n",
"# The number of qubits of the quantum circuit in each layer.\n",
"num_qubits = [8, 8]\n",
"\n",
"# The depth of the quantum circuit in each layer.\n",
"num_depths = [2, 2]\n",
"\n",
"# The observables of the quantum circuit in each layer.\n",
"observables = [['Z0','Z1','Z2','Z3'], ['X0','X1','X2','X3']]\n",
"\"\"\"\n",
"\n",
"config = toml.loads(test_toml)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The prediction results of the input images are 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0 respectively.\n",
"The labels of the input images are 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0 respectively.\n"
]
}
],
"source": [
"from paddle_quantum.qml.qnnmic import inference\n",
"\n",
"prediction, prob, label = inference(**config)\n",
"print(f\"The prediction results of the input images are {str(prediction)[1:-1]} respectively.\")\n",
"print(f\"The labels of the input images are {str(label)[1:-1]} respectively.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here label 0 means abnormal lungs, and label 1 means normal lungs."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In `test_toml` :\n",
"- `model_path`: this is the trained model, here we set it as `qnnmic.pdparams`.\n",
"- `num_qubits`, `num_depths`, `observables` these parameters correspond to the model ``qnnmic.pdparams``, `num_qubits = [8,8]` represents the quantum part of a total of two layers of circuit, each layer of the circuit has 8 qubits; `num_depths = [2,2]` represents the depth of parameterized circuit of each layer is 2;`observables` is the specific form of the measurement operator at each layer.\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"For an abnormal image from the dataset\n",
"\n",
"<img src=\"./medical_image/image_label_0.png\" width=\"20%\" height=\"20%\"/>\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"For this input image, the model can detect the abnormality of the lung with 98.30% confidence.\n"
]
}
],
"source": [
"# Use the model to make predictions and get the corresponding probability\n",
"msg = f'For this input image, the model can detect the abnormality of the lung with {prob[10][1]:3.2%} confidence.'\n",
"print(msg)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Remarks\n",
"\n",
"- We usually consider adjusting three hyperparameters,`num_qubits`, `num_depths` and `observables`, which have a greater impact on the model."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Reference information\n",
"\n",
"```\n",
"@article{medmnistv2,\n",
" title={MedMNIST v2: A Large-Scale Lightweight Benchmark for 2D and 3D Biomedical Image Classification},\n",
" author={Yang, Jiancheng and Shi, Rui and Wei, Donglai and Liu, Zequan and Zhao, Lin and Ke, Bilian and Pfister, Hanspeter and Ni, Bingbing},\n",
" journal={arXiv preprint arXiv:2110.14795},\n",
" year={2021}\n",
"}\n",
"```\n",
"\n",
"## Reference\n",
"\n",
"\\[1\\] Yang, Jiancheng, et al. \"Medmnist v2: A large-scale lightweight benchmark for 2d and 3d biomedical image classification.\" arXiv preprint arXiv:2110.14795 (2021)."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "modellib",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.15 (default, Nov 24 2022, 18:44:54) [MSC v.1916 64 bit (AMD64)]"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "dfa0523b1e359b8fd3ea126fa0459d0c86d49956d91b464930b80cba21582eac"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}
{
"cells": [
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"from PIL import Image\n",
"image = np.load('pneumoniamnist.npz')\n",
"x_train = image['train_images']\n",
"x_label = image['train_labels']\n",
"\n",
"im1 = Image.fromarray(x_train[28])\n",
"im0 = Image.fromarray(x_train[-20])\n",
"\n",
"im1.save('image_label_1.png')\n",
"im0.save('image_label_0.png')"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "modellib",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.15"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "dfa0523b1e359b8fd3ea126fa0459d0c86d49956d91b464930b80cba21582eac"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}
# !/usr/bin/env python3
# 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.
# 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.
import argparse
import os
import warnings
warnings.filterwarnings('ignore')
os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'python'
import toml
from paddle_quantum.qml.qnnmic import train, inference
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Detect whether there are cracks on the surface of images by the QNNMIC model.")
parser.add_argument("--config", type=str, help="Input the config file with toml format.")
args = parser.parse_args()
config = toml.load(args.config)
task = config.pop('task')
if task == 'train':
train(**config)
elif task == 'test':
prediction, prob, label = inference(**config)
print(f"The prediction results of the input pictures are {str(prediction)[1:-1]} respectively.")
else:
raise ValueError("Unknown task, it can be train or test.")
# The config for testing the QNNMIC model.
# The task of this config. Available values: 'train' | 'test'.
task = 'test'
# The path of the input image.
image_path = 'pneumoniamnist'
# The number of the data in the test dataset.
# The value defaults to -1 which means using all data.
num_samples = 10
# The path of the trained model, which will be loaded.
model_path = 'qnnmic.pdparams'
# The number of qubits of quantum circuit in each layer.
num_qubits = [8, 8]
# The depth of quantum circuit in each layer.
num_depths = [2, 2]
# The observables of quantum circuit in each layer.
observables = [['Z0', 'Z1', 'Z2', 'Z3'], ['X0', 'X1', 'X2', 'X3']]
\ No newline at end of file
# The config for training the QNNMIC model.
# The task of this config. Available values: 'train' | 'test'.
task = 'train'
# The name of the model, which is used to save the model.
model_name = 'qnnmic'
# The path to save the model. Both relative and absolute paths are allowed.
# It saves the model to the current path by default.
# saved_path = './'
# The number of qubits of the quantum circuit in each layer.
num_qubits = [8, 8]
# # The depth of the quantum circuit in each layer.
num_depths = [2, 2]
# The observables of the quantum circuit in each layer.
observables = [['Z0', 'Z1', 'Z2', 'Z3'], ['X0', 'X1', 'X2', 'X3']]
# The size of the batch samplers.
batch_size = 40
# The number of epochs to train the model.
num_epochs = 20
# The learning rate used to update the parameters, default to 0.01.
learning_rate = 0.1
# The path of the dataset. It defaults to breastmnist.
dataset = 'pneumoniamnist'
# The path used to save logs. Default to ``./``.
saved_dir = './'
# Whether use the validation.
# It is true means the dataset contains training, validation and test datasets.
# It is false means the dataset only contains training datasets and test datasets.
using_validation = true
# The number of the data in the training dataset.
# The value defaults to -1 which means using all data.
num_train = 500
# The number of the data in the validation dataset.
# The value defaults to -1 which means using all data.
num_val = -1
# The number of the data in the test dataset.
# The value defaults to -1 which means using all data.
num_test = -1
# Number of epochs with no improvement after which training will be stopped.
early_stopping = 1000
# The number of subprocess to load data, 0 for no subprocess used and loading data in main process, default to 0.
num_workers = 0
# The overall profile used to calculate the option pricing model
# initial price
initial_price = 100
# strike price
strike_price = 110
# risk-free rate
interest_rate = 0.05
# Market volatility
volatility = 0.1
# Option expiration date (in years)
maturity_date = 1
# Estimation accuracy index
degree_of_estimation = 5
# !/usr/bin/env python3
# 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.
# 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.
import argparse
import os
import warnings
from typing import Dict
warnings.filterwarnings('ignore')
os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'python'
import toml
from paddle_quantum.finance import EuroOptionEstimator
def main(args):
parsed_configs: Dict = toml.load(args.config)
# input option settings
initial_price = parsed_configs["initial_price"]
strike_price = parsed_configs["strike_price"]
interest_rate = parsed_configs["interest_rate"]
volatility = parsed_configs["volatility"]
maturity_date = parsed_configs["maturity_date"]
degree_of_estimation = parsed_configs["degree_of_estimation"]
estimator = EuroOptionEstimator(initial_price, strike_price,
interest_rate, volatility,
maturity_date, degree_of_estimation)
print("The risk-neutral price of this option is", estimator.estimate())
print("Below is the circuit realization of this quantum solution.")
estimator.plot()
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="European option pricing with paddle quantum.")
parser.add_argument("--config", type=str, help="Input the config file with toml format.")
main(parser.parse_args())
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"# 期权定价问题\n",
"\n",
"*Copyright (c) 2022 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.*"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"期权定价的任务是评估当前股票期权在到期日的预期价值。决定期权价值的因素有很多,包括当前股票价格、内在价值、到期时间或时间价值、波动性、利率和支付的现金股息。许多期权定价模型以这些因素作为模型的参数,用来确定期权的公允市场价值,其中最广为人知的是布莱克-斯科尔斯模型(Black-Scholes model)。布莱克-斯科尔斯模型可以通过使用少量输入参数的简单且可分析求解的模型对各种金融衍生品进行定价。该模型认为,大量交易资产的价格遵循几何布朗运动,具有恒定的漂移和波动。当应用于股票期权时,该模型包含股票的恒定价格变化、货币的时间价值、期权的执行价格以及期权到期的时间。特别地,股票或期货合约等工具在随机游走后将具有服从对数正态分布的价格,具有恒定的漂移和波动性。\n",
"\n",
"欧式期权定价是布莱克-斯科尔斯模型的一个简单应用,该模型可以用来计算欧式看涨期权的价格。欧式看涨期权赋予期权持有人在到期日 $T$ 以预先商定的价格 $K$ 购买股票的权利。通常,期权收益函数为 \n",
"$$\n",
"f(S_{T})=\\max\\{0, S_{T}-K\\}, \\tag{1}\n",
"$$\n",
"其中 $S_{T}$ 表示期权到期日的资产价格(asset price),$K$ 表示预先商定的价格(strike price)。这里,资产价格 $S_{T}$ 在布莱克-斯科尔斯模型下服从一个已知的概率分布,且依赖于初始价格(initial price),无风险利率(risk-free interest rate),波动性(volatility)以及期权到期日(maturity date) $T$。在经典计算中,期权股票到期时的期望价值可以通过蒙特卡罗方法计算:从已知的(风险中性)概率分布中获取市场样本,然后计算给定该市场样本的资产价格。之后,计算给定资产价格的期权收益,最后,对多个样本的收益求平均值,得出期权价格的近似值。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 量子解决方案\n",
"\n",
"不同于经典算法,量子蒙特卡洛(quantum Monte Carlo)方法的核心是用量子电路模拟概率分布并将资产价格储存在量子态中,进而通过量子振幅估计算法并行计算收益的平均值。通过量子叠加和纠缠的特性,量子方案与经典方案相比具有二次加速的优势。接下来我们以欧式看涨期权为例,展示如何使用量桨来模拟该量子方案,从而完成欧式看涨期权的风险中性定价问题。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 在线演示"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"我们已经给出了一个设置好的参数,可以直接用于欧式看涨期权的定价。只需要在 `config.toml` 这个配置文件中进行对应的配置,然后输入命令 \n",
"`python euro_pricing.py --config config.toml`\n",
"即可对配置好的欧式期权进行定价。\n",
"\n",
"这里,我们给出一个在线演示的版本,可以在线进行测试。首先定义配置文件的内容:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"euro_toml = r\"\"\"\n",
"# 用于计算期权定价模型的整体配置文件。\n",
"# 初始价格。\n",
"initial_price = 100\n",
"# 既定价格。\n",
"strike_price = 110\n",
"# 无风险利率。\n",
"interest_rate = 0.05\n",
"# 市场波动性。\n",
"volatility = 0.1\n",
"# 期权到期日(以年为单位)。\n",
"maturity_date = 1\n",
"# 估计精度指数。\n",
"degree_of_estimation = 5\n",
"\"\"\""
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"量桨的金融模块实现了量子蒙特卡洛方案的数值模拟。我们可以从 ``paddle_quantum.finance`` 模块里导入 ``EuroOptionEstimator`` 来解决配置好的期权定价问题。"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"该期权的风险中性价格大约为 2.2613329887390137\n",
"以下是该量子方案的电路实现图。\n"
]
},
{
"data": {
"image/png": "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PTE0NBQR1X1Cy+rVq2PdunURIXgAAI0zbdq0+O///b/HmjVr4lOf+tTI99/97nfHHXfcEXfffXccdNBBDZwQAGqr9DctzWbx4sVj+izguXPnlv7ZwQAAW2vmzJnx93//9/HpT386IiI+/elPp31zOgDYmFd4AAAAAOkIHgAAAEA6ggcAAACQjuABAAAApCN4AAAAAOkIHgAAAEA6ggcAAACQjuABAAAApCN4AAAAAOkIHgAAAEA6ggcAAACQjuABAAAApCN4AAAAAOkIHgAAAEA6ggcAAACQjuABAAAApCN4AAAAAOkIHgAAAEA6ggcAAACQjuABAAAApCN4AAAAAOkIHgAAAEA6ggcAAACQjuABAAAApCN4AAAAAOkIHgAAAEA6ggcAAACQjuABAAAApCN4AAAAAOm0NHqAeqhUKo0eYatN5NkBAACgUSZF8Ojq6mr0CAAAAEAduaQFAAAAJpgf/ehH0dTUFFdeeWWjRxm30r7Co62tLXp7exs9Rqna2toaPQIAAABMCGmDR0tLS3R0dDR6DAAAAKABXNICAABAak899VTccMMN8Y53vCP23XffmDVrVsyYMSN23333OOqoo+Jb3/pWPPPMM1s8x/HHHx9NTU1V/e+rX/1qfOQjH6n6+Of736GHHvqcGc4555yRX3/Na14TEREnnnjiyPcOOeSQWtx9E1baV3gAAADA97///ViyZEn86le/es6v9fb2Rm9vb3zve9+LCy64IK677rrYY489nvc8y5cvr/r3/Ku/+qv4+te/vpUT//kcz/bWt741XvziF0dExAMPPBDnn39+nHzyyfGqV70qIiJmz569Tb9nNoIHAAAAKZ111lnxj//4jxERsdtuu8X73//+OOyww2LPPfeMoijigQceiCuuuCL+1//6X7F8+fJ45StfGXfddddzwsHg4GCsXLkyIiKWLFkS55133hZ/3x122CFuvPHG533VyKpVq2L//fePiIhzzz03TjvttOc9x/Tp05/zvQULFsSCBQsi4o9vWnr++efHQQcdFMcff/wo98TkJHgAAACQzplnnhkXXHBBREQcddRR8ZWvfCV22mmnTY7Zbbfd4tWvfnUsXrw4PvjBD8aaNWvi1FNPjWuvvXaT43p6emJoaCgi/hgddthhh1F//9bW1uf9/qpVq0a+Xrx4cVXnYut4Dw8AAABSue6660Zix9ve9rb4zne+85zYsbHTTz995D0xrrvuunjwwQc3+fWNL2fZe++9t2m2n/3sZyNfv/zlL9+mc7FlggcAAABpPPzww/G+970vIiL+8i//Mq688sqYMmX0p74nnXRSREQURRE333zzJr9Wi+Cx2267RVtb2zadiy0TPAAAAEjj4osvjt/97ncREXHRRRfF9ttvX9XtFi9ePPJ1T0/PJr82HDxmz54dM2fO3Kb5hoOHV3fUnuABAABAChs2bIjLL788IiL22WefeNOb3lT1bWfNmjXy9cMPPzzydVEUce+990bEtr+6Y926dfHrX/86IgSPevCmpQAAAKTwgx/8IB555JGIiHjnO98ZTU1NVd/2iSeeGPl6u+22G/l69erVMTAwEBERc+fOjccee2yz59h+++23+Ht6/4768goPAAAAUrjllltGvn7DG94wptuuWbNm5OsXvOAFI19v/P4d//zP/xw77rjj8/5vl1122SSaPB/Bo74EDwAAAFIYDgrTp0+P+fPnj+m2d95558jXG8eIjYPHlsyfP3+zH0X77Pm22267eOlLXzqm+Z5txowZMXfu3C1++sxk55IWAAAAUujv74+IP765aHNz85hue+ONN458/cpXvnLk6+HgMW3atBgYGIipU6du9XzDwWP+/PnbdJ6IiAMOOCBWrVq1TefIzis8AAAASGHDhg0R8cdXeIxFX19f3HbbbRERsWjRok1efTEcPBYsWLBNkeLpp5+O++67LyJczlIvggcAAAApDH/SyqOPPjqm21144YUxNDQUERFLliwZ+f7atWtH3ttj0aJF2zTbypUrY3BwMCIEj3oRPAAAAEjhZS97WURE/O53v4u+vr6qbrNixYr44he/GBER+++/fxx//PEjv7bx+3dsa/DwhqX1J3gAAACQwuGHHz7y9Ve/+tVRj3/44Yfj6KOPjqeeeipaW1vj61//ekyZ8uenyYLHxCZ4AAAAkMKxxx4bc+bMiYiIz3zmM5t88sqz/fznP49DDjkkVq5cGc3NzXHllVeOvEJk2MZvWPrsXxur4eAxZ86c2HXXXbfpXFRH8AAAACCFadOmxTe+8Y1oaWmJJ554Ig455JA4++yz42c/+1k88sgj0d/fH7feemuccsopse+++0ZPT0+0trbGd77znTj66KOfc77h4LHvvvtu86eqDAcPr+6oHx9LCwAAQBqH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U06J9evXxy9/+cv40Ic+FHPnzq3z1Dyfse7y85//fLS1tcVb3vKWBkzLlox1l0uWLImVK1fG2rVr45vf/GZcffXV8dGPfrQBk8P4JngA48o///M/x+c+97nYfffd46Mf/WhccsklceCBB8Zll10W++yzT/z7v//7yLE77rhjRET8/ve/3+Qc69ati5122qmuc/NcY9kl49/W7vMrX/lKfOxjH4tbbrkl9thjj/oOzfPalp/NPfbYI4488sh4wxveEEVR1HFqns9Ydrlq1aq46KKL4gtf+EIDJ2ZzxvpzuXDhwthtt91iypQpsXDhwjjvvPPim9/8ZoOmh3GsgD/p7e0tIqKIiKK3t7fR42yzf/3Xfy1+/vOfN3qMTdTrPp7Iu7zzzjuLRx999Dnf/9KXvlRERHH00Udv8v3dd9+9+NrXvjbyfz/wwANFU1NT8Zvf/Kamc9bzPp6o+xzrLofdfvvtxbRp02o83Z/ZZXW2Zp+XXXZZ8cIXvrC45557aj9gYZfV2tqfzWE/+clPiqampuLxxx+v0YR2Wa2x7PKrX/1qsd122xW77rprseuuuxYzZ84sIqKYNWtWcfnll9d0To9/RretP5ff+973itmzZ9douj+byPcxk5NXeJDSb3/723jjG98YP/nJTxo9CmO0ePHi572u+Nhjj42IiHvvvXeT75988snx2c9+Nv7jP/4jfv/738eZZ54ZRx55pDcsHQfGusunn346BgcHR65BHhwcjMHBwZrPSXXGus9LL700zjnnnLj11ltjv/32q8OEVGssu9ywYUNcccUV8cgjj0RExOrVq+Oss86KV73qVT7lYxwYyy7f/va3x+rVq2P58uWxfPny+D//5/9ERMQPf/jDeMc73lGXedm8sf4d++1vf3vkFa4rVqyIs88+O44++uiazwkTjU9pIaVTTjklHnnkkZH3eGDiW7NmTUREzJ49e5Pvn3XWWfHII4/EokWL4g9/+EMceuih8aUvfakRI1Klze3yqquu2uQjhWfMmBER4WXz49zm9vnBD34wpk6dGgcddNAm33/sscfqNhtj83y7bGpqiu9+97vx0Y9+NJ544onYdddd47DDDvN+LOPc8+2ytbV1k0g1NDQUERHt7e2xww471HdAqra5v2Mvu+yyeN/73hdPPfVUtLW1xbHHHhuf+MQnGjEijGuCB+lcffXVcd1110VECB7jzIYNG6KpqWnkiexYnH322RERmzwhjohobm6Oiy66KC666KJSZqQ6tdjlCSecECeccEIZ4zFGtdinUNUYZe9yxowZ8X//7/8tbT6qV4ufy43tsccefk7rpBa7/PGPf1zKbJCdS1pI5Xe/+1184AMfGPm/fVJHYz355JNx5ZVXxuGHHx677LJLbL/99tHa2hq77rprvP3tb4+f/vSnVZ3n/PPPj2uvvTbe/OY3x7ve9a4aT83zsctc7DMPu8zDLvOwSxhHGvweIowjGd6E6G1ve1vx1re+deS/4/3vf3+jR9rEZHrTrqVLlxadnZ3FoYceWnz3u98tent7i8HBweLnP/95cdpppxVNTU3FlClTii996UtbPM+ll15aRERxyCGH1PQN8sZqMr2hnl1OzN9rczLv0y7tcrz/XpuTeZdF4fGPXULjCB6MmOh/gX3nO98pXvSiFxW//e1vR/47/u7v/q7RY21iMvyDPzQ0VJx11lnFjBkzim9+85ubPe5Tn/pUERFFc3NzcccddzzvMRdddFEREcVrX/vacfWPfVFMjgfjdjmxf69nmwz7tMtN2eX4+72ebTLssig8/tmYXUJ9CR6MmMh/gT300EPF7Nmzix/+8IdFURTFlClTiogo3vKWtzR4sk1l/wf/mWeeKY466qiiubm5uOGGG7Z47Pr164vtttuuiIji9a9//XN+/bOf/WwREcVhhx1WPPHEE7UaeatlfzBulxP/99rYZNmnXW7KLsff77WxybLLovD4Z2N2CfUleDBiIv8FdswxxxSnnHLKyP+94447FhFRvO51r2vgVM+V/R/8//bf/lsREcVZZ51V1fEHHnhgERFFS0tLsX79+pHvn3feeUVEFEceeWQxODhYq3G3SfYH43Y58X+vjU2Wfdrlc9nl+Pq9NjZZdlkUHv88m11C/fiUFia86667Lu68885NPp98hx12iIGBAZ/SUke33357fOpTn4rZs2fHOeecU9Vt/vIv/zKWLVsWQ0NDsWrVqth///3jn/7pn+LjH/94zJ49O9761rfGNddc85zbHX/88SVPz8bsMhf7zMMu87DLPOwSxjfBgwntkUceife///1x9dVXx/bbbz/y/eGvBY/6KIoi/st/+S/xzDPPxPve976YNm1aVbfbcccdR75+4oknIiLizjvvjIiI3/72t/Hud7/7eW/nH/zasctc7DMPu8zDLvOwSxj/fCwtE9oHPvCBOProo+Ov//qvN/m+4FFf/+///b9Yvnx5REQcccQRW3WOXXfdNSIirrzyyij+eLndZv9H7dhlLvaZh13mYZd52CWMf17hwYT1/e9/P7q7u2PZsmXx2GOPbfJr06dPj4iI9evXN2K0SWfp0qUREdHc3BwLFy6s+naPPvpoRETMmDEj5s6dW4vRGCO7zMU+87DLPOwyD7uE8U/wYEJ6+OGH433ve19MnTo1Zs+eHU8//fTzHvfsEEJt3H333RERMWvWrGhubq76dj09PRER8dd//dfR0uKvo/HALnOxzzzsMg+7zMMuYfxzSQsT0rvf/e54/etfH7/61a9iaGjoOS/5O/zwwyMi4umnn47HH3+8wdPm99BDD435NmvWrIkHHnggImKz16pSf3aZi33mYZd52GUedgnjn+DBuLZ+/fq44YYbNnmlxic/+cl44IEH4rLLLtvs7WbNmjXy9Zo1a2o6IxG77bZbRPzxH/5Vq1ZVdZvLL788iqKIBQsWxNve9rZajscY2GUu9pmHXeZhl3nYJYx/ggfj2jvf+c74z//5P8dxxx0XDz/8cJx55plxwQUXxLe+9a1NPpXl2V784hePfH3rrbdGRMT9998ffX19NZ95MnrjG9848vWSJUviqaeees4xg4ODI+9E3tvbG5dccklMnTo1rrjiipgyxV9F44Vd5mKfedhlHnaZh13C+OenjHHtN7/5TUREXH/99fGCF7wgLrjggvjSl74UixYt2uLt/uZv/mbk67POOive+MY3xlve8pbYbrvtajrvZHXKKafEQQcdFBERN910U7ziFa+I73znO7FixYpYtmxZXHLJJXHMMcdEpVKJJ598Mo477rjYsGFD/NM//VN0dXU1eHo2Zpe52GcedpmHXeZhlzABFPAnvb29RUQUEVH09vY2epyiKIri6quvLlpaWoqIKGbMmFFcccUVVd/2k5/8ZLHzzjsXO+20U/GmN72pWL16dQ0nrU697uNG7HLDhg3FeeedV+y7775Fa2trMWPGjGLPPfcsjjnmmOKaa64pnnrqqWLdunXF4YcfXmy33XbFl7/85brMVSv1vI/rvU+7zPF7DZtM+7RLuxzvv9ewybTLovD4xy6hcQQPRozXv8AefPDB4tprry3WrFnT6FG2WeZ/8Ldk3bp1xRVXXFF0dnYWixcvLn760582eqRtlv3B+ObY5cT5vaqRbZ92aZfj/feqRrZdFoXHP3YJjeNzkBj35s2bF/PmzWv0GFSpv78/fvrTn8bPfvazWLFiRaxcuTIeeOCBePWrXx2f//zn481vfnM0NTU1ekyqYJe52GcedpmHXeZhlzA+CR7ANhsaGorzzz8/rr/++rjrrruiKIqRXzv66KPjhhtuiDlz5mz29j/4wQ/i8ccfjze/+c11mJYtsctc7DMPu8zDLvOwSxj/vGkpsM2amppir732ir/927+NY489NnbfffeRX7vmmmtir732ir/7u7+LH/7wh/H0009vctt77703zj333DjssMPqPTbPwy5zsc887DIPu8zDLmH88woPYJs1NzfHscceu8n3uru741vf+lZ85zvfid/85jdx1VVXxVVXXRUzZ86MAw44IF7wghfEr371q/iP//iPuOGGG2L69OkNmp6N2WUu9pmHXeZhl3nYJYx/ggdQE11dXdHV1RUXXXRRLFu2LH7wgx/E3XffHWvXro0nn3wytttuu3jPe94TRx11VLS2tjZ6XLbALnOxzzzsMg+7zMMuYXwRPICamjJlShx88MFx8MEHN3oUtpFd5mKfedhlHnaZh13C+OA9PAAAAIB0BA8AAAAgHcEDAAAASEfwAAAAANIRPAAAAIB0BA8AAAAgHcEDAAAASEfwAAAAANIRPAAAAIB0BA8AAAAgHcEDAAAASEfwAAAAANIRPAAAAIB0BA8AAAAgHcEDAAAASEfwAAAAANIRPAAAAIB0BA8AAAAgHcEDAAAASEfwAAAAANIRPAAAAIB0BA8AAAAgHcEDAAAASEfwAAAAANIRPAAAAIB0BA8AAAAgHcEDAAAASEfwAAAAANIRPAAAAIB0BA8AAAAgHcEDAAAASEfwAAAAANIRPAAAAIB0BA8AAAAgHcEDAAAASKel7BP29fWVfUrqpFKpNHqESaWW97dd1let72/7rB+7zMMu87DLXDz+ycP9TS10dHSUer7Sg0dnZ2fZp4SUurq6Gj0CJbHLPOwyD7vMwy5zsc887JJaKIqi1PO5pAUAAABIp/RXePT29pZ9SuqkUqkotXXU3d0d7e3tNTm3XdZXLXcZYZ/1ZJd52GUedpmLxz951PpnE8pQevAo+5obyKq9vd3PSxJ2mYdd5mGXedhlLvaZh10yEbik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",
"text/plain": [
"<Figure size 1088x1320 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import os\n",
"import warnings\n",
"warnings.filterwarnings(\"ignore\")\n",
"os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'python'\n",
"\n",
"import toml\n",
"from paddle_quantum.finance import EuroOptionEstimator\n",
"\n",
"config = toml.loads(euro_toml)\n",
"initial_price = config[\"initial_price\"]\n",
"strike_price = config[\"strike_price\"]\n",
"interest_rate = config[\"interest_rate\"]\n",
"volatility = config[\"volatility\"]\n",
"maturity_date = config[\"maturity_date\"]\n",
"degree_of_estimation = config[\"degree_of_estimation\"]\n",
"\n",
"\n",
"estimator = EuroOptionEstimator(initial_price, strike_price, interest_rate, volatility, maturity_date, degree_of_estimation)\n",
"print(\"该期权的风险中性价格大约为\", estimator.estimate())\n",
"print(\"以下是该量子方案的电路实现图。\")\n",
"estimator.plot()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"通过修改配置文件的内容,并运行预测代码,即可在线对模型进行测试。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"___\n",
"\n",
"# 注意事项\n",
"\n",
"这里提供的模型只用于解决布莱克-斯科尔斯模型的期权定价问题。\n",
"\n",
"# 引用信息\n",
"\n",
"```\n",
"@article{rebentrost2018quantum,\n",
" title = {Quantum Computational Finance: {{Monte Carlo}} Pricing of Financial Derivatives},\n",
" shorttitle = {Quantum Computational Finance},\n",
" author = {Rebentrost, Patrick and Gupt, Brajesh and Bromley, Thomas R.},\n",
" year = {2018},\n",
" month = aug,\n",
" journal = {Physical Review A},\n",
" volume = {98},\n",
" number = {2},\n",
" pages = {022321},\n",
" publisher = {{American Physical Society}},\n",
" doi = {10.1103/PhysRevA.98.022321},\n",
" url = {https://link.aps.org/doi/10.1103/PhysRevA.98.022321},\n",
"}\n",
"```\n",
"\n",
"# 参考文献\n",
"\n",
"[1] Rebentrost, Patrick, Brajesh Gupt, and Thomas R. Bromley. \"Quantum computational finance: Monte Carlo pricing of financial derivatives.\" Physical Review A 98.2 (2018): 022321."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "pq",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.13 (default, Mar 28 2022, 06:16:26) \n[Clang 12.0.0 ]"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "08942b1340a5932ff3a93f52933a99b0e263568f3aace1d262ffa4d9a0f2da31"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"# Option pricing problem\n",
"\n",
"*Copyright (c) 2022 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.*"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"The task of option pricing is to assess the expected value of the current stock option at the expiration date. Many factors determine the value of an option, including the current stock price, intrinsic value, time to maturity or time value, volatility, interest rates, and cash dividends paid. Many option pricing models use these factors as parameters to determine the fair market value of an option, the most widely known of which is the Black-Scholes model. The Black-Scholes model can price a variety of financial derivatives through a simple and analytically solvable model with a small number of input parameters. The model assumes that the prices of a large number of traded assets follow geometric Brownian motion with constant drift and volatility. When applied to stock options, the model contains a constant price change for the stock, the time value of the currency, the strike price of the option, and the time the option expires. In particular, instruments such as stocks or futures contracts will have a lognormally distributed price after a random walk, with constant drift and volatility. \n",
"\n",
"European option pricing is a direct application of the Black-Scholes model, which can be used to calculate the price of a European call option. Europeans call options give the option holder the right to purchase shares at a pre-agreed price of $K$ at $T$ on the expiration date. Typically, the option payoff function is given by\n",
"$$\n",
"f(S_{T})=\\max\\{0, S_{T}-K\\}, \\tag{1}\n",
"$$\n",
"where $S_{T}$ represents the asset price at the expiration date of the option and $K$ represents the strike price. Here, the asset price $S_{T}$ follows a known probability distribution under the Black-Scholes model and depends on the initial price, risk-free interest rate, volatility, and maturity date $T$. In classical calculations, the expected value of an option's stock at maturity can be calculated by Monte Carlo methods: a market sample is taken from a known (risk-neutral) probability distribution, and then the asset price given that market sample is calculated. Afterwards, the payoff of the option for a given asset price is calculated, and finally, averaging payoffs overall multiple samples gives an approximation of the option price."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Quantum solutions\n",
"Unlike classical algorithms, the core of the quantum Monte Carlo method is to simulate probability distributions with quantum circuits and store asset prices in quantum states, and then calculate the average of returns in parallel through quantum amplitude estimation algorithms. Through the characteristics of quantum superposition and entanglement, quantum schemes have the advantage of quadratic acceleration compared with classical schemes. Next, we take a European call option as an example to show how to use Paddle Quantum to simulate this quantum scheme to complete the risk-neutral pricing problem of European call options."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Online demonstration"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"We have set a parameter that can be used directly for the pricing of European call options. Just configure it in the configuration file `config.toml` and enter the command \n",
"`python euro_pricing.py --config config.toml`\n",
"The configured European options can be priced.\n",
"\n",
"Here, we give a version of the online demo that can be tested online. First define the contents of the configuration file:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"euro_toml = r\"\"\"\n",
"# The overall profile used to calculate the option pricing model\n",
"# initial price\n",
"initial_price = 100\n",
"# strike price\n",
"strike_price = 110\n",
"# risk-free rate\n",
"interest_rate = 0.05\n",
"# Market volatility\n",
"volatility = 0.1\n",
"# Option expiration date (in years)\n",
"maturity_date = 1\n",
"# Estimation accuracy index\n",
"degree_of_estimation = 5\n",
"\"\"\""
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"The financial module of the Paddle Quantum enables numerical simulation of quantum Monte Carlo schemes. We can import ``EuroOptionEstimator`` from the ``paddle_quantum.finance`` module to solve the configured option pricing problem."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The risk-neutral price of the option is approximately 2.2613329887390137\n",
"The following is a circuit implementation diagram of this quantum scheme.\n"
]
},
{
"data": {
"image/png": "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PTE0NBQR1X1Cy+rVq2PdunURIXgAAI0zbdq0+O///b/HmjVr4lOf+tTI99/97nfHHXfcEXfffXccdNBBDZwQAGqr9DctzWbx4sVj+izguXPnlv7ZwQAAW2vmzJnx93//9/HpT386IiI+/elPp31zOgDYmFd4AAAAAOkIHgAAAEA6ggcAAACQjuABAAAApCN4AAAAAOkIHgAAAEA6ggcAAACQjuABAAAApCN4AAAAAOkIHgAAAEA6ggcAAACQjuABAAAApCN4AAAAAOkIHgAAAEA6ggcAAACQjuABAAAApCN4AAAAAOkIHgAAAEA6ggcAAACQjuABAAAApCN4AAAAAOkIHgAAAEA6ggcAAACQjuABAAAApCN4AAAAAOkIHgAAAEA6ggcAAACQjuABAAAApCN4AAAAAOm0NHqAeqhUKo0eYatN5NkBAACgUSZF8Ojq6mr0CAAAAEAduaQFAAAAJpgf/ehH0dTUFFdeeWWjRxm30r7Co62tLXp7exs9Rqna2toaPQIAAABMCGmDR0tLS3R0dDR6DAAAAKABXNICAABAak899VTccMMN8Y53vCP23XffmDVrVsyYMSN23333OOqoo+Jb3/pWPPPMM1s8x/HHHx9NTU1V/e+rX/1qfOQjH6n6+Of736GHHvqcGc4555yRX3/Na14TEREnnnjiyPcOOeSQWtx9E1baV3gAAADA97///ViyZEn86le/es6v9fb2Rm9vb3zve9+LCy64IK677rrYY489nvc8y5cvr/r3/Ku/+qv4+te/vpUT//kcz/bWt741XvziF0dExAMPPBDnn39+nHzyyfGqV70qIiJmz569Tb9nNoIHAAAAKZ111lnxj//4jxERsdtuu8X73//+OOyww2LPPfeMoijigQceiCuuuCL+1//6X7F8+fJ45StfGXfddddzwsHg4GCsXLkyIiKWLFkS55133hZ/3x122CFuvPHG533VyKpVq2L//fePiIhzzz03TjvttOc9x/Tp05/zvQULFsSCBQsi4o9vWnr++efHQQcdFMcff/wo98TkJHgAAACQzplnnhkXXHBBREQcddRR8ZWvfCV22mmnTY7Zbbfd4tWvfnUsXrw4PvjBD8aaNWvi1FNPjWuvvXaT43p6emJoaCgi/hgddthhh1F//9bW1uf9/qpVq0a+Xrx4cVXnYut4Dw8AAABSue6660Zix9ve9rb4zne+85zYsbHTTz995D0xrrvuunjwwQc3+fWNL2fZe++9t2m2n/3sZyNfv/zlL9+mc7FlggcAAABpPPzww/G+970vIiL+8i//Mq688sqYMmX0p74nnXRSREQURRE333zzJr9Wi+Cx2267RVtb2zadiy0TPAAAAEjj4osvjt/97ncREXHRRRfF9ttvX9XtFi9ePPJ1T0/PJr82HDxmz54dM2fO3Kb5hoOHV3fUnuABAABAChs2bIjLL788IiL22WefeNOb3lT1bWfNmjXy9cMPPzzydVEUce+990bEtr+6Y926dfHrX/86IgSPevCmpQAAAKTwgx/8IB555JGIiHjnO98ZTU1NVd/2iSeeGPl6u+22G/l69erVMTAwEBERc+fOjccee2yz59h+++23+Ht6/4768goPAAAAUrjllltGvn7DG94wptuuWbNm5OsXvOAFI19v/P4d//zP/xw77rjj8/5vl1122SSaPB/Bo74EDwAAAFIYDgrTp0+P+fPnj+m2d95558jXG8eIjYPHlsyfP3+zH0X77Pm22267eOlLXzqm+Z5txowZMXfu3C1++sxk55IWAAAAUujv74+IP765aHNz85hue+ONN458/cpXvnLk6+HgMW3atBgYGIipU6du9XzDwWP+/PnbdJ6IiAMOOCBWrVq1TefIzis8AAAASGHDhg0R8cdXeIxFX19f3HbbbRERsWjRok1efTEcPBYsWLBNkeLpp5+O++67LyJczlIvggcAAAApDH/SyqOPPjqm21144YUxNDQUERFLliwZ+f7atWtH3ttj0aJF2zTbypUrY3BwMCIEj3oRPAAAAEjhZS97WURE/O53v4u+vr6qbrNixYr44he/GBER+++/fxx//PEjv7bx+3dsa/DwhqX1J3gAAACQwuGHHz7y9Ve/+tVRj3/44Yfj6KOPjqeeeipaW1vj61//ekyZ8uenyYLHxCZ4AAAAkMKxxx4bc+bMiYiIz3zmM5t88sqz/fznP49DDjkkVq5cGc3NzXHllVeOvEJk2MZvWPrsXxur4eAxZ86c2HXXXbfpXFRH8AAAACCFadOmxTe+8Y1oaWmJJ554Ig455JA4++yz42c/+1k88sgj0d/fH7feemuccsopse+++0ZPT0+0trbGd77znTj66KOfc77h4LHvvvtu86eqDAcPr+6oHx9LCwAAQBqH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U06J9evXxy9/+cv40Ic+FHPnzq3z1Dyfse7y85//fLS1tcVb3vKWBkzLlox1l0uWLImVK1fG2rVr45vf/GZcffXV8dGPfrQBk8P4JngA48o///M/x+c+97nYfffd46Mf/WhccsklceCBB8Zll10W++yzT/z7v//7yLE77rhjRET8/ve/3+Qc69ati5122qmuc/NcY9kl49/W7vMrX/lKfOxjH4tbbrkl9thjj/oOzfPalp/NPfbYI4488sh4wxveEEVR1HFqns9Ydrlq1aq46KKL4gtf+EIDJ2ZzxvpzuXDhwthtt91iypQpsXDhwjjvvPPim9/8ZoOmh3GsgD/p7e0tIqKIiKK3t7fR42yzf/3Xfy1+/vOfN3qMTdTrPp7Iu7zzzjuLRx999Dnf/9KXvlRERHH00Udv8v3dd9+9+NrXvjbyfz/wwANFU1NT8Zvf/Kamc9bzPp6o+xzrLofdfvvtxbRp02o83Z/ZZXW2Zp+XXXZZ8cIXvrC45557aj9gYZfV2tqfzWE/+clPiqampuLxxx+v0YR2Wa2x7PKrX/1qsd122xW77rprseuuuxYzZ84sIqKYNWtWcfnll9d0To9/RretP5ff+973itmzZ9douj+byPcxk5NXeJDSb3/723jjG98YP/nJTxo9CmO0ePHi572u+Nhjj42IiHvvvXeT75988snx2c9+Nv7jP/4jfv/738eZZ54ZRx55pDcsHQfGusunn346BgcHR65BHhwcjMHBwZrPSXXGus9LL700zjnnnLj11ltjv/32q8OEVGssu9ywYUNcccUV8cgjj0RExOrVq+Oss86KV73qVT7lYxwYyy7f/va3x+rVq2P58uWxfPny+D//5/9ERMQPf/jDeMc73lGXedm8sf4d++1vf3vkFa4rVqyIs88+O44++uiazwkTjU9pIaVTTjklHnnkkZH3eGDiW7NmTUREzJ49e5Pvn3XWWfHII4/EokWL4g9/+EMceuih8aUvfakRI1Klze3yqquu2uQjhWfMmBER4WXz49zm9vnBD34wpk6dGgcddNAm33/sscfqNhtj83y7bGpqiu9+97vx0Y9+NJ544onYdddd47DDDvN+LOPc8+2ytbV1k0g1NDQUERHt7e2xww471HdAqra5v2Mvu+yyeN/73hdPPfVUtLW1xbHHHhuf+MQnGjEijGuCB+lcffXVcd1110VECB7jzIYNG6KpqWnkiexYnH322RERmzwhjohobm6Oiy66KC666KJSZqQ6tdjlCSecECeccEIZ4zFGtdinUNUYZe9yxowZ8X//7/8tbT6qV4ufy43tsccefk7rpBa7/PGPf1zKbJCdS1pI5Xe/+1184AMfGPm/fVJHYz355JNx5ZVXxuGHHx677LJLbL/99tHa2hq77rprvP3tb4+f/vSnVZ3n/PPPj2uvvTbe/OY3x7ve9a4aT83zsctc7DMPu8zDLvOwSxhHGvweIowjGd6E6G1ve1vx1re+deS/4/3vf3+jR9rEZHrTrqVLlxadnZ3FoYceWnz3u98tent7i8HBweLnP/95cdpppxVNTU3FlClTii996UtbPM+ll15aRERxyCGH1PQN8sZqMr2hnl1OzN9rczLv0y7tcrz/XpuTeZdF4fGPXULjCB6MmOh/gX3nO98pXvSiFxW//e1vR/47/u7v/q7RY21iMvyDPzQ0VJx11lnFjBkzim9+85ubPe5Tn/pUERFFc3NzcccddzzvMRdddFEREcVrX/vacfWPfVFMjgfjdjmxf69nmwz7tMtN2eX4+72ebTLssig8/tmYXUJ9CR6MmMh/gT300EPF7Nmzix/+8IdFURTFlClTiogo3vKWtzR4sk1l/wf/mWeeKY466qiiubm5uOGGG7Z47Pr164vtttuuiIji9a9//XN+/bOf/WwREcVhhx1WPPHEE7UaeatlfzBulxP/99rYZNmnXW7KLsff77WxybLLovD4Z2N2CfUleDBiIv8FdswxxxSnnHLKyP+94447FhFRvO51r2vgVM+V/R/8//bf/lsREcVZZ51V1fEHHnhgERFFS0tLsX79+pHvn3feeUVEFEceeWQxODhYq3G3SfYH43Y58X+vjU2Wfdrlc9nl+Pq9NjZZdlkUHv88m11C/fiUFia86667Lu68885NPp98hx12iIGBAZ/SUke33357fOpTn4rZs2fHOeecU9Vt/vIv/zKWLVsWQ0NDsWrVqth///3jn/7pn+LjH/94zJ49O9761rfGNddc85zbHX/88SVPz8bsMhf7zMMu87DLPOwSxjfBgwntkUceife///1x9dVXx/bbbz/y/eGvBY/6KIoi/st/+S/xzDPPxPve976YNm1aVbfbcccdR75+4oknIiLizjvvjIiI3/72t/Hud7/7eW/nH/zasctc7DMPu8zDLvOwSxj/fCwtE9oHPvCBOProo+Ov//qvN/m+4FFf/+///b9Yvnx5REQcccQRW3WOXXfdNSIirrzyyij+eLndZv9H7dhlLvaZh13mYZd52CWMf17hwYT1/e9/P7q7u2PZsmXx2GOPbfJr06dPj4iI9evXN2K0SWfp0qUREdHc3BwLFy6s+naPPvpoRETMmDEj5s6dW4vRGCO7zMU+87DLPOwyD7uE8U/wYEJ6+OGH433ve19MnTo1Zs+eHU8//fTzHvfsEEJt3H333RERMWvWrGhubq76dj09PRER8dd//dfR0uKvo/HALnOxzzzsMg+7zMMuYfxzSQsT0rvf/e54/etfH7/61a9iaGjoOS/5O/zwwyMi4umnn47HH3+8wdPm99BDD435NmvWrIkHHnggImKz16pSf3aZi33mYZd52GUedgnjn+DBuLZ+/fq44YYbNnmlxic/+cl44IEH4rLLLtvs7WbNmjXy9Zo1a2o6IxG77bZbRPzxH/5Vq1ZVdZvLL788iqKIBQsWxNve9rZajscY2GUu9pmHXeZhl3nYJYx/ggfj2jvf+c74z//5P8dxxx0XDz/8cJx55plxwQUXxLe+9a1NPpXl2V784hePfH3rrbdGRMT9998ffX19NZ95MnrjG9848vWSJUviqaeees4xg4ODI+9E3tvbG5dccklMnTo1rrjiipgyxV9F44Vd5mKfedhlHnaZh13C+OenjHHtN7/5TUREXH/99fGCF7wgLrjggvjSl74UixYt2uLt/uZv/mbk67POOive+MY3xlve8pbYbrvtajrvZHXKKafEQQcdFBERN910U7ziFa+I73znO7FixYpYtmxZXHLJJXHMMcdEpVKJJ598Mo477rjYsGFD/NM//VN0dXU1eHo2Zpe52GcedpmHXeZhlzABFPAnvb29RUQUEVH09vY2epyiKIri6quvLlpaWoqIKGbMmFFcccUVVd/2k5/8ZLHzzjsXO+20U/GmN72pWL16dQ0nrU697uNG7HLDhg3FeeedV+y7775Fa2trMWPGjGLPPfcsjjnmmOKaa64pnnrqqWLdunXF4YcfXmy33XbFl7/85brMVSv1vI/rvU+7zPF7DZtM+7RLuxzvv9ewybTLovD4xy6hcQQPRozXv8AefPDB4tprry3WrFnT6FG2WeZ/8Ldk3bp1xRVXXFF0dnYWixcvLn760582eqRtlv3B+ObY5cT5vaqRbZ92aZfj/feqRrZdFoXHP3YJjeNzkBj35s2bF/PmzWv0GFSpv78/fvrTn8bPfvazWLFiRaxcuTIeeOCBePWrXx2f//zn481vfnM0NTU1ekyqYJe52GcedpmHXeZhlzA+CR7ANhsaGorzzz8/rr/++rjrrruiKIqRXzv66KPjhhtuiDlz5mz29j/4wQ/i8ccfjze/+c11mJYtsctc7DMPu8zDLvOwSxj/vGkpsM2amppir732ir/927+NY489NnbfffeRX7vmmmtir732ir/7u7+LH/7wh/H0009vctt77703zj333DjssMPqPTbPwy5zsc887DIPu8zDLmH88woPYJs1NzfHscceu8n3uru741vf+lZ85zvfid/85jdx1VVXxVVXXRUzZ86MAw44IF7wghfEr371q/iP//iPuOGGG2L69OkNmp6N2WUu9pmHXeZhl3nYJYx/ggdQE11dXdHV1RUXXXRRLFu2LH7wgx/E3XffHWvXro0nn3wytttuu3jPe94TRx11VLS2tjZ6XLbALnOxzzzsMg+7zMMuYXwRPICamjJlShx88MFx8MEHN3oUtpFd5mKfedhlHnaZh13C+OA9PAAAAIB0BA8AAAAgHcEDAAAASEfwAAAAANIRPAAAAIB0BA8AAAAgHcEDAAAASEfwAAAAANIRPAAAAIB0BA8AAAAgHcEDAAAASEfwAAAAANIRPAAAAIB0BA8AAAAgHcEDAAAASEfwAAAAANIRPAAAAIB0BA8AAAAgHcEDAAAASEfwAAAAANIRPAAAAIB0BA8AAAAgHcEDAAAASEfwAAAAANIRPAAAAIB0BA8AAAAgHcEDAAAASEfwAAAAANIRPAAAAIB0BA8AAAAgHcEDAAAASEfwAAAAANIRPAAAAIB0BA8AAAAgHcEDAAAASKel7BP29fWVfUrqpFKpNHqESaWW97dd1let72/7rB+7zMMu87DLXDz+ycP9TS10dHSUer7Sg0dnZ2fZp4SUurq6Gj0CJbHLPOwyD7vMwy5zsc887JJaKIqi1PO5pAUAAABIp/RXePT29pZ9SuqkUqkotXXU3d0d7e3tNTm3XdZXLXcZYZ/1ZJd52GUedpmLxz951PpnE8pQevAo+5obyKq9vd3PSxJ2mYdd5mGXedhlLvaZh10yEbik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",
"text/plain": [
"<Figure size 1088x1320 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import os\n",
"import warnings\n",
"warnings.filterwarnings(\"ignore\")\n",
"os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'python'\n",
"\n",
"import toml\n",
"from paddle_quantum.finance import EuroOptionEstimator\n",
"\n",
"config = toml.loads(euro_toml)\n",
"initial_price = config[\"initial_price\"]\n",
"strike_price = config[\"strike_price\"]\n",
"interest_rate = config[\"interest_rate\"]\n",
"volatility = config[\"volatility\"]\n",
"maturity_date = config[\"maturity_date\"]\n",
"degree_of_estimation = config[\"degree_of_estimation\"]\n",
"\n",
"\n",
"estimator = EuroOptionEstimator(initial_price, strike_price, interest_rate, volatility, maturity_date, degree_of_estimation)\n",
"print(\"The risk-neutral price of the option is approximately \", estimator.estimate())\n",
"print(\"The following is a circuit implementation diagram of this quantum scheme.\")\n",
"estimator.plot()"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"By modifying the contents of the configuration file and running the prediction code, you can test the model online."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"___\n",
"\n",
"# Note\n",
"\n",
"The models presented here are only intended to solve the option pricing problem of the Black-Scholes model.\n",
"\n",
"# Citation\n",
"\n",
"```\n",
"@article{rebentrost2018quantum,\n",
" title = {Quantum Computational Finance: {{Monte Carlo}} Pricing of Financial Derivatives},\n",
" shorttitle = {Quantum Computational Finance},\n",
" author = {Rebentrost, Patrick and Gupt, Brajesh and Bromley, Thomas R.},\n",
" year = {2018},\n",
" month = aug,\n",
" journal = {Physical Review A},\n",
" volume = {98},\n",
" number = {2},\n",
" pages = {022321},\n",
" publisher = {{American Physical Society}},\n",
" doi = {10.1103/PhysRevA.98.022321},\n",
" url = {https://link.aps.org/doi/10.1103/PhysRevA.98.022321},\n",
"}\n",
"```\n",
"\n",
"# References\n",
"\n",
"[1] Rebentrost, Patrick, Brajesh Gupt, and Thomas R. Bromley. \"Quantum computational finance: Monte Carlo pricing of financial derivatives.\" Physical Review A 98.2 (2018): 022321."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "pq",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.13 (default, Mar 28 2022, 06:16:26) \n[Clang 12.0.0 ]"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "08942b1340a5932ff3a93f52933a99b0e263568f3aace1d262ffa4d9a0f2da31"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}
# The configuration file of quantum portfolio optimization problem.
# This field specifies whether to use random data for stocks, or stock data provided by the customer.
# stock = 'random'
# stock = 'custom'
stock = 'demo'
# Get stock data from demo file or custom file
demo_data_path = 'demo_stock.csv'
custom_data_path = 'file_name.csv'
# Specifies the start_time and end_time of random stock
[random_data]
start_time = [2016, 1, 1]
end_time = [2016, 1, 30]
# This field stores information about the asset, risk, etc.
[stock_para]
# Number of investable projects
num_asset = 7
# The risk factor of investment decision making
risk_weight = 0.5
# The budget
budget = 0
#The penalty
penalty = 0
# This field stores parameters for the parametric quantum circuits
[train_para]
# The depth of the quantum circuits
circuit_depth = 2
# Number of optimization cycles, default is 100.
iterations = 600
# The rate of optimization of gradient descent, default is 0.4.
learning_rate = 0.2
closePrice0,closePrice1,closePrice2,closePrice3,closePrice4,closePrice5,closePrice6,closePrice7,closePrice8,closePrice9,closePrice10,closePrice11
16.87,32.56,5.4,3.71,5.72,7.62,3.7,6.94,5.43,3.46,8.22,4.56
17.18,32.05,5.48,3.75,5.75,7.56,3.7,6.89,5.37,3.45,8.14,4.54
17.07,31.51,5.46,3.73,5.74,7.68,3.68,6.91,5.37,3.41,8.1,4.55
17.15,31.76,5.49,3.79,5.81,7.75,3.7,6.97,5.42,3.5,8.16,4.58
16.66,31.68,5.39,3.72,5.69,7.79,3.63,6.85,5.29,3.42,7.93,4.48
16.79,32.2,5.47,3.77,5.79,7.84,3.66,6.94,5.41,3.46,8.02,4.56
16.69,31.46,5.46,3.76,5.77,7.82,3.63,7.01,5.42,3.48,8,4.53
16.99,31.68,5.53,3.74,5.8,7.8,3.63,7.03,5.39,3.47,8.03,4.53
16.76,31.39,5.5,3.78,5.89,7.92,3.66,7.04,5.45,3.48,8.05,4.56
16.52,30.49,5.47,3.71,5.78,7.96,3.63,7.01,5.43,3.45,7.95,4.47
16.33,30.53,5.39,3.61,5.7,7.93,3.6,6.99,5.35,3.4,7.92,4.42
16.39,30.46,5.35,3.58,5.69,7.87,3.59,6.95,5.26,3.41,7.93,4.38
16.45,29.87,5.37,3.61,5.75,7.86,3.63,6.96,5.54,3.42,7.99,4.35
16,29.21,5.24,3.53,5.7,7.82,3.6,6.87,6.09,3.32,7.9,4.32
16.09,30.11,5.26,3.5,5.71,7.9,3.61,6.87,6.7,3.33,8.01,4.34
15.54,28.98,5.08,3.42,5.54,7.7,3.54,6.58,7.37,3.23,7.73,4.13
13.99,26.63,4.57,3.08,4.99,6.93,3.19,5.92,8.11,2.91,6.96,3.72
14.6,27.62,4.44,2.95,4.89,6.91,3.27,5.78,8.1,2.96,7.01,3.51
14.63,27.64,4.5,3.04,4.94,7.18,3.27,5.89,8.91,3.02,7.06,3.61
14.77,27.9,4.56,3.05,5.08,7.31,3.31,5.94,9.8,3.06,7.08,3.88
14.62,27.5,4.52,3.05,5.39,7.35,3.3,5.93,10.78,3.05,7.07,3.87
14.5,28.67,4.59,3.13,5.35,7.53,3.32,6.06,11.86,3.13,7.15,3.9
14.79,29.08,4.66,3.12,5.23,7.47,3.33,6.16,10.67,3.15,7.17,3.91
14.77,29.08,4.67,3.14,5.26,7.48,3.38,6.18,11.36,3.17,7.21,3.95
14.65,29.95,4.66,3.11,5.19,7.35,3.36,6.15,10.56,3.14,7.19,3.94
15.03,30.8,4.72,3.07,5.18,7.33,3.34,6.11,9.56,3.15,7.29,3.96
15.37,30.42,4.84,3.23,5.31,7.46,3.39,6.35,9.15,3.18,7.41,4.04
15.2,29.7,4.81,3.3,5.33,7.47,3.39,6.34,9.11,3.17,7.4,4.06
15.24,29.65,4.84,3.31,5.31,7.39,3.37,6.26,8.89,3.12,7.34,3.99
15.59,29.85,4.88,3.3,5.38,7.47,3.42,6.44,8.36,3.15,7.42,4.04
15.58,29.25,4.89,3.33,5.39,7.48,3.43,6.46,8.68,3.16,7.52,4.03
15.23,28.9,4.82,3.31,5.41,8.06,3.37,6.41,8.77,3.12,7.41,3.97
15.04,29.33,4.74,3.22,5.28,8.02,3.32,6.32,9.65,3.06,7.31,3.9
14.99,30.11,4.84,3.31,5.3,8.01,3.36,6.32,9.11,3.13,7.51,3.9
15.11,29.67,4.79,3.25,5.38,8.11,3.37,6.42,8.41,3.15,7.5,3.88
14.5,29.59,4.63,3.12,5.12,7.87,3.3,6.15,8.4,3.08,7.18,3.76
\ No newline at end of file
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 量子金融投资组合优化简介\n",
"*Copyright (c) 2022 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.*\n",
"\n",
"假如你是一位资产管理人,想要将数额为$K$的基金一次性投入到$N$个可投资的项目中,各项目都有自己的投资回报率和风险,你的目标就是在考虑到市场影响和交易费用的的基础上找到一个最佳的投资组合,使得该笔资产以最优的投资方案实施。\n",
"\n",
"为了方便建模,我们做如下两点假设:\n",
" 1.每个项目都是等额投资的;\n",
" 2.给定的预算是投资一个项目金额的整数倍,且必须全部花完。\n",
"\n",
"在投资组合的基本理论中,投资组合的总体风险与项目间的协方差有关,而协方差与任意两项目的相关系数成正比。相关系数越小,其协方差就越小,投资组合的总体风险也就越小。在这里我们给出了采用均值方差组合优化的方法下的该问题的建模方程:\n",
"$$\n",
"\\omega=\\max _{x \\in\\{0,1\\}^n} \\mu^T x-q x^T S x \\quad \\text { subject to: } 1^T x=B,\n",
"$$\n",
"该式子中各符号代表的含义如下:\n",
"- $x \\in \\{0, 1\\}^{n}$ 表示一个向量,其中每一个元素均为二进制变量,即如果资产$i$被投资了,则 $x_i$=1,如果没有被选择,则 $x_i=0$;\n",
"- $\\mu \\in \\mathbb{R}^n$ 表示投资每个项目的预期回报率;\n",
"- $S \\in \\mathbb{R}^{n \\times n}$ 表示各投资项目回报率之间的协方差矩阵;\n",
"- $q > 0$ 表示做出该投资决定的风险系数;\n",
"- $B$ 代表投资预算,即我们可以投资的项目数。\n",
"\n",
"让我们对这个方程的含义进行说明。$\\mu^T x$ 刻画 $x$ 代表的投资方案的预期收益。$x^T S x$ 刻画投资项目之间的关联性,乘上风险系数 $q$ 之后,代表该投资方案包含的风险。$1^T x=B$ 要求我们投资的项目数等于我们的预算总数。因此,当我们对所有的投资方案寻找等式右边的最大值,得到的 $\\omega$ 就是我们理论上可以得到的最大收益。\n",
"\n",
"为了方便寻找使收益最大化的投资组合,我们定义如下的损失函数:\n",
"$$\n",
"C_x=q \\sum_i \\sum_j S_{j i} x_i x_j-\\sum_i x_i \\mu_i+A\\left(B-\\sum_i x_i\\right)^2,\n",
"$$\n",
"其中,约束条件以拉格朗日乘子的形式进入方程。于是,我们的任务转化成寻找使损失函数最小的$x$。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 量子编码及求解\n",
"我们通过变换 $x_i \\mapsto \\frac{I-Z_i}{2}$ 将损失函数转为一个哈密顿量,从而完成投资组合优化问题的编码。这里$Z_i=I \\otimes I \\otimes \\ldots \\otimes Z \\otimes \\ldots \\otimes I$,即 $Z_{i}$ 是作用在第$i$ 个比特上的Pauli算符。我们用这个映射将 $C_x$ 转化成量子比特数为 $n$ 的系统的哈密顿矩阵 $H_C$,其基态即为投资组合优化问题的最优解。为了寻找这一哈密顿量的基态,我们使用变分量子算法的思想,通过一个参数化量子线路,生成一个试验态 $|\\theta^* \\rangle$。我们通过量子线路获得哈密顿量在该试验态上的期望值,然后,通过经典的梯度下降算法调节参数化量子线路的参数,使期望值向基态能量靠拢。重复若干次之后,我们找到最优解:\n",
"$$\n",
"|\\theta^* \\rangle = \\argmin_\\theta L(\\vec{\\theta})=\\argmin_\\theta \\left\\langle\\vec{\\theta}\\left|H_C\\right| \\vec{\\theta}\\right\\rangle.\n",
"$$\n",
"最后,我们读出测量结果的概率分布:$p(z)=\\left|\\left\\langle z \\mid \\vec{\\theta}^*\\right\\rangle\\right|^2$,即由量子编码还原出原先比特串的信息。某个比特串出现的概率越大,意味着其是投资组合优化问题最优解的可能性越大。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 使用教程\n",
"### 配置文件\n",
"我们给出了一个设置好参数,可以直接进行组合优化计算的配置文件。用户只需在`config.toml`里修改相应的参数,并在终端运行\n",
"`python qpo.py --config config.toml --logger qpo_log.log`,即可计算最优投资组合。\n",
"### 输出结果\n",
"运行结果将输出到文件 `qpo_log.log` 中。我们的优化过程将被记录在日志中。用户可以看到随着循环数的增加,损失大小的变化。最后我们会输出优化得到的方案选择。\n",
"\n",
"### 参数说明\n",
"- `stock`,默认为 `'demo'`,即使用我们提供的样本数据。也可选 `'random'` 或 `'custom'` 来随机生成或使用自定义数据。\n",
"若用户选择随机生成数据,用户可以通过修改 `start_time` 和 `end_time` 参数来选择股票数据的起止日期。对于自定义数据,用户可以使用格式和表头命名规则(即 `csv` 文件的第一行)与 `demo_stock.csv` 文件相同的自定义文件,并在配置文件修改该文件路径:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"custom_data_path = 'file_name.csv'"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 在线演示\n",
"这里,我们给出一个在线演示的版本,可以在线进行测试。首先定义配置文件的内容:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"config_toml = r\"\"\"\n",
"# 用于计算金融组合优化问题模型的整体配置文件。\n",
"# 使用样例股票数据\n",
"stock = 'demo' \n",
"demo_data_path = 'demo_stock.csv'\n",
"# 可投资项目的数目\n",
"num_asset = 7\n",
"# 决策风险系数\n",
"risk_weight = 0.5\n",
"# 投资预算\n",
"budget = 0\n",
"# 投资惩罚\n",
"penalty = 0\n",
"# 量子电路深度\n",
"circuit_depth = 2\n",
"# 优化循环次数\n",
"iterations = 600\n",
"# 梯度下降优化的学习速率\n",
"learning_rate = 0.2 \n",
"\"\"\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"量桨 PaddleQuantum 的金融模块实现了量子金融优化的数值模拟。我们可以从 ``paddle_quantum.finance.qpo`` 模块里导入 ``portfolio_combination_optimization`` 来解决配置好的金融组合优化问题。"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"100%|██████████| 600/600 [01:15<00:00, 7.93it/s]\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"******************* 最优组合为: [2, 5, 6] *******************\n"
]
}
],
"source": [
"import os\n",
"import warnings\n",
"warnings.filterwarnings(\"ignore\")\n",
"os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'python'\n",
"import pandas as pd\n",
"\n",
"import toml\n",
"from paddle_quantum.finance.qpo import portfolio_combination_optimization\n",
"from paddle_quantum.finance import DataSimulator\n",
"\n",
"config = toml.loads(config_toml)\n",
"demo_data_path = config[\"demo_data_path\"]\n",
"num_asset = config[\"num_asset\"]\n",
"risk_weight = config[\"risk_weight\"]\n",
"budget = config[\"budget\"]\n",
"penalty = config[\"penalty\"]\n",
"circuit_depth = config[\"circuit_depth\"]\n",
"iterations = config[\"iterations\"]\n",
"learning_rate = config[\"learning_rate\"]\n",
"\n",
"stocks_name = [(\"STOCK%s\" % i) for i in range(num_asset)]\n",
"source_data = pd.read_csv(demo_data_path)\n",
"processed_data = [source_data['closePrice'+str(i)].tolist() for i in range(num_asset)]\n",
"data = DataSimulator(stocks_name)\n",
"data.set_data(processed_data)\n",
"\n",
"invest = portfolio_combination_optimization(num_asset, data, iterations, learning_rate, risk_weight, budget,\n",
" penalty, circuit=circuit_depth)\n",
"print(f\"******************* 最优组合为: {invest} *******************\")\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"## 注意事项\n",
"若投资方案数较小(`num_asset`$< 12$),我们可以通过严格对角化哈密顿量来计算真实的损失最小值,并与优化的结果比较。若二者的差别较大,该优化结果不可靠,需要重新选择训练参数。\n",
"## 相关论文以及引用信息\n",
"```\n",
"@article{ORUS2019100028,\n",
"title = {Quantum computing for finance: Overview and prospects},\n",
"journal = {Reviews in Physics},\n",
"volume = {4},\n",
"pages = {100028},\n",
"year = {2019},\n",
"issn = {2405-4283},\n",
"doi = {https://doi.org/10.1016/j.revip.2019.100028},\n",
"url = {https://www.sciencedirect.com/science/article/pii/S2405428318300571},\n",
"author = {Román Orús and Samuel Mugel and Enrique Lizaso}\n",
"}\n",
"\n",
"@ARTICLE{2020arXiv200614510E,\n",
" author = {{Egger}, Daniel J. and {Gambella}, Claudio and {Marecek}, Jakub and {McFaddin}, Scott and {Mevissen}, Martin and {Raymond}, Rudy and {Simonetto}, Andrea and {Woerner}, Stefan and {Yndurain}, Elena},\n",
" title = \"{Quantum Computing for Finance: State of the Art and Future Prospects}\",\n",
" journal = {arXiv e-prints},\n",
" keywords = {Quantum Physics, Quantitative Finance - Statistical Finance},\n",
" year = 2020,\n",
" month = jun,\n",
" eid = {arXiv:2006.14510},\n",
" pages = {arXiv:2006.14510},\n",
"archivePrefix = {arXiv},\n",
" eprint = {2006.14510},\n",
" primaryClass = {quant-ph},\n",
" adsurl = {https://ui.adsabs.harvard.edu/abs/2020arXiv200614510E},\n",
" adsnote = {Provided by the SAO/NASA Astrophysics Data System}\n",
"}\n",
"\n",
"@article{10.2307/2975974,\n",
" ISSN = {00221082, 15406261},\n",
" URL = {http://www.jstor.org/stable/2975974},\n",
" author = {Harry Markowitz},\n",
" journal = {The Journal of Finance},\n",
" number = {1},\n",
" pages = {77--91},\n",
" publisher = {[American Finance Association, Wiley]},\n",
" title = {Portfolio Selection},\n",
" urldate = {2022-12-07},\n",
" volume = {7},\n",
" year = {1952}\n",
"}\n",
"```"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.8.13 ('pq')",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.13"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "d3caffbb123012c2d0622db402df9f37d80adc57c1cef1fdb856f61446d88d0a"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Introduction of quantum portfolio optimization\n",
"*Copyright (c) 2022 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.*\n",
"\n",
"If you are an active investment manager who wants to invest $K$ dollars to $N$ projects, each with its return and risk, your goal is to find an optimal way to invest in the projects, taking into account the market impact and transaction costs.\n",
"\n",
"To make the modeling easy to formulate, two assumptions are made to constrain the problem:\n",
" 1.Each asset is invested with an equal amount of money;\n",
" 2.Budget is a multiple of each investment amount and must be fully spent.\n",
"\n",
"In the theory of portfolio optimization, the overall risk of a portfolio is related to the covariance between assets, which is proportional to the correlation coefficients of any two assets. The smaller the correlation coefficients, the smaller the covariance, and then the smaller the overall risk of the portfolio. Here we use the mean-variance approach to model this problem:\n",
"$$\n",
"\\omega=\\max _{x \\in\\{0,1\\}^n} \\mu^T x-q x^T S x \\quad \\text { subject to: } 1^T x=B,\n",
"$$\n",
"where each symbol has the following meaning:\n",
"- $x \\in \\{0, 1\\}^{n}$ denotes the vector of binary decision variables, which indicate which each assets is picked ($x_i$=1) or not ($x_i=0$)\n",
"- $\\mu \\in \\mathbb{R}^n$ defines the expected returns for the assets\n",
"- $S \\in \\mathbb{R}^{n \\times n}$ represents the covariances between the assets\n",
"- $q > 0$ represents the risk factor of investment decision making\n",
"- $B$ denotes the budget, i.e. the number of assets to be selected out of $N$\n",
"\n",
"Let us illustrate on the meaning of this equation. $\\mu^T x$ describes the expected benefit of the investment plan represented by $x$. $x^T S x$ describes the correlation between the projects, which, after producting with the risk coefficient $q$, represents the risk incorporated in the investment plan. The restriction $1^T x=B$ requires the number of invested projects equals to our total budget. Therefore, $\\omega$ represents the largest benefit we could get theoretically.\n",
"\n",
"In order to find the optimal investment plan more easily, we can define the loss function\n",
"$$\n",
"C_x=q \\sum_i \\sum_j S_{j i} x_i x_j-\\sum_i x_i \\mu_i+A\\left(B-\\sum_i x_i\\right)^2,\n",
"$$\n",
"where the restriction condition enters the function with the form of Lagrange multiplier. Therefore, our task becomes finding the investment plan $x$ that minimizes the loss $C_x$."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Quantum encoding and solution\n",
"\n",
"We now need to transform the cost function $C_x$ into a Hamiltonian to realize the encoding of the portfolio optimization problem. One just needs to do the following transformation:\n",
"$\n",
"x_i \\mapsto \\frac{I-Z_i}{2},\n",
"$\n",
"where $Z_i=I \\otimes I \\otimes \\ldots \\otimes Z \\otimes \\ldots \\otimes I$, i.e., $Z_{i}$ is the Pauli operator acting solely on the $i$-th qubit. Thus using the above mapping, we can transform the cost function $C_x$ into a Hamiltonian $H_C$ for the system of $n$ qubits, the ground state of which represents the solution of the portfolio optimization problem. In order to find the ground state, we use the idea of variational quantum algorithms. We implement a parametric quantum circuit, and use it to generate a trial state $|\\theta^* \\rangle$. We use the quantum circuit to measure the expectation value of the Hamiltonian on this state. Then, classical gradient descent algorithm is implemented to adjust the parameters of the parametric circuit, where the expectation value evolves towards the ground state energy. After some iterations, we arrive at the optimal value\n",
"$$\n",
"|\\theta^* \\rangle = \\argmin_\\theta L(\\vec{\\theta})=\\argmin_\\theta \\left\\langle\\vec{\\theta}\\left|H_C\\right| \\vec{\\theta}\\right\\rangle.\n",
"$$\n",
"\n",
"Finally, we read out the probability distribution from the measurement result (i.e. decoding the quantum problem to give information about the original bit string)\n",
"$\n",
"p(z)=\\left|\\left\\langle z \\mid \\vec{\\theta}^*\\right\\rangle\\right|^2.\n",
"$\n",
"In the case of quantum parameterized circuits with sufficient expressiveness, the greater the probability of a certain bit string, the greater the probability that it corresponds to an optimal solution to the portfolio optimization problem."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## User's guide\n",
"### Configuration file and input parameters\n",
"We provide a configuration file with previously chosen parameter. The user just needs to change the parameters in the `config.toml` file, and run `python qpo.py --config config.toml --logger qpo_log.log` in the terminal, to solve the portfolio optimization problem.\n",
"### Output\n",
"The results will be output to the `qpo_log.log` file. First of all, the process of optimization will be documented in the log. Users can see the evolution of loss function as the looping times increases. \n",
"### Parameters\n",
"- `stock`, default is `'demo'`, i.e., using the stock data we provide in the demo file. Users can switch to `'random'` or `'custom'` to generate random stock data or use custom stock data. If user chooses to generate data randomly, the parameters `start_time` and `endtime` can be altered to specify the start and end date of the stock data. If user chooses to use custom data, he or she can store the information of the stock in a csv file, and write in the configuration file:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"custom_data_path = 'file_name.csv'"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Online demonstration\n",
"Here, we provide an online demonstration version. Firstly, we define the parameters in the configuration file:"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [],
"source": [
"config_toml = r\"\"\"\n",
"# # The configuration file of quantum portfolio optimization problem.\n",
"# Use demo stock data\n",
"stock = 'demo' \n",
"demo_data_path = 'demo_stock.csv'\n",
"# Number of investable projects\n",
"num_asset = 7\n",
"# Risk of decision making\n",
"risk_weight = 0.5\n",
"# Budget\n",
"budget = 0\n",
"# Penalty\n",
"penalty = 0\n",
"# The depth of the quantum circuit\n",
"circuit_depth = 2\n",
"# Number of loop cycles used in the optimization\n",
"iterations = 600\n",
"# Learning rate of gradient descent\n",
"learning_rate = 0.2\n",
"\"\"\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The finance module in PaddleQuantum realizes the numerical simulation of the quantum portfolio optimization problem."
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"100%|██████████| 600/600 [01:04<00:00, 9.24it/s]\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"******************* The optimal investment plan is: [2, 5, 6] *******************\n"
]
}
],
"source": [
"import os\n",
"import warnings\n",
"warnings.filterwarnings(\"ignore\")\n",
"os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'python'\n",
"import pandas as pd\n",
"\n",
"import toml\n",
"from paddle_quantum.finance.qpo import portfolio_combination_optimization\n",
"from paddle_quantum.finance import DataSimulator\n",
"\n",
"config = toml.loads(config_toml)\n",
"demo_data_path = config[\"demo_data_path\"]\n",
"num_asset = config[\"num_asset\"]\n",
"risk_weight = config[\"risk_weight\"]\n",
"budget = config[\"budget\"]\n",
"penalty = config[\"penalty\"]\n",
"circuit_depth = config[\"circuit_depth\"]\n",
"iterations = config[\"iterations\"]\n",
"learning_rate = config[\"learning_rate\"]\n",
"\n",
"stocks_name = [(\"STOCK%s\" % i) for i in range(num_asset)]\n",
"source_data = pd.read_csv(demo_data_path)\n",
"processed_data = [source_data['closePrice'+str(i)].tolist() for i in range(num_asset)]\n",
"data = DataSimulator(stocks_name)\n",
"data.set_data(processed_data)\n",
"\n",
"invest = portfolio_combination_optimization(num_asset, data, iterations, learning_rate, risk_weight, budget,\n",
" penalty, circuit=circuit_depth)\n",
"print(f\"******************* The optimal investment plan is: {invest} *******************\")"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Note\n",
"If the number of investable projects is small (`num_asset`$< 12$), we can diagonalize the Hamiltonian exactly, and compare the real minimum loss value with that found by the optimization process. If the difference is large, the optimization result may be unreliable, and re-choosing of the training parameters might be necessary. Finally, we output the optimal investment plan."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## References\n",
"```\n",
"@article{ORUS2019100028,\n",
"title = {Quantum computing for finance: Overview and prospects},\n",
"journal = {Reviews in Physics},\n",
"volume = {4},\n",
"pages = {100028},\n",
"year = {2019},\n",
"issn = {2405-4283},\n",
"doi = {https://doi.org/10.1016/j.revip.2019.100028},\n",
"url = {https://www.sciencedirect.com/science/article/pii/S2405428318300571},\n",
"author = {Román Orús and Samuel Mugel and Enrique Lizaso}\n",
"}\n",
"\n",
"@ARTICLE{2020arXiv200614510E,\n",
" author = {{Egger}, Daniel J. and {Gambella}, Claudio and {Marecek}, Jakub and {McFaddin}, Scott and {Mevissen}, Martin and {Raymond}, Rudy and {Simonetto}, Andrea and {Woerner}, Stefan and {Yndurain}, Elena},\n",
" title = \"{Quantum Computing for Finance: State of the Art and Future Prospects}\",\n",
" journal = {arXiv e-prints},\n",
" keywords = {Quantum Physics, Quantitative Finance - Statistical Finance},\n",
" year = 2020,\n",
" month = jun,\n",
" eid = {arXiv:2006.14510},\n",
" pages = {arXiv:2006.14510},\n",
"archivePrefix = {arXiv},\n",
" eprint = {2006.14510},\n",
" primaryClass = {quant-ph},\n",
" adsurl = {https://ui.adsabs.harvard.edu/abs/2020arXiv200614510E},\n",
" adsnote = {Provided by the SAO/NASA Astrophysics Data System}\n",
"}\n",
"\n",
"@article{10.2307/2975974,\n",
" ISSN = {00221082, 15406261},\n",
" URL = {http://www.jstor.org/stable/2975974},\n",
" author = {Harry Markowitz},\n",
" journal = {The Journal of Finance},\n",
" number = {1},\n",
" pages = {77--91},\n",
" publisher = {[American Finance Association, Wiley]},\n",
" title = {Portfolio Selection},\n",
" urldate = {2022-12-07},\n",
" volume = {7},\n",
" year = {1952}\n",
"}\n",
"```"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.8.13 ('pq')",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.13"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "d3caffbb123012c2d0622db402df9f37d80adc57c1cef1fdb856f61446d88d0a"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}
# !/usr/bin/env python3
# Copyright (c) 2021 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.
# 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.
r"""
Quantum portfolio optimization.
"""
import os
import sys
from typing import Dict
import logging
import argparse
import toml
import datetime
import pandas as pd
from paddle_quantum.finance.qpo import portfolio_combination_optimization
from paddle_quantum.finance import DataSimulator
def main(args):
# logger configure
log_path = args.logger
logger = logging.Logger(name='logger_qpo')
logger_file_handler = logging.FileHandler(log_path)
logger_file_handler.setFormatter(logging.Formatter(r'%(levelname)s %(asctime)s %(message)s'))
logger_file_handler.setLevel(logging.INFO)
logger.addHandler(logger_file_handler)
logger.warning("------------------- Process starts -------------------")
# data preparation
parsed_configs: Dict = toml.load(args.config)
num_asset = parsed_configs["stock_para"]["num_asset"]
if parsed_configs['stock'] == 'demo':
stock_file_path = os.path.join(this_file_path, './demo_stock.csv')
stocks_name = [("STOCK%s" % i) for i in range(num_asset)]
source_data = pd.read_csv(stock_file_path)
processed_data = [source_data['closePrice'+str(i)].tolist() for i in range(num_asset)]
data = DataSimulator(stocks_name)
data.set_data(processed_data)
logger.warning(f"******************* {num_asset} stocks processed *******************")
elif parsed_configs['stock'] == 'random':
stocks_name = [("STOCK%s" % i) for i in range(num_asset)]
data = DataSimulator(stocks=stocks_name, start=datetime.datetime(
*parsed_configs['random_data']['start_time']), end=datetime.datetime(*parsed_configs['random_data']['end_time']))
data.randomly_generate()
logger.warning(f"******************* {num_asset} stocks randomly generated *******************")
elif parsed_configs['stock'] == 'custom':
stock_file_path = parsed_configs["custom_data_path"]
stocks_name = [("STOCK%s" % i) for i in range(num_asset)]
source_data = pd.read_csv(stock_file_path)
processed_data = [source_data['closePrice'+str(i)].tolist() for i in range(num_asset)]
data = DataSimulator(stocks_name)
data.set_data(processed_data)
logger.warning(f"******************* {num_asset} stocks processed *******************")
# load model parameters
risk_weight = parsed_configs["stock_para"]["risk_weight"]
budget = parsed_configs["stock_para"]["budget"]
penalty = parsed_configs["stock_para"]["penalty"]
circuit_depth = parsed_configs["train_para"]["circuit_depth"]
iters = parsed_configs["train_para"]["iterations"]
lr = parsed_configs["train_para"]["learning_rate"]
# optimization
logger.warning("******************* Train starts *******************")
invest = portfolio_combination_optimization(num_asset, data, iters, lr, risk_weight, budget,
penalty, circuit=circuit_depth, logger=logger, compare=True)
logger.warning("******************* Train ends *******************")
logger.warning(f"******************* Output is {invest} *******************")
logger.warning("------------------- Process ends -------------------")
if __name__ == "__main__":
this_file_path = sys.path[0]
parser = argparse.ArgumentParser(description="Quantum chemistry task with paddle quantum.")
parser.add_argument(
"--config", default=os.path.join(this_file_path, './config.toml'), type=str, help="The path of toml format config file.")
parser.add_argument(
"--logger", default=os.path.join(this_file_path, './qpo_log.log'), type=str, help="The path of log file saved.")
main(parser.parse_args())
# The configuration file for protein folding problem
# The amino acids sequence that form a protein.
# Valid amino acid labels are (https://en.wikipedia.org/wiki/Amino_acid):
# C: Cysteine
# M: Methionine
# F: Phenylalanine
# I: Isoleucine
# L: Leucine
# V: Valine
# W: Tryptophan
# Y: Tyrosine
# A: Alanine
# G: Glycine
# T: Threonine
# S: Serine
# N: Asparagine
# Q: Glutamine
# D: Aspartate
# E: Glutamate
# H: Histidine
# R: Arginine
# K: Lysine
# P: Proline
# NOTE: the more amino acids in the sequence, the longer program will run
# NOTE: the example below takes approximately 0.5h!
amino_acids = ["A", "P", "R", "L", "R", "F", "Y"]
# Pair of indices indicates the potentially interact amino acide pair, below indicates that
# the 0-th and 5-th acids will interact and 1-th and 6-th acids will interact.
possible_contractions = [[0, 5], [1, 6]]
# Depth of the quantum circuit used in VQE
depth = 1
# Number of VQE iterations
num_iterations = 200
# The condition for VQE convergence
tol = 1e-3
# The number of steps between two consecutive loss records
save_every = 10
# learning rate for the optimizer
learning_rate = 0.5
\ No newline at end of file
# !/usr/bin/env python3
# Copyright (c) 2021 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.
# 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.
import argparse
import toml
import time
import os
import warnings
import logging
from paddle import optimizer as paddle_optimizer
from paddle_quantum.ansatz import Circuit
from paddle_quantum.biocomputing import Protein
from paddle_quantum.biocomputing import ProteinFoldingSolver
from paddle_quantum.biocomputing import visualize_protein_structure
warnings.filterwarnings('ignore')
os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'python'
logging.basicConfig(filename="log", filemode="w", level=logging.INFO, format="%(message)s")
def circuit(num_qubits: int, depth: int) -> Circuit:
r"""Ansatz used in protein folding VQE.
"""
cir = Circuit(num_qubits)
cir.superposition_layer()
for _ in range(depth):
cir.ry()
cir.cx()
cir.ry()
return cir
def main(args):
time_start = time.strftime("%Y%m%d-%H:%M:%S", time.localtime())
logging.info(f"Job start at {time_start:s}")
# construct the protein
parsed_configs = toml.load(args.config)
aa_seq = parsed_configs["amino_acids"]
contact_pairs = parsed_configs["possible_contactions"]
num_aa = len(aa_seq)
protein = Protein("".join(aa_seq), {(0, 1): 1, (1, 2): 0, (num_aa-2, num_aa-1): 3}, contact_pairs)
# build the solver
cir_depth = parsed_configs["depth"]
cir = circuit(protein.num_qubits, cir_depth)
penalty_factors = [10.0, 10.0]
alpha = 0.5
optimizer = paddle_optimizer.Adam
num_iterations = parsed_configs["num_iterations"]
tol = parsed_configs["tol"]
save_every = parsed_configs["save_every"]
learning_rate = parsed_configs["learning_rate"]
problem = ProteinFoldingSolver(penalty_factors, alpha, optimizer, num_iterations, tol, save_every)
_, protein_str = problem.solve(protein, cir, learning_rate=learning_rate)
# parse results & plot the 3d structure of protein
num_config_qubits = protein.num_config_qubits
bond_directions = [1, 0]
bond_directions.extend(int(protein_str[slice(i, i + 2)], 2) for i in range(0, num_config_qubits, 2))
bond_directions.append(3)
visualize_protein_structure(aa_seq, bond_directions)
logging.info("\n#######################################\nSummary\n#######################################")
logging.info(f"Protein bonds direction: {bond_directions}.")
time_stop = time.strftime("%Y%m%d-%H:%M:%S", time.localtime())
logging.info(f"\nJob end at {time_stop:s}\n")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Protein folding task with paddle quantum.")
parser.add_argument("--config", type=str, help="Input the config file with toml format.")
main(parser.parse_args())
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import warnings\n",
"\n",
"warnings.filterwarnings(\"ignore\")"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"# 蛋白质功能与结构设计简介\n",
"*Copyright (c) 2022 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.*\n",
"\n",
"蛋白质是生物体中重要的结构和功能分子,它们通过组装氨基酸形成长链,并通过氨基酸链的空间结构来实现特定的功能。蛋白质的空间结构指的是氨基酸链在三维空间中的构型。这种构型可以通过X射线衍射、核磁共振或其它方法测定。研究表明,蛋白质的空间结构与其功能密切相关。例如,酶作为一类重要的蛋白质,其空间结构决定了其与底物的相互作用,从而实现了化学反应的催化作用。此外,蛋白质的空间结构还可以通过改变氨基酸序列来控制其功能。\n",
"\n",
"蛋白质在不同的折叠方式下会产生不同的空间结构,因此研究蛋白质折叠对于研究蛋白质功能有重要意义。由于蛋白质的结构和功能问题具有高度的复杂性和非线性性,目前用经典计算求解蛋白质折叠问题的效率很低。量子计算可以通过量子力学原理来快速求解复杂的非线性优化问题,普遍认为将会在未来对蛋白质折叠方面的研究起到极大的帮助。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 利用量子计算方法模拟蛋白质折叠过程\n",
"### 晶格模型\n",
"在蛋白质结构研究中,一种常用的方法是晶格模型\\[1\\],它将蛋白质中的氨基酸链划分为一系列晶格单元,每个晶格单元包括若干个氨基酸。通过对晶格单元之间相互作用的分析,我们可以推测出蛋白质的空间结构。晶格模型可以帮助我们更好地理解蛋白质的结构与功能,为药物设计和治疗疾病提供重要的理论依据。\n",
"![](lattice_model_demo.jpg)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Protein with 7 nodes and 6 edges\n"
]
}
],
"source": [
"from paddle_quantum.biocomputing import Protein\n",
"\n",
"protein = Protein(\"APRLRFY\")\n",
"print(protein)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"利用 `paddle_quantum` 的 `biocomputing` 模块, 我们可以很容易地完成一个蛋白质的构建,上面的代码就构造了一个包含7个氨基酸的氨基酸链。\n",
"\n",
"从晶格模型出发,我们可以根据格点之间的相互作用得到一个蛋白质的哈密顿量\\[2\\],我们可以基于这个哈密顿量构造变分量子算法(VQE)来求解蛋白质分子的稳定结构(能量最低时的结构)。"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"327.0085 I\n",
"-47.5 Z1, Z3\n",
"65.0 Z1, Z5\n",
"-50.0 Z1, Z7\n",
"52.5 Z1, Z9\n",
"-47.5 Z0, Z2\n",
"65.0 Z0, Z4\n",
"-50.0 Z0, Z6\n",
"52.5 Z0, Z8\n",
"-47.5 Z0, Z1, Z2, Z3\n",
"65.0 Z0, Z1, Z4, Z5\n",
"-50.0 Z0, Z1, Z6, Z7\n",
"52.5 Z0, Z1, Z8, Z9\n",
"-65.0 Z3, Z5\n",
"92.5 Z3, Z7\n",
"-60.0 Z3, Z9\n",
"-65.0 Z2, Z4\n",
"92.5 Z2, Z6\n",
"-60.0 Z2, Z8\n",
"-65.0 Z2, Z3, Z4, Z5\n",
"92.5 Z2, Z3, Z6, Z7\n",
"-60.0 Z2, Z3, Z8, Z9\n",
"-72.5 Z5, Z7\n",
"92.5 Z5, Z9\n",
"-72.5 Z4, Z6\n",
"92.5 Z4, Z8\n",
"-72.5 Z4, Z5, Z6, Z7\n",
"92.5 Z4, Z5, Z8, Z9\n",
"-65.0 Z7, Z9\n",
"-65.0 Z6, Z8\n",
"-65.0 Z6, Z7, Z8, Z9\n",
"-157.168 Z12\n",
"30.0 Z1, Z3, Z12\n",
"-40.0 Z1, Z5, Z12\n",
"30.0 Z1, Z7, Z12\n",
"-27.5 Z1, Z9, Z12\n",
"30.0 Z0, Z2, Z12\n",
"-40.0 Z0, Z4, Z12\n",
"30.0 Z0, Z6, Z12\n",
"-27.5 Z0, Z8, Z12\n",
"30.0 Z0, Z1, Z2, Z3, Z12\n",
"-40.0 Z0, Z1, Z4, Z5, Z12\n",
"30.0 Z0, Z1, Z6, Z7, Z12\n",
"-27.5 Z0, Z1, Z8, Z9, Z12\n",
"37.5 Z3, Z5, Z12\n",
"-52.5 Z3, Z7, Z12\n",
"30.0 Z3, Z9, Z12\n",
"37.5 Z2, Z4, Z12\n",
"-52.5 Z2, Z6, Z12\n",
"30.0 Z2, Z8, Z12\n",
"37.5 Z2, Z3, Z4, Z5, Z12\n",
"-52.5 Z2, Z3, Z6, Z7, Z12\n",
"30.0 Z2, Z3, Z8, Z9, Z12\n",
"37.5 Z5, Z7, Z12\n",
"-40.0 Z5, Z9, Z12\n",
"37.5 Z4, Z6, Z12\n",
"-40.0 Z4, Z8, Z12\n",
"37.5 Z4, Z5, Z6, Z7, Z12\n",
"-40.0 Z4, Z5, Z8, Z9, Z12\n",
"30.0 Z7, Z9, Z12\n",
"30.0 Z6, Z8, Z12\n",
"30.0 Z6, Z7, Z8, Z9, Z12\n",
"-12.5 Z2, Z3, Z5, Z6\n",
"-10.0 Z2, Z3, Z5, Z8\n",
"-12.5 Z2, Z5, Z6, Z7\n",
"-10.0 Z2, Z5, Z8, Z9\n",
"-12.5 Z3, Z4, Z5, Z6\n",
"-10.0 Z3, Z4, Z5, Z8\n",
"-12.5 Z3, Z4, Z6, Z7\n",
"-10.0 Z3, Z4, Z8, Z9\n",
"30.0 Z3, Z5, Z7, Z9\n",
"10.0 Z3, Z5, Z6, Z8\n",
"10.0 Z3, Z5, Z6, Z7, Z8, Z9\n",
"-12.5 Z2, Z3, Z4, Z7\n",
"-10.0 Z2, Z3, Z7, Z8\n",
"-12.5 Z2, Z4, Z5, Z7\n",
"-10.0 Z2, Z7, Z8, Z9\n",
"10.0 Z3, Z4, Z7, Z8\n",
"10.0 Z3, Z4, Z5, Z7, Z8, Z9\n",
"-10.0 Z3, Z6, Z7, Z8\n",
"-10.0 Z3, Z6, Z8, Z9\n",
"-10.0 Z2, Z3, Z4, Z9\n",
"-10.0 Z2, Z3, Z6, Z9\n",
"-10.0 Z2, Z4, Z5, Z9\n",
"-10.0 Z2, Z6, Z7, Z9\n",
"10.0 Z3, Z4, Z6, Z9\n",
"10.0 Z3, Z4, Z5, Z6, Z7, Z9\n",
"10.0 Z2, Z4, Z7, Z9\n",
"30.0 Z2, Z4, Z6, Z8\n",
"10.0 Z2, Z4, Z6, Z7, Z8, Z9\n",
"10.0 Z2, Z5, Z6, Z9\n",
"10.0 Z2, Z4, Z5, Z6, Z8, Z9\n",
"10.0 Z2, Z5, Z7, Z8\n",
"10.0 Z2, Z4, Z5, Z6, Z7, Z8\n",
"10.0 Z2, Z3, Z4, Z5, Z7, Z9\n",
"10.0 Z2, Z3, Z4, Z5, Z6, Z8\n",
"30.0 Z2, Z3, Z4, Z5, Z6, Z7, Z8, Z9\n",
"10.0 Z2, Z3, Z5, Z6, Z7, Z9\n",
"10.0 Z2, Z3, Z4, Z6, Z7, Z8\n",
"10.0 Z2, Z3, Z5, Z7, Z8, Z9\n",
"10.0 Z2, Z3, Z4, Z6, Z8, Z9\n",
"-12.5 Z4, Z5, Z7, Z8\n",
"-12.5 Z4, Z7, Z8, Z9\n",
"-12.5 Z5, Z6, Z7, Z8\n",
"-12.5 Z5, Z6, Z8, Z9\n",
"-12.5 Z4, Z5, Z6, Z9\n",
"-12.5 Z4, Z6, Z7, Z9\n",
"7.5 Z2, Z3, Z5, Z6, Z12\n",
"5.0 Z2, Z3, Z5, Z8, Z12\n",
"7.5 Z2, Z5, Z6, Z7, Z12\n",
"5.0 Z2, Z5, Z8, Z9, Z12\n",
"7.5 Z3, Z4, Z5, Z6, Z12\n",
"5.0 Z3, Z4, Z5, Z8, Z12\n",
"7.5 Z3, Z4, Z6, Z7, Z12\n",
"5.0 Z3, Z4, Z8, Z9, Z12\n",
"-15.0 Z3, Z5, Z7, Z9, Z12\n",
"-5.0 Z3, Z5, Z6, Z8, Z12\n",
"-5.0 Z3, Z5, Z6, Z7, Z8, Z9, Z12\n",
"7.5 Z2, Z3, Z4, Z7, Z12\n",
"5.0 Z2, Z3, Z7, Z8, Z12\n",
"7.5 Z2, Z4, Z5, Z7, Z12\n",
"5.0 Z2, Z7, Z8, Z9, Z12\n",
"-5.0 Z3, Z4, Z7, Z8, Z12\n",
"-5.0 Z3, Z4, Z5, Z7, Z8, Z9, Z12\n",
"5.0 Z3, Z6, Z7, Z8, Z12\n",
"5.0 Z3, Z6, Z8, Z9, Z12\n",
"5.0 Z2, Z3, Z4, Z9, Z12\n",
"5.0 Z2, Z3, Z6, Z9, Z12\n",
"5.0 Z2, Z4, Z5, Z9, Z12\n",
"5.0 Z2, Z6, Z7, Z9, Z12\n",
"-5.0 Z3, Z4, Z6, Z9, Z12\n",
"-5.0 Z3, Z4, Z5, Z6, Z7, Z9, Z12\n",
"-5.0 Z2, Z4, Z7, Z9, Z12\n",
"-15.0 Z2, Z4, Z6, Z8, Z12\n",
"-5.0 Z2, Z4, Z6, Z7, Z8, Z9, Z12\n",
"-5.0 Z2, Z5, Z6, Z9, Z12\n",
"-5.0 Z2, Z4, Z5, Z6, Z8, Z9, Z12\n",
"-5.0 Z2, Z5, Z7, Z8, Z12\n",
"-5.0 Z2, Z4, Z5, Z6, Z7, Z8, Z12\n",
"-5.0 Z2, Z3, Z4, Z5, Z7, Z9, Z12\n",
"-5.0 Z2, Z3, Z4, Z5, Z6, Z8, Z12\n",
"-15.0 Z2, Z3, Z4, Z5, Z6, Z7, Z8, Z9, Z12\n",
"-5.0 Z2, Z3, Z5, Z6, Z7, Z9, Z12\n",
"-5.0 Z2, Z3, Z4, Z6, Z7, Z8, Z12\n",
"-5.0 Z2, Z3, Z5, Z7, Z8, Z9, Z12\n",
"-5.0 Z2, Z3, Z4, Z6, Z8, Z9, Z12\n",
"5.0 Z4, Z5, Z7, Z8, Z12\n",
"5.0 Z4, Z7, Z8, Z9, Z12\n",
"5.0 Z5, Z6, Z7, Z8, Z12\n",
"5.0 Z5, Z6, Z8, Z9, Z12\n",
"5.0 Z4, Z5, Z6, Z9, Z12\n",
"5.0 Z4, Z6, Z7, Z9, Z12\n",
"-7.5 Z0, Z1, Z3, Z4\n",
"-7.5 Z0, Z1, Z3, Z6\n",
"-7.5 Z0, Z3, Z4, Z5\n",
"-7.5 Z0, Z3, Z6, Z7\n",
"-7.5 Z1, Z2, Z3, Z4\n",
"-7.5 Z1, Z2, Z3, Z6\n",
"-7.5 Z1, Z2, Z4, Z5\n",
"-7.5 Z1, Z2, Z6, Z7\n",
"22.5 Z1, Z3, Z5, Z7\n",
"7.5 Z1, Z3, Z4, Z6\n",
"7.5 Z1, Z3, Z4, Z5, Z6, Z7\n",
"-7.5 Z0, Z1, Z2, Z5\n",
"-7.5 Z0, Z1, Z5, Z6\n",
"-7.5 Z0, Z2, Z3, Z5\n",
"-7.5 Z0, Z5, Z6, Z7\n",
"7.5 Z1, Z2, Z5, Z6\n",
"7.5 Z1, Z2, Z3, Z5, Z6, Z7\n",
"-7.5 Z1, Z4, Z5, Z6\n",
"-7.5 Z1, Z4, Z6, Z7\n",
"-7.5 Z0, Z1, Z2, Z7\n",
"-7.5 Z0, Z1, Z4, Z7\n",
"-7.5 Z0, Z2, Z3, Z7\n",
"-7.5 Z0, Z4, Z5, Z7\n",
"7.5 Z1, Z2, Z4, Z7\n",
"7.5 Z1, Z2, Z3, Z4, Z5, Z7\n",
"7.5 Z0, Z2, Z5, Z7\n",
"22.5 Z0, Z2, Z4, Z6\n",
"7.5 Z0, Z2, Z4, Z5, Z6, Z7\n",
"7.5 Z0, Z3, Z4, Z7\n",
"7.5 Z0, Z2, Z3, Z4, Z6, Z7\n",
"7.5 Z0, Z3, Z5, Z6\n",
"7.5 Z0, Z2, Z3, Z4, Z5, Z6\n",
"7.5 Z0, Z1, Z2, Z3, Z5, Z7\n",
"7.5 Z0, Z1, Z2, Z3, Z4, Z6\n",
"22.5 Z0, Z1, Z2, Z3, Z4, Z5, Z6, Z7\n",
"7.5 Z0, Z1, Z3, Z4, Z5, Z7\n",
"7.5 Z0, Z1, Z2, Z4, Z5, Z6\n",
"7.5 Z0, Z1, Z3, Z5, Z6, Z7\n",
"7.5 Z0, Z1, Z2, Z4, Z6, Z7\n",
"5.0 Z0, Z1, Z3, Z4, Z12\n",
"5.0 Z0, Z1, Z3, Z6, Z12\n",
"5.0 Z0, Z3, Z4, Z5, Z12\n",
"5.0 Z0, Z3, Z6, Z7, Z12\n",
"5.0 Z1, Z2, Z3, Z4, Z12\n",
"5.0 Z1, Z2, Z3, Z6, Z12\n",
"5.0 Z1, Z2, Z4, Z5, Z12\n",
"5.0 Z1, Z2, Z6, Z7, Z12\n",
"-15.0 Z1, Z3, Z5, Z7, Z12\n",
"-5.0 Z1, Z3, Z4, Z6, Z12\n",
"-5.0 Z1, Z3, Z4, Z5, Z6, Z7, Z12\n",
"5.0 Z0, Z1, Z2, Z5, Z12\n",
"5.0 Z0, Z1, Z5, Z6, Z12\n",
"5.0 Z0, Z2, Z3, Z5, Z12\n",
"5.0 Z0, Z5, Z6, Z7, Z12\n",
"-5.0 Z1, Z2, Z5, Z6, Z12\n",
"-5.0 Z1, Z2, Z3, Z5, Z6, Z7, Z12\n",
"5.0 Z1, Z4, Z5, Z6, Z12\n",
"5.0 Z1, Z4, Z6, Z7, Z12\n",
"5.0 Z0, Z1, Z2, Z7, Z12\n",
"5.0 Z0, Z1, Z4, Z7, Z12\n",
"5.0 Z0, Z2, Z3, Z7, Z12\n",
"5.0 Z0, Z4, Z5, Z7, Z12\n",
"-5.0 Z1, Z2, Z4, Z7, Z12\n",
"-5.0 Z1, Z2, Z3, Z4, Z5, Z7, Z12\n",
"-5.0 Z0, Z2, Z5, Z7, Z12\n",
"-15.0 Z0, Z2, Z4, Z6, Z12\n",
"-5.0 Z0, Z2, Z4, Z5, Z6, Z7, Z12\n",
"-5.0 Z0, Z3, Z4, Z7, Z12\n",
"-5.0 Z0, Z2, Z3, Z4, Z6, Z7, Z12\n",
"-5.0 Z0, Z3, Z5, Z6, Z12\n",
"-5.0 Z0, Z2, Z3, Z4, Z5, Z6, Z12\n",
"-5.0 Z0, Z1, Z2, Z3, Z5, Z7, Z12\n",
"-5.0 Z0, Z1, Z2, Z3, Z4, Z6, Z12\n",
"-15.0 Z0, Z1, Z2, Z3, Z4, Z5, Z6, Z7, Z12\n",
"-5.0 Z0, Z1, Z3, Z4, Z5, Z7, Z12\n",
"-5.0 Z0, Z1, Z2, Z4, Z5, Z6, Z12\n",
"-5.0 Z0, Z1, Z3, Z5, Z6, Z7, Z12\n",
"-5.0 Z0, Z1, Z2, Z4, Z6, Z7, Z12\n",
"-40.0 Z1, Z11\n",
"-40.0 Z0, Z10\n",
"-40.0 Z0, Z1, Z10, Z11\n",
"52.5 Z3, Z11\n",
"52.5 Z2, Z10\n",
"52.5 Z2, Z3, Z10, Z11\n",
"-50.0 Z5, Z11\n",
"-50.0 Z4, Z10\n",
"-50.0 Z4, Z5, Z10, Z11\n",
"65.0 Z7, Z11\n",
"65.0 Z6, Z10\n",
"65.0 Z6, Z7, Z10, Z11\n",
"-47.5 Z9, Z11\n",
"-47.5 Z8, Z10\n",
"-47.5 Z8, Z9, Z10, Z11\n",
"-5.0 Z0, Z1, Z3, Z8\n",
"-5.0 Z0, Z1, Z3, Z10\n",
"-5.0 Z0, Z3, Z8, Z9\n",
"-5.0 Z0, Z3, Z10, Z11\n",
"-5.0 Z1, Z2, Z3, Z8\n",
"-5.0 Z1, Z2, Z3, Z10\n",
"-5.0 Z1, Z2, Z8, Z9\n",
"-5.0 Z1, Z2, Z10, Z11\n",
"-15.0 Z1, Z3, Z5, Z9\n",
"15.0 Z1, Z3, Z5, Z11\n",
"-5.0 Z1, Z3, Z4, Z8\n",
"5.0 Z1, Z3, Z4, Z10\n",
"-5.0 Z1, Z3, Z4, Z5, Z8, Z9\n",
"5.0 Z1, Z3, Z4, Z5, Z10, Z11\n",
"15.0 Z1, Z3, Z7, Z9\n",
"-15.0 Z1, Z3, Z7, Z11\n",
"5.0 Z1, Z3, Z6, Z8\n",
"-5.0 Z1, Z3, Z6, Z10\n",
"5.0 Z1, Z3, Z6, Z7, Z8, Z9\n",
"-5.0 Z1, Z3, Z6, Z7, Z10, Z11\n",
"15.0 Z1, Z3, Z9, Z11\n",
"5.0 Z1, Z3, Z8, Z10\n",
"5.0 Z1, Z3, Z8, Z9, Z10, Z11\n",
"15.0 Z0, Z1, Z5, Z8\n",
"-5.0 Z0, Z1, Z5, Z10\n",
"15.0 Z0, Z5, Z8, Z9\n",
"-5.0 Z0, Z5, Z10, Z11\n",
"-5.0 Z1, Z2, Z5, Z8\n",
"5.0 Z1, Z2, Z5, Z10\n",
"-5.0 Z1, Z2, Z3, Z5, Z8, Z9\n",
"5.0 Z1, Z2, Z3, Z5, Z10, Z11\n",
"15.0 Z1, Z4, Z5, Z8\n",
"-5.0 Z1, Z4, Z5, Z10\n",
"15.0 Z1, Z4, Z8, Z9\n",
"-5.0 Z1, Z4, Z10, Z11\n",
"-15.0 Z1, Z5, Z7, Z9\n",
"15.0 Z1, Z5, Z7, Z11\n",
"-5.0 Z1, Z5, Z6, Z8\n",
"5.0 Z1, Z5, Z6, Z10\n",
"-5.0 Z1, Z5, Z6, Z7, Z8, Z9\n",
"5.0 Z1, Z5, Z6, Z7, Z10, Z11\n",
"-15.0 Z1, Z5, Z9, Z11\n",
"-5.0 Z1, Z5, Z8, Z10\n",
"-5.0 Z1, Z5, Z8, Z9, Z10, Z11\n",
"-5.0 Z0, Z1, Z7, Z8\n",
"-5.0 Z0, Z1, Z7, Z10\n",
"-5.0 Z0, Z7, Z8, Z9\n",
"-5.0 Z0, Z7, Z10, Z11\n",
"5.0 Z1, Z2, Z7, Z8\n",
"-5.0 Z1, Z2, Z7, Z10\n",
"5.0 Z1, Z2, Z3, Z7, Z8, Z9\n",
"-5.0 Z1, Z2, Z3, Z7, Z10, Z11\n",
"-5.0 Z1, Z4, Z7, Z8\n",
"5.0 Z1, Z4, Z7, Z10\n",
"-5.0 Z1, Z4, Z5, Z7, Z8, Z9\n",
"5.0 Z1, Z4, Z5, Z7, Z10, Z11\n",
"-5.0 Z1, Z6, Z7, Z8\n",
"-5.0 Z1, Z6, Z7, Z10\n",
"-5.0 Z1, Z6, Z8, Z9\n",
"-5.0 Z1, Z6, Z10, Z11\n",
"15.0 Z1, Z7, Z9, Z11\n",
"5.0 Z1, Z7, Z8, Z10\n",
"5.0 Z1, Z7, Z8, Z9, Z10, Z11\n",
"-5.0 Z0, Z1, Z2, Z9\n",
"15.0 Z0, Z1, Z4, Z9\n",
"-5.0 Z0, Z1, Z6, Z9\n",
"-5.0 Z0, Z1, Z9, Z10\n",
"-5.0 Z0, Z2, Z3, Z9\n",
"15.0 Z0, Z4, Z5, Z9\n",
"-5.0 Z0, Z6, Z7, Z9\n",
"-5.0 Z0, Z9, Z10, Z11\n",
"-5.0 Z1, Z2, Z4, Z9\n",
"5.0 Z1, Z2, Z6, Z9\n",
"5.0 Z1, Z2, Z9, Z10\n",
"-5.0 Z1, Z2, Z3, Z4, Z5, Z9\n",
"5.0 Z1, Z2, Z3, Z6, Z7, Z9\n",
"5.0 Z1, Z2, Z3, Z9, Z10, Z11\n",
"-5.0 Z1, Z4, Z6, Z9\n",
"-5.0 Z1, Z4, Z9, Z10\n",
"-5.0 Z1, Z4, Z5, Z6, Z7, Z9\n",
"-5.0 Z1, Z4, Z5, Z9, Z10, Z11\n",
"5.0 Z1, Z6, Z9, Z10\n",
"5.0 Z1, Z6, Z7, Z9, Z10, Z11\n",
"-5.0 Z1, Z8, Z9, Z10\n",
"-5.0 Z1, Z8, Z10, Z11\n",
"-5.0 Z0, Z1, Z2, Z11\n",
"-5.0 Z0, Z1, Z4, Z11\n",
"-5.0 Z0, Z1, Z6, Z11\n",
"-5.0 Z0, Z1, Z8, Z11\n",
"-5.0 Z0, Z2, Z3, Z11\n",
"-5.0 Z0, Z4, Z5, Z11\n",
"-5.0 Z0, Z6, Z7, Z11\n",
"-5.0 Z0, Z8, Z9, Z11\n",
"5.0 Z1, Z2, Z4, Z11\n",
"-5.0 Z1, Z2, Z6, Z11\n",
"5.0 Z1, Z2, Z8, Z11\n",
"5.0 Z1, Z2, Z3, Z4, Z5, Z11\n",
"-5.0 Z1, Z2, Z3, Z6, Z7, Z11\n",
"5.0 Z1, Z2, Z3, Z8, Z9, Z11\n",
"5.0 Z1, Z4, Z6, Z11\n",
"-5.0 Z1, Z4, Z8, Z11\n",
"5.0 Z1, Z4, Z5, Z6, Z7, Z11\n",
"-5.0 Z1, Z4, Z5, Z8, Z9, Z11\n",
"5.0 Z1, Z6, Z8, Z11\n",
"5.0 Z1, Z6, Z7, Z8, Z9, Z11\n",
"-5.0 Z0, Z2, Z5, Z9\n",
"5.0 Z0, Z2, Z5, Z11\n",
"-15.0 Z0, Z2, Z4, Z8\n",
"15.0 Z0, Z2, Z4, Z10\n",
"-5.0 Z0, Z2, Z4, Z5, Z8, Z9\n",
"5.0 Z0, Z2, Z4, Z5, Z10, Z11\n",
"5.0 Z0, Z2, Z7, Z9\n",
"-5.0 Z0, Z2, Z7, Z11\n",
"15.0 Z0, Z2, Z6, Z8\n",
"-15.0 Z0, Z2, Z6, Z10\n",
"5.0 Z0, Z2, Z6, Z7, Z8, Z9\n",
"-5.0 Z0, Z2, Z6, Z7, Z10, Z11\n",
"5.0 Z0, Z2, Z9, Z11\n",
"15.0 Z0, Z2, Z8, Z10\n",
"5.0 Z0, Z2, Z8, Z9, Z10, Z11\n",
"-5.0 Z0, Z3, Z4, Z9\n",
"5.0 Z0, Z3, Z4, Z11\n",
"-5.0 Z0, Z2, Z3, Z4, Z8, Z9\n",
"5.0 Z0, Z2, Z3, Z4, Z10, Z11\n",
"-5.0 Z0, Z4, Z7, Z9\n",
"5.0 Z0, Z4, Z7, Z11\n",
"-15.0 Z0, Z4, Z6, Z8\n",
"15.0 Z0, Z4, Z6, Z10\n",
"-5.0 Z0, Z4, Z6, Z7, Z8, Z9\n",
"5.0 Z0, Z4, Z6, Z7, Z10, Z11\n",
"-5.0 Z0, Z4, Z9, Z11\n",
"-15.0 Z0, Z4, Z8, Z10\n",
"-5.0 Z0, Z4, Z8, Z9, Z10, Z11\n",
"5.0 Z0, Z3, Z6, Z9\n",
"-5.0 Z0, Z3, Z6, Z11\n",
"5.0 Z0, Z2, Z3, Z6, Z8, Z9\n",
"-5.0 Z0, Z2, Z3, Z6, Z10, Z11\n",
"-5.0 Z0, Z5, Z6, Z9\n",
"5.0 Z0, Z5, Z6, Z11\n",
"-5.0 Z0, Z4, Z5, Z6, Z8, Z9\n",
"5.0 Z0, Z4, Z5, Z6, Z10, Z11\n",
"5.0 Z0, Z6, Z9, Z11\n",
"15.0 Z0, Z6, Z8, Z10\n",
"5.0 Z0, Z6, Z8, Z9, Z10, Z11\n",
"-5.0 Z0, Z3, Z5, Z8\n",
"5.0 Z0, Z3, Z7, Z8\n",
"5.0 Z0, Z3, Z8, Z11\n",
"-5.0 Z0, Z2, Z3, Z4, Z5, Z8\n",
"5.0 Z0, Z2, Z3, Z6, Z7, Z8\n",
"5.0 Z0, Z2, Z3, Z8, Z10, Z11\n",
"-5.0 Z0, Z5, Z7, Z8\n",
"-5.0 Z0, Z5, Z8, Z11\n",
"-5.0 Z0, Z4, Z5, Z6, Z7, Z8\n",
"-5.0 Z0, Z4, Z5, Z8, Z10, Z11\n",
"5.0 Z0, Z7, Z8, Z11\n",
"5.0 Z0, Z6, Z7, Z8, Z10, Z11\n",
"5.0 Z0, Z3, Z5, Z10\n",
"-5.0 Z0, Z3, Z7, Z10\n",
"5.0 Z0, Z3, Z9, Z10\n",
"5.0 Z0, Z2, Z3, Z4, Z5, Z10\n",
"-5.0 Z0, Z2, Z3, Z6, Z7, Z10\n",
"5.0 Z0, Z2, Z3, Z8, Z9, Z10\n",
"5.0 Z0, Z5, Z7, Z10\n",
"-5.0 Z0, Z5, Z9, Z10\n",
"5.0 Z0, Z4, Z5, Z6, Z7, Z10\n",
"-5.0 Z0, Z4, Z5, Z8, Z9, Z10\n",
"5.0 Z0, Z7, Z9, Z10\n",
"5.0 Z0, Z6, Z7, Z8, Z9, Z10\n",
"-5.0 Z0, Z1, Z2, Z3, Z5, Z9\n",
"5.0 Z0, Z1, Z2, Z3, Z5, Z11\n",
"-5.0 Z0, Z1, Z2, Z3, Z4, Z8\n",
"5.0 Z0, Z1, Z2, Z3, Z4, Z10\n",
"-15.0 Z0, Z1, Z2, Z3, Z4, Z5, Z8, Z9\n",
"15.0 Z0, Z1, Z2, Z3, Z4, Z5, Z10, Z11\n",
"5.0 Z0, Z1, Z2, Z3, Z7, Z9\n",
"-5.0 Z0, Z1, Z2, Z3, Z7, Z11\n",
"5.0 Z0, Z1, Z2, Z3, Z6, Z8\n",
"-5.0 Z0, Z1, Z2, Z3, Z6, Z10\n",
"15.0 Z0, Z1, Z2, Z3, Z6, Z7, Z8, Z9\n",
"-15.0 Z0, Z1, Z2, Z3, Z6, Z7, Z10, Z11\n",
"5.0 Z0, Z1, Z2, Z3, Z9, Z11\n",
"5.0 Z0, Z1, Z2, Z3, Z8, Z10\n",
"15.0 Z0, Z1, Z2, Z3, Z8, Z9, Z10, Z11\n",
"-5.0 Z0, Z1, Z3, Z4, Z5, Z9\n",
"5.0 Z0, Z1, Z3, Z4, Z5, Z11\n",
"-5.0 Z0, Z1, Z2, Z4, Z5, Z8\n",
"5.0 Z0, Z1, Z2, Z4, Z5, Z10\n",
"-5.0 Z0, Z1, Z4, Z5, Z7, Z9\n",
"5.0 Z0, Z1, Z4, Z5, Z7, Z11\n",
"-5.0 Z0, Z1, Z4, Z5, Z6, Z8\n",
"5.0 Z0, Z1, Z4, Z5, Z6, Z10\n",
"-15.0 Z0, Z1, Z4, Z5, Z6, Z7, Z8, Z9\n",
"15.0 Z0, Z1, Z4, Z5, Z6, Z7, Z10, Z11\n",
"-5.0 Z0, Z1, Z4, Z5, Z9, Z11\n",
"-5.0 Z0, Z1, Z4, Z5, Z8, Z10\n",
"-15.0 Z0, Z1, Z4, Z5, Z8, Z9, Z10, Z11\n",
"5.0 Z0, Z1, Z3, Z6, Z7, Z9\n",
"-5.0 Z0, Z1, Z3, Z6, Z7, Z11\n",
"5.0 Z0, Z1, Z2, Z6, Z7, Z8\n",
"-5.0 Z0, Z1, Z2, Z6, Z7, Z10\n",
"-5.0 Z0, Z1, Z5, Z6, Z7, Z9\n",
"5.0 Z0, Z1, Z5, Z6, Z7, Z11\n",
"-5.0 Z0, Z1, Z4, Z6, Z7, Z8\n",
"5.0 Z0, Z1, Z4, Z6, Z7, Z10\n",
"5.0 Z0, Z1, Z6, Z7, Z9, Z11\n",
"5.0 Z0, Z1, Z6, Z7, Z8, Z10\n",
"15.0 Z0, Z1, Z6, Z7, Z8, Z9, Z10, Z11\n",
"-5.0 Z0, Z1, Z3, Z5, Z8, Z9\n",
"5.0 Z0, Z1, Z3, Z7, Z8, Z9\n",
"5.0 Z0, Z1, Z3, Z8, Z9, Z11\n",
"-5.0 Z0, Z1, Z2, Z4, Z8, Z9\n",
"5.0 Z0, Z1, Z2, Z6, Z8, Z9\n",
"5.0 Z0, Z1, Z2, Z8, Z9, Z10\n",
"-5.0 Z0, Z1, Z5, Z7, Z8, Z9\n",
"-5.0 Z0, Z1, Z5, Z8, Z9, Z11\n",
"-5.0 Z0, Z1, Z4, Z6, Z8, Z9\n",
"-5.0 Z0, Z1, Z4, Z8, Z9, Z10\n",
"5.0 Z0, Z1, Z7, Z8, Z9, Z11\n",
"5.0 Z0, Z1, Z6, Z8, Z9, Z10\n",
"5.0 Z0, Z1, Z3, Z5, Z10, Z11\n",
"-5.0 Z0, Z1, Z3, Z7, Z10, Z11\n",
"5.0 Z0, Z1, Z3, Z9, Z10, Z11\n",
"5.0 Z0, Z1, Z2, Z4, Z10, Z11\n",
"-5.0 Z0, Z1, Z2, Z6, Z10, Z11\n",
"5.0 Z0, Z1, Z2, Z8, Z10, Z11\n",
"5.0 Z0, Z1, Z5, Z7, Z10, Z11\n",
"-5.0 Z0, Z1, Z5, Z9, Z10, Z11\n",
"5.0 Z0, Z1, Z4, Z6, Z10, Z11\n",
"-5.0 Z0, Z1, Z4, Z8, Z10, Z11\n",
"5.0 Z0, Z1, Z7, Z9, Z10, Z11\n",
"5.0 Z0, Z1, Z6, Z8, Z10, Z11\n",
"-5.0 Z2, Z3, Z5, Z10\n",
"-5.0 Z2, Z5, Z10, Z11\n",
"-5.0 Z3, Z4, Z5, Z10\n",
"-5.0 Z3, Z4, Z10, Z11\n",
"-15.0 Z3, Z5, Z7, Z11\n",
"-5.0 Z3, Z5, Z6, Z10\n",
"-5.0 Z3, Z5, Z6, Z7, Z10, Z11\n",
"15.0 Z3, Z5, Z9, Z11\n",
"5.0 Z3, Z5, Z8, Z10\n",
"5.0 Z3, Z5, Z8, Z9, Z10, Z11\n",
"15.0 Z2, Z3, Z7, Z10\n",
"15.0 Z2, Z7, Z10, Z11\n",
"-5.0 Z3, Z4, Z7, Z10\n",
"-5.0 Z3, Z4, Z5, Z7, Z10, Z11\n",
"15.0 Z3, Z6, Z7, Z10\n",
"15.0 Z3, Z6, Z10, Z11\n",
"-15.0 Z3, Z7, Z9, Z11\n",
"-5.0 Z3, Z7, Z8, Z10\n",
"-5.0 Z3, Z7, Z8, Z9, Z10, Z11\n",
"-5.0 Z2, Z3, Z9, Z10\n",
"-5.0 Z2, Z9, Z10, Z11\n",
"5.0 Z3, Z4, Z9, Z10\n",
"5.0 Z3, Z4, Z5, Z9, Z10, Z11\n",
"-5.0 Z3, Z6, Z9, Z10\n",
"-5.0 Z3, Z6, Z7, Z9, Z10, Z11\n",
"-5.0 Z3, Z8, Z9, Z10\n",
"-5.0 Z3, Z8, Z10, Z11\n",
"-5.0 Z2, Z3, Z4, Z11\n",
"15.0 Z2, Z3, Z6, Z11\n",
"-5.0 Z2, Z3, Z8, Z11\n",
"-5.0 Z2, Z4, Z5, Z11\n",
"15.0 Z2, Z6, Z7, Z11\n",
"-5.0 Z2, Z8, Z9, Z11\n",
"-5.0 Z3, Z4, Z6, Z11\n",
"5.0 Z3, Z4, Z8, Z11\n",
"-5.0 Z3, Z4, Z5, Z6, Z7, Z11\n",
"5.0 Z3, Z4, Z5, Z8, Z9, Z11\n",
"-5.0 Z3, Z6, Z8, Z11\n",
"-5.0 Z3, Z6, Z7, Z8, Z9, Z11\n",
"-5.0 Z2, Z4, Z7, Z11\n",
"-15.0 Z2, Z4, Z6, Z10\n",
"-5.0 Z2, Z4, Z6, Z7, Z10, Z11\n",
"5.0 Z2, Z4, Z9, Z11\n",
"15.0 Z2, Z4, Z8, Z10\n",
"5.0 Z2, Z4, Z8, Z9, Z10, Z11\n",
"-5.0 Z2, Z5, Z6, Z11\n",
"-5.0 Z2, Z4, Z5, Z6, Z10, Z11\n",
"-5.0 Z2, Z6, Z9, Z11\n",
"-15.0 Z2, Z6, Z8, Z10\n",
"-5.0 Z2, Z6, Z8, Z9, Z10, Z11\n",
"5.0 Z2, Z5, Z8, Z11\n",
"5.0 Z2, Z4, Z5, Z8, Z10, Z11\n",
"-5.0 Z2, Z7, Z8, Z11\n",
"-5.0 Z2, Z6, Z7, Z8, Z10, Z11\n",
"-5.0 Z2, Z5, Z7, Z10\n",
"5.0 Z2, Z5, Z9, Z10\n",
"-5.0 Z2, Z4, Z5, Z6, Z7, Z10\n",
"5.0 Z2, Z4, Z5, Z8, Z9, Z10\n",
"-5.0 Z2, Z7, Z9, Z10\n",
"-5.0 Z2, Z6, Z7, Z8, Z9, Z10\n",
"-5.0 Z2, Z3, Z4, Z5, Z7, Z11\n",
"-5.0 Z2, Z3, Z4, Z5, Z6, Z10\n",
"-15.0 Z2, Z3, Z4, Z5, Z6, Z7, Z10, Z11\n",
"5.0 Z2, Z3, Z4, Z5, Z9, Z11\n",
"5.0 Z2, Z3, Z4, Z5, Z8, Z10\n",
"15.0 Z2, Z3, Z4, Z5, Z8, Z9, Z10, Z11\n",
"-5.0 Z2, Z3, Z5, Z6, Z7, Z11\n",
"-5.0 Z2, Z3, Z4, Z6, Z7, Z10\n",
"-5.0 Z2, Z3, Z6, Z7, Z9, Z11\n",
"-5.0 Z2, Z3, Z6, Z7, Z8, Z10\n",
"-15.0 Z2, Z3, Z6, Z7, Z8, Z9, Z10, Z11\n",
"5.0 Z2, Z3, Z5, Z8, Z9, Z11\n",
"5.0 Z2, Z3, Z4, Z8, Z9, Z10\n",
"-5.0 Z2, Z3, Z7, Z8, Z9, Z11\n",
"-5.0 Z2, Z3, Z6, Z8, Z9, Z10\n",
"-5.0 Z2, Z3, Z5, Z7, Z10, Z11\n",
"5.0 Z2, Z3, Z5, Z9, Z10, Z11\n",
"-5.0 Z2, Z3, Z4, Z6, Z10, Z11\n",
"5.0 Z2, Z3, Z4, Z8, Z10, Z11\n",
"-5.0 Z2, Z3, Z7, Z9, Z10, Z11\n",
"-5.0 Z2, Z3, Z6, Z8, Z10, Z11\n",
"-7.5 Z4, Z5, Z7, Z10\n",
"-7.5 Z4, Z7, Z10, Z11\n",
"-7.5 Z5, Z6, Z7, Z10\n",
"-7.5 Z5, Z6, Z10, Z11\n",
"22.5 Z5, Z7, Z9, Z11\n",
"7.5 Z5, Z7, Z8, Z10\n",
"7.5 Z5, Z7, Z8, Z9, Z10, Z11\n",
"-7.5 Z4, Z5, Z9, Z10\n",
"-7.5 Z4, Z9, Z10, Z11\n",
"7.5 Z5, Z6, Z9, Z10\n",
"7.5 Z5, Z6, Z7, Z9, Z10, Z11\n",
"-7.5 Z5, Z8, Z9, Z10\n",
"-7.5 Z5, Z8, Z10, Z11\n",
"-7.5 Z4, Z5, Z6, Z11\n",
"-7.5 Z4, Z5, Z8, Z11\n",
"-7.5 Z4, Z6, Z7, Z11\n",
"-7.5 Z4, Z8, Z9, Z11\n",
"7.5 Z5, Z6, Z8, Z11\n",
"7.5 Z5, Z6, Z7, Z8, Z9, Z11\n",
"7.5 Z4, Z6, Z9, Z11\n",
"22.5 Z4, Z6, Z8, Z10\n",
"7.5 Z4, Z6, Z8, Z9, Z10, Z11\n",
"7.5 Z4, Z7, Z8, Z11\n",
"7.5 Z4, Z6, Z7, Z8, Z10, Z11\n",
"7.5 Z4, Z7, Z9, Z10\n",
"7.5 Z4, Z6, Z7, Z8, Z9, Z10\n",
"7.5 Z4, Z5, Z6, Z7, Z9, Z11\n",
"7.5 Z4, Z5, Z6, Z7, Z8, Z10\n",
"22.5 Z4, Z5, Z6, Z7, Z8, Z9, Z10, Z11\n",
"7.5 Z4, Z5, Z7, Z8, Z9, Z11\n",
"7.5 Z4, Z5, Z6, Z8, Z9, Z10\n",
"7.5 Z4, Z5, Z7, Z9, Z10, Z11\n",
"7.5 Z4, Z5, Z6, Z8, Z10, Z11\n",
"-7.5 Z6, Z7, Z9, Z10\n",
"-7.5 Z6, Z9, Z10, Z11\n",
"-7.5 Z7, Z8, Z9, Z10\n",
"-7.5 Z7, Z8, Z10, Z11\n",
"-7.5 Z6, Z7, Z8, Z11\n",
"-7.5 Z6, Z8, Z9, Z11\n",
"20.0 Z1, Z11, Z12\n",
"20.0 Z0, Z10, Z12\n",
"20.0 Z0, Z1, Z10, Z11, Z12\n",
"-25.0 Z3, Z11, Z12\n",
"-25.0 Z2, Z10, Z12\n",
"-25.0 Z2, Z3, Z10, Z11, Z12\n",
"20.0 Z5, Z11, Z12\n",
"20.0 Z4, Z10, Z12\n",
"20.0 Z4, Z5, Z10, Z11, Z12\n",
"-25.0 Z7, Z11, Z12\n",
"-25.0 Z6, Z10, Z12\n",
"-25.0 Z6, Z7, Z10, Z11, Z12\n",
"20.0 Z9, Z11, Z12\n",
"20.0 Z8, Z10, Z12\n",
"20.0 Z8, Z9, Z10, Z11, Z12\n",
"2.5 Z0, Z1, Z3, Z8, Z12\n",
"2.5 Z0, Z1, Z3, Z10, Z12\n",
"2.5 Z0, Z3, Z8, Z9, Z12\n",
"2.5 Z0, Z3, Z10, Z11, Z12\n",
"2.5 Z1, Z2, Z3, Z8, Z12\n",
"2.5 Z1, Z2, Z3, Z10, Z12\n",
"2.5 Z1, Z2, Z8, Z9, Z12\n",
"2.5 Z1, Z2, Z10, Z11, Z12\n",
"7.5 Z1, Z3, Z5, Z9, Z12\n",
"-7.5 Z1, Z3, Z5, Z11, Z12\n",
"2.5 Z1, Z3, Z4, Z8, Z12\n",
"-2.5 Z1, Z3, Z4, Z10, Z12\n",
"2.5 Z1, Z3, Z4, Z5, Z8, Z9, Z12\n",
"-2.5 Z1, Z3, Z4, Z5, Z10, Z11, Z12\n",
"-7.5 Z1, Z3, Z7, Z9, Z12\n",
"7.5 Z1, Z3, Z7, Z11, Z12\n",
"-2.5 Z1, Z3, Z6, Z8, Z12\n",
"2.5 Z1, Z3, Z6, Z10, Z12\n",
"-2.5 Z1, Z3, Z6, Z7, Z8, Z9, Z12\n",
"2.5 Z1, Z3, Z6, Z7, Z10, Z11, Z12\n",
"-7.5 Z1, Z3, Z9, Z11, Z12\n",
"-2.5 Z1, Z3, Z8, Z10, Z12\n",
"-2.5 Z1, Z3, Z8, Z9, Z10, Z11, Z12\n",
"-7.5 Z0, Z1, Z5, Z8, Z12\n",
"2.5 Z0, Z1, Z5, Z10, Z12\n",
"-7.5 Z0, Z5, Z8, Z9, Z12\n",
"2.5 Z0, Z5, Z10, Z11, Z12\n",
"2.5 Z1, Z2, Z5, Z8, Z12\n",
"-2.5 Z1, Z2, Z5, Z10, Z12\n",
"2.5 Z1, Z2, Z3, Z5, Z8, Z9, Z12\n",
"-2.5 Z1, Z2, Z3, Z5, Z10, Z11, Z12\n",
"-7.5 Z1, Z4, Z5, Z8, Z12\n",
"2.5 Z1, Z4, Z5, Z10, Z12\n",
"-7.5 Z1, Z4, Z8, Z9, Z12\n",
"2.5 Z1, Z4, Z10, Z11, Z12\n",
"7.5 Z1, Z5, Z7, Z9, Z12\n",
"-7.5 Z1, Z5, Z7, Z11, Z12\n",
"2.5 Z1, Z5, Z6, Z8, Z12\n",
"-2.5 Z1, Z5, Z6, Z10, Z12\n",
"2.5 Z1, Z5, Z6, Z7, Z8, Z9, Z12\n",
"-2.5 Z1, Z5, Z6, Z7, Z10, Z11, Z12\n",
"7.5 Z1, Z5, Z9, Z11, Z12\n",
"2.5 Z1, Z5, Z8, Z10, Z12\n",
"2.5 Z1, Z5, Z8, Z9, Z10, Z11, Z12\n",
"2.5 Z0, Z1, Z7, Z8, Z12\n",
"2.5 Z0, Z1, Z7, Z10, Z12\n",
"2.5 Z0, Z7, Z8, Z9, Z12\n",
"2.5 Z0, Z7, Z10, Z11, Z12\n",
"-2.5 Z1, Z2, Z7, Z8, Z12\n",
"2.5 Z1, Z2, Z7, Z10, Z12\n",
"-2.5 Z1, Z2, Z3, Z7, Z8, Z9, Z12\n",
"2.5 Z1, Z2, Z3, Z7, Z10, Z11, Z12\n",
"2.5 Z1, Z4, Z7, Z8, Z12\n",
"-2.5 Z1, Z4, Z7, Z10, Z12\n",
"2.5 Z1, Z4, Z5, Z7, Z8, Z9, Z12\n",
"-2.5 Z1, Z4, Z5, Z7, Z10, Z11, Z12\n",
"2.5 Z1, Z6, Z7, Z8, Z12\n",
"2.5 Z1, Z6, Z7, Z10, Z12\n",
"2.5 Z1, Z6, Z8, Z9, Z12\n",
"2.5 Z1, Z6, Z10, Z11, Z12\n",
"-7.5 Z1, Z7, Z9, Z11, Z12\n",
"-2.5 Z1, Z7, Z8, Z10, Z12\n",
"-2.5 Z1, Z7, Z8, Z9, Z10, Z11, Z12\n",
"2.5 Z0, Z1, Z2, Z9, Z12\n",
"-7.5 Z0, Z1, Z4, Z9, Z12\n",
"2.5 Z0, Z1, Z6, Z9, Z12\n",
"2.5 Z0, Z1, Z9, Z10, Z12\n",
"2.5 Z0, Z2, Z3, Z9, Z12\n",
"-7.5 Z0, Z4, Z5, Z9, Z12\n",
"2.5 Z0, Z6, Z7, Z9, Z12\n",
"2.5 Z0, Z9, Z10, Z11, Z12\n",
"2.5 Z1, Z2, Z4, Z9, Z12\n",
"-2.5 Z1, Z2, Z6, Z9, Z12\n",
"-2.5 Z1, Z2, Z9, Z10, Z12\n",
"2.5 Z1, Z2, Z3, Z4, Z5, Z9, Z12\n",
"-2.5 Z1, Z2, Z3, Z6, Z7, Z9, Z12\n",
"-2.5 Z1, Z2, Z3, Z9, Z10, Z11, Z12\n",
"2.5 Z1, Z4, Z6, Z9, Z12\n",
"2.5 Z1, Z4, Z9, Z10, Z12\n",
"2.5 Z1, Z4, Z5, Z6, Z7, Z9, Z12\n",
"2.5 Z1, Z4, Z5, Z9, Z10, Z11, Z12\n",
"-2.5 Z1, Z6, Z9, Z10, Z12\n",
"-2.5 Z1, Z6, Z7, Z9, Z10, Z11, Z12\n",
"2.5 Z1, Z8, Z9, Z10, Z12\n",
"2.5 Z1, Z8, Z10, Z11, Z12\n",
"2.5 Z0, Z1, Z2, Z11, Z12\n",
"2.5 Z0, Z1, Z4, Z11, Z12\n",
"2.5 Z0, Z1, Z6, Z11, Z12\n",
"2.5 Z0, Z1, Z8, Z11, Z12\n",
"2.5 Z0, Z2, Z3, Z11, Z12\n",
"2.5 Z0, Z4, Z5, Z11, Z12\n",
"2.5 Z0, Z6, Z7, Z11, Z12\n",
"2.5 Z0, Z8, Z9, Z11, Z12\n",
"-2.5 Z1, Z2, Z4, Z11, Z12\n",
"2.5 Z1, Z2, Z6, Z11, Z12\n",
"-2.5 Z1, Z2, Z8, Z11, Z12\n",
"-2.5 Z1, Z2, Z3, Z4, Z5, Z11, Z12\n",
"2.5 Z1, Z2, Z3, Z6, Z7, Z11, Z12\n",
"-2.5 Z1, Z2, Z3, Z8, Z9, Z11, Z12\n",
"-2.5 Z1, Z4, Z6, Z11, Z12\n",
"2.5 Z1, Z4, Z8, Z11, Z12\n",
"-2.5 Z1, Z4, Z5, Z6, Z7, Z11, Z12\n",
"2.5 Z1, Z4, Z5, Z8, Z9, Z11, Z12\n",
"-2.5 Z1, Z6, Z8, Z11, Z12\n",
"-2.5 Z1, Z6, Z7, Z8, Z9, Z11, Z12\n",
"2.5 Z0, Z2, Z5, Z9, Z12\n",
"-2.5 Z0, Z2, Z5, Z11, Z12\n",
"7.5 Z0, Z2, Z4, Z8, Z12\n",
"-7.5 Z0, Z2, Z4, Z10, Z12\n",
"2.5 Z0, Z2, Z4, Z5, Z8, Z9, Z12\n",
"-2.5 Z0, Z2, Z4, Z5, Z10, Z11, Z12\n",
"-2.5 Z0, Z2, Z7, Z9, Z12\n",
"2.5 Z0, Z2, Z7, Z11, Z12\n",
"-7.5 Z0, Z2, Z6, Z8, Z12\n",
"7.5 Z0, Z2, Z6, Z10, Z12\n",
"-2.5 Z0, Z2, Z6, Z7, Z8, Z9, Z12\n",
"2.5 Z0, Z2, Z6, Z7, Z10, Z11, Z12\n",
"-2.5 Z0, Z2, Z9, Z11, Z12\n",
"-7.5 Z0, Z2, Z8, Z10, Z12\n",
"-2.5 Z0, Z2, Z8, Z9, Z10, Z11, Z12\n",
"2.5 Z0, Z3, Z4, Z9, Z12\n",
"-2.5 Z0, Z3, Z4, Z11, Z12\n",
"2.5 Z0, Z2, Z3, Z4, Z8, Z9, Z12\n",
"-2.5 Z0, Z2, Z3, Z4, Z10, Z11, Z12\n",
"2.5 Z0, Z4, Z7, Z9, Z12\n",
"-2.5 Z0, Z4, Z7, Z11, Z12\n",
"7.5 Z0, Z4, Z6, Z8, Z12\n",
"-7.5 Z0, Z4, Z6, Z10, Z12\n",
"2.5 Z0, Z4, Z6, Z7, Z8, Z9, Z12\n",
"-2.5 Z0, Z4, Z6, Z7, Z10, Z11, Z12\n",
"2.5 Z0, Z4, Z9, Z11, Z12\n",
"7.5 Z0, Z4, Z8, Z10, Z12\n",
"2.5 Z0, Z4, Z8, Z9, Z10, Z11, Z12\n",
"-2.5 Z0, Z3, Z6, Z9, Z12\n",
"2.5 Z0, Z3, Z6, Z11, Z12\n",
"-2.5 Z0, Z2, Z3, Z6, Z8, Z9, Z12\n",
"2.5 Z0, Z2, Z3, Z6, Z10, Z11, Z12\n",
"2.5 Z0, Z5, Z6, Z9, Z12\n",
"-2.5 Z0, Z5, Z6, Z11, Z12\n",
"2.5 Z0, Z4, Z5, Z6, Z8, Z9, Z12\n",
"-2.5 Z0, Z4, Z5, Z6, Z10, Z11, Z12\n",
"-2.5 Z0, Z6, Z9, Z11, Z12\n",
"-7.5 Z0, Z6, Z8, Z10, Z12\n",
"-2.5 Z0, Z6, Z8, Z9, Z10, Z11, Z12\n",
"2.5 Z0, Z3, Z5, Z8, Z12\n",
"-2.5 Z0, Z3, Z7, Z8, Z12\n",
"-2.5 Z0, Z3, Z8, Z11, Z12\n",
"2.5 Z0, Z2, Z3, Z4, Z5, Z8, Z12\n",
"-2.5 Z0, Z2, Z3, Z6, Z7, Z8, Z12\n",
"-2.5 Z0, Z2, Z3, Z8, Z10, Z11, Z12\n",
"2.5 Z0, Z5, Z7, Z8, Z12\n",
"2.5 Z0, Z5, Z8, Z11, Z12\n",
"2.5 Z0, Z4, Z5, Z6, Z7, Z8, Z12\n",
"2.5 Z0, Z4, Z5, Z8, Z10, Z11, Z12\n",
"-2.5 Z0, Z7, Z8, Z11, Z12\n",
"-2.5 Z0, Z6, Z7, Z8, Z10, Z11, Z12\n",
"-2.5 Z0, Z3, Z5, Z10, Z12\n",
"2.5 Z0, Z3, Z7, Z10, Z12\n",
"-2.5 Z0, Z3, Z9, Z10, Z12\n",
"-2.5 Z0, Z2, Z3, Z4, Z5, Z10, Z12\n",
"2.5 Z0, Z2, Z3, Z6, Z7, Z10, Z12\n",
"-2.5 Z0, Z2, Z3, Z8, Z9, Z10, Z12\n",
"-2.5 Z0, Z5, Z7, Z10, Z12\n",
"2.5 Z0, Z5, Z9, Z10, Z12\n",
"-2.5 Z0, Z4, Z5, Z6, Z7, Z10, Z12\n",
"2.5 Z0, Z4, Z5, Z8, Z9, Z10, Z12\n",
"-2.5 Z0, Z7, Z9, Z10, Z12\n",
"-2.5 Z0, Z6, Z7, Z8, Z9, Z10, Z12\n",
"2.5 Z0, Z1, Z2, Z3, Z5, Z9, Z12\n",
"-2.5 Z0, Z1, Z2, Z3, Z5, Z11, Z12\n",
"2.5 Z0, Z1, Z2, Z3, Z4, Z8, Z12\n",
"-2.5 Z0, Z1, Z2, Z3, Z4, Z10, Z12\n",
"7.5 Z0, Z1, Z2, Z3, Z4, Z5, Z8, Z9, Z12\n",
"-7.5 Z0, Z1, Z2, Z3, Z4, Z5, Z10, Z11, Z12\n",
"-2.5 Z0, Z1, Z2, Z3, Z7, Z9, Z12\n",
"2.5 Z0, Z1, Z2, Z3, Z7, Z11, Z12\n",
"-2.5 Z0, Z1, Z2, Z3, Z6, Z8, Z12\n",
"2.5 Z0, Z1, Z2, Z3, Z6, Z10, Z12\n",
"-7.5 Z0, Z1, Z2, Z3, Z6, Z7, Z8, Z9, Z12\n",
"7.5 Z0, Z1, Z2, Z3, Z6, Z7, Z10, Z11, Z12\n",
"-2.5 Z0, Z1, Z2, Z3, Z9, Z11, Z12\n",
"-2.5 Z0, Z1, Z2, Z3, Z8, Z10, Z12\n",
"-7.5 Z0, Z1, Z2, Z3, Z8, Z9, Z10, Z11, Z12\n",
"2.5 Z0, Z1, Z3, Z4, Z5, Z9, Z12\n",
"-2.5 Z0, Z1, Z3, Z4, Z5, Z11, Z12\n",
"2.5 Z0, Z1, Z2, Z4, Z5, Z8, Z12\n",
"-2.5 Z0, Z1, Z2, Z4, Z5, Z10, Z12\n",
"2.5 Z0, Z1, Z4, Z5, Z7, Z9, Z12\n",
"-2.5 Z0, Z1, Z4, Z5, Z7, Z11, Z12\n",
"2.5 Z0, Z1, Z4, Z5, Z6, Z8, Z12\n",
"-2.5 Z0, Z1, Z4, Z5, Z6, Z10, Z12\n",
"7.5 Z0, Z1, Z4, Z5, Z6, Z7, Z8, Z9, Z12\n",
"-7.5 Z0, Z1, Z4, Z5, Z6, Z7, Z10, Z11, Z12\n",
"2.5 Z0, Z1, Z4, Z5, Z9, Z11, Z12\n",
"2.5 Z0, Z1, Z4, Z5, Z8, Z10, Z12\n",
"7.5 Z0, Z1, Z4, Z5, Z8, Z9, Z10, Z11, Z12\n",
"-2.5 Z0, Z1, Z3, Z6, Z7, Z9, Z12\n",
"2.5 Z0, Z1, Z3, Z6, Z7, Z11, Z12\n",
"-2.5 Z0, Z1, Z2, Z6, Z7, Z8, Z12\n",
"2.5 Z0, Z1, Z2, Z6, Z7, Z10, Z12\n",
"2.5 Z0, Z1, Z5, Z6, Z7, Z9, Z12\n",
"-2.5 Z0, Z1, Z5, Z6, Z7, Z11, Z12\n",
"2.5 Z0, Z1, Z4, Z6, Z7, Z8, Z12\n",
"-2.5 Z0, Z1, Z4, Z6, Z7, Z10, Z12\n",
"-2.5 Z0, Z1, Z6, Z7, Z9, Z11, Z12\n",
"-2.5 Z0, Z1, Z6, Z7, Z8, Z10, Z12\n",
"-7.5 Z0, Z1, Z6, Z7, Z8, Z9, Z10, Z11, Z12\n",
"2.5 Z0, Z1, Z3, Z5, Z8, Z9, Z12\n",
"-2.5 Z0, Z1, Z3, Z7, Z8, Z9, Z12\n",
"-2.5 Z0, Z1, Z3, Z8, Z9, Z11, Z12\n",
"2.5 Z0, Z1, Z2, Z4, Z8, Z9, Z12\n",
"-2.5 Z0, Z1, Z2, Z6, Z8, Z9, Z12\n",
"-2.5 Z0, Z1, Z2, Z8, Z9, Z10, Z12\n",
"2.5 Z0, Z1, Z5, Z7, Z8, Z9, Z12\n",
"2.5 Z0, Z1, Z5, Z8, Z9, Z11, Z12\n",
"2.5 Z0, Z1, Z4, Z6, Z8, Z9, Z12\n",
"2.5 Z0, Z1, Z4, Z8, Z9, Z10, Z12\n",
"-2.5 Z0, Z1, Z7, Z8, Z9, Z11, Z12\n",
"-2.5 Z0, Z1, Z6, Z8, Z9, Z10, Z12\n",
"-2.5 Z0, Z1, Z3, Z5, Z10, Z11, Z12\n",
"2.5 Z0, Z1, Z3, Z7, Z10, Z11, Z12\n",
"-2.5 Z0, Z1, Z3, Z9, Z10, Z11, Z12\n",
"-2.5 Z0, Z1, Z2, Z4, Z10, Z11, Z12\n",
"2.5 Z0, Z1, Z2, Z6, Z10, Z11, Z12\n",
"-2.5 Z0, Z1, Z2, Z8, Z10, Z11, Z12\n",
"-2.5 Z0, Z1, Z5, Z7, Z10, Z11, Z12\n",
"2.5 Z0, Z1, Z5, Z9, Z10, Z11, Z12\n",
"-2.5 Z0, Z1, Z4, Z6, Z10, Z11, Z12\n",
"2.5 Z0, Z1, Z4, Z8, Z10, Z11, Z12\n",
"-2.5 Z0, Z1, Z7, Z9, Z10, Z11, Z12\n",
"-2.5 Z0, Z1, Z6, Z8, Z10, Z11, Z12\n",
"2.5 Z2, Z3, Z5, Z10, Z12\n",
"2.5 Z2, Z5, Z10, Z11, Z12\n",
"2.5 Z3, Z4, Z5, Z10, Z12\n",
"2.5 Z3, Z4, Z10, Z11, Z12\n",
"7.5 Z3, Z5, Z7, Z11, Z12\n",
"2.5 Z3, Z5, Z6, Z10, Z12\n",
"2.5 Z3, Z5, Z6, Z7, Z10, Z11, Z12\n",
"-7.5 Z3, Z5, Z9, Z11, Z12\n",
"-2.5 Z3, Z5, Z8, Z10, Z12\n",
"-2.5 Z3, Z5, Z8, Z9, Z10, Z11, Z12\n",
"-7.5 Z2, Z3, Z7, Z10, Z12\n",
"-7.5 Z2, Z7, Z10, Z11, Z12\n",
"2.5 Z3, Z4, Z7, Z10, Z12\n",
"2.5 Z3, Z4, Z5, Z7, Z10, Z11, Z12\n",
"-7.5 Z3, Z6, Z7, Z10, Z12\n",
"-7.5 Z3, Z6, Z10, Z11, Z12\n",
"7.5 Z3, Z7, Z9, Z11, Z12\n",
"2.5 Z3, Z7, Z8, Z10, Z12\n",
"2.5 Z3, Z7, Z8, Z9, Z10, Z11, Z12\n",
"2.5 Z2, Z3, Z9, Z10, Z12\n",
"2.5 Z2, Z9, Z10, Z11, Z12\n",
"-2.5 Z3, Z4, Z9, Z10, Z12\n",
"-2.5 Z3, Z4, Z5, Z9, Z10, Z11, Z12\n",
"2.5 Z3, Z6, Z9, Z10, Z12\n",
"2.5 Z3, Z6, Z7, Z9, Z10, Z11, Z12\n",
"2.5 Z3, Z8, Z9, Z10, Z12\n",
"2.5 Z3, Z8, Z10, Z11, Z12\n",
"2.5 Z2, Z3, Z4, Z11, Z12\n",
"-7.5 Z2, Z3, Z6, Z11, Z12\n",
"2.5 Z2, Z3, Z8, Z11, Z12\n",
"2.5 Z2, Z4, Z5, Z11, Z12\n",
"-7.5 Z2, Z6, Z7, Z11, Z12\n",
"2.5 Z2, Z8, Z9, Z11, Z12\n",
"2.5 Z3, Z4, Z6, Z11, Z12\n",
"-2.5 Z3, Z4, Z8, Z11, Z12\n",
"2.5 Z3, Z4, Z5, Z6, Z7, Z11, Z12\n",
"-2.5 Z3, Z4, Z5, Z8, Z9, Z11, Z12\n",
"2.5 Z3, Z6, Z8, Z11, Z12\n",
"2.5 Z3, Z6, Z7, Z8, Z9, Z11, Z12\n",
"2.5 Z2, Z4, Z7, Z11, Z12\n",
"7.5 Z2, Z4, Z6, Z10, Z12\n",
"2.5 Z2, Z4, Z6, Z7, Z10, Z11, Z12\n",
"-2.5 Z2, Z4, Z9, Z11, Z12\n",
"-7.5 Z2, Z4, Z8, Z10, Z12\n",
"-2.5 Z2, Z4, Z8, Z9, Z10, Z11, Z12\n",
"2.5 Z2, Z5, Z6, Z11, Z12\n",
"2.5 Z2, Z4, Z5, Z6, Z10, Z11, Z12\n",
"2.5 Z2, Z6, Z9, Z11, Z12\n",
"7.5 Z2, Z6, Z8, Z10, Z12\n",
"2.5 Z2, Z6, Z8, Z9, Z10, Z11, Z12\n",
"-2.5 Z2, Z5, Z8, Z11, Z12\n",
"-2.5 Z2, Z4, Z5, Z8, Z10, Z11, Z12\n",
"2.5 Z2, Z7, Z8, Z11, Z12\n",
"2.5 Z2, Z6, Z7, Z8, Z10, Z11, Z12\n",
"2.5 Z2, Z5, Z7, Z10, Z12\n",
"-2.5 Z2, Z5, Z9, Z10, Z12\n",
"2.5 Z2, Z4, Z5, Z6, Z7, Z10, Z12\n",
"-2.5 Z2, Z4, Z5, Z8, Z9, Z10, Z12\n",
"2.5 Z2, Z7, Z9, Z10, Z12\n",
"2.5 Z2, Z6, Z7, Z8, Z9, Z10, Z12\n",
"2.5 Z2, Z3, Z4, Z5, Z7, Z11, Z12\n",
"2.5 Z2, Z3, Z4, Z5, Z6, Z10, Z12\n",
"7.5 Z2, Z3, Z4, Z5, Z6, Z7, Z10, Z11, Z12\n",
"-2.5 Z2, Z3, Z4, Z5, Z9, Z11, Z12\n",
"-2.5 Z2, Z3, Z4, Z5, Z8, Z10, Z12\n",
"-7.5 Z2, Z3, Z4, Z5, Z8, Z9, Z10, Z11, Z12\n",
"2.5 Z2, Z3, Z5, Z6, Z7, Z11, Z12\n",
"2.5 Z2, Z3, Z4, Z6, Z7, Z10, Z12\n",
"2.5 Z2, Z3, Z6, Z7, Z9, Z11, Z12\n",
"2.5 Z2, Z3, Z6, Z7, Z8, Z10, Z12\n",
"7.5 Z2, Z3, Z6, Z7, Z8, Z9, Z10, Z11, Z12\n",
"-2.5 Z2, Z3, Z5, Z8, Z9, Z11, Z12\n",
"-2.5 Z2, Z3, Z4, Z8, Z9, Z10, Z12\n",
"2.5 Z2, Z3, Z7, Z8, Z9, Z11, Z12\n",
"2.5 Z2, Z3, Z6, Z8, Z9, Z10, Z12\n",
"2.5 Z2, Z3, Z5, Z7, Z10, Z11, Z12\n",
"-2.5 Z2, Z3, Z5, Z9, Z10, Z11, Z12\n",
"2.5 Z2, Z3, Z4, Z6, Z10, Z11, Z12\n",
"-2.5 Z2, Z3, Z4, Z8, Z10, Z11, Z12\n",
"2.5 Z2, Z3, Z7, Z9, Z10, Z11, Z12\n",
"2.5 Z2, Z3, Z6, Z8, Z10, Z11, Z12\n",
"2.5 Z4, Z5, Z7, Z10, Z12\n",
"2.5 Z4, Z7, Z10, Z11, Z12\n",
"2.5 Z5, Z6, Z7, Z10, Z12\n",
"2.5 Z5, Z6, Z10, Z11, Z12\n",
"-7.5 Z5, Z7, Z9, Z11, Z12\n",
"-2.5 Z5, Z7, Z8, Z10, Z12\n",
"-2.5 Z5, Z7, Z8, Z9, Z10, Z11, Z12\n",
"2.5 Z4, Z5, Z9, Z10, Z12\n",
"2.5 Z4, Z9, Z10, Z11, Z12\n",
"-2.5 Z5, Z6, Z9, Z10, Z12\n",
"-2.5 Z5, Z6, Z7, Z9, Z10, Z11, Z12\n",
"2.5 Z5, Z8, Z9, Z10, Z12\n",
"2.5 Z5, Z8, Z10, Z11, Z12\n",
"2.5 Z4, Z5, Z6, Z11, Z12\n",
"2.5 Z4, Z5, Z8, Z11, Z12\n",
"2.5 Z4, Z6, Z7, Z11, Z12\n",
"2.5 Z4, Z8, Z9, Z11, Z12\n",
"-2.5 Z5, Z6, Z8, Z11, Z12\n",
"-2.5 Z5, Z6, Z7, Z8, Z9, Z11, Z12\n",
"-2.5 Z4, Z6, Z9, Z11, Z12\n",
"-7.5 Z4, Z6, Z8, Z10, Z12\n",
"-2.5 Z4, Z6, Z8, Z9, Z10, Z11, Z12\n",
"-2.5 Z4, Z7, Z8, Z11, Z12\n",
"-2.5 Z4, Z6, Z7, Z8, Z10, Z11, Z12\n",
"-2.5 Z4, Z7, Z9, Z10, Z12\n",
"-2.5 Z4, Z6, Z7, Z8, Z9, Z10, Z12\n",
"-2.5 Z4, Z5, Z6, Z7, Z9, Z11, Z12\n",
"-2.5 Z4, Z5, Z6, Z7, Z8, Z10, Z12\n",
"-7.5 Z4, Z5, Z6, Z7, Z8, Z9, Z10, Z11, Z12\n",
"-2.5 Z4, Z5, Z7, Z8, Z9, Z11, Z12\n",
"-2.5 Z4, Z5, Z6, Z8, Z9, Z10, Z12\n",
"-2.5 Z4, Z5, Z7, Z9, Z10, Z11, Z12\n",
"-2.5 Z4, Z5, Z6, Z8, Z10, Z11, Z12\n",
"2.5 Z6, Z7, Z9, Z10, Z12\n",
"2.5 Z6, Z9, Z10, Z11, Z12\n",
"2.5 Z7, Z8, Z9, Z10, Z12\n",
"2.5 Z7, Z8, Z10, Z11, Z12\n",
"2.5 Z6, Z7, Z8, Z11, Z12\n",
"2.5 Z6, Z8, Z9, Z11, Z12\n",
"-157.34050000000002 Z13\n",
"30.0 Z3, Z5, Z13\n",
"-40.0 Z3, Z7, Z13\n",
"30.0 Z3, Z9, Z13\n",
"-27.5 Z3, Z11, Z13\n",
"30.0 Z2, Z4, Z13\n",
"-40.0 Z2, Z6, Z13\n",
"30.0 Z2, Z8, Z13\n",
"-27.5 Z2, Z10, Z13\n",
"30.0 Z2, Z3, Z4, Z5, Z13\n",
"-40.0 Z2, Z3, Z6, Z7, Z13\n",
"30.0 Z2, Z3, Z8, Z9, Z13\n",
"-27.5 Z2, Z3, Z10, Z11, Z13\n",
"37.5 Z5, Z7, Z13\n",
"-52.5 Z5, Z9, Z13\n",
"30.0 Z5, Z11, Z13\n",
"37.5 Z4, Z6, Z13\n",
"-52.5 Z4, Z8, Z13\n",
"30.0 Z4, Z10, Z13\n",
"37.5 Z4, Z5, Z6, Z7, Z13\n",
"-52.5 Z4, Z5, Z8, Z9, Z13\n",
"30.0 Z4, Z5, Z10, Z11, Z13\n",
"37.5 Z7, Z9, Z13\n",
"-40.0 Z7, Z11, Z13\n",
"37.5 Z6, Z8, Z13\n",
"-40.0 Z6, Z10, Z13\n",
"37.5 Z6, Z7, Z8, Z9, Z13\n",
"-40.0 Z6, Z7, Z10, Z11, Z13\n",
"30.0 Z9, Z11, Z13\n",
"30.0 Z8, Z10, Z13\n",
"30.0 Z8, Z9, Z10, Z11, Z13\n",
"20.0 Z1, Z3, Z13\n",
"-25.0 Z1, Z5, Z13\n",
"20.0 Z1, Z7, Z13\n",
"-25.0 Z1, Z9, Z13\n",
"20.0 Z1, Z11, Z13\n",
"20.0 Z0, Z2, Z13\n",
"-25.0 Z0, Z4, Z13\n",
"20.0 Z0, Z6, Z13\n",
"-25.0 Z0, Z8, Z13\n",
"20.0 Z0, Z10, Z13\n",
"20.0 Z0, Z1, Z2, Z3, Z13\n",
"-25.0 Z0, Z1, Z4, Z5, Z13\n",
"20.0 Z0, Z1, Z6, Z7, Z13\n",
"-25.0 Z0, Z1, Z8, Z9, Z13\n",
"20.0 Z0, Z1, Z10, Z11, Z13\n",
"2.5 Z0, Z1, Z3, Z4, Z13\n",
"2.5 Z0, Z1, Z3, Z6, Z13\n",
"2.5 Z0, Z1, Z3, Z8, Z13\n",
"2.5 Z0, Z1, Z3, Z10, Z13\n",
"2.5 Z0, Z3, Z4, Z5, Z13\n",
"2.5 Z0, Z3, Z6, Z7, Z13\n",
"2.5 Z0, Z3, Z8, Z9, Z13\n",
"2.5 Z0, Z3, Z10, Z11, Z13\n",
"2.5 Z1, Z2, Z3, Z4, Z13\n",
"2.5 Z1, Z2, Z3, Z6, Z13\n",
"2.5 Z1, Z2, Z3, Z8, Z13\n",
"2.5 Z1, Z2, Z3, Z10, Z13\n",
"2.5 Z1, Z2, Z4, Z5, Z13\n",
"2.5 Z1, Z2, Z6, Z7, Z13\n",
"2.5 Z1, Z2, Z8, Z9, Z13\n",
"2.5 Z1, Z2, Z10, Z11, Z13\n",
"-7.5 Z1, Z3, Z5, Z7, Z13\n",
"7.5 Z1, Z3, Z5, Z9, Z13\n",
"-7.5 Z1, Z3, Z5, Z11, Z13\n",
"-2.5 Z1, Z3, Z4, Z6, Z13\n",
"2.5 Z1, Z3, Z4, Z8, Z13\n",
"-2.5 Z1, Z3, Z4, Z10, Z13\n",
"-2.5 Z1, Z3, Z4, Z5, Z6, Z7, Z13\n",
"2.5 Z1, Z3, Z4, Z5, Z8, Z9, Z13\n",
"-2.5 Z1, Z3, Z4, Z5, Z10, Z11, Z13\n",
"-7.5 Z1, Z3, Z7, Z9, Z13\n",
"7.5 Z1, Z3, Z7, Z11, Z13\n",
"-2.5 Z1, Z3, Z6, Z8, Z13\n",
"2.5 Z1, Z3, Z6, Z10, Z13\n",
"-2.5 Z1, Z3, Z6, Z7, Z8, Z9, Z13\n",
"2.5 Z1, Z3, Z6, Z7, Z10, Z11, Z13\n",
"-7.5 Z1, Z3, Z9, Z11, Z13\n",
"-2.5 Z1, Z3, Z8, Z10, Z13\n",
"-2.5 Z1, Z3, Z8, Z9, Z10, Z11, Z13\n",
"2.5 Z0, Z1, Z2, Z5, Z13\n",
"2.5 Z0, Z1, Z5, Z6, Z13\n",
"-7.5 Z0, Z1, Z5, Z8, Z13\n",
"2.5 Z0, Z1, Z5, Z10, Z13\n",
"2.5 Z0, Z2, Z3, Z5, Z13\n",
"2.5 Z0, Z5, Z6, Z7, Z13\n",
"-7.5 Z0, Z5, Z8, Z9, Z13\n",
"2.5 Z0, Z5, Z10, Z11, Z13\n",
"-2.5 Z1, Z2, Z5, Z6, Z13\n",
"2.5 Z1, Z2, Z5, Z8, Z13\n",
"-2.5 Z1, Z2, Z5, Z10, Z13\n",
"-2.5 Z1, Z2, Z3, Z5, Z6, Z7, Z13\n",
"2.5 Z1, Z2, Z3, Z5, Z8, Z9, Z13\n",
"-2.5 Z1, Z2, Z3, Z5, Z10, Z11, Z13\n",
"2.5 Z1, Z4, Z5, Z6, Z13\n",
"-7.5 Z1, Z4, Z5, Z8, Z13\n",
"2.5 Z1, Z4, Z5, Z10, Z13\n",
"2.5 Z1, Z4, Z6, Z7, Z13\n",
"-7.5 Z1, Z4, Z8, Z9, Z13\n",
"2.5 Z1, Z4, Z10, Z11, Z13\n",
"7.5 Z1, Z5, Z7, Z9, Z13\n",
"-7.5 Z1, Z5, Z7, Z11, Z13\n",
"2.5 Z1, Z5, Z6, Z8, Z13\n",
"-2.5 Z1, Z5, Z6, Z10, Z13\n",
"2.5 Z1, Z5, Z6, Z7, Z8, Z9, Z13\n",
"-2.5 Z1, Z5, Z6, Z7, Z10, Z11, Z13\n",
"7.5 Z1, Z5, Z9, Z11, Z13\n",
"2.5 Z1, Z5, Z8, Z10, Z13\n",
"2.5 Z1, Z5, Z8, Z9, Z10, Z11, Z13\n",
"2.5 Z0, Z1, Z2, Z7, Z13\n",
"2.5 Z0, Z1, Z4, Z7, Z13\n",
"2.5 Z0, Z1, Z7, Z8, Z13\n",
"2.5 Z0, Z1, Z7, Z10, Z13\n",
"2.5 Z0, Z2, Z3, Z7, Z13\n",
"2.5 Z0, Z4, Z5, Z7, Z13\n",
"2.5 Z0, Z7, Z8, Z9, Z13\n",
"2.5 Z0, Z7, Z10, Z11, Z13\n",
"-2.5 Z1, Z2, Z4, Z7, Z13\n",
"-2.5 Z1, Z2, Z7, Z8, Z13\n",
"2.5 Z1, Z2, Z7, Z10, Z13\n",
"-2.5 Z1, Z2, Z3, Z4, Z5, Z7, Z13\n",
"-2.5 Z1, Z2, Z3, Z7, Z8, Z9, Z13\n",
"2.5 Z1, Z2, Z3, Z7, Z10, Z11, Z13\n",
"2.5 Z1, Z4, Z7, Z8, Z13\n",
"-2.5 Z1, Z4, Z7, Z10, Z13\n",
"2.5 Z1, Z4, Z5, Z7, Z8, Z9, Z13\n",
"-2.5 Z1, Z4, Z5, Z7, Z10, Z11, Z13\n",
"2.5 Z1, Z6, Z7, Z8, Z13\n",
"2.5 Z1, Z6, Z7, Z10, Z13\n",
"2.5 Z1, Z6, Z8, Z9, Z13\n",
"2.5 Z1, Z6, Z10, Z11, Z13\n",
"-7.5 Z1, Z7, Z9, Z11, Z13\n",
"-2.5 Z1, Z7, Z8, Z10, Z13\n",
"-2.5 Z1, Z7, Z8, Z9, Z10, Z11, Z13\n",
"2.5 Z0, Z1, Z2, Z9, Z13\n",
"-7.5 Z0, Z1, Z4, Z9, Z13\n",
"2.5 Z0, Z1, Z6, Z9, Z13\n",
"2.5 Z0, Z1, Z9, Z10, Z13\n",
"2.5 Z0, Z2, Z3, Z9, Z13\n",
"-7.5 Z0, Z4, Z5, Z9, Z13\n",
"2.5 Z0, Z6, Z7, Z9, Z13\n",
"2.5 Z0, Z9, Z10, Z11, Z13\n",
"2.5 Z1, Z2, Z4, Z9, Z13\n",
"-2.5 Z1, Z2, Z6, Z9, Z13\n",
"-2.5 Z1, Z2, Z9, Z10, Z13\n",
"2.5 Z1, Z2, Z3, Z4, Z5, Z9, Z13\n",
"-2.5 Z1, Z2, Z3, Z6, Z7, Z9, Z13\n",
"-2.5 Z1, Z2, Z3, Z9, Z10, Z11, Z13\n",
"2.5 Z1, Z4, Z6, Z9, Z13\n",
"2.5 Z1, Z4, Z9, Z10, Z13\n",
"2.5 Z1, Z4, Z5, Z6, Z7, Z9, Z13\n",
"2.5 Z1, Z4, Z5, Z9, Z10, Z11, Z13\n",
"-2.5 Z1, Z6, Z9, Z10, Z13\n",
"-2.5 Z1, Z6, Z7, Z9, Z10, Z11, Z13\n",
"2.5 Z1, Z8, Z9, Z10, Z13\n",
"2.5 Z1, Z8, Z10, Z11, Z13\n",
"2.5 Z0, Z1, Z2, Z11, Z13\n",
"2.5 Z0, Z1, Z4, Z11, Z13\n",
"2.5 Z0, Z1, Z6, Z11, Z13\n",
"2.5 Z0, Z1, Z8, Z11, Z13\n",
"2.5 Z0, Z2, Z3, Z11, Z13\n",
"2.5 Z0, Z4, Z5, Z11, Z13\n",
"2.5 Z0, Z6, Z7, Z11, Z13\n",
"2.5 Z0, Z8, Z9, Z11, Z13\n",
"-2.5 Z1, Z2, Z4, Z11, Z13\n",
"2.5 Z1, Z2, Z6, Z11, Z13\n",
"-2.5 Z1, Z2, Z8, Z11, Z13\n",
"-2.5 Z1, Z2, Z3, Z4, Z5, Z11, Z13\n",
"2.5 Z1, Z2, Z3, Z6, Z7, Z11, Z13\n",
"-2.5 Z1, Z2, Z3, Z8, Z9, Z11, Z13\n",
"-2.5 Z1, Z4, Z6, Z11, Z13\n",
"2.5 Z1, Z4, Z8, Z11, Z13\n",
"-2.5 Z1, Z4, Z5, Z6, Z7, Z11, Z13\n",
"2.5 Z1, Z4, Z5, Z8, Z9, Z11, Z13\n",
"-2.5 Z1, Z6, Z8, Z11, Z13\n",
"-2.5 Z1, Z6, Z7, Z8, Z9, Z11, Z13\n",
"-2.5 Z0, Z2, Z5, Z7, Z13\n",
"2.5 Z0, Z2, Z5, Z9, Z13\n",
"-2.5 Z0, Z2, Z5, Z11, Z13\n",
"-7.5 Z0, Z2, Z4, Z6, Z13\n",
"7.5 Z0, Z2, Z4, Z8, Z13\n",
"-7.5 Z0, Z2, Z4, Z10, Z13\n",
"-2.5 Z0, Z2, Z4, Z5, Z6, Z7, Z13\n",
"2.5 Z0, Z2, Z4, Z5, Z8, Z9, Z13\n",
"-2.5 Z0, Z2, Z4, Z5, Z10, Z11, Z13\n",
"-2.5 Z0, Z2, Z7, Z9, Z13\n",
"2.5 Z0, Z2, Z7, Z11, Z13\n",
"-7.5 Z0, Z2, Z6, Z8, Z13\n",
"7.5 Z0, Z2, Z6, Z10, Z13\n",
"-2.5 Z0, Z2, Z6, Z7, Z8, Z9, Z13\n",
"2.5 Z0, Z2, Z6, Z7, Z10, Z11, Z13\n",
"-2.5 Z0, Z2, Z9, Z11, Z13\n",
"-7.5 Z0, Z2, Z8, Z10, Z13\n",
"-2.5 Z0, Z2, Z8, Z9, Z10, Z11, Z13\n",
"-2.5 Z0, Z3, Z4, Z7, Z13\n",
"2.5 Z0, Z3, Z4, Z9, Z13\n",
"-2.5 Z0, Z3, Z4, Z11, Z13\n",
"-2.5 Z0, Z2, Z3, Z4, Z6, Z7, Z13\n",
"2.5 Z0, Z2, Z3, Z4, Z8, Z9, Z13\n",
"-2.5 Z0, Z2, Z3, Z4, Z10, Z11, Z13\n",
"2.5 Z0, Z4, Z7, Z9, Z13\n",
"-2.5 Z0, Z4, Z7, Z11, Z13\n",
"7.5 Z0, Z4, Z6, Z8, Z13\n",
"-7.5 Z0, Z4, Z6, Z10, Z13\n",
"2.5 Z0, Z4, Z6, Z7, Z8, Z9, Z13\n",
"-2.5 Z0, Z4, Z6, Z7, Z10, Z11, Z13\n",
"2.5 Z0, Z4, Z9, Z11, Z13\n",
"7.5 Z0, Z4, Z8, Z10, Z13\n",
"2.5 Z0, Z4, Z8, Z9, Z10, Z11, Z13\n",
"-2.5 Z0, Z3, Z5, Z6, Z13\n",
"-2.5 Z0, Z3, Z6, Z9, Z13\n",
"2.5 Z0, Z3, Z6, Z11, Z13\n",
"-2.5 Z0, Z2, Z3, Z4, Z5, Z6, Z13\n",
"-2.5 Z0, Z2, Z3, Z6, Z8, Z9, Z13\n",
"2.5 Z0, Z2, Z3, Z6, Z10, Z11, Z13\n",
"2.5 Z0, Z5, Z6, Z9, Z13\n",
"-2.5 Z0, Z5, Z6, Z11, Z13\n",
"2.5 Z0, Z4, Z5, Z6, Z8, Z9, Z13\n",
"-2.5 Z0, Z4, Z5, Z6, Z10, Z11, Z13\n",
"-2.5 Z0, Z6, Z9, Z11, Z13\n",
"-7.5 Z0, Z6, Z8, Z10, Z13\n",
"-2.5 Z0, Z6, Z8, Z9, Z10, Z11, Z13\n",
"2.5 Z0, Z3, Z5, Z8, Z13\n",
"-2.5 Z0, Z3, Z7, Z8, Z13\n",
"-2.5 Z0, Z3, Z8, Z11, Z13\n",
"2.5 Z0, Z2, Z3, Z4, Z5, Z8, Z13\n",
"-2.5 Z0, Z2, Z3, Z6, Z7, Z8, Z13\n",
"-2.5 Z0, Z2, Z3, Z8, Z10, Z11, Z13\n",
"2.5 Z0, Z5, Z7, Z8, Z13\n",
"2.5 Z0, Z5, Z8, Z11, Z13\n",
"2.5 Z0, Z4, Z5, Z6, Z7, Z8, Z13\n",
"2.5 Z0, Z4, Z5, Z8, Z10, Z11, Z13\n",
"-2.5 Z0, Z7, Z8, Z11, Z13\n",
"-2.5 Z0, Z6, Z7, Z8, Z10, Z11, Z13\n",
"-2.5 Z0, Z3, Z5, Z10, Z13\n",
"2.5 Z0, Z3, Z7, Z10, Z13\n",
"-2.5 Z0, Z3, Z9, Z10, Z13\n",
"-2.5 Z0, Z2, Z3, Z4, Z5, Z10, Z13\n",
"2.5 Z0, Z2, Z3, Z6, Z7, Z10, Z13\n",
"-2.5 Z0, Z2, Z3, Z8, Z9, Z10, Z13\n",
"-2.5 Z0, Z5, Z7, Z10, Z13\n",
"2.5 Z0, Z5, Z9, Z10, Z13\n",
"-2.5 Z0, Z4, Z5, Z6, Z7, Z10, Z13\n",
"2.5 Z0, Z4, Z5, Z8, Z9, Z10, Z13\n",
"-2.5 Z0, Z7, Z9, Z10, Z13\n",
"-2.5 Z0, Z6, Z7, Z8, Z9, Z10, Z13\n",
"-2.5 Z0, Z1, Z2, Z3, Z5, Z7, Z13\n",
"2.5 Z0, Z1, Z2, Z3, Z5, Z9, Z13\n",
"-2.5 Z0, Z1, Z2, Z3, Z5, Z11, Z13\n",
"-2.5 Z0, Z1, Z2, Z3, Z4, Z6, Z13\n",
"2.5 Z0, Z1, Z2, Z3, Z4, Z8, Z13\n",
"-2.5 Z0, Z1, Z2, Z3, Z4, Z10, Z13\n",
"-7.5 Z0, Z1, Z2, Z3, Z4, Z5, Z6, Z7, Z13\n",
"7.5 Z0, Z1, Z2, Z3, Z4, Z5, Z8, Z9, Z13\n",
"-7.5 Z0, Z1, Z2, Z3, Z4, Z5, Z10, Z11, Z13\n",
"-2.5 Z0, Z1, Z2, Z3, Z7, Z9, Z13\n",
"2.5 Z0, Z1, Z2, Z3, Z7, Z11, Z13\n",
"-2.5 Z0, Z1, Z2, Z3, Z6, Z8, Z13\n",
"2.5 Z0, Z1, Z2, Z3, Z6, Z10, Z13\n",
"-7.5 Z0, Z1, Z2, Z3, Z6, Z7, Z8, Z9, Z13\n",
"7.5 Z0, Z1, Z2, Z3, Z6, Z7, Z10, Z11, Z13\n",
"-2.5 Z0, Z1, Z2, Z3, Z9, Z11, Z13\n",
"-2.5 Z0, Z1, Z2, Z3, Z8, Z10, Z13\n",
"-7.5 Z0, Z1, Z2, Z3, Z8, Z9, Z10, Z11, Z13\n",
"-2.5 Z0, Z1, Z3, Z4, Z5, Z7, Z13\n",
"2.5 Z0, Z1, Z3, Z4, Z5, Z9, Z13\n",
"-2.5 Z0, Z1, Z3, Z4, Z5, Z11, Z13\n",
"-2.5 Z0, Z1, Z2, Z4, Z5, Z6, Z13\n",
"2.5 Z0, Z1, Z2, Z4, Z5, Z8, Z13\n",
"-2.5 Z0, Z1, Z2, Z4, Z5, Z10, Z13\n",
"2.5 Z0, Z1, Z4, Z5, Z7, Z9, Z13\n",
"-2.5 Z0, Z1, Z4, Z5, Z7, Z11, Z13\n",
"2.5 Z0, Z1, Z4, Z5, Z6, Z8, Z13\n",
"-2.5 Z0, Z1, Z4, Z5, Z6, Z10, Z13\n",
"7.5 Z0, Z1, Z4, Z5, Z6, Z7, Z8, Z9, Z13\n",
"-7.5 Z0, Z1, Z4, Z5, Z6, Z7, Z10, Z11, Z13\n",
"2.5 Z0, Z1, Z4, Z5, Z9, Z11, Z13\n",
"2.5 Z0, Z1, Z4, Z5, Z8, Z10, Z13\n",
"7.5 Z0, Z1, Z4, Z5, Z8, Z9, Z10, Z11, Z13\n",
"-2.5 Z0, Z1, Z3, Z5, Z6, Z7, Z13\n",
"-2.5 Z0, Z1, Z3, Z6, Z7, Z9, Z13\n",
"2.5 Z0, Z1, Z3, Z6, Z7, Z11, Z13\n",
"-2.5 Z0, Z1, Z2, Z4, Z6, Z7, Z13\n",
"-2.5 Z0, Z1, Z2, Z6, Z7, Z8, Z13\n",
"2.5 Z0, Z1, Z2, Z6, Z7, Z10, Z13\n",
"2.5 Z0, Z1, Z5, Z6, Z7, Z9, Z13\n",
"-2.5 Z0, Z1, Z5, Z6, Z7, Z11, Z13\n",
"2.5 Z0, Z1, Z4, Z6, Z7, Z8, Z13\n",
"-2.5 Z0, Z1, Z4, Z6, Z7, Z10, Z13\n",
"-2.5 Z0, Z1, Z6, Z7, Z9, Z11, Z13\n",
"-2.5 Z0, Z1, Z6, Z7, Z8, Z10, Z13\n",
"-7.5 Z0, Z1, Z6, Z7, Z8, Z9, Z10, Z11, Z13\n",
"2.5 Z0, Z1, Z3, Z5, Z8, Z9, Z13\n",
"-2.5 Z0, Z1, Z3, Z7, Z8, Z9, Z13\n",
"-2.5 Z0, Z1, Z3, Z8, Z9, Z11, Z13\n",
"2.5 Z0, Z1, Z2, Z4, Z8, Z9, Z13\n",
"-2.5 Z0, Z1, Z2, Z6, Z8, Z9, Z13\n",
"-2.5 Z0, Z1, Z2, Z8, Z9, Z10, Z13\n",
"2.5 Z0, Z1, Z5, Z7, Z8, Z9, Z13\n",
"2.5 Z0, Z1, Z5, Z8, Z9, Z11, Z13\n",
"2.5 Z0, Z1, Z4, Z6, Z8, Z9, Z13\n",
"2.5 Z0, Z1, Z4, Z8, Z9, Z10, Z13\n",
"-2.5 Z0, Z1, Z7, Z8, Z9, Z11, Z13\n",
"-2.5 Z0, Z1, Z6, Z8, Z9, Z10, Z13\n",
"-2.5 Z0, Z1, Z3, Z5, Z10, Z11, Z13\n",
"2.5 Z0, Z1, Z3, Z7, Z10, Z11, Z13\n",
"-2.5 Z0, Z1, Z3, Z9, Z10, Z11, Z13\n",
"-2.5 Z0, Z1, Z2, Z4, Z10, Z11, Z13\n",
"2.5 Z0, Z1, Z2, Z6, Z10, Z11, Z13\n",
"-2.5 Z0, Z1, Z2, Z8, Z10, Z11, Z13\n",
"-2.5 Z0, Z1, Z5, Z7, Z10, Z11, Z13\n",
"2.5 Z0, Z1, Z5, Z9, Z10, Z11, Z13\n",
"-2.5 Z0, Z1, Z4, Z6, Z10, Z11, Z13\n",
"2.5 Z0, Z1, Z4, Z8, Z10, Z11, Z13\n",
"-2.5 Z0, Z1, Z7, Z9, Z10, Z11, Z13\n",
"-2.5 Z0, Z1, Z6, Z8, Z10, Z11, Z13\n",
"5.0 Z2, Z3, Z5, Z6, Z13\n",
"5.0 Z2, Z3, Z5, Z8, Z13\n",
"2.5 Z2, Z3, Z5, Z10, Z13\n",
"5.0 Z2, Z5, Z6, Z7, Z13\n",
"5.0 Z2, Z5, Z8, Z9, Z13\n",
"2.5 Z2, Z5, Z10, Z11, Z13\n",
"5.0 Z3, Z4, Z5, Z6, Z13\n",
"5.0 Z3, Z4, Z5, Z8, Z13\n",
"2.5 Z3, Z4, Z5, Z10, Z13\n",
"5.0 Z3, Z4, Z6, Z7, Z13\n",
"5.0 Z3, Z4, Z8, Z9, Z13\n",
"2.5 Z3, Z4, Z10, Z11, Z13\n",
"-15.0 Z3, Z5, Z7, Z9, Z13\n",
"7.5 Z3, Z5, Z7, Z11, Z13\n",
"-5.0 Z3, Z5, Z6, Z8, Z13\n",
"2.5 Z3, Z5, Z6, Z10, Z13\n",
"-5.0 Z3, Z5, Z6, Z7, Z8, Z9, Z13\n",
"2.5 Z3, Z5, Z6, Z7, Z10, Z11, Z13\n",
"-7.5 Z3, Z5, Z9, Z11, Z13\n",
"-2.5 Z3, Z5, Z8, Z10, Z13\n",
"-2.5 Z3, Z5, Z8, Z9, Z10, Z11, Z13\n",
"5.0 Z2, Z3, Z4, Z7, Z13\n",
"5.0 Z2, Z3, Z7, Z8, Z13\n",
"-7.5 Z2, Z3, Z7, Z10, Z13\n",
"5.0 Z2, Z4, Z5, Z7, Z13\n",
"5.0 Z2, Z7, Z8, Z9, Z13\n",
"-7.5 Z2, Z7, Z10, Z11, Z13\n",
"-5.0 Z3, Z4, Z7, Z8, Z13\n",
"2.5 Z3, Z4, Z7, Z10, Z13\n",
"-5.0 Z3, Z4, Z5, Z7, Z8, Z9, Z13\n",
"2.5 Z3, Z4, Z5, Z7, Z10, Z11, Z13\n",
"5.0 Z3, Z6, Z7, Z8, Z13\n",
"-7.5 Z3, Z6, Z7, Z10, Z13\n",
"5.0 Z3, Z6, Z8, Z9, Z13\n",
"-7.5 Z3, Z6, Z10, Z11, Z13\n",
"7.5 Z3, Z7, Z9, Z11, Z13\n",
"2.5 Z3, Z7, Z8, Z10, Z13\n",
"2.5 Z3, Z7, Z8, Z9, Z10, Z11, Z13\n",
"5.0 Z2, Z3, Z4, Z9, Z13\n",
"5.0 Z2, Z3, Z6, Z9, Z13\n",
"2.5 Z2, Z3, Z9, Z10, Z13\n",
"5.0 Z2, Z4, Z5, Z9, Z13\n",
"5.0 Z2, Z6, Z7, Z9, Z13\n",
"2.5 Z2, Z9, Z10, Z11, Z13\n",
"-5.0 Z3, Z4, Z6, Z9, Z13\n",
"-2.5 Z3, Z4, Z9, Z10, Z13\n",
"-5.0 Z3, Z4, Z5, Z6, Z7, Z9, Z13\n",
"-2.5 Z3, Z4, Z5, Z9, Z10, Z11, Z13\n",
"2.5 Z3, Z6, Z9, Z10, Z13\n",
"2.5 Z3, Z6, Z7, Z9, Z10, Z11, Z13\n",
"2.5 Z3, Z8, Z9, Z10, Z13\n",
"2.5 Z3, Z8, Z10, Z11, Z13\n",
"2.5 Z2, Z3, Z4, Z11, Z13\n",
"-7.5 Z2, Z3, Z6, Z11, Z13\n",
"2.5 Z2, Z3, Z8, Z11, Z13\n",
"2.5 Z2, Z4, Z5, Z11, Z13\n",
"-7.5 Z2, Z6, Z7, Z11, Z13\n",
"2.5 Z2, Z8, Z9, Z11, Z13\n",
"2.5 Z3, Z4, Z6, Z11, Z13\n",
"-2.5 Z3, Z4, Z8, Z11, Z13\n",
"2.5 Z3, Z4, Z5, Z6, Z7, Z11, Z13\n",
"-2.5 Z3, Z4, Z5, Z8, Z9, Z11, Z13\n",
"2.5 Z3, Z6, Z8, Z11, Z13\n",
"2.5 Z3, Z6, Z7, Z8, Z9, Z11, Z13\n",
"-5.0 Z2, Z4, Z7, Z9, Z13\n",
"2.5 Z2, Z4, Z7, Z11, Z13\n",
"-15.0 Z2, Z4, Z6, Z8, Z13\n",
"7.5 Z2, Z4, Z6, Z10, Z13\n",
"-5.0 Z2, Z4, Z6, Z7, Z8, Z9, Z13\n",
"2.5 Z2, Z4, Z6, Z7, Z10, Z11, Z13\n",
"-2.5 Z2, Z4, Z9, Z11, Z13\n",
"-7.5 Z2, Z4, Z8, Z10, Z13\n",
"-2.5 Z2, Z4, Z8, Z9, Z10, Z11, Z13\n",
"-5.0 Z2, Z5, Z6, Z9, Z13\n",
"2.5 Z2, Z5, Z6, Z11, Z13\n",
"-5.0 Z2, Z4, Z5, Z6, Z8, Z9, Z13\n",
"2.5 Z2, Z4, Z5, Z6, Z10, Z11, Z13\n",
"2.5 Z2, Z6, Z9, Z11, Z13\n",
"7.5 Z2, Z6, Z8, Z10, Z13\n",
"2.5 Z2, Z6, Z8, Z9, Z10, Z11, Z13\n",
"-5.0 Z2, Z5, Z7, Z8, Z13\n",
"-2.5 Z2, Z5, Z8, Z11, Z13\n",
"-5.0 Z2, Z4, Z5, Z6, Z7, Z8, Z13\n",
"-2.5 Z2, Z4, Z5, Z8, Z10, Z11, Z13\n",
"2.5 Z2, Z7, Z8, Z11, Z13\n",
"2.5 Z2, Z6, Z7, Z8, Z10, Z11, Z13\n",
"2.5 Z2, Z5, Z7, Z10, Z13\n",
"-2.5 Z2, Z5, Z9, Z10, Z13\n",
"2.5 Z2, Z4, Z5, Z6, Z7, Z10, Z13\n",
"-2.5 Z2, Z4, Z5, Z8, Z9, Z10, Z13\n",
"2.5 Z2, Z7, Z9, Z10, Z13\n",
"2.5 Z2, Z6, Z7, Z8, Z9, Z10, Z13\n",
"-5.0 Z2, Z3, Z4, Z5, Z7, Z9, Z13\n",
"2.5 Z2, Z3, Z4, Z5, Z7, Z11, Z13\n",
"-5.0 Z2, Z3, Z4, Z5, Z6, Z8, Z13\n",
"2.5 Z2, Z3, Z4, Z5, Z6, Z10, Z13\n",
"-15.0 Z2, Z3, Z4, Z5, Z6, Z7, Z8, Z9, Z13\n",
"7.5 Z2, Z3, Z4, Z5, Z6, Z7, Z10, Z11, Z13\n",
"-2.5 Z2, Z3, Z4, Z5, Z9, Z11, Z13\n",
"-2.5 Z2, Z3, Z4, Z5, Z8, Z10, Z13\n",
"-7.5 Z2, Z3, Z4, Z5, Z8, Z9, Z10, Z11, Z13\n",
"-5.0 Z2, Z3, Z5, Z6, Z7, Z9, Z13\n",
"2.5 Z2, Z3, Z5, Z6, Z7, Z11, Z13\n",
"-5.0 Z2, Z3, Z4, Z6, Z7, Z8, Z13\n",
"2.5 Z2, Z3, Z4, Z6, Z7, Z10, Z13\n",
"2.5 Z2, Z3, Z6, Z7, Z9, Z11, Z13\n",
"2.5 Z2, Z3, Z6, Z7, Z8, Z10, Z13\n",
"7.5 Z2, Z3, Z6, Z7, Z8, Z9, Z10, Z11, Z13\n",
"-5.0 Z2, Z3, Z5, Z7, Z8, Z9, Z13\n",
"-2.5 Z2, Z3, Z5, Z8, Z9, Z11, Z13\n",
"-5.0 Z2, Z3, Z4, Z6, Z8, Z9, Z13\n",
"-2.5 Z2, Z3, Z4, Z8, Z9, Z10, Z13\n",
"2.5 Z2, Z3, Z7, Z8, Z9, Z11, Z13\n",
"2.5 Z2, Z3, Z6, Z8, Z9, Z10, Z13\n",
"2.5 Z2, Z3, Z5, Z7, Z10, Z11, Z13\n",
"-2.5 Z2, Z3, Z5, Z9, Z10, Z11, Z13\n",
"2.5 Z2, Z3, Z4, Z6, Z10, Z11, Z13\n",
"-2.5 Z2, Z3, Z4, Z8, Z10, Z11, Z13\n",
"2.5 Z2, Z3, Z7, Z9, Z10, Z11, Z13\n",
"2.5 Z2, Z3, Z6, Z8, Z10, Z11, Z13\n",
"7.5 Z4, Z5, Z7, Z8, Z13\n",
"5.0 Z4, Z5, Z7, Z10, Z13\n",
"7.5 Z4, Z7, Z8, Z9, Z13\n",
"5.0 Z4, Z7, Z10, Z11, Z13\n",
"7.5 Z5, Z6, Z7, Z8, Z13\n",
"5.0 Z5, Z6, Z7, Z10, Z13\n",
"7.5 Z5, Z6, Z8, Z9, Z13\n",
"5.0 Z5, Z6, Z10, Z11, Z13\n",
"-15.0 Z5, Z7, Z9, Z11, Z13\n",
"-5.0 Z5, Z7, Z8, Z10, Z13\n",
"-5.0 Z5, Z7, Z8, Z9, Z10, Z11, Z13\n",
"7.5 Z4, Z5, Z6, Z9, Z13\n",
"5.0 Z4, Z5, Z9, Z10, Z13\n",
"7.5 Z4, Z6, Z7, Z9, Z13\n",
"5.0 Z4, Z9, Z10, Z11, Z13\n",
"-5.0 Z5, Z6, Z9, Z10, Z13\n",
"-5.0 Z5, Z6, Z7, Z9, Z10, Z11, Z13\n",
"5.0 Z5, Z8, Z9, Z10, Z13\n",
"5.0 Z5, Z8, Z10, Z11, Z13\n",
"5.0 Z4, Z5, Z6, Z11, Z13\n",
"5.0 Z4, Z5, Z8, Z11, Z13\n",
"5.0 Z4, Z6, Z7, Z11, Z13\n",
"5.0 Z4, Z8, Z9, Z11, Z13\n",
"-5.0 Z5, Z6, Z8, Z11, Z13\n",
"-5.0 Z5, Z6, Z7, Z8, Z9, Z11, Z13\n",
"-5.0 Z4, Z6, Z9, Z11, Z13\n",
"-15.0 Z4, Z6, Z8, Z10, Z13\n",
"-5.0 Z4, Z6, Z8, Z9, Z10, Z11, Z13\n",
"-5.0 Z4, Z7, Z8, Z11, Z13\n",
"-5.0 Z4, Z6, Z7, Z8, Z10, Z11, Z13\n",
"-5.0 Z4, Z7, Z9, Z10, Z13\n",
"-5.0 Z4, Z6, Z7, Z8, Z9, Z10, Z13\n",
"-5.0 Z4, Z5, Z6, Z7, Z9, Z11, Z13\n",
"-5.0 Z4, Z5, Z6, Z7, Z8, Z10, Z13\n",
"-15.0 Z4, Z5, Z6, Z7, Z8, Z9, Z10, Z11, Z13\n",
"-5.0 Z4, Z5, Z7, Z8, Z9, Z11, Z13\n",
"-5.0 Z4, Z5, Z6, Z8, Z9, Z10, Z13\n",
"-5.0 Z4, Z5, Z7, Z9, Z10, Z11, Z13\n",
"-5.0 Z4, Z5, Z6, Z8, Z10, Z11, Z13\n",
"5.0 Z6, Z7, Z9, Z10, Z13\n",
"5.0 Z6, Z9, Z10, Z11, Z13\n",
"5.0 Z7, Z8, Z9, Z10, Z13\n",
"5.0 Z7, Z8, Z10, Z11, Z13\n",
"5.0 Z6, Z7, Z8, Z11, Z13\n",
"5.0 Z6, Z8, Z9, Z11, Z13\n"
]
}
],
"source": [
"# 其中 lambda0 和 lambda1 是蛋白质哈密顿量中的两个参数,用于约束蛋白质的空间结构。\n",
"h = protein.get_protein_hamiltonian(lambda0=10.0, lambda1=10.0)\n",
"print(h)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### 变分量子线路\n",
"用户可以使用变分量子算法(VQE)来解决蛋白质折叠问题。这个问题中的变分量子线路如下。"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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",
"text/plain": [
"<Figure size 494x220 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from folding_protein import circuit\n",
"\n",
"# 下面的代码搭建了一个宽度为4,包含两个线路单元的参数化量子线路(注:一个线路单元包含一层RY和一层CNOT)。\n",
"cir = circuit(4, 2)\n",
"cir.plot()"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 如何使用\n",
"用户可以通过编辑配置文件config.toml对任务进行自定义,其中用户可以设置的参数如下\n",
"```toml\n",
"# The configuration file for protein folding problem\n",
"\n",
"# The amino acides consists in protein. \n",
"amino_acids = [\"A\", \"P\", \"R\", \"L\", \"R\", \"F\", \"Y\"]\n",
"# Pair of indices indicates the potentially interact amino acide pair.\n",
"possible_contactions = [[0, 5], [1, 6]]\n",
"# Depth of the quantum circuit used in VQE\n",
"depth = 1\n",
"# Number of VQE iterations\n",
"num_iterations = 200\n",
"# The condition for VQE convergence\n",
"tol = 1e-3\n",
"# The number of steps between two consecutive loss records\n",
"save_every = 10\n",
"# learning rate for the optimizer\n",
"learning_rate = 0.5\n",
"```\n",
"用户可以在命令行中运行\n",
"```shell\n",
"python folding_protein.py --config config.toml\n",
"```\n",
"来得到上面氨基酸序列在空间中折叠的三维结构,程序会自动保存这个空间结构的图片。\n",
"\n",
"![](APRLRFY_3d_structure.jpg)\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 参考文献\n",
"\\[1\\] Pande, Vijay S., and Daniel S. Rokhsar. \"Folding pathway of a lattice model for proteins.\" Proceedings of the National Academy of Sciences 96.4 (1999): 1273-1278.\n",
"\n",
"\\[2\\] Robert, Anton, et al. \"Resource-efficient quantum algorithm for protein folding.\" npj Quantum Information 7.1 (2021): 1-5."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "modellib",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.15 (default, Nov 10 2022, 12:46:26) \n[Clang 14.0.6 ]"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "8f24120f890011f53feb4ed62c47961d8565ec1de8b7cb23548c15bd6da8f2d2"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import warnings\n",
"\n",
"warnings.filterwarnings(\"ignore\")"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"# Introduction to protein functionality and structure design\n",
"*Copyright (c) 2022 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.*\n",
"\n",
"Proteins are important structural and functional molecules in biological organisms. They form long chains by assembling amino acids and realize specific functionality through the spatial structure of amino acid chains. The spatial structure of proteins refers to the conformation of amino acid chains in three-dimensional space. This conformation can be determined by X-ray diffraction, nuclear magnetic resonance, or other methods. Studies have shown that the spatial structure of proteins is closely related to their functionalities. For example, as an important class of proteins, enzymes determine their interaction with substrates through their spatial structure, thus realizing the catalytic effect of chemical reactions. In addition, the spatial structure of proteins can be controlled by changing the amino acid sequence to regulate their functionality.\n",
"\n",
"Proteins produce different spatial structures in different folding modes, it is important to study protein folding in order to predict protein behaviors. Due to the high complexity and non-linearity appearing in the protein structures, it's inefficient to solve protein folding problems via classical computation. Quantum computation can quickly solve complex non-linear optimization problems based on the principles of quantum mechanics, and is generally believed to be of great help in future research on protein folding."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Using quantum computation method to simulate the protein folding\n",
"### Lattice model\n",
"In protein structure research, a common method is the lattice model \\[1\\], which divides the amino acid chain in the protein into a series of lattice units, each of which includes several amino acids. By analyzing the interaction between lattice units, we can infer the spatial structure of the protein. The lattice model can help us better understand the structure and function of proteins, and provide an important theoretical basis for drug design and disease treatment.\n",
"![](lattice_model_en.jpg)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Protein with 7 nodes and 6 edges\n"
]
}
],
"source": [
"from paddle_quantum.biocomputing import Protein\n",
"\n",
"protein = Protein(\"APRLRFY\")\n",
"print(protein)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"With the `biocomputing` module in `paddle_quantum`, we can easily construct a protein., the above code has built an amino acid chain contains 7 amino acids.\n",
"\n",
"Starting from the lattice model, we can obtain a protein Hamiltonian \\[2\\] based on the interactions between lattice points. We can then construct a variational quantum algorithm (VQE) based on this Hamiltonian to solve for the stable structure (the structure with the lowest energy) of the protein molecule."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"327.0085 I\n",
"-47.5 Z1, Z3\n",
"65.0 Z1, Z5\n",
"-50.0 Z1, Z7\n",
"52.5 Z1, Z9\n",
"-47.5 Z0, Z2\n",
"65.0 Z0, Z4\n",
"-50.0 Z0, Z6\n",
"52.5 Z0, Z8\n",
"-47.5 Z0, Z1, Z2, Z3\n",
"65.0 Z0, Z1, Z4, Z5\n",
"-50.0 Z0, Z1, Z6, Z7\n",
"52.5 Z0, Z1, Z8, Z9\n",
"-65.0 Z3, Z5\n",
"92.5 Z3, Z7\n",
"-60.0 Z3, Z9\n",
"-65.0 Z2, Z4\n",
"92.5 Z2, Z6\n",
"-60.0 Z2, Z8\n",
"-65.0 Z2, Z3, Z4, Z5\n",
"92.5 Z2, Z3, Z6, Z7\n",
"-60.0 Z2, Z3, Z8, Z9\n",
"-72.5 Z5, Z7\n",
"92.5 Z5, Z9\n",
"-72.5 Z4, Z6\n",
"92.5 Z4, Z8\n",
"-72.5 Z4, Z5, Z6, Z7\n",
"92.5 Z4, Z5, Z8, Z9\n",
"-65.0 Z7, Z9\n",
"-65.0 Z6, Z8\n",
"-65.0 Z6, Z7, Z8, Z9\n",
"-157.168 Z12\n",
"30.0 Z1, Z3, Z12\n",
"-40.0 Z1, Z5, Z12\n",
"30.0 Z1, Z7, Z12\n",
"-27.5 Z1, Z9, Z12\n",
"30.0 Z0, Z2, Z12\n",
"-40.0 Z0, Z4, Z12\n",
"30.0 Z0, Z6, Z12\n",
"-27.5 Z0, Z8, Z12\n",
"30.0 Z0, Z1, Z2, Z3, Z12\n",
"-40.0 Z0, Z1, Z4, Z5, Z12\n",
"30.0 Z0, Z1, Z6, Z7, Z12\n",
"-27.5 Z0, Z1, Z8, Z9, Z12\n",
"37.5 Z3, Z5, Z12\n",
"-52.5 Z3, Z7, Z12\n",
"30.0 Z3, Z9, Z12\n",
"37.5 Z2, Z4, Z12\n",
"-52.5 Z2, Z6, Z12\n",
"30.0 Z2, Z8, Z12\n",
"37.5 Z2, Z3, Z4, Z5, Z12\n",
"-52.5 Z2, Z3, Z6, Z7, Z12\n",
"30.0 Z2, Z3, Z8, Z9, Z12\n",
"37.5 Z5, Z7, Z12\n",
"-40.0 Z5, Z9, Z12\n",
"37.5 Z4, Z6, Z12\n",
"-40.0 Z4, Z8, Z12\n",
"37.5 Z4, Z5, Z6, Z7, Z12\n",
"-40.0 Z4, Z5, Z8, Z9, Z12\n",
"30.0 Z7, Z9, Z12\n",
"30.0 Z6, Z8, Z12\n",
"30.0 Z6, Z7, Z8, Z9, Z12\n",
"-12.5 Z2, Z3, Z5, Z6\n",
"-10.0 Z2, Z3, Z5, Z8\n",
"-12.5 Z2, Z5, Z6, Z7\n",
"-10.0 Z2, Z5, Z8, Z9\n",
"-12.5 Z3, Z4, Z5, Z6\n",
"-10.0 Z3, Z4, Z5, Z8\n",
"-12.5 Z3, Z4, Z6, Z7\n",
"-10.0 Z3, Z4, Z8, Z9\n",
"30.0 Z3, Z5, Z7, Z9\n",
"10.0 Z3, Z5, Z6, Z8\n",
"10.0 Z3, Z5, Z6, Z7, Z8, Z9\n",
"-12.5 Z2, Z3, Z4, Z7\n",
"-10.0 Z2, Z3, Z7, Z8\n",
"-12.5 Z2, Z4, Z5, Z7\n",
"-10.0 Z2, Z7, Z8, Z9\n",
"10.0 Z3, Z4, Z7, Z8\n",
"10.0 Z3, Z4, Z5, Z7, Z8, Z9\n",
"-10.0 Z3, Z6, Z7, Z8\n",
"-10.0 Z3, Z6, Z8, Z9\n",
"-10.0 Z2, Z3, Z4, Z9\n",
"-10.0 Z2, Z3, Z6, Z9\n",
"-10.0 Z2, Z4, Z5, Z9\n",
"-10.0 Z2, Z6, Z7, Z9\n",
"10.0 Z3, Z4, Z6, Z9\n",
"10.0 Z3, Z4, Z5, Z6, Z7, Z9\n",
"10.0 Z2, Z4, Z7, Z9\n",
"30.0 Z2, Z4, Z6, Z8\n",
"10.0 Z2, Z4, Z6, Z7, Z8, Z9\n",
"10.0 Z2, Z5, Z6, Z9\n",
"10.0 Z2, Z4, Z5, Z6, Z8, Z9\n",
"10.0 Z2, Z5, Z7, Z8\n",
"10.0 Z2, Z4, Z5, Z6, Z7, Z8\n",
"10.0 Z2, Z3, Z4, Z5, Z7, Z9\n",
"10.0 Z2, Z3, Z4, Z5, Z6, Z8\n",
"30.0 Z2, Z3, Z4, Z5, Z6, Z7, Z8, Z9\n",
"10.0 Z2, Z3, Z5, Z6, Z7, Z9\n",
"10.0 Z2, Z3, Z4, Z6, Z7, Z8\n",
"10.0 Z2, Z3, Z5, Z7, Z8, Z9\n",
"10.0 Z2, Z3, Z4, Z6, Z8, Z9\n",
"-12.5 Z4, Z5, Z7, Z8\n",
"-12.5 Z4, Z7, Z8, Z9\n",
"-12.5 Z5, Z6, Z7, Z8\n",
"-12.5 Z5, Z6, Z8, Z9\n",
"-12.5 Z4, Z5, Z6, Z9\n",
"-12.5 Z4, Z6, Z7, Z9\n",
"7.5 Z2, Z3, Z5, Z6, Z12\n",
"5.0 Z2, Z3, Z5, Z8, Z12\n",
"7.5 Z2, Z5, Z6, Z7, Z12\n",
"5.0 Z2, Z5, Z8, Z9, Z12\n",
"7.5 Z3, Z4, Z5, Z6, Z12\n",
"5.0 Z3, Z4, Z5, Z8, Z12\n",
"7.5 Z3, Z4, Z6, Z7, Z12\n",
"5.0 Z3, Z4, Z8, Z9, Z12\n",
"-15.0 Z3, Z5, Z7, Z9, Z12\n",
"-5.0 Z3, Z5, Z6, Z8, Z12\n",
"-5.0 Z3, Z5, Z6, Z7, Z8, Z9, Z12\n",
"7.5 Z2, Z3, Z4, Z7, Z12\n",
"5.0 Z2, Z3, Z7, Z8, Z12\n",
"7.5 Z2, Z4, Z5, Z7, Z12\n",
"5.0 Z2, Z7, Z8, Z9, Z12\n",
"-5.0 Z3, Z4, Z7, Z8, Z12\n",
"-5.0 Z3, Z4, Z5, Z7, Z8, Z9, Z12\n",
"5.0 Z3, Z6, Z7, Z8, Z12\n",
"5.0 Z3, Z6, Z8, Z9, Z12\n",
"5.0 Z2, Z3, Z4, Z9, Z12\n",
"5.0 Z2, Z3, Z6, Z9, Z12\n",
"5.0 Z2, Z4, Z5, Z9, Z12\n",
"5.0 Z2, Z6, Z7, Z9, Z12\n",
"-5.0 Z3, Z4, Z6, Z9, Z12\n",
"-5.0 Z3, Z4, Z5, Z6, Z7, Z9, Z12\n",
"-5.0 Z2, Z4, Z7, Z9, Z12\n",
"-15.0 Z2, Z4, Z6, Z8, Z12\n",
"-5.0 Z2, Z4, Z6, Z7, Z8, Z9, Z12\n",
"-5.0 Z2, Z5, Z6, Z9, Z12\n",
"-5.0 Z2, Z4, Z5, Z6, Z8, Z9, Z12\n",
"-5.0 Z2, Z5, Z7, Z8, Z12\n",
"-5.0 Z2, Z4, Z5, Z6, Z7, Z8, Z12\n",
"-5.0 Z2, Z3, Z4, Z5, Z7, Z9, Z12\n",
"-5.0 Z2, Z3, Z4, Z5, Z6, Z8, Z12\n",
"-15.0 Z2, Z3, Z4, Z5, Z6, Z7, Z8, Z9, Z12\n",
"-5.0 Z2, Z3, Z5, Z6, Z7, Z9, Z12\n",
"-5.0 Z2, Z3, Z4, Z6, Z7, Z8, Z12\n",
"-5.0 Z2, Z3, Z5, Z7, Z8, Z9, Z12\n",
"-5.0 Z2, Z3, Z4, Z6, Z8, Z9, Z12\n",
"5.0 Z4, Z5, Z7, Z8, Z12\n",
"5.0 Z4, Z7, Z8, Z9, Z12\n",
"5.0 Z5, Z6, Z7, Z8, Z12\n",
"5.0 Z5, Z6, Z8, Z9, Z12\n",
"5.0 Z4, Z5, Z6, Z9, Z12\n",
"5.0 Z4, Z6, Z7, Z9, Z12\n",
"-7.5 Z0, Z1, Z3, Z4\n",
"-7.5 Z0, Z1, Z3, Z6\n",
"-7.5 Z0, Z3, Z4, Z5\n",
"-7.5 Z0, Z3, Z6, Z7\n",
"-7.5 Z1, Z2, Z3, Z4\n",
"-7.5 Z1, Z2, Z3, Z6\n",
"-7.5 Z1, Z2, Z4, Z5\n",
"-7.5 Z1, Z2, Z6, Z7\n",
"22.5 Z1, Z3, Z5, Z7\n",
"7.5 Z1, Z3, Z4, Z6\n",
"7.5 Z1, Z3, Z4, Z5, Z6, Z7\n",
"-7.5 Z0, Z1, Z2, Z5\n",
"-7.5 Z0, Z1, Z5, Z6\n",
"-7.5 Z0, Z2, Z3, Z5\n",
"-7.5 Z0, Z5, Z6, Z7\n",
"7.5 Z1, Z2, Z5, Z6\n",
"7.5 Z1, Z2, Z3, Z5, Z6, Z7\n",
"-7.5 Z1, Z4, Z5, Z6\n",
"-7.5 Z1, Z4, Z6, Z7\n",
"-7.5 Z0, Z1, Z2, Z7\n",
"-7.5 Z0, Z1, Z4, Z7\n",
"-7.5 Z0, Z2, Z3, Z7\n",
"-7.5 Z0, Z4, Z5, Z7\n",
"7.5 Z1, Z2, Z4, Z7\n",
"7.5 Z1, Z2, Z3, Z4, Z5, Z7\n",
"7.5 Z0, Z2, Z5, Z7\n",
"22.5 Z0, Z2, Z4, Z6\n",
"7.5 Z0, Z2, Z4, Z5, Z6, Z7\n",
"7.5 Z0, Z3, Z4, Z7\n",
"7.5 Z0, Z2, Z3, Z4, Z6, Z7\n",
"7.5 Z0, Z3, Z5, Z6\n",
"7.5 Z0, Z2, Z3, Z4, Z5, Z6\n",
"7.5 Z0, Z1, Z2, Z3, Z5, Z7\n",
"7.5 Z0, Z1, Z2, Z3, Z4, Z6\n",
"22.5 Z0, Z1, Z2, Z3, Z4, Z5, Z6, Z7\n",
"7.5 Z0, Z1, Z3, Z4, Z5, Z7\n",
"7.5 Z0, Z1, Z2, Z4, Z5, Z6\n",
"7.5 Z0, Z1, Z3, Z5, Z6, Z7\n",
"7.5 Z0, Z1, Z2, Z4, Z6, Z7\n",
"5.0 Z0, Z1, Z3, Z4, Z12\n",
"5.0 Z0, Z1, Z3, Z6, Z12\n",
"5.0 Z0, Z3, Z4, Z5, Z12\n",
"5.0 Z0, Z3, Z6, Z7, Z12\n",
"5.0 Z1, Z2, Z3, Z4, Z12\n",
"5.0 Z1, Z2, Z3, Z6, Z12\n",
"5.0 Z1, Z2, Z4, Z5, Z12\n",
"5.0 Z1, Z2, Z6, Z7, Z12\n",
"-15.0 Z1, Z3, Z5, Z7, Z12\n",
"-5.0 Z1, Z3, Z4, Z6, Z12\n",
"-5.0 Z1, Z3, Z4, Z5, Z6, Z7, Z12\n",
"5.0 Z0, Z1, Z2, Z5, Z12\n",
"5.0 Z0, Z1, Z5, Z6, Z12\n",
"5.0 Z0, Z2, Z3, Z5, Z12\n",
"5.0 Z0, Z5, Z6, Z7, Z12\n",
"-5.0 Z1, Z2, Z5, Z6, Z12\n",
"-5.0 Z1, Z2, Z3, Z5, Z6, Z7, Z12\n",
"5.0 Z1, Z4, Z5, Z6, Z12\n",
"5.0 Z1, Z4, Z6, Z7, Z12\n",
"5.0 Z0, Z1, Z2, Z7, Z12\n",
"5.0 Z0, Z1, Z4, Z7, Z12\n",
"5.0 Z0, Z2, Z3, Z7, Z12\n",
"5.0 Z0, Z4, Z5, Z7, Z12\n",
"-5.0 Z1, Z2, Z4, Z7, Z12\n",
"-5.0 Z1, Z2, Z3, Z4, Z5, Z7, Z12\n",
"-5.0 Z0, Z2, Z5, Z7, Z12\n",
"-15.0 Z0, Z2, Z4, Z6, Z12\n",
"-5.0 Z0, Z2, Z4, Z5, Z6, Z7, Z12\n",
"-5.0 Z0, Z3, Z4, Z7, Z12\n",
"-5.0 Z0, Z2, Z3, Z4, Z6, Z7, Z12\n",
"-5.0 Z0, Z3, Z5, Z6, Z12\n",
"-5.0 Z0, Z2, Z3, Z4, Z5, Z6, Z12\n",
"-5.0 Z0, Z1, Z2, Z3, Z5, Z7, Z12\n",
"-5.0 Z0, Z1, Z2, Z3, Z4, Z6, Z12\n",
"-15.0 Z0, Z1, Z2, Z3, Z4, Z5, Z6, Z7, Z12\n",
"-5.0 Z0, Z1, Z3, Z4, Z5, Z7, Z12\n",
"-5.0 Z0, Z1, Z2, Z4, Z5, Z6, Z12\n",
"-5.0 Z0, Z1, Z3, Z5, Z6, Z7, Z12\n",
"-5.0 Z0, Z1, Z2, Z4, Z6, Z7, Z12\n",
"-40.0 Z1, Z11\n",
"-40.0 Z0, Z10\n",
"-40.0 Z0, Z1, Z10, Z11\n",
"52.5 Z3, Z11\n",
"52.5 Z2, Z10\n",
"52.5 Z2, Z3, Z10, Z11\n",
"-50.0 Z5, Z11\n",
"-50.0 Z4, Z10\n",
"-50.0 Z4, Z5, Z10, Z11\n",
"65.0 Z7, Z11\n",
"65.0 Z6, Z10\n",
"65.0 Z6, Z7, Z10, Z11\n",
"-47.5 Z9, Z11\n",
"-47.5 Z8, Z10\n",
"-47.5 Z8, Z9, Z10, Z11\n",
"-5.0 Z0, Z1, Z3, Z8\n",
"-5.0 Z0, Z1, Z3, Z10\n",
"-5.0 Z0, Z3, Z8, Z9\n",
"-5.0 Z0, Z3, Z10, Z11\n",
"-5.0 Z1, Z2, Z3, Z8\n",
"-5.0 Z1, Z2, Z3, Z10\n",
"-5.0 Z1, Z2, Z8, Z9\n",
"-5.0 Z1, Z2, Z10, Z11\n",
"-15.0 Z1, Z3, Z5, Z9\n",
"15.0 Z1, Z3, Z5, Z11\n",
"-5.0 Z1, Z3, Z4, Z8\n",
"5.0 Z1, Z3, Z4, Z10\n",
"-5.0 Z1, Z3, Z4, Z5, Z8, Z9\n",
"5.0 Z1, Z3, Z4, Z5, Z10, Z11\n",
"15.0 Z1, Z3, Z7, Z9\n",
"-15.0 Z1, Z3, Z7, Z11\n",
"5.0 Z1, Z3, Z6, Z8\n",
"-5.0 Z1, Z3, Z6, Z10\n",
"5.0 Z1, Z3, Z6, Z7, Z8, Z9\n",
"-5.0 Z1, Z3, Z6, Z7, Z10, Z11\n",
"15.0 Z1, Z3, Z9, Z11\n",
"5.0 Z1, Z3, Z8, Z10\n",
"5.0 Z1, Z3, Z8, Z9, Z10, Z11\n",
"15.0 Z0, Z1, Z5, Z8\n",
"-5.0 Z0, Z1, Z5, Z10\n",
"15.0 Z0, Z5, Z8, Z9\n",
"-5.0 Z0, Z5, Z10, Z11\n",
"-5.0 Z1, Z2, Z5, Z8\n",
"5.0 Z1, Z2, Z5, Z10\n",
"-5.0 Z1, Z2, Z3, Z5, Z8, Z9\n",
"5.0 Z1, Z2, Z3, Z5, Z10, Z11\n",
"15.0 Z1, Z4, Z5, Z8\n",
"-5.0 Z1, Z4, Z5, Z10\n",
"15.0 Z1, Z4, Z8, Z9\n",
"-5.0 Z1, Z4, Z10, Z11\n",
"-15.0 Z1, Z5, Z7, Z9\n",
"15.0 Z1, Z5, Z7, Z11\n",
"-5.0 Z1, Z5, Z6, Z8\n",
"5.0 Z1, Z5, Z6, Z10\n",
"-5.0 Z1, Z5, Z6, Z7, Z8, Z9\n",
"5.0 Z1, Z5, Z6, Z7, Z10, Z11\n",
"-15.0 Z1, Z5, Z9, Z11\n",
"-5.0 Z1, Z5, Z8, Z10\n",
"-5.0 Z1, Z5, Z8, Z9, Z10, Z11\n",
"-5.0 Z0, Z1, Z7, Z8\n",
"-5.0 Z0, Z1, Z7, Z10\n",
"-5.0 Z0, Z7, Z8, Z9\n",
"-5.0 Z0, Z7, Z10, Z11\n",
"5.0 Z1, Z2, Z7, Z8\n",
"-5.0 Z1, Z2, Z7, Z10\n",
"5.0 Z1, Z2, Z3, Z7, Z8, Z9\n",
"-5.0 Z1, Z2, Z3, Z7, Z10, Z11\n",
"-5.0 Z1, Z4, Z7, Z8\n",
"5.0 Z1, Z4, Z7, Z10\n",
"-5.0 Z1, Z4, Z5, Z7, Z8, Z9\n",
"5.0 Z1, Z4, Z5, Z7, Z10, Z11\n",
"-5.0 Z1, Z6, Z7, Z8\n",
"-5.0 Z1, Z6, Z7, Z10\n",
"-5.0 Z1, Z6, Z8, Z9\n",
"-5.0 Z1, Z6, Z10, Z11\n",
"15.0 Z1, Z7, Z9, Z11\n",
"5.0 Z1, Z7, Z8, Z10\n",
"5.0 Z1, Z7, Z8, Z9, Z10, Z11\n",
"-5.0 Z0, Z1, Z2, Z9\n",
"15.0 Z0, Z1, Z4, Z9\n",
"-5.0 Z0, Z1, Z6, Z9\n",
"-5.0 Z0, Z1, Z9, Z10\n",
"-5.0 Z0, Z2, Z3, Z9\n",
"15.0 Z0, Z4, Z5, Z9\n",
"-5.0 Z0, Z6, Z7, Z9\n",
"-5.0 Z0, Z9, Z10, Z11\n",
"-5.0 Z1, Z2, Z4, Z9\n",
"5.0 Z1, Z2, Z6, Z9\n",
"5.0 Z1, Z2, Z9, Z10\n",
"-5.0 Z1, Z2, Z3, Z4, Z5, Z9\n",
"5.0 Z1, Z2, Z3, Z6, Z7, Z9\n",
"5.0 Z1, Z2, Z3, Z9, Z10, Z11\n",
"-5.0 Z1, Z4, Z6, Z9\n",
"-5.0 Z1, Z4, Z9, Z10\n",
"-5.0 Z1, Z4, Z5, Z6, Z7, Z9\n",
"-5.0 Z1, Z4, Z5, Z9, Z10, Z11\n",
"5.0 Z1, Z6, Z9, Z10\n",
"5.0 Z1, Z6, Z7, Z9, Z10, Z11\n",
"-5.0 Z1, Z8, Z9, Z10\n",
"-5.0 Z1, Z8, Z10, Z11\n",
"-5.0 Z0, Z1, Z2, Z11\n",
"-5.0 Z0, Z1, Z4, Z11\n",
"-5.0 Z0, Z1, Z6, Z11\n",
"-5.0 Z0, Z1, Z8, Z11\n",
"-5.0 Z0, Z2, Z3, Z11\n",
"-5.0 Z0, Z4, Z5, Z11\n",
"-5.0 Z0, Z6, Z7, Z11\n",
"-5.0 Z0, Z8, Z9, Z11\n",
"5.0 Z1, Z2, Z4, Z11\n",
"-5.0 Z1, Z2, Z6, Z11\n",
"5.0 Z1, Z2, Z8, Z11\n",
"5.0 Z1, Z2, Z3, Z4, Z5, Z11\n",
"-5.0 Z1, Z2, Z3, Z6, Z7, Z11\n",
"5.0 Z1, Z2, Z3, Z8, Z9, Z11\n",
"5.0 Z1, Z4, Z6, Z11\n",
"-5.0 Z1, Z4, Z8, Z11\n",
"5.0 Z1, Z4, Z5, Z6, Z7, Z11\n",
"-5.0 Z1, Z4, Z5, Z8, Z9, Z11\n",
"5.0 Z1, Z6, Z8, Z11\n",
"5.0 Z1, Z6, Z7, Z8, Z9, Z11\n",
"-5.0 Z0, Z2, Z5, Z9\n",
"5.0 Z0, Z2, Z5, Z11\n",
"-15.0 Z0, Z2, Z4, Z8\n",
"15.0 Z0, Z2, Z4, Z10\n",
"-5.0 Z0, Z2, Z4, Z5, Z8, Z9\n",
"5.0 Z0, Z2, Z4, Z5, Z10, Z11\n",
"5.0 Z0, Z2, Z7, Z9\n",
"-5.0 Z0, Z2, Z7, Z11\n",
"15.0 Z0, Z2, Z6, Z8\n",
"-15.0 Z0, Z2, Z6, Z10\n",
"5.0 Z0, Z2, Z6, Z7, Z8, Z9\n",
"-5.0 Z0, Z2, Z6, Z7, Z10, Z11\n",
"5.0 Z0, Z2, Z9, Z11\n",
"15.0 Z0, Z2, Z8, Z10\n",
"5.0 Z0, Z2, Z8, Z9, Z10, Z11\n",
"-5.0 Z0, Z3, Z4, Z9\n",
"5.0 Z0, Z3, Z4, Z11\n",
"-5.0 Z0, Z2, Z3, Z4, Z8, Z9\n",
"5.0 Z0, Z2, Z3, Z4, Z10, Z11\n",
"-5.0 Z0, Z4, Z7, Z9\n",
"5.0 Z0, Z4, Z7, Z11\n",
"-15.0 Z0, Z4, Z6, Z8\n",
"15.0 Z0, Z4, Z6, Z10\n",
"-5.0 Z0, Z4, Z6, Z7, Z8, Z9\n",
"5.0 Z0, Z4, Z6, Z7, Z10, Z11\n",
"-5.0 Z0, Z4, Z9, Z11\n",
"-15.0 Z0, Z4, Z8, Z10\n",
"-5.0 Z0, Z4, Z8, Z9, Z10, Z11\n",
"5.0 Z0, Z3, Z6, Z9\n",
"-5.0 Z0, Z3, Z6, Z11\n",
"5.0 Z0, Z2, Z3, Z6, Z8, Z9\n",
"-5.0 Z0, Z2, Z3, Z6, Z10, Z11\n",
"-5.0 Z0, Z5, Z6, Z9\n",
"5.0 Z0, Z5, Z6, Z11\n",
"-5.0 Z0, Z4, Z5, Z6, Z8, Z9\n",
"5.0 Z0, Z4, Z5, Z6, Z10, Z11\n",
"5.0 Z0, Z6, Z9, Z11\n",
"15.0 Z0, Z6, Z8, Z10\n",
"5.0 Z0, Z6, Z8, Z9, Z10, Z11\n",
"-5.0 Z0, Z3, Z5, Z8\n",
"5.0 Z0, Z3, Z7, Z8\n",
"5.0 Z0, Z3, Z8, Z11\n",
"-5.0 Z0, Z2, Z3, Z4, Z5, Z8\n",
"5.0 Z0, Z2, Z3, Z6, Z7, Z8\n",
"5.0 Z0, Z2, Z3, Z8, Z10, Z11\n",
"-5.0 Z0, Z5, Z7, Z8\n",
"-5.0 Z0, Z5, Z8, Z11\n",
"-5.0 Z0, Z4, Z5, Z6, Z7, Z8\n",
"-5.0 Z0, Z4, Z5, Z8, Z10, Z11\n",
"5.0 Z0, Z7, Z8, Z11\n",
"5.0 Z0, Z6, Z7, Z8, Z10, Z11\n",
"5.0 Z0, Z3, Z5, Z10\n",
"-5.0 Z0, Z3, Z7, Z10\n",
"5.0 Z0, Z3, Z9, Z10\n",
"5.0 Z0, Z2, Z3, Z4, Z5, Z10\n",
"-5.0 Z0, Z2, Z3, Z6, Z7, Z10\n",
"5.0 Z0, Z2, Z3, Z8, Z9, Z10\n",
"5.0 Z0, Z5, Z7, Z10\n",
"-5.0 Z0, Z5, Z9, Z10\n",
"5.0 Z0, Z4, Z5, Z6, Z7, Z10\n",
"-5.0 Z0, Z4, Z5, Z8, Z9, Z10\n",
"5.0 Z0, Z7, Z9, Z10\n",
"5.0 Z0, Z6, Z7, Z8, Z9, Z10\n",
"-5.0 Z0, Z1, Z2, Z3, Z5, Z9\n",
"5.0 Z0, Z1, Z2, Z3, Z5, Z11\n",
"-5.0 Z0, Z1, Z2, Z3, Z4, Z8\n",
"5.0 Z0, Z1, Z2, Z3, Z4, Z10\n",
"-15.0 Z0, Z1, Z2, Z3, Z4, Z5, Z8, Z9\n",
"15.0 Z0, Z1, Z2, Z3, Z4, Z5, Z10, Z11\n",
"5.0 Z0, Z1, Z2, Z3, Z7, Z9\n",
"-5.0 Z0, Z1, Z2, Z3, Z7, Z11\n",
"5.0 Z0, Z1, Z2, Z3, Z6, Z8\n",
"-5.0 Z0, Z1, Z2, Z3, Z6, Z10\n",
"15.0 Z0, Z1, Z2, Z3, Z6, Z7, Z8, Z9\n",
"-15.0 Z0, Z1, Z2, Z3, Z6, Z7, Z10, Z11\n",
"5.0 Z0, Z1, Z2, Z3, Z9, Z11\n",
"5.0 Z0, Z1, Z2, Z3, Z8, Z10\n",
"15.0 Z0, Z1, Z2, Z3, Z8, Z9, Z10, Z11\n",
"-5.0 Z0, Z1, Z3, Z4, Z5, Z9\n",
"5.0 Z0, Z1, Z3, Z4, Z5, Z11\n",
"-5.0 Z0, Z1, Z2, Z4, Z5, Z8\n",
"5.0 Z0, Z1, Z2, Z4, Z5, Z10\n",
"-5.0 Z0, Z1, Z4, Z5, Z7, Z9\n",
"5.0 Z0, Z1, Z4, Z5, Z7, Z11\n",
"-5.0 Z0, Z1, Z4, Z5, Z6, Z8\n",
"5.0 Z0, Z1, Z4, Z5, Z6, Z10\n",
"-15.0 Z0, Z1, Z4, Z5, Z6, Z7, Z8, Z9\n",
"15.0 Z0, Z1, Z4, Z5, Z6, Z7, Z10, Z11\n",
"-5.0 Z0, Z1, Z4, Z5, Z9, Z11\n",
"-5.0 Z0, Z1, Z4, Z5, Z8, Z10\n",
"-15.0 Z0, Z1, Z4, Z5, Z8, Z9, Z10, Z11\n",
"5.0 Z0, Z1, Z3, Z6, Z7, Z9\n",
"-5.0 Z0, Z1, Z3, Z6, Z7, Z11\n",
"5.0 Z0, Z1, Z2, Z6, Z7, Z8\n",
"-5.0 Z0, Z1, Z2, Z6, Z7, Z10\n",
"-5.0 Z0, Z1, Z5, Z6, Z7, Z9\n",
"5.0 Z0, Z1, Z5, Z6, Z7, Z11\n",
"-5.0 Z0, Z1, Z4, Z6, Z7, Z8\n",
"5.0 Z0, Z1, Z4, Z6, Z7, Z10\n",
"5.0 Z0, Z1, Z6, Z7, Z9, Z11\n",
"5.0 Z0, Z1, Z6, Z7, Z8, Z10\n",
"15.0 Z0, Z1, Z6, Z7, Z8, Z9, Z10, Z11\n",
"-5.0 Z0, Z1, Z3, Z5, Z8, Z9\n",
"5.0 Z0, Z1, Z3, Z7, Z8, Z9\n",
"5.0 Z0, Z1, Z3, Z8, Z9, Z11\n",
"-5.0 Z0, Z1, Z2, Z4, Z8, Z9\n",
"5.0 Z0, Z1, Z2, Z6, Z8, Z9\n",
"5.0 Z0, Z1, Z2, Z8, Z9, Z10\n",
"-5.0 Z0, Z1, Z5, Z7, Z8, Z9\n",
"-5.0 Z0, Z1, Z5, Z8, Z9, Z11\n",
"-5.0 Z0, Z1, Z4, Z6, Z8, Z9\n",
"-5.0 Z0, Z1, Z4, Z8, Z9, Z10\n",
"5.0 Z0, Z1, Z7, Z8, Z9, Z11\n",
"5.0 Z0, Z1, Z6, Z8, Z9, Z10\n",
"5.0 Z0, Z1, Z3, Z5, Z10, Z11\n",
"-5.0 Z0, Z1, Z3, Z7, Z10, Z11\n",
"5.0 Z0, Z1, Z3, Z9, Z10, Z11\n",
"5.0 Z0, Z1, Z2, Z4, Z10, Z11\n",
"-5.0 Z0, Z1, Z2, Z6, Z10, Z11\n",
"5.0 Z0, Z1, Z2, Z8, Z10, Z11\n",
"5.0 Z0, Z1, Z5, Z7, Z10, Z11\n",
"-5.0 Z0, Z1, Z5, Z9, Z10, Z11\n",
"5.0 Z0, Z1, Z4, Z6, Z10, Z11\n",
"-5.0 Z0, Z1, Z4, Z8, Z10, Z11\n",
"5.0 Z0, Z1, Z7, Z9, Z10, Z11\n",
"5.0 Z0, Z1, Z6, Z8, Z10, Z11\n",
"-5.0 Z2, Z3, Z5, Z10\n",
"-5.0 Z2, Z5, Z10, Z11\n",
"-5.0 Z3, Z4, Z5, Z10\n",
"-5.0 Z3, Z4, Z10, Z11\n",
"-15.0 Z3, Z5, Z7, Z11\n",
"-5.0 Z3, Z5, Z6, Z10\n",
"-5.0 Z3, Z5, Z6, Z7, Z10, Z11\n",
"15.0 Z3, Z5, Z9, Z11\n",
"5.0 Z3, Z5, Z8, Z10\n",
"5.0 Z3, Z5, Z8, Z9, Z10, Z11\n",
"15.0 Z2, Z3, Z7, Z10\n",
"15.0 Z2, Z7, Z10, Z11\n",
"-5.0 Z3, Z4, Z7, Z10\n",
"-5.0 Z3, Z4, Z5, Z7, Z10, Z11\n",
"15.0 Z3, Z6, Z7, Z10\n",
"15.0 Z3, Z6, Z10, Z11\n",
"-15.0 Z3, Z7, Z9, Z11\n",
"-5.0 Z3, Z7, Z8, Z10\n",
"-5.0 Z3, Z7, Z8, Z9, Z10, Z11\n",
"-5.0 Z2, Z3, Z9, Z10\n",
"-5.0 Z2, Z9, Z10, Z11\n",
"5.0 Z3, Z4, Z9, Z10\n",
"5.0 Z3, Z4, Z5, Z9, Z10, Z11\n",
"-5.0 Z3, Z6, Z9, Z10\n",
"-5.0 Z3, Z6, Z7, Z9, Z10, Z11\n",
"-5.0 Z3, Z8, Z9, Z10\n",
"-5.0 Z3, Z8, Z10, Z11\n",
"-5.0 Z2, Z3, Z4, Z11\n",
"15.0 Z2, Z3, Z6, Z11\n",
"-5.0 Z2, Z3, Z8, Z11\n",
"-5.0 Z2, Z4, Z5, Z11\n",
"15.0 Z2, Z6, Z7, Z11\n",
"-5.0 Z2, Z8, Z9, Z11\n",
"-5.0 Z3, Z4, Z6, Z11\n",
"5.0 Z3, Z4, Z8, Z11\n",
"-5.0 Z3, Z4, Z5, Z6, Z7, Z11\n",
"5.0 Z3, Z4, Z5, Z8, Z9, Z11\n",
"-5.0 Z3, Z6, Z8, Z11\n",
"-5.0 Z3, Z6, Z7, Z8, Z9, Z11\n",
"-5.0 Z2, Z4, Z7, Z11\n",
"-15.0 Z2, Z4, Z6, Z10\n",
"-5.0 Z2, Z4, Z6, Z7, Z10, Z11\n",
"5.0 Z2, Z4, Z9, Z11\n",
"15.0 Z2, Z4, Z8, Z10\n",
"5.0 Z2, Z4, Z8, Z9, Z10, Z11\n",
"-5.0 Z2, Z5, Z6, Z11\n",
"-5.0 Z2, Z4, Z5, Z6, Z10, Z11\n",
"-5.0 Z2, Z6, Z9, Z11\n",
"-15.0 Z2, Z6, Z8, Z10\n",
"-5.0 Z2, Z6, Z8, Z9, Z10, Z11\n",
"5.0 Z2, Z5, Z8, Z11\n",
"5.0 Z2, Z4, Z5, Z8, Z10, Z11\n",
"-5.0 Z2, Z7, Z8, Z11\n",
"-5.0 Z2, Z6, Z7, Z8, Z10, Z11\n",
"-5.0 Z2, Z5, Z7, Z10\n",
"5.0 Z2, Z5, Z9, Z10\n",
"-5.0 Z2, Z4, Z5, Z6, Z7, Z10\n",
"5.0 Z2, Z4, Z5, Z8, Z9, Z10\n",
"-5.0 Z2, Z7, Z9, Z10\n",
"-5.0 Z2, Z6, Z7, Z8, Z9, Z10\n",
"-5.0 Z2, Z3, Z4, Z5, Z7, Z11\n",
"-5.0 Z2, Z3, Z4, Z5, Z6, Z10\n",
"-15.0 Z2, Z3, Z4, Z5, Z6, Z7, Z10, Z11\n",
"5.0 Z2, Z3, Z4, Z5, Z9, Z11\n",
"5.0 Z2, Z3, Z4, Z5, Z8, Z10\n",
"15.0 Z2, Z3, Z4, Z5, Z8, Z9, Z10, Z11\n",
"-5.0 Z2, Z3, Z5, Z6, Z7, Z11\n",
"-5.0 Z2, Z3, Z4, Z6, Z7, Z10\n",
"-5.0 Z2, Z3, Z6, Z7, Z9, Z11\n",
"-5.0 Z2, Z3, Z6, Z7, Z8, Z10\n",
"-15.0 Z2, Z3, Z6, Z7, Z8, Z9, Z10, Z11\n",
"5.0 Z2, Z3, Z5, Z8, Z9, Z11\n",
"5.0 Z2, Z3, Z4, Z8, Z9, Z10\n",
"-5.0 Z2, Z3, Z7, Z8, Z9, Z11\n",
"-5.0 Z2, Z3, Z6, Z8, Z9, Z10\n",
"-5.0 Z2, Z3, Z5, Z7, Z10, Z11\n",
"5.0 Z2, Z3, Z5, Z9, Z10, Z11\n",
"-5.0 Z2, Z3, Z4, Z6, Z10, Z11\n",
"5.0 Z2, Z3, Z4, Z8, Z10, Z11\n",
"-5.0 Z2, Z3, Z7, Z9, Z10, Z11\n",
"-5.0 Z2, Z3, Z6, Z8, Z10, Z11\n",
"-7.5 Z4, Z5, Z7, Z10\n",
"-7.5 Z4, Z7, Z10, Z11\n",
"-7.5 Z5, Z6, Z7, Z10\n",
"-7.5 Z5, Z6, Z10, Z11\n",
"22.5 Z5, Z7, Z9, Z11\n",
"7.5 Z5, Z7, Z8, Z10\n",
"7.5 Z5, Z7, Z8, Z9, Z10, Z11\n",
"-7.5 Z4, Z5, Z9, Z10\n",
"-7.5 Z4, Z9, Z10, Z11\n",
"7.5 Z5, Z6, Z9, Z10\n",
"7.5 Z5, Z6, Z7, Z9, Z10, Z11\n",
"-7.5 Z5, Z8, Z9, Z10\n",
"-7.5 Z5, Z8, Z10, Z11\n",
"-7.5 Z4, Z5, Z6, Z11\n",
"-7.5 Z4, Z5, Z8, Z11\n",
"-7.5 Z4, Z6, Z7, Z11\n",
"-7.5 Z4, Z8, Z9, Z11\n",
"7.5 Z5, Z6, Z8, Z11\n",
"7.5 Z5, Z6, Z7, Z8, Z9, Z11\n",
"7.5 Z4, Z6, Z9, Z11\n",
"22.5 Z4, Z6, Z8, Z10\n",
"7.5 Z4, Z6, Z8, Z9, Z10, Z11\n",
"7.5 Z4, Z7, Z8, Z11\n",
"7.5 Z4, Z6, Z7, Z8, Z10, Z11\n",
"7.5 Z4, Z7, Z9, Z10\n",
"7.5 Z4, Z6, Z7, Z8, Z9, Z10\n",
"7.5 Z4, Z5, Z6, Z7, Z9, Z11\n",
"7.5 Z4, Z5, Z6, Z7, Z8, Z10\n",
"22.5 Z4, Z5, Z6, Z7, Z8, Z9, Z10, Z11\n",
"7.5 Z4, Z5, Z7, Z8, Z9, Z11\n",
"7.5 Z4, Z5, Z6, Z8, Z9, Z10\n",
"7.5 Z4, Z5, Z7, Z9, Z10, Z11\n",
"7.5 Z4, Z5, Z6, Z8, Z10, Z11\n",
"-7.5 Z6, Z7, Z9, Z10\n",
"-7.5 Z6, Z9, Z10, Z11\n",
"-7.5 Z7, Z8, Z9, Z10\n",
"-7.5 Z7, Z8, Z10, Z11\n",
"-7.5 Z6, Z7, Z8, Z11\n",
"-7.5 Z6, Z8, Z9, Z11\n",
"20.0 Z1, Z11, Z12\n",
"20.0 Z0, Z10, Z12\n",
"20.0 Z0, Z1, Z10, Z11, Z12\n",
"-25.0 Z3, Z11, Z12\n",
"-25.0 Z2, Z10, Z12\n",
"-25.0 Z2, Z3, Z10, Z11, Z12\n",
"20.0 Z5, Z11, Z12\n",
"20.0 Z4, Z10, Z12\n",
"20.0 Z4, Z5, Z10, Z11, Z12\n",
"-25.0 Z7, Z11, Z12\n",
"-25.0 Z6, Z10, Z12\n",
"-25.0 Z6, Z7, Z10, Z11, Z12\n",
"20.0 Z9, Z11, Z12\n",
"20.0 Z8, Z10, Z12\n",
"20.0 Z8, Z9, Z10, Z11, Z12\n",
"2.5 Z0, Z1, Z3, Z8, Z12\n",
"2.5 Z0, Z1, Z3, Z10, Z12\n",
"2.5 Z0, Z3, Z8, Z9, Z12\n",
"2.5 Z0, Z3, Z10, Z11, Z12\n",
"2.5 Z1, Z2, Z3, Z8, Z12\n",
"2.5 Z1, Z2, Z3, Z10, Z12\n",
"2.5 Z1, Z2, Z8, Z9, Z12\n",
"2.5 Z1, Z2, Z10, Z11, Z12\n",
"7.5 Z1, Z3, Z5, Z9, Z12\n",
"-7.5 Z1, Z3, Z5, Z11, Z12\n",
"2.5 Z1, Z3, Z4, Z8, Z12\n",
"-2.5 Z1, Z3, Z4, Z10, Z12\n",
"2.5 Z1, Z3, Z4, Z5, Z8, Z9, Z12\n",
"-2.5 Z1, Z3, Z4, Z5, Z10, Z11, Z12\n",
"-7.5 Z1, Z3, Z7, Z9, Z12\n",
"7.5 Z1, Z3, Z7, Z11, Z12\n",
"-2.5 Z1, Z3, Z6, Z8, Z12\n",
"2.5 Z1, Z3, Z6, Z10, Z12\n",
"-2.5 Z1, Z3, Z6, Z7, Z8, Z9, Z12\n",
"2.5 Z1, Z3, Z6, Z7, Z10, Z11, Z12\n",
"-7.5 Z1, Z3, Z9, Z11, Z12\n",
"-2.5 Z1, Z3, Z8, Z10, Z12\n",
"-2.5 Z1, Z3, Z8, Z9, Z10, Z11, Z12\n",
"-7.5 Z0, Z1, Z5, Z8, Z12\n",
"2.5 Z0, Z1, Z5, Z10, Z12\n",
"-7.5 Z0, Z5, Z8, Z9, Z12\n",
"2.5 Z0, Z5, Z10, Z11, Z12\n",
"2.5 Z1, Z2, Z5, Z8, Z12\n",
"-2.5 Z1, Z2, Z5, Z10, Z12\n",
"2.5 Z1, Z2, Z3, Z5, Z8, Z9, Z12\n",
"-2.5 Z1, Z2, Z3, Z5, Z10, Z11, Z12\n",
"-7.5 Z1, Z4, Z5, Z8, Z12\n",
"2.5 Z1, Z4, Z5, Z10, Z12\n",
"-7.5 Z1, Z4, Z8, Z9, Z12\n",
"2.5 Z1, Z4, Z10, Z11, Z12\n",
"7.5 Z1, Z5, Z7, Z9, Z12\n",
"-7.5 Z1, Z5, Z7, Z11, Z12\n",
"2.5 Z1, Z5, Z6, Z8, Z12\n",
"-2.5 Z1, Z5, Z6, Z10, Z12\n",
"2.5 Z1, Z5, Z6, Z7, Z8, Z9, Z12\n",
"-2.5 Z1, Z5, Z6, Z7, Z10, Z11, Z12\n",
"7.5 Z1, Z5, Z9, Z11, Z12\n",
"2.5 Z1, Z5, Z8, Z10, Z12\n",
"2.5 Z1, Z5, Z8, Z9, Z10, Z11, Z12\n",
"2.5 Z0, Z1, Z7, Z8, Z12\n",
"2.5 Z0, Z1, Z7, Z10, Z12\n",
"2.5 Z0, Z7, Z8, Z9, Z12\n",
"2.5 Z0, Z7, Z10, Z11, Z12\n",
"-2.5 Z1, Z2, Z7, Z8, Z12\n",
"2.5 Z1, Z2, Z7, Z10, Z12\n",
"-2.5 Z1, Z2, Z3, Z7, Z8, Z9, Z12\n",
"2.5 Z1, Z2, Z3, Z7, Z10, Z11, Z12\n",
"2.5 Z1, Z4, Z7, Z8, Z12\n",
"-2.5 Z1, Z4, Z7, Z10, Z12\n",
"2.5 Z1, Z4, Z5, Z7, Z8, Z9, Z12\n",
"-2.5 Z1, Z4, Z5, Z7, Z10, Z11, Z12\n",
"2.5 Z1, Z6, Z7, Z8, Z12\n",
"2.5 Z1, Z6, Z7, Z10, Z12\n",
"2.5 Z1, Z6, Z8, Z9, Z12\n",
"2.5 Z1, Z6, Z10, Z11, Z12\n",
"-7.5 Z1, Z7, Z9, Z11, Z12\n",
"-2.5 Z1, Z7, Z8, Z10, Z12\n",
"-2.5 Z1, Z7, Z8, Z9, Z10, Z11, Z12\n",
"2.5 Z0, Z1, Z2, Z9, Z12\n",
"-7.5 Z0, Z1, Z4, Z9, Z12\n",
"2.5 Z0, Z1, Z6, Z9, Z12\n",
"2.5 Z0, Z1, Z9, Z10, Z12\n",
"2.5 Z0, Z2, Z3, Z9, Z12\n",
"-7.5 Z0, Z4, Z5, Z9, Z12\n",
"2.5 Z0, Z6, Z7, Z9, Z12\n",
"2.5 Z0, Z9, Z10, Z11, Z12\n",
"2.5 Z1, Z2, Z4, Z9, Z12\n",
"-2.5 Z1, Z2, Z6, Z9, Z12\n",
"-2.5 Z1, Z2, Z9, Z10, Z12\n",
"2.5 Z1, Z2, Z3, Z4, Z5, Z9, Z12\n",
"-2.5 Z1, Z2, Z3, Z6, Z7, Z9, Z12\n",
"-2.5 Z1, Z2, Z3, Z9, Z10, Z11, Z12\n",
"2.5 Z1, Z4, Z6, Z9, Z12\n",
"2.5 Z1, Z4, Z9, Z10, Z12\n",
"2.5 Z1, Z4, Z5, Z6, Z7, Z9, Z12\n",
"2.5 Z1, Z4, Z5, Z9, Z10, Z11, Z12\n",
"-2.5 Z1, Z6, Z9, Z10, Z12\n",
"-2.5 Z1, Z6, Z7, Z9, Z10, Z11, Z12\n",
"2.5 Z1, Z8, Z9, Z10, Z12\n",
"2.5 Z1, Z8, Z10, Z11, Z12\n",
"2.5 Z0, Z1, Z2, Z11, Z12\n",
"2.5 Z0, Z1, Z4, Z11, Z12\n",
"2.5 Z0, Z1, Z6, Z11, Z12\n",
"2.5 Z0, Z1, Z8, Z11, Z12\n",
"2.5 Z0, Z2, Z3, Z11, Z12\n",
"2.5 Z0, Z4, Z5, Z11, Z12\n",
"2.5 Z0, Z6, Z7, Z11, Z12\n",
"2.5 Z0, Z8, Z9, Z11, Z12\n",
"-2.5 Z1, Z2, Z4, Z11, Z12\n",
"2.5 Z1, Z2, Z6, Z11, Z12\n",
"-2.5 Z1, Z2, Z8, Z11, Z12\n",
"-2.5 Z1, Z2, Z3, Z4, Z5, Z11, Z12\n",
"2.5 Z1, Z2, Z3, Z6, Z7, Z11, Z12\n",
"-2.5 Z1, Z2, Z3, Z8, Z9, Z11, Z12\n",
"-2.5 Z1, Z4, Z6, Z11, Z12\n",
"2.5 Z1, Z4, Z8, Z11, Z12\n",
"-2.5 Z1, Z4, Z5, Z6, Z7, Z11, Z12\n",
"2.5 Z1, Z4, Z5, Z8, Z9, Z11, Z12\n",
"-2.5 Z1, Z6, Z8, Z11, Z12\n",
"-2.5 Z1, Z6, Z7, Z8, Z9, Z11, Z12\n",
"2.5 Z0, Z2, Z5, Z9, Z12\n",
"-2.5 Z0, Z2, Z5, Z11, Z12\n",
"7.5 Z0, Z2, Z4, Z8, Z12\n",
"-7.5 Z0, Z2, Z4, Z10, Z12\n",
"2.5 Z0, Z2, Z4, Z5, Z8, Z9, Z12\n",
"-2.5 Z0, Z2, Z4, Z5, Z10, Z11, Z12\n",
"-2.5 Z0, Z2, Z7, Z9, Z12\n",
"2.5 Z0, Z2, Z7, Z11, Z12\n",
"-7.5 Z0, Z2, Z6, Z8, Z12\n",
"7.5 Z0, Z2, Z6, Z10, Z12\n",
"-2.5 Z0, Z2, Z6, Z7, Z8, Z9, Z12\n",
"2.5 Z0, Z2, Z6, Z7, Z10, Z11, Z12\n",
"-2.5 Z0, Z2, Z9, Z11, Z12\n",
"-7.5 Z0, Z2, Z8, Z10, Z12\n",
"-2.5 Z0, Z2, Z8, Z9, Z10, Z11, Z12\n",
"2.5 Z0, Z3, Z4, Z9, Z12\n",
"-2.5 Z0, Z3, Z4, Z11, Z12\n",
"2.5 Z0, Z2, Z3, Z4, Z8, Z9, Z12\n",
"-2.5 Z0, Z2, Z3, Z4, Z10, Z11, Z12\n",
"2.5 Z0, Z4, Z7, Z9, Z12\n",
"-2.5 Z0, Z4, Z7, Z11, Z12\n",
"7.5 Z0, Z4, Z6, Z8, Z12\n",
"-7.5 Z0, Z4, Z6, Z10, Z12\n",
"2.5 Z0, Z4, Z6, Z7, Z8, Z9, Z12\n",
"-2.5 Z0, Z4, Z6, Z7, Z10, Z11, Z12\n",
"2.5 Z0, Z4, Z9, Z11, Z12\n",
"7.5 Z0, Z4, Z8, Z10, Z12\n",
"2.5 Z0, Z4, Z8, Z9, Z10, Z11, Z12\n",
"-2.5 Z0, Z3, Z6, Z9, Z12\n",
"2.5 Z0, Z3, Z6, Z11, Z12\n",
"-2.5 Z0, Z2, Z3, Z6, Z8, Z9, Z12\n",
"2.5 Z0, Z2, Z3, Z6, Z10, Z11, Z12\n",
"2.5 Z0, Z5, Z6, Z9, Z12\n",
"-2.5 Z0, Z5, Z6, Z11, Z12\n",
"2.5 Z0, Z4, Z5, Z6, Z8, Z9, Z12\n",
"-2.5 Z0, Z4, Z5, Z6, Z10, Z11, Z12\n",
"-2.5 Z0, Z6, Z9, Z11, Z12\n",
"-7.5 Z0, Z6, Z8, Z10, Z12\n",
"-2.5 Z0, Z6, Z8, Z9, Z10, Z11, Z12\n",
"2.5 Z0, Z3, Z5, Z8, Z12\n",
"-2.5 Z0, Z3, Z7, Z8, Z12\n",
"-2.5 Z0, Z3, Z8, Z11, Z12\n",
"2.5 Z0, Z2, Z3, Z4, Z5, Z8, Z12\n",
"-2.5 Z0, Z2, Z3, Z6, Z7, Z8, Z12\n",
"-2.5 Z0, Z2, Z3, Z8, Z10, Z11, Z12\n",
"2.5 Z0, Z5, Z7, Z8, Z12\n",
"2.5 Z0, Z5, Z8, Z11, Z12\n",
"2.5 Z0, Z4, Z5, Z6, Z7, Z8, Z12\n",
"2.5 Z0, Z4, Z5, Z8, Z10, Z11, Z12\n",
"-2.5 Z0, Z7, Z8, Z11, Z12\n",
"-2.5 Z0, Z6, Z7, Z8, Z10, Z11, Z12\n",
"-2.5 Z0, Z3, Z5, Z10, Z12\n",
"2.5 Z0, Z3, Z7, Z10, Z12\n",
"-2.5 Z0, Z3, Z9, Z10, Z12\n",
"-2.5 Z0, Z2, Z3, Z4, Z5, Z10, Z12\n",
"2.5 Z0, Z2, Z3, Z6, Z7, Z10, Z12\n",
"-2.5 Z0, Z2, Z3, Z8, Z9, Z10, Z12\n",
"-2.5 Z0, Z5, Z7, Z10, Z12\n",
"2.5 Z0, Z5, Z9, Z10, Z12\n",
"-2.5 Z0, Z4, Z5, Z6, Z7, Z10, Z12\n",
"2.5 Z0, Z4, Z5, Z8, Z9, Z10, Z12\n",
"-2.5 Z0, Z7, Z9, Z10, Z12\n",
"-2.5 Z0, Z6, Z7, Z8, Z9, Z10, Z12\n",
"2.5 Z0, Z1, Z2, Z3, Z5, Z9, Z12\n",
"-2.5 Z0, Z1, Z2, Z3, Z5, Z11, Z12\n",
"2.5 Z0, Z1, Z2, Z3, Z4, Z8, Z12\n",
"-2.5 Z0, Z1, Z2, Z3, Z4, Z10, Z12\n",
"7.5 Z0, Z1, Z2, Z3, Z4, Z5, Z8, Z9, Z12\n",
"-7.5 Z0, Z1, Z2, Z3, Z4, Z5, Z10, Z11, Z12\n",
"-2.5 Z0, Z1, Z2, Z3, Z7, Z9, Z12\n",
"2.5 Z0, Z1, Z2, Z3, Z7, Z11, Z12\n",
"-2.5 Z0, Z1, Z2, Z3, Z6, Z8, Z12\n",
"2.5 Z0, Z1, Z2, Z3, Z6, Z10, Z12\n",
"-7.5 Z0, Z1, Z2, Z3, Z6, Z7, Z8, Z9, Z12\n",
"7.5 Z0, Z1, Z2, Z3, Z6, Z7, Z10, Z11, Z12\n",
"-2.5 Z0, Z1, Z2, Z3, Z9, Z11, Z12\n",
"-2.5 Z0, Z1, Z2, Z3, Z8, Z10, Z12\n",
"-7.5 Z0, Z1, Z2, Z3, Z8, Z9, Z10, Z11, Z12\n",
"2.5 Z0, Z1, Z3, Z4, Z5, Z9, Z12\n",
"-2.5 Z0, Z1, Z3, Z4, Z5, Z11, Z12\n",
"2.5 Z0, Z1, Z2, Z4, Z5, Z8, Z12\n",
"-2.5 Z0, Z1, Z2, Z4, Z5, Z10, Z12\n",
"2.5 Z0, Z1, Z4, Z5, Z7, Z9, Z12\n",
"-2.5 Z0, Z1, Z4, Z5, Z7, Z11, Z12\n",
"2.5 Z0, Z1, Z4, Z5, Z6, Z8, Z12\n",
"-2.5 Z0, Z1, Z4, Z5, Z6, Z10, Z12\n",
"7.5 Z0, Z1, Z4, Z5, Z6, Z7, Z8, Z9, Z12\n",
"-7.5 Z0, Z1, Z4, Z5, Z6, Z7, Z10, Z11, Z12\n",
"2.5 Z0, Z1, Z4, Z5, Z9, Z11, Z12\n",
"2.5 Z0, Z1, Z4, Z5, Z8, Z10, Z12\n",
"7.5 Z0, Z1, Z4, Z5, Z8, Z9, Z10, Z11, Z12\n",
"-2.5 Z0, Z1, Z3, Z6, Z7, Z9, Z12\n",
"2.5 Z0, Z1, Z3, Z6, Z7, Z11, Z12\n",
"-2.5 Z0, Z1, Z2, Z6, Z7, Z8, Z12\n",
"2.5 Z0, Z1, Z2, Z6, Z7, Z10, Z12\n",
"2.5 Z0, Z1, Z5, Z6, Z7, Z9, Z12\n",
"-2.5 Z0, Z1, Z5, Z6, Z7, Z11, Z12\n",
"2.5 Z0, Z1, Z4, Z6, Z7, Z8, Z12\n",
"-2.5 Z0, Z1, Z4, Z6, Z7, Z10, Z12\n",
"-2.5 Z0, Z1, Z6, Z7, Z9, Z11, Z12\n",
"-2.5 Z0, Z1, Z6, Z7, Z8, Z10, Z12\n",
"-7.5 Z0, Z1, Z6, Z7, Z8, Z9, Z10, Z11, Z12\n",
"2.5 Z0, Z1, Z3, Z5, Z8, Z9, Z12\n",
"-2.5 Z0, Z1, Z3, Z7, Z8, Z9, Z12\n",
"-2.5 Z0, Z1, Z3, Z8, Z9, Z11, Z12\n",
"2.5 Z0, Z1, Z2, Z4, Z8, Z9, Z12\n",
"-2.5 Z0, Z1, Z2, Z6, Z8, Z9, Z12\n",
"-2.5 Z0, Z1, Z2, Z8, Z9, Z10, Z12\n",
"2.5 Z0, Z1, Z5, Z7, Z8, Z9, Z12\n",
"2.5 Z0, Z1, Z5, Z8, Z9, Z11, Z12\n",
"2.5 Z0, Z1, Z4, Z6, Z8, Z9, Z12\n",
"2.5 Z0, Z1, Z4, Z8, Z9, Z10, Z12\n",
"-2.5 Z0, Z1, Z7, Z8, Z9, Z11, Z12\n",
"-2.5 Z0, Z1, Z6, Z8, Z9, Z10, Z12\n",
"-2.5 Z0, Z1, Z3, Z5, Z10, Z11, Z12\n",
"2.5 Z0, Z1, Z3, Z7, Z10, Z11, Z12\n",
"-2.5 Z0, Z1, Z3, Z9, Z10, Z11, Z12\n",
"-2.5 Z0, Z1, Z2, Z4, Z10, Z11, Z12\n",
"2.5 Z0, Z1, Z2, Z6, Z10, Z11, Z12\n",
"-2.5 Z0, Z1, Z2, Z8, Z10, Z11, Z12\n",
"-2.5 Z0, Z1, Z5, Z7, Z10, Z11, Z12\n",
"2.5 Z0, Z1, Z5, Z9, Z10, Z11, Z12\n",
"-2.5 Z0, Z1, Z4, Z6, Z10, Z11, Z12\n",
"2.5 Z0, Z1, Z4, Z8, Z10, Z11, Z12\n",
"-2.5 Z0, Z1, Z7, Z9, Z10, Z11, Z12\n",
"-2.5 Z0, Z1, Z6, Z8, Z10, Z11, Z12\n",
"2.5 Z2, Z3, Z5, Z10, Z12\n",
"2.5 Z2, Z5, Z10, Z11, Z12\n",
"2.5 Z3, Z4, Z5, Z10, Z12\n",
"2.5 Z3, Z4, Z10, Z11, Z12\n",
"7.5 Z3, Z5, Z7, Z11, Z12\n",
"2.5 Z3, Z5, Z6, Z10, Z12\n",
"2.5 Z3, Z5, Z6, Z7, Z10, Z11, Z12\n",
"-7.5 Z3, Z5, Z9, Z11, Z12\n",
"-2.5 Z3, Z5, Z8, Z10, Z12\n",
"-2.5 Z3, Z5, Z8, Z9, Z10, Z11, Z12\n",
"-7.5 Z2, Z3, Z7, Z10, Z12\n",
"-7.5 Z2, Z7, Z10, Z11, Z12\n",
"2.5 Z3, Z4, Z7, Z10, Z12\n",
"2.5 Z3, Z4, Z5, Z7, Z10, Z11, Z12\n",
"-7.5 Z3, Z6, Z7, Z10, Z12\n",
"-7.5 Z3, Z6, Z10, Z11, Z12\n",
"7.5 Z3, Z7, Z9, Z11, Z12\n",
"2.5 Z3, Z7, Z8, Z10, Z12\n",
"2.5 Z3, Z7, Z8, Z9, Z10, Z11, Z12\n",
"2.5 Z2, Z3, Z9, Z10, Z12\n",
"2.5 Z2, Z9, Z10, Z11, Z12\n",
"-2.5 Z3, Z4, Z9, Z10, Z12\n",
"-2.5 Z3, Z4, Z5, Z9, Z10, Z11, Z12\n",
"2.5 Z3, Z6, Z9, Z10, Z12\n",
"2.5 Z3, Z6, Z7, Z9, Z10, Z11, Z12\n",
"2.5 Z3, Z8, Z9, Z10, Z12\n",
"2.5 Z3, Z8, Z10, Z11, Z12\n",
"2.5 Z2, Z3, Z4, Z11, Z12\n",
"-7.5 Z2, Z3, Z6, Z11, Z12\n",
"2.5 Z2, Z3, Z8, Z11, Z12\n",
"2.5 Z2, Z4, Z5, Z11, Z12\n",
"-7.5 Z2, Z6, Z7, Z11, Z12\n",
"2.5 Z2, Z8, Z9, Z11, Z12\n",
"2.5 Z3, Z4, Z6, Z11, Z12\n",
"-2.5 Z3, Z4, Z8, Z11, Z12\n",
"2.5 Z3, Z4, Z5, Z6, Z7, Z11, Z12\n",
"-2.5 Z3, Z4, Z5, Z8, Z9, Z11, Z12\n",
"2.5 Z3, Z6, Z8, Z11, Z12\n",
"2.5 Z3, Z6, Z7, Z8, Z9, Z11, Z12\n",
"2.5 Z2, Z4, Z7, Z11, Z12\n",
"7.5 Z2, Z4, Z6, Z10, Z12\n",
"2.5 Z2, Z4, Z6, Z7, Z10, Z11, Z12\n",
"-2.5 Z2, Z4, Z9, Z11, Z12\n",
"-7.5 Z2, Z4, Z8, Z10, Z12\n",
"-2.5 Z2, Z4, Z8, Z9, Z10, Z11, Z12\n",
"2.5 Z2, Z5, Z6, Z11, Z12\n",
"2.5 Z2, Z4, Z5, Z6, Z10, Z11, Z12\n",
"2.5 Z2, Z6, Z9, Z11, Z12\n",
"7.5 Z2, Z6, Z8, Z10, Z12\n",
"2.5 Z2, Z6, Z8, Z9, Z10, Z11, Z12\n",
"-2.5 Z2, Z5, Z8, Z11, Z12\n",
"-2.5 Z2, Z4, Z5, Z8, Z10, Z11, Z12\n",
"2.5 Z2, Z7, Z8, Z11, Z12\n",
"2.5 Z2, Z6, Z7, Z8, Z10, Z11, Z12\n",
"2.5 Z2, Z5, Z7, Z10, Z12\n",
"-2.5 Z2, Z5, Z9, Z10, Z12\n",
"2.5 Z2, Z4, Z5, Z6, Z7, Z10, Z12\n",
"-2.5 Z2, Z4, Z5, Z8, Z9, Z10, Z12\n",
"2.5 Z2, Z7, Z9, Z10, Z12\n",
"2.5 Z2, Z6, Z7, Z8, Z9, Z10, Z12\n",
"2.5 Z2, Z3, Z4, Z5, Z7, Z11, Z12\n",
"2.5 Z2, Z3, Z4, Z5, Z6, Z10, Z12\n",
"7.5 Z2, Z3, Z4, Z5, Z6, Z7, Z10, Z11, Z12\n",
"-2.5 Z2, Z3, Z4, Z5, Z9, Z11, Z12\n",
"-2.5 Z2, Z3, Z4, Z5, Z8, Z10, Z12\n",
"-7.5 Z2, Z3, Z4, Z5, Z8, Z9, Z10, Z11, Z12\n",
"2.5 Z2, Z3, Z5, Z6, Z7, Z11, Z12\n",
"2.5 Z2, Z3, Z4, Z6, Z7, Z10, Z12\n",
"2.5 Z2, Z3, Z6, Z7, Z9, Z11, Z12\n",
"2.5 Z2, Z3, Z6, Z7, Z8, Z10, Z12\n",
"7.5 Z2, Z3, Z6, Z7, Z8, Z9, Z10, Z11, Z12\n",
"-2.5 Z2, Z3, Z5, Z8, Z9, Z11, Z12\n",
"-2.5 Z2, Z3, Z4, Z8, Z9, Z10, Z12\n",
"2.5 Z2, Z3, Z7, Z8, Z9, Z11, Z12\n",
"2.5 Z2, Z3, Z6, Z8, Z9, Z10, Z12\n",
"2.5 Z2, Z3, Z5, Z7, Z10, Z11, Z12\n",
"-2.5 Z2, Z3, Z5, Z9, Z10, Z11, Z12\n",
"2.5 Z2, Z3, Z4, Z6, Z10, Z11, Z12\n",
"-2.5 Z2, Z3, Z4, Z8, Z10, Z11, Z12\n",
"2.5 Z2, Z3, Z7, Z9, Z10, Z11, Z12\n",
"2.5 Z2, Z3, Z6, Z8, Z10, Z11, Z12\n",
"2.5 Z4, Z5, Z7, Z10, Z12\n",
"2.5 Z4, Z7, Z10, Z11, Z12\n",
"2.5 Z5, Z6, Z7, Z10, Z12\n",
"2.5 Z5, Z6, Z10, Z11, Z12\n",
"-7.5 Z5, Z7, Z9, Z11, Z12\n",
"-2.5 Z5, Z7, Z8, Z10, Z12\n",
"-2.5 Z5, Z7, Z8, Z9, Z10, Z11, Z12\n",
"2.5 Z4, Z5, Z9, Z10, Z12\n",
"2.5 Z4, Z9, Z10, Z11, Z12\n",
"-2.5 Z5, Z6, Z9, Z10, Z12\n",
"-2.5 Z5, Z6, Z7, Z9, Z10, Z11, Z12\n",
"2.5 Z5, Z8, Z9, Z10, Z12\n",
"2.5 Z5, Z8, Z10, Z11, Z12\n",
"2.5 Z4, Z5, Z6, Z11, Z12\n",
"2.5 Z4, Z5, Z8, Z11, Z12\n",
"2.5 Z4, Z6, Z7, Z11, Z12\n",
"2.5 Z4, Z8, Z9, Z11, Z12\n",
"-2.5 Z5, Z6, Z8, Z11, Z12\n",
"-2.5 Z5, Z6, Z7, Z8, Z9, Z11, Z12\n",
"-2.5 Z4, Z6, Z9, Z11, Z12\n",
"-7.5 Z4, Z6, Z8, Z10, Z12\n",
"-2.5 Z4, Z6, Z8, Z9, Z10, Z11, Z12\n",
"-2.5 Z4, Z7, Z8, Z11, Z12\n",
"-2.5 Z4, Z6, Z7, Z8, Z10, Z11, Z12\n",
"-2.5 Z4, Z7, Z9, Z10, Z12\n",
"-2.5 Z4, Z6, Z7, Z8, Z9, Z10, Z12\n",
"-2.5 Z4, Z5, Z6, Z7, Z9, Z11, Z12\n",
"-2.5 Z4, Z5, Z6, Z7, Z8, Z10, Z12\n",
"-7.5 Z4, Z5, Z6, Z7, Z8, Z9, Z10, Z11, Z12\n",
"-2.5 Z4, Z5, Z7, Z8, Z9, Z11, Z12\n",
"-2.5 Z4, Z5, Z6, Z8, Z9, Z10, Z12\n",
"-2.5 Z4, Z5, Z7, Z9, Z10, Z11, Z12\n",
"-2.5 Z4, Z5, Z6, Z8, Z10, Z11, Z12\n",
"2.5 Z6, Z7, Z9, Z10, Z12\n",
"2.5 Z6, Z9, Z10, Z11, Z12\n",
"2.5 Z7, Z8, Z9, Z10, Z12\n",
"2.5 Z7, Z8, Z10, Z11, Z12\n",
"2.5 Z6, Z7, Z8, Z11, Z12\n",
"2.5 Z6, Z8, Z9, Z11, Z12\n",
"-157.34050000000002 Z13\n",
"30.0 Z3, Z5, Z13\n",
"-40.0 Z3, Z7, Z13\n",
"30.0 Z3, Z9, Z13\n",
"-27.5 Z3, Z11, Z13\n",
"30.0 Z2, Z4, Z13\n",
"-40.0 Z2, Z6, Z13\n",
"30.0 Z2, Z8, Z13\n",
"-27.5 Z2, Z10, Z13\n",
"30.0 Z2, Z3, Z4, Z5, Z13\n",
"-40.0 Z2, Z3, Z6, Z7, Z13\n",
"30.0 Z2, Z3, Z8, Z9, Z13\n",
"-27.5 Z2, Z3, Z10, Z11, Z13\n",
"37.5 Z5, Z7, Z13\n",
"-52.5 Z5, Z9, Z13\n",
"30.0 Z5, Z11, Z13\n",
"37.5 Z4, Z6, Z13\n",
"-52.5 Z4, Z8, Z13\n",
"30.0 Z4, Z10, Z13\n",
"37.5 Z4, Z5, Z6, Z7, Z13\n",
"-52.5 Z4, Z5, Z8, Z9, Z13\n",
"30.0 Z4, Z5, Z10, Z11, Z13\n",
"37.5 Z7, Z9, Z13\n",
"-40.0 Z7, Z11, Z13\n",
"37.5 Z6, Z8, Z13\n",
"-40.0 Z6, Z10, Z13\n",
"37.5 Z6, Z7, Z8, Z9, Z13\n",
"-40.0 Z6, Z7, Z10, Z11, Z13\n",
"30.0 Z9, Z11, Z13\n",
"30.0 Z8, Z10, Z13\n",
"30.0 Z8, Z9, Z10, Z11, Z13\n",
"20.0 Z1, Z3, Z13\n",
"-25.0 Z1, Z5, Z13\n",
"20.0 Z1, Z7, Z13\n",
"-25.0 Z1, Z9, Z13\n",
"20.0 Z1, Z11, Z13\n",
"20.0 Z0, Z2, Z13\n",
"-25.0 Z0, Z4, Z13\n",
"20.0 Z0, Z6, Z13\n",
"-25.0 Z0, Z8, Z13\n",
"20.0 Z0, Z10, Z13\n",
"20.0 Z0, Z1, Z2, Z3, Z13\n",
"-25.0 Z0, Z1, Z4, Z5, Z13\n",
"20.0 Z0, Z1, Z6, Z7, Z13\n",
"-25.0 Z0, Z1, Z8, Z9, Z13\n",
"20.0 Z0, Z1, Z10, Z11, Z13\n",
"2.5 Z0, Z1, Z3, Z4, Z13\n",
"2.5 Z0, Z1, Z3, Z6, Z13\n",
"2.5 Z0, Z1, Z3, Z8, Z13\n",
"2.5 Z0, Z1, Z3, Z10, Z13\n",
"2.5 Z0, Z3, Z4, Z5, Z13\n",
"2.5 Z0, Z3, Z6, Z7, Z13\n",
"2.5 Z0, Z3, Z8, Z9, Z13\n",
"2.5 Z0, Z3, Z10, Z11, Z13\n",
"2.5 Z1, Z2, Z3, Z4, Z13\n",
"2.5 Z1, Z2, Z3, Z6, Z13\n",
"2.5 Z1, Z2, Z3, Z8, Z13\n",
"2.5 Z1, Z2, Z3, Z10, Z13\n",
"2.5 Z1, Z2, Z4, Z5, Z13\n",
"2.5 Z1, Z2, Z6, Z7, Z13\n",
"2.5 Z1, Z2, Z8, Z9, Z13\n",
"2.5 Z1, Z2, Z10, Z11, Z13\n",
"-7.5 Z1, Z3, Z5, Z7, Z13\n",
"7.5 Z1, Z3, Z5, Z9, Z13\n",
"-7.5 Z1, Z3, Z5, Z11, Z13\n",
"-2.5 Z1, Z3, Z4, Z6, Z13\n",
"2.5 Z1, Z3, Z4, Z8, Z13\n",
"-2.5 Z1, Z3, Z4, Z10, Z13\n",
"-2.5 Z1, Z3, Z4, Z5, Z6, Z7, Z13\n",
"2.5 Z1, Z3, Z4, Z5, Z8, Z9, Z13\n",
"-2.5 Z1, Z3, Z4, Z5, Z10, Z11, Z13\n",
"-7.5 Z1, Z3, Z7, Z9, Z13\n",
"7.5 Z1, Z3, Z7, Z11, Z13\n",
"-2.5 Z1, Z3, Z6, Z8, Z13\n",
"2.5 Z1, Z3, Z6, Z10, Z13\n",
"-2.5 Z1, Z3, Z6, Z7, Z8, Z9, Z13\n",
"2.5 Z1, Z3, Z6, Z7, Z10, Z11, Z13\n",
"-7.5 Z1, Z3, Z9, Z11, Z13\n",
"-2.5 Z1, Z3, Z8, Z10, Z13\n",
"-2.5 Z1, Z3, Z8, Z9, Z10, Z11, Z13\n",
"2.5 Z0, Z1, Z2, Z5, Z13\n",
"2.5 Z0, Z1, Z5, Z6, Z13\n",
"-7.5 Z0, Z1, Z5, Z8, Z13\n",
"2.5 Z0, Z1, Z5, Z10, Z13\n",
"2.5 Z0, Z2, Z3, Z5, Z13\n",
"2.5 Z0, Z5, Z6, Z7, Z13\n",
"-7.5 Z0, Z5, Z8, Z9, Z13\n",
"2.5 Z0, Z5, Z10, Z11, Z13\n",
"-2.5 Z1, Z2, Z5, Z6, Z13\n",
"2.5 Z1, Z2, Z5, Z8, Z13\n",
"-2.5 Z1, Z2, Z5, Z10, Z13\n",
"-2.5 Z1, Z2, Z3, Z5, Z6, Z7, Z13\n",
"2.5 Z1, Z2, Z3, Z5, Z8, Z9, Z13\n",
"-2.5 Z1, Z2, Z3, Z5, Z10, Z11, Z13\n",
"2.5 Z1, Z4, Z5, Z6, Z13\n",
"-7.5 Z1, Z4, Z5, Z8, Z13\n",
"2.5 Z1, Z4, Z5, Z10, Z13\n",
"2.5 Z1, Z4, Z6, Z7, Z13\n",
"-7.5 Z1, Z4, Z8, Z9, Z13\n",
"2.5 Z1, Z4, Z10, Z11, Z13\n",
"7.5 Z1, Z5, Z7, Z9, Z13\n",
"-7.5 Z1, Z5, Z7, Z11, Z13\n",
"2.5 Z1, Z5, Z6, Z8, Z13\n",
"-2.5 Z1, Z5, Z6, Z10, Z13\n",
"2.5 Z1, Z5, Z6, Z7, Z8, Z9, Z13\n",
"-2.5 Z1, Z5, Z6, Z7, Z10, Z11, Z13\n",
"7.5 Z1, Z5, Z9, Z11, Z13\n",
"2.5 Z1, Z5, Z8, Z10, Z13\n",
"2.5 Z1, Z5, Z8, Z9, Z10, Z11, Z13\n",
"2.5 Z0, Z1, Z2, Z7, Z13\n",
"2.5 Z0, Z1, Z4, Z7, Z13\n",
"2.5 Z0, Z1, Z7, Z8, Z13\n",
"2.5 Z0, Z1, Z7, Z10, Z13\n",
"2.5 Z0, Z2, Z3, Z7, Z13\n",
"2.5 Z0, Z4, Z5, Z7, Z13\n",
"2.5 Z0, Z7, Z8, Z9, Z13\n",
"2.5 Z0, Z7, Z10, Z11, Z13\n",
"-2.5 Z1, Z2, Z4, Z7, Z13\n",
"-2.5 Z1, Z2, Z7, Z8, Z13\n",
"2.5 Z1, Z2, Z7, Z10, Z13\n",
"-2.5 Z1, Z2, Z3, Z4, Z5, Z7, Z13\n",
"-2.5 Z1, Z2, Z3, Z7, Z8, Z9, Z13\n",
"2.5 Z1, Z2, Z3, Z7, Z10, Z11, Z13\n",
"2.5 Z1, Z4, Z7, Z8, Z13\n",
"-2.5 Z1, Z4, Z7, Z10, Z13\n",
"2.5 Z1, Z4, Z5, Z7, Z8, Z9, Z13\n",
"-2.5 Z1, Z4, Z5, Z7, Z10, Z11, Z13\n",
"2.5 Z1, Z6, Z7, Z8, Z13\n",
"2.5 Z1, Z6, Z7, Z10, Z13\n",
"2.5 Z1, Z6, Z8, Z9, Z13\n",
"2.5 Z1, Z6, Z10, Z11, Z13\n",
"-7.5 Z1, Z7, Z9, Z11, Z13\n",
"-2.5 Z1, Z7, Z8, Z10, Z13\n",
"-2.5 Z1, Z7, Z8, Z9, Z10, Z11, Z13\n",
"2.5 Z0, Z1, Z2, Z9, Z13\n",
"-7.5 Z0, Z1, Z4, Z9, Z13\n",
"2.5 Z0, Z1, Z6, Z9, Z13\n",
"2.5 Z0, Z1, Z9, Z10, Z13\n",
"2.5 Z0, Z2, Z3, Z9, Z13\n",
"-7.5 Z0, Z4, Z5, Z9, Z13\n",
"2.5 Z0, Z6, Z7, Z9, Z13\n",
"2.5 Z0, Z9, Z10, Z11, Z13\n",
"2.5 Z1, Z2, Z4, Z9, Z13\n",
"-2.5 Z1, Z2, Z6, Z9, Z13\n",
"-2.5 Z1, Z2, Z9, Z10, Z13\n",
"2.5 Z1, Z2, Z3, Z4, Z5, Z9, Z13\n",
"-2.5 Z1, Z2, Z3, Z6, Z7, Z9, Z13\n",
"-2.5 Z1, Z2, Z3, Z9, Z10, Z11, Z13\n",
"2.5 Z1, Z4, Z6, Z9, Z13\n",
"2.5 Z1, Z4, Z9, Z10, Z13\n",
"2.5 Z1, Z4, Z5, Z6, Z7, Z9, Z13\n",
"2.5 Z1, Z4, Z5, Z9, Z10, Z11, Z13\n",
"-2.5 Z1, Z6, Z9, Z10, Z13\n",
"-2.5 Z1, Z6, Z7, Z9, Z10, Z11, Z13\n",
"2.5 Z1, Z8, Z9, Z10, Z13\n",
"2.5 Z1, Z8, Z10, Z11, Z13\n",
"2.5 Z0, Z1, Z2, Z11, Z13\n",
"2.5 Z0, Z1, Z4, Z11, Z13\n",
"2.5 Z0, Z1, Z6, Z11, Z13\n",
"2.5 Z0, Z1, Z8, Z11, Z13\n",
"2.5 Z0, Z2, Z3, Z11, Z13\n",
"2.5 Z0, Z4, Z5, Z11, Z13\n",
"2.5 Z0, Z6, Z7, Z11, Z13\n",
"2.5 Z0, Z8, Z9, Z11, Z13\n",
"-2.5 Z1, Z2, Z4, Z11, Z13\n",
"2.5 Z1, Z2, Z6, Z11, Z13\n",
"-2.5 Z1, Z2, Z8, Z11, Z13\n",
"-2.5 Z1, Z2, Z3, Z4, Z5, Z11, Z13\n",
"2.5 Z1, Z2, Z3, Z6, Z7, Z11, Z13\n",
"-2.5 Z1, Z2, Z3, Z8, Z9, Z11, Z13\n",
"-2.5 Z1, Z4, Z6, Z11, Z13\n",
"2.5 Z1, Z4, Z8, Z11, Z13\n",
"-2.5 Z1, Z4, Z5, Z6, Z7, Z11, Z13\n",
"2.5 Z1, Z4, Z5, Z8, Z9, Z11, Z13\n",
"-2.5 Z1, Z6, Z8, Z11, Z13\n",
"-2.5 Z1, Z6, Z7, Z8, Z9, Z11, Z13\n",
"-2.5 Z0, Z2, Z5, Z7, Z13\n",
"2.5 Z0, Z2, Z5, Z9, Z13\n",
"-2.5 Z0, Z2, Z5, Z11, Z13\n",
"-7.5 Z0, Z2, Z4, Z6, Z13\n",
"7.5 Z0, Z2, Z4, Z8, Z13\n",
"-7.5 Z0, Z2, Z4, Z10, Z13\n",
"-2.5 Z0, Z2, Z4, Z5, Z6, Z7, Z13\n",
"2.5 Z0, Z2, Z4, Z5, Z8, Z9, Z13\n",
"-2.5 Z0, Z2, Z4, Z5, Z10, Z11, Z13\n",
"-2.5 Z0, Z2, Z7, Z9, Z13\n",
"2.5 Z0, Z2, Z7, Z11, Z13\n",
"-7.5 Z0, Z2, Z6, Z8, Z13\n",
"7.5 Z0, Z2, Z6, Z10, Z13\n",
"-2.5 Z0, Z2, Z6, Z7, Z8, Z9, Z13\n",
"2.5 Z0, Z2, Z6, Z7, Z10, Z11, Z13\n",
"-2.5 Z0, Z2, Z9, Z11, Z13\n",
"-7.5 Z0, Z2, Z8, Z10, Z13\n",
"-2.5 Z0, Z2, Z8, Z9, Z10, Z11, Z13\n",
"-2.5 Z0, Z3, Z4, Z7, Z13\n",
"2.5 Z0, Z3, Z4, Z9, Z13\n",
"-2.5 Z0, Z3, Z4, Z11, Z13\n",
"-2.5 Z0, Z2, Z3, Z4, Z6, Z7, Z13\n",
"2.5 Z0, Z2, Z3, Z4, Z8, Z9, Z13\n",
"-2.5 Z0, Z2, Z3, Z4, Z10, Z11, Z13\n",
"2.5 Z0, Z4, Z7, Z9, Z13\n",
"-2.5 Z0, Z4, Z7, Z11, Z13\n",
"7.5 Z0, Z4, Z6, Z8, Z13\n",
"-7.5 Z0, Z4, Z6, Z10, Z13\n",
"2.5 Z0, Z4, Z6, Z7, Z8, Z9, Z13\n",
"-2.5 Z0, Z4, Z6, Z7, Z10, Z11, Z13\n",
"2.5 Z0, Z4, Z9, Z11, Z13\n",
"7.5 Z0, Z4, Z8, Z10, Z13\n",
"2.5 Z0, Z4, Z8, Z9, Z10, Z11, Z13\n",
"-2.5 Z0, Z3, Z5, Z6, Z13\n",
"-2.5 Z0, Z3, Z6, Z9, Z13\n",
"2.5 Z0, Z3, Z6, Z11, Z13\n",
"-2.5 Z0, Z2, Z3, Z4, Z5, Z6, Z13\n",
"-2.5 Z0, Z2, Z3, Z6, Z8, Z9, Z13\n",
"2.5 Z0, Z2, Z3, Z6, Z10, Z11, Z13\n",
"2.5 Z0, Z5, Z6, Z9, Z13\n",
"-2.5 Z0, Z5, Z6, Z11, Z13\n",
"2.5 Z0, Z4, Z5, Z6, Z8, Z9, Z13\n",
"-2.5 Z0, Z4, Z5, Z6, Z10, Z11, Z13\n",
"-2.5 Z0, Z6, Z9, Z11, Z13\n",
"-7.5 Z0, Z6, Z8, Z10, Z13\n",
"-2.5 Z0, Z6, Z8, Z9, Z10, Z11, Z13\n",
"2.5 Z0, Z3, Z5, Z8, Z13\n",
"-2.5 Z0, Z3, Z7, Z8, Z13\n",
"-2.5 Z0, Z3, Z8, Z11, Z13\n",
"2.5 Z0, Z2, Z3, Z4, Z5, Z8, Z13\n",
"-2.5 Z0, Z2, Z3, Z6, Z7, Z8, Z13\n",
"-2.5 Z0, Z2, Z3, Z8, Z10, Z11, Z13\n",
"2.5 Z0, Z5, Z7, Z8, Z13\n",
"2.5 Z0, Z5, Z8, Z11, Z13\n",
"2.5 Z0, Z4, Z5, Z6, Z7, Z8, Z13\n",
"2.5 Z0, Z4, Z5, Z8, Z10, Z11, Z13\n",
"-2.5 Z0, Z7, Z8, Z11, Z13\n",
"-2.5 Z0, Z6, Z7, Z8, Z10, Z11, Z13\n",
"-2.5 Z0, Z3, Z5, Z10, Z13\n",
"2.5 Z0, Z3, Z7, Z10, Z13\n",
"-2.5 Z0, Z3, Z9, Z10, Z13\n",
"-2.5 Z0, Z2, Z3, Z4, Z5, Z10, Z13\n",
"2.5 Z0, Z2, Z3, Z6, Z7, Z10, Z13\n",
"-2.5 Z0, Z2, Z3, Z8, Z9, Z10, Z13\n",
"-2.5 Z0, Z5, Z7, Z10, Z13\n",
"2.5 Z0, Z5, Z9, Z10, Z13\n",
"-2.5 Z0, Z4, Z5, Z6, Z7, Z10, Z13\n",
"2.5 Z0, Z4, Z5, Z8, Z9, Z10, Z13\n",
"-2.5 Z0, Z7, Z9, Z10, Z13\n",
"-2.5 Z0, Z6, Z7, Z8, Z9, Z10, Z13\n",
"-2.5 Z0, Z1, Z2, Z3, Z5, Z7, Z13\n",
"2.5 Z0, Z1, Z2, Z3, Z5, Z9, Z13\n",
"-2.5 Z0, Z1, Z2, Z3, Z5, Z11, Z13\n",
"-2.5 Z0, Z1, Z2, Z3, Z4, Z6, Z13\n",
"2.5 Z0, Z1, Z2, Z3, Z4, Z8, Z13\n",
"-2.5 Z0, Z1, Z2, Z3, Z4, Z10, Z13\n",
"-7.5 Z0, Z1, Z2, Z3, Z4, Z5, Z6, Z7, Z13\n",
"7.5 Z0, Z1, Z2, Z3, Z4, Z5, Z8, Z9, Z13\n",
"-7.5 Z0, Z1, Z2, Z3, Z4, Z5, Z10, Z11, Z13\n",
"-2.5 Z0, Z1, Z2, Z3, Z7, Z9, Z13\n",
"2.5 Z0, Z1, Z2, Z3, Z7, Z11, Z13\n",
"-2.5 Z0, Z1, Z2, Z3, Z6, Z8, Z13\n",
"2.5 Z0, Z1, Z2, Z3, Z6, Z10, Z13\n",
"-7.5 Z0, Z1, Z2, Z3, Z6, Z7, Z8, Z9, Z13\n",
"7.5 Z0, Z1, Z2, Z3, Z6, Z7, Z10, Z11, Z13\n",
"-2.5 Z0, Z1, Z2, Z3, Z9, Z11, Z13\n",
"-2.5 Z0, Z1, Z2, Z3, Z8, Z10, Z13\n",
"-7.5 Z0, Z1, Z2, Z3, Z8, Z9, Z10, Z11, Z13\n",
"-2.5 Z0, Z1, Z3, Z4, Z5, Z7, Z13\n",
"2.5 Z0, Z1, Z3, Z4, Z5, Z9, Z13\n",
"-2.5 Z0, Z1, Z3, Z4, Z5, Z11, Z13\n",
"-2.5 Z0, Z1, Z2, Z4, Z5, Z6, Z13\n",
"2.5 Z0, Z1, Z2, Z4, Z5, Z8, Z13\n",
"-2.5 Z0, Z1, Z2, Z4, Z5, Z10, Z13\n",
"2.5 Z0, Z1, Z4, Z5, Z7, Z9, Z13\n",
"-2.5 Z0, Z1, Z4, Z5, Z7, Z11, Z13\n",
"2.5 Z0, Z1, Z4, Z5, Z6, Z8, Z13\n",
"-2.5 Z0, Z1, Z4, Z5, Z6, Z10, Z13\n",
"7.5 Z0, Z1, Z4, Z5, Z6, Z7, Z8, Z9, Z13\n",
"-7.5 Z0, Z1, Z4, Z5, Z6, Z7, Z10, Z11, Z13\n",
"2.5 Z0, Z1, Z4, Z5, Z9, Z11, Z13\n",
"2.5 Z0, Z1, Z4, Z5, Z8, Z10, Z13\n",
"7.5 Z0, Z1, Z4, Z5, Z8, Z9, Z10, Z11, Z13\n",
"-2.5 Z0, Z1, Z3, Z5, Z6, Z7, Z13\n",
"-2.5 Z0, Z1, Z3, Z6, Z7, Z9, Z13\n",
"2.5 Z0, Z1, Z3, Z6, Z7, Z11, Z13\n",
"-2.5 Z0, Z1, Z2, Z4, Z6, Z7, Z13\n",
"-2.5 Z0, Z1, Z2, Z6, Z7, Z8, Z13\n",
"2.5 Z0, Z1, Z2, Z6, Z7, Z10, Z13\n",
"2.5 Z0, Z1, Z5, Z6, Z7, Z9, Z13\n",
"-2.5 Z0, Z1, Z5, Z6, Z7, Z11, Z13\n",
"2.5 Z0, Z1, Z4, Z6, Z7, Z8, Z13\n",
"-2.5 Z0, Z1, Z4, Z6, Z7, Z10, Z13\n",
"-2.5 Z0, Z1, Z6, Z7, Z9, Z11, Z13\n",
"-2.5 Z0, Z1, Z6, Z7, Z8, Z10, Z13\n",
"-7.5 Z0, Z1, Z6, Z7, Z8, Z9, Z10, Z11, Z13\n",
"2.5 Z0, Z1, Z3, Z5, Z8, Z9, Z13\n",
"-2.5 Z0, Z1, Z3, Z7, Z8, Z9, Z13\n",
"-2.5 Z0, Z1, Z3, Z8, Z9, Z11, Z13\n",
"2.5 Z0, Z1, Z2, Z4, Z8, Z9, Z13\n",
"-2.5 Z0, Z1, Z2, Z6, Z8, Z9, Z13\n",
"-2.5 Z0, Z1, Z2, Z8, Z9, Z10, Z13\n",
"2.5 Z0, Z1, Z5, Z7, Z8, Z9, Z13\n",
"2.5 Z0, Z1, Z5, Z8, Z9, Z11, Z13\n",
"2.5 Z0, Z1, Z4, Z6, Z8, Z9, Z13\n",
"2.5 Z0, Z1, Z4, Z8, Z9, Z10, Z13\n",
"-2.5 Z0, Z1, Z7, Z8, Z9, Z11, Z13\n",
"-2.5 Z0, Z1, Z6, Z8, Z9, Z10, Z13\n",
"-2.5 Z0, Z1, Z3, Z5, Z10, Z11, Z13\n",
"2.5 Z0, Z1, Z3, Z7, Z10, Z11, Z13\n",
"-2.5 Z0, Z1, Z3, Z9, Z10, Z11, Z13\n",
"-2.5 Z0, Z1, Z2, Z4, Z10, Z11, Z13\n",
"2.5 Z0, Z1, Z2, Z6, Z10, Z11, Z13\n",
"-2.5 Z0, Z1, Z2, Z8, Z10, Z11, Z13\n",
"-2.5 Z0, Z1, Z5, Z7, Z10, Z11, Z13\n",
"2.5 Z0, Z1, Z5, Z9, Z10, Z11, Z13\n",
"-2.5 Z0, Z1, Z4, Z6, Z10, Z11, Z13\n",
"2.5 Z0, Z1, Z4, Z8, Z10, Z11, Z13\n",
"-2.5 Z0, Z1, Z7, Z9, Z10, Z11, Z13\n",
"-2.5 Z0, Z1, Z6, Z8, Z10, Z11, Z13\n",
"5.0 Z2, Z3, Z5, Z6, Z13\n",
"5.0 Z2, Z3, Z5, Z8, Z13\n",
"2.5 Z2, Z3, Z5, Z10, Z13\n",
"5.0 Z2, Z5, Z6, Z7, Z13\n",
"5.0 Z2, Z5, Z8, Z9, Z13\n",
"2.5 Z2, Z5, Z10, Z11, Z13\n",
"5.0 Z3, Z4, Z5, Z6, Z13\n",
"5.0 Z3, Z4, Z5, Z8, Z13\n",
"2.5 Z3, Z4, Z5, Z10, Z13\n",
"5.0 Z3, Z4, Z6, Z7, Z13\n",
"5.0 Z3, Z4, Z8, Z9, Z13\n",
"2.5 Z3, Z4, Z10, Z11, Z13\n",
"-15.0 Z3, Z5, Z7, Z9, Z13\n",
"7.5 Z3, Z5, Z7, Z11, Z13\n",
"-5.0 Z3, Z5, Z6, Z8, Z13\n",
"2.5 Z3, Z5, Z6, Z10, Z13\n",
"-5.0 Z3, Z5, Z6, Z7, Z8, Z9, Z13\n",
"2.5 Z3, Z5, Z6, Z7, Z10, Z11, Z13\n",
"-7.5 Z3, Z5, Z9, Z11, Z13\n",
"-2.5 Z3, Z5, Z8, Z10, Z13\n",
"-2.5 Z3, Z5, Z8, Z9, Z10, Z11, Z13\n",
"5.0 Z2, Z3, Z4, Z7, Z13\n",
"5.0 Z2, Z3, Z7, Z8, Z13\n",
"-7.5 Z2, Z3, Z7, Z10, Z13\n",
"5.0 Z2, Z4, Z5, Z7, Z13\n",
"5.0 Z2, Z7, Z8, Z9, Z13\n",
"-7.5 Z2, Z7, Z10, Z11, Z13\n",
"-5.0 Z3, Z4, Z7, Z8, Z13\n",
"2.5 Z3, Z4, Z7, Z10, Z13\n",
"-5.0 Z3, Z4, Z5, Z7, Z8, Z9, Z13\n",
"2.5 Z3, Z4, Z5, Z7, Z10, Z11, Z13\n",
"5.0 Z3, Z6, Z7, Z8, Z13\n",
"-7.5 Z3, Z6, Z7, Z10, Z13\n",
"5.0 Z3, Z6, Z8, Z9, Z13\n",
"-7.5 Z3, Z6, Z10, Z11, Z13\n",
"7.5 Z3, Z7, Z9, Z11, Z13\n",
"2.5 Z3, Z7, Z8, Z10, Z13\n",
"2.5 Z3, Z7, Z8, Z9, Z10, Z11, Z13\n",
"5.0 Z2, Z3, Z4, Z9, Z13\n",
"5.0 Z2, Z3, Z6, Z9, Z13\n",
"2.5 Z2, Z3, Z9, Z10, Z13\n",
"5.0 Z2, Z4, Z5, Z9, Z13\n",
"5.0 Z2, Z6, Z7, Z9, Z13\n",
"2.5 Z2, Z9, Z10, Z11, Z13\n",
"-5.0 Z3, Z4, Z6, Z9, Z13\n",
"-2.5 Z3, Z4, Z9, Z10, Z13\n",
"-5.0 Z3, Z4, Z5, Z6, Z7, Z9, Z13\n",
"-2.5 Z3, Z4, Z5, Z9, Z10, Z11, Z13\n",
"2.5 Z3, Z6, Z9, Z10, Z13\n",
"2.5 Z3, Z6, Z7, Z9, Z10, Z11, Z13\n",
"2.5 Z3, Z8, Z9, Z10, Z13\n",
"2.5 Z3, Z8, Z10, Z11, Z13\n",
"2.5 Z2, Z3, Z4, Z11, Z13\n",
"-7.5 Z2, Z3, Z6, Z11, Z13\n",
"2.5 Z2, Z3, Z8, Z11, Z13\n",
"2.5 Z2, Z4, Z5, Z11, Z13\n",
"-7.5 Z2, Z6, Z7, Z11, Z13\n",
"2.5 Z2, Z8, Z9, Z11, Z13\n",
"2.5 Z3, Z4, Z6, Z11, Z13\n",
"-2.5 Z3, Z4, Z8, Z11, Z13\n",
"2.5 Z3, Z4, Z5, Z6, Z7, Z11, Z13\n",
"-2.5 Z3, Z4, Z5, Z8, Z9, Z11, Z13\n",
"2.5 Z3, Z6, Z8, Z11, Z13\n",
"2.5 Z3, Z6, Z7, Z8, Z9, Z11, Z13\n",
"-5.0 Z2, Z4, Z7, Z9, Z13\n",
"2.5 Z2, Z4, Z7, Z11, Z13\n",
"-15.0 Z2, Z4, Z6, Z8, Z13\n",
"7.5 Z2, Z4, Z6, Z10, Z13\n",
"-5.0 Z2, Z4, Z6, Z7, Z8, Z9, Z13\n",
"2.5 Z2, Z4, Z6, Z7, Z10, Z11, Z13\n",
"-2.5 Z2, Z4, Z9, Z11, Z13\n",
"-7.5 Z2, Z4, Z8, Z10, Z13\n",
"-2.5 Z2, Z4, Z8, Z9, Z10, Z11, Z13\n",
"-5.0 Z2, Z5, Z6, Z9, Z13\n",
"2.5 Z2, Z5, Z6, Z11, Z13\n",
"-5.0 Z2, Z4, Z5, Z6, Z8, Z9, Z13\n",
"2.5 Z2, Z4, Z5, Z6, Z10, Z11, Z13\n",
"2.5 Z2, Z6, Z9, Z11, Z13\n",
"7.5 Z2, Z6, Z8, Z10, Z13\n",
"2.5 Z2, Z6, Z8, Z9, Z10, Z11, Z13\n",
"-5.0 Z2, Z5, Z7, Z8, Z13\n",
"-2.5 Z2, Z5, Z8, Z11, Z13\n",
"-5.0 Z2, Z4, Z5, Z6, Z7, Z8, Z13\n",
"-2.5 Z2, Z4, Z5, Z8, Z10, Z11, Z13\n",
"2.5 Z2, Z7, Z8, Z11, Z13\n",
"2.5 Z2, Z6, Z7, Z8, Z10, Z11, Z13\n",
"2.5 Z2, Z5, Z7, Z10, Z13\n",
"-2.5 Z2, Z5, Z9, Z10, Z13\n",
"2.5 Z2, Z4, Z5, Z6, Z7, Z10, Z13\n",
"-2.5 Z2, Z4, Z5, Z8, Z9, Z10, Z13\n",
"2.5 Z2, Z7, Z9, Z10, Z13\n",
"2.5 Z2, Z6, Z7, Z8, Z9, Z10, Z13\n",
"-5.0 Z2, Z3, Z4, Z5, Z7, Z9, Z13\n",
"2.5 Z2, Z3, Z4, Z5, Z7, Z11, Z13\n",
"-5.0 Z2, Z3, Z4, Z5, Z6, Z8, Z13\n",
"2.5 Z2, Z3, Z4, Z5, Z6, Z10, Z13\n",
"-15.0 Z2, Z3, Z4, Z5, Z6, Z7, Z8, Z9, Z13\n",
"7.5 Z2, Z3, Z4, Z5, Z6, Z7, Z10, Z11, Z13\n",
"-2.5 Z2, Z3, Z4, Z5, Z9, Z11, Z13\n",
"-2.5 Z2, Z3, Z4, Z5, Z8, Z10, Z13\n",
"-7.5 Z2, Z3, Z4, Z5, Z8, Z9, Z10, Z11, Z13\n",
"-5.0 Z2, Z3, Z5, Z6, Z7, Z9, Z13\n",
"2.5 Z2, Z3, Z5, Z6, Z7, Z11, Z13\n",
"-5.0 Z2, Z3, Z4, Z6, Z7, Z8, Z13\n",
"2.5 Z2, Z3, Z4, Z6, Z7, Z10, Z13\n",
"2.5 Z2, Z3, Z6, Z7, Z9, Z11, Z13\n",
"2.5 Z2, Z3, Z6, Z7, Z8, Z10, Z13\n",
"7.5 Z2, Z3, Z6, Z7, Z8, Z9, Z10, Z11, Z13\n",
"-5.0 Z2, Z3, Z5, Z7, Z8, Z9, Z13\n",
"-2.5 Z2, Z3, Z5, Z8, Z9, Z11, Z13\n",
"-5.0 Z2, Z3, Z4, Z6, Z8, Z9, Z13\n",
"-2.5 Z2, Z3, Z4, Z8, Z9, Z10, Z13\n",
"2.5 Z2, Z3, Z7, Z8, Z9, Z11, Z13\n",
"2.5 Z2, Z3, Z6, Z8, Z9, Z10, Z13\n",
"2.5 Z2, Z3, Z5, Z7, Z10, Z11, Z13\n",
"-2.5 Z2, Z3, Z5, Z9, Z10, Z11, Z13\n",
"2.5 Z2, Z3, Z4, Z6, Z10, Z11, Z13\n",
"-2.5 Z2, Z3, Z4, Z8, Z10, Z11, Z13\n",
"2.5 Z2, Z3, Z7, Z9, Z10, Z11, Z13\n",
"2.5 Z2, Z3, Z6, Z8, Z10, Z11, Z13\n",
"7.5 Z4, Z5, Z7, Z8, Z13\n",
"5.0 Z4, Z5, Z7, Z10, Z13\n",
"7.5 Z4, Z7, Z8, Z9, Z13\n",
"5.0 Z4, Z7, Z10, Z11, Z13\n",
"7.5 Z5, Z6, Z7, Z8, Z13\n",
"5.0 Z5, Z6, Z7, Z10, Z13\n",
"7.5 Z5, Z6, Z8, Z9, Z13\n",
"5.0 Z5, Z6, Z10, Z11, Z13\n",
"-15.0 Z5, Z7, Z9, Z11, Z13\n",
"-5.0 Z5, Z7, Z8, Z10, Z13\n",
"-5.0 Z5, Z7, Z8, Z9, Z10, Z11, Z13\n",
"7.5 Z4, Z5, Z6, Z9, Z13\n",
"5.0 Z4, Z5, Z9, Z10, Z13\n",
"7.5 Z4, Z6, Z7, Z9, Z13\n",
"5.0 Z4, Z9, Z10, Z11, Z13\n",
"-5.0 Z5, Z6, Z9, Z10, Z13\n",
"-5.0 Z5, Z6, Z7, Z9, Z10, Z11, Z13\n",
"5.0 Z5, Z8, Z9, Z10, Z13\n",
"5.0 Z5, Z8, Z10, Z11, Z13\n",
"5.0 Z4, Z5, Z6, Z11, Z13\n",
"5.0 Z4, Z5, Z8, Z11, Z13\n",
"5.0 Z4, Z6, Z7, Z11, Z13\n",
"5.0 Z4, Z8, Z9, Z11, Z13\n",
"-5.0 Z5, Z6, Z8, Z11, Z13\n",
"-5.0 Z5, Z6, Z7, Z8, Z9, Z11, Z13\n",
"-5.0 Z4, Z6, Z9, Z11, Z13\n",
"-15.0 Z4, Z6, Z8, Z10, Z13\n",
"-5.0 Z4, Z6, Z8, Z9, Z10, Z11, Z13\n",
"-5.0 Z4, Z7, Z8, Z11, Z13\n",
"-5.0 Z4, Z6, Z7, Z8, Z10, Z11, Z13\n",
"-5.0 Z4, Z7, Z9, Z10, Z13\n",
"-5.0 Z4, Z6, Z7, Z8, Z9, Z10, Z13\n",
"-5.0 Z4, Z5, Z6, Z7, Z9, Z11, Z13\n",
"-5.0 Z4, Z5, Z6, Z7, Z8, Z10, Z13\n",
"-15.0 Z4, Z5, Z6, Z7, Z8, Z9, Z10, Z11, Z13\n",
"-5.0 Z4, Z5, Z7, Z8, Z9, Z11, Z13\n",
"-5.0 Z4, Z5, Z6, Z8, Z9, Z10, Z13\n",
"-5.0 Z4, Z5, Z7, Z9, Z10, Z11, Z13\n",
"-5.0 Z4, Z5, Z6, Z8, Z10, Z11, Z13\n",
"5.0 Z6, Z7, Z9, Z10, Z13\n",
"5.0 Z6, Z9, Z10, Z11, Z13\n",
"5.0 Z7, Z8, Z9, Z10, Z13\n",
"5.0 Z7, Z8, Z10, Z11, Z13\n",
"5.0 Z6, Z7, Z8, Z11, Z13\n",
"5.0 Z6, Z8, Z9, Z11, Z13\n"
]
}
],
"source": [
"# lambda0 and lambda1 are two parameters used in constraining the spatial structure of protein.\n",
"h = protein.get_protein_hamiltonian(lambda0=10.0, lambda1=10.0)\n",
"print(h)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### Variational quantum circuit\n",
"Users can use variational quantum algorithm (VQA) to solve protein folding problem, the variational quantum circuit is shown below"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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",
"text/plain": [
"<Figure size 494x220 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from folding_protein import circuit\n",
"\n",
"# The following code builds a 4-qubit parameterized circuit that contains two circuit blocks (NOTE: one circuit block contains a layer of RY and a layer of CNOT).\n",
"cir = circuit(4, 2)\n",
"cir.plot()"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## How to use\n",
"Users can customize their task via a configuration file `config.toml`, the user defined settings are listed below.\n",
"```toml\n",
"# The configuration file for protein folding problem\n",
"\n",
"# The amino acides consists in protein. \n",
"amino_acids = [\"A\", \"P\", \"R\", \"L\", \"R\", \"F\", \"Y\"]\n",
"# Pair of indices indicates the potentially interact amino acide pair.\n",
"possible_contactions = [[0, 5], [1, 6]]\n",
"# Depth of the quantum circuit used in VQE\n",
"depth = 1\n",
"# Number of VQE iterations\n",
"num_iterations = 200\n",
"# The condition for VQE convergence\n",
"tol = 1e-3\n",
"# The number of steps between two consecutive loss records\n",
"save_every = 10\n",
"# learning rate for the optimizer\n",
"learning_rate = 0.5\n",
"```\n",
"In order to obtained the 3D structure of the amino acid sequence, user can run\n",
"```shell\n",
"python folding_protein.py --config config.toml\n",
"```\n",
"in terminal, the program will save the figure automatically after the computation.\n",
"\n",
"![](APRLRFY_3d_structure.jpg)\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## References \n",
"\\[1\\] Pande, Vijay S., and Daniel S. Rokhsar. \"Folding pathway of a lattice model for proteins.\" Proceedings of the National Academy of Sciences 96.4 (1999): 1273-1278.\n",
"\n",
"\\[2\\] Robert, Anton, et al. \"Resource-efficient quantum algorithm for protein folding.\" npj Quantum Information 7.1 (2021): 1-5."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "modellib",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.15 (default, Nov 10 2022, 12:46:26) \n[Clang 14.0.6 ]"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "8f24120f890011f53feb4ed62c47961d8565ec1de8b7cb23548c15bd6da8f2d2"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册