Skip to content

Commit

Permalink
restore JuliaFormatter
Browse files Browse the repository at this point in the history
  • Loading branch information
araujoms committed Jan 2, 2025
1 parent 32eb613 commit a009983
Show file tree
Hide file tree
Showing 25 changed files with 582 additions and 565 deletions.
10 changes: 10 additions & 0 deletions .JuliaFormatter.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Configuration file for JuliaFormatter.jl
# For more information, see: https://domluna.github.io/JuliaFormatter.jl/stable/config/

margin = 120
trailing_comma = false
remove_extra_newlines = true
separate_kwargs_with_semicolon = true
normalize_line_endings = "unix"
always_for_in = true
for_in_replacement = ""
2 changes: 1 addition & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ open(joinpath(generated_path, "index.md"), "w") do io
"""
)
# Write the contents out below the meta block
for line in eachline(joinpath(dirname(@__DIR__), "README.md"))
for line eachline(joinpath(dirname(@__DIR__), "README.md"))
println(io, line)
end
end
Expand Down
123 changes: 61 additions & 62 deletions src/basic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Produces a ket of dimension `d` with nonzero element `i`.
"""
function ket(::Type{T}, i::Integer, d::Integer = 2) where {T <: Number}
function ket(::Type{T}, i::Integer, d::Integer = 2) where {T<:Number}
psi = zeros(T, d)
psi[i] = 1
return psi
Expand All @@ -26,15 +26,15 @@ export ketbra
Produces a projector onto the basis state `i` in dimension `d`.
"""
function proj(::Type{T}, i::Integer, d::Integer = 2) where {T <: Number}
function proj(::Type{T}, i::Integer, d::Integer = 2) where {T<:Number}
p = Hermitian(zeros(T, d, d))
p[i, i] = 1
return p
end
proj(i::Integer, d::Integer = 2) = proj(Bool, i, d)
export proj

const Measurement{T} = Vector{Hermitian{T, Matrix{T}}}
const Measurement{T} = Vector{Hermitian{T,Matrix{T}}}
export Measurement

"""
Expand All @@ -43,7 +43,7 @@ export Measurement
Creates a set of (projective) measurements from a set of bases given as unitary matrices.
"""
function povm(B::Vector{<:AbstractMatrix})
return [[ketbra(B[x][:, a]) for a in 1:size(B[x], 2)] for x in eachindex(B)]
return [[ketbra(B[x][:, a]) for a 1:size(B[x], 2)] for x eachindex(B)]
end
export povm

Expand All @@ -54,8 +54,8 @@ Converts a set of measurements in the common tensor format into a matrix of (her
By default, the second argument is fixed by the size of `A`.
It can also contain custom number of outcomes if there are measurements with less outcomes.
"""
function tensor_to_povm(Aax::Array{T, 4}, o::Vector{Int} = fill(size(Aax, 3), size(Aax, 4))) where {T}
return [[Hermitian(Aax[:, :, a, x]) for a in 1:o[x]] for x in axes(Aax, 4)]
function tensor_to_povm(Aax::Array{T,4}, o::Vector{Int} = fill(size(Aax, 3), size(Aax, 4))) where {T}
return [[Hermitian(Aax[:, :, a, x]) for a 1:o[x]] for x axes(Aax, 4)]
end
export tensor_to_povm

