From 0aee91487a7437c54af4db98039ea596ab71d4d2 Mon Sep 17 00:00:00 2001 From: Yi-Te Huang Date: Wed, 22 May 2024 12:59:41 +0800 Subject: [PATCH 1/6] change CI JuliaFormatter-PR to FormatCheck --- .github/workflows/FormatCheck.yml | 42 ++++++++++++++++++++++++++++ .github/workflows/JuliaFormatter.yml | 31 -------------------- 2 files changed, 42 insertions(+), 31 deletions(-) create mode 100644 .github/workflows/FormatCheck.yml delete mode 100644 .github/workflows/JuliaFormatter.yml diff --git a/.github/workflows/FormatCheck.yml b/.github/workflows/FormatCheck.yml new file mode 100644 index 00000000..a691e4b3 --- /dev/null +++ b/.github/workflows/FormatCheck.yml @@ -0,0 +1,42 @@ +name: Format Check +on: + push: + branches: + - 'main' + tags: + - '*' + pull_request: + branches: + - 'main' + types: + - opened + - reopened + - synchronize + - ready_for_review + +jobs: + build: + runs-on: ubuntu-latest + if: ${{ !github.event.pull_request.draft }} + steps: + - uses: actions/checkout@v4 + - uses: julia-actions/setup-julia@v2 + with: + version: '1' + - name: Install and Run JuliaFormatter + run: | + julia -e 'import Pkg; Pkg.add("JuliaFormatter")' + julia -e 'using JuliaFormatter; format(".", verbose=true)' + + - name: Format Check + run: | + julia -e ' + output = Cmd(`git diff --name-only`) |> read |> String + if output == "" + exit(0) + else + @error "The following files have not been formatted !!!" + write(stdout, output) + write(stdout, "Please format it by running: \'using JuliaFormatter; format(\".\")\'") + exit(1) + end' \ No newline at end of file diff --git a/.github/workflows/JuliaFormatter.yml b/.github/workflows/JuliaFormatter.yml deleted file mode 100644 index 13aba6b8..00000000 --- a/.github/workflows/JuliaFormatter.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: JuliaFormatter PR -on: - schedule: - - cron: '0 0 * * *' -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: julia-actions/cache@v1 - - name: Install JuliaFormatter and format - run: | - julia -e 'import Pkg; Pkg.add("JuliaFormatter")' - julia -e 'using JuliaFormatter; format(".")' - - # https://github.com/marketplace/actions/create-pull-request - # https://github.com/peter-evans/create-pull-request#reference-example - - name: Create Pull Request - id: cpr - uses: peter-evans/create-pull-request@v3 - with: - token: ${{ secrets.GITHUB_TOKEN }} - commit-message: Format .jl files - title: 'Automatic JuliaFormatter.jl run' - branch: auto-juliaformatter-pr - delete-branch: true - labels: formatting, automated pr, no changelog - - name: Check outputs - run: | - echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}" - echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}" \ No newline at end of file From 66d912e4aab5f652db4e27736d1cf103ac99a8df Mon Sep 17 00:00:00 2001 From: Yi-Te Huang Date: Wed, 22 May 2024 13:17:32 +0800 Subject: [PATCH 2/6] fix typo --- .github/workflows/FormatCheck.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/FormatCheck.yml b/.github/workflows/FormatCheck.yml index a691e4b3..b109bbcd 100644 --- a/.github/workflows/FormatCheck.yml +++ b/.github/workflows/FormatCheck.yml @@ -37,6 +37,6 @@ jobs: else @error "The following files have not been formatted !!!" write(stdout, output) - write(stdout, "Please format it by running: \'using JuliaFormatter; format(\".\")\'") + write(stdout, "-----\nPlease format it by running: using JuliaFormatter; format(\".\")") exit(1) end' \ No newline at end of file From 8767346881a6dd67c3254e8303253f1e8a8726df Mon Sep 17 00:00:00 2001 From: Yi-Te Huang Date: Wed, 22 May 2024 14:40:26 +0800 Subject: [PATCH 3/6] modify output message --- .github/workflows/FormatCheck.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/FormatCheck.yml b/.github/workflows/FormatCheck.yml index b109bbcd..969d6285 100644 --- a/.github/workflows/FormatCheck.yml +++ b/.github/workflows/FormatCheck.yml @@ -25,8 +25,8 @@ jobs: version: '1' - name: Install and Run JuliaFormatter run: | - julia -e 'import Pkg; Pkg.add("JuliaFormatter")' - julia -e 'using JuliaFormatter; format(".", verbose=true)' + julia -e 'import Pkg; Pkg.add("JuliaFormatter")' + julia -e 'using JuliaFormatter; format(".", verbose=true)' - name: Format Check run: | @@ -37,6 +37,8 @@ jobs: else @error "The following files have not been formatted !!!" write(stdout, output) - write(stdout, "-----\nPlease format it by running: using JuliaFormatter; format(\".\")") + write(stdout, "-----") + write(stdout, "Please format them by running the following command:") + write(stdout, "julia -e \"using JuliaFormatter; format(\\\".\\\")\"") exit(1) end' \ No newline at end of file From d1621d6167904f14df5f19819079d805f5485379 Mon Sep 17 00:00:00 2001 From: Yi-Te Huang Date: Wed, 22 May 2024 14:43:00 +0800 Subject: [PATCH 4/6] add newlines in output messages --- .github/workflows/FormatCheck.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/FormatCheck.yml b/.github/workflows/FormatCheck.yml index 969d6285..503fdcc0 100644 --- a/.github/workflows/FormatCheck.yml +++ b/.github/workflows/FormatCheck.yml @@ -37,8 +37,8 @@ jobs: else @error "The following files have not been formatted !!!" write(stdout, output) - write(stdout, "-----") - write(stdout, "Please format them by running the following command:") + write(stdout, "-----\n") + write(stdout, "Please format them by running the following command:\n") write(stdout, "julia -e \"using JuliaFormatter; format(\\\".\\\")\"") exit(1) end' \ No newline at end of file From 64d7c26bad14e96fa8bd5151b1ab7a28584a83a5 Mon Sep 17 00:00:00 2001 From: Yi-Te Huang Date: Wed, 22 May 2024 16:44:18 +0800 Subject: [PATCH 5/6] format files --- README.md | 14 +- docs/src/api.md | 6 +- docs/src/benchmarks/benchmark_history.md | 2 +- docs/src/tutorials/logo.md | 38 +++-- docs/src/tutorials/lowrank.md | 142 ++++++++++-------- ext/QuantumToolboxCUDAExt.jl | 2 +- src/arnoldi.jl | 2 +- src/general_functions.jl | 2 +- src/negativity.jl | 2 +- src/permutation.jl | 2 +- src/progress_bar.jl | 2 +- src/quantum_object.jl | 2 +- src/quantum_operators.jl | 2 +- src/steadystate.jl | 2 +- src/time_evolution/mcsolve.jl | 2 +- src/time_evolution/mesolve.jl | 2 +- src/time_evolution/sesolve.jl | 2 +- src/time_evolution/time_evolution.jl | 9 +- .../time_evolution_dynamical.jl | 2 +- src/versioninfo.jl | 2 +- src/wigner.jl | 2 +- test/aqua.jl | 2 +- test/correlations_and_spectrum.jl | 2 +- test/dynamical-shifted-fock.jl | 2 +- test/dynamical_fock_dimension_mesolve.jl | 2 +- test/eigenvalues_and_operators.jl | 2 +- test/entanglement.jl | 2 +- test/generalized_master_equation.jl | 2 +- test/jet.jl | 2 +- test/low_rank_dynamics.jl | 2 +- test/negativity_and_partial_transpose.jl | 2 +- test/permutation.jl | 2 +- test/progress_bar.jl | 2 +- test/quantum_objects.jl | 2 +- test/runtests.jl | 2 +- test/steady_state.jl | 2 +- test/time_evolution_and_partial_trace.jl | 2 +- test/wigner.jl | 2 +- 38 files changed, 141 insertions(+), 134 deletions(-) diff --git a/README.md b/README.md index 0156ba36..52eb9eb1 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,10 @@
QuantumToolbox.jl logo
- # QuantumToolbox.jl - [![Release](https://img.shields.io/github/release/albertomercurio/QuantumToolbox.jl.svg)](https://github.com/albertomercurio/QuantumToolbox.jl/releases) [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.11096277.svg)](https://doi.org/10.5281/zenodo.11096277) [![Downloads](https://img.shields.io/badge/dynamic/json?url=http%3A%2F%2Fjuliapkgstats.com%2Fapi%2Fv1%2Fmonthly_downloads%2FQuantumToolbox&query=total_requests&suffix=%2Fmonth&label=Downloads)](https://juliapkgstats.com/pkg/QuantumToolbox) - [![Build Status](https://github.com/albertomercurio/QuantumToolbox.jl/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/albertomercurio/QuantumToolbox.jl/actions/workflows/CI.yml?query=branch%3Amain) [![Aqua QA](https://raw.githubusercontent.com/JuliaTesting/Aqua.jl/master/badge.svg)](https://github.com/JuliaTesting/Aqua.jl) [![Coverage](https://codecov.io/gh/albertomercurio/QuantumToolbox.jl/branch/main/graph/badge.svg)](https://codecov.io/gh/albertomercurio/QuantumToolbox.jl) @@ -16,17 +13,20 @@ [![Doc-Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://albertomercurio.github.io/QuantumToolbox.jl/dev) ## Introduction + [QuantumToolbox.jl](https://github.com/albertomercurio/QuantumToolbox.jl) is a cutting-edge Julia package designed for quantum physics simulations, closely emulating the popular Python [QuTiP](https://github.com/qutip/qutip) package. It uniquely combines the simplicity and power of Julia with advanced features like GPU acceleration and distributed computing, making simulation of quantum systems more accessible and efficient. ## Features + QuantumToolbox.jl is equipped with a robust set of features: -- **Quantum State and Operator Manipulation:** Easily handle quantum states and operators with a rich set of tools. -- **Dynamical Evolution:** Advanced solvers for time evolution of quantum systems. -- **Measurement and Statistics:** Comprehensive quantum measurement simulation and analysis. -- **GPU and Distributed Computing:** Leverage GPU and distributed resources for high-performance computing. + - **Quantum State and Operator Manipulation:** Easily handle quantum states and operators with a rich set of tools. + - **Dynamical Evolution:** Advanced solvers for time evolution of quantum systems. + - **Measurement and Statistics:** Comprehensive quantum measurement simulation and analysis. + - **GPU and Distributed Computing:** Leverage GPU and distributed resources for high-performance computing. ## Installation + ```julia using Pkg Pkg.add("QuantumToolbox") diff --git a/docs/src/api.md b/docs/src/api.md index 55296931..317acd82 100644 --- a/docs/src/api.md +++ b/docs/src/api.md @@ -110,6 +110,7 @@ steadystate_floquet ``` ## [Correlations and Spectrum](@id API: Correlations and Spectrum) + ```@docs correlation_3op_2t correlation_2op_2t @@ -118,6 +119,7 @@ spectrum ``` ## [Eigenvalues and eigenvectors](@id API: Eigenvalues and eigenvectors) + ```@docs EigsolveResult eigenenergies @@ -129,6 +131,7 @@ eigsolve_al ``` ## [Low Rank internal APIs](@id API: Low Rank internal APIs) + ```@docs _calculate_expectation! _adjM_condition_variational @@ -139,7 +142,8 @@ dBdz! ``` ## [Miscellaneous](@id API: Miscellaneous) + ```@docs QuantumToolbox.versioninfo QuantumToolbox.about -``` \ No newline at end of file +``` diff --git a/docs/src/benchmarks/benchmark_history.md b/docs/src/benchmarks/benchmark_history.md index 78def6b3..18f38be9 100644 --- a/docs/src/benchmarks/benchmark_history.md +++ b/docs/src/benchmarks/benchmark_history.md @@ -15,4 +15,4 @@ window.addEventListener('message', adjustIframeHeight, false); -``` \ No newline at end of file +``` diff --git a/docs/src/tutorials/logo.md b/docs/src/tutorials/logo.md index 5ecb11e8..d397ca49 100644 --- a/docs/src/tutorials/logo.md +++ b/docs/src/tutorials/logo.md @@ -14,23 +14,23 @@ A cat state, often referred to as a Schrödinger cat state, is a quantum state t where ``| \alpha \rangle`` is a coherent state with amplitude ``\alpha``. -The triangular cat state is a generalization of the standard cat state. It is a superposition of three coherent states with phases ``\theta_0, \theta_1, \theta_2 ``separated by ``120^\circ ``(or ``2\pi/3 ``radians): +The triangular cat state is a generalization of the standard cat state. It is a superposition of three coherent states with phases ``\theta_0, \theta_1, \theta_2``separated by ``120^\circ``(or ``2\pi/3``radians): ```math | \psi_{\text{tri-cat}} \rangle = \frac{1}{\sqrt{3}} \left( | \alpha_0 \rangle + | \alpha_1 \rangle + | \alpha_2 \rangle \right) ``` -where ``\alpha_j = \rho e^{i\theta_j} ``with ``\theta_j = \frac{\pi}{2} + \frac{2\pi j}{3} ``and ``j = 0, 1, 2 ``. +where ``\alpha_j = \rho e^{i\theta_j}``with ``\theta_j = \frac{\pi}{2} + \frac{2\pi j}{3}``and ``j = 0, 1, 2``. ### Wigner Function -The Wigner function ``W(x, p) ``is a quasi-probability distribution used in quantum mechanics to represent quantum states in phase space. It is defined as: +The Wigner function ``W(x, p)``is a quasi-probability distribution used in quantum mechanics to represent quantum states in phase space. It is defined as: ```math W(x, p) = \frac{1}{\pi \hbar} \int_{-\infty}^{\infty} \psi^*(x + y) \psi(x - y) e^{2ipy / \hbar} \, dy ``` -where ``\psi(x) ``is the wave function of the quantum state, ``x ``is the position, ``p ``is the momentum, and ``\hbar ``is the reduced Planck constant. Unlike classical probability distributions, the Wigner function can take negative values, which indicates non-classical behavior. +where ``\psi(x)``is the wave function of the quantum state, ``x``is the position, ``p``is the momentum, and ``\hbar``is the reduced Planck constant. Unlike classical probability distributions, the Wigner function can take negative values, which indicates non-classical behavior. ## Generating the Logo @@ -50,9 +50,9 @@ Here we define the parameters for the triangular cat state: ```@example logo N = 30 # Cutoff of the Hilbert space for the harmonic oscillator ρ = 2.5 # Amplitude of the coherent state -θ1 = π/2 -θ2 = π/2 + 2π/3 -θ3 = π/2 + 4π/3 +θ1 = π / 2 +θ2 = π / 2 + 2π / 3 +θ3 = π / 2 + 4π / 3 α1 = ρ * exp(im * θ1) α2 = ρ * exp(im * θ2) α3 = ρ * exp(im * θ3) @@ -75,7 +75,7 @@ We define the grid for the Wigner function and calculate it using the [`wigner`] xvec = range(-ρ, ρ, 500) .* 1.5 yvec = xvec .+ (abs(imag(α1)) - abs(imag(α2))) / 2 -wig = wigner(ψ, xvec, yvec, g=2) +wig = wigner(ψ, xvec, yvec, g = 2) ``` ### Plotting the Wigner function @@ -100,7 +100,7 @@ The figure obtained above coulb be already a potential logo for the package. How \frac{d \hat{\rho}}{dt} = -i [\hat{H}, \hat{\rho}] + \gamma \left( 2 \hat{a} \hat{\rho} \hat{a}^\dagger - \hat{a}^\dagger \hat{a} \hat{\rho} - \hat{\rho} \hat{a}^\dagger \hat{a} \right) ``` -where ``\hat{\rho}`` is the density matrix, ``\hat{H} = \omega \hat{a}^\dagger \hat{a} ``is the Hamiltonian of the harmonic oscillator (``\hbar = 1``), ``\hat{a} ``and ``\hat{a}^\dagger ``are the annihilation and creation operators, and ``\gamma ``is the damping rate. Thus, we initialize the system in the triangular cat state and evolve it under the Lindblad master equation, using the [`mesolve`](@ref) function. +where ``\hat{\rho}`` is the density matrix, ``\hat{H} = \omega \hat{a}^\dagger \hat{a}``is the Hamiltonian of the harmonic oscillator (``\hbar = 1``), ``\hat{a}``and ``\hat{a}^\dagger``are the annihilation and creation operators, and ``\gamma``is the damping rate. Thus, we initialize the system in the triangular cat state and evolve it under the Lindblad master equation, using the [`mesolve`](@ref) function. ```@example logo γ = 0.012 @@ -111,19 +111,19 @@ c_ops = [sqrt(γ) * a] tlist = range(0, 2π, 100) -sol = mesolve(H, ψ, tlist, c_ops, progress_bar=false) +sol = mesolve(H, ψ, tlist, c_ops, progress_bar = false) nothing # hide ``` And the Wigner function becomes more uniform: ```@example logo -wig = wigner(sol.states[end], xvec, yvec, g=2) +wig = wigner(sol.states[end], xvec, yvec, g = 2) -fig = Figure(size=(500, 500), figure_padding=0) +fig = Figure(size = (500, 500), figure_padding = 0) ax = Axis(fig[1, 1]) -img_wig = heatmap!(ax, xvec, yvec, wig', colormap=:RdBu, interpolate=true, rasterize=2) +img_wig = heatmap!(ax, xvec, yvec, wig', colormap = :RdBu, interpolate = true, rasterize = 2) hidespines!(ax) hidexdecorations!(ax) hideydecorations!(ax) @@ -138,8 +138,7 @@ At this stage, we have finished to use the `QuantumToolbox` package. From now on We define a custom colormap that changes depending on the Wigner function and spatial coordinates. Indeed, we want the three different colormaps, in the regions corresponding to the three coherent states, to match the colors of the Julia logo. We also want the colormap change to be smooth, so we use a Gaussian function to blend the colors. We introduce also a Wigner function dependent transparency to make the logo more appealing. ```@example logo -function set_color_julia(x, y, wig::T, α1, α2, α3, cmap1, cmap2, cmap3, δ) where T - +function set_color_julia(x, y, wig::T, α1, α2, α3, cmap1, cmap2, cmap3, δ) where {T} amp1 = gaussian(x, real(α1), δ) * gaussian(y, imag(α1), δ) amp2 = gaussian(x, real(α2), δ) * gaussian(y, imag(α2), δ) amp3 = gaussian(x, real(α3), δ) * gaussian(y, imag(α3), δ) @@ -149,13 +148,12 @@ function set_color_julia(x, y, wig::T, α1, α2, α3, cmap1, cmap2, cmap3, δ) w c3 = get(cmap3, wig) c_tot = (amp1 * c1 + amp2 * c2 + amp3 * c3) / (amp1 + amp2 + amp3) - - wig_abs = abs( 2 * (wig - 1/2) ) + + wig_abs = abs(2 * (wig - 1 / 2)) # We introduce some non-linearity to increase the contrast - alpha = 2 * ( 1 / (1 + exp(-5 * wig_abs)) - 1/2 ) + alpha = 2 * (1 / (1 + exp(-5 * wig_abs)) - 1 / 2) return RGBAf(c_tot.r, c_tot.g, c_tot.b, alpha) - end X, Y = meshgrid(xvec, yvec) @@ -210,4 +208,4 @@ fig ## Conclusion -This tutorial demonstrates how to generate the [QuantumToolbox.jl](https://github.com/albertomercurio/QuantumToolbox.jl) logo using the package itself and [Makie.jl](https://github.com/MakieOrg/Makie.jl) for visualization. The logo is a visualization of the Wigner function of a triangular cat state, with a custom colormap that highlights the different coherent states with colors matching the Julia logo. \ No newline at end of file +This tutorial demonstrates how to generate the [QuantumToolbox.jl](https://github.com/albertomercurio/QuantumToolbox.jl) logo using the package itself and [Makie.jl](https://github.com/MakieOrg/Makie.jl) for visualization. The logo is a visualization of the Wigner function of a triangular cat state, with a custom colormap that highlights the different coherent states with colors matching the Julia logo. diff --git a/docs/src/tutorials/lowrank.md b/docs/src/tutorials/lowrank.md index 1148418a..6ecd3205 100644 --- a/docs/src/tutorials/lowrank.md +++ b/docs/src/tutorials/lowrank.md @@ -9,104 +9,112 @@ CairoMakie.enable_only_mime!(MIME"image/svg+xml"()) ``` Define lattice + ```@example lowrank Nx, Ny = 2, 3 -latt = Lattice(Nx=Nx, Ny=Ny) +latt = Lattice(Nx = Nx, Ny = Ny) ``` Define lr-space dimensions + ```@example lowrank N_cut = 2 # Number of states of each mode N_modes = latt.N # Number of modes N = N_cut^N_modes # Total number of states -M = Nx*Ny+1 # Number of states in the LR basis +M = Nx * Ny + 1 # Number of states in the LR basis ``` Define lr states. Take as initial state all spins up. All other N states are taken as those with miniman Hamming distance to the initial state. + ```@example lowrank -ϕ = Vector{QuantumObject{Vector{ComplexF64}, KetQuantumObject}}(undef, M) -ϕ[1] = kron(repeat([basis(2,0)],N_modes)...) +ϕ = Vector{QuantumObject{Vector{ComplexF64},KetQuantumObject}}(undef, M) +ϕ[1] = kron(repeat([basis(2, 0)], N_modes)...) -global i=1 +global i = 1 for j in 1:N_modes - global i+=1 - i<=M && (ϕ[i] = mb(sp, j, latt) * ϕ[1]) + global i += 1 + i <= M && (ϕ[i] = mb(sp, j, latt) * ϕ[1]) end for k in 1:N_modes-1 - for l=k+1:N_modes - global i+=1 - i<=M && (ϕ[i] = mb(sp, k, latt) * mb(sp, l, latt) * ϕ[1]) + for l in k+1:N_modes + global i += 1 + i <= M && (ϕ[i] = mb(sp, k, latt) * mb(sp, l, latt) * ϕ[1]) end end for i in i+1:M - ϕ[i] = QuantumObject(rand(ComplexF64,size(ϕ[1])[1]), dims=ϕ[1].dims) + ϕ[i] = QuantumObject(rand(ComplexF64, size(ϕ[1])[1]), dims = ϕ[1].dims) normalize!(ϕ[i]) end ``` Define the initial state + ```@example lowrank -z = hcat(broadcast(x->x.data, ϕ)...) -p0 = 0. # Population of the lr states other than the initial state -B = Matrix(Diagonal([1+0im; p0 * ones(M-1)])) -S = z'*z # Overlap matrix -B = B / tr(S*B) # Normalize B +z = hcat(broadcast(x -> x.data, ϕ)...) +p0 = 0.0 # Population of the lr states other than the initial state +B = Matrix(Diagonal([1 + 0im; p0 * ones(M - 1)])) +S = z' * z # Overlap matrix +B = B / tr(S * B) # Normalize B -ρ = QuantumObject(z*B*z', dims=ones(Int,N_modes)*N_cut); # Full density matrix +ρ = QuantumObject(z * B * z', dims = ones(Int, N_modes) * N_cut); # Full density matrix ``` Define the Hamiltonian and collapse operators + ```@example lowrank # Define Hamiltonian and collapse operators -Jx = 0.9 +Jx = 0.9 Jy = 1.04 -Jz = 1. -hx = 0. -γ = 1 +Jz = 1.0 +hx = 0.0 +γ = 1 Sx = sum([mb(sx, i, latt) for i in 1:latt.N]) Sy = sum([mb(sy, i, latt) for i in 1:latt.N]) Sz = sum([mb(sz, i, latt) for i in 1:latt.N]) SFxx = sum([mb(sx, i, latt) * mb(sx, j, latt) for i in 1:latt.N for j in 1:latt.N]) -H, c_ops = TFIM(Jx, Jy, Jz, hx, γ, latt; bc=pbc, order=1) -e_ops = (Sx,Sy,Sz,SFxx) +H, c_ops = TFIM(Jx, Jy, Jz, hx, γ, latt; bc = pbc, order = 1) +e_ops = (Sx, Sy, Sz, SFxx) -tl = LinRange(0,10,100); +tl = LinRange(0, 10, 100); ``` ### Full evolution + ```@example lowrank -@time mesol = mesolve(H, ρ, tl, c_ops; e_ops=[e_ops...]); +@time mesol = mesolve(H, ρ, tl, c_ops; e_ops = [e_ops...]); A = Matrix(mesol.states[end].data) λ = eigvals(Hermitian(A)) -Strue = -sum(λ.*log2.(λ))/latt.N; +Strue = -sum(λ .* log2.(λ)) / latt.N; ``` ### Low Rank evolution + Define functions to be evaluated during the low-rank evolution + ```@example lowrank -function f_purity(p,z,B) - N = p.N - M = p.M - S = p.S - T = p.temp_MM +function f_purity(p, z, B) + N = p.N + M = p.M + S = p.S + T = p.temp_MM mul!(T, S, B) - tr(T^2) + return tr(T^2) end -function f_trace(p,z,B) - N = p.N - M = p.M - S = p.S - T = p.temp_MM +function f_trace(p, z, B) + N = p.N + M = p.M + S = p.S + T = p.temp_MM - mul!(T,S,B) - tr(T) + mul!(T, S, B) + return tr(T) end -function f_entropy(p,z,B) +function f_entropy(p, z, B) C = p.A0 σ = p.Bi @@ -119,36 +127,40 @@ end; ``` Define the options for the low-rank evolution + ```@example lowrank -opt = LRMesolveOptions( - alg = Tsit5(), - err_max = 1e-3, - p0 = 0., - atol_inv = 1e-6, - adj_condition="variational", - Δt = 0. -); - -@time lrsol = lr_mesolve(H, z, B, tl, c_ops; e_ops=e_ops, f_ops=(f_purity, f_entropy, f_trace,), opt=opt); +opt = + LRMesolveOptions(alg = Tsit5(), err_max = 1e-3, p0 = 0.0, atol_inv = 1e-6, adj_condition = "variational", Δt = 0.0); + +@time lrsol = lr_mesolve(H, z, B, tl, c_ops; e_ops = e_ops, f_ops = (f_purity, f_entropy, f_trace), opt = opt); ``` Plot the results + ```@example lowrank -m_me = real(mesol.expect[3,:])/Nx/Ny -m_lr = real(lrsol.expvals[3,:])/Nx/Ny - -fig = Figure(size=(800, 400), fontsize=15) -ax = Axis(fig[1, 1], xlabel=L"\gamma t", ylabel=L"M_{z}", xlabelsize=20, ylabelsize=20) -lines!(ax, tl, m_lr, label=L"LR $[M=M(t)]$", linewidth=2) -lines!(ax, tl, m_me, label="Fock", linewidth=2, linestyle=:dash) -axislegend(ax, position=:rb) - -ax2 = Axis(fig[1, 2], xlabel=L"\gamma t", ylabel="Value", xlabelsize=20, ylabelsize=20) -lines!(ax2, tl, 1 .-real(lrsol.funvals[1,:]), label=L"$1-P$", linewidth=2) -lines!(ax2, tl, 1 .-real(lrsol.funvals[3,:]), label=L"$1-\mathrm{Tr}(\rho)$", linewidth=2, linestyle=:dash, color=:orange) -lines!(ax2, tl, real(lrsol.funvals[2,:])/Nx/Ny, color=:blue, label=L"S", linewidth=2) -hlines!(ax2, [Strue], color=:blue, linestyle=:dash, linewidth=2, label=L"S^{\,\mathrm{true}}_{\mathrm{ss}}") -axislegend(ax2, position=:rb) +m_me = real(mesol.expect[3, :]) / Nx / Ny +m_lr = real(lrsol.expvals[3, :]) / Nx / Ny + +fig = Figure(size = (800, 400), fontsize = 15) +ax = Axis(fig[1, 1], xlabel = L"\gamma t", ylabel = L"M_{z}", xlabelsize = 20, ylabelsize = 20) +lines!(ax, tl, m_lr, label = L"LR $[M=M(t)]$", linewidth = 2) +lines!(ax, tl, m_me, label = "Fock", linewidth = 2, linestyle = :dash) +axislegend(ax, position = :rb) + +ax2 = Axis(fig[1, 2], xlabel = L"\gamma t", ylabel = "Value", xlabelsize = 20, ylabelsize = 20) +lines!(ax2, tl, 1 .- real(lrsol.funvals[1, :]), label = L"$1-P$", linewidth = 2) +lines!( + ax2, + tl, + 1 .- real(lrsol.funvals[3, :]), + label = L"$1-\mathrm{Tr}(\rho)$", + linewidth = 2, + linestyle = :dash, + color = :orange, +) +lines!(ax2, tl, real(lrsol.funvals[2, :]) / Nx / Ny, color = :blue, label = L"S", linewidth = 2) +hlines!(ax2, [Strue], color = :blue, linestyle = :dash, linewidth = 2, label = L"S^{\,\mathrm{true}}_{\mathrm{ss}}") +axislegend(ax2, position = :rb) fig ``` diff --git a/ext/QuantumToolboxCUDAExt.jl b/ext/QuantumToolboxCUDAExt.jl index 4e104c0a..a9ebd616 100644 --- a/ext/QuantumToolboxCUDAExt.jl +++ b/ext/QuantumToolboxCUDAExt.jl @@ -89,4 +89,4 @@ _change_eltype(::Type{T}, ::Val{32}) where {T<:AbstractFloat} = Float32 _change_eltype(::Type{Complex{T}}, ::Val{64}) where {T<:Union{Int,AbstractFloat}} = ComplexF64 _change_eltype(::Type{Complex{T}}, ::Val{32}) where {T<:Union{Int,AbstractFloat}} = ComplexF32 -end \ No newline at end of file +end diff --git a/src/arnoldi.jl b/src/arnoldi.jl index 354818f8..11f4199f 100644 --- a/src/arnoldi.jl +++ b/src/arnoldi.jl @@ -122,4 +122,4 @@ function expv( ) where {T1<:BlasFloat,T2<:BlasFloat} x = similar(b) return expv!(x, A, t, b, m = m) -end \ No newline at end of file +end diff --git a/src/general_functions.jl b/src/general_functions.jl index 3d15f484..61ac28d7 100644 --- a/src/general_functions.jl +++ b/src/general_functions.jl @@ -441,4 +441,4 @@ end Convert a quantum object from matrix ([`OperatorQuantumObject`](@ref)-type) to vector ([`OperatorKetQuantumObject`](@ref)-type) """ mat2vec(A::QuantumObject{<:AbstractArray{T},OperatorQuantumObject}) where {T} = - QuantumObject(mat2vec(A.data), OperatorKet, A.dims) \ No newline at end of file + QuantumObject(mat2vec(A.data), OperatorKet, A.dims) diff --git a/src/negativity.jl b/src/negativity.jl index 69d75a96..455d01cc 100644 --- a/src/negativity.jl +++ b/src/negativity.jl @@ -131,4 +131,4 @@ function _partial_transpose(ρ::QuantumObject{<:AbstractSparseArray,OperatorQuan end return QuantumObject(sparse(I_pt, J_pt, V_pt, M, N), Operator, ρ.dims) -end \ No newline at end of file +end diff --git a/src/permutation.jl b/src/permutation.jl index 86d62b28..32715790 100644 --- a/src/permutation.jl +++ b/src/permutation.jl @@ -35,4 +35,4 @@ function get_bdf_blocks( block_sizes::Vector{Int}, ) where {T,M,OpType<:Union{OperatorQuantumObject,SuperOperatorQuantumObject}} return get_bdf_blocks(A.data, block_sizes) -end \ No newline at end of file +end diff --git a/src/progress_bar.jl b/src/progress_bar.jl index 616dc8bb..5d723612 100644 --- a/src/progress_bar.jl +++ b/src/progress_bar.jl @@ -53,4 +53,4 @@ function next!(p::ProgressBar, io::IO = stdout) counter == p.max_counts && print(io, "\n") return flush(io) -end \ No newline at end of file +end diff --git a/src/quantum_object.jl b/src/quantum_object.jl index c5496f5b..4a4c7769 100644 --- a/src/quantum_object.jl +++ b/src/quantum_object.jl @@ -814,4 +814,4 @@ SparseArrays.SparseVector{T}(A::QuantumObject{<:SparseVector}) where {T<:Number} SparseArrays.SparseMatrixCSC(A::QuantumObject{<:AbstractMatrix}) = QuantumObject(SparseMatrixCSC(A.data), A.type, A.dims) SparseArrays.SparseMatrixCSC{T}(A::QuantumObject{<:SparseMatrixCSC}) where {T<:Number} = - QuantumObject(SparseMatrixCSC{T}(A.data), A.type, A.dims) \ No newline at end of file + QuantumObject(SparseMatrixCSC{T}(A.data), A.type, A.dims) diff --git a/src/quantum_operators.jl b/src/quantum_operators.jl index cf539262..60c748cf 100644 --- a/src/quantum_operators.jl +++ b/src/quantum_operators.jl @@ -248,4 +248,4 @@ Generates the cosine of the operator `O`, defined as ``\cos \left( \hat{O} \right) = \frac{e^{i \hat{O}} + e^{-i \hat{O}}}{2}`` """ -cosm(O::QuantumObject{<:AbstractArray{T},OperatorQuantumObject}) where {T} = 0.5 * (exp(1im * O) + exp(-1im * O)) \ No newline at end of file +cosm(O::QuantumObject{<:AbstractArray{T},OperatorQuantumObject}) where {T} = 0.5 * (exp(1im * O) + exp(-1im * O)) diff --git a/src/steadystate.jl b/src/steadystate.jl index 3587ad7f..5ae6400a 100644 --- a/src/steadystate.jl +++ b/src/steadystate.jl @@ -101,4 +101,4 @@ function steadystate_floquet( L_m = liouvillian(H_m) return steadystate(liouvillian_floquet(L_0, L_p, L_m, ω, n_max = n_max, tol = tol), solver = ss_solver) -end \ No newline at end of file +end diff --git a/src/time_evolution/mcsolve.jl b/src/time_evolution/mcsolve.jl index d06049f1..fbaa7355 100644 --- a/src/time_evolution/mcsolve.jl +++ b/src/time_evolution/mcsolve.jl @@ -406,4 +406,4 @@ function mcsolve( expvals = dropdims(sum(expvals_all, dims = 1), dims = 1) ./ length(sol) return TimeEvolutionMCSol(times, states, expvals, expvals_all, jump_times, jump_which) -end \ No newline at end of file +end diff --git a/src/time_evolution/mesolve.jl b/src/time_evolution/mesolve.jl index cacd9fd5..9161a13c 100644 --- a/src/time_evolution/mesolve.jl +++ b/src/time_evolution/mesolve.jl @@ -212,4 +212,4 @@ function _mesolve_sol(sol; kwargs...) ρt = !haskey(kwargs, :save_idxs) ? map(ϕ -> QuantumObject(vec2mat(ϕ), dims = Hdims), sol.u) : sol.u return TimeEvolutionSol(sol.t, ρt, sol.prob.p.expvals) -end \ No newline at end of file +end diff --git a/src/time_evolution/sesolve.jl b/src/time_evolution/sesolve.jl index f5abcc2d..67718dbb 100644 --- a/src/time_evolution/sesolve.jl +++ b/src/time_evolution/sesolve.jl @@ -187,4 +187,4 @@ function _sesolve_sol(sol; kwargs...) ψt = !haskey(kwargs, :save_idxs) ? map(ϕ -> QuantumObject(ϕ, dims = Hdims), sol.u) : sol.u return TimeEvolutionSol(sol.t, ψt, sol.prob.p.expvals) -end \ No newline at end of file +end diff --git a/src/time_evolution/time_evolution.jl b/src/time_evolution/time_evolution.jl index 3e745f79..4893dc62 100644 --- a/src/time_evolution/time_evolution.jl +++ b/src/time_evolution/time_evolution.jl @@ -179,14 +179,7 @@ function liouvillian_floquet( OpType2<:Union{OperatorQuantumObject,SuperOperatorQuantumObject}, OpType3<:Union{OperatorQuantumObject,SuperOperatorQuantumObject}, } - return liouvillian_floquet( - liouvillian(H, c_ops), - liouvillian(Hₚ), - liouvillian(Hₘ), - ω, - n_max = n_max, - tol = tol, - ) + return liouvillian_floquet(liouvillian(H, c_ops), liouvillian(Hₚ), liouvillian(Hₘ), ω, n_max = n_max, tol = tol) end @doc raw""" diff --git a/src/time_evolution/time_evolution_dynamical.jl b/src/time_evolution/time_evolution_dynamical.jl index da5683da..15d97613 100644 --- a/src/time_evolution/time_evolution_dynamical.jl +++ b/src/time_evolution/time_evolution_dynamical.jl @@ -717,4 +717,4 @@ function dsf_mcsolve( ) return mcsolve(ens_prob_mc; alg = alg, n_traj = n_traj, ensemble_method = ensemble_method, kwargs...) -end \ No newline at end of file +end diff --git a/src/versioninfo.jl b/src/versioninfo.jl index f878a086..3463d6aa 100644 --- a/src/versioninfo.jl +++ b/src/versioninfo.jl @@ -56,4 +56,4 @@ function _get_pkg_version(pkg_name::String) return D[uuid].version end end -end \ No newline at end of file +end diff --git a/src/wigner.jl b/src/wigner.jl index d2f0b7cb..466cbe37 100644 --- a/src/wigner.jl +++ b/src/wigner.jl @@ -192,4 +192,4 @@ function _wig_laguerre_clenshaw!(res, L::Int, x, c, y0, y1, y0_old) @. res = y0 - y1 * (L + 1 - x) / sqrt(L + 1) return res -end \ No newline at end of file +end diff --git a/test/aqua.jl b/test/aqua.jl index 4d0ba935..316d06a1 100644 --- a/test/aqua.jl +++ b/test/aqua.jl @@ -2,4 +2,4 @@ using Aqua @testset "Code quality (Aqua.jl)" begin Aqua.test_all(QuantumToolbox; ambiguities = false) -end \ No newline at end of file +end diff --git a/test/correlations_and_spectrum.jl b/test/correlations_and_spectrum.jl index 985eb155..6b4df001 100644 --- a/test/correlations_and_spectrum.jl +++ b/test/correlations_and_spectrum.jl @@ -15,4 +15,4 @@ idxs2 = test_func2 .> 0.05 @test sum(abs2.(spec1[idxs1] .- test_func1[idxs1])) / sum(abs2.(test_func1[idxs1])) < 0.01 @test sum(abs2.(spec2[idxs2] .- test_func2[idxs2])) / sum(abs2.(test_func2[idxs2])) < 0.01 -end \ No newline at end of file +end diff --git a/test/dynamical-shifted-fock.jl b/test/dynamical-shifted-fock.jl index b3668bd5..529b03a2 100644 --- a/test/dynamical-shifted-fock.jl +++ b/test/dynamical-shifted-fock.jl @@ -130,4 +130,4 @@ @test sum(abs2.(sol0.expect[1, :] .- sol_dsf_mc.expect[1, :])) / (val_ss * length(tlist)) < 0.6 @test sum(abs2.(sol0.expect[2, :] .- sol_dsf_me.expect[2, :])) / (val_ss * length(tlist)) < 0.6 @test sum(abs2.(sol0.expect[2, :] .- sol_dsf_mc.expect[2, :])) / (val_ss * length(tlist)) < 0.6 -end \ No newline at end of file +end diff --git a/test/dynamical_fock_dimension_mesolve.jl b/test/dynamical_fock_dimension_mesolve.jl index e124b670..22d00d0a 100644 --- a/test/dynamical_fock_dimension_mesolve.jl +++ b/test/dynamical_fock_dimension_mesolve.jl @@ -103,4 +103,4 @@ @test sum(abs.((sol.expect[1, :] .- sol0.expect[1, :]) ./ (sol0.expect[1, :] .+ 1e-16))) + sum(abs.((sol.expect[2, :] .- sol0.expect[2, :]) ./ (sol0.expect[2, :] .+ 1e-16))) < 0.01 -end \ No newline at end of file +end diff --git a/test/eigenvalues_and_operators.jl b/test/eigenvalues_and_operators.jl index 4e7dd554..6f281208 100644 --- a/test/eigenvalues_and_operators.jl +++ b/test/eigenvalues_and_operators.jl @@ -91,4 +91,4 @@ @test isapprox(abs2(vals2[1]), abs2(vals3[1]), atol = 1e-7) @test isapprox(vec2mat(vecs[1]).data * exp(-1im * angle(vecs[1][1])), vec2mat(vecs2[1]).data, atol = 1e-7) @test isapprox(vec2mat(vecs[1]).data * exp(-1im * angle(vecs[1][1])), vec2mat(state3[1]).data, atol = 1e-5) -end \ No newline at end of file +end diff --git a/test/entanglement.jl b/test/entanglement.jl index 3d0e7c7a..860e168c 100644 --- a/test/entanglement.jl +++ b/test/entanglement.jl @@ -5,4 +5,4 @@ rho = state * state' @test entanglement(state, 1) / log(2) ≈ 1 @test entanglement(rho, 1) / log(2) ≈ 1 -end \ No newline at end of file +end diff --git a/test/generalized_master_equation.jl b/test/generalized_master_equation.jl index a87d016e..965206f9 100644 --- a/test/generalized_master_equation.jl +++ b/test/generalized_master_equation.jl @@ -41,4 +41,4 @@ sm2 = Qobj(dense_to_sparse((U'*sm*U).data[1:N_trunc, 1:N_trunc], tol)) @test abs(expect(Xp' * Xp, steadystate(L1)) - n_th(1, Tlist[1])) / n_th(1, Tlist[1]) < 1e-4 -end \ No newline at end of file +end diff --git a/test/jet.jl b/test/jet.jl index 5025f30b..a7a348d1 100644 --- a/test/jet.jl +++ b/test/jet.jl @@ -2,4 +2,4 @@ using JET @testset "Code quality (JET.jl)" begin JET.test_package(QuantumToolbox; target_defined_modules = true, ignore_missing_comparison = true) -end \ No newline at end of file +end diff --git a/test/low_rank_dynamics.jl b/test/low_rank_dynamics.jl index 7a66bd7f..40ead0b3 100644 --- a/test/low_rank_dynamics.jl +++ b/test/low_rank_dynamics.jl @@ -78,4 +78,4 @@ S_lr = real(lrsol.funvals[1, end]) @test abs((S_lr - Strue) / Strue) < 0.5 -end \ No newline at end of file +end diff --git a/test/negativity_and_partial_transpose.jl b/test/negativity_and_partial_transpose.jl index e347f171..0151438c 100644 --- a/test/negativity_and_partial_transpose.jl +++ b/test/negativity_and_partial_transpose.jl @@ -29,4 +29,4 @@ end end @test_throws ErrorException partial_transpose(rho, [true]) -end \ No newline at end of file +end diff --git a/test/permutation.jl b/test/permutation.jl index 92e3859d..3b28d9bf 100644 --- a/test/permutation.jl +++ b/test/permutation.jl @@ -24,4 +24,4 @@ @test length(blocks_list) == 4 @test length(block_indices) == 4 @test sum(block_sizes .== 100) == 4 -end \ No newline at end of file +end diff --git a/test/progress_bar.jl b/test/progress_bar.jl index 8a1f84cb..05eafc82 100644 --- a/test/progress_bar.jl +++ b/test/progress_bar.jl @@ -11,4 +11,4 @@ @test length(output) == strLength + 1 end end -end \ No newline at end of file +end diff --git a/test/quantum_objects.jl b/test/quantum_objects.jl index 9d888569..f7097feb 100644 --- a/test/quantum_objects.jl +++ b/test/quantum_objects.jl @@ -281,4 +281,4 @@ @test typeof(SparseMatrixCSC(Md).data) == SparseMatrixCSC{Int64,Int64} @test typeof(SparseMatrixCSC(Ms).data) == SparseMatrixCSC{Int64,Int64} @test typeof(SparseMatrixCSC{ComplexF64}(Ms).data) == SparseMatrixCSC{ComplexF64,Int64} -end \ No newline at end of file +end diff --git a/test/runtests.jl b/test/runtests.jl index 875cce0a..ad9708aa 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -41,4 +41,4 @@ end if (GROUP == "CUDA_Ext")# || (GROUP == "All") Pkg.add("CUDA") include(joinpath(testdir, "cuda_ext.jl")) -end \ No newline at end of file +end diff --git a/test/steady_state.jl b/test/steady_state.jl index 75b7d653..a8b4eabf 100644 --- a/test/steady_state.jl +++ b/test/steady_state.jl @@ -21,4 +21,4 @@ sol_me = mesolve(H, psi0, t_l, c_ops, e_ops = e_ops, H_t = H_t_f, alg = Vern7(), progress_bar = false) ρ_ss = steadystate_floquet(H, c_ops, -1im * 0.5 * H_t, 1im * 0.5 * H_t, 1) @test abs(sum(sol_me.expect[1, end-100:end]) / 101 - expect(e_ops[1], ρ_ss)) < 1e-2 -end \ No newline at end of file +end diff --git a/test/time_evolution_and_partial_trace.jl b/test/time_evolution_and_partial_trace.jl index 2944d32e..9b9d00b5 100644 --- a/test/time_evolution_and_partial_trace.jl +++ b/test/time_evolution_and_partial_trace.jl @@ -48,4 +48,4 @@ sol_mc = mcsolve(H, psi0, t_l, c_ops, n_traj = 500, e_ops = [sp1 * sm1, sp2 * sm2], progress_bar = false) @test sum(abs.(sol_mc.expect[1:2, :] .- sol_me.expect[1:2, :])) / length(t_l) < 0.1 @test expect(sp1 * sm1, sol_me.states[end]) ≈ expect(sigmap() * sigmam(), ptrace(sol_me.states[end], 1)) -end \ No newline at end of file +end diff --git a/test/wigner.jl b/test/wigner.jl index 47c8ee38..3a4d3ee2 100644 --- a/test/wigner.jl +++ b/test/wigner.jl @@ -20,4 +20,4 @@ wig2 = maximum(wig) * reshape(kron(wig_tmp1, wig_tmp2), 300, 300) @test sqrt(sum(abs.(wig2 .- wig)) / length(wig)) < 0.1 -end \ No newline at end of file +end From bddc96f89641da7c8875238467b7eccab23753be Mon Sep 17 00:00:00 2001 From: Yi-Te Huang Date: Wed, 22 May 2024 17:02:31 +0800 Subject: [PATCH 6/6] fix README and ignore by `JuliaFormatter` --- .JuliaFormatter.toml | 1 + README.md | 15 ++++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.JuliaFormatter.toml b/.JuliaFormatter.toml index 72a0d993..18efd325 100644 --- a/.JuliaFormatter.toml +++ b/.JuliaFormatter.toml @@ -6,3 +6,4 @@ always_use_return=true format_docstrings=true indent_submodule=true format_markdown=true +ignore = ["README.md"] \ No newline at end of file diff --git a/README.md b/README.md index 52eb9eb1..ac7ecfda 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,15 @@
QuantumToolbox.jl logo
+ # QuantumToolbox.jl + [![Release](https://img.shields.io/github/release/albertomercurio/QuantumToolbox.jl.svg)](https://github.com/albertomercurio/QuantumToolbox.jl/releases) [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.11096277.svg)](https://doi.org/10.5281/zenodo.11096277) -[![Downloads](https://img.shields.io/badge/dynamic/json?url=http%3A%2F%2Fjuliapkgstats.com%2Fapi%2Fv1%2Fmonthly_downloads%2FQuantumToolbox&query=total_requests&suffix=%2Fmonth&label=Downloads)](https://juliapkgstats.com/pkg/QuantumToolbox) +[![Downloads](https://img.shields.io/badge/dynamic/json?url=http%3A%2F%2Fjuliapkgstats.com%2Fapi%2Fv1%2Fmonthly_downloads%2FQuantumToolbox&query=total_requests&suffix=%2Fmonth&label=Downloads)](https://juliapkgstats.com/pkg/QuantumToolbox) [![Build Status](https://github.com/albertomercurio/QuantumToolbox.jl/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/albertomercurio/QuantumToolbox.jl/actions/workflows/CI.yml?query=branch%3Amain) [![Aqua QA](https://raw.githubusercontent.com/JuliaTesting/Aqua.jl/master/badge.svg)](https://github.com/JuliaTesting/Aqua.jl) -[![Coverage](https://codecov.io/gh/albertomercurio/QuantumToolbox.jl/branch/main/graph/badge.svg)](https://codecov.io/gh/albertomercurio/QuantumToolbox.jl) - +[![Coverage](https://codecov.io/gh/albertomercurio/QuantumToolbox.jl/branch/main/graph/badge.svg)](https://codecov.io/gh/albertomercurio/QuantumToolbox.jl) [![Doc-Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://albertomercurio.github.io/QuantumToolbox.jl/stable) [![Doc-Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://albertomercurio.github.io/QuantumToolbox.jl/dev) @@ -20,10 +21,10 @@ QuantumToolbox.jl is equipped with a robust set of features: - - **Quantum State and Operator Manipulation:** Easily handle quantum states and operators with a rich set of tools. - - **Dynamical Evolution:** Advanced solvers for time evolution of quantum systems. - - **Measurement and Statistics:** Comprehensive quantum measurement simulation and analysis. - - **GPU and Distributed Computing:** Leverage GPU and distributed resources for high-performance computing. +- **Quantum State and Operator Manipulation:** Easily handle quantum states and operators with a rich set of tools. +- **Dynamical Evolution:** Advanced solvers for time evolution of quantum systems. +- **Measurement and Statistics:** Comprehensive quantum measurement simulation and analysis. +- **GPU and Distributed Computing:** Leverage GPU and distributed resources for high-performance computing. ## Installation