ITensors.jl
ITensors.jl copied to clipboard
[ITensors] [ENHANCEMENT] Combining operators with parenthesis in single line in OpSum
Since the documentation for OpSum is lacking, I'd like to know if there is a way of writing on one line an expression like
$$\sigma_1 (\sigma_2 + \sigma_3)$$
Now I'm able to do it in two lines as
os = OpSum()
os += "Z", 1, "Z", 2
os += "Z", 1, "Z", 3
but since I have expressions with many terms I'd like to able to write on one line. I tried something like
os = OpSum()
os += "Z", 1, "(", "Z", 2, "+", "Z", 3, ")"
or similar to this but it doesn't work.
Maybe not quite what you're hoping for, but you can do this:
julia> (OpSum() + ("Z", 1)) * (OpSum() + ("Z", 2) + ("Z", 3))
prod(
sum(
1.0 Z(1,)
)
sum(
1.0 Z(2,)
1.0 Z(3,)
)
)
julia> Ops.expand((OpSum() + ("Z", 1)) * (OpSum() + ("Z", 2) + ("Z", 3)))
sum(
1.0 Z(1,) Z(2,)
1.0 Z(1,) Z(3,)
)
An alternative which isn't documented is that all of these operations are based on converting tuples like ("Z", 2) which represent operators on a certain site to an object Op("Z", 2). Those operators have various algebra operations defined for them. So you can do the same thing as the above with:
julia> Op("Z", 1) * (Op("Z", 2) + Op("Z", 3))
sum(
Z(1,) Z(2,)
Z(1,) Z(3,)
)
I don't think we will support the parentheses syntax you propose above. I was trying to move more towards lazy operations happening at the Op level using normal Julia algebra syntax, rather than through specialized syntax or parsing.
Something that isn't working now but should work is:
julia> ("Z", 1) * (OpSum() + ("Z", 2) + ("Z", 3))
ERROR: MethodError: no method matching *(::Op, ::Scaled{ComplexF64, Prod{Op}})
Closest candidates are:
*(::Any, ::Any, ::Any, ::Any...)
@ Base operators.jl:578
*(::Union{InitialValues.NonspecificInitialValue, InitialValues.SpecificInitialValue{typeof(*)}}, ::Any)
@ InitialValues ~/.julia/packages/InitialValues/OWP8V/src/InitialValues.jl:154
*(::Number, ::ITensors.LazyApply.Applied{typeof(*), Tuple{C, A}, NamedTuple{(), Tuple{}}} where A) where C
@ ITensors ~/.julia/packages/ITensors/hLDmL/src/LazyApply/LazyApply.jl:72
...
Stacktrace:
[1] (::ITensors.Ops.var"#3#4"{Op})(a::Scaled{ComplexF64, Prod{Op}})
@ ITensors.Ops ~/.julia/packages/ITensors/hLDmL/src/Ops/Ops.jl:208
[2] iterate
@ ./generator.jl:47 [inlined]
[3] _collect
@ ./array.jl:802 [inlined]
[4] collect_similar
@ ./array.jl:711 [inlined]
[5] map
@ ./abstractarray.jl:3261 [inlined]
[6] *
@ ~/.julia/packages/ITensors/hLDmL/src/Ops/Ops.jl:208 [inlined]
[7] *(o1::Tuple{String, Int64}, o2::Sum{Scaled{ComplexF64, Prod{Op}}})
@ ITensors.Ops ~/.julia/packages/ITensors/hLDmL/src/Ops/Ops.jl:296
[8] top-level scope
@ REPL[28]:1
julia> Op("Z", 1) * (OpSum() + ("Z", 2) + ("Z", 3))
ERROR: MethodError: no method matching *(::Op, ::Scaled{ComplexF64, Prod{Op}})
Closest candidates are:
*(::Any, ::Any, ::Any, ::Any...)
@ Base operators.jl:578
*(::Union{InitialValues.NonspecificInitialValue, InitialValues.SpecificInitialValue{typeof(*)}}, ::Any)
@ InitialValues ~/.julia/packages/InitialValues/OWP8V/src/InitialValues.jl:154
*(::Number, ::ITensors.LazyApply.Applied{typeof(*), Tuple{C, A}, NamedTuple{(), Tuple{}}} where A) where C
@ ITensors ~/.julia/packages/ITensors/hLDmL/src/LazyApply/LazyApply.jl:72
...
Stacktrace:
[1] (::ITensors.Ops.var"#3#4"{Op})(a::Scaled{ComplexF64, Prod{Op}})
@ ITensors.Ops ~/.julia/packages/ITensors/hLDmL/src/Ops/Ops.jl:208
[2] iterate
@ ./generator.jl:47 [inlined]
[3] _collect
@ ./array.jl:802 [inlined]
[4] collect_similar
@ ./array.jl:711 [inlined]
[5] map
@ ./abstractarray.jl:3261 [inlined]
[6] *(o1::Op, o2::Sum{Scaled{ComplexF64, Prod{Op}}})
@ ITensors.Ops ~/.julia/packages/ITensors/hLDmL/src/Ops/Ops.jl:208
[7] top-level scope
@ REPL[29]:1
I'll have to look into that, I think just a missing definition.
I'll leave this open as a remind to fix the last two bugs.