JuliaAttic / QuBase.jl

A foundational library for quantum mechanics in Julia
Other
43 stars 6 forks source link

Behavior of accessor functions on ladderops #21

Closed amitjamadagni closed 9 years ago

amitjamadagni commented 9 years ago

The following error occurs when accessor functions are called on ladderops.


julia> r = raiseop(4)
4x4 QuMatrix in QuBase.FiniteBasis{QuBase.Orthonormal,1}:
...coefficients: Base.SparseMatrix.SparseMatrixCSC{Float64,Int64}

    [2, 1]  =  1.0
    [3, 2]  =  1.41421
    [4, 3]  =  1.73205

julia> coeffs(r)
ERROR: MethodError: `coeffs` has no method matching coeffs(::QuBase.QuArray{QuBase.FiniteBasis{QuBase.Orthonormal,1},Float64,2,Base.SparseMatrix.SparseMatrixCSC{Float64,Int64}})

# but the following thing works.

julia> m = [1+1im 2+2im 3+3im; 
            4.9+4im 5+5im 6+6im; 
            7+7im 8+8im 9+9im]
3x3 Array{Complex{Float64},2}:
 1.0+1.0im  2.0+2.0im  3.0+3.0im
 4.9+4.0im  5.0+5.0im  6.0+6.0im
 7.0+7.0im  8.0+8.0im  9.0+9.0im

julia> spm = sparse(m)
3x3 sparse matrix with 9 Complex{Float64} entries:
    [1, 1]  =  1.0+1.0im
    [2, 1]  =  4.9+4.0im
    [3, 1]  =  7.0+7.0im
    [1, 2]  =  2.0+2.0im
    [2, 2]  =  5.0+5.0im
    [3, 2]  =  8.0+8.0im
    [1, 3]  =  3.0+3.0im
    [2, 3]  =  6.0+6.0im
    [3, 3]  =  9.0+9.0im

julia> qspm = QuArray(spm)
3x3 QuMatrix in QuBase.FiniteBasis{QuBase.Orthonormal,1}:
...coefficients: Base.SparseMatrix.SparseMatrixCSC{Complex{Float64},Int64}

    [1, 1]  =  1.0+1.0im
    [2, 1]  =  4.9+4.0im
    [3, 1]  =  7.0+7.0im
    [1, 2]  =  2.0+2.0im
    [2, 2]  =  5.0+5.0im
    [3, 2]  =  8.0+8.0im
    [1, 3]  =  3.0+3.0im
    [2, 3]  =  6.0+6.0im
    [3, 3]  =  9.0+9.0im

julia> coeffs(qspm)
3x3 sparse matrix with 9 Complex{Float64} entries:
    [1, 1]  =  1.0+1.0im
    [2, 1]  =  4.9+4.0im
    [3, 1]  =  7.0+7.0im
    [1, 2]  =  2.0+2.0im
    [2, 2]  =  5.0+5.0im
    [3, 2]  =  8.0+8.0im
    [1, 3]  =  3.0+3.0im
    [2, 3]  =  6.0+6.0im
    [3, 3]  =  9.0+9.0im

Similarly with respect to other functions. I have tried playing around but I have not found any solution for this. It would be great to hear something on this. Thanks.

jrevels commented 9 years ago

