{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Use Paddle Quantum to train a PQC\n", "\n", "_Copyright (c) 2023 Institute for Quantum Computing, Baidu Inc. All Rights Reserved._" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Variational Quantum Algorithms (VQA) refers to algorithms that solve specific problems by training a parameterized quantum circuit (PQC) using a classical optimizer. It can be seen as a natural analogy of machine learning in quantum computing. Therefore, a PQC is also referred to as a quantum neural network (QNN).\n", "\n", "Paddle Quantum provides a comprehensive and easy-to-use toolkit for training PQCs. Using Paddle Quantum, we take quantum state preparation as an example to introduce how to conveniently build a PQC, set parameters, and train the PQC using a classical optimizer." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Construct a QNN" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Using the Circuit class in Paddle Quantum, we can construct a QNN by composing various quantum gates. Let's take a concrete example below." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "# import packages\n", "import numpy as np\n", "import paddle\n", "from paddle_quantum.ansatz import Circuit\n", "from paddle_quantum.state import ghz_state\n", "from paddle_quantum.loss import StateFidelity\n", "import matplotlib.pyplot as plt\n", "import warnings\n", "warnings.filterwarnings(\"ignore\")" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "--Ry(1.332)----Rx(5.582)----*--------------x--\n", " | | \n", "--Ry(6.031)----Rx(1.548)----x----*---------|--\n", " | | \n", "--Ry(5.681)----Rx(4.597)---------x----*----|--\n", " | | \n", "--Ry(4.998)----Rx(6.073)--------------x----*--\n", " \n" ] } ], "source": [ "# construct a blank quantum circuit on 4 qubits\n", "cir_1 = Circuit(4)\n", "\n", "# add a layer of Ry, Rx and CNOT gates\n", "cir_1.ry() # default:qubits_idx='full',i.e., add such a single-qubit quantum gate to all qubits. The training parameters are initialized randomly\n", "cir_1.rx()\n", "cir_1.cnot() # default:qubits_idx='cycle',i.e., add such a two-qubit quantum gate to all pairs of neighboring qubits\n", "\n", "# print the constructed circuit\n", "print(cir_1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the example above, quantum gates are added to all qubits by default in a layer-wise manner, which is a common method for constructing QNNs. Similar to classical neural networks, each layer of quantum gates can be referred to as a training layer. If we want to specify the qubits on which a certain quantum gate acts, we can simply change the qubits_idx parameter." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "--Ry(2.892)----*-------\n", " | \n", "--Rx(3.203)----x----x--\n", " | \n", "--Ry(6.145)---------*--\n", " \n" ] } ], "source": [ "# construct a blank quantum circuit\n", "cir_2 = Circuit(3)\n", "\n", "# add quantum gates in a specific way\n", "cir_2.ry(qubits_idx='even') # add such a single-qubit quantum gate to all even-numbered qubits\n", "cir_2.rx(qubits_idx=1) # add quantum gates by specifying the qubit index\n", "cir_2.cnot(qubits_idx=[[0,1],[2,1]]) # add quantum gates by specifying the qubit indices, where the former is the control qubit and the latter is the target qubit\n", "\n", "# print the constructed circuit\n", "print(cir_2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Paddle Quantum also provides built-in templates for common training layers, which make it easier for users to quickly construct QNNs. Other templates can be found in the [Paddle Quantum API](https://qml.baidu.com/api/paddle_quantum.ansatz.circuit.html)." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "--Ry(5.156)----*--------------x----Ry(3.702)----*--------------x----U----*--------------x--\n", " | | | | | | \n", "--Ry(0.102)----x----*---------|----Ry(5.598)----x----*---------|----U----x----*---------|--\n", " | | | | | | \n", "--Ry(4.582)---------x----*----|----Ry(0.862)---------x----*----|----U---------x----*----|--\n", " | | | | | | \n", "--Ry(3.816)--------------x----*----Ry(2.835)--------------x----*----U--------------x----*--\n", " \n" ] } ], "source": [ "# construct a blank quantum circuit\n", "cir_3 = Circuit(4)\n", "\n", "# add two layers of the built-in template real_entangled_layer: each layer contains a layer of Ry gates and a layer of CNOT gates\n", "cir_3.real_entangled_layer(depth=2)\n", "# add one layer of the built-in template complex_entangled_layer: each layer contains a layer of U3 gates and a layer of CNOT gates\n", "cir_3.complex_entangled_layer(depth=1)\n", "\n", "# print the constructed circuit\n", "print(cir_3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Set parameters in QNNs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the above example, the parameters in the QNN are initialized randomly by default. We can retrieve the values of the existing parameters in the circuit and store them in an array by accessing the param property." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "--Ry(3.633)--\n", " \n", "--Ry(4.663)--\n", " \n", "Tensor(shape=[2], dtype=float32, place=Place(cpu), stop_gradient=False,\n", " [3.63321853, 4.66316223])\n" ] } ], "source": [ "# construct a blank quantum circuit\n", "cir_4 = Circuit(2)\n", "# add a layer of Ry gates\n", "cir_4.ry()\n", "# print the constructed circuit\n", "print(cir_4)\n", "# print the values of the parameters in the circuit\n", "print(cir_4.param)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In addition, we can manually set the values of the parameters in the circuit by executing the update_param() method." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "--Ry(0.100)--\n", " \n", "--Ry(0.200)--\n", " \n", "Tensor(shape=[2], dtype=float32, place=Place(cpu), stop_gradient=False,\n", " [0.10000000, 0.20000000])\n" ] } ], "source": [ "# create an array of new parameters\n", "theta_new = paddle.to_tensor([0.1, 0.2], dtype='float32')\n", "# update the parameters in the circuit\n", "cir_4.update_param(theta_new)\n", "# print the constructed circuit\n", "print(cir_4)\n", "# print the values of the parameters in the circuit\n", "print(cir_4.param)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Use a classical optimizer to train a QNN" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "After constructing the QNN, we can define a loss function as needed and call the classical optimizer to train this QNN. Here we use QNNs to learn a GHZ state, and use the fidelity distance as the loss function." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "iter: 0, loss: 0.0379\n", "iter: 5, loss: 0.0226\n", "iter: 10, loss: 0.0126\n", "iter: 15, loss: 0.0065\n", "iter: 20, loss: 0.0032\n", "iter: 25, loss: 0.0014\n", "iter: 30, loss: 0.0005\n", "iter: 35, loss: 0.0003\n", "iter: 40, loss: 0.0003\n", "iter: 45, loss: 0.0003\n", "iter: 50, loss: 0.0002\n", "iter: 55, loss: 0.0001\n", "iter: 60, loss: 0.0000\n", "iter: 65, loss: 0.0001\n", "iter: 70, loss: 0.0000\n", "iter: 75, loss: 0.0000\n", "iter: 80, loss: 0.0000\n", "iter: 85, loss: 0.0000\n", "iter: 90, loss: 0.0000\n", "iter: 95, loss: 0.0000\n" ] } ], "source": [ "# define the hyperparameters in the training\n", "ITR = 100 # training iteration number\n", "LR = 0.02 # learning rate\n", "\n", "# define a PQC\n", "cir = Circuit(4)\n", "cir.ry()\n", "cir.rx()\n", "cir.cnot()\n", "\n", "# define the form of the loss function. Here we use the fidelity distance between the output state from the circuit and the GHZ state\n", "loss_func = StateFidelity(ghz_state(4))\n", "# choose a classical optimizer, where we usually use Adam\n", "opt = paddle.optimizer.Adam(learning_rate=LR, parameters=cir.parameters())\n", "# create a list to record the training process\n", "loss_list = []\n", "# start iteration of optimization\n", "for itr in range(ITR):\n", " # run the circuit, get the output state, compute the loss value\n", " loss = loss_func(cir())\n", " # backward propagating,compute the gradient\n", " loss.backward()\n", " # minimize the loss function, update the parameters\n", " opt.minimize(loss)\n", " opt.clear_grad()\n", " # record the loss value\n", " loss_list.append(loss.numpy().item())\n", " if itr % 5 == 0:\n", " print(f'iter: {itr}, loss: {loss.numpy().item():.4f}')" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "--Ry(5.709)----Rx(3.130)----*--------------x--\n", " | | \n", "--Ry(4.281)----Rx(0.462)----x----*---------|--\n", " | | \n", "--Ry(3.437)----Rx(-0.01)---------x----*----|--\n", " | | \n", "--Ry(0.000)----Rx(3.140)--------------x----*--\n", " \n" ] }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# output the PQC after training\n", "print(cir)\n", "\n", "# plot the loss value as a function of the iteration number\n", "func = plt.plot(loss_list)\n", "plt.xlabel('Iterations')\n", "plt.ylabel('Loss')\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can find that the fidelity distance converges near zero as the training proceeds, which means that the output state of the PQC is very close to the target state, and hence we have successfully trained a quantum circuit that can prepare the target state." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.16" } }, "nbformat": 4, "nbformat_minor": 2 }