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

Build hamiltonians from custom lattices #6226

Merged
merged 96 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
7f63b0f
[skip ci] Added Kitaev model Hamiltonian
ddhawan11 Aug 28, 2024
756dd76
Update pennylane/spin/spin_hamiltonian.py
ddhawan11 Aug 28, 2024
ed029a5
Cleaned up some
ddhawan11 Sep 3, 2024
7177342
Merge branch 'master' into kitaev_model
ddhawan11 Sep 3, 2024
4026924
Merge branch 'master' into kitaev_model
ddhawan11 Sep 4, 2024
1db7eb5
docstring fix
ddhawan11 Sep 4, 2024
c15a6f5
Update pennylane/spin/spin_hamiltonian.py
ddhawan11 Sep 4, 2024
702864f
Added custom_edges example
ddhawan11 Sep 5, 2024
f0cbfbe
Merge branch 'master' into kitaev_model
ddhawan11 Sep 5, 2024
4a4d6bf
docstring fix
ddhawan11 Sep 5, 2024
e766e2e
docstring fix
ddhawan11 Sep 5, 2024
393dc0e
custom spin hamiltonian function
austingmhuang Sep 5, 2024
9f6e9e4
Update pennylane/spin/lattice.py
ddhawan11 Sep 6, 2024
f47b3ec
Update pennylane/spin/spin_hamiltonian.py
ddhawan11 Sep 6, 2024
902be92
Update pennylane/spin/lattice.py
ddhawan11 Sep 6, 2024
201fab9
Update pennylane/spin/lattice.py
ddhawan11 Sep 6, 2024
17317b0
Merge branch 'master' into kitaev_model
ddhawan11 Sep 6, 2024
d3ced11
Addressed comments
ddhawan11 Sep 6, 2024
44491ba
Merge branch 'master' into kitaev_model
ddhawan11 Sep 6, 2024
54624a5
draft tests and code
austingmhuang Sep 6, 2024
5386827
Update pennylane/spin/lattice.py
ddhawan11 Sep 8, 2024
c285ec7
Update pennylane/spin/spin_hamiltonian.py
ddhawan11 Sep 8, 2024
0972735
fixed docstring for custom_edges
ddhawan11 Sep 9, 2024
60491e2
Fixed tests
ddhawan11 Sep 9, 2024
af8c601
Updated changelog
ddhawan11 Sep 9, 2024
cd42fde
Documentation build fix
ddhawan11 Sep 9, 2024
15b6222
test for error
austingmhuang Sep 9, 2024
05cad7d
import errors
austingmhuang Sep 9, 2024
82aa678
import errors
austingmhuang Sep 9, 2024
0b96a07
import errors
austingmhuang Sep 9, 2024
2075d93
import errors
austingmhuang Sep 9, 2024
8dc021b
Update doc/releases/changelog-dev.md
ddhawan11 Sep 10, 2024
e350990
Update pennylane/spin/spin_hamiltonian.py
ddhawan11 Sep 10, 2024
a8288e6
Update pennylane/spin/spin_hamiltonian.py
ddhawan11 Sep 10, 2024
d80c494
Update pennylane/spin/lattice.py
ddhawan11 Sep 16, 2024
5b940d4
Update pennylane/spin/lattice.py
ddhawan11 Sep 16, 2024
acd399d
Update pennylane/spin/lattice.py
ddhawan11 Sep 16, 2024
9b4579e
Update pennylane/spin/lattice.py
ddhawan11 Sep 16, 2024
c4db4eb
Addressed comments
ddhawan11 Sep 16, 2024
8cf6bbb
Merge branch 'master' into kitaev_model
ddhawan11 Sep 17, 2024
5ac6844
Merge branch 'master' into kitaev_model
obliviateandsurrender Sep 17, 2024
f600efb
minor docstring fix
ddhawan11 Sep 19, 2024
775ba90
Addressed comments
ddhawan11 Sep 20, 2024
81c9766
used dictionary for lattice mapping
ddhawan11 Sep 20, 2024
d92d431
Merge branch 'master' into kitaev_model
ddhawan11 Sep 20, 2024
f12a173
Update doc/releases/changelog-dev.md
ddhawan11 Sep 20, 2024
3eadc14
Update pennylane/spin/lattice.py
ddhawan11 Sep 20, 2024
5e0f4d7
address comments
austingmhuang Sep 20, 2024
b4a0f9c
docstring update
austingmhuang Sep 20, 2024
0d49388
temp custom nodes
austingmhuang Sep 20, 2024
3cfbe56
fixes
austingmhuang Sep 20, 2024
804498e
fixes
austingmhuang Sep 20, 2024
b45dd17
resolved conflicts
ddhawan11 Sep 20, 2024
2c0c7b0
Merge branch 'master' into kitaev_model
ddhawan11 Sep 20, 2024
d9f9144
Update tests/spin/test_lattice.py
ddhawan11 Sep 20, 2024
e426979
spin hamiltonian lattice
austingmhuang Sep 20, 2024
828e7e7
spin hamiltonian lattice
austingmhuang Sep 20, 2024
188ddd6
Update tests/spin/test_spin_hamiltonian.py
austingmhuang Sep 20, 2024
b792a94
Merge branch 'kitaev_model' into custom_lattice_function
austingmhuang Sep 20, 2024
9e554f2
merge conflicts and quick fixes
austingmhuang Sep 20, 2024
9c68d74
Update pennylane/spin/lattice.py
austingmhuang Sep 20, 2024
7c3360e
address most comments
austingmhuang Sep 20, 2024
1d0f533
merge confs
austingmhuang Sep 20, 2024
7151456
merge confs
austingmhuang Sep 20, 2024
1fed9ab
merge confs
austingmhuang Sep 20, 2024
d5e88da
merge confs
austingmhuang Sep 20, 2024
38d3832
merge confs
austingmhuang Sep 20, 2024
8dc63e2
merge confs
austingmhuang Sep 20, 2024
86934cc
merge confs
austingmhuang Sep 20, 2024
880fe66
merge confs
austingmhuang Sep 20, 2024
346e975
merge confs
austingmhuang Sep 20, 2024
3bc6469
merge confs
austingmhuang Sep 20, 2024
1020990
pylint
austingmhuang Sep 20, 2024
8a4866c
opqrst
austingmhuang Sep 20, 2024
cf1e376
opqrst
austingmhuang Sep 20, 2024
8dadcfe
Update pennylane/spin/spin_hamiltonian.py
austingmhuang Sep 20, 2024
be08721
Update pennylane/spin/spin_hamiltonian.py
austingmhuang Sep 20, 2024
97fd0ff
Update pennylane/spin/lattice.py
austingmhuang Sep 20, 2024
04fe016
address comments
austingmhuang Sep 20, 2024
4b91a85
address comments
austingmhuang Sep 20, 2024
7669353
Update tests/spin/test_spin_hamiltonian.py
austingmhuang Sep 20, 2024
bfa9e2f
Update tests/spin/test_spin_hamiltonian.py
austingmhuang Sep 20, 2024
eb0670b
address comments
austingmhuang Sep 20, 2024
9af9532
Update tests/spin/test_lattice.py
austingmhuang Sep 20, 2024
94df8e1
Update pennylane/spin/lattice.py
austingmhuang Sep 20, 2024
66a5488
Update pennylane/spin/spin_hamiltonian.py
austingmhuang Sep 20, 2024
a70d2bc
Update pennylane/spin/spin_hamiltonian.py
austingmhuang Sep 20, 2024
132177b
addres comments
austingmhuang Sep 20, 2024
7fc2137
i guess this is a bit more accurate?
austingmhuang Sep 20, 2024
22e1e10
like this?
austingmhuang Sep 20, 2024
e01f4f5
like this?
austingmhuang Sep 20, 2024
465fbc4
Update pennylane/spin/spin_hamiltonian.py
austingmhuang Sep 20, 2024
cc51482
changelog entry
austingmhuang Sep 20, 2024
4b39e33
docs
austingmhuang Sep 20, 2024
ac7e49f
Merge branch 'master' into custom_lattice_function
soranjh Sep 20, 2024
ae632f5
Merge branch 'master' into custom_lattice_function
soranjh Sep 20, 2024
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
4 changes: 4 additions & 0 deletions doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
[Kitaev](https://arxiv.org/abs/cond-mat/0506438) model on a lattice.
[(#6174)](https://github.com/PennyLaneAI/pennylane/pull/6174)

* Function is added for generating the spin Hamiltonians for custom lattices.
[(#6226)](https://github.com/PennyLaneAI/pennylane/pull/6226)

* Functions are added for generating spin Hamiltonians for [Emery]
(https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.58.2794) and
[Haldane](https://journals.aps.org/prl/pdf/10.1103/PhysRevLett.61.2015) models on a lattice.
Expand Down Expand Up @@ -203,6 +206,7 @@ Diksha Dhawan,
Lillian M. A. Frederiksen,
Pietropaolo Frisoni,
Emiliano Godinez,
Austin Huang,
Christina Lee,
William Maxwell,
Lee J. O'Riordan,
Expand Down
10 changes: 9 additions & 1 deletion pennylane/spin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,12 @@
"""

from .lattice import Lattice
from .spin_hamiltonian import emery, fermi_hubbard, haldane, heisenberg, kitaev, transverse_ising
from .spin_hamiltonian import (
emery,
fermi_hubbard,
haldane,
heisenberg,
kitaev,
spin_hamiltonian,
transverse_ising,
)
21 changes: 20 additions & 1 deletion pennylane/spin/lattice.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

# pylint: disable=too-many-arguments, too-many-instance-attributes
# pylint: disable=use-a-generator, too-few-public-methods
# pylint: disable=too-many-branches


class Lattice:
Expand All @@ -32,7 +33,7 @@ class Lattice:
Args:
n_cells (list[int]): Number of cells in each direction of the grid.
vectors (list[list[float]]): Primitive vectors for the lattice.
positions (list[list[float]]): Initial positions of spin cites. Default value is
positions (list[list[float]]): Initial positions of spin sites. Default value is
austingmhuang marked this conversation as resolved.
Show resolved Hide resolved
``[[0.0]`` :math:`\times` ``number of dimensions]``.
boundary_condition (bool or list[bool]): Defines boundary conditions for different lattice axes,
default is ``False`` indicating open boundary condition.
Expand All @@ -44,6 +45,11 @@ class Lattice:
First tuple contains the indices of the starting and ending vertices of the edge.
Second tuple is optional and contains the operator on that edge and coefficient
of that operator. Default value is the index of edge in custom_edges list.
custom_nodes (Optional(list(list(int, tuples)))): Specifies the on-site potentials and
operators for nodes in the lattice. The default value is `None`, which means no on-site
potentials. Each element in the list is for a separate node. For each element, the first
value is the index of the node, and the second element is a tuple which contains the
operator and coefficient.
distance_tol (float): Distance below which spatial points are considered equal for the
purpose of identifying nearest neighbours. Default value is 1e-5.

Expand All @@ -54,6 +60,7 @@ class Lattice:
if ``positions`` doesn't have a dimension of 2.
if ``vectors`` doesn't have a dimension of 2 or the length of vectors is not equal to the number of vectors.
if ``boundary_condition`` is not a bool or a list of bools with length equal to the number of vectors
if ``custom_nodes`` contains nodes with negative indices or indices greater than number of sites
obliviateandsurrender marked this conversation as resolved.
Show resolved Hide resolved

Returns:
Lattice object
Expand All @@ -78,6 +85,7 @@ def __init__(
boundary_condition=False,
neighbour_order=1,
custom_edges=None,
custom_nodes=None,
distance_tol=1e-5,
):

Expand Down Expand Up @@ -134,6 +142,17 @@ def __init__(

self.edges_indices = [(v1, v2) for (v1, v2, color) in self.edges]

if custom_nodes is not None:
for node in custom_nodes:
if node[0] > self.n_sites:
raise ValueError(
"The custom node has an index larger than the number of sites."
)
if node[0] < 0:
raise ValueError("The custom node has an index smaller than 0.")
austingmhuang marked this conversation as resolved.
Show resolved Hide resolved

self.nodes = custom_nodes

def _identify_neighbours(self, cutoff):
r"""Identifies the connections between lattice points and returns the unique connections
based on the neighbour_order. This function uses KDTree to identify neighbours, which
Expand Down
65 changes: 64 additions & 1 deletion pennylane/spin/spin_hamiltonian.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"""

import pennylane as qml
from pennylane import X, Y, Z, math
from pennylane import I, X, Y, Z, math
from pennylane.fermi import FermiWord

from .lattice import Lattice, _generate_lattice
Expand Down Expand Up @@ -689,3 +689,66 @@ def kitaev(n_cells, coupling=None, boundary_condition=False):
hamiltonian += coeff * (opmap[op1](v1) @ opmap[op2](v2))

return hamiltonian.simplify()


def spin_hamiltonian(lattice):
r"""Generates a spin Hamiltonian for a custom lattice.
obliviateandsurrender marked this conversation as resolved.
Show resolved Hide resolved

Args:
lattice (Lattice): custom lattice defined with custom_edges
austingmhuang marked this conversation as resolved.
Show resolved Hide resolved

Raises:
ValueError: if the provided Lattice does not have ``custom_edges`` defined with operators

Returns:
~ops.op_math.Sum: Hamiltonian for the lattice

**Example**

.. code-block:: python

>>> lattice = qml.spin.Lattice(
... n_cells=[2, 2],
... vectors=[[1, 0], [0, 1]],
... positions=[[0, 0], [1, 5]],
... boundary_condition=False,
... custom_edges=[[(0, 1), ("XX", 0.5)], [(1, 2), ("YY", 0.6)], [(1, 4), ("ZZ", 0.7)]],
... custom_nodes=[[0, ("X", 0.5)], [1, ("Y", 0.3)]],
... )
>>> qml.spin.spin_hamiltonian(lattice=lattice)
austingmhuang marked this conversation as resolved.
Show resolved Hide resolved
(
0.5 * (X(0) @ X(1))
+ 0.5 * (X(2) @ X(3))
+ 0.5 * (X(4) @ X(5))
+ 0.5 * (X(6) @ X(7))
+ 0.6 * (Y(1) @ Y(2))
+ 0.6 * (Y(5) @ Y(6))
+ 0.7 * (Z(1) @ Z(4))
+ 0.7 * (Z(3) @ Z(6))
+ 0.5 * X(0)
+ 0.3 * Y(1)
)

"""
if not isinstance(lattice.edges[0][2], tuple):
raise ValueError(
"Custom edges need to be defined and should have an operator defined as a `str`"
)
austingmhuang marked this conversation as resolved.
Show resolved Hide resolved

opmap = {"I": I, "X": X, "Y": Y, "Z": Z}
hamiltonian = 0.0 * qml.I(0)
for edge in lattice.edges:
v1, v2 = edge[0:2]
op1, op2 = edge[2][0]
coeff = edge[2][1]

hamiltonian += coeff * (opmap[op1](v1) @ opmap[op2](v2))

if lattice.nodes is not None:
for node in lattice.nodes:
n = node[0]
op = node[1][0]
coeff = node[1][1]
hamiltonian += coeff * (opmap[op](n))

return hamiltonian.simplify()
53 changes: 53 additions & 0 deletions tests/spin/test_lattice.py
Original file line number Diff line number Diff line change
Expand Up @@ -865,6 +865,59 @@ def test_custom_edges(vectors, positions, n_cells, custom_edges, expected_edges)
assert np.all(np.isin(expected_edges, lattice.edges))


@pytest.mark.parametrize(
# expected_nodes here were obtained manually
("vectors", "positions", "n_cells", "custom_nodes", "expected_nodes"),
[
(
[[0, 1], [1, 0]],
[[0, 0]],
[3, 3],
[[0, ("X", 0.3)], [2, ("Y", 0.3)]],
[[0, ("X", 0.3)], [2, ("Y", 0.3)]],
),
(
[[1, 0], [0.5, np.sqrt(3) / 2]],
[[0.5, 0.5 / 3**0.5], [1, 1 / 3**0.5]],
[2, 2],
[[0, ("X", 0.3)], [2, ("Y", 0.3)], [1, ("Z", 0.9)]],
[[0, ("X", 0.3)], [2, ("Y", 0.3)], [1, ("Z", 0.9)]],
),
],
)
def test_custom_nodes(vectors, positions, n_cells, custom_nodes, expected_nodes):
r"""Test that the nodes are added as per custom_nodes provided"""
lattice = Lattice(
n_cells=n_cells, vectors=vectors, positions=positions, custom_nodes=custom_nodes
)

assert lattice.nodes == expected_nodes


@pytest.mark.parametrize(
("vectors", "positions", "n_cells", "custom_nodes"),
[
(
[[0, 1], [1, 0]],
[[0, 0]],
[3, 3],
[[0, ("X", 0.3)], [-202, ("Y", 0.3)]],
),
(
[[1, 0], [0.5, np.sqrt(3) / 2]],
[[0.5, 0.5 / 3**0.5], [1, 1 / 3**0.5]],
[2, 2],
[[0, ("X", 0.3)], [204, ("Y", 0.3)], [1, ("Z", 0.9)]],
),
],
)
def test_custom_nodes_error(vectors, positions, n_cells, custom_nodes):
r"""Test that the incompatible `custom_nodes` raise correct error"""

with pytest.raises(ValueError, match="The custom node has"):
Lattice(n_cells=n_cells, vectors=vectors, positions=positions, custom_nodes=custom_nodes)


def test_dimension_error():
r"""Test that an error is raised if wrong dimension is provided for a given lattice shape."""
n_cells = [5, 5, 5]
Expand Down
97 changes: 96 additions & 1 deletion tests/spin/test_spin_hamiltonian.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,16 @@

import pennylane as qml
from pennylane import I, X, Y, Z
from pennylane.spin import emery, fermi_hubbard, haldane, heisenberg, kitaev, transverse_ising
from pennylane.spin import (
Lattice,
emery,
fermi_hubbard,
haldane,
heisenberg,
kitaev,
spin_hamiltonian,
transverse_ising,
)

# pylint: disable=too-many-arguments
pytestmark = pytest.mark.usefixtures("new_opmath_only")
Expand Down Expand Up @@ -1394,3 +1403,89 @@ def test_kitaev_hamiltonian(n_cells, j, boundary_condition, expected_ham):
kitaev_ham = kitaev(n_cells=n_cells, coupling=j, boundary_condition=boundary_condition)

qml.assert_equal(kitaev_ham, expected_ham)


@pytest.mark.parametrize(
("lattice", "expected_ham"),
[
# This is the Hamiltonian for the Kitaev model on the Honeycomb lattice
(
Lattice(
n_cells=[2, 2],
vectors=[[1, 0], [0, 1]],
positions=[[0, 0], [1, 5]],
boundary_condition=False,
custom_edges=[[(0, 1), ("XX", 0.5)], [(1, 2), ("YY", 0.6)], [(1, 4), ("ZZ", 0.7)]],
),
(
0.5 * (X(0) @ X(1))
+ 0.5 * (X(2) @ X(3))
+ 0.5 * (X(4) @ X(5))
+ 0.5 * (X(6) @ X(7))
+ 0.6 * (Y(1) @ Y(2))
+ 0.6 * (Y(5) @ Y(6))
+ 0.7 * (Z(1) @ Z(4))
+ 0.7 * (Z(3) @ Z(6))
),
),
(
Lattice(
n_cells=[2, 2],
vectors=[[1, 0], [0, 1]],
positions=[[0, 0], [1, 5]],
boundary_condition=False,
custom_edges=[[(0, 1), ("XX", 0.5)], [(1, 2), ("YY", 0.6)], [(1, 4), ("ZZ", 0.7)]],
custom_nodes=[[0, ("X", 0.3)], [7, ("Y", 0.9)]],
austingmhuang marked this conversation as resolved.
Show resolved Hide resolved
),
(
0.5 * (X(0) @ X(1))
+ 0.5 * (X(2) @ X(3))
+ 0.5 * (X(4) @ X(5))
+ 0.5 * (X(6) @ X(7))
+ 0.6 * (Y(1) @ Y(2))
+ 0.6 * (Y(5) @ Y(6))
+ 0.7 * (Z(1) @ Z(4))
+ 0.7 * (Z(3) @ Z(6))
+ 0.3 * X(0)
+ 0.9 * Y(7)
),
),
(
Lattice(
n_cells=[2, 2],
vectors=[[1, 0], [0, 1]],
positions=[[0, 0], [1, 5]],
boundary_condition=False,
custom_edges=[[(0, 1), ("XX", 0.5)], [(1, 2), ("YY", 0.6)], [(1, 4), ("ZZ", 0.7)]],
custom_nodes=[[0, ("X", 0.3)], [7, ("Y", 0.9)], [0, ("X", 0.5)]],
),
(
austingmhuang marked this conversation as resolved.
Show resolved Hide resolved
0.5 * (X(0) @ X(1))
+ 0.5 * (X(2) @ X(3))
+ 0.5 * (X(4) @ X(5))
+ 0.5 * (X(6) @ X(7))
+ 0.6 * (Y(1) @ Y(2))
+ 0.6 * (Y(5) @ Y(6))
+ 0.7 * (Z(1) @ Z(4))
+ 0.7 * (Z(3) @ Z(6))
+ 0.8 * X(0)
+ 0.9 * Y(7)
),
),
],
)
def test_spin_hamiltonian(lattice, expected_ham):
r"""Test that the correct Hamiltonian is generated from a given Lattice"""
spin_ham = spin_hamiltonian(lattice=lattice)

qml.assert_equal(spin_ham, expected_ham)


def test_spin_hamiltonian_error():
r"""Test that the correct error is raised Hamiltonian with incompatible Lattice"""
lattice = Lattice(n_cells=[2, 2], vectors=[[1, 0], [0, 1]], positions=[[0, 0], [1, 1]])
with pytest.raises(
ValueError,
match="Custom edges need to be defined and should have an operator defined as a `str`",
):
spin_hamiltonian(lattice=lattice)
Loading