Constructing operators

Start by importing PauliStrings:

using PauliStrings
import PauliStrings as ps

To construct an operator we first need to declare an empty operator of $N$ qubits:

H = Operator(N)

PauliStrings.jl supports up to 128 qubits.

We can add a term of the form $J X_i$ by doing

H += J, "X", i

and a term of the form $J X_iX_j$ by doing

H += J, "X", i, "X", j

Similarly, we add a term of the form $J X_iX_jX_k$ by doing

H += J, "X", i, "X", j, "X", k

etc.

1D transverse Ising model

Let's construct the Hamiltonian of a 1D transverse Ising model $H=-J(\sum_{<i,j>}Z_i Z_j +g \sum_i X_i)$

function ising1D(N, J, g)
    H = Operator(N)
    for j in 1:(N - 1)
        H += "Z",j,"Z",j+1
    end
    H += "Z",1,"Z",N # periodic boundary condition
    for j in 1:N
        H += g,"X",j
    end
    return -J*H
end
ising1D (generic function with 1 method)

Note that the first qubit starts at index 1, following Julia's 1-based index.

Operators can be printed in strings format with the println function:

println(ising1D(3, 1, 0.5))
(-1.0 + 0.0im) Z1Z
(-1.0 + 0.0im) 1ZZ
(-0.5 + 0.0im) 1X1
(-0.5 + 0.0im) X11
(-1.0 + 0.0im) ZZ1
(-0.5 + 0.0im) 11X

2D transverse Ising model

Here we construct a 2D Ising model on a square lattice of L*L sites, with no periodic boundary conditions.

function ising2D(L, J, g)
    H = ps.Operator(L * L)
    for x in 1:L-1
        for y in 1:L
            # convert x,y to qubit index
            i = L * (y - 1) + x
            j = L * (y - 1) + (x + 1)
            # horizontal interaction terms
            H += ("Z", i, "Z", j)
            # convert x,y to qubit index
            i = L * (x - 1) + y
            j = L * x + y
            # vertical interaction terms
            H += ("Z", i, "Z", j)
        end
    end
    for j in 1:L*L
        H += g, "X", j
    end
    return -J * H
end

println(ising2D(3, 1.0, 0.5))
(-0.5 + 0.0im) 111111X11
(-0.5 + 0.0im) 1X1111111
(-1.0 + 0.0im) 1111111ZZ
(-0.5 + 0.0im) 11X111111
(-1.0 + 0.0im) 1111ZZ111
(-1.0 + 0.0im) 1Z11Z1111
(-0.5 + 0.0im) 1111111X1
(-0.5 + 0.0im) 1111X1111
(-1.0 + 0.0im) 1111Z11Z1
(-1.0 + 0.0im) 111111ZZ1
(-1.0 + 0.0im) 111Z11Z11
(-1.0 + 0.0im) 111ZZ1111
(-0.5 + 0.0im) 11111X111
(-1.0 + 0.0im) 1ZZ111111
(-1.0 + 0.0im) 11Z11Z111
(-0.5 + 0.0im) X11111111
(-1.0 + 0.0im) Z11Z11111
(-0.5 + 0.0im) 11111111X
(-1.0 + 0.0im) 11111Z11Z
(-1.0 + 0.0im) ZZ1111111
(-0.5 + 0.0im) 111X11111

We can also construct a 2d operator using the string_2d function,

function ising2D(L, J, g)
    H = Operator(L * L)
    for x in 1:L
        for y in 1:L
            # horizontal interaction
            (x < L) && (H += string_2d(("Z", x, y, "Z", x + 1, y), L, L))
            # vertical interaction
            (y < L) &&  (H += string_2d(("Z", x, y, "Z", x, y + 1), L, L))
            # transverse field
            H += g * string_2d(("X", x, y), L, L)
        end
    end
    return -J * H
end

println(ising2D(3, 1.0, 0.5))
(-0.5 + 0.0im) 111111X11
(-0.5 + 0.0im) 1X1111111
(-1.0 + 0.0im) 1111111ZZ
(-0.5 + 0.0im) 11X111111
(-1.0 + 0.0im) 1111ZZ111
(-1.0 + 0.0im) 1Z11Z1111
(-0.5 + 0.0im) 1111111X1
(-0.5 + 0.0im) 1111X1111
(-1.0 + 0.0im) 1111Z11Z1
(-1.0 + 0.0im) 111111ZZ1
(-1.0 + 0.0im) 111Z11Z11
(-1.0 + 0.0im) 111ZZ1111
(-0.5 + 0.0im) 11111X111
(-1.0 + 0.0im) 1ZZ111111
(-1.0 + 0.0im) 11Z11Z111
(-0.5 + 0.0im) X11111111
(-1.0 + 0.0im) Z11Z11111
(-0.5 + 0.0im) 11111111X
(-1.0 + 0.0im) 11111Z11Z
(-1.0 + 0.0im) ZZ1111111
(-0.5 + 0.0im) 111X11111