Nonmoralizing model

Global interaction quantum stochastic walk suffers from creating additional connections. This renders it unsuitable for constructing fast quantum walks on directed graphs. To counteract this effect, the nonmoralizing quantum stochastic walk was introduced (see arXiv preprint and its published version). Such a model is constructed in several steps. First, the dimensionality of the system is increased by attaching a multidimensional subspace to each vertex. Next, the Hamiltonian and the Lindblad operators are modified, and an additional Hamiltonian - so-called local Hamiltonian - is introduced.

Please note that current definition of nm_glob_ham differs from the one presented in the paper.

Below we present additional functionality useful for analyzing nonmoralizing quantum stochastic walk. By default, the operator is generalized as in the original paper.

Full docs

QSWalk.VertexType
type Vertex

Type consisting of list of Int, describing the labels of vectors from the canonical basis corresponding to the Vertex. To get the vector label one can use Vertex() function, or Vertex[i] for a unique label.

See [1] for the more information and usage exmaples.

[1] K. Domino, A. Glos, M. Ostaszewski, Superdiffusive quantum stochastic walk definable on arbitrary directed graph, Quantum Information & Computation, Vol.17 No.11&12, pp. 0973-0986, arXiv:1701.04624.

source
QSWalk.VertexSetType
type VertexSet

Type consisting of a list of Vertex objects. It describes the partition of the linear subspace. Object of this type should be constructed using make_vertex_set or by nm_lind functions. In order to get a list of the vertices from an object of type vertexset, one should use vlist function, or, for a specific Vertex, an getindex function vertexset[i].

source
QSWalk.nm_glob_hamFunction
nm_glob_ham(A[, hamiltonians][, weights, epsilon])

Return global Hamiltonian for the moralization procedure. Matrix A should the adjacency matrix of a directed graph, for which one aims to construct the nonmoralizing dynamics. Here, hamiltonians is an optional argument which is a Dictionary with keys of type Tuple{Int, Int} or Tuple{Vertex, Vertex}. The first collects the submatrices according to their shape, while the second collects them according to each pair of vertices. As the default all-one submatrices are chosen. The last argument states that only those elements for which abs(A[i, j]) >= epsilon are considered.

Note: The submatrices of the result matrix are scaled by corresponding weights argument, which should be a square matrix of the same dimension as A. If weights is not provided, then weights[i,j]=A[i,j], if A[i,j] is nonzero and A[j,i] is zero, weights[i,j]=A[j,i], if A[i,j] in reverse scenario, weights[i,j]=(A[i,j]+A[j,i])/2 if both are nonzero, and zero otherwise.

Examples

julia> A = [ 0 1 0; 1 0 1; 0 1 0]
3×3 Array{Int64,2}:
 0  1  0
 1  0  1
 0  1  0

julia> nm_glob_ham(A) |> Matrix
4×4 Array{Complex{Float64},2}:
 0.0+0.0im  1.0+0.0im  1.0+0.0im  0.0+0.0im
 1.0+0.0im  0.0+0.0im  0.0+0.0im  1.0+0.0im
 1.0+0.0im  0.0+0.0im  0.0+0.0im  1.0+0.0im
 0.0+0.0im  1.0+0.0im  1.0+0.0im  0.0+0.0im

julia> dict_deg = Dict{Tuple{Int,Int},Matrix{ComplexF64}}((1, 2) => (2+1im)*ones(1, 2), (2, 1) =>1im*ones(2, 1));

julia> nm_glob_ham(A, dict_deg) |> Matrix
4×4 Array{Complex{Float64},2}:
 0.0+0.0im  2.0+1.0im  2.0+1.0im  0.0+0.0im
 2.0-1.0im  0.0+0.0im  0.0+0.0im  0.0+1.0im
 2.0-1.0im  0.0+0.0im  0.0+0.0im  0.0+1.0im
 0.0+0.0im  0.0-1.0im  0.0-1.0im  0.0+0.0im

julia> v1, v2, v3 = vlist(make_vertex_set(A))
3-element Array{Vertex,1}:
 Vertex([1])
 Vertex([2, 3])
 Vertex([4])

