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

Improve standard order printing #214

Merged
merged 4 commits into from
May 9, 2018
Merged

Improve standard order printing #214

merged 4 commits into from
May 9, 2018

Conversation

goropikari
Copy link
Contributor

I have improved standard order printing by removing permutation.

Present issues

As far as I know, there are two issues related to standard order printing.

  • As increasing dimensions, permutation can't work correctly at a certain point.
  • It takes a lot of time to print for high dimensional state.
julia> using QuantumOptics

julia> QuantumOptics.set_printing(standard_order=false)

julia> n = 16;

julia> state = randstate(tensor([SpinBasis(1//2) for i in 1:n]...))
Ket(dim=65536)
  basis: [Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)]
  0.00356055+0.00413365im
  0.00125937+0.000968859im
   0.0037847+0.000102558im
  0.00148401+0.00277967im
  0.00431765+0.00336918im
  0.00230288+0.00412798im
 0.000792853+0.00240365im
            
  0.00308116+0.00377516im
   0.0035116+0.00118091im
  0.00297204+0.000868845im
  0.00122666+0.00166977im
  0.00458962+0.00297235im
 0.000244887+0.00462441im

julia> QuantumOptics.set_printing(standard_order=true)

julia> state
Ket(dim=65536)
  basis: [Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)]
Error showing value of type QuantumOptics.states.Ket:
ERROR: MethodError: no method matching checkdims_perm(::Array{Complex{Float64},2}, ::Array{Complex{Float64},16}, ::Array{Int64,1})
Closest candidates are:
  checkdims_perm(::AbstractArray{TP,N}, ::AbstractArray{TB,N}, ::Any) where {TP, TB, N} at multidimensional.jl:1301
Stacktrace:
 [1] permutedims! at ./permuteddimsarray.jl:132 [inlined]
 [2] permutedims(::Array{Complex{Float64},16}, ::Array{Int64,1}) at ./multidimensional.jl:1297
 [3] permutesystems(::QuantumOptics.states.Ket, ::Array{Int64,1}) at /home/goropikari/.julia/v0.6/QuantumOptics/src/states.jl:118
 [4] showquantumstatebody(::IOContext{Base.Terminals.TTYTerminal}, ::QuantumOptics.states.Ket) at /home/goropikari/.julia/v0.6/QuantumOptics/src/printing.jl:126
 [5] show(::IOContext{Base.Terminals.TTYTerminal}, ::QuantumOptics.states.Ket) at /home/goropikari/.julia/v0.6/QuantumOptics/src/printing.jl:92
 [6] display(::Base.REPL.REPLDisplay{Base.REPL.LineEditREPL}, ::MIME{Symbol("text/plain")}, ::QuantumOptics.states.Ket) at ./REPL.jl:122
 [7] display(::Base.REPL.REPLDisplay{Base.REPL.LineEditREPL}, ::QuantumOptics.states.Ket) at ./REPL.jl:125
 [8] display(::QuantumOptics.states.Ket) at ./multimedia.jl:218
 [9] hookless(::Media.##7#8{QuantumOptics.states.Ket}) at /home/goropikari/.julia/v0.6/Media/src/compat.jl:14
 [10] render(::Media.NoDisplay, ::QuantumOptics.states.Ket) at /home/goropikari/.julia/v0.6/Media/src/compat.jl:27
 [11] display(::Media.DisplayHook, ::QuantumOptics.states.Ket) at /home/goropikari/.julia/v0.6/Media/src/compat.jl:9
 [12] display(::QuantumOptics.states.Ket) at ./multimedia.jl:218
 [13] print_response(::Base.Terminals.TTYTerminal, ::Any, ::Void, ::Bool, ::Bool, ::Void) at ./REPL.jl:144
 [14] print_response(::Base.REPL.LineEditREPL, ::Any, ::Void, ::Bool, ::Bool) at ./REPL.jl:129
 [15] (::Base.REPL.#do_respond#16{Bool,Base.REPL.##26#36{Base.REPL.LineEditREPL,Base.REPL.REPLHistoryProvider},Base.REPL.LineEditREPL,Base.LineEdit.Prompt})(::Base.LineEdit.MIState, ::Base.AbstractIOBuffer{Array{UInt8,1}}, ::Bool) at ./REPL.jl:646
 [16] run_repl(::Base.REPL.LineEditREPL, ::Base.##510#511) at ./REPL.jl:180
julia> QuantumOptics.set_printing(standard_order=false)

julia> begin
           start = now()
           println(IOContext(STDOUT, :limit => true), tensor([sigmax(SpinBasis(1//2)) for i in 1:10]...) )
           println("\nElapsed time ", now() - start)
       end
SparseOperator(dim=1024x1024)
  basis: [Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)]
  [1024,    1]  =  1.0+0.0im
  [1023,    2]  =  1.0+0.0im
  [1022,    3]  =  1.0+0.0im
  [1021,    4]  =  1.0+0.0im
  
  [5   , 1020]  =  1.0+0.0im
  [4   , 1021]  =  1.0+0.0im
  [3   , 1022]  =  1.0+0.0im
  [2   , 1023]  =  1.0+0.0im
  [1   , 1024]  =  1.0+0.0im

Elapsed time 40 milliseconds

julia> QuantumOptics.set_printing(standard_order=true)

julia> begin
           start = now()
           println(IOContext(STDOUT, :limit => true), tensor([sigmax(SpinBasis(1//2)) for i in 1:10]...) )
           println("\nElapsed time ", now() - start)
       end
SparseOperator(dim=1024x1024)
  basis: [Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)]
  [1024,    1]  =  1.0+0.0im
  [1023,    2]  =  1.0+0.0im
  [1022,    3]  =  1.0+0.0im
  [1021,    4]  =  1.0+0.0im
  
  [5   , 1020]  =  1.0+0.0im
  [4   , 1021]  =  1.0+0.0im
  [3   , 1022]  =  1.0+0.0im
  [2   , 1023]  =  1.0+0.0im
  [1   , 1024]  =  1.0+0.0im

Elapsed time 112604 milliseconds

Improved version

The above problems are caused by permutation. So I remove it and have modified pretty-print for Vector and Matrix in order to support standard order print.

julia> QuantumOptics.set_printing(standard_order=true)

julia> n = 16;

julia> state = randstate(tensor([SpinBasis(1//2) for i in 1:n]...))
Ket(dim=65536)
  basis: [Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)]
   0.0046426+0.000733012im
 0.000834063+0.000656921im
  0.00208061+0.00376535im
  0.00474521+0.00398865im
  0.00340159+0.00475972im
  0.00452512+0.00308996im
  0.00170184+0.000141695im
                         
 0.000460809+3.53136e-5im
   0.0030361+0.00310422im
  0.00365822+0.000224724im
  0.00232017+0.00361737im
  1.48747e-6+0.00142205im
  0.00234002+9.80094e-6im
julia> begin
           start = now()
           println(IOContext(STDOUT, :limit => true), tensor([sigmax(SpinBasis(1//2)) for i in 1:10]...) )
           println("\nElapsed time ", now() - start)
       end
SparseOperator(dim=1024x1024)
  basis: [Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)  Spin(1/2)]
  [1024,    1]  =  1.0+0.0im
  [512 ,  513]  =  1.0+0.0im
  [768 ,  257]  =  1.0+0.0im
  [256 ,  769]  =  1.0+0.0im
  
  [129 ,  896]  =  1.0+0.0im
  [769 ,  256]  =  1.0+0.0im
  [257 ,  768]  =  1.0+0.0im
  [513 ,  512]  =  1.0+0.0im
  [1   , 1024]  =  1.0+0.0im

Elapsed time 49 milliseconds

New issue

By this modification, I fix above problems (error and printing speed).
However as you look above output, about sparse matrix it is not same as permutation version (current version).

As you see following small example, the printed order is not same although information is identical.
I want to print it same order, but I don't have the good idea.

Is there a good solution?

julia> QuantumOptics.set_printing(standard_order=true)

# before modification
julia> sigmax(SpinBasis(1//2))  sigmay(SpinBasis(1//2))
SparseOperator(dim=4x4)
  basis: [Spin(1/2)  Spin(1/2)]
  [4, 1]  =  0.0+1.0im
  [3, 2]  =  0.0-1.0im
  [2, 3]  =  0.0+1.0im
  [1, 4]  =  0.0-1.0im
julia> QuantumOptics.set_printing(standard_order=true)

# after modification
julia> sigmax(SpinBasis(1//2))  sigmay(SpinBasis(1//2))
SparseOperator(dim=4x4)
  basis: [Spin(1/2)  Spin(1/2)]
  [4, 1]  =  0.0+1.0im
  [2, 3]  =  0.0+1.0im
  [3, 2]  =  0.0-1.0im
  [1, 4]  =  0.0-1.0im

My environment

julia> versioninfo()
Julia Version 0.6.2
Commit d386e40 (2017-12-13 18:08 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: Intel(R) Xeon(R) CPU           E5645  @ 2.40GHz
  WORD_SIZE: 64
  BLAS: libopenblas (DYNAMIC_ARCH NO_AFFINITY Nehalem)
  LAPACK: libopenblas
  LIBM: libm
  LLVM: libLLVM-3.9.1 (ORCJIT, westmere)

@coveralls
Copy link

coveralls commented May 4, 2018

Coverage Status

Coverage decreased (-0.07%) to 99.931% when pulling 71a0056 on goropikari:print_stdord into 4fec08f on qojulia:master.

@codecov
Copy link

codecov bot commented May 4, 2018

Codecov Report

Merging #214 into master will decrease coverage by 0.06%.
The diff coverage is 98.62%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #214      +/-   ##
==========================================
- Coverage     100%   99.93%   -0.07%     
==========================================
  Files          34       34              
  Lines        2755     2878     +123     
==========================================
+ Hits         2755     2876     +121     
- Misses          0        2       +2
Impacted Files Coverage Δ
src/printing.jl 99% <98.62%> (-1%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 4fec08f...71a0056. Read the comment docs.

@david-pl
Copy link
Member

david-pl commented May 6, 2018

Thanks for all the work you put in this PR. I would really like to merge it, but I agree that the order of printing should be fixed first.

Unfortunately, I also couldn't come up with a good solution for this new issue when going through your code. Basically, in the printing loop in the showsparsearray_stdord function you print out the data in the same order as for standard_order=false but with updated (standard order) indexes. This needs to be changed so that it follows Julia's column-major order. I'm not sure how to do this, though. A kind of hacky solution would be to store the data to be printed from the loop (instead of printing immediately) and then re-order it according to the column index. This will cause allocations, though, so it will affect performance.

I have one more unrelated question: could the indexing with mirror_world_index be generalized to index arbitrary orders? If so, could one use that to improve the implementation of permutesystems in general?

src/printing.jl Outdated
half_screen_rows = typemax(Int)
end
pad = ndigits(max(S.m,S.n))
k = 0
Copy link
Member

Choose a reason for hiding this comment

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

The assignment of k here is overwritten later when k is used as loop variable, so this line here is not needed.

src/printing.jl Outdated
elseif k == half_screen_rows
print(io, sep, '\u22ee')
end
k += 1
Copy link
Member

Choose a reason for hiding this comment

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

Again this line has no effect since k is overwritten by the next step in the loop.

@goropikari
Copy link
Contributor Author

I will reconstruct showsparsearray_stdord to print same order.

I have one more unrelated question: could the indexing with mirror_world_index be generalized to index arbitrary orders? If so, could one use that to improve the implementation of permutesystems in general?

No. mirror_world_index doesn't support arbitrary order. By combining ind2Nary and Nary2ind, it is possible to support arbitry order. But the performance gets worse.
It is because its computational cost is higher than permutedims.

For printing case, only part of the matrix entries are printed in REPL. So we don't need all matrix entries information. We need several thousand entries information at most. In that case even if a matrix size becomes larger and lager, computational cost is almost constant (since the number of printed entries is fixed).
Therefore the modified program is faster than permutation.

However permutedims is more efficient than the modified program when we need all matrix entries.

@goropikari
Copy link
Contributor Author

I fix showsparsearray_stdord. The output is same as permutation version.

@david-pl
Copy link
Member

david-pl commented May 8, 2018

Thanks for the update. Everything looks to be fine now. I am just a bit worried because there is entire functions that are never called during testing (e.g. show_delim_array_std). Is it possible to test these functions or are all of them reserved for cases where the output has to be truncated to a smaller space in the REPL?

@goropikari
Copy link
Contributor Author

Sorry. Those functions are not necessary.
I delete them.

@david-pl david-pl merged commit b571452 into qojulia:master May 9, 2018
@goropikari goropikari deleted the print_stdord branch July 24, 2018 00:59
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.

3 participants