{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "rz159NaSyQNW" }, "source": [ "##### Copyright 2020 The OpenFermion Developers" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "cellView": "form", "execution": { "iopub.execute_input": "2025-05-10T09:42:25.448818Z", "iopub.status.busy": "2025-05-10T09:42:25.448558Z", "iopub.status.idle": "2025-05-10T09:42:25.453026Z", "shell.execute_reply": "2025-05-10T09:42:25.452353Z" }, "id": "XwmPOS8rySzo" }, "outputs": [], "source": [ "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n", "# you may not use this file except in compliance with the License.\n", "# You may obtain a copy of the License at\n", "#\n", "# https://www.apache.org/licenses/LICENSE-2.0\n", "#\n", "# Unless required by applicable law or agreed to in writing, software\n", "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", "# See the License for the specific language governing permissions and\n", "# limitations under the License." ] }, { "cell_type": "markdown", "metadata": { "id": "9f8d4dd70ff9" }, "source": [ "# Circuits 3: Low rank, arbitrary basis molecular simulations" ] }, { "cell_type": "markdown", "metadata": { "id": "E7CNq-HzyXBY" }, "source": [ "\n", " \n", " \n", " \n", " \n", "
\n", " View on QuantumAI\n", " \n", " Run in Google Colab\n", " \n", " View source on GitHub\n", " \n", " Download notebook\n", "
" ] }, { "cell_type": "markdown", "metadata": { "id": "wJqrHiNcyrMH" }, "source": [ "## Setup\n", "\n", "Install the OpenFermion package:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2025-05-10T09:42:25.456224Z", "iopub.status.busy": "2025-05-10T09:42:25.455981Z", "iopub.status.idle": "2025-05-10T09:42:45.596529Z", "shell.execute_reply": "2025-05-10T09:42:45.595518Z" }, "id": "5cbe6b680387" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Collecting openfermion\r\n", " Cloning https://github.com/quantumlib/OpenFermion.git (to revision master) to /tmpfs/tmp/pip-install-sfczrxbc/openfermion_19c612af092e41d3b5f0aa5db42bbee7\r\n", " Running command git clone --filter=blob:none --quiet https://github.com/quantumlib/OpenFermion.git /tmpfs/tmp/pip-install-sfczrxbc/openfermion_19c612af092e41d3b5f0aa5db42bbee7\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ " Resolved https://github.com/quantumlib/OpenFermion.git to commit 9423933ed05a150f9681e9a1e9cac40e29c81ead\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ " Installing build dependencies ... \u001b[?25l-" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b \b\\" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b \bdone\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[?25h Getting requirements to build wheel ... \u001b[?25l-" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b \bdone\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[?25h Preparing metadata (pyproject.toml) ... \u001b[?25l-" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b \bdone\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[?25hCollecting cirq-core (from openfermion)\r\n", " Using cached cirq_core-1.5.0-py3-none-any.whl.metadata (4.9 kB)\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Collecting deprecation (from openfermion)\r\n", " Using cached deprecation-2.1.0-py2.py3-none-any.whl.metadata (4.6 kB)\r\n", "Requirement already satisfied: h5py>=3.10.0 in /tmpfs/src/tf_docs_env/lib/python3.10/site-packages (from openfermion) (3.13.0)\r\n", "Requirement already satisfied: networkx in /tmpfs/src/tf_docs_env/lib/python3.10/site-packages (from openfermion) (3.4.2)\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Collecting numpy<2.0,>=1.24 (from openfermion)\r\n", " Using cached numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (61 kB)\r\n", "Collecting pubchempy (from openfermion)\r\n", " Using cached pubchempy-1.0.4-py3-none-any.whl\r\n", "Requirement already satisfied: requests~=2.32.2 in /tmpfs/src/tf_docs_env/lib/python3.10/site-packages (from openfermion) (2.32.3)\r\n", "Requirement already satisfied: scipy~=1.15 in /tmpfs/src/tf_docs_env/lib/python3.10/site-packages (from openfermion) (1.15.3)\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Collecting sympy (from openfermion)\r\n", " Using cached sympy-1.14.0-py3-none-any.whl.metadata (12 kB)\r\n", "Requirement already satisfied: charset-normalizer<4,>=2 in /tmpfs/src/tf_docs_env/lib/python3.10/site-packages (from requests~=2.32.2->openfermion) (3.4.2)\r\n", "Requirement already satisfied: idna<4,>=2.5 in /tmpfs/src/tf_docs_env/lib/python3.10/site-packages (from requests~=2.32.2->openfermion) (3.10)\r\n", "Requirement already satisfied: urllib3<3,>=1.21.1 in /tmpfs/src/tf_docs_env/lib/python3.10/site-packages (from requests~=2.32.2->openfermion) (2.4.0)\r\n", "Requirement already satisfied: certifi>=2017.4.17 in /tmpfs/src/tf_docs_env/lib/python3.10/site-packages (from requests~=2.32.2->openfermion) (2025.4.26)\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Requirement already satisfied: attrs>=21.3.0 in /tmpfs/src/tf_docs_env/lib/python3.10/site-packages (from cirq-core->openfermion) (25.3.0)\r\n", "Collecting duet>=0.2.8 (from cirq-core->openfermion)\r\n", " Using cached duet-0.2.9-py3-none-any.whl.metadata (2.3 kB)\r\n", "Requirement already satisfied: matplotlib~=3.7 in /tmpfs/src/tf_docs_env/lib/python3.10/site-packages (from cirq-core->openfermion) (3.10.3)\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Requirement already satisfied: pandas~=2.0 in /tmpfs/src/tf_docs_env/lib/python3.10/site-packages (from cirq-core->openfermion) (2.2.3)\r\n", "Collecting sortedcontainers~=2.0 (from cirq-core->openfermion)\r\n", " Using cached sortedcontainers-2.4.0-py2.py3-none-any.whl.metadata (10 kB)\r\n", "Requirement already satisfied: typing_extensions>=4.2 in /tmpfs/src/tf_docs_env/lib/python3.10/site-packages (from cirq-core->openfermion) (4.13.2)\r\n", "Requirement already satisfied: tqdm>=4.12 in /tmpfs/src/tf_docs_env/lib/python3.10/site-packages (from cirq-core->openfermion) (4.67.1)\r\n", "Requirement already satisfied: contourpy>=1.0.1 in /tmpfs/src/tf_docs_env/lib/python3.10/site-packages (from matplotlib~=3.7->cirq-core->openfermion) (1.3.2)\r\n", "Requirement already satisfied: cycler>=0.10 in /tmpfs/src/tf_docs_env/lib/python3.10/site-packages (from matplotlib~=3.7->cirq-core->openfermion) (0.12.1)\r\n", "Requirement already satisfied: fonttools>=4.22.0 in /tmpfs/src/tf_docs_env/lib/python3.10/site-packages (from matplotlib~=3.7->cirq-core->openfermion) (4.57.0)\r\n", "Requirement already satisfied: kiwisolver>=1.3.1 in /tmpfs/src/tf_docs_env/lib/python3.10/site-packages (from matplotlib~=3.7->cirq-core->openfermion) (1.4.8)\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Requirement already satisfied: packaging>=20.0 in /tmpfs/src/tf_docs_env/lib/python3.10/site-packages (from matplotlib~=3.7->cirq-core->openfermion) (25.0)\r\n", "Requirement already satisfied: pillow>=8 in /tmpfs/src/tf_docs_env/lib/python3.10/site-packages (from matplotlib~=3.7->cirq-core->openfermion) (11.2.1)\r\n", "Requirement already satisfied: pyparsing>=2.3.1 in /tmpfs/src/tf_docs_env/lib/python3.10/site-packages (from matplotlib~=3.7->cirq-core->openfermion) (3.2.3)\r\n", "Requirement already satisfied: python-dateutil>=2.7 in /tmpfs/src/tf_docs_env/lib/python3.10/site-packages (from matplotlib~=3.7->cirq-core->openfermion) (2.9.0.post0)\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Requirement already satisfied: pytz>=2020.1 in /tmpfs/src/tf_docs_env/lib/python3.10/site-packages (from pandas~=2.0->cirq-core->openfermion) (2025.2)\r\n", "Requirement already satisfied: tzdata>=2022.7 in /tmpfs/src/tf_docs_env/lib/python3.10/site-packages (from pandas~=2.0->cirq-core->openfermion) (2025.2)\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Requirement already satisfied: six>=1.5 in /tmpfs/src/tf_docs_env/lib/python3.10/site-packages (from python-dateutil>=2.7->matplotlib~=3.7->cirq-core->openfermion) (1.17.0)\r\n", "Collecting mpmath<1.4,>=1.1.0 (from sympy->openfermion)\r\n", " Using cached mpmath-1.3.0-py3-none-any.whl.metadata (8.6 kB)\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Using cached numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (18.2 MB)\r\n", "Using cached cirq_core-1.5.0-py3-none-any.whl (2.0 MB)\r\n", "Using cached sortedcontainers-2.4.0-py2.py3-none-any.whl (29 kB)\r\n", "Using cached duet-0.2.9-py3-none-any.whl (29 kB)\r\n", "Using cached deprecation-2.1.0-py2.py3-none-any.whl (11 kB)\r\n", "Using cached sympy-1.14.0-py3-none-any.whl (6.3 MB)\r\n", "Using cached mpmath-1.3.0-py3-none-any.whl (536 kB)\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Building wheels for collected packages: openfermion\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ " Building wheel for openfermion (pyproject.toml) ... \u001b[?25l-" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b \b\\" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b \b|" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b \b/" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b \b-" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b \b\\" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b \b|" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b \bdone\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[?25h Created wheel for openfermion: filename=openfermion-1.7.1.dev0-py3-none-any.whl size=44717459 sha256=06eeba193e47c433acbc308fd434e81cd8bbdaf8435a6445fe0313e636856917\r\n", " Stored in directory: /tmpfs/tmp/pip-ephem-wheel-cache-bxiybq8z/wheels/7a/93/a6/5746203c4afd3b6e8d40a4edb587d608c51290286c5680f422\r\n", "Successfully built openfermion\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Installing collected packages: sortedcontainers, pubchempy, mpmath, sympy, numpy, duet, deprecation, cirq-core, openfermion\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ " Attempting uninstall: numpy\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ " Found existing installation: numpy 2.1.3\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ " Uninstalling numpy-2.1.3:\r\n", " Successfully uninstalled numpy-2.1.3\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Successfully installed cirq-core-1.5.0 deprecation-2.1.0 duet-0.2.9 mpmath-1.3.0 numpy-1.26.4 openfermion-1.7.1.dev0 pubchempy-1.0.4 sortedcontainers-2.4.0 sympy-1.14.0\r\n" ] } ], "source": [ "try:\n", " import openfermion\n", "except ImportError:\n", " !pip install git+https://github.com/quantumlib/OpenFermion.git@master#egg=openfermion" ] }, { "cell_type": "markdown", "metadata": { "id": "90c6d9693f39" }, "source": [ "## Low rank decomposition of the Coulomb operator\n", "\n", "The algorithm discussed in this tutorial is described in [arXiv:1808.02625](https://arxiv.org/abs/1808.02625).\n", "\n", "In [Circuits 1](./circuits_1_basis_change.ipynb) we discussed methods for very compiling single-particle basis transformations of fermionic operators in $O(N)$ depth on a linearly connected architecture. We looked at the particular example of simulating a free fermion model by using Bogoliubov transformations to diagonalize the model.\n", "\n", "In [Circuits 2](./circuits_2_diagonal_coulomb_trotter.ipynb) we discussed methods for compiling Trotter steps of electronic structure Hamiltonian in $O(N)$ depth on a linearly connected architecture when expressed in a basis diagonalizing the Coulomb operator so that\n", "$$\n", "H = \\sum_{pq} T_{pq} a^\\dagger_p a_q + \\sum_{pq} V_{pq} a^\\dagger_p a_p a^\\dagger_q a_q.\n", "$$\n", "\n", "Here we will discuss how both of those techniques can be combined, along with some insights from electronic structure, in order to simulate arbitrary basis molecular Hamiltonians taking the form\n", "$$\n", "H = \\sum_{pq} T_{pq} a^\\dagger_p a_q + \\sum_{pqrs} V_{pqrs} a^\\dagger_p a_q a^\\dagger_r a_s\n", "$$\n", "in depth scaling only as $O(N^2)$ on a linear array of qubits. First, we note that the one-body part of the above expression is easy to simulate using the techniques introduced in [Circuits 1](./circuits_1_basis_change.ipynb). Thus, the real challenge is to simulate the two-body part of the operator.\n", "\n", "We begin with the observation that the rank-4 tensor $V$, with the values $V_{pqrs}$ representing the coefficient of $a^\\dagger_p a_q a^\\dagger_r a_s$ can be flattened into an $N^2 \\times N^2$ array by making $p,q$ one index and $r,s$ the other. This is the electronic repulsion integral (ERI) matrix in chemist notation. We will refer to the ERI matrix as $W$. By diagonalizing $W$, one obtains $W g_\\ell = \\lambda_\\ell g_\\ell$ where the eigenvector $g_\\ell$ is a vector of dimension $N^2$. If we reshape $g_\\ell$ into an $N \\times N$ vector, we realize that\n", "$$\n", "\\sum_{pqrs} V_{pqrs} a^\\dagger_p a_q a^\\dagger_r a_s = \\sum_{\\ell=0}^{L-1} \\lambda_\\ell \\left(\\sum_{pq} \\left[g_{\\ell}\\right]_{pq} a^\\dagger_p a_q\\right)^2.\n", "$$\n", "This is related to the concept of density fitting in electronic structure, which is often accomplished using a Cholesky decomposition. It is fairly well known in the quantum chemistry community that the ERI matrix is positive semi-definite and despite having linear dimension $N^2$, has rank of only $L = O(N)$. Thus, the eigenvalues $\\lambda_\\ell$ are positive and there are only $O(N)$ of them.\n", "\n", "Next, we diagonalize the one-body operators inside of the square so that\n", "$$\n", "R_\\ell \\left(\\sum_{pq} \\left[g_\\ell\\right]_{pq} a^\\dagger_p a_q\\right) R_\\ell^\\dagger = \\sum_{p} f_{\\ell p} a^\\dagger_p a_p\n", "$$\n", "where the $R_\\ell$ represent single-particle basis transformations of the sort we compiled in [Circuits 1](./circuits_1_basis_change.ipynb). Then,\n", "$$\n", "\\sum_{\\ell=0}^{L-1} \\lambda_\\ell \\left(\\sum_{pq} \\left[g_{\\ell}\\right]_{pq} a^\\dagger_p a_q\\right)^2 =\n", "\\sum_{\\ell=0}^{L-1} \\lambda_\\ell \\left(R_\\ell \\left(\\sum_{p} f_{\\ell p} a^\\dagger_p a_p\\right) R_\\ell^\\dagger\\right)^2 = \\sum_{\\ell=0}^{L-1} \\lambda_\\ell \\left(R_\\ell \\left(\\sum_{p} f_{\\ell p} a^\\dagger_p a_p\\right) R_\\ell^\\dagger R_\\ell \\left(\\sum_{p} f_{\\ell p} a^\\dagger_p a_p\\right) R_\\ell^\\dagger\\right)\n", "= \\sum_{\\ell=0}^{L-1} \\lambda_\\ell R_\\ell \\left(\\sum_{pq} f_{\\ell p} f_{\\ell q} a^\\dagger_p a_p a^\\dagger_q a_q\\right) R_\\ell^\\dagger.\n", "$$\n", "We now see that we can simulate a Trotter step under the arbitrary basis two-body operator as\n", "$$\n", "\\prod_{\\ell=0}^{L-1} R_\\ell \\exp\\left(-i\\sum_{pq} f_{\\ell p} f_{\\ell q} a^\\dagger_p a_p a^\\dagger_q a_q\\right) R_\\ell^\\dagger\n", "$$\n", "where we note that the operator in the exponential take the form of a diagonal Coulomb operator. Since we can implement the $R_\\ell$ circuits in $O(N)$ depth (see [Circuits 1](./circuits_1_basis_change.ipynb)) and we can implement Trotter steps under diagonal Coulomb operators in $O(N)$ layers of gates (see [Circuits 2](./circuits_2_diagonal_coulomb_trotter.ipynb)) we see that we can implement Trotter steps under arbitrary basis electronic structure Hamiltionians in $O(L N) = O(N^2)$ depth, and all on a linearly connected device. This is a big improvement over the usual way of doing things, which would lead to no less than $O(N^5)$ depth! In fact, it is also possible to do better by truncating rank on the second diagonalization but we have not implemented that (details will be discussed in aforementioned paper-in-preparation).\n", "\n", "Note that these techniques are also applicable to realizing evolution under other two-body operators, such as the generator of unitary coupled cluster. Note that one can create variational algorithms where a variational parameter specifies the rank at which to truncate the $\\lambda_\\ell$." ] }, { "cell_type": "markdown", "metadata": { "id": "0800a1366c50" }, "source": [ "## Example implementation: Trotter steps of LiH in molecular orbital basis\n", "\n", "We will now use these techniques to implement Trotter steps for an actual molecule. We will focus on LiH at equilibrium geometry, since integrals for that system are provided with every OpenFermion installation. However, by installing [OpenFermion-PySCF](https://github.com/quantumlib/OpenFermion-PySCF) or [OpenFermion-Psi4](https://github.com/quantumlib/OpenFermion-Psi4) one can use these techniques for any molecule at any geometry. We will generate LiH in an active space consisting of 4 qubits. First, we obtain the Hamiltonian as an InteractionOperator." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "execution": { "iopub.execute_input": "2025-05-10T09:42:45.600310Z", "iopub.status.busy": "2025-05-10T09:42:45.600018Z", "iopub.status.idle": "2025-05-10T09:42:47.471878Z", "shell.execute_reply": "2025-05-10T09:42:47.471139Z" }, "id": "9b51e47b58f7" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-6.7698132180879735 [] +\n", "-0.7952726864779313 [0^ 0] +\n", "0.24889540266275176 [0^ 0^ 0 0] +\n", "-0.02307282640154995 [0^ 0^ 0 2] +\n", "-0.023072826401549944 [0^ 0^ 2 0] +\n", "0.005865992881900444 [0^ 0^ 2 2] +\n", "0.24889540266275176 [0^ 1^ 1 0] +\n", "-0.02307282640154995 [0^ 1^ 1 2] +\n", "-0.023072826401549944 [0^ 1^ 3 0] +\n", "0.005865992881900444 [0^ 1^ 3 2] +\n", "0.04614563473199314 [0^ 2] +\n", "-0.02307282640154995 [0^ 2^ 0 0] +\n", "0.005865992881900456 [0^ 2^ 0 2] +\n", "0.11412688446849813 [0^ 2^ 2 0] +\n", "0.0027487522157917266 [0^ 2^ 2 2] +\n", "-0.02307282640154995 [0^ 3^ 1 0] +\n", "0.005865992881900456 [0^ 3^ 1 2] +\n", "0.11412688446849813 [0^ 3^ 3 0] +\n", "0.0027487522157917266 [0^ 3^ 3 2] +\n", "0.24889540266275176 [1^ 0^ 0 1] +\n", "-0.02307282640154995 [1^ 0^ 0 3] +\n", "-0.023072826401549944 [1^ 0^ 2 1] +\n", "0.005865992881900444 [1^ 0^ 2 3] +\n", "-0.7952726864779313 [1^ 1] +\n", "0.24889540266275176 [1^ 1^ 1 1] +\n", "-0.02307282640154995 [1^ 1^ 1 3] +\n", "-0.023072826401549944 [1^ 1^ 3 1] +\n", "0.005865992881900444 [1^ 1^ 3 3] +\n", "-0.02307282640154995 [1^ 2^ 0 1] +\n", "0.005865992881900456 [1^ 2^ 0 3] +\n", "0.11412688446849813 [1^ 2^ 2 1] +\n", "0.0027487522157917266 [1^ 2^ 2 3] +\n", "0.04614563473199314 [1^ 3] +\n", "-0.02307282640154995 [1^ 3^ 1 1] +\n", "0.005865992881900456 [1^ 3^ 1 3] +\n", "0.11412688446849813 [1^ 3^ 3 1] +\n", "0.0027487522157917266 [1^ 3^ 3 3] +\n", "0.04614563473199324 [2^ 0] +\n", "-0.023072826401549958 [2^ 0^ 0 0] +\n", "0.11412688446849814 [2^ 0^ 0 2] +\n", "0.005865992881900458 [2^ 0^ 2 0] +\n", "0.002748752215791747 [2^ 0^ 2 2] +\n", "-0.023072826401549958 [2^ 1^ 1 0] +\n", "0.11412688446849814 [2^ 1^ 1 2] +\n", "0.005865992881900458 [2^ 1^ 3 0] +\n", "0.002748752215791747 [2^ 1^ 3 2] +\n", "-0.36549257026798354 [2^ 2] +\n", "0.0058659928819004585 [2^ 2^ 0 0] +\n", "0.002748752215791731 [2^ 2^ 0 2] +\n", "0.002748752215791736 [2^ 2^ 2 0] +\n", "0.16959219087341962 [2^ 2^ 2 2] +\n", "0.0058659928819004585 [2^ 3^ 1 0] +\n", "0.002748752215791731 [2^ 3^ 1 2] +\n", "0.002748752215791736 [2^ 3^ 3 0] +\n", "0.16959219087341962 [2^ 3^ 3 2] +\n", "-0.023072826401549958 [3^ 0^ 0 1] +\n", "0.11412688446849814 [3^ 0^ 0 3] +\n", "0.005865992881900458 [3^ 0^ 2 1] +\n", "0.002748752215791747 [3^ 0^ 2 3] +\n", "0.04614563473199324 [3^ 1] +\n", "-0.023072826401549958 [3^ 1^ 1 1] +\n", "0.11412688446849814 [3^ 1^ 1 3] +\n", "0.005865992881900458 [3^ 1^ 3 1] +\n", "0.002748752215791747 [3^ 1^ 3 3] +\n", "0.0058659928819004585 [3^ 2^ 0 1] +\n", "0.002748752215791731 [3^ 2^ 0 3] +\n", "0.002748752215791736 [3^ 2^ 2 1] +\n", "0.16959219087341962 [3^ 2^ 2 3] +\n", "-0.36549257026798354 [3^ 3] +\n", "0.0058659928819004585 [3^ 3^ 1 1] +\n", "0.002748752215791731 [3^ 3^ 1 3] +\n", "0.002748752215791736 [3^ 3^ 3 1] +\n", "0.16959219087341962 [3^ 3^ 3 3]\n" ] } ], "source": [ "import openfermion\n", "\n", "# Set Hamiltonian parameters for LiH simulation in active space.\n", "diatomic_bond_length = 1.45\n", "geometry = [('Li', (0., 0., 0.)), ('H', (0., 0., diatomic_bond_length))]\n", "basis = 'sto-3g'\n", "multiplicity = 1\n", "active_space_start = 1\n", "active_space_stop = 3\n", "\n", "# Generate and populate instance of MolecularData.\n", "molecule = openfermion.MolecularData(geometry, basis, multiplicity, description=\"1.45\")\n", "molecule.load()\n", "\n", "# Get the Hamiltonian in an active space.\n", "molecular_hamiltonian = molecule.get_molecular_hamiltonian(\n", " occupied_indices=range(active_space_start),\n", " active_indices=range(active_space_start, active_space_stop))\n", "print(openfermion.get_fermion_operator(molecular_hamiltonian))" ] }, { "cell_type": "markdown", "metadata": { "id": "9265fc9c3dae" }, "source": [ "We see from the above output that this is a fairly complex Hamiltonian already. Next we will use the `simulate_trotter` function from [Circuits 1](./circuits_1_basis_change.ipynb), but this time using a different type of Trotter step associated with these low rank techniques. To keep this circuit very short for pedagogical purposes we will force a truncation of the eigenvalues $\\lambda_\\ell$ at a predetermined value of `final_rank`. While we also support a canned `LOW_RANK` option for the Trotter steps, in order to pass this value of `final_rank` we will instantiate a custom Trotter algorithm type." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "execution": { "iopub.execute_input": "2025-05-10T09:42:47.475391Z", "iopub.status.busy": "2025-05-10T09:42:47.474671Z", "iopub.status.idle": "2025-05-10T09:42:47.504529Z", "shell.execute_reply": "2025-05-10T09:42:47.503768Z" }, "id": "d530047fea8c" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 1 2 3\n", "│ │ │ │\n", "Rz(π) Rz(π) Rz(π) Rz(π)\n", "│ │ │ │\n", "│ PhISwap(0.25)────────PhISwap(0.25)^-1 │\n", "│ │ │ │\n", "PhISwap(0.25)─PhISwap(0.25)^0.081 Z^0 │\n", "│ │ │ │\n", "Rz(0.337π) Z^0 PhISwap(0.25)────PhISwap(0.25)^-0.081\n", "│ │ │ │\n", "Rz(0) PhISwap(0.25)────────PhISwap(0.25)^-1 Z^0\n", "│ │ │ │\n", "│ Rz(0.337π) Z^0 Rz(0.169π)\n", "│ │ │ │\n", "│ Rz(0) Rz(0.169π) Rz(0)\n", "│ │ │ │\n", "│ │ Rz(0) │\n", "│ │ │ │\n", "│ PhISwap(0.25)────────PhISwap(0.25)^-1 │\n", "│ │ │ │\n", "PhISwap(0.25)─PhISwap(0.25)^-0.051 Z^0 │\n", "│ │ │ │\n", "│ Z^0 PhISwap(0.25)────PhISwap(0.25)^0.051\n", "│ │ │ │\n", "│ PhISwap(0.25)────────PhISwap(0.25)^-1 Z^0\n", "│ │ │ │\n", "@─────────────@^-0.145 Z^0 │\n", "│ │ │ │\n", "×─────────────× @────────────────@^(-1/15)\n", "│ │ │ │\n", "│ │ ×────────────────×\n", "│ │ │ │\n", "│ @────────────────────@^-0.098 │\n", "│ │ │ │\n", "│ ×────────────────────× │\n", "│ │ │ │\n", "@─────────────@^-0.098 @────────────────@^-0.098\n", "│ │ │ │\n", "×─────────────× ×────────────────×\n", "│ │ │ │\n", "Rz(-0.033π) @────────────────────@^-0.098 Rz(-0.072π)\n", "│ │ │ │\n", "Rz(0) ×────────────────────× Rz(0)\n", "│ │ │ │\n", "│ Rz(-0.033π) Rz(-0.072π) │\n", "│ │ │ │\n", "│ Rz(π) Rz(π) │\n", "│ │ │ │\n", "│ PhISwap(0.25)────────PhISwap(0.25)^-1 │\n", "│ │ │ │\n", "│ Z^0 PhISwap(0.25)────PhISwap(0.25)^-0.95\n", "│ │ │ │\n", "PhISwap(0.25)─PhISwap(0.25)^0.95 Z^0 │\n", "│ │ │ │\n", "Z^0 PhISwap(0.25)────────PhISwap(0.25)^-1 │\n", "│ │ │ │\n", "│ Z^0 @────────────────@^-0.041\n", "│ │ │ │\n", "@─────────────@^-0.019 ×────────────────×\n", "│ │ │ │\n", "×─────────────× │ │\n", "│ │ │ │\n", "│ @────────────────────@^0.028 │\n", "│ │ │ │\n", "│ ×────────────────────× │\n", "│ │ │ │\n", "@─────────────@^0.028 @────────────────@^0.028\n", "│ │ │ │\n", "×─────────────× ×────────────────×\n", "│ │ │ │\n", "Rz(-0.02π) @────────────────────@^0.028 Rz(-0.009π)\n", "│ │ │ │\n", "Rz(0) ×────────────────────× Rz(0)\n", "│ │ │ │\n", "│ Rz(-0.02π) Rz(-0.009π) │\n", "│ │ │ │\n", "│ Rz(π) Rz(π) │\n", "│ │ │ │\n", "│ PhISwap(0.25)────────PhISwap(0.25)^-1 │\n", "│ │ │ │\n", "PhISwap(0.25)─PhISwap(0.25)^-0.918 Z^0 │\n", "│ │ │ │\n", "│ Z^0 PhISwap(0.25)────PhISwap(0.25)^0.918\n", "│ │ │ │\n", "│ PhISwap(0.25)────────PhISwap(0.25)^-1 Z^0\n", "│ │ │ │\n", "│ │ Z^0 │\n", "│ │ │ │\n" ] } ], "source": [ "import cirq\n", "import openfermion\n", "from openfermion.circuits import trotter\n", "\n", "# Trotter step parameters.\n", "time = 1.\n", "final_rank = 2\n", "\n", "# Initialize circuit qubits in a line.\n", "n_qubits = openfermion.count_qubits(molecular_hamiltonian)\n", "qubits = cirq.LineQubit.range(n_qubits)\n", "\n", "# Compile the low rank Trotter step using OpenFermion.\n", "custom_algorithm = trotter.LowRankTrotterAlgorithm(final_rank=final_rank)\n", "circuit = cirq.Circuit(\n", " trotter.simulate_trotter(\n", " qubits, molecular_hamiltonian,\n", " time=time, omit_final_swaps=True,\n", " algorithm=custom_algorithm),\n", " strategy=cirq.InsertStrategy.EARLIEST)\n", "\n", "# Print circuit.\n", "cirq.drop_negligible_operations(circuit)\n", "print(circuit.to_text_diagram(transpose=True))" ] }, { "cell_type": "markdown", "metadata": { "id": "40f8df9e4f45" }, "source": [ "We were able to print out the circuit this way but forcing `final_rank` of 2 is not very accurate. In the cell below, we compile the Trotter step with full rank so $L = N^2$ and depth is actually $O(N^3)$ and repeat the Trotter step multiple times to show that it actually converges to the correct result. Since we are not forcing the rank truncation we can use the built-in `LOW_RANK` Trotter step type. Note that the rank of the Coulomb operators is asymptotically $O(N)$ but for very small molecules in small basis sets only a few eigenvalues can be truncated." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "execution": { "iopub.execute_input": "2025-05-10T09:42:47.507493Z", "iopub.status.busy": "2025-05-10T09:42:47.507083Z", "iopub.status.idle": "2025-05-10T09:42:47.667330Z", "shell.execute_reply": "2025-05-10T09:42:47.666636Z" }, "id": "e2f406181547" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Fidelity with exact result is 0.9999962935300256.\n", "\n", "0 1 2 3\n", "│ │ │ │\n", "Rz(π) Rz(π) Rz(π) Rz(π)\n", "│ │ │ │\n", "│ PhISwap(0.25)─────────PhISwap(0.25)^-1 │\n", "│ │ │ │\n", "PhISwap(0.25)─PhISwap(0.25)^0.081 Z^0 │\n", "│ │ │ │\n", "Rz(0.112π) Z^0 PhISwap(0.25)────PhISwap(0.25)^-0.081\n", "│ │ │ │\n", "Rz(0) PhISwap(0.25)─────────PhISwap(0.25)^-1 Z^0\n", "│ │ │ │\n", "│ Rz(0.112π) Z^0 Rz(0.056π)\n", "│ │ │ │\n", "│ Rz(0) Rz(0.056π) Rz(0)\n", "│ │ │ │\n", "│ │ Rz(0) │\n", "│ │ │ │\n", "│ PhISwap(0.25)─────────PhISwap(0.25)^-1 │\n", "│ │ │ │\n", "PhISwap(0.25)─PhISwap(0.25)^-0.051 Z^0 │\n", "│ │ │ │\n", "│ Z^0 PhISwap(0.25)────PhISwap(0.25)^0.051\n", "│ │ │ │\n", "│ PhISwap(0.25)─────────PhISwap(0.25)^-1 Z^0\n", "│ │ │ │\n", "@─────────────@^-0.048 Z^0 │\n", "│ │ │ │\n", "×─────────────× @────────────────@^-0.022\n", "│ │ │ │\n", "│ │ ×────────────────×\n", "│ │ │ │\n", "│ @─────────────────────@^-0.033 │\n", "│ │ │ │\n", "│ ×─────────────────────× │\n", "│ │ │ │\n", "@─────────────@^-0.033 @────────────────@^-0.033\n", "│ │ │ │\n", "×─────────────× ×────────────────×\n", "│ │ │ │\n", "Rz(-0.011π) @─────────────────────@^-0.033 Rz(-0.024π)\n", "│ │ │ │\n", "Rz(0) ×─────────────────────× Rz(0)\n", "│ │ │ │\n", "│ Rz(-0.011π) Rz(-0.024π) │\n", "│ │ │ │\n", "│ Rz(π) Rz(π) │\n", "│ │ │ │\n", "│ PhISwap(0.25)─────────PhISwap(0.25)^-1 │\n", "│ │ │ │\n", "│ Z^0 PhISwap(0.25)────PhISwap(0.25)^-0.95\n", "│ │ │ │\n", "PhISwap(0.25)─PhISwap(0.25)^0.95 Z^0 │\n", "│ │ │ │\n", "Z^0 PhISwap(0.25)─────────PhISwap(0.25)^-1 │\n", "│ │ │ │\n", "│ Z^0 @────────────────@^-0.014\n", "│ │ │ │\n", "@─────────────@^-0.006 ×────────────────×\n", "│ │ │ │\n", "×─────────────× │ │\n", "│ │ │ │\n", "│ @─────────────────────@^0.009 │\n", "│ │ │ │\n", "│ ×─────────────────────× │\n", "│ │ │ │\n", "@─────────────@^0.009 @────────────────@^0.009\n", "│ │ │ │\n", "×─────────────× ×────────────────×\n", "│ │ │ │\n", "Rz(-0.007π) @─────────────────────@^0.009 Rz(-0.003π)\n", "│ │ │ │\n", "Rz(π) ×─────────────────────× Rz(π)\n", "│ │ │ │\n", "│ Rz(-0.007π) Rz(-0.003π) │\n", "│ │ │ │\n", "│ Rz(0) Rz(0) │\n", "│ │ │ │\n", "│ PhISwap(0.25)─────────PhISwap(0.25)^-1 │\n", "│ │ │ │\n", "PhISwap(0.25)─PhISwap(0.25)^-0.502 Z^0 │\n", "│ │ │ │\n", "│ Z^0 PhISwap(0.25)────PhISwap(0.25)^0.502\n", "│ │ │ │\n", "│ PhISwap(0.25)─────────PhISwap(0.25)^-1 Z^0\n", "│ │ │ │\n", "@─────────────@^0 Z^0 │\n", "│ │ │ │\n", "×─────────────× @────────────────@^0\n", "│ │ │ │\n", "│ │ ×────────────────×\n", "│ │ │ │\n", "│ @─────────────────────@^0 │\n", "│ │ │ │\n", "│ ×─────────────────────× │\n", "│ │ │ │\n", "@─────────────@^0 @────────────────@^0\n", "│ │ │ │\n", "×─────────────× ×────────────────×\n", "│ │ │ │\n", "Rz(0) @─────────────────────@^0 Rz(0)\n", "│ │ │ │\n", "Rz(π) ×─────────────────────× Rz(π)\n", "│ │ │ │\n", "│ Rz(0) Rz(0) │\n", "│ │ │ │\n", "│ Rz(0) Rz(0) │\n", "│ │ │ │\n", "│ PhISwap(0.25)─────────PhISwap(0.25)^-1 │\n", "│ │ │ │\n", "│ Z^0 PhISwap(0.25)────PhISwap(0.25)^(-5/12)\n", "│ │ │ │\n", "PhISwap(0.25)─PhISwap(0.25)^(5/12) Z^0 Rz(π)\n", "│ │ │ │\n", "Z^0 PhISwap(0.25)─────────PhISwap(0.25)^-1 │\n", "│ │ │ │\n", "Rz(π) Z^0 Rz(π) │\n", "│ │ │ │\n", "│ Rz(π) │ │\n", "│ │ │ │\n", "│ PhISwap(0.25)─────────PhISwap(0.25)^-1 │\n", "│ │ │ │\n", "│ Z^0 PhISwap(0.25)────PhISwap(0.25)^0.081\n", "│ │ │ │\n", "PhISwap(0.25)─PhISwap(0.25)^-0.081 Z^0 Rz(0.112π)\n", "│ │ │ │\n", "Z^0 PhISwap(0.25)─────────PhISwap(0.25)^-1 Rz(0)\n", "│ │ │ │\n", "Rz(0.056π) Z^0 Rz(0.112π) │\n", "│ │ │ │\n", "Rz(0) Rz(0.056π) Rz(0) │\n", "│ │ │ │\n", "│ Rz(0) │ │\n", "│ │ │ │\n", "│ PhISwap(0.25)─────────PhISwap(0.25)^-1 │\n", "│ │ │ │\n", "│ Z^0 PhISwap(0.25)────PhISwap(0.25)^-0.051\n", "│ │ │ │\n", "PhISwap(0.25)─PhISwap(0.25)^0.051 Z^0 │\n", "│ │ │ │\n", "Z^0 PhISwap(0.25)─────────PhISwap(0.25)^-1 │\n", "│ │ │ │\n", "│ Z^0 @────────────────@^-0.048\n", "│ │ │ │\n", "@─────────────@^-0.022 ×────────────────×\n", "│ │ │ │\n", "×─────────────× │ │\n", "│ │ │ │\n", "│ @─────────────────────@^-0.033 │\n", "│ │ │ │\n", "│ ×─────────────────────× │\n", "│ │ │ │\n", "@─────────────@^-0.033 @────────────────@^-0.033\n", "│ │ │ │\n", "×─────────────× ×────────────────×\n", "│ │ │ │\n", "Rz(-0.024π) @─────────────────────@^-0.033 Rz(-0.011π)\n", "│ │ │ │\n", "Rz(0) ×─────────────────────× Rz(0)\n", "│ │ │ │\n", "│ Rz(-0.024π) Rz(-0.011π) │\n", "│ │ │ │\n", "│ Rz(π) Rz(π) │\n", "│ │ │ │\n", "│ PhISwap(0.25)─────────PhISwap(0.25)^-1 │\n", "│ │ │ │\n", "PhISwap(0.25)─PhISwap(0.25)^-0.95 Z^0 │\n", "│ │ │ │\n", "│ Z^0 PhISwap(0.25)────PhISwap(0.25)^0.95\n", "│ │ │ │\n", "│ PhISwap(0.25)─────────PhISwap(0.25)^-1 Z^0\n", "│ │ │ │\n", "@─────────────@^-0.014 Z^0 │\n", "│ │ │ │\n", "×─────────────× @────────────────@^-0.006\n", "│ │ │ │\n", "│ │ ×────────────────×\n", "│ │ │ │\n", "│ @─────────────────────@^0.009 │\n", "│ │ │ │\n", "│ ×─────────────────────× │\n", "│ │ │ │\n", "@─────────────@^0.009 @────────────────@^0.009\n", "│ │ │ │\n", "×─────────────× ×────────────────×\n", "│ │ │ │\n", "Rz(-0.003π) @─────────────────────@^0.009 Rz(-0.007π)\n", "│ │ │ │\n", "Rz(π) ×─────────────────────× Rz(π)\n", "│ │ │ │\n", "│ Rz(-0.003π) Rz(-0.007π) │\n", "│ │ │ │\n", "│ Rz(0) Rz(0) │\n", "│ │ │ │\n", "│ PhISwap(0.25)─────────PhISwap(0.25)^-1 │\n", "│ │ │ │\n", "│ Z^0 PhISwap(0.25)────PhISwap(0.25)^-0.502\n", "│ │ │ │\n", "PhISwap(0.25)─PhISwap(0.25)^0.502 Z^0 │\n", "│ │ │ │\n", "Z^0 PhISwap(0.25)─────────PhISwap(0.25)^-1 │\n", "│ │ │ │\n", "│ Z^0 @────────────────@^0\n", "│ │ │ │\n", "@─────────────@^0 ×────────────────×\n", "│ │ │ │\n", "×─────────────× │ │\n", "│ │ │ │\n", "│ @─────────────────────@^0 │\n", "│ │ │ │\n", "│ ×─────────────────────× │\n", "│ │ │ │\n", "@─────────────@^0 @────────────────@^0\n", "│ │ │ │\n", "×─────────────× ×────────────────×\n", "│ │ │ │\n", "Rz(0) @─────────────────────@^0 Rz(0)\n", "│ │ │ │\n", "Rz(π) ×─────────────────────× Rz(π)\n", "│ │ │ │\n", "│ Rz(0) Rz(0) │\n", "│ │ │ │\n", "│ Rz(0) Rz(0) │\n", "│ │ │ │\n", "│ PhISwap(0.25)─────────PhISwap(0.25)^-1 │\n", "│ │ │ │\n", "PhISwap(0.25)─PhISwap(0.25)^(-5/12) Z^0 │\n", "│ │ │ │\n", "Rz(π) Z^0 PhISwap(0.25)────PhISwap(0.25)^(5/12)\n", "│ │ │ │\n", "│ PhISwap(0.25)─────────PhISwap(0.25)^-1 Z^0\n", "│ │ │ │\n", "│ Rz(π) Z^0 Rz(π)\n", "│ │ │ │\n", "│ │ Rz(π) │\n", "│ │ │ │\n", "│ PhISwap(0.25)─────────PhISwap(0.25)^-1 │\n", "│ │ │ │\n", "PhISwap(0.25)─PhISwap(0.25)^0.081 Z^0 │\n", "│ │ │ │\n", "Rz(0.112π) Z^0 PhISwap(0.25)────PhISwap(0.25)^-0.081\n", "│ │ │ │\n", "Rz(0) PhISwap(0.25)─────────PhISwap(0.25)^-1 Z^0\n", "│ │ │ │\n", "│ Rz(0.112π) Z^0 Rz(0.056π)\n", "│ │ │ │\n", "│ Rz(0) Rz(0.056π) Rz(0)\n", "│ │ │ │\n", "│ │ Rz(0) │\n", "│ │ │ │\n", "│ PhISwap(0.25)─────────PhISwap(0.25)^-1 │\n", "│ │ │ │\n", "PhISwap(0.25)─PhISwap(0.25)^-0.051 Z^0 │\n", "│ │ │ │\n", "│ Z^0 PhISwap(0.25)────PhISwap(0.25)^0.051\n", "│ │ │ │\n", "│ PhISwap(0.25)─────────PhISwap(0.25)^-1 Z^0\n", "│ │ │ │\n", "@─────────────@^-0.048 Z^0 │\n", "│ │ │ │\n", "×─────────────× @────────────────@^-0.022\n", "│ │ │ │\n", "│ │ ×────────────────×\n", "│ │ │ │\n", "│ @─────────────────────@^-0.033 │\n", "│ │ │ │\n", "│ ×─────────────────────× │\n", "│ │ │ │\n", "@─────────────@^-0.033 @────────────────@^-0.033\n", "│ │ │ │\n", "×─────────────× ×────────────────×\n", "│ │ │ │\n", "Rz(-0.011π) @─────────────────────@^-0.033 Rz(-0.024π)\n", "│ │ │ │\n", "Rz(0) ×─────────────────────× Rz(0)\n", "│ │ │ │\n", "│ Rz(-0.011π) Rz(-0.024π) │\n", "│ │ │ │\n", "│ Rz(π) Rz(π) │\n", "│ │ │ │\n", "│ PhISwap(0.25)─────────PhISwap(0.25)^-1 │\n", "│ │ │ │\n", "│ Z^0 PhISwap(0.25)────PhISwap(0.25)^-0.95\n", "│ │ │ │\n", "PhISwap(0.25)─PhISwap(0.25)^0.95 Z^0 │\n", "│ │ │ │\n", "Z^0 PhISwap(0.25)─────────PhISwap(0.25)^-1 │\n", "│ │ │ │\n", "│ Z^0 @────────────────@^-0.014\n", "│ │ │ │\n", "@─────────────@^-0.006 ×────────────────×\n", "│ │ │ │\n", "×─────────────× │ │\n", "│ │ │ │\n", "│ @─────────────────────@^0.009 │\n", "│ │ │ │\n", "│ ×─────────────────────× │\n", "│ │ │ │\n", "@─────────────@^0.009 @────────────────@^0.009\n", "│ │ │ │\n", "×─────────────× ×────────────────×\n", "│ │ │ │\n", "Rz(-0.007π) @─────────────────────@^0.009 Rz(-0.003π)\n", "│ │ │ │\n", "Rz(π) ×─────────────────────× Rz(π)\n", "│ │ │ │\n", "│ Rz(-0.007π) Rz(-0.003π) │\n", "│ │ │ │\n", "│ Rz(0) Rz(0) │\n", "│ │ │ │\n", "│ PhISwap(0.25)─────────PhISwap(0.25)^-1 │\n", "│ │ │ │\n", "PhISwap(0.25)─PhISwap(0.25)^-0.502 Z^0 │\n", "│ │ │ │\n", "│ Z^0 PhISwap(0.25)────PhISwap(0.25)^0.502\n", "│ │ │ │\n", "│ PhISwap(0.25)─────────PhISwap(0.25)^-1 Z^0\n", "│ │ │ │\n", "@─────────────@^0 Z^0 │\n", "│ │ │ │\n", "×─────────────× @────────────────@^0\n", "│ │ │ │\n", "│ │ ×────────────────×\n", "│ │ │ │\n", "│ @─────────────────────@^0 │\n", "│ │ │ │\n", "│ ×─────────────────────× │\n", "│ │ │ │\n", "@─────────────@^0 @────────────────@^0\n", "│ │ │ │\n", "×─────────────× ×────────────────×\n", "│ │ │ │\n", "Rz(0) @─────────────────────@^0 Rz(0)\n", "│ │ │ │\n", "Rz(π) ×─────────────────────× Rz(π)\n", "│ │ │ │\n", "│ Rz(0) Rz(0) │\n", "│ │ │ │\n", "│ Rz(0) Rz(0) │\n", "│ │ │ │\n", "│ PhISwap(0.25)─────────PhISwap(0.25)^-1 │\n", "│ │ │ │\n", "│ Z^0 PhISwap(0.25)────PhISwap(0.25)^(-5/12)\n", "│ │ │ │\n", "PhISwap(0.25)─PhISwap(0.25)^(5/12) Z^0 │\n", "│ │ │ │\n", "Z^0 PhISwap(0.25)─────────PhISwap(0.25)^-1 │\n", "│ │ │ │\n", "│ Z^0 ×────────────────×\n", "│ │ │ │\n", "×─────────────× │ │\n", "│ │ │ │\n", "│ ×─────────────────────× │\n", "│ │ │ │\n", "×─────────────× ×────────────────×\n", "│ │ │ │\n", "│ ×─────────────────────× │\n", "│ │ │ │\n" ] } ], "source": [ "# Initialize a random initial state.\n", "import numpy\n", "random_seed = 8317\n", "initial_state = openfermion.haar_random_vector(\n", " 2 ** n_qubits, random_seed).astype(numpy.complex64)\n", "\n", "# Numerically compute the correct circuit output.\n", "import scipy\n", "hamiltonian_sparse = openfermion.get_sparse_operator(molecular_hamiltonian)\n", "exact_state = scipy.sparse.linalg.expm_multiply(\n", " -1j * time * hamiltonian_sparse, initial_state)\n", "\n", "# Trotter step parameters.\n", "n_steps = 3\n", "\n", "# Compile the low rank Trotter step using OpenFermion.\n", "qubits = cirq.LineQubit.range(n_qubits)\n", "circuit = cirq.Circuit(\n", " trotter.simulate_trotter(\n", " qubits, molecular_hamiltonian,\n", " time=time, n_steps=n_steps,\n", " algorithm=trotter.LOW_RANK),\n", " strategy=cirq.InsertStrategy.EARLIEST)\n", "\n", "# Use Cirq simulator to apply circuit.\n", "simulator = cirq.Simulator()\n", "result = simulator.simulate(circuit, qubit_order=qubits, initial_state=initial_state)\n", "simulated_state = result.final_state_vector\n", "\n", "# Print final fidelity.\n", "fidelity = abs(numpy.dot(simulated_state, numpy.conjugate(exact_state))) ** 2\n", "print('Fidelity with exact result is {}.\\n'.format(fidelity))\n", "\n", "# Print circuit.\n", "cirq.drop_negligible_operations(circuit)\n", "print(circuit.to_text_diagram(transpose=True))" ] } ], "metadata": { "colab": { "name": "circuits_3_arbitrary_basis_trotter.ipynb", "toc_visible": true }, "kernelspec": { "display_name": "Python 3", "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.10.17" } }, "nbformat": 4, "nbformat_minor": 1 }