Skip to content

Commit

Permalink
Deploying to gh-pages from @ 955b43f 🚀
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinsung committed Jul 23, 2024
1 parent 021361b commit 2074806
Show file tree
Hide file tree
Showing 229 changed files with 73,304 additions and 0 deletions.
4 changes: 4 additions & 0 deletions stable/v0.0.43/.buildinfo
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
config: 49d4efd4548eac48d2129af8ca1c8733
tags: 645f666f9bcd5a90fca523b33c5a78b7
Binary file not shown.
Binary file added stable/v0.0.43/.doctrees/api/ffsim.doctree
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added stable/v0.0.43/.doctrees/api/index.doctree
Binary file not shown.
Binary file added stable/v0.0.43/.doctrees/environment.pickle
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added stable/v0.0.43/.doctrees/index.doctree
Binary file not shown.
Binary file added stable/v0.0.43/.doctrees/install.doctree
Binary file not shown.
122 changes: 122 additions & 0 deletions stable/v0.0.43/.doctrees/nbsphinx/explanations/double-factorized.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Double-factorized representation of the molecular Hamiltonian\n",
"\n",
"This page discusses the double-factorized representation of the molecular Hamiltonian.\n",
"\n",
"## Double-factorized representation\n",
"\n",
"The molecular Hamiltonian is commonly written in the form\n",
"\n",
"$$\n",
" H = \\sum_{\\sigma, pq} h_{pq} a^\\dagger_{\\sigma, p} a_{\\sigma, q}\n",
" + \\frac12 \\sum_{\\sigma \\tau, pqrs} h_{pqrs}\n",
" a^\\dagger_{\\sigma, p} a^\\dagger_{\\tau, r} a_{\\tau, s} a_{\\sigma, q}\n",
" + \\text{constant}.\n",
"$$\n",
"\n",
"This representation of the Hamiltonian is daunting for quantum simulations because the number of terms in the two-body part scales as $N^4$ where $N$ is the number of spatial orbitals. An alternative representation can be obtained by performing a \"double-factorization\" of the two-body tensor $h_{pqrs}$:\n",
"\n",
"$$\n",
" H = \\sum_{\\sigma, pq} h'_{pq} a^\\dagger_{\\sigma, p} a_{\\sigma, q}\n",
" + \\sum_{k=1}^L \\mathcal{W}_k \\mathcal{J}_k \\mathcal{W}_k^\\dagger\n",
" + \\text{constant}'.\n",
"$$\n",
"\n",
"Here each $\\mathcal{W}_k$ is an [orbital rotation](orbital-rotation.ipynb) and each $\\mathcal{J}_k$ is a so-called diagonal Coulomb operator of the form\n",
"\n",
"$$\n",
" \\mathcal{J} = \\frac12\\sum_{\\sigma \\tau, ij} \\mathbf{J}_{ij} n_{\\sigma, i} n_{\\tau, j},\n",
"$$\n",
"\n",
"where $n_{\\sigma, i} = a^\\dagger_{\\sigma, i} a_{\\sigma, i}$ is the occupation number operator and $\\mathbf{J}_{ij}$ is a real symmetric matrix. The one-body tensor and the constant have been updated to accomodate extra terms that arise from reordering fermionic ladder operators.\n",
"\n",
"For an exact factorization, $L$ is proportional to $N^2$. However, the two-body tensor often has low-rank structure, and the decomposition can be truncated while still maintaining an accurate representation. Thus, in practice, $L$ often scales only linearly with $N$, resulting in a much more compact representation that gives rise to more efficient schemes for simulating and measuring the Hamiltonian, which utilize efficient quantum circuits for orbital rotations and time evolution by a diagonal Coulomb operator.\n",
"\n",
"## Application to time evolution via Trotter-Suzuki formulas\n",
"\n",
"In this section, we discuss how the double-factorized Hamiltonian can be simulated using Trotter-Suzuki formulas.\n",
"\n",
"### Brief background on Trotter-Suzuki formulas\n",
"\n",
"Trotter-Suzuki formulas are used to approximate time evolution by a Hamiltonian $H$ which is decomposed as a sum of terms:\n",
"\n",
"$$\n",
"H = \\sum_k H_k.\n",
"$$\n",
"\n",
"Time evolution by time $t$ is given by the unitary operator\n",
"\n",
"$$\n",
"e^{i H t}.\n",
"$$\n",
"\n",
"To approximate this operator, the total evolution time is first divided into a number of smaller time steps, called \"Trotter steps\":\n",
"\n",
"$$\n",
"e^{i H t} = (e^{i H t / r})^r.\n",
"$$\n",
"\n",
"The time evolution for a single Trotter step is then approximated using a product formula, which approximates the exponential of a sum of terms by a product of exponentials of the individual terms. The formulas are approximate because the terms do not in general commute. A first-order asymmetric product formula has the form\n",
"\n",
"$$\n",
"e^{i H \\tau} \\approx \\prod_k e^{i H_k \\tau}.\n",
"$$\n",
"\n",
"Higher-order formulas can be derived which yield better approximations.\n",
"\n",
"### Application to the double-factorized Hamiltonian\n",
"\n",
"Using the double-factorized representation, the Hamiltonian is decomposed into $L+1$ terms (ignoring the constant term),\n",
"\n",
"$$\n",
"H = \\sum_{k=0}^L H_k,\n",
"$$\n",
"\n",
"where\n",
"\n",
"$$\n",
"H_0 = \\sum_{\\sigma, pq} h'_{pq} a^\\dagger_{\\sigma, p} a_{\\sigma, q}\n",
"$$\n",
"\n",
"and for $k = 1, \\ldots, L$,\n",
"\n",
"$$\n",
"H_k = \\mathcal{W}_k \\mathcal{J}_k \\mathcal{W}_k^\\dagger.\n",
"$$\n",
"\n",
"We have that\n",
"\n",
"- $H_0$ is a quadratic Hamiltonian and can be simulated as described in [Orbital rotations and quadratic Hamiltonians](orbital-rotation.ipynb#Time-evolution-by-a-quadratic-Hamiltonian), and\n",
"- $H_k$ is a diagonal Coulomb operator (up to an orbital rotation) for $k = 1, \\ldots, L$, and ffsim includes the function [apply_diag_coulomb_evolution](../api/ffsim.rst#ffsim.apply_diag_coulomb_evolution) for simulating time evolution by such an operator.\n",
"\n",
"Given the ability to simulate each of the individual terms, we can implement Trotter-Suzuki formulas for time evolution by the entire Hamiltonian. This is implemented in ffsim by the function [simulate_trotter_double_factorized](../api/ffsim.rst#ffsim.simulate_trotter_double_factorized), which implements higher-order Trotter-Suzuki formulas in addition to the first-order asymmetric formula mentioned previously. The first-order asymmetric formula corresponds to setting the argument `order=0`, which is the default. `order=1` corresponds to the first-order symmetric (commonly known as the second-order) formula, `order=2` corresponds to the second-order symmetric (fourth-order) formula, and so on."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "ffsim-1cfkSnAR",
"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.12.4"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
263 changes: 263 additions & 0 deletions stable/v0.0.43/.doctrees/nbsphinx/explanations/hamiltonians.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Hamiltonians\n",
"\n",
"This page explains how ffsim represents Hamiltonians.\n",
"\n",
"## Data representation\n",
"\n",
"ffsim includes several classes for representing Hamiltonians in different forms. In this page we'll focus on the molecular Hamiltonian of the form\n",
"\n",
"$$\n",
"H = \\sum_{\\sigma, pq} h_{pq} a^\\dagger_{\\sigma, p} a_{\\sigma, q}\n",
" + \\frac12 \\sum_{\\sigma \\tau, pqrs} h_{pqrs}\n",
" a^\\dagger_{\\sigma, p} a^\\dagger_{\\tau, r} a_{\\tau, s} a_{\\sigma, q}\n",
" + \\text{constant}.\n",
"$$\n",
"\n",
"To represent this Hamiltonian, the information that needs to be stored consists of ($N$ is the number of spatial orbitals):\n",
"\n",
"- The one-body tensor $h_{pq}$, which is an $N \\times N$ matrix (stored as a NumPy array).\n",
"- The two-body tensor $h_{pqrs}$, which is an $N \\times N \\times N \\times N$ tensor (stored as a NumPy array).\n",
"- The constant, which is a real number (stored as a float).\n",
"\n",
"In order to have some concrete objects to work with, we sample some random instances of these data in the following code cell."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"execution": {
"iopub.execute_input": "2024-07-23T22:27:19.612468Z",
"iopub.status.busy": "2024-07-23T22:27:19.612046Z",
"iopub.status.idle": "2024-07-23T22:27:20.363764Z",
"shell.execute_reply": "2024-07-23T22:27:20.363097Z"
}
},
"outputs": [],
"source": [
"import numpy as np\n",
"\n",
"import ffsim\n",
"\n",
"# Use 4 spatial orbitals, as an example.\n",
"norb = 4\n",
"\n",
"rng = np.random.default_rng(1234)\n",
"one_body_tensor = ffsim.random.random_real_symmetric_matrix(norb, seed=rng)\n",
"# Pass dtype=float to obtain a real-valued two-body tensor.\n",
"# Complex tensors are not fully supported yet.\n",
"two_body_tensor = ffsim.random.random_two_body_tensor(norb, seed=rng, dtype=float)\n",
"constant = rng.standard_normal()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The molecular Hamiltonian is represented in ffsim using the [MolecularHamiltonian](../api/ffsim.rst#ffsim.MolecularHamiltonian) class. You initialize the class by passing the three pieces of information (the constant is optional and defaults to zero if not specified):"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"execution": {
"iopub.execute_input": "2024-07-23T22:27:20.366747Z",
"iopub.status.busy": "2024-07-23T22:27:20.366427Z",
"iopub.status.idle": "2024-07-23T22:27:20.369530Z",
"shell.execute_reply": "2024-07-23T22:27:20.369011Z"
}
},
"outputs": [],
"source": [
"mol_hamiltonian = ffsim.MolecularHamiltonian(\n",
" one_body_tensor=one_body_tensor,\n",
" two_body_tensor=two_body_tensor,\n",
" constant=constant,\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The arguments passed to the initialization are now available as attributes of the same name, i.e., `mol_hamiltonian.one_body_tensor` accesses the one-body tensor.\n",
"\n",
"## Operator action via SciPy LinearOperators\n",
"\n",
"The basic operation that a Hamiltonian represention should support is applying its action, as a linear operator, to a vector. This basic operation can be used to implement more complex ones, such as operator exponentiation and eigenvalue computation. ffsim uses Scipy's [LinearOperator](https://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.linalg.LinearOperator.html) class to support these operations for Hamiltonians. To obtain a LinearOperator, call the `linear_operator` function:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"execution": {
"iopub.execute_input": "2024-07-23T22:27:20.372052Z",
"iopub.status.busy": "2024-07-23T22:27:20.371636Z",
"iopub.status.idle": "2024-07-23T22:27:20.375353Z",
"shell.execute_reply": "2024-07-23T22:27:20.374848Z"
}
},
"outputs": [],
"source": [
"# Use 2 alpha electrons and 2 beta electrons, as an example.\n",
"nelec = (2, 2)\n",
"\n",
"linop = ffsim.linear_operator(mol_hamiltonian, norb=norb, nelec=nelec)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The `linear_operator` function requires the number of orbitals and the number of alpha and beta electrons to be passed because this information is needed to fully specify the vector space on which the linear operator acts.\n",
"\n",
"LinearOperators support matrix multiplication with a vector:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"execution": {
"iopub.execute_input": "2024-07-23T22:27:20.377591Z",
"iopub.status.busy": "2024-07-23T22:27:20.377392Z",
"iopub.status.idle": "2024-07-23T22:27:20.382628Z",
"shell.execute_reply": "2024-07-23T22:27:20.382024Z"
}
},
"outputs": [],
"source": [
"vec = ffsim.hartree_fock_state(norb, nelec)\n",
"\n",
"result = linop @ vec"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"They also work with many of Scipy's sparse linear algebra routines. For example, you can compute the ground state energy using the `eigsh` eigenvalue routine:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"execution": {
"iopub.execute_input": "2024-07-23T22:27:20.386036Z",
"iopub.status.busy": "2024-07-23T22:27:20.385798Z",
"iopub.status.idle": "2024-07-23T22:27:20.407456Z",
"shell.execute_reply": "2024-07-23T22:27:20.406687Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
"np.float64(-99.55717072551552)"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import scipy.sparse.linalg\n",
"\n",
"eigs, vecs = scipy.sparse.linalg.eigsh(linop, k=1, which=\"SA\")\n",
"energy = eigs[0]\n",
"\n",
"energy"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Time evolution by the Hamiltonian can be computed using `expm_multiply`:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"execution": {
"iopub.execute_input": "2024-07-23T22:27:20.445241Z",
"iopub.status.busy": "2024-07-23T22:27:20.444751Z",
"iopub.status.idle": "2024-07-23T22:27:20.843157Z",
"shell.execute_reply": "2024-07-23T22:27:20.842508Z"
}
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/tmp/ipykernel_4288/2190712273.py:2: UserWarning: Trace of LinearOperator not available, it will be estimated. Provide `traceA` to ensure performance.\n",
" evolved_vec = scipy.sparse.linalg.expm_multiply(-1j * time * linop, vec)\n"
]
}
],
"source": [
"time = 1.0\n",
"evolved_vec = scipy.sparse.linalg.expm_multiply(-1j * time * linop, vec)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"When passing a LinearOperator to `expm_multiply`, Scipy issues a warning if an estimate of the trace is not provided via the `traceA` argument. You can avoid this warning by passing an estimate of the trace. For Hamiltonians with real-valued tensors, the `trace` function can compute the exact trace (complex-valued tensors are not supported yet):"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"execution": {
"iopub.execute_input": "2024-07-23T22:27:20.847559Z",
"iopub.status.busy": "2024-07-23T22:27:20.846418Z",
"iopub.status.idle": "2024-07-23T22:27:21.208241Z",
"shell.execute_reply": "2024-07-23T22:27:21.207580Z"
}
},
"outputs": [],
"source": [
"trace = ffsim.trace(mol_hamiltonian, norb=norb, nelec=nelec)\n",
"evolved_vec_2 = scipy.sparse.linalg.expm_multiply(\n",
" -1j * time * linop, vec, traceA=-1j * time * trace\n",
")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "ffsim-1cfkSnAR",
"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.12.4"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
82 changes: 82 additions & 0 deletions stable/v0.0.43/.doctrees/nbsphinx/explanations/lucj.ipynb

Large diffs are not rendered by default.

Loading

0 comments on commit 2074806

Please sign in to comment.