julia> dict_vec = Dict{Tuple{Vertex,Vertex},Matrix{ComplexF64}}((v1, v2) =>2*ones(1, 2), (v2, v3) =>[1im 2im;]');

julia> nm_glob_ham(A, dict_vec) |> Matrix
4×4 Array{Complex{Float64},2}:
 0.0+0.0im  2.0+0.0im  2.0+0.0im  0.0+0.0im
 2.0+0.0im  0.0+0.0im  0.0+0.0im  0.0-1.0im
 2.0+0.0im  0.0+0.0im  0.0+0.0im  0.0-2.0im
 0.0+0.0im  0.0+1.0im  0.0+2.0im  0.0+0.0im
source
nm_glob_ham(A[, hamiltonians][, weights, epsilon])

Return global Hamiltonian for the moralization procedure. Matrix A should the adjacency matrix of a directed graph, for which one aims to construct the nonmoralizing dynamics. Here, hamiltonians is an optional argument which is a Dictionary with keys of type Tuple{Int, Int} or Tuple{Vertex, Vertex}. The first collects the submatrices according to their shape, while the second collects them according to each pair of vertices. As the default all-one submatrices are chosen. The last argument states that only those elements for which abs(A[i, j]) >= epsilon are considered.

Note: The submatrices of the result matrix are scaled by corresponding weights argument, which should be a square matrix of the same dimension as A. If weights is not provided, then weights[i,j]=A[i,j], if A[i,j] is nonzero and A[j,i] is zero, weights[i,j]=A[j,i], if A[i,j] in reverse scenario, weights[i,j]=(A[i,j]+A[j,i])/2 if both are nonzero, and zero otherwise.

Examples

julia> A = [ 0 1 0; 1 0 1; 0 1 0]
3×3 Array{Int64,2}:
 0  1  0
 1  0  1
 0  1  0

julia> nm_glob_ham(A) |> Matrix
4×4 Array{Complex{Float64},2}:
 0.0+0.0im  1.0+0.0im  1.0+0.0im  0.0+0.0im
 1.0+0.0im  0.0+0.0im  0.0+0.0im  1.0+0.0im
 1.0+0.0im  0.0+0.0im  0.0+0.0im  1.0+0.0im
 0.0+0.0im  1.0+0.0im  1.0+0.0im  0.0+0.0im

julia> dict_deg = Dict{Tuple{Int,Int},Matrix{ComplexF64}}((1, 2) => (2+1im)*ones(1, 2), (2, 1) =>1im*ones(2, 1));

julia> nm_glob_ham(A, dict_deg) |> Matrix
4×4 Array{Complex{Float64},2}:
 0.0+0.0im  2.0+1.0im  2.0+1.0im  0.0+0.0im
 2.0-1.0im  0.0+0.0im  0.0+0.0im  0.0+1.0im
 2.0-1.0im  0.0+0.0im  0.0+0.0im  0.0+1.0im
 0.0+0.0im  0.0-1.0im  0.0-1.0im  0.0+0.0im

julia> v1, v2, v3 = vlist(make_vertex_set(A))
3-element Array{Vertex,1}:
 Vertex([1])
 Vertex([2, 3])
 Vertex([4])

julia> dict_vec = Dict{Tuple{Vertex,Vertex},Matrix{ComplexF64}}((v1, v2) =>2*ones(1, 2), (v2, v3) =>[1im 2im;]');

julia> nm_glob_ham(A, dict_vec) |> Matrix
4×4 Array{Complex{Float64},2}:
 0.0+0.0im  2.0+0.0im  2.0+0.0im  0.0+0.0im
 2.0+0.0im  0.0+0.0im  0.0+0.0im  0.0-1.0im
 2.0+0.0im  0.0+0.0im  0.0+0.0im  0.0-2.0im
 0.0+0.0im  0.0+1.0im  0.0+2.0im  0.0+0.0im
source
nm_glob_ham(A[, hamiltonians][, weights, epsilon])

Return global Hamiltonian for the moralization procedure. Matrix A should the adjacency matrix of a directed graph, for which one aims to construct the nonmoralizing dynamics. Here, hamiltonians is an optional argument which is a Dictionary with keys of type Tuple{Int, Int} or Tuple{Vertex, Vertex}. The first collects the submatrices according to their shape, while the second collects them according to each pair of vertices. As the default all-one submatrices are chosen. The last argument states that only those elements for which abs(A[i, j]) >= epsilon are considered.

Note: The submatrices of the result matrix are scaled by corresponding weights argument, which should be a square matrix of the same dimension as A. If weights is not provided, then weights[i,j]=A[i,j], if A[i,j] is nonzero and A[j,i] is zero, weights[i,j]=A[j,i], if A[i,j] in reverse scenario, weights[i,j]=(A[i,j]+A[j,i])/2 if both are nonzero, and zero otherwise.

Examples

julia> A = [ 0 1 0; 1 0 1; 0 1 0]
3×3 Array{Int64,2}:
 0  1  0
 1  0  1
 0  1  0

julia> nm_glob_ham(A) |> Matrix
4×4 Array{Complex{Float64},2}:
 0.0+0.0im  1.0+0.0im  1.0+0.0im  0.0+0.0im
 1.0+0.0im  0.0+0.0im  0.0+0.0im  1.0+0.0im
 1.0+0.0im  0.0+0.0im  0.0+0.0im  1.0+0.0im
 0.0+0.0im  1.0+0.0im  1.0+0.0im  0.0+0.0im

julia> dict_deg = Dict{Tuple{Int,Int},Matrix{ComplexF64}}((1, 2) => (2+1im)*ones(1, 2), (2, 1) =>1im*ones(2, 1));

julia> nm_glob_ham(A, dict_deg) |> Matrix
4×4 Array{Complex{Float64},2}:
 0.0+0.0im  2.0+1.0im  2.0+1.0im  0.0+0.0im
 2.0-1.0im  0.0+0.0im  0.0+0.0im  0.0+1.0im
 2.0-1.0im  0.0+0.0im  0.0+0.0im  0.0+1.0im
 0.0+0.0im  0.0-1.0im  0.0-1.0im  0.0+0.0im

julia> v1, v2, v3 = vlist(make_vertex_set(A))
3-element Array{Vertex,1}:
 Vertex([1])
 Vertex([2, 3])
 Vertex([4])

julia> dict_vec = Dict{Tuple{Vertex,Vertex},Matrix{ComplexF64}}((v1, v2) =>2*ones(1, 2), (v2, v3) =>[1im 2im;]');

julia> nm_glob_ham(A, dict_vec) |> Matrix
4×4 Array{Complex{Float64},2}:
 0.0+0.0im  2.0+0.0im  2.0+0.0im  0.0+0.0im
 2.0+0.0im  0.0+0.0im  0.0+0.0im  0.0-1.0im
 2.0+0.0im  0.0+0.0im  0.0+0.0im  0.0-2.0im
 0.0+0.0im  0.0+1.0im  0.0+2.0im  0.0+0.0im
source
QSWalk.nm_lindFunction
nm_lind(A[, lindbladians][, epsilon])

Return single Lindbladian operator and a vertex set describing how vertices are bound to subspaces. The operator is constructed according to the corection scheme presented in [1]. Parameter A is a square matrix, describing the connection between the canonical subspaces in a similar manner as the adjacency matrix. Parameter epsilon, with the default value eps(), determines the relevant values by abs(A[i, j]) >= epsilon formula. List lindbladians describes the elementary matrices used. It can be Dict{Int, SparseDenseMatrix}, which returns the matrix by the indegree, or Dict{Vertex, SparseDenseMatrix} which, for different vertices, may return different matrix. The matrix should have orthogonal columns and be of the size outdeg of the vertex. As default the function uses Fourier matrices.

Note: It is expected that for all pair of vertices there exists a matrix in the lindbladians list.

Note: The orthogonality of matrices in lindbladians is not verified.

Note: The submatrices of the result matrix are multiplied by corresponding A element.

[1] K. Domino, A. Glos, M. Ostaszewski, Superdiffusive quantum stochastic walk definable on arbitrary directed graph, Quantum Information & Computation, Vol.17 No.11&12, pp. 0973-0986, arXiv:1701.04624.

Examples

julia> A = [0 1 0; 1 0 1; 0 1 0]
3×3 Array{Int64,2}:
 0  1  0
 1  0  1
 0  1  0

julia> L, vset = nm_lind(A)
(
  [2, 1]  =  1.0+0.0im
  [3, 1]  =  1.0+0.0im
  [1, 2]  =  1.0+0.0im
  [4, 2]  =  1.0+0.0im
  [1, 3]  =  1.0+0.0im
  [4, 3]  =  1.0+0.0im
  [2, 4]  =  1.0+0.0im
  [3, 4]  =  -1.0+1.22465e-16im, VertexSet(Vertex[Vertex([1]), Vertex([2, 3]), Vertex([4])]))

julia> B1, B2 = 2*diagm(0=>[1.]), 3*ones(2, 2)
([2.0], [3.0 3.0; 3.0 3.0])

julia> nm_lind(A, Dict{Int,Matrix{Float64}}(1=>B1, 2=>B2))
(
  [2, 1]  =  3.0+0.0im
  [3, 1]  =  3.0+0.0im
  [1, 2]  =  2.0+0.0im
  [4, 2]  =  2.0+0.0im
  [1, 3]  =  2.0+0.0im
  [4, 3]  =  2.0+0.0im
  [2, 4]  =  3.0+0.0im
  [3, 4]  =  3.0+0.0im, VertexSet(Vertex[Vertex([1]), Vertex([2, 3]), Vertex([4])]))

julia> v1, v2, v3 = vlist(vset)
3-element Array{Vertex,1}:
 Vertex([1])
 Vertex([2, 3])
 Vertex([4])

julia> nm_lind(A, Dict{Vertex,Matrix{Float64}}(v1 => ones(1, 1), v2 => [2 2; 2 -2], v3 => 3*ones(1, 1)))[1] |> Matrix
4×4 Array{Complex{Float64},2}:
 0.0+0.0im  1.0+0.0im  1.0+0.0im   0.0+0.0im
 2.0+0.0im  0.0+0.0im  0.0+0.0im   2.0+0.0im
 2.0+0.0im  0.0+0.0im  0.0+0.0im  -2.0+0.0im
 0.0+0.0im  3.0+0.0im  3.0+0.0im   0.0+0.0im
source
nm_lind(A[, lindbladians][, epsilon])

Return single Lindbladian operator and a vertex set describing how vertices are bound to subspaces. The operator is constructed according to the corection scheme presented in [1]. Parameter A is a square matrix, describing the connection between the canonical subspaces in a similar manner as the adjacency matrix. Parameter epsilon, with the default value eps(), determines the relevant values by abs(A[i, j]) >= epsilon formula. List lindbladians describes the elementary matrices used. It can be Dict{Int, SparseDenseMatrix}, which returns the matrix by the indegree, or Dict{Vertex, SparseDenseMatrix} which, for different vertices, may return different matrix. The matrix should have orthogonal columns and be of the size outdeg of the vertex. As default the function uses Fourier matrices.

Note: It is expected that for all pair of vertices there exists a matrix in the lindbladians list.

Note: The orthogonality of matrices in lindbladians is not verified.

Note: The submatrices of the result matrix are multiplied by corresponding A element.

[1] K. Domino, A. Glos, M. Ostaszewski, Superdiffusive quantum stochastic walk definable on arbitrary directed graph, Quantum Information & Computation, Vol.17 No.11&12, pp. 0973-0986, arXiv:1701.04624.

Examples

julia> A = [0 1 0; 1 0 1; 0 1 0]
3×3 Array{Int64,2}:
 0  1  0
 1  0  1
 0  1  0

julia> L, vset = nm_lind(A)
(
  [2, 1]  =  1.0+0.0im
  [3, 1]  =  1.0+0.0im
  [1, 2]  =  1.0+0.0im
  [4, 2]  =  1.0+0.0im
  [1, 3]  =  1.0+0.0im
  [4, 3]  =  1.0+0.0im
  [2, 4]  =  1.0+0.0im
  [3, 4]  =  -1.0+1.22465e-16im, VertexSet(Vertex[Vertex([1]), Vertex([2, 3]), Vertex([4])]))

julia> B1, B2 = 2*diagm(0=>[1.]), 3*ones(2, 2)
([2.0], [3.0 3.0; 3.0 3.0])

julia> nm_lind(A, Dict{Int,Matrix{Float64}}(1=>B1, 2=>B2))
(
  [2, 1]  =  3.0+0.0im
  [3, 1]  =  3.0+0.0im
  [1, 2]  =  2.0+0.0im
  [4, 2]  =  2.0+0.0im
  [1, 3]  =  2.0+0.0im
  [4, 3]  =  2.0+0.0im
  [2, 4]  =  3.0+0.0im
  [3, 4]  =  3.0+0.0im, VertexSet(Vertex[Vertex([1]), Vertex([2, 3]), Vertex([4])]))

julia> v1, v2, v3 = vlist(vset)
3-element Array{Vertex,1}:
 Vertex([1])
 Vertex([2, 3])
 Vertex([4])

julia> nm_lind(A, Dict{Vertex,Matrix{Float64}}(v1 => ones(1, 1), v2 => [2 2; 2 -2], v3 => 3*ones(1, 1)))[1] |> Matrix
4×4 Array{Complex{Float64},2}:
 0.0+0.0im  1.0+0.0im  1.0+0.0im   0.0+0.0im
 2.0+0.0im  0.0+0.0im  0.0+0.0im   2.0+0.0im
 2.0+0.0im  0.0+0.0im  0.0+0.0im  -2.0+0.0im
 0.0+0.0im  3.0+0.0im  3.0+0.0im   0.0+0.0im
source
nm_lind(A[, lindbladians][, epsilon])

Return single Lindbladian operator and a vertex set describing how vertices are bound to subspaces. The operator is constructed according to the corection scheme presented in [1]. Parameter A is a square matrix, describing the connection between the canonical subspaces in a similar manner as the adjacency matrix. Parameter epsilon, with the default value eps(), determines the relevant values by abs(A[i, j]) >= epsilon formula. List lindbladians describes the elementary matrices used. It can be Dict{Int, SparseDenseMatrix}, which returns the matrix by the indegree, or Dict{Vertex, SparseDenseMatrix} which, for different vertices, may return different matrix. The matrix should have orthogonal columns and be of the size outdeg of the vertex. As default the function uses Fourier matrices.

Note: It is expected that for all pair of vertices there exists a matrix in the lindbladians list.

Note: The orthogonality of matrices in lindbladians is not verified.

Note: The submatrices of the result matrix are multiplied by corresponding A element.

[1] K. Domino, A. Glos, M. Ostaszewski, Superdiffusive quantum stochastic walk definable on arbitrary directed graph, Quantum Information & Computation, Vol.17 No.11&12, pp. 0973-0986, arXiv:1701.04624.

Examples

julia> A = [0 1 0; 1 0 1; 0 1 0]
3×3 Array{Int64,2}:
 0  1  0
 1  0  1
 0  1  0

julia> L, vset = nm_lind(A)
(
  [2, 1]  =  1.0+0.0im
  [3, 1]  =  1.0+0.0im
  [1, 2]  =  1.0+0.0im
  [4, 2]  =  1.0+0.0im
  [1, 3]  =  1.0+0.0im
  [4, 3]  =  1.0+0.0im
  [2, 4]  =  1.0+0.0im
  [3, 4]  =  -1.0+1.22465e-16im, VertexSet(Vertex[Vertex([1]), Vertex([2, 3]), Vertex([4])]))

julia> B1, B2 = 2*diagm(0=>[1.]), 3*ones(2, 2)
([2.0], [3.0 3.0; 3.0 3.0])

julia> nm_lind(A, Dict{Int,Matrix{Float64}}(1=>B1, 2=>B2))
(
  [2, 1]  =  3.0+0.0im
  [3, 1]  =  3.0+0.0im
  [1, 2]  =  2.0+0.0im
  [4, 2]  =  2.0+0.0im
  [1, 3]  =  2.0+0.0im
  [4, 3]  =  2.0+0.0im
  [2, 4]  =  3.0+0.0im
  [3, 4]  =  3.0+0.0im, VertexSet(Vertex[Vertex([1]), Vertex([2, 3]), Vertex([4])]))

julia> v1, v2, v3 = vlist(vset)
3-element Array{Vertex,1}:
 Vertex([1])
 Vertex([2, 3])
 Vertex([4])

julia> nm_lind(A, Dict{Vertex,Matrix{Float64}}(v1 => ones(1, 1), v2 => [2 2; 2 -2], v3 => 3*ones(1, 1)))[1] |> Matrix
4×4 Array{Complex{Float64},2}:
 0.0+0.0im  1.0+0.0im  1.0+0.0im   0.0+0.0im
 2.0+0.0im  0.0+0.0im  0.0+0.0im   2.0+0.0im
 2.0+0.0im  0.0+0.0im  0.0+0.0im  -2.0+0.0im
 0.0+0.0im  3.0+0.0im  3.0+0.0im   0.0+0.0im
source
QSWalk.nm_measurementFunction
nm_measurement(probability, vertexset)

Return joint probability of probability, which is real-valued probability vector according to vertexset.

Note: It is up to user to provide proper probability vector.

Examples

julia> probability = [0.05, 0.1, 0.25, 0.3, 0.01, 0.20, 0.04, 0.05]
8-element Array{Float64,1}:
 0.05
 0.1
 0.25
 0.3
 0.01
 0.2
 0.04
 0.05

julia> nm_measurement(probability, VertexSet([[1, 4], [2, 3, 5], [6], [7, 8]]))
4-element Array{Float64,1}:
 0.35
 0.36
 0.2
 0.09
source
nm_measurement(state, vertexset)

Return joint probability of cannonical measurement of density matrix state, according to vertexset.

Note: It is up to user to provide proper density state.

Examples

julia> state = [1/6 0 1/6; 0 2/3 0; 1/6 0 1/6]
3×3 Array{Float64,2}:
 0.166667  0.0       0.166667
 0.0       0.666667  0.0
 0.166667  0.0       0.166667

julia> nm_measurement(state, VertexSet([[1, 3], [2]]))
2-element Array{Float64,1}:
 0.3333333333333333
 0.6666666666666666
source
QSWalk.nm_loc_hamFunction
nm_loc_ham(vertexset[, hamiltoniansByDegree])

Return Hamiltonian acting locally on each vertex from vertexset linear subspace. hamiltoniansByDegree is a dictionary Dict{Int, SparseDenseMatrix}, which, for a given dimension of vertex linear subspace, yields a hermitian operator. Only matrices for existing dimensions needs to be specified.

Note: Value of vertexset should be generated by make_vertex_set in order to match demoralization procedure. Numerical analysis suggests, that hamiltonians should be complex valued.

Examples

julia> vset = VertexSet([[1, 2], [3, 4]])
VertexSet(Vertex[Vertex([1, 2]), Vertex([3, 4])])

julia> Matrix(nm_loc_ham(vset))
4×4 Array{Complex{Float64},2}:
 0.0+0.0im  0.0+1.0im  0.0+0.0im  0.0+0.0im
 0.0-1.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im
 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+1.0im
 0.0+0.0im  0.0+0.0im  0.0-1.0im  0.0+0.0im

julia> A = [1 1im; -1im 1]
2×2 Array{Complex{Int64},2}:
 1+0im  0+1im
 0-1im  1+0im

julia> nm_loc_ham(vset, Dict{Int,Matrix{ComplexF64}}(2  => A))
4×4 SparseArrays.SparseMatrixCSC{Complex{Float64},Int64} with 8 stored entries:
  [1, 1]  =  1.0+0.0im
  [2, 1]  =  0.0-1.0im
  [1, 2]  =  0.0+1.0im
  [2, 2]  =  1.0+0.0im
  [3, 3]  =  1.0+0.0im
  [4, 3]  =  0.0-1.0im
  [3, 4]  =  0.0+1.0im
  [4, 4]  =  1.0+0.0im
source
nm_loc_ham(vertexset[, hamiltoniansByVertex])

Return Hamiltonian acting locally on each vertex from vertexset linear subspace. hamiltoniansByVertex is a dictionary Dict{Vertex, SparseDenseMatrix}, which, for a given vertex, yields a hermitian operator of the size equal to the dimension of the vertex subspace.

Note: Value of vertexset should be generated by make_vertex_set in order to match demoralization procedure. Numerical analysis suggests, that hamiltonians should be complex valued.

Examples

julia> vset = VertexSet([[1, 2], [3, 4]])
VertexSet(Vertex[Vertex([1, 2]), Vertex([3, 4])])

julia> Matrix(nm_loc_ham(vset))
4×4 Array{Complex{Float64},2}:
 0.0+0.0im  0.0+1.0im  0.0+0.0im  0.0+0.0im
 0.0-1.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im
 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+1.0im
 0.0+0.0im  0.0+0.0im  0.0-1.0im  0.0+0.0im

julia> A, B = [1 1im; -1im 1], [0 1; 1 0]
(Complex{Int64}[1 + 0im 0 + 1im; 0 - 1im 1 + 0im], [0 1; 1 0])

julia> v1, v2 = vlist(vset)
2-element Array{Vertex,1}:
 Vertex([1, 2])
 Vertex([3, 4])

julia> nm_loc_ham(vset, Dict{Vertex,Matrix{Number}}(v1  => A, v2  => B))
4×4 SparseArrays.SparseMatrixCSC{Complex{Float64},Int64} with 6 stored entries:
  [1, 1]  =  1.0+0.0im
  [2, 1]  =  0.0-1.0im
  [1, 2]  =  0.0+1.0im
  [2, 2]  =  1.0+0.0im
  [4, 3]  =  1.0+0.0im
  [3, 4]  =  1.0+0.0im
source
QSWalk.nm_initFunction
nm_init(init_vertices, vertexset)

Create initial state in the case of the nonmoralizing evolution based on init_vertices of type Vector{Vertex}. The result is a block diagonal matrix, where each block corresponds to vertex from vertexset. The final state represent an uniform probability over nm_measurement.

Note: The function returns sparse matrix with ComplexF64 field type.

Examples

julia> vset = VertexSet([[1], [2, 3, 4], [5, 6, 7], [8, 9]])
VertexSet(Vertex[Vertex([1]), Vertex([2, 3, 4]), Vertex([5, 6, 7]), Vertex([8, 9])])

julia> nm_init(vset[[1, 3, 4]], vset)
9×9 SparseArrays.SparseMatrixCSC{Complex{Float64},Int64} with 6 stored entries:
  [1, 1]  =  0.333333+0.0im
  [5, 5]  =  0.111111+0.0im
  [6, 6]  =  0.111111+0.0im
  [7, 7]  =  0.111111+0.0im
  [8, 8]  =  0.166667+0.0im
  [9, 9]  =  0.166667+0.0im
source
nm_init(init_states, vertexset)

Create initial state in the case of the nonmoralizing evolution based on init_states of type Dict{Vertex, <:AbstractMatrix{<:Number}}. For each given vertex a block from dictionary is used, otherwise zero matrix is chosen. Each matrix from dictionary should be nonnegative and sum of all traces should equal one. The keys of init_vertices should be a vertices from vertexset. Note that matrix from init_states corresponding to vertex v should be of size length(v)×length(v).

Note: The function returns sparse matrix with ComplexF64 field type.

Examples

julia> vset = VertexSet([[1], [2, 3, 4], [5, 6, 7], [8, 9]])
VertexSet(Vertex[Vertex([1]), Vertex([2, 3, 4]), Vertex([5, 6, 7]), Vertex([8, 9])])

julia> A1, A2, A3 = ones(ComplexF64, 1, 1)/4, [ 1/5+0im 0 1/5; 0 1/10 0 ; 1/5 0 1/5 ], [0.125 -0.125+0im; -0.125 0.125]
(Complex{Float64}[0.25 + 0.0im], Complex{Float64}[0.2 + 0.0im 0.0 + 0.0im 0.2 + 0.0im; 0.0 + 0.0im 0.1 + 0.0im 0.0 + 0.0im; 0.2 + 0.0im 0.0 + 0.0im 0.2 + 0.0im], Complex{Float64}[0.125 + 0.0im -0.125 + 0.0im; -0.125 + 0.0im 0.125 + 0.0im])

julia> nm_init(Dict(vset[1] =>A1, vset[3] =>A2, vset[4] =>A3), vset)
9×9 SparseArrays.SparseMatrixCSC{Complex{Float64},Int64} with 10 stored entries:
  [1, 1]  =  0.25+0.0im
  [5, 5]  =  0.2+0.0im
  [7, 5]  =  0.2+0.0im
  [6, 6]  =  0.1+0.0im
  [5, 7]  =  0.2+0.0im
  [7, 7]  =  0.2+0.0im
  [8, 8]  =  0.125+0.0im
  [9, 8]  =  -0.125+0.0im
  [8, 9]  =  -0.125+0.0im
  [9, 9]  =  0.125+0.0im
source
QSWalk.default_nm_loc_hamFunction
default_nm_loc_ham(size)

Return default local Hamiltonian of size size×size for the demoralization procedure. The Hamiltonian is sparse with nonzero elements on the first upper diagonal (equal to 1im) and lower diagonal (equal to -1im).

Note: This function is used to provide the default argument for nm_loc_ham function.

Examples

julia> QSWalk.default_nm_loc_ham(4)
4×4 SparseArrays.SparseMatrixCSC{Complex{Float64},Int64} with 6 stored entries:
  [2, 1]  =  0.0-1.0im
  [1, 2]  =  0.0+1.0im
  [3, 2]  =  0.0-1.0im
  [2, 3]  =  0.0+1.0im
  [4, 3]  =  0.0-1.0im
  [3, 4]  =  0.0+1.0im
source
QSWalk.make_vertex_setFunction
make_vertex_set(A[, epsilon])

Creates object of type VertexSet which represents how vertices are located in matrix. Should be used only in the nondefault use of evolve_generator function. It is always equal to the second element if output of evolve_generator function.

Examples

julia> A = [1 2 3; 0 3. 4.; 0 0 5.]
3×3 Array{Float64,2}:
 1.0  2.0  3.0
 0.0  3.0  4.0
 0.0  0.0  5.0

julia> vlist(make_vertex_set(A))
3-element Array{Vertex,1}:
 Vertex([1, 2, 3])
 Vertex([4, 5])
 Vertex([6])

julia> vlist(make_vertex_set(A, epsilon = 2.5))
3-element Array{Vertex,1}:
 Vertex([1])
 Vertex([2, 3])
 Vertex([4])
source
QSWalk.vlistFunction
vlist(vset)

Returns the list of vertices for given vset of type VertexSet.

julia> vset = VertexSet([[1], [2, 3, 4], [5, 6, 7], [8, 9]])
VertexSet(Vertex[Vertex([1]), Vertex([2, 3, 4]), Vertex([5, 6, 7]), Vertex([8, 9])])

julia> vlist(vset)
4-element Array{Vertex,1}:
 Vertex([1])
 Vertex([2, 3, 4])
 Vertex([5, 6, 7])
 Vertex([8, 9])
source
QSWalk.subspaceFunction
subspace(v)

Returns the subspace connected to vertex v.

julia> v = Vertex([1,2,3])
Vertex([1, 2, 3])

julia> subspace(v)
3-element Array{Int64,1}:
 1
 2
 3
source
QSWalk.fourier_matrixFunction
fourier_matrix(size)

Returns Fourier matrix of size size×size.

Examples

julia> fourier_matrix(1)
1×1 SparseArrays.SparseMatrixCSC{Complex{Float64},Int64} with 1 stored entry:
  [1, 1]  =  1.0+0.0im

julia> fourier_matrix(2)
2×2 SparseArrays.SparseMatrixCSC{Complex{Float64},Int64} with 4 stored entries:
  [1, 1]  =  1.0+0.0im
  [2, 1]  =  1.0+0.0im
  [1, 2]  =  1.0+0.0im
  [2, 2]  =  -1.0+1.22465e-16im
source
QSWalk.vertexsetsizeFunction
vertexsetsize(vertexset)

Return the dimension of the linearspace corresponding to given vertexset.

Examples

julia> vertexsetsize(VertexSet([[1, 2, 3], [4, 5]]))
5
source