Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added multiplication of LazyOperators #108

Closed

Conversation

mabuni1998
Copy link
Contributor

@mabuni1998 mabuni1998 commented Jun 19, 2023

Added functions for multiplying two LazySum operators, LazySum with LazyTensor / LazyProduct and LazyTensor with LazyProduct. I also added tests for the new functions.

Although debatable whether necessary, there might be situations where you would prefer not to explicitly have to calculate the product and create the appropriate LazyOperator. For example, if you wanted to create a unitary time evolution operator you might write:

U = identityoperator(H) - im*dt*H + (-im*dt)^2/2*H^2

where H is a LazyOperator. This is currently not possible, but with the few added lines of code here, you can do the above.

One thing to note is that when multiplying a non-lazy operator with a LazyOperator currently the following functions are used:

function *(op1::AbstractOperator{B1,B2}, op2::Operator{B2,B3,T}) where {B1,B2,B3,T}
result = Operator{B1,B3}(op1.basis_l, op2.basis_r, similar(_parent(op2.data),promote_type(eltype(op1),eltype(op2)),length(op1.basis_l),length(op2.basis_r)))
mul!(result,op1,op2)
return result
end
function *(op1::Operator{B1,B2,T}, op2::AbstractOperator{B2,B3}) where {B1,B2,B3,T}
result = Operator{B1,B3}(op1.basis_l, op2.basis_r, similar(_parent(op1.data),promote_type(eltype(op1),eltype(op2)),length(op1.basis_l),length(op2.basis_r)))
mul!(result,op1,op2)
return result
end
function *(op::AbstractOperator{BL,BR}, psi::Ket{BR,T}) where {BL,BR,T}
result = Ket{BL,T}(op.basis_l,similar(psi.data,length(op.basis_l)))
mul!(result,op,psi)
return result
end
function *(psi::Bra{BL,T}, op::AbstractOperator{BL,BR}) where {BL,BR,T}
result = Bra{BR,T}(op.basis_r, similar(psi.data,length(op.basis_r)))
mul!(result,psi,op)
return result
end

The LazyOperators are thus not contagious with non-lazy operators in multiplication. This is, however, probably for the best since the above lines of code are also used when computing multiplication with a density matrix (which is represented as an operator) and in this instance, we don't want to create a LazyOperator but actually calculate e.g. the expectation value. If we wanted to have contagious LazyOperators in multiplication we would have to distinguish between operators and density matrices.

@codecov
Copy link

codecov bot commented Jun 19, 2023

Codecov Report

Merging #108 (c35dfe3) into master (f98ec89) will increase coverage by 0.05%.
The diff coverage is 100.00%.

@@            Coverage Diff             @@
##           master     #108      +/-   ##
==========================================
+ Coverage   93.33%   93.39%   +0.05%     
==========================================
  Files          24       24              
  Lines        2881     2907      +26     
==========================================
+ Hits         2689     2715      +26     
  Misses        192      192              
Impacted Files Coverage Δ
src/operators_lazysum.jl 97.38% <100.00%> (+0.48%) ⬆️
src/operators_lazytensor.jl 96.99% <100.00%> (+0.01%) ⬆️

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

for i in eachindex(a.operators)
c[i] = LazyProduct(a.operators[i]) * b
end
LazySum(a.basis_l, b.basis_r, a.factors, (c...,))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have an array typed to AbstractOperator. If your array is already meant to contain abstract types, there is not much reason to do anything more specific than Any, especially given that it would be slightly more readable code.

More importantly though, here you create a temporary array and then you immediately destroy it. It is a bit wasteful (causing unnecessary allocations). It might be a bit simpler to just use a "generator" (a "lazy" object that does not actually compute the content until it is queried):

julia> generator = (i for i in 1:10)
Base.Generator{UnitRange{Int64}, typeof(identity)}(identity, 1:10)

julia> tuple = (generator...,)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

So your code can be simplified to something like LazySum(bl, br, a.factors, ((LazyProduct(op)*b for op in a.operators)...,))

for i in eachindex(b.operators)
c[i] = a * LazyProduct(b.operators[i])
end
LazySum(a.basis_l, b.basis_r, b.factors, (c...,))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same simplificaiton here

@Krastanov
Copy link
Collaborator

I suggested some minor simplifications, but they are more of a style suggestion, no need to actually follow up on them. They will save one allocation each, but this is not a place in the codebase that saving an allocation is very valuable. Especially given that for the third method you have defined, they are not much of a simplification anyway.

Looks good to merge for me! I would also love to have access to this as work is picking up momentum on QuantumSavory and QuantumSymbolics.

Could you also bump the version number to 0.4.4.

I will wait for a couple of days if anyone else wants to comment on this before merging.

@Krastanov
Copy link
Collaborator

Actually, the bump in Project.toml should be to 0.4.5

@Krastanov
Copy link
Collaborator

I take the comment about merging in the nearterm back. I think this overlaps a bit with #104 which we should evaluate first, as it brings up a bunch of other functionality as well.

@Krastanov
Copy link
Collaborator

@mabuni1998 , now that #104 is merged, I think we can close this one as it is a subset of #104. Please let me know if anything is missing from #104 and we can cherry pick it into a new PR.

@Krastanov Krastanov closed this Jul 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants