From 46a16fa228046139c1f07d3c30ae5eed657e3b23 Mon Sep 17 00:00:00 2001
From: JachyMeow <114171061+JachyMeow@users.noreply.github.com>
Date: Mon, 7 Aug 2023 00:47:50 +0800
Subject: [PATCH 1/2] Add files via upload
---
docs/source/tutorials/nnvqe.ipynb | 4001 +++++++++++++++++++++++++++++
1 file changed, 4001 insertions(+)
create mode 100644 docs/source/tutorials/nnvqe.ipynb
diff --git a/docs/source/tutorials/nnvqe.ipynb b/docs/source/tutorials/nnvqe.ipynb
new file mode 100644
index 00000000..3669b34d
--- /dev/null
+++ b/docs/source/tutorials/nnvqe.ipynb
@@ -0,0 +1,4001 @@
+{
+ "cells": [
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "id": "64ba95d6",
+ "metadata": {},
+ "source": [
+ "#
NN-VQE"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b65f64bf",
+ "metadata": {},
+ "source": [
+ "## Overview\n",
+ "\n",
+ "In this tutorial, we'll show you a general framework called neural network encoded variational quantum algorithms (NN-VQAs) with TensorCircuit. NN-VQA feeds input (such as parameters of a Hamiltonian) from a given problem to a neural network and uses its outputs to parameterize an ansatz circuit for the standard VQA. Here, we take NN-variational quantum eigensolver (VQE) to illustrate concretely."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "831930ae",
+ "metadata": {},
+ "source": [
+ "## Setup"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "4e1651b9",
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "import tensorflow as tf\n",
+ "import tensorcircuit as tc\n",
+ "import cotengra\n",
+ "import quimb\n",
+ "from tqdm.notebook import tqdm\n",
+ "from functools import partial\n",
+ "\n",
+ "optc = cotengra.ReusableHyperOptimizer(\n",
+ " methods=[\"greedy\"],\n",
+ " parallel=\"ray\",\n",
+ " minimize=\"combo\",\n",
+ " max_time=30,\n",
+ " max_repeats=1024,\n",
+ " progbar=True,\n",
+ ")\n",
+ "tc.set_contractor(\"custom\", optimizer=optc, preprocessing=True)\n",
+ "\n",
+ "K = tc.set_backend(\"tensorflow\")\n",
+ "tc.set_dtype(\"complex128\")"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "id": "d78b480b",
+ "metadata": {},
+ "source": [
+ "## Energy\n",
+ "\n",
+ "The Hamiltonian used in this tutorial is a 1D XXZ model with periodic boundary conditions, with the transverse field strength $\\lambda$ and the anisotropy parameter $\\Delta$. The Hamiltonian energy expectation function is chosen as loss.\n",
+ "\n",
+ "$$ \\hat{H}_{XXZ}=\\sum_{i}{ \\left( X_{i}X_{i+1}+Y_{i}Y_{i+1}+\\Delta Z_{i}Z_{i+1} \\right) } + \\lambda \\sum_{i}{Z_{i}} $$"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "fff67346",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def energy(c: tc.Circuit, lamb: float = 1.0, delta: float = 1.0):\n",
+ " e = 0.0\n",
+ " n = c._nqubits\n",
+ " for i in range(n):\n",
+ " e += lamb * c.expectation((tc.gates.z(), [i])) # \n",
+ " for i in range(n): \n",
+ " e += c.expectation(\n",
+ " (tc.gates.x(), [i]), (tc.gates.x(), [(i + 1) % n])\n",
+ " ) # \n",
+ " e += c.expectation(\n",
+ " (tc.gates.y(), [i]), (tc.gates.y(), [(i + 1) % n])\n",
+ " ) # \n",
+ " e += delta * c.expectation(\n",
+ " (tc.gates.z(), [i]), (tc.gates.z(), [(i + 1) % n])\n",
+ " ) # \n",
+ " return K.real(e)"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "id": "0ad6a7a6",
+ "metadata": {},
+ "source": [
+ "## Ansatz circuit\n",
+ "\n",
+ "Now we design the circuit. We choose multi-scale entangled renormalization ansatz (MERA) as the ansatz here, $d$ is the circuit depth. (see tutorial of MERA [here](https://tensorcircuit.readthedocs.io/en/latest/tutorials/mera.html))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "445b7c86",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def MERA(inp, n, d=1, lamb=1., energy_flag=False): # for single-parameter 1D XXZ model, we fix lamb\n",
+ " params = K.cast(inp[\"params\"], \"complex128\")\n",
+ " delta = K.cast(inp[\"delta\"], \"complex128\") \n",
+ " c = tc.Circuit(n)\n",
+ " \n",
+ " idx = 0\n",
+ "\n",
+ " for i in range(n):\n",
+ " c.rx(i, theta=params[3 * i])\n",
+ " c.rz(i, theta=params[3 * i + 1])\n",
+ " c.rx(i, theta=params[3 * i + 2])\n",
+ " idx += 3 * n\n",
+ " \n",
+ "\n",
+ " for n_layer in range(1, int(np.log2(n)) + 1):\n",
+ " n_qubit = 2**n_layer # number of qubits involving\n",
+ " step = int(n / n_qubit)\n",
+ "\n",
+ " for _ in range(d): # circuit depth\n",
+ " # even \n",
+ " for i in range(step, n - step, 2 * step):\n",
+ " c.rxx(i, i + step, theta=params[idx])\n",
+ " c.rzz(i, i + step, theta=params[idx + 1])\n",
+ " idx += 2\n",
+ " \n",
+ " # odd \n",
+ " for i in range(0, n, 2 * step):\n",
+ " c.rxx(i, i + step, theta=params[idx])\n",
+ " c.rzz(i, i + step, theta=params[idx + 1])\n",
+ " idx += 2\n",
+ "\n",
+ " # single qubit\n",
+ " for i in range(0, n, step):\n",
+ " c.rx(i, theta=params[idx])\n",
+ " c.rz(i, theta=params[idx + 1])\n",
+ " idx += 2\n",
+ " \n",
+ " if energy_flag:\n",
+ " return energy(c, lamb, delta) # return Hamiltonian energy expectation\n",
+ " else:\n",
+ " return c, idx # return the circuit & number of circuit parameters"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "6daa2f64",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "The number of parameters is 74\n"
+ ]
+ },
+ {
+ "data": {
+ "image/svg+xml": [
+ "\n",
+ "\n",
+ "\n"
+ ],
+ "text/plain": [
+ "