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

add on-site number-number interaction gate #86

Merged
merged 1 commit into from
Dec 12, 2023
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
2 changes: 2 additions & 0 deletions python/ffsim/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
apply_num_num_interaction,
apply_num_op_prod_interaction,
apply_num_op_sum_evolution,
apply_on_site_num_num_interaction,
apply_orbital_rotation,
apply_tunneling_interaction,
)
Expand Down Expand Up @@ -98,6 +99,7 @@
"apply_num_num_interaction",
"apply_num_op_prod_interaction",
"apply_num_op_sum_evolution",
"apply_on_site_num_num_interaction",
"apply_orbital_rotation",
"apply_tunneling_interaction",
"apply_unitary",
Expand Down
2 changes: 2 additions & 0 deletions python/ffsim/gates/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
apply_num_interaction,
apply_num_num_interaction,
apply_num_op_prod_interaction,
apply_on_site_num_num_interaction,
apply_tunneling_interaction,
)
from ffsim.gates.diag_coulomb import apply_diag_coulomb_evolution
Expand All @@ -32,6 +33,7 @@
"apply_num_num_interaction",
"apply_num_op_prod_interaction",
"apply_num_op_sum_evolution",
"apply_on_site_num_num_interaction",
"apply_orbital_rotation",
"apply_tunneling_interaction",
]
46 changes: 46 additions & 0 deletions python/ffsim/gates/basic_gates.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,52 @@ def apply_num_num_interaction(
return vec


def apply_on_site_num_num_interaction(
vec: np.ndarray,
theta: float,
target_orb: int,
norb: int,
nelec: tuple[int, int],
*,
copy: bool = True,
):
r"""Apply an on-site number-number interaction gate.

The on-site number-number interaction gate is

.. math::

\text{OSNN}(\theta, p) =
\exp\left(i \theta a^\dagger_{\alpha, p} a_{\alpha, p}
a^\dagger_{\beta, p} a_{\beta, p}\right)

Args:
vec: The state vector to be transformed.
theta: The rotation angle.
target_orb: The orbital on which to apply the interaction.
norb: The number of spatial orbitals.
nelec: The number of alpha and beta electrons.
copy: Whether to copy the vector before operating on it.
- If ``copy=True`` then this function always returns a newly allocated
vector and the original vector is left untouched.
- If ``copy=False`` then this function may still return a newly allocated
vector, but the original vector may have its data overwritten.
It is also possible that the original vector is returned,
modified in-place.
"""
if copy:
vec = vec.copy()
vec = apply_num_op_prod_interaction(
vec,
theta,
target_orbs=([target_orb], [target_orb]),
norb=norb,
nelec=nelec,
copy=False,
)
return vec


def apply_num_op_prod_interaction(
vec: np.ndarray,
theta: float,
Expand Down
36 changes: 34 additions & 2 deletions tests/gates/basic_gates_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ def test_apply_num_interaction(norb: int, nelec: tuple[int, int]):
],
)
def test_apply_num_num_interaction(norb: int, nelec: tuple[int, int]):
"""Test applying number interaction."""
"""Test applying number-number interaction."""
dim = ffsim.dim(norb, nelec)
rng = np.random.default_rng()
vec = np.array(ffsim.random.random_statevector(dim, seed=rng))
Expand Down Expand Up @@ -267,7 +267,7 @@ def test_apply_num_num_interaction(norb: int, nelec: tuple[int, int]):
],
)
def test_apply_num_num_interaction_eigenvalues(norb: int, nelec: tuple[int, int]):
"""Test applying number interaction."""
"""Test eigenvalues of number-number interaction."""
rng = np.random.default_rng()
occupied_orbitals = ffsim.testing.random_occupied_orbitals(norb, nelec)
vec = ffsim.slater_determinant(norb, occupied_orbitals)
Expand All @@ -290,6 +290,38 @@ def test_apply_num_num_interaction_eigenvalues(norb: int, nelec: tuple[int, int]
np.testing.assert_allclose(result, expected)


@pytest.mark.parametrize(
"norb, nelec",
[
(2, (1, 1)),
(3, (2, 1)),
],
)
def test_apply_on_site_num_num_interaction(norb: int, nelec: tuple[int, int]):
"""Test applying on-site number-number interaction."""
dim = ffsim.dim(norb, nelec)
rng = np.random.default_rng()
vec = np.array(ffsim.random.random_statevector(dim, seed=rng))
theta = rng.uniform(-10, 10)
for i in range(norb):
result = ffsim.apply_on_site_num_num_interaction(
vec, theta, i, norb=norb, nelec=nelec
)
generator = ffsim.FermionOperator(
{
(
ffsim.cre_a(i),
ffsim.des_a(i),
ffsim.cre_b(i),
ffsim.des_b(i),
): theta
}
)
linop = ffsim.linear_operator(generator, norb=norb, nelec=nelec)
expected = scipy.sparse.linalg.expm_multiply(1j * linop, vec, traceA=theta)
np.testing.assert_allclose(result, expected)


@pytest.mark.parametrize(
"norb, nelec",
[
Expand Down