-
Notifications
You must be signed in to change notification settings - Fork 207
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* First attempt at hex lattice class * Added hexagonal Lattice class * Update qiskit_nature/second_q/hamiltonians/lattices/hexagonal_lattice.py Co-authored-by: Matthew Treinish <[email protected]> * added tests * simplified test * fixed copyright * use more performant rustworkx functions * Apply suggestions from code review Co-authored-by: Max Rossmannek <[email protected]> * Make changes requested in review * Added default positions * ✨ lint! ✨ * remove heavy hex arg * fix mypy issues * Fix typing * increased rustworkx * fixed mypy again? * lint: fix mypy * lint: update headers * docs: Add reno --------- Co-authored-by: Matthew Treinish <[email protected]> Co-authored-by: Max Rossmannek <[email protected]> Co-authored-by: Max Rossmannek <[email protected]>
- Loading branch information
1 parent
0f73ea7
commit 9b48d54
Showing
5 changed files
with
233 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
122 changes: 122 additions & 0 deletions
122
qiskit_nature/second_q/hamiltonians/lattices/hexagonal_lattice.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
# This code is part of a Qiskit project. | ||
# | ||
# (C) Copyright IBM 2021, 2023. | ||
# | ||
# This code is licensed under the Apache License, Version 2.0. You may | ||
# obtain a copy of this license in the LICENSE.txt file in the root directory | ||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. | ||
# | ||
# Any modifications or derivative works of this code must retain this | ||
# copyright notice, and modified files need to carry a notice indicating | ||
# that they have been altered from the originals. | ||
|
||
"""The hexagonal lattice""" | ||
|
||
from __future__ import annotations | ||
|
||
from rustworkx import generators # type: ignore[attr-defined] | ||
|
||
from .lattice import Lattice | ||
|
||
|
||
class HexagonalLattice(Lattice): | ||
"""Hexagonal lattice.""" | ||
|
||
def __init__( | ||
self, | ||
rows: int, | ||
cols: int, | ||
edge_parameter: complex = 1.0, | ||
onsite_parameter: complex = 0.0, | ||
) -> None: | ||
""" | ||
Args: | ||
rows: Number of hexagons in the x direction. | ||
cols: Number of hexagons in the y direction. | ||
edge_parameter: Weight on all the edges, specified as a single value. | ||
Defaults to 1.0. | ||
onsite_parameter: Weight on the self-loops, which are edges connecting a node to itself. | ||
Defaults to 0.0. | ||
""" | ||
self._rows = rows | ||
self._cols = cols | ||
self._edge_parameter = edge_parameter | ||
self._onsite_parameter = onsite_parameter | ||
|
||
graph = generators.hexagonal_lattice_graph(rows, cols, multigraph=False) | ||
|
||
# Add edge weights | ||
for idx in range(graph.num_edges()): | ||
graph.update_edge_by_index(idx, self._edge_parameter) | ||
|
||
# Add self loops | ||
for node in range(graph.num_nodes()): | ||
graph.add_edges_from([(node, node, self._onsite_parameter)]) | ||
|
||
super().__init__(graph) | ||
|
||
self.pos = self._default_position() | ||
|
||
@property | ||
def edge_parameter(self) -> complex: | ||
"""Weights on all edges. | ||
Returns: | ||
the parameter for the edges. | ||
""" | ||
return self._edge_parameter | ||
|
||
@property | ||
def onsite_parameter(self) -> complex: | ||
"""Weight on the self-loops (edges connecting a node to itself). | ||
Returns: | ||
the parameter for the self-loops. | ||
""" | ||
return self._onsite_parameter | ||
|
||
def _default_position(self) -> dict[int, tuple[int, int]]: | ||
"""Return a dictionary of default positions for visualization of | ||
a one- or two-dimensional lattice. | ||
Returns: | ||
A dictionary where the keys are the labels of lattice points, and the values are | ||
two-dimensional coordinates. | ||
""" | ||
pos = {} | ||
rowlen = 2 * self._rows + 2 | ||
collen = self._cols + 1 | ||
x_adjust = 0 | ||
|
||
for i in range(collen): | ||
x_adjust += 1 | ||
for j in range(rowlen): | ||
idx = i * rowlen + j - 1 | ||
x = i | ||
|
||
# plot the y coords to form heavy hex shape | ||
if i == 0: | ||
y = j - 1 | ||
elif (self._cols % 2 == 0) and (i == self._cols): | ||
y = j + 1 | ||
else: | ||
y = j | ||
|
||
# even numbered nodes in the first, last and odd numbered columns need to be | ||
# shifted to the right | ||
if i == 0 or (i == self._cols) or (i % 2 != 0): | ||
if idx % 2 == 0: | ||
x = i + x_adjust | ||
else: | ||
x = i + i | ||
# odd numbered nodes that aren't in the first, last or odd numbered columns | ||
# need to be shifted to the right | ||
else: | ||
if idx % 2 == 0: | ||
x = i + i | ||
else: | ||
x = i + x_adjust | ||
|
||
pos[idx] = (x, y) | ||
|
||
return pos |
21 changes: 21 additions & 0 deletions
21
releasenotes/notes/add-hexagonal-lattice-a981f1b5c832a154.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
--- | ||
features: | ||
- | | ||
Adds a new lattice class, :class:`~qiskit_nature.second_q.hamiltonians.lattices.HexagonalLattice` | ||
for the generation of hexagonal lattices. | ||
You construct a hexagonal lattice by specifying the number of rows and columns of hexagons. | ||
You can also specify the edge- and on-site-parameters. | ||
Below is a simple example to illustrate this: | ||
.. code-block:: python | ||
from qiskit_nature.second_q.hamiltonians.lattices import HexagonalLattice | ||
lattice = HexagonalLattice( | ||
2, | ||
3, | ||
edge_parameter=1.0, | ||
onsite_parameter=1.5, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,4 +5,4 @@ psutil>=5 | |
setuptools>=40.1.0 | ||
typing_extensions | ||
h5py | ||
rustworkx | ||
rustworkx>=0.12 |
86 changes: 86 additions & 0 deletions
86
test/second_q/hamiltonians/lattices/test_hexagonal_lattice.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
# This code is part of a Qiskit project. | ||
# | ||
# (C) Copyright IBM 2021, 2023. | ||
# | ||
# This code is licensed under the Apache License, Version 2.0. You may | ||
# obtain a copy of this license in the LICENSE.txt file in the root directory | ||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. | ||
# | ||
# Any modifications or derivative works of this code must retain this | ||
# copyright notice, and modified files need to carry a notice indicating | ||
# that they have been altered from the originals. | ||
|
||
"""Test for HexgonalLattice.""" | ||
from test import QiskitNatureTestCase | ||
import numpy as np | ||
from numpy.testing import assert_array_equal | ||
from rustworkx import PyGraph, is_isomorphic # type: ignore[attr-defined] | ||
from qiskit_nature.second_q.hamiltonians.lattices import HexagonalLattice | ||
|
||
|
||
class TestHexagonalLattice(QiskitNatureTestCase): | ||
"""Test HexagonalLattice""" | ||
|
||
def test_init(self): | ||
"""Test init.""" | ||
rows = 1 | ||
cols = 2 | ||
edge_parameter = 0 + 1.42j | ||
onsite_parameter = 1.0 | ||
weighted_edge_list = [ | ||
(0, 1, 1.42j), | ||
(1, 2, 1.42j), | ||
(3, 4, 1.42j), | ||
(4, 5, 1.42j), | ||
(5, 6, 1.42j), | ||
(7, 8, 1.42j), | ||
(8, 9, 1.42j), | ||
(0, 3, 1.42j), | ||
(2, 5, 1.42j), | ||
(4, 7, 1.42j), | ||
(6, 9, 1.42j), | ||
(0, 0, 1.0), | ||
(1, 1, 1.0), | ||
(2, 2, 1.0), | ||
(3, 3, 1.0), | ||
(4, 4, 1.0), | ||
(5, 5, 1.0), | ||
(6, 6, 1.0), | ||
(7, 7, 1.0), | ||
(8, 8, 1.0), | ||
(9, 9, 1.0), | ||
] | ||
|
||
hexa = HexagonalLattice(rows, cols, edge_parameter, onsite_parameter) | ||
|
||
with self.subTest("Check the graph."): | ||
target_graph = PyGraph(multigraph=False) | ||
target_graph.add_nodes_from(range(10)) | ||
target_graph.add_edges_from(weighted_edge_list) | ||
self.assertTrue( | ||
is_isomorphic(hexa.graph, target_graph, edge_matcher=lambda x, y: x == y) | ||
) | ||
|
||
with self.subTest("Check the number of nodes."): | ||
self.assertEqual(hexa.num_nodes, 10) | ||
|
||
with self.subTest("Check the set of nodes."): | ||
self.assertSetEqual(set(hexa.node_indexes), set(range(10))) | ||
|
||
with self.subTest("Check the set of weights."): | ||
target_set = set(weighted_edge_list) | ||
self.assertSetEqual(set(hexa.weighted_edge_list), target_set) | ||
|
||
with self.subTest("Check the adjacency matrix."): | ||
target_matrix = np.zeros((10, 10), dtype=complex) | ||
|
||
indices = [(a, b) for a, b, _ in weighted_edge_list] | ||
|
||
for idx1, idx2 in indices: | ||
target_matrix[idx1, idx2] = 0 + 1.42j | ||
|
||
target_matrix -= target_matrix.T | ||
|
||
np.fill_diagonal(target_matrix, 1.0) | ||
|
||
assert_array_equal(hexa.to_adjacency_matrix(weighted=True), target_matrix) |