Applied example
In this example, we will create the spin-boson Hamiltonian we have used for open-system research in our paper, for 1 spin and 3 bosonic modes.
The Hamiltonian reads as follows: \[ \hat{H} = \hat{H}_S + \hat{H}_B + \hat{H}_C \]
with the spin (system) Hamiltonian \(\hat{H}_S\) :
\[ \hat{H} = \frac {\hbar \Delta} {2} \sigma^z_0, \]
the bosonic bath Hamiltonian \(\hat{H}_B\) :
\[ \hat{H} = \sum_{k=0}^2 \hbar \omega_k c_k^{\dagger} c_k, \]
and the coupling between system and bath \(\hat{H}_C\) :
\[ \hat{H} = \sigma_0^x \sum_{k=0}^2 \frac {v_k} {2} \left( c_k + c_k^{\dagger} \right) \]
For simplicity, we will set \(\hbar\) to 1.0 for this example.
Implementation:
# We start by importing the Hamiltonian class, and the Product classes we will need:
# BosonProduct and PauliProduct for the terms in the Hamiltonian defined above,
# and HermitianMixedProduct to add them into the MixedHamiltonian.
from struqture_py.bosons import BosonProduct
from struqture_py.mixed_systems import (
HermitianMixedProduct, MixedHamiltonian,
)
from struqture_py.spins import PauliProduct
# We initialize the Hamiltonian class: it should contain one spin system and one boson system, but
# no fermion systems
hamiltonian = MixedHamiltonian(1, 1, 0)
# Setting up constants:
delta = 1.0
omega_k = [2.0, 3.0, 4.0]
v_k = [5.0, 6.0, 7.0]
# First, we build H_S.
# We initialize our PauliProduct and add on a sigma_z term on spin 1
pp = PauliProduct().z(1)
# This term is a spin-only term, so the bosonic part of it will be empty
bp = BosonProduct([], [])
# We create a HermitianMixedProduct from the spin and bosonic terms
hmp = HermitianMixedProduct([pp], [bp], [])
# We add the created HermitianMixedProduct containing all the operator information into the hamiltonian, with the correct prefactor
hamiltonian.add_operator_product(
hmp, delta / 2.0
)
# Second, H_B:
# This term is a boson-only term, so the spin part of it will be empty
pp = PauliProduct()
# We iterate over all the bosonic modes
for k in range(3):
# We initialize our BosonProduct with the creation operator acting on k and the annihilation operator acting on k
bp = BosonProduct([k], [k])
# We create a HermitianMixedProduct from the spin and bosonic terms
hmp = HermitianMixedProduct([pp], [bp], [])
# We add the created HermitianMixedProduct containing all the operator information into the hamiltonian, with the correct prefactor
hamiltonian.add_operator_product(
hmp, v_k[k] / 2.0
)
# Third, H_C: the hermitian conjugate is implicitly stored, we don't need to add it manually
# We create the spin part of the term by initializing a PauliProduct and adding a sigma_x term acting on spin 0
pp = PauliProduct().x(0)
# We iterate over all the bosonic modes
for k in range(3):
# We initialize our BosonProduct with the annihilation operator acting on k
bp = BosonProduct([], [k])
# We create a HermitianMixedProduct from the spin and bosonic terms
hmp = HermitianMixedProduct([pp], [bp], [])
# We add the created HermitianMixedProduct containing all the operator information into the hamiltonian, with the correct prefactor
hamiltonian.add_operator_product(
hmp, omega_k[k]
)
# Our resulting H:
print(hamiltonian)
# NOTE: the above values used can also be complex, or symbolic.
# Symbolic parameters can be very useful for a variety of reasons, as detailed in the introduction.
# In order to set a symbolic parameter, we can pass either a string or use the `qoqo_calculator_pyo3` package:
from qoqo_calculator_pyo3 import CalculatorComplex
hamiltonian.add_operator_product(hmp, "parameter")
# The syntax below is particularly useful for building non-hermitian operators, such as MixedOperators, as the imaginary part can then be non-zero
hamiltonian.add_operator_product(hmp, CalculatorComplex.from_pair("parameter", 0.0))