We didn't have these functions exported yet, which is why you couldn't call it (if you input QuBase.coeffs instead just coeffs, it should've worked). I just pushed a commit to add rawcoeffs and coeffs to the export list, so it should work fine in the future.

Also on a side note - from what you posted, it looks like you're using a post-v0.3 release of Julia. We're targeting the v0.3 release for now, since it's the current stable version. Functionality might be broken if you use a newer build than that...though keeping track of issues on the latest build now will help when we update to v0.4 in the future :)

EDIT: Ah early morning tiredness got me, I see where calling coeffs DID work for you...hmm. This might just be because you're on a later build, I need to look deeper...

jrevels commented 9 years ago

Are you sure you didn't have a using QuBase.coeffs statement or something before calling coeffs(qspm)? That function definitely wasn't exported before 4e939d845c9fc77519b33f623c0cbcf52684ebe1...failing to find the coeffs method was the expected behavior before that commit. It's weird that it worked at all for you without calling it directly from the module.

Either way, try pulling the latest version and see if it takes care of the problems you were having.

EDIT: I bet you ran the test suite before your second example! We had using statements for rawcoeffs and coeffs there so that we could easily call them during tests. Those statements are no longer there in master, since the functions are now exported.

amitjamadagni commented 9 years ago

@jrevels thanks for input on this. However I had pulled the latest master and then did this https://gist.github.com/amitjamadagni/9884dc93dd0a08051e43. Yeah I have been working on the latest master (Julia) which is a higher version than 0.3, which has been reflected in the link. Could you please have a look at the gist I posted. Thanks :)

jrevels commented 9 years ago

The ambiguity warnings are definitely due to being on v0.4, as call overloading isn't a feature included in v0.3. As for coeffs not dispatching properly...strange indeed. I ran that code on v0.3, and everything worked as expected.

Like I said, v0.4 compatibility isn't one of our goals for now, but I'm curious - what's the output when you call methods(coeffs) and methods(rawcoeffs)?

jrevels commented 9 years ago

Also, you shouldn't need to call require(...) after the using statement. Running using QuBase calls require on the module file in the package repo by default, from which quarray.jl is included.

amitjamadagni commented 9 years ago

I end up with these when I run methods(coeffs) and methods(rawcoeffs)

julia> methods(coeffs)
# 2 methods for generic function "coeffs":
coeffs(qarr::QuArray{B<:QuBase.AbstractBasis{S<:QuBase.AbstractStructure},T,N,A}) at /home/amit/Downloads/SemVII/QuBase.jl/src/arrays/quarray.jl:34
coeffs(ct::CTranspose{B,T,N,A}) at /home/amit/Downloads/SemVII/QuBase.jl/src/arrays/quarray.jl:78

julia> methods(rawcoeffs)
# 2 methods for generic function "rawcoeffs":
rawcoeffs(qarr::QuArray{B<:QuBase.AbstractBasis{S<:QuBase.AbstractStructure},T,N,A}) at /home/amit/Downloads/SemVII/QuBase.jl/src/arrays/quarray.jl:33
rawcoeffs(ct::CTranspose{B,T,N,A}) at /home/amit/Downloads/SemVII/QuBase.jl/src/arrays/quarray.jl:77

As per my understanding these are as expected.

And yeah coming to require statement, I did not pull in the latest commit which had exported so I had to do it. Though I did pull in the master before that.

So what do you suggest for this case, I was trying to implement the position and momentum related operators by using lowerop and raiseop (by initially defining +,- for QuArray). Should I move to a lower version and build julia and then carry out the operations or is there any other work around ??

jrevels commented 9 years ago

That output you just posted looks okay...it's possible the behavior you were having trouble with before might be coming from a bug in Julia master, though I'm not running v0.4 so I wouldn't know. Either way, it seems like it's just an incompatibility issue. I'm going to tag it as such and close this up, but feel free to update this thread if anything related pops up, it could be useful later when we do eventually move to the v0.4 :)

Should I move to a lower version and build julia and then carry out the operations or is there any other work around ??

Yes, specifically you should be building off of the latest stable release (the "release-0.3" branch of the Julia language repo) for all development/testing/usage of QuBase. There was a mention of having an experimental 0.4 branch but it's not a priority for us right now.

amitjamadagni commented 9 years ago

@jrevels I have reverted back to the stable version. Here are a few related doubts :

  1. I have defined the following in the arraymath.jl
function +{B<:OrthonormalBasis}(qm1::QuMatrix{B}, qm2::QuMatrix{B})
    return QuArray(rawcoeffs(qm1)+rawcoeffs(qm2), bases(qm1,1), bases(qm1,1))
end

Then when I do this

using QuBase
require("/home/amit/Downloads/SemVII/QuBase.jl/src/arrays/quarray.jl")
require("/home/amit/Downloads/SemVII/QuBase.jl/src/arrays/arraymath.jl")
m = [1.0+1im 2+2im 3+3im;
            4+4im 5+5im 6+6im;
            7+7im 8+8im 9+9im]
qm = QuArray(m)
println(qm)
qm1 = 1/2*qm
println(qm1)
a = raiseop(3)
println(a)
b = lowerop(3)
println(b)
println(a*b)
println(qm+qm1)
println(a+b)

I get the consistent results until the last one, the last one fails. Here is the output

3x3 QuMatrix in FiniteBasis{Orthonormal,1}:
...coefficients: Array{Complex{Float64},2}
Complex{Float64}[1.0 + 1.0im 2.0 + 2.0im 3.0 + 3.0im
                 4.0 + 4.0im 5.0 + 5.0im 6.0 + 6.0im
                 7.0 + 7.0im 8.0 + 8.0im 9.0 + 9.0im]
3x3 QuMatrix in FiniteBasis{Orthonormal,1}:
...coefficients: Array{Complex{Float64},2}
Complex{Float64}[0.5 + 0.5im 1.0 + 1.0im 1.5 + 1.5im
                 2.0 + 2.0im 2.5 + 2.5im 3.0 + 3.0im
                 3.5 + 3.5im 4.0 + 4.0im 4.5 + 4.5im]
3x3 QuMatrix in FiniteBasis{Orthonormal,1}:
...coefficients: SparseMatrixCSC{Float64,Int64}

    [2, 1]  =  1.0
    [3, 2]  =  1.41421
3x3 QuMatrix in FiniteBasis{Orthonormal,1}:
...coefficients: SparseMatrixCSC{Float64,Int64}

    [1, 2]  =  1.0
    [2, 3]  =  1.41421
3x3 QuMatrix in FiniteBasis{Orthonormal,1}:
...coefficients: SparseMatrixCSC{Float64,Int64}

    [2, 2]  =  1.0
    [3, 3]  =  2.0
3x3 QuMatrix in FiniteBasis{Orthonormal,1}:
...coefficients: Array{Complex{Float64},2}
Complex{Float64}[1.5 + 1.5im 3.0 + 3.0im 4.5 + 4.5im
                 6.0 + 6.0im 7.5 + 7.5im 9.0 + 9.0im
                 10.5 + 10.5im 12.0 + 12.0im 13.5 + 13.5im]
ERROR: `+` has no method matching +(::QuArray{FiniteBasis{Orthonormal,1},Float64,2,SparseMatrixCSC{Float64,Int64}}, ::QuArray{FiniteBasis{Orthonormal,1},Float64,2,SparseMatrixCSC{Float64,Int64}})
  1. I have a bit of problem understanding the passing of bases in QuArray. In sense we use bases(qm,1) and bases(qm,2), for example in the multiplication of operator and conjugate transpose we explicitly pass bases when we could have created QuArray by just passing the coefficients. It would be helpful to get more insight on this. For example :
julia> m = [1+1im 2+2im 3+3im; 
            4.9+4im 5+5im 6+6im; 
            7+7im 8+8im 9+9im]
3x3 Array{Complex{Float64},2}:
 1.0+1.0im  2.0+2.0im  3.0+3.0im
 4.9+4.0im  5.0+5.0im  6.0+6.0im
 7.0+7.0im  8.0+8.0im  9.0+9.0im

julia> mt = m'
3x3 Array{Complex{Float64},2}:
 1.0-1.0im  4.9-4.0im  7.0-7.0im
 2.0-2.0im  5.0-5.0im  8.0-8.0im
 3.0-3.0im  6.0-6.0im  9.0-9.0im

julia> m*m'
3x3 Array{Complex{Float64},2}:
  28.0+0.0im    64.9+0.9im  100.0+0.0im
  64.9-0.9im  162.01+0.0im  250.3-6.3im
 100.0+0.0im   250.3+6.3im  388.0+0.0im

julia> QuArray(m*m')
3x3 QuMatrix in FiniteBasis{Orthonormal,1}:
...coefficients: Array{Complex{Float64},2}
Complex{Float64}[28.0 + 0.0im 64.9 + 0.9000000000000004im 100.0 + 0.0im
                 64.9 - 0.9000000000000004im 162.01 + 0.0im 250.3 - 6.300000000000004im
                 100.0 + 0.0im 250.3 + 6.300000000000004im 388.0 + 0.0im]
acroy commented 9 years ago

You don't need the require calls after using QuBase [1], but you have to make sure that you import Base.+ in arraymath.jl like we import Base.* (to make sure that you are actually extending Base.+). For addition of QuArrays both arguments need to have the same bases as you anticipated, and the result will also have the same bases, so you can write (haven't tested this)

function +{B<:OrthonormalBasis}(qm1::QuMatrix{B}, qm2::QuMatrix{B})
    return QuArray(rawcoeffs(qm1)+rawcoeffs(qm2), bases(qm1))
end

(Maybe we should have some kind of assert macro which checks that the bases are actually equal?) if you get this to work, try to generalize this function to arbitrary QuArrays.

In general we have to pass the bases around, since they contain additional information. For example, they could result from a tensor product of states. In your last example, QuArray(m*m') assumes that no such structure is present the the most simple basis is used (it just contains the number of basis functions, which is size(m*m',1)).

[1] If you have two versions of QuBase, say one installed via Pkg.checkout and one development version somewhere else, you might have to include the latter before using QuBase, I.e.

include("/home/amit/Downloads/SemVII/QuBase.jl/src/QuBase.jl")
using QuBase
amitjamadagni commented 9 years ago

@acroy Ah seems like include statement gives the result. Thanks for this :). I will try sending in a pull with the additions.