Exported functions

Running trajectories

BackAction.run_trajectories_gillipsieMethod
run_trajectories_gillipsie(sys::System, params::SimulParameters; progbar::Bool = true,
                          psireset::VecOrMat{ComplexF64}=zeros(ComplexF64, 0))

Sample multiple trajectories of sys. with the seed, nsamples and psi0 specified in params using the Quantum Gillipsie Algorithm [2]. If the process is of renewal type,i.e. after a jump it always comes to the same state, that state can be specified via psireset and it will be used to optimize the sampling of the jump times.

Arguments

  • sys::System: The system for which to run the trajectoris
  • params::SimulParameters: specificies the details of the trajectiories: seed, number of points in the finegrid, initial state and tolerance for the dark state detection, and the number of trajectories to run.

Optional Arguments

  • progbar::Bool: if true, show a progress bar of the iteration, true by default.
  • psireset::VecOrMat{ComplexF64}: if specified, it is used to optimize the jump time sampling.

Return

A Vector{Trajectory} of length params.ntraj with the sampled trajectories.

source

State Evaluation

BackAction.states_atjumpsMethod
states_atjumps(traj::Trajectory, sys::System, psi0::Union{Vector{ComplexF64},
               Matrix{ComplexF64}}; normalize::Bool=true)

Obtain the states at jumps of the trajectory given the initial state psi0, they are (un)normalized if normalize is true(false). The return is an Array of dimensions (sys.NLEVELS, njumps) if the initial state was pure, and (sys.NLEVELS, sys.NLEVELS, njumps) if it was mixed; njumps is the number of jumps in the trajectory. You would access the state at the k-th jump with something like states_atjumps(traj, sys, psi0)[:, k].

In case isempty(traj)=true the returned array is also empty.

source
BackAction.states_attMethod
states_att(t_given::Vector{Float64}, traj::Trajectory, sys::System,
                       psi0::Union{Vector{ComplexF64}, Matrix{ComplexF64}};
                       normalize::Bool=true)

Provided the initial state psi0 obtain the states at the times in t_given on the trajectory, they are (un)normalized if normalize is true(false). The return is an Array of dimensions (sys.NLEVELS, ntimes) if the initial state was pure and (sys.NLEVELS, sys.NLEVELS, ntimes) if it was mixed; ntimes is the number of times in t_given. In case isempty(t_given)=true the returned array is also empty.

source

Internal functions

Utilities

BackAction.fixlastindexFunction
fixlastindex(array::Array{ComplexF64}, k::Int64)

Return a SubArray of array, defined by fixing the last index to k.

Example

using BackAction
arr = [[1+1.0im, 2] [3, 4]]
BackAction.fixlastindex(arr, 2)
# output
2-element view(::Matrix{ComplexF64}, :, 2) with eltype ComplexF64:
 3.0 + 0.0im
 4.0 + 0.0im
source

Precomputation

BackAction.setVs!Method

setVs!(sys::System, nsamples::Int64, ts::Vector{Float64}, Vs::Array{ComplexF64})`

Calculate the matrix exponentials $\mathrm{exp}(-iH_e t_s)$ for each $t_s$ in the vector ts, where $H_e$ is the effective hamiltonian of the system sys, and the results are written in Vs, which is an array of dimensions (sys.NLEVELS, sys.NLEVELS, nsamples). To access the exponential corresponding to ts[k] you would do Vs[:, ;, k].

source
BackAction.setQs!Method
setQs!(sys::System, nsamples::Int64,ts::Vector{Float64}, Qs::Array{ComplexF64}, Vs::Array{ComplexF64})

Calculate the matrix producs $VJV^\dagger$ for each $V$ in Vs, where $J=\sum_k L_{k}^\dagger L_k$ is sys.J, and the results are written in Qs which is an array of dimensions (sys.NLEVELS, sys.NLEVELS, nsamples). To access the product corresponding to ts[k] you would do Qs[:, ;, k].

source
BackAction.precompute!Method
precompute!(sys::System, nsamples::Int64, ts::Vector{Float64}, Qs::Array{ComplexF64}, Vs::Array{ComplexF64})

Precompute the $Q(t_s)$ and $V(t_s)$ necessary for running the Quantum Gillipsie Algorithm [2] with the time grid ts. The result is written in Qs and Vs. Under the hood, this simply calls setVs! and setQs!.

source

Click Sampling

BackAction.calculatewtdweights!Method
calculatewtdweights!(W::Array{Float64}, Qs::Array{ComplexF64}, psi::Vector{ComplexF64},
                                        params::SimulParameters)

Calculate the discretized Waiting Time Distribution for a pure state $|\psi\rangle$ i.e. $\langle\psi|Q(t_s)\psi\rangle$, and writes it at W. This is done using LinearAlgebra's dot, and usually is the thing in which run_singletrajectory spends most of the time since params.nsamples is typically in the thousands.

source
BackAction.calculatewtdweights!Method
calculatewtdweights!(W::Array{Float64}, Qs::Array{ComplexF64}, psi::Matrix{ComplexF64},
                                         params::SimulParameters)

Calculate the discretized Waiting Time Distribution for a mixed state $\psi$ i.e. $\mathrm{Tr}(Q(t_s)\psi)$, and writes it at W. This is done using LinearAlgebra's tr, and usually is the thing in which run_singletrajectory spends most of the time since params.nsamples is typically in the thousands.

source
BackAction.calculatechannelweights!Method
calculatechannelweights!(P::Vector{Float64}, psi::Vector{ComplexF64}, sys::System)

Calculate the probabilities for a pure state $|\psi\rangle$ to jump to any of the given channels i.e. $\langle\psi| L^\dagger L|\psi\rangle$ for each jump operator $L$, and writes it at P. This is done using the square of LinearAlgebra's norm.

source
BackAction.calculatechannelweights!Method
calculatechannelweights!(P::Vector{Float64}, psi::Matrix{ComplexF64}, sys::System)

Calculate the probabilities for a mixed state $\psi$ to jump to any of the given channels i.e. $\mathrm{Tr}(L^\dagger L\psi)$ for each jump operator $L$, and writes it at P. This is done using of LinearAlgebra's tr.

source
BackAction.sampletauindex!Method
samplejumptime!(W::Vector{Float64}, Qs::Array{ComplexF64}, psi::VecOrMat{ComplexF64})

Sample a jump time index from the state psi (pure or mixed), modfying W to write on it. The technique is inversion sampling

source
BackAction.sampletauindex!Method
samplejumptime!(W::Vector{Float64}, Qs::Array{ComplexF64}, psi::VecOrMat{ComplexF64})

Sample a jump time index from the state psi (pure or mixed), modfying W to write on it. The technique is inversion sampling

source

State Updates

BackAction.prejumpupdate!Method
prejumpupdate!(V::Matrix{ComplexF64}, psi::Vector{ComplexF64}; normalize=false)

Do the pure state transformation $|\psi\rangle\to V|\psi\rangle$ modifying psi , if normalize=true it also normalizes the final state.

source
BackAction.prejumpupdate!Method
prejumpupdate!(psi::Vector{ComplexF64}, V::Matrix{ComplexF64},
               psi0::Union{Vector{ComplexF64}, SubArray{ComplexF64}}; normalize=false)

Do the pure state transformation $|\psi_0\rangle\to V|\psi_0\rangle$ and store the result in psi, if normalize=true it also normalizes the final state.

source
BackAction.prejumpupdate!Method
prejumpupdate!(psi::Matrix{ComplexF64}, V::Matrix{ComplexF64},
               psi0::Union{Vector{ComplexF64}, SubArray{ComplexF64}}; normalize=false)

Do the mixed state transformation $\psi_0\to V\psi_0 V^\dagger$ and store the result in psi, if normalize=true it also normalizes the final state.

source
BackAction.prejumpupdate!Method
prejumpupdate!(V::Matrix{ComplexF64}, psi::Vector{ComplexF64}; normalize=false)

Do the mixed state transformation $\psi\to V\psi V^\dagger$ modifying psi , if normalize=true it also normalizes the final state.

source
BackAction.postjumpupdate!Method
postjumpupdate!(L::Matrix{ComplexF64}, psi::Vector{ComplexF64}; normalize=true)

Do the pure state transformation $|\psi\rangle\to L|\psi\rangle$ modifying psi , if normalize=true it also normalizes the final state.

source
BackAction.postjumpupdate!Method
postjumpupdate!(L::Matrix{ComplexF64}, psi::Vector{ComplexF64}; normalize=true)

Do the pure mixed state transformation $\psi\to L\psi L^\dagger$ modifying psi , if normalize=true it also normalizes the final state.

source

Trajectory Evaluation

BackAction.run_singletrajectory_gillipsieMethod
run_singletrajectory_gillipsie(sys::System, params::SimulParameters,
    W::Vector{Float64}, P::Vector{Float64}, ts::Vector{Float64},
    Qs::Array{ComplexF64}, Vs::Array{ComplexF64}; seed::Int64 = 1)

Sample a jump trajectory for the system sys using the Quantum Gillipsie Algorithm [2].

Positional Arguments

  • sys::System: the system from which the trajectory is obtained.
  • params::SimulParameters: specifies the number of points in the grid, the initial state and the tolerance for the dark state test.
  • W::Vector{Float64}: to store the probabilities of the WTDs used at each step
  • P::Vector{Float64}: to store the probabilites of jumps to each channel used at each step
  • ts::Vector{Float64}: the fine grid used to sample from the WTD
  • Qs::Array{ComplexF64}: the precomputed matrices from which the WTD weights are calculated
  • Vs::Array{ComplexF64}: the precomputed exponentials that evolve the state from jump to jump.

Keyword Arguments

  • seed::Int64 = 1: the seed of the sample. It does not need to coincide with that in params

Returns

  • traj::Trajectory: vector with the obtained detection clicks.
source
BackAction.run_singletrajectory_gillipsie_renewalMethod
run_singletrajectory_gillipsie_renewal(sys::System, params::SimulParameters,
    W::Vector{Float64}, W0::Vector{Float64}, P::Vector{Float64}, ts::Vector{Float64},
    Qs::Array{ComplexF64}, Vs::Array{ComplexF64}, psireset::VecOrMat{ComplexF64}; seed::Int64 = 1)

Same as run_singletrajectory_gillipsie but uses psireset to optimize the jump time sampling by exploiting the process is renewal. Additionally, W0 must be provided to sample the first jump from the initial state, which may not coincide with psireset.

source
BackAction.gillipsiestep_returntau!Method
gillipsiestep_returntau!(sys::System, params::SimulParameters, W::Vector{Float64},
                        P::Vector{Float64}, Vs::Array{ComplexF64}, ts::Vector{Float64},
                        t::Float64, psi::VecOrMat{ComplexF64}, traj::Trajectory )

Do a step of the Gillipsie algorithm, updating the state and the weights, and returning the obtained jump time. In this version the time jump sampling is done by calling StatsBase.

source
BackAction.gillipsiestep_returntau!Method
gillipsiestep_returntau!(sys::System, params::SimulParameters, W::Vector{Float64},
                        P::Vector{Float64}, Qs::Array{ComplexF64}, Vs::Array{ComplexF64},
 ts::Vector{Float64},
                        t::Float64, psi::VecOrMat{ComplexF64}, traj::Trajectory )

Do a step of the Gillipsie algorithm, updating the state and the weights, and returning the obtained jump time. In this version the time is extracted using inversion sampling instead of calling StatsBase.

source
BackAction.writestate!Method
writestate!(states::array{complexf64}, psi::union{vector{complexf64},
                                        matrix{complexf64}}, counter::int64)

Writes psi in states at the subarray with the last index fixed at counter.

source