Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Docs] Format math expressions #738

Merged
merged 7 commits into from
Jul 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 39 additions & 30 deletions src/openfermion/circuits/gates/fermionic_simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,18 +184,18 @@ def sum_of_interaction_operator_gate_generators(

@cirq.value_equality(approximate=True)
class ParityPreservingFermionicGate(cirq.Gate, metaclass=abc.ABCMeta):
r"""The Jordan-Wigner transform of :math:`\exp(-i H)` for a fermionic
Hamiltonian :math:`H`.
r"""The Jordan-Wigner transform of $\exp(-i H)$ for a fermionic
Hamiltonian $H$.

Each subclass corresponds to a set of generators :math:`\{G_i\}`
corresponding to the family of Hamiltonians :math:`\sum_i w_i G_i +
\text{h.c.}`, where the weights :math:`w_i \in \mathbb C` are specified by
Each subclass corresponds to a set of generators $\{G_i\}$
corresponding to the family of Hamiltonians $\sum_i w_i G_i +
\text{h.c.}$, where the weights $w_i \in \mathbb C$ are specified by
the instance.

The Jordan-Wigner mapping maps the fermionic modes :math:`(0, \ldots, n -
1)` to qubits :math:`(0, \ldots, n - 1)`, respectively.
The Jordan-Wigner mapping maps the fermionic modes $(0, \ldots, n -
1)$ to qubits $(0, \ldots, n - 1)$, respectively.

Each generator :math:`G_i` must be a linear combination of fermionic
Each generator $G_i$ must be a linear combination of fermionic
monomials consisting of an even number of creation/annihilation operators.
This is so that the Jordan-Wigner transform acts only on the gate's qubits,
even when the fermionic modes are offset as part of a larger Jordan-Wigner
Expand Down Expand Up @@ -231,8 +231,8 @@ def __init__(
@staticmethod
@abc.abstractmethod
def fermion_generator_components() -> Tuple['openfermion.FermionOperator']:
r"""The FermionOperators :math:`(G_i)_i` such that the gate's fermionic
generator is :math:`\sum_i w_i G_i + \text{h.c.}` where :math:`(w_i)_i`
r"""The FermionOperators $(G_i)_i$ such that the gate's fermionic
generator is $\sum_i w_i G_i + \text{h.c.}$ where $(w_i)_i$
are the gate's weights."""

@abc.abstractmethod
Expand Down Expand Up @@ -360,8 +360,8 @@ def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs


class InteractionOperatorFermionicGate(ParityPreservingFermionicGate):
r"""The Jordan-Wigner transform of :math:`\exp(-i H)` for a fermionic
Hamiltonian :math:`H`, where :math:`H` is an interaction operator.
r"""The Jordan-Wigner transform of $\exp(-i H)$ for a fermionic
Hamiltonian $H$, where $H$ is an interaction operator.

See openfermion.ParityPreservingFermionicGate and
openfermion.InteractionOperator for more details.
Expand Down Expand Up @@ -401,27 +401,30 @@ class QuadraticFermionicSimulationGate(InteractionOperatorFermionicGate,
cirq.TwoQubitGate, cirq.EigenGate):
r"""``(w0 |10⟩⟨01| + h.c.) + w1 |11⟩⟨11|`` interaction.

With weights :math:`(w_0, w_1)` and exponent :math:`t`, this gate's matrix
With weights $(w_0, w_1)$ and exponent $t$, this gate's matrix
is defined as

.. math::
$$
e^{-i t H},
$$

where

.. math::
$$
H = \left(w_0 \left| 10 \right\rangle\left\langle 01 \right| +
\text{h.c.}\right) -
w_1 \left| 11 \right\rangle \left\langle 11 \right|.
$$

This corresponds to the Jordan-Wigner transform of

.. math::
$$
H = (w_0 a^{\dagger}_i a_{i+1} + \text{h.c.}) +
w_1 a_{i}^{\dagger} a_{i+1}^{\dagger} a_{i} a_{i+1},
$$

where :math:`a_i` and :math:`a_{i+1}` are the annihilation operators for
the fermionic modes :math:`i` and :math:`(i+1)`, respectively mapped to the
where $a_i$ and $a_{i+1}$ are the annihilation operators for
the fermionic modes $i$ and $(i+1)$, respectively mapped to the
first and second qubits on which this gate acts.

Args:
Expand Down Expand Up @@ -532,34 +535,37 @@ class CubicFermionicSimulationGate(InteractionOperatorFermionicGate,
cirq.ThreeQubitGate, cirq.EigenGate):
r"""``w0|110⟩⟨101| + w1|110⟩⟨011| + w2|101⟩⟨011|`` + h.c. interaction.

With weights :math:`(w_0, w_1, w_2)` and exponent :math:`t`, this gate's
With weights $(w_0, w_1, w_2)$ and exponent $t$, this gate's
matrix is defined as

.. math::
$$
e^{-i t H},
$$

where

.. math::
$$
H = \left(w_0 \left| 110 \right\rangle\left\langle 101 \right| +
\text{h.c.}\right) +
\left(w_1 \left| 110 \right\rangle\left\langle 011 \right| +
\text{h.c.}\right) +
\left(w_2 \left| 101 \right\rangle\left\langle 011 \right| +
\text{h.c.}\right)
$$

This corresponds to the Jordan-Wigner transform of

.. math::
$$
H = -\left(w_0 a^{\dagger}_i a^{\dagger}_{i+1} a_{i} a_{i+2} +
\text{h.c.}\right) -
\left(w_1 a^{\dagger}_i a^{\dagger}_{i+1} a_{i+1} a_{i+2} +
\text{h.c.}\right) -
\left(w_2 a^{\dagger}_i a^{\dagger}_{i+2} a_{i+1} a_{i+2} +
\text{h.c.}\right),
$$

where :math:`a_i`, :math:`a_{i+1}`, :math:`a_{i+2}` are the annihilation
operators for the fermionic modes :math:`i`, :math:`(i+1)` :math:`(i+2)`,
where $a_i$, $a_{i+1}$, $a_{i+2}$ are the annihilation
operators for the fermionic modes $i$, $(i+1)$ $(i+2)$,
respectively mapped to the three qubits on which this gate acts.

Args:
Expand Down Expand Up @@ -681,34 +687,37 @@ class QuarticFermionicSimulationGate(InteractionOperatorFermionicGate,
cirq.EigenGate):
r"""Rotates Hamming-weight 2 states into their bitwise complements.

With weights :math:`(w_0, w_1, w_2)` and exponent :math:`t`, this gate's
With weights $(w_0, w_1, w_2)$ and exponent $t$, this gate's
matrix is defined as

.. math::
$$
e^{-i t H},
$$

where

.. math::
$$
H = \left(w_0 \left| 1001 \right\rangle\left\langle 0110 \right| +
\text{h.c.}\right) +
\left(w_1 \left| 1010 \right\rangle\left\langle 0101 \right| +
\text{h.c.}\right) +
\left(w_2 \left| 1100 \right\rangle\left\langle 0011 \right| +
\text{h.c.}\right)
$$

This corresponds to the Jordan-Wigner transform of

.. math::
$$
H = -\left(w_0 a^{\dagger}_i a^{\dagger}_{i+3} a_{i+1} a_{i+2} +
\text{h.c.}\right) -
\left(w_1 a^{\dagger}_i a^{\dagger}_{i+2} a_{i+1} a_{i+3} +
\text{h.c.}\right) -
\left(w_2 a^{\dagger}_i a^{\dagger}_{i+1} a_{i+2} a_{i+3} +
\text{h.c.}\right),
$$

where :math:`a_i`, ..., :math:`a_{i+3}` are the annihilation operators for
the fermionic modes :math:`i`, ..., :math:`(i+3)`, respectively
where $a_i$, ..., $a_{i+3}$ are the annihilation operators for
the fermionic modes $i$, ..., $(i+3)$, respectively
mapped to the four qubits on which this gate acts.


Expand Down
34 changes: 17 additions & 17 deletions src/openfermion/circuits/low_rank.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,26 @@ def get_chemist_two_body_coefficients(two_body_coefficients, spin_basis=True):
r"""Convert two-body operator coefficients to low rank tensor.

The input is a two-body fermionic Hamiltonian expressed as
:math:`\sum_{pqrs} h_{pqrs} a^\dagger_p a^\dagger_q a_r a_s`
$\sum_{pqrs} h_{pqrs} a^\dagger_p a^\dagger_q a_r a_s$

We will convert this to the chemistry convention expressing it as
:math:`\sum_{pqrs} g_{pqrs} a^\dagger_p a_q a^\dagger_r a_s`
$\sum_{pqrs} g_{pqrs} a^\dagger_p a_q a^\dagger_r a_s$
but without the spin degree of freedom.

In the process of performing this conversion, constants and one-body
terms come out, which will be returned as well.

Args:
two_body_coefficients (ndarray): an N x N x N x N
numpy array giving the :math:`h_{pqrs}` tensor.
numpy array giving the $h_{pqrs}$ tensor.
spin_basis (bool): True if the two-body terms are passed in spin
orbital basis. False if already in spatial orbital basis.

Returns:
one_body_correction (ndarray): an N x N array of floats giving
coefficients of the :math:`a^\dagger_p a_q` terms that come out.
coefficients of the $a^\dagger_p a_q$ terms that come out.
chemist_two_body_coefficients (ndarray): an N x N x N x N numpy array
giving the :math:`g_{pqrs}` tensor in chemist notation.
giving the $g_{pqrs}$ tensor in chemist notation.

Raises:
TypeError: Input must be two-body number conserving
Expand Down Expand Up @@ -80,14 +80,14 @@ def low_rank_two_body_decomposition(two_body_coefficients,
r"""Convert two-body operator into sum of squared one-body operators.

As in arXiv:1808.02625, this function decomposes
:math:`\sum_{pqrs} h_{pqrs} a^\dagger_p a^\dagger_q a_r a_s` as
:math:`\sum_{l} \lambda_l (\sum_{pq} g_{lpq} a^\dagger_p a_q)^2`
$\sum_{pqrs} h_{pqrs} a^\dagger_p a^\dagger_q a_r a_s$ as
$\sum_{l} \lambda_l (\sum_{pq} g_{lpq} a^\dagger_p a_q)^2$
l is truncated to take max value L so that
:math:`\sum_{l=0}^{L-1} (\sum_{pq} |g_{lpq}|)^2 |\lambda_l| < x`
$\sum_{l=0}^{L-1} (\sum_{pq} |g_{lpq}|)^2 |\lambda_l| < x$

Args:
two_body_coefficients (ndarray): an N x N x N x N
numpy array giving the :math:`h_{pqrs}` tensor.
numpy array giving the $h_{pqrs}$ tensor.
This tensor must be 8-fold symmetric (real integrals).
truncation_threshold (optional Float): the value of x, above.
final_rank (optional int): if provided, this specifies the value of
Expand All @@ -97,13 +97,13 @@ def low_rank_two_body_decomposition(two_body_coefficients,

Returns:
eigenvalues (ndarray of floats): length L array
giving the :math:`\lambda_l`.
giving the $\lambda_l$.
one_body_squares (ndarray of floats): L x N x N array of floats
corresponding to the value of :math:`g_{pql}`.
corresponding to the value of $g_{pql}$.
one_body_correction (ndarray): One-body correction terms that result
from reordering to chemist ordering, in spin-orbital basis.
truncation_value (float): after truncation, this is the value
:math:`\sum_{l=0}^{L-1} (\sum_{pq} |g_{lpq}|)^2 |\lambda_l| < x`
$\sum_{l=0}^{L-1} (\sum_{pq} |g_{lpq}|)^2 |\lambda_l| < x$

Raises:
TypeError: Invalid two-body coefficient tensor specification.
Expand Down Expand Up @@ -163,22 +163,22 @@ def prepare_one_body_squared_evolution(one_body_matrix, spin_basis=True):
r"""Get Givens angles and DiagonalHamiltonian to simulate squared one-body.

The goal here will be to prepare to simulate evolution under
:math:`(\sum_{pq} h_{pq} a^\dagger_p a_q)^2` by decomposing as
:math:`R e^{-i \sum_{pq} V_{pq} n_p n_q} R^\dagger' where
:math:`R` is a basis transformation matrix.
$(\sum_{pq} h_{pq} a^\dagger_p a_q)^2$ by decomposing as
$R e^{-i \sum_{pq} V_{pq} n_p n_q} R^\dagger$ where
$R$ is a basis transformation matrix.

TODO: Add option for truncation based on one-body eigenvalues.

Args:
one_body_matrix (ndarray of floats): an N by N array storing the
coefficients of a one-body operator to be squared. For instance,
in the above the elements of this matrix are :math:`h_{pq}`.
in the above the elements of this matrix are $h_{pq}$.
spin_basis (bool): Whether the matrix is passed in the
spin orbital basis.

Returns:
density_density_matrix(ndarray of floats) an N by N array storing
the diagonal two-body coefficeints :math:`V_{pq}` above.
the diagonal two-body coefficeints $V_{pq}$ above.
basis_transformation_matrix (ndarray of floats) an N by N array
storing the values of the basis transformation.

Expand Down
30 changes: 15 additions & 15 deletions src/openfermion/circuits/primitives/bogoliubov_transform.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,41 +28,41 @@ def bogoliubov_transform(
r"""Perform a Bogoliubov transformation.

This circuit performs the transformation to a basis determined by a new set
of fermionic ladder operators. It performs the unitary :math:`U` such that

.. math::
of fermionic ladder operators. It performs the unitary $U$ such that

$$
U a^\dagger_p U^{-1} = b^\dagger_p
$$

where the :math:`a^\dagger_p` are the original creation operators and the
:math:`b^\dagger_p` are the new creation operators. The new creation
where the $a^\dagger_p$ are the original creation operators and the
$b^\dagger_p$ are the new creation operators. The new creation
operators are linear combinations of the original ladder operators with
coefficients given by the matrix `transformation_matrix`, which will be
referred to as :math:`W` in the following.
referred to as $W$ in the following.

If :math:`W` is an `N \times N` matrix, then the :math:`b^\dagger_p` are
If $W$ is an $N \times N$ matrix, then the $b^\dagger_p$ are
given by

.. math::

$$
b^\dagger_p = \sum_{q=1}^N W_{pq} a^\dagger_q.
$$

If :math:`W` is an `N \times 2N` matrix, then the :math:`b^\dagger_p` are
If $W$ is an $N \times 2N$ matrix, then the $b^\dagger_p$ are
given by

.. math::

$$
b^\dagger_p = \sum_{q=1}^N W_{pq} a^\dagger_q
+ \sum_{q=N+1}^{2N} W_{pq} a_q.
$$

This algorithm assumes the Jordan-Wigner Transform.

Args:
qubits: The qubits to which to apply the circuit.
transformation_matrix: The matrix :math:`W` holding the coefficients
transformation_matrix: The matrix $W$ holding the coefficients
that describe the new creation operators in terms of the original
ladder operators. Its shape should be either :math:`NxN` or
:math:`Nx(2N)`, where :math:`N` is the number of qubits.
ladder operators. Its shape should be either $NxN$ or
$Nx(2N)$, where $N$ is the number of qubits.
initial_state: Optionally specifies a computational basis state
to assume that the qubits start in. This assumption enables
optimizations that result in a circuit with fewer gates.
Expand Down
Loading