Skip to content

Commit

Permalink
Fix some bugs in QantumOperators.
Browse files Browse the repository at this point in the history
  • Loading branch information
waltergu committed Dec 3, 2021
1 parent eb5a893 commit 85eb0ae
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 32 deletions.
63 changes: 32 additions & 31 deletions src/Essentials/QuantumOperators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ using ...Prerequisites.Traits: rawtype, fulltype, parametertype, parameterpairs,

import LaTeXStrings: latexstring
import LinearAlgebra: ishermitian
import ..Essentials: dtype
import ...Interfaces: id, value, rank, add!, sub!, mul!, div!, , , permute
import ...Prerequisites.Traits: contentnames, dissolve, isparameterbound, parameternames

export QuantumOperator, OperatorUnit, ID, OperatorProd, OperatorSum, Scalar, Operator, Operators, LaTeX
export QuantumOperator, OperatorUnit, ID, OperatorProd, OperatorSum, Operator, Operators, LaTeX
export Transformation, Identity, Numericalization, MatrixRepresentation, Permutation, AbstractSubstitution, AbstractUnitSubstitution, UnitSubstitution, RankFilter
export ishermitian, idtype, optype, sequence, latexname, latexformat, superscript, subscript, script, matrix, matrix!

Expand Down Expand Up @@ -166,15 +167,7 @@ abstract type OperatorProd{V, I<:ID{OperatorUnit}} <: QuantumOperator end
M = r₂==0 ? rawtype(M₁) : r₁==0 ? rawtype(M₂) : typejoin(rawtype(M₁), rawtype(M₂))
return fulltype(M, promoteparameters(parameterpairs(M₁), parameterpairs(M₂)))
end

"""
Scalar{V}
Scalar quantum operator.
Type alias for `OperatorProd{V, Tuple{}}`.
"""
const Scalar{V} = OperatorProd{V, Tuple{}}
@inline Base.promote_rule(::Type{M}, ::Type{N}) where {M<:OperatorProd, N<:Number} = reparameter(M, :value, promote_type(valtype(M), N))

"""
rank(::Type{M}) where {M<:OperatorProd} -> Int
Expand All @@ -201,6 +194,15 @@ The type of the id of an `OperatorProd`.
@inline idtype(m::OperatorProd) = idtype(typeof(m))
@inline @generated idtype(::Type{T}) where {T<:OperatorProd} = parametertype(supertype(T, :OperatorProd), :id)

"""
dtype(m::OperatorProd)
dtype(::Type{T}) where {T<:OperatorProd}
The data type of the coefficient of an `OperatorProd`.
"""
@inline dtype(m::OperatorProd) = dtype(typeof(m))
@inline dtype(::Type{T}) where {T<:OperatorProd} = valtype(T)

"""
value(m::OperatorProd) -> valtype(m)
Expand All @@ -215,13 +217,13 @@ Get the id of an `OperatorProd`.
"""
@inline id(m::OperatorProd) = getcontent(m, :id)

@inline newvalue(m::OperatorProd, v::Number) = v
@inline newvalue(m::OperatorProd, v) = v
"""
replace(m::OperatorProd, v::Number) -> OperatorProd
replace(m::OperatorProd, v) -> OperatorProd
Replace the value of an `OperatorProd`.
"""
@inline Base.replace(m::OperatorProd, v::Number) = rawtype(typeof(m))(dissolve(m, newvalue, (v,))...)
@inline Base.replace(m::OperatorProd, v) = rawtype(typeof(m))(dissolve(m, newvalue, (v,))...)
@inline dissolve(m::OperatorProd, ::Val{:value}, ::typeof(newvalue), args::Tuple, kwargs::NamedTuple) = newvalue(m, args...; kwargs...)

"""
Expand Down Expand Up @@ -292,7 +294,7 @@ Get the sequence of the id of a quantum operator according to a table.
"""
@inline function Base.convert(::Type{M}, m::Number) where {M<:OperatorProd}
@assert isa(one(M), M) "convert error: not convertible."
return one(M)*convert(valtype(M), m)
return one(M)*convert(dtype(M), m)
end
@inline function Base.convert(::Type{M}, m::OperatorProd) where {M<:OperatorProd}
(typeof(m) <: M) && return m
Expand Down Expand Up @@ -442,11 +444,11 @@ Get the in-place addition of quantum operators.
"""
@inline add!(ms::OperatorSum) = ms
@inline function add!(ms::OperatorSum, m::Union{Number, OperatorUnit, OperatorProd})
isa(m, Number) && abs(m)==0 && return ms
isa(m, Number) && m==0 && return ms
m = convert(eltype(ms), m)
old = get(ms.contents, id(m), nothing)
new = isnothing(old) ? m : replace(old, value(old)+value(m))
abs(value(new))==0 ? delete!(ms.contents, id(m)) : (ms[id(m)] = new)
value(new)==0 ? delete!(ms.contents, id(m)) : (ms[id(m)] = new)
return ms
end
@inline function add!(ms::OperatorSum, mms::OperatorSum)
Expand All @@ -469,7 +471,7 @@ Get the in-place subtraction of quantum operators.
m = convert(eltype(ms), m)
old = get(ms.contents, id(m), nothing)
new = isnothing(old) ? -m : replace(old, value(old)-value(m))
abs(value(new))==0 ? delete!(ms.contents, id(m)) : (ms[id(m)] = new)
value(new)==0 ? delete!(ms.contents, id(m)) : (ms[id(m)] = new)
return ms
end
@inline function sub!(ms::OperatorSum, mms::OperatorSum)
Expand All @@ -486,10 +488,9 @@ Get the in-place multiplication of an `OperatorSum` with a number.
"""
function mul!(ms::OperatorSum, factor::Number)
abs(factor)==0 && return empty!(ms)
@assert isa(one(ms|>eltype|>valtype)*factor, ms|>eltype|>valtype) "mul! error: mismatched type, $(ms|>eltype) and $(factor|>typeof)."
for m in ms
new = replace(m, value(m)*factor)
abs(value(new))==0 ? delete!(ms.contents, id(m)) : (ms[id(m)] = new)
value(new)==0 ? delete!(ms.contents, id(m)) : (ms[id(m)] = new)
end
return ms
end
Expand All @@ -499,7 +500,7 @@ end
Get the in-place division of an `OperatorSum` with a number.
"""
@inline div!(ms::OperatorSum, factor::Number) = mul!(ms, one(ms|>eltype|>valtype)/factor)
@inline div!(ms::OperatorSum, factor::Number) = mul!(ms, one(dtype(eltype(ms)))/factor)

"""
optype(m::QuantumOperator)
Expand Down Expand Up @@ -578,7 +579,7 @@ end
@inline Base.:*(factor::Number, ms::OperatorSum) = ms * factor
function Base.:*(ms::OperatorSum, factor::Number)
abs(factor)==0 && return zero(ms)
result = OperatorSum{reparameter(eltype(ms), :value, promote_type(valtype(eltype(ms)), typeof(factor)))}()
result = OperatorSum{promote_type(eltype(ms), typeof(factor))}()
for m in ms
add!(result, m*factor)
end
Expand All @@ -593,21 +594,21 @@ end
Overloaded `/` between a quantum operator and a number.
"""
Base.:/(m::QuantumOperator, factor::Number) = m * (one(valtype(optype(m)))/factor)
@inline Base.:/(m::QuantumOperator, factor::Number) = m * (one(dtype(optype(m)))/factor)

"""
//(m::QuantumOperator, factor::Integer) -> QuantumOperator
Overloaded `//` between a quantum operator and an integer.
"""
Base.://(m::QuantumOperator, factor::Integer) = m * (1//factor)
@inline Base.://(m::QuantumOperator, factor::Integer) = m * (1//factor)

"""
^(m::QuantumOperator, n::Integer) -> QuantumOperator
Overloaded `^` between a quantum operator and an integer.
"""
Base.:^(m::QuantumOperator, n::Integer) = (@assert n>0 "^ error: non-positive integers are not allowed."; prod(ntuple(i->m, Val(n)), init=1))
@inline Base.:^(m::QuantumOperator, n::Integer) = (@assert n>0 "^ error: non-positive integers are not allowed."; prod(ntuple(i->m, Val(n)), init=1))

"""
⊗(m::Union{OperatorUnit, OperatorProd}, ms::OperatorSum) -> OperatorSum
Expand All @@ -616,9 +617,9 @@ Base.:^(m::QuantumOperator, n::Integer) = (@assert n>0 "^ error: non-positive in
Overloaded `⊗` between quantum operators.
"""
(m::Union{OperatorUnit, OperatorProd}, ms::OperatorSum) = OperatorSum(collect(m mm for mm in ms))
(ms::OperatorSum, m::Union{OperatorUnit, OperatorProd}) = OperatorSum(collect(mm m for mm in ms))
(ms₁::OperatorSum, ms₂::OperatorSum) = OperatorSum(collect(m₁ m₂ for m₁ in ms₁ for m₂ in ms₂))
@inline (m::Union{OperatorUnit, OperatorProd}, ms::OperatorSum) = OperatorSum(collect(m mm for mm in ms))
@inline (ms::OperatorSum, m::Union{OperatorUnit, OperatorProd}) = OperatorSum(collect(mm m for mm in ms))
@inline (ms₁::OperatorSum, ms₂::OperatorSum) = OperatorSum(collect(m₁ m₂ for m₁ in ms₁ for m₂ in ms₂))

"""
⋅(m::Union{OperatorUnit, OperatorProd}, ms::OperatorSum) -> OperatorSum
Expand All @@ -627,9 +628,9 @@ Overloaded `⊗` between quantum operators.
Overloaded `⋅` between quantum operators.
"""
(m::Union{OperatorUnit, OperatorProd}, ms::OperatorSum) = OperatorSum(collect(m mm for mm in ms))
(ms::OperatorSum, m::Union{OperatorUnit, OperatorProd}) = OperatorSum(collect(mm m for mm in ms))
(ms₁::OperatorSum, ms₂::OperatorSum) = OperatorSum(collect(m₁ m₂ for m₁ in ms₁ for m₂ in ms₂))
@inline (m::Union{OperatorUnit, OperatorProd}, ms::OperatorSum) = OperatorSum(collect(m mm for mm in ms))
@inline (ms::OperatorSum, m::Union{OperatorUnit, OperatorProd}) = OperatorSum(collect(mm m for mm in ms))
@inline (ms₁::OperatorSum, ms₂::OperatorSum) = OperatorSum(collect(m₁ m₂ for m₁ in ms₁ for m₂ in ms₂))

"""
Operators{O<:Operator, I<:ID{OperatorUnit}}
Expand All @@ -639,7 +640,7 @@ A set of operators.
Type alias for `OperatorSum{O<:Operator, I<:ID{OperatorUnit}}`.
"""
const Operators{O<:Operator, I<:ID{OperatorUnit}} = OperatorSum{O, I}
Base.summary(io::IO, opts::Operators) = @printf io "Operators"
@inline Base.summary(io::IO, opts::Operators) = @printf io "Operators"

"""
Operators(opts::Operator...)
Expand Down
2 changes: 1 addition & 1 deletion src/QuantumLattices.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export expand, expand!, decompose, decompose!, permute
export dtype, kind, update, update!, reset!

# Essentials.QuantumOperators
export QuantumOperator, OperatorUnit, ID, OperatorProd, OperatorSum, Scalar, Operator, Operators, ishermitian, idtype, optype, sequence, latexformat
export QuantumOperator, OperatorUnit, ID, OperatorProd, OperatorSum, Operator, Operators, ishermitian, idtype, optype, sequence, latexformat
export Transformation, Identity, Numericalization, MatrixRepresentation, Permutation, UnitSubstitution, RankFilter, matrix, matrix!

# Essentials.QuantumNumbers
Expand Down
3 changes: 3 additions & 0 deletions test/Essentials/QuantumOperators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ using Test
using LaTeXStrings: latexstring
using Printf: @printf, @sprintf
using QuantumLattices.Essentials.QuantumOperators
using QuantumLattices.Essentials: dtype
using QuantumLattices.Interfaces: id, value, rank, add!, sub!, mul!, div!
using QuantumLattices.Prerequisites: Float
using QuantumLattices.Prerequisites.Combinatorics: Combinations
Expand Down Expand Up @@ -81,6 +82,7 @@ end
@test promote_type(Operator{Int}, Operator{Float}) == Operator{Float}
@test promote_type(Operator{Int, ID{AID{Int, Int}, 2}}, Operator{Float, ID{AID{Int, Int}, 2}}) == Operator{Float, ID{AID{Int, Int}, 2}}
@test promote_type(Operator{Int, ID{AID}}, Operator{Float, ID{AID}}) == Operator{Float, <:ID{AID}}
@test promote_type(Operator{Int}, Float) == Operator{Float}

opt = Operator(2.0, AID(1, 1))
@test deepcopy(opt)==opt && isequal(deepcopy(opt), opt)
Expand All @@ -89,6 +91,7 @@ end
@test opt|>rank == opt|>typeof|>rank == 1
@test opt|>valtype == opt|>typeof|>valtype == parametertype(opt|>typeof, :value) == Float
@test opt|>idtype == opt|>typeof|>idtype == parametertype(opt|>typeof, :id) == ID{AID{Int, Int}, 1}
@test opt|>dtype == opt|>typeof|>dtype == Float
@test value(opt) == 2.0
@test id(opt) == ID(AID(1, 1))
@test replace(opt, 3) == replace(opt, value=3) == Operator(3, AID(1, 1))
Expand Down

0 comments on commit 85eb0ae

Please sign in to comment.