# Operator definition as a product of operators

**URL:** <https://itensor.discourse.group/t/operator-definition-as-a-product-of-operators/673>\
**Category:** ITensor Julia Questions\
**Created:** [March 1, 2023, 4:08pm UTC](https://itensor.discourse.group/t/operator-definition-as-a-product-of-operators/673 "2023-03-01T16:08:25Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![EmilioRui](https://yyz2.discourse-cdn.com/free1/user_avatar/itensor.discourse.group/emiliorui/32/208_2.png) [@EmilioRui](https://itensor.discourse.group/u/EmilioRui)\
**Post date:** [March 1, 2023, 4:08pm UTC](https://itensor.discourse.group/t/operator-definition-as-a-product-of-operators/673/1 "2023-03-01T16:08:25Z")

</div>

Is there a OpProd function like OpSum to have products of operators?

I need to create an operator in a bosonic space that is like:  
(a + a\dagger)^N + a\dagger a

I tried with: (freq is just a constant and m is the site number)  
ϕ = OpSum()  
ϕ += freq, “a”,m  
ϕ += freq, “a†”,m

cosine = OpSum()  
cosine += c\_p, ϕ, [1:N\_sites]

But it is not working

BoundsError: attempt to access 0-element Vector{Int64} at index [1]

---

<div class="post-metadata">

**Author:** ![EmilioRui](https://yyz2.discourse-cdn.com/free1/user_avatar/itensor.discourse.group/emiliorui/32/208_2.png) [@EmilioRui](https://itensor.discourse.group/u/EmilioRui)\
**Post date:** [March 7, 2023, 10:04am UTC](https://itensor.discourse.group/t/operator-definition-as-a-product-of-operators/673/2 "2023-03-07T10:04:57Z")

</div>

No hints?

---

<div class="post-metadata">

**Author:** ![mtfishman](https://yyz2.discourse-cdn.com/free1/user_avatar/itensor.discourse.group/mtfishman/32/11_2.png) [@mtfishman](https://itensor.discourse.group/u/mtfishman)\
**Post date:** [March 7, 2023, 2:24pm UTC](https://itensor.discourse.group/t/operator-definition-as-a-product-of-operators/673/3 "2023-03-07T14:24:42Z")

</div>

Could you be more specific? It is easier to help if you give more information. I don’t really understand the equation or the code you wrote. Please write a self contained equation defining all of the variables, and a full code that you hope would work with all of the variables defined (and the code formatted, see [Welcome to ITensor Discourse](https://itensor.discourse.group/t/welcome-to-itensor-discourse/7)).

---

<div class="post-metadata">

**Author:** ![EmilioRui](https://yyz2.discourse-cdn.com/free1/user_avatar/itensor.discourse.group/emiliorui/32/208_2.png) [@EmilioRui](https://itensor.discourse.group/u/EmilioRui)\
**Post date:** [March 8, 2023, 10:38am UTC](https://itensor.discourse.group/t/operator-definition-as-a-product-of-operators/673/4 "2023-03-08T10:38:54Z")

</div>

I am sorry.  
I want to write a bosonic hamiltonian that is:

H = \sum\_{sites} \sum\_{n = 1}^N(a\_s + a\_s^\dagger)^n + \sum\_{sites}a\_s^\dagger a\_s

I was wondering if there is a built in method to build a product (or in this case the power) of an operator.

To recap, I cannot build (a\_s + a\_s^\dagger)^n and sum it to other operator.

```auto
using ITensors
N_sites = 2
N = 5

sites = siteinds("Boson",N_sites,dim=10)

op = OpSum()
for m in 1:N_sites
    op += 1, "a",m
    op += 1, "a†",m
end
pow_of_op = OpSum()

for n in 1:N
    pow_of_op += 1, op^n, sites
    end
end

```

I fully understand my first post was a mess, if you prefer I can create a new topic

---

<div class="post-metadata">

**Author:** ![mtfishman](https://yyz2.discourse-cdn.com/free1/user_avatar/itensor.discourse.group/mtfishman/32/11_2.png) [@mtfishman](https://itensor.discourse.group/u/mtfishman)\
**Post date:** [March 8, 2023, 7:19pm UTC](https://itensor.discourse.group/t/operator-definition-as-a-product-of-operators/673/5 "2023-03-08T19:19:22Z")

</div>

One way to repeat an operator multiple times on a site would be:

```julia
julia> os = OpSum() + ("Id", 1)
sum(
  1.0 Id(1,)
)

julia> for j in 1:5
         os *= ("X", 1)
       end

julia> os
sum(
  1.0 Id(1,) X(1,) X(1,) X(1,) X(1,) X(1,)
)

```

---

<div class="post-metadata">

**Author:** ![mtfishman](https://yyz2.discourse-cdn.com/free1/user_avatar/itensor.discourse.group/mtfishman/32/11_2.png) [@mtfishman](https://itensor.discourse.group/u/mtfishman)\
**Post date:** [March 8, 2023, 7:20pm UTC](https://itensor.discourse.group/t/operator-definition-as-a-product-of-operators/673/6 "2023-03-08T19:20:56Z")

</div>

Alternatively, you could define your own operator type (see [Physics (SiteType) System Examples · ITensors.jl](https://itensor.github.io/ITensors.jl/stable/examples/Physics.html#Making-a-Custom-op-Definition)) for `"op^n"`, though it may be subtle to do that for any `n`.

---

<div class="post-metadata">

**Author:** ![EmilioRui](https://yyz2.discourse-cdn.com/free1/user_avatar/itensor.discourse.group/emiliorui/32/208_2.png) [@EmilioRui](https://itensor.discourse.group/u/EmilioRui)\
**Post date:** [March 14, 2023, 2:39pm UTC](https://itensor.discourse.group/t/operator-definition-as-a-product-of-operators/673/7 "2023-03-14T14:39:01Z")

</div>

It does not work with my problem though.

I would want to define an operator as an OpSum()

```auto
my_op = OpSum()
for m in 1:N_sites
    op += 1, "a",m
    op += 1, "a†",m
end

```

and then apply this self defined operator multiple times

```auto
pow_of_op = OpSum()
for n in 1:N
    pow_of_op *= my_op
end

```

In such a case pow\_of\_op is no more an OpSum() but its type is prod(), and I cannot use it to build an MPO

---

<div class="post-metadata">

**Author:** ![mtfishman](https://yyz2.discourse-cdn.com/free1/user_avatar/itensor.discourse.group/mtfishman/32/11_2.png) [@mtfishman](https://itensor.discourse.group/u/mtfishman)\
**Post date:** [March 15, 2023, 1:14am UTC](https://itensor.discourse.group/t/operator-definition-as-a-product-of-operators/673/8 "2023-03-15T01:14:50Z")

</div>

You could try:

```julia
julia> using ITensors

julia> os = OpSum() + ("X", 1) + ("X", 2)
sum(
  1.0 X(1,)
  1.0 X(2,)
)

julia> os2 = os * os
prod(
  sum(
  1.0 X(1,)
  1.0 X(2,)
)
  sum(
  1.0 X(1,)
  1.0 X(2,)
)
)

julia> Ops.expand(os2)
sum(
  1.0 X(1,) X(1,)
  1.0 X(2,) X(1,)
  1.0 X(1,) X(2,)
  1.0 X(2,) X(2,)
)

```

---

<div class="post-metadata">

**Author:** ![EmilioRui](https://yyz2.discourse-cdn.com/free1/user_avatar/itensor.discourse.group/emiliorui/32/208_2.png) [@EmilioRui](https://itensor.discourse.group/u/EmilioRui)\
**Post date:** [March 15, 2023, 1:31pm UTC](https://itensor.discourse.group/t/operator-definition-as-a-product-of-operators/673/9 "2023-03-15T13:31:55Z")

</div>

It works!

Thank you so much!

Is it in the documentation? Otherwise it seems to be something possibly useful to general users

---

<div class="post-metadata">

**Author:** ![mtfishman](https://yyz2.discourse-cdn.com/free1/user_avatar/itensor.discourse.group/mtfishman/32/11_2.png) [@mtfishman](https://itensor.discourse.group/u/mtfishman)\
**Post date:** [March 20, 2023, 2:26pm UTC](https://itensor.discourse.group/t/operator-definition-as-a-product-of-operators/673/10 "2023-03-20T14:26:57Z")

</div>

Glad that worked!

It’s a bit of a “secret” feature. It came about because I rewrote the design of the `OpSum` object in terms of a general lazy operator algebra system (actually more generally a full lazy algebra system, similar to the design of Julia packages like [GitHub - JuliaArrays/LazyArrays.jl: Lazy arrays and linear algebra in Julia](https://github.com/JuliaArrays/LazyArrays.jl)), with the motivation of performing more general operations on `OpSum`, such as implementing a system for automatically creating the Trotterization of a Hamiltonian. I wasn’t quite ready to advertise that system since I wanted to see it tested out “in the wild” and be free to change some of the interface if needed. I think I would like to see it tested out more before fully documenting and advertizing it, but specific functions like `Ops.expand` are pretty self-explanatory and the functionality is quite clear and unlikely to change, so I would be open to documenting that function.

---

<div class="post-metadata">

**Author:** ![EmilioRui](https://yyz2.discourse-cdn.com/free1/user_avatar/itensor.discourse.group/emiliorui/32/208_2.png) [@EmilioRui](https://itensor.discourse.group/u/EmilioRui)\
**Post date:** [March 23, 2023, 2:50pm UTC](https://itensor.discourse.group/t/operator-definition-as-a-product-of-operators/673/11 "2023-03-23T14:50:40Z")

</div>

It is working great and we are using it a lot!  
Thank you so much!

---

<div class="post-metadata">

**Author:** ![adityab999](https://avatars.discourse-cdn.com/v4/letter/a/7c8e57/32.png) [@adityab999](https://itensor.discourse.group/u/adityab999)\
**Post date:** [August 19, 2023, 11:36pm UTC](https://itensor.discourse.group/t/operator-definition-as-a-product-of-operators/673/12 "2023-08-19T23:36:43Z")

</div>

@EmilioRui - Thanks for asking this question back in March. I encountered a similar situation with a product of sum of operators (specifically a square of an OpSum() defined at each site), which led me to this thread. Thanks a lot to Matt for posting its resolution.

However, I am facing a new problem with this - I am unable to create an MPO representation of the Hamiltonian with this. Specifically, from Matt’s example above, if I define at first a HAM = OpSum(), and then starting a loop over sites ‘j’, where at each ‘j’ I have something like the aforementioned os2, then how are you doing HAM += os2 in a manner such that H=MPO(HAM,sites) works (where ‘sites’ is whatever your siteinds are) ? I am being shown either a method matching error for MPO or “Overload of “op” or “op!” functions not found for operator name os2…” depending on a few things that I tried around.

@mtfishman - any suggestion ? I can post a code snippet if needed in case what I said above is not clear.

I apologise if the resolution is something embarrassingly simple and straightforward - I am new to ITensors (and even Julia) and this is just the beginning of my first MPS project 🙂

---

<div class="post-metadata">

**Author:** ![JanReimers](https://yyz2.discourse-cdn.com/free1/user_avatar/itensor.discourse.group/janreimers/32/171_2.png) [@JanReimers](https://itensor.discourse.group/u/JanReimers)\
**Post date:** [August 20, 2023, 4:32pm UTC](https://itensor.discourse.group/t/operator-definition-as-a-product-of-operators/673/13 "2023-08-20T16:32:51Z")

</div>

Hi adityab999, Does this code do something similar to what you need?

```auto
using ITensors
let 
    N=5
    os2=OpSum()
    for i in 1:N-1
        osi=OpSum() + ("X", i) + ("X", i+1)
        os2+=Ops.expand(osi*osi)
    end
    @show os2
    s=siteinds("S=1/2",N;conserve_qns=false)
    HAM=MPO(os2,s)
end

```

Kind Regards  
Jan

---

<div class="post-metadata">

**Author:** ![EmilioRui](https://yyz2.discourse-cdn.com/free1/user_avatar/itensor.discourse.group/emiliorui/32/208_2.png) [@EmilioRui](https://itensor.discourse.group/u/EmilioRui)\
**Post date:** [August 20, 2023, 5:28pm UTC](https://itensor.discourse.group/t/operator-definition-as-a-product-of-operators/673/14 "2023-08-20T17:28:48Z")

</div>

Hi adityab999,  
I was having similar issues and Jan solution worked for me.

As a note you can also create the square an operator by applying it twice.

```auto
using ITensors

let
    N = 5
    s = siteinds("S=1/2", N; conserve_qns=false)

    H_vec = []

    for i in 1:N-1
        osi=OpSum() + ("X", i) + ("X", i+1)
        H_i = MPO(osi, s)
        H_i_square = apply(H_i, H_i)
        push!(H_vec, H_i_square)
    end

    HAM = sum(H_vec)
end

```

@mtfishman Is there any reason to prefer one over the other?

---

<div class="post-metadata">

**Author:** ![adityab999](https://avatars.discourse-cdn.com/v4/letter/a/7c8e57/32.png) [@adityab999](https://itensor.discourse.group/u/adityab999)\
**Post date:** [August 20, 2023, 9:17pm UTC](https://itensor.discourse.group/t/operator-definition-as-a-product-of-operators/673/15 "2023-08-20T21:17:58Z")

</div>

@JanReimers - Hi Jan, yes that’s very much what my code is essentially trying to do. Thanks a lot really, your suggestion works without any issue.

@EmilioRui - Hi Emilio, thanks very much, your suggestion is also working equally well as Jan’s suggestion.

On small systems both are showing similar running times after starting the DMRG engine with the same parameters for both cases, perhaps if there’s any performance difference between the two it shows up for large enough systems (to check later!)