Expand All @@ -64,19 +64,19 @@ export tensor_to_povm
Converts a matrix of (hermitian) matrices into a set of measurements in the common tensor format.
"""
function povm_to_tensor(Axa::Vector{Measurement{T}}) where {T <: Number}
function povm_to_tensor(Axa::Vector{Measurement{T}}) where {T<:Number}
d, o, m = _measurements_parameters(Axa)
Aax = zeros(T, d, d, maximum(o), m)
for x in eachindex(Axa)
for a in eachindex(Axa[x])
for x eachindex(Axa)
for a eachindex(Axa[x])
Aax[:, :, a, x] .= Axa[x][a]
end
end
return Aax
end
export povm_to_tensor

function _measurements_parameters(Axa::Vector{Measurement{T}}) where {T <: Number}
function _measurements_parameters(Axa::Vector{Measurement{T}}) where {T<:Number}
@assert !isempty(Axa)
# dimension on which the measurements act
d = size(Axa[1][1], 1)
Expand All @@ -93,11 +93,11 @@ _measurements_parameters(Aa::Measurement) = _measurements_parameters([Aa])
Checks if the measurement defined by A is valid (hermitian, semi-definite positive, and normalized).
"""
function test_povm(E::Vector{<:AbstractMatrix{T}}) where {T <: Number}
function test_povm(E::Vector{<:AbstractMatrix{T}}) where {T<:Number}
!all(ishermitian.(E)) && return false
d = size(E[1], 1)
!(sum(E) I(d)) && return false
for i in 1:length(E)
for i 1:length(E)
minimum(eigvals(E[i])) < -_rtol(T) && return false
end
return true
Expand All @@ -111,10 +111,10 @@ Constructs the shift operator X of dimension `d` to the power `p`.
Reference: [Generalized Clifford algebra](https://en.wikipedia.org/wiki/Generalized_Clifford_algebra)
"""
function shift(::Type{T}, d::Integer, p::Integer = 1) where {T <: Number}
function shift(::Type{T}, d::Integer, p::Integer = 1) where {T<:Number}
X = zeros(T, d, d)
for i in 0:(d - 1)
X[mod(i + p, d) + 1, i + 1] = 1
for i 0:(d-1)
X[mod(i + p, d)+1, i+1] = 1
end
return X
end
Expand All @@ -128,21 +128,21 @@ Constructs the clock operator Z of dimension `d` to the power `p`.
Reference: [Generalized Clifford algebra](https://en.wikipedia.org/wiki/Generalized_Clifford_algebra)
"""
function clock(::Type{T}, d::Integer, p::Integer = 1) where {T <: Number}
function clock(::Type{T}, d::Integer, p::Integer = 1) where {T<:Number}
z = zeros(T, d)
ω = _root_unity(T, d)
for i in 0:(d - 1)
for i 0:(d-1)
exponent = mod(i * p, d)
if exponent == 0
z[i + 1] = 1
z[i+1] = 1
elseif 4exponent == d
z[i + 1] = im
z[i+1] = im
elseif 2exponent == d
z[i + 1] = -1
z[i+1] = -1
elseif 4exponent == 3d
z[i + 1] = -im
z[i+1] = -im
else
z[i + 1] = ω^exponent
z[i+1] = ω^exponent
end
end
return Diagonal(z)
Expand All @@ -160,19 +160,19 @@ Vectors of integers between 0 and 3 or strings of I, X, Y, Z
automatically generate Kronecker products of the corresponding
operators.
"""
function pauli(::Type{T}, i::Integer) where {T <: Number}
function pauli(::Type{T}, i::Integer) where {T<:Number}
return gellmann(T, i ÷ 2 + 1, i % 2 + 1, 2)
end
function pauli(::Type{T}, ind::Vector{<:Integer}) where {T <: Number}
function pauli(::Type{T}, ind::Vector{<:Integer}) where {T<:Number}
if length(ind) == 1
return pauli(T, ind[1])
else
return kron([pauli(T, i) for i in ind]...)
return kron([pauli(T, i) for i ind]...)
end
end
function pauli(::Type{T}, str::String) where {T <: Number}
function pauli(::Type{T}, str::String) where {T<:Number}
ind = Int[]
for c in str
for c str
if c in ['I', 'i', '1']
push!(ind, 0)
elseif c in ['X', 'x']
Expand All @@ -187,7 +187,7 @@ function pauli(::Type{T}, str::String) where {T <: Number}
end
return pauli(T, ind)
end
pauli(::Type{T}, c::Char) where {T <: Number} = pauli(T, string(c))
pauli(::Type{T}, c::Char) where {T<:Number} = pauli(T, string(c))
pauli(i::Integer) = pauli(ComplexF64, i)
pauli(ind::Vector{<:Integer}) = pauli(ComplexF64, ind)
pauli(str::String) = pauli(ComplexF64, str)
Expand All @@ -202,8 +202,8 @@ Constructs the set `G` of generalized Gell-Mann matrices in dimension `d` such t
Reference: [Generalizations of Pauli matrices](https://en.wikipedia.org/wiki/Generalizations_of_Pauli_matrices)
"""
function gellmann(::Type{T}, d::Integer = 3) where {T <: Number}
return [gellmann(T, i, j, d) for j in 1:d, i in 1:d][:]
function gellmann(::Type{T}, d::Integer = 3) where {T<:Number}
return [gellmann(T, i, j, d) for j 1:d, i 1:d][:]
# d=2, ρ = 1/2(σ0 + n*σ)
# d=3, ρ = 1/3(I + √3 n*λ)
# ρ = 1/d(I + sqrt(2/(d*(d-1))) n*λ)
Expand All @@ -221,7 +221,7 @@ Constructs the set `i`,`j`th Gell-Mann matrix of dimension `d`.
Reference: [Generalizations of Pauli matrices](https://en.wikipedia.org/wiki/Generalizations_of_Pauli_matrices)
"""
function gellmann(::Type{T}, i::Integer, j::Integer, d::Integer = 3) where {T <: Number}
function gellmann(::Type{T}, i::Integer, j::Integer, d::Integer = 3) where {T<:Number}
return gellmann!(zeros(T, d, d), i, j, d)
end
gellmann(i::Integer, j::Integer, d::Integer = 3) = gellmann(ComplexF64, i, j, d)
Expand All @@ -231,48 +231,48 @@ gellmann(i::Integer, j::Integer, d::Integer = 3) = gellmann(ComplexF64, i, j, d)
In-place version of `gellmann`.
"""
function gellmann!(res::AbstractMatrix{T}, i::Integer, j::Integer, d::Integer = 3) where {T <: Number}
function gellmann!(res::AbstractMatrix{T}, i::Integer, j::Integer, d::Integer = 3) where {T<:Number}
if i < j
res[i, j] = 1
res[j, i] = 1
elseif i > j
res[i, j] = im
res[j, i] = -im
elseif i == 1
for k in 1:d
for k 1:d
res[k, k] = 1 # _sqrt(T, 2) / _sqrt(T, d) if we want a proper normalisation
end
elseif i == d
tmp = _sqrt(T, 2) / _sqrt(T, d * (d - 1))
for k in 1:(d - 1)
for k 1:(d-1)
res[k, k] = tmp
end
res[d, d] = -(d - 1) * tmp
else
gellmann!(view(res, 1:(d - 1), 1:(d - 1)), i, j, d - 1)
gellmann!(view(res, 1:(d-1), 1:(d-1)), i, j, d - 1)
end
return res
end
export gellmann!

_rtol(::Type{T}) where {T <: Number} = Base.rtoldefault(real(T))
_rtol(::Type{T}) where {T<:Number} = Base.rtoldefault(real(T))

_eps(::Type{T}) where {T <: Number} = _realeps(real(T))
_realeps(::Type{T}) where {T <: AbstractFloat} = eps(T)
_eps(::Type{T}) where {T<:Number} = _realeps(real(T))
_realeps(::Type{T}) where {T<:AbstractFloat} = eps(T)
_realeps(::Type{<:Real}) = 0

"""
cleanup!(M::AbstractArray{T}; tol = Base.rtoldefault(real(T)))
Zeroes out real or imaginary parts of `M` that are smaller than `tol`.
"""
function cleanup!(M::AbstractArray{T}; tol = _eps(T)) where {T <: Number}
function cleanup!(M::AbstractArray{T}; tol = _eps(T)) where {T<:Number}
wrapper = Base.typename(typeof(M)).wrapper
cleanup!(parent(M); tol)
return wrapper(M)
end

function cleanup!(M::Array{T}; tol = _eps(T)) where {T <: Number}
function cleanup!(M::Array{T}; tol = _eps(T)) where {T<:Number}
if isbitstype(T)
M2 = reinterpret(real(T), M) #this is a no-op when T<:Real
_cleanup!(M2; tol)
Expand All @@ -288,29 +288,29 @@ end
export cleanup!

function _cleanup!(M; tol)
return M[abs.(M) .< tol] .= 0
return M[abs.(M).<tol] .= 0
end

function applykraus(K, M)
return sum(Hermitian(Ki * M * Ki') for Ki in K)
return sum(Hermitian(Ki * M * Ki') for Ki K)
end
export applykraus

function _orthonormal_range_svd!(
A::AbstractMatrix{T};
tol::Union{Real, Nothing} = nothing,
alg = LinearAlgebra.default_svd_alg(A)
) where {T <: Number}
A::AbstractMatrix{T};
tol::Union{Real,Nothing} = nothing,
alg = LinearAlgebra.default_svd_alg(A)
) where {T<:Number}
dec = svd!(A; alg = alg)
tol = isnothing(tol) ? maximum(dec.S) * _eps(T) * minimum(size(A)) : tol
rank = sum(dec.S .> tol)
dec.U[:, 1:rank]
end

_orthonormal_range_svd(A::AbstractMatrix; tol::Union{Real, Nothing} = nothing) =
_orthonormal_range_svd(A::AbstractMatrix; tol::Union{Real,Nothing} = nothing) =
_orthonormal_range_svd!(deepcopy(A); tol)

function _orthonormal_range_qr(A::SA.AbstractSparseMatrix{T, M}; tol::Union{Real, Nothing} = nothing) where {T <: Number, M}
function _orthonormal_range_qr(A::SA.AbstractSparseMatrix{T,M}; tol::Union{Real,Nothing} = nothing) where {T<:Number,M}
dec = qr(A)
tol = isnothing(tol) ? maximum(abs.(dec.R)) * _eps(T) : tol
rank = sum(abs.(Diagonal(dec.R)) .> tol)
Expand All @@ -325,10 +325,10 @@ otherwise uses an SVD and returns a dense matrix (`mode = 1`). Input `A` will be
Tolerance `tol` is used to compute the rank and is automatically set if not provided.
"""
function orthonormal_range(
A::SA.AbstractMatrix{T};
mode::Integer = -1,
tol::Union{Real, Nothing} = nothing
) where {T <: Number}
A::SA.AbstractMatrix{T};
mode::Integer = -1,
tol::Union{Real,Nothing} = nothing
) where {T<:Number}
mode == 1 && SA.issparse(A) && throw(ArgumentError("SVD does not work with sparse matrices, use a dense matrix."))
mode == -1 && (mode = SA.issparse(A) ? 0 : 1)

Expand All @@ -349,7 +349,7 @@ function symmetric_projection(::Type{T}, dim::Integer, n::Integer; partial::Bool
is_sparse = T <: SA.CHOLMOD.VTypes #sparse qr decomposition fails for anything other than Float64 or ComplexF64
P = is_sparse ? SA.spzeros(T, dim^n, dim^n) : zeros(T, dim^n, dim^n)
perms = Combinatorics.permutations(1:n)
for perm in perms
for perm perms
P .+= permutation_matrix(dim, perm; is_sparse)
end
P ./= length(perms)
Expand Down Expand Up @@ -383,22 +383,21 @@ This function returns a generator, which can then be used e.g. in for loops with
entire basis at once. If you need a vector, call `collect` on it.
"""
function n_body_basis(
n::Integer,
n_parties::Integer;
sb::AbstractVector{<:AbstractMatrix} = [pauli(1), pauli(2), pauli(3)],
sparse::Bool = true,
eye::AbstractMatrix = I(size(sb[1], 1))
)
n::Integer,
n_parties::Integer;
sb::AbstractVector{<:AbstractMatrix} = [pauli(1), pauli(2), pauli(3)],
sparse::Bool = true,
eye::AbstractMatrix = I(size(sb[1], 1))
)
(n >= 0 && n_parties >= 2) || throw(ArgumentError("Number of parties must be ≥ 2 and n ≥ 0."))
n <= n_parties || throw(ArgumentError("Number of parties cannot be larger than n."))

sb = sparse ? [SA.sparse.(sb); [eye]] : [sb; [eye]]
nb = length(sb) - 1
idx_eye = length(sb)
(
Base.kron(sb[t]...)
for p in Combinatorics.with_replacement_combinations(1:nb, n)
for t in Combinatorics.multiset_permutations([p; repeat([idx_eye], n_parties - n)], n_parties)
Base.kron(sb[t]...) for p Combinatorics.with_replacement_combinations(1:nb, n) for
t Combinatorics.multiset_permutations([p; repeat([idx_eye], n_parties - n)], n_parties)
)
end
export n_body_basis
Loading

0 comments on commit a009983

Please sign in to comment.