diff --git a/demonstrations/tutorial_how_to_spin_hamiltonian.py b/demonstrations/tutorial_how_to_spin_hamiltonian.py index a02a2f0385..318f9b413d 100644 --- a/demonstrations/tutorial_how_to_spin_hamiltonian.py +++ b/demonstrations/tutorial_how_to_spin_hamiltonian.py @@ -64,15 +64,52 @@ hopping = 0.2 onsite = 0.3 -hamiltonian = qml.spin.fermi_hubbard("square", n_cells, hopping, onsite) +hamiltonian = qml.spin.fermi_hubbard('square', n_cells, hopping, onsite) +print('Hamiltonian:\n') hamiltonian ###################################################################### -# Similarly, we can construct the Hamiltonian for a :math:`5 \times 5 \times 5` cubic lattice as follows. +# Let's also visualize the square lattice we created. To do that, we need to +# create a simple plotting function and also the helper function +# :func:`~.pennylane.spin.generate_lattice`, which you will learn more about in the next sections. -hamiltonian = qml.spin.fermi_hubbard("cubic", [5, 5, 5], hopping, onsite) +import matplotlib.pyplot as plt + +def plot(lattice, figsize=None, showlabel=True): + + if not figsize: + figsize = lattice.n_cells[::-1] + + plt.figure(figsize=figsize) + + nodes = lattice.lattice_points + + for edge in lattice.edges: + start_index, end_index, color = edge + start_pos, end_pos = nodes[start_index], nodes[end_index] + + x_axis = [start_pos[0], end_pos[0]] + y_axis = [start_pos[1], end_pos[1]] + plt.plot(x_axis, y_axis, color='gold') + + plt.scatter(nodes[:,0], nodes[:,1], color='dodgerblue', s=100) + + if showlabel: + for index, pos in enumerate(nodes): + plt.text(pos[0]-0.2, pos[1]+0.1, str(index), color='gray') + + plt.axis("off") + plt.show() + +lattice = qml.spin.generate_lattice('square', n_cells) +plot(lattice) ###################################################################### +# Note that we currently support the following in-built lattice shapes: ``chain``, ``square``, +# ``rectangle``, ``triangle``, ``honeycomb``, ``kagome``, ``lieb``, ``cubic``, ``bcc``, ``fcc`` +# and ``diamond``. More details are provided +# `here `__. +# # Heisenberg model # ^^^^^^^^^^^^^^^^ # The `Heisenberg model Hamiltonian `__ @@ -82,11 +119,14 @@ # # H = J\sum_{ < i, j >}(\sigma_i ^ x\sigma_j ^ x + \sigma_i ^ y\sigma_j ^ y + \sigma_i ^ z\sigma_j ^ z), # -# where :math:`J` is the coupling constant, :math:`\left< i,j \right>` represents the indices for neighbouring -# sites, and :math:`\sigma` is a Pauli operator. The Hamiltonian can be constructed as follows. +# where :math:`J` is the coupling constant and :math:`\sigma` is a Pauli operator. The Hamiltonian +# can be constructed on a ``triangle`` lattice as follows. coupling = [0.5, 0.5, 0.5] -hamiltonian = qml.spin.heisenberg("square", n_cells, coupling) +hamiltonian = qml.spin.heisenberg('triangle', n_cells, coupling) + +lattice = qml.spin.generate_lattice('triangle', n_cells) +plot(lattice) ###################################################################### # Transverse-field Ising model @@ -100,11 +140,14 @@ # H = -J \sum_{} \sigma_i^{z} \sigma_j^{z} - h\sum_{i} \sigma_{i}^{x}, # # where :math:`J` is the coupling constant, :math:`h` is the strength of the transverse magnetic -# field, :math:`\left< i,j \right>` represents the indices for neighbouring sites and :math:`\sigma` is a Pauli -# operator. The Hamiltonian can be constructed as follows. +# field and :math:`\sigma` is a Pauli operator. The Hamiltonian can be constructed on the +# ``honeycomb`` lattice as follows. coupling, h = 0.5, 1.0 -hamiltonian = qml.spin.transverse_ising("square", n_cells, coupling, h) +hamiltonian = qml.spin.transverse_ising('honeycomb', n_cells, coupling, h) + +lattice = qml.spin.generate_lattice('honeycomb', n_cells) +plot(lattice) ###################################################################### # Kitaev's honeycomb model @@ -118,10 +161,8 @@ # \:\: K_Y \sum_{\langle i,j \rangle \in Y}\sigma_i^y\sigma_j^y + # \:\: K_Z \sum_{\langle i,j \rangle \in Z}\sigma_i^z\sigma_j^z, # -# where :math:`\sigma` is a Pauli operator and :math:`\left< i,j \right>` represents the indices for -# neighbouring spins. The parameters :math:`K_X`, :math:`K_Y`, :math:`K_Z` are the coupling -# constants defined for the Hamiltonian in each direction. In PennyLane, -# the Hamiltonian can be constructed as follows. +# where :math:`\sigma` is a Pauli operator and the parameters :math:`K_X`, :math:`K_Y`, :math:`K_Z` +# are the coupling constants in each direction. The Hamiltonian can be constructed as follows. coupling = [0.5, 0.6, 0.7] hamiltonian = qml.spin.kitaev(n_cells, coupling) @@ -144,12 +185,15 @@ # sites :math:`\langle \langle i,j \rangle \rangle`, :math:`\phi` is the phase factor that breaks # time-reversal symmetry in the system, and :math:`\sigma` is the spin degree of freedom. This # function assumes two fermions with opposite spins on each lattice site. The Hamiltonian can be -# constructed using the following code. +# constructed on the ``kagome`` lattice using the following code. hopping = 0.5 hopping_next = 1.0 phi = 0.1 -hamiltonian = qml.spin.haldane("square", n_cells, hopping, hopping_next, phi) +hamiltonian = qml.spin.haldane('kagome', n_cells, hopping, hopping_next, phi) + +lattice = qml.spin.generate_lattice('kagome', n_cells) +plot(lattice) ###################################################################### # Emery model @@ -165,16 +209,19 @@ # # where :math:`t` is the hopping term representing the kinetic energy of electrons, # :math:`U` is the on-site Coulomb interaction representing the repulsion between electrons, -# :math:`V` is the intersite coupling, :math:`\langle i,j \rangle` represents the indices for neighbouring sites, +# :math:`V` is the intersite coupling, # :math:`\sigma` is the spin degree of freedom, and :math:`n_{k \uparrow}`, :math:`n_{k \downarrow}` # are number operators for spin-up and spin-down fermions at site :math:`k`. This function assumes # two fermions with opposite spins on each lattice site. The Hamiltonian can be -# constructed as follows. +# constructed on the ``lieb`` lattice as follows. hopping = 0.5 coulomb = 1.0 intersite_coupling = 0.2 -hamiltonian = qml.spin.emery("square", n_cells, hopping, coulomb, intersite_coupling) +hamiltonian = qml.spin.emery('lieb', n_cells, hopping, coulomb, intersite_coupling) + +lattice = qml.spin.generate_lattice('lieb', n_cells) +plot(lattice) ###################################################################### # Building Hamiltonians manually @@ -192,10 +239,11 @@ # H = -J \sum_{\left< i,j \right>} \sigma_i^{z} \sigma_j^{z} - h\sum_{i} \sigma_{i}^{x}, # # where :math:`J` is the coupling defined for the Hamiltonian, :math:`h` is the strength of -# transverse magnetic field, and :math:`\left< i,j \right>` represents the indices of neighbouring spins. +# transverse magnetic field, and :math:`\left< i,j \right>` represents the indices of neighbouring +# spins. # -# Our approach for doing this is to construct a lattice that represents the spin sites and -# their connectivity. This is done by using the :class:`~.pennylane.spin.Lattice` class, which can be +# Our approach for doing this is to construct a lattice that represents the spin sites and their +# connectivity. This is done by using the :class:`~.pennylane.spin.Lattice` class, which can be # constructed either by calling the helper function :func:`~.pennylane.spin.generate_lattice` or by # manually constructing the object. Let's see examples of both methods. First we use # :func:`~.pennylane.spin.generate_lattice` to construct a square lattice containing @@ -205,36 +253,7 @@ lattice = qml.spin.generate_lattice('square', [3, 3]) ###################################################################### -# To visualize this lattice, we create a simple plotting function. -# - -import matplotlib.pyplot as plt - -def plot(lattice, figsize=None, showlabel=True): - - if not figsize: - figsize = lattice.n_cells[::-1] - - plt.figure(figsize=figsize) - - nodes = lattice.lattice_points - - for edge in lattice.edges: - start_index, end_index, color = edge - start_pos, end_pos = nodes[start_index], nodes[end_index] - - x_axis = [start_pos[0], end_pos[0]] - y_axis = [start_pos[1], end_pos[1]] - plt.plot(x_axis, y_axis, color='gold') - - plt.scatter(nodes[:,0], nodes[:,1], color='dodgerblue', s=100) - - if showlabel: - for index, pos in enumerate(nodes): - plt.text(pos[0]-0.2, pos[1]+0.1, str(index), color='gray') - - plt.axis("off") - plt.show() +# To visualize this lattice, we use the plotting function we created before. plot(lattice) @@ -370,12 +389,14 @@ def plot(lattice, figsize=None, showlabel=True): # # Conclusion # ---------- -# The spin module in PennyLane provides a set of powerful tools for constructing spin -# Hamiltonians. Here we learned how to use these tools to construct predefined Hamiltonian -# templates, such as the Fermi–Hubbard model Hamiltonian, and used the -# :class:`~.pennylane.spin.Lattice` object to construct more advanced and customised models such as -# the Kitaev honeycomb Hamiltonian. The versatility of the new spin functions and classes allows you -# to quickly construct any new spin model Hamiltonian intuitively. +# The spin module in PennyLane provides a set of powerful tools for constructing spin Hamiltonians. +# Here we learned how to use these tools to construct predefined Hamiltonian templates such as the +# Fermi–Hubbard Hamiltonian. This can be done with our built-in functions that currently support +# several commonly used spin models and a variety of lattice shapes. More importantly, PennyLane +# provides easy-to-use function to manually build spin Hamiltonians on customized lattice structures +# with anisotropic interactions between the sites. This can be done intuitively using the +# :class:`~.pennylane.spin.Lattice` object and provided helper functions. The versatility of the new +# spin functionality allows you to construct any new spin Hamiltonian quickly and intuitively. # # References # ----------