Skip to content

Commit

Permalink
Reorganize and simplify code
Browse files Browse the repository at this point in the history
  • Loading branch information
mtfishman committed Jan 20, 2025
1 parent 871aabb commit 21b1e78
Show file tree
Hide file tree
Showing 18 changed files with 613 additions and 1,081 deletions.
15 changes: 14 additions & 1 deletion src/ITensorQuantumOperatorDefinitions.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
module ITensorQuantumOperatorDefinitions

include("sitetype.jl")
include("ITensorQuantumOperatorDefinitionsChainRulesCoreExt.jl")
include("space.jl")
include("val.jl")
include("state.jl")
include("op.jl")
include("has_fermion_string.jl")

include("sitetypes/aliases.jl")
include("sitetypes/generic_sites.jl")
include("sitetypes/qubit.jl")
Expand All @@ -13,4 +18,12 @@ include("sitetypes/tj.jl")
include("sitetypes/qudit.jl")
include("sitetypes/boson.jl")

include("ITensorQuantumOperatorDefinitionsChainRulesCoreExt.jl")

include("itensor/siteinds.jl")
include("itensor/val.jl")
include("itensor/state.jl")
include("itensor/op.jl")
include("itensor/has_fermion_string.jl")

end
1 change: 1 addition & 0 deletions src/has_fermion_string.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
has_fermion_string(::OpName, ::SiteType) = nothing

Check warning on line 1 in src/has_fermion_string.jl

View check run for this annotation

Codecov / codecov/patch

src/has_fermion_string.jl#L1

Added line #L1 was not covered by tests
25 changes: 25 additions & 0 deletions src/itensor/has_fermion_string.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using ITensorBase: Index

has_fermion_string(operator::AbstractArray{<:Number}, s::Index; kwargs...)::Bool = false

Check warning on line 3 in src/itensor/has_fermion_string.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/has_fermion_string.jl#L3

Added line #L3 was not covered by tests

function has_fermion_string(opname::AbstractString, s::Index; kwargs...)::Bool
opname = strip(opname)

Check warning on line 6 in src/itensor/has_fermion_string.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/has_fermion_string.jl#L5-L6

Added lines #L5 - L6 were not covered by tests

# Interpret operator names joined by *
# as acting sequentially on the same site
starpos = findfirst(isequal('*'), opname)
if !isnothing(starpos)
op1 = opname[1:prevind(opname, starpos)]
op2 = opname[nextind(opname, starpos):end]
return xor(has_fermion_string(op1, s; kwargs...), has_fermion_string(op2, s; kwargs...))

Check warning on line 14 in src/itensor/has_fermion_string.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/has_fermion_string.jl#L10-L14

Added lines #L10 - L14 were not covered by tests
end

Ntags = length(tags(s))
stypes = _sitetypes(s)
opn = OpName(opname)
for st in stypes
res = has_fermion_string(opn, st)
!isnothing(res) && return res
end
return false

Check warning on line 24 in src/itensor/has_fermion_string.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/has_fermion_string.jl#L17-L24

Added lines #L17 - L24 were not covered by tests
end
138 changes: 138 additions & 0 deletions src/itensor/op.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
using ITensorBase: Index, ITensor, dag, prime, tags

op(::OpName, ::SiteType, ::Index...; kwargs...) = nothing
function op(

Check warning on line 4 in src/itensor/op.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/op.jl#L3-L4

Added lines #L3 - L4 were not covered by tests
::OpName, ::SiteType, ::SiteType, sitetypes_inds::Union{SiteType,Index}...; kwargs...
)
return nothing

Check warning on line 7 in src/itensor/op.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/op.jl#L7

Added line #L7 was not covered by tests
end

_sitetypes(i::Index) = _sitetypes(tags(i))

function commontags(i::Index...)
return union(tags.(i)...)
end

op(X::AbstractArray, s::Index...) = ITensor(X, (prime.(s)..., dag.(s)...))

Check warning on line 16 in src/itensor/op.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/op.jl#L16

Added line #L16 was not covered by tests

# TODO: Delete these.
op(opname, s::Vector{<:Index}; kwargs...) = op(opname, s...; kwargs...)
op(s::Vector{<:Index}, opname; kwargs...) = op(opname, s...; kwargs...)

Check warning on line 20 in src/itensor/op.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/op.jl#L19-L20

Added lines #L19 - L20 were not covered by tests

function op(name::AbstractString, s::Index...; adjoint::Bool=false, kwargs...)
name = strip(name)
# TODO: filter out only commons tags
# if there are multiple indices
commontags_s = commontags(s...)
# first we handle the + and - algebra, which requires a space between ops to avoid clashing
name_split = nothing
@ignore_derivatives name_split = String.(split(name, " "))
oplocs = findall(x -> x ("+", "-"), name_split)
if !isempty(oplocs)
@ignore_derivatives !isempty(kwargs) &&

Check warning on line 32 in src/itensor/op.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/op.jl#L32

Added line #L32 was not covered by tests
error("Lazy algebra on parametric gates not allowed")
# the string representation of algebra ops: ex ["+", "-", "+"]
labels = name_split[oplocs]

Check warning on line 35 in src/itensor/op.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/op.jl#L35

Added line #L35 was not covered by tests
# assign coefficients to each term: ex [+1, -1, +1]
coeffs = [1, [(-1)^Int(label == "-") for label in labels]...]

Check warning on line 37 in src/itensor/op.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/op.jl#L37

Added line #L37 was not covered by tests
# grad the name of each operator block separated by an algebra op, and do so by
# making sure blank spaces between opnames are kept when building the new block.
start, opnames = 0, String[]
for oploc in oplocs
finish = oploc
opnames = vcat(

Check warning on line 43 in src/itensor/op.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/op.jl#L40-L43

Added lines #L40 - L43 were not covered by tests
opnames, [prod([name_split[k] * " " for k in (start + 1):(finish - 1)])]
)
start = oploc
end
opnames = vcat(

Check warning on line 48 in src/itensor/op.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/op.jl#L46-L48

Added lines #L46 - L48 were not covered by tests
opnames, [prod([name_split[k] * " " for k in (start + 1):length(name_split)])]
)
# build the vector of blocks and sum
op_list = [

Check warning on line 52 in src/itensor/op.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/op.jl#L52

Added line #L52 was not covered by tests
coeff * (op(opname, s...; kwargs...)) for (coeff, opname) in zip(coeffs, opnames)
]
return sum(op_list)

Check warning on line 55 in src/itensor/op.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/op.jl#L55

Added line #L55 was not covered by tests
end
# the the multiplication come after
oploc = findfirst("*", name)
if !isnothing(oploc)
op1, op2 = nothing, nothing
@ignore_derivatives begin
op1 = name[1:prevind(name, oploc.start)]
op2 = name[nextind(name, oploc.start):end]
if !(op1[end] == ' ' && op2[1] == ' ')
@warn "($op1*$op2) composite op definition `A*B` deprecated: please use `A * B` instead (with spaces)"

Check warning on line 65 in src/itensor/op.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/op.jl#L60-L65

Added lines #L60 - L65 were not covered by tests
end
end
return product(op(op1, s...; kwargs...), op(op2, s...; kwargs...))

Check warning on line 68 in src/itensor/op.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/op.jl#L68

Added line #L68 was not covered by tests
end
common_stypes = _sitetypes(commontags_s)
@ignore_derivatives push!(common_stypes, SiteType("Generic"))
opn = OpName(name)
for st in common_stypes
op_mat = op(opn, st; kwargs...)
if !isnothing(op_mat)
rs = reverse(s)
res = ITensor(op_mat, (prime.(rs)..., dag.(rs)...))
adjoint && return swapprime(dag(res), 0 => 1)
return res
end
end
return throw(

Check warning on line 82 in src/itensor/op.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/op.jl#L81-L82

Added lines #L81 - L82 were not covered by tests
ArgumentError(
"Overload of \"op\" or \"op!\" functions not found for operator name \"$name\" and Index tags: $(tags.(s)).",
),
)
end

function op(opname, s::Vector{<:Index}, ns::NTuple{N,Integer}; kwargs...) where {N}
return op(opname, ntuple(n -> s[ns[n]], Val(N))...; kwargs...)

Check warning on line 90 in src/itensor/op.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/op.jl#L89-L90

Added lines #L89 - L90 were not covered by tests
end

function op(opname, s::Vector{<:Index}, ns::Vararg{Integer}; kwargs...)
return op(opname, s, ns; kwargs...)

Check warning on line 94 in src/itensor/op.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/op.jl#L93-L94

Added lines #L93 - L94 were not covered by tests
end

function op(s::Vector{<:Index}, opname, ns::Tuple{Vararg{Integer}}; kwargs...)
return op(opname, s, ns...; kwargs...)

Check warning on line 98 in src/itensor/op.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/op.jl#L97-L98

Added lines #L97 - L98 were not covered by tests
end

function op(s::Vector{<:Index}, opname, ns::Integer...; kwargs...)
return op(opname, s, ns; kwargs...)

Check warning on line 102 in src/itensor/op.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/op.jl#L101-L102

Added lines #L101 - L102 were not covered by tests
end

function op(s::Vector{<:Index}, opname, ns::Tuple{Vararg{Integer}}, kwargs::NamedTuple)
return op(opname, s, ns; kwargs...)

Check warning on line 106 in src/itensor/op.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/op.jl#L105-L106

Added lines #L105 - L106 were not covered by tests
end

function op(s::Vector{<:Index}, opname, ns::Integer, kwargs::NamedTuple)
return op(opname, s, (ns,); kwargs...)

Check warning on line 110 in src/itensor/op.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/op.jl#L109-L110

Added lines #L109 - L110 were not covered by tests
end

op(s::Vector{<:Index}, o::Tuple) = op(s, o...)

Check warning on line 113 in src/itensor/op.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/op.jl#L113

Added line #L113 was not covered by tests

op(o::Tuple, s::Vector{<:Index}) = op(s, o...)

Check warning on line 115 in src/itensor/op.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/op.jl#L115

Added line #L115 was not covered by tests

function op(

Check warning on line 117 in src/itensor/op.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/op.jl#L117

Added line #L117 was not covered by tests
s::Vector{<:Index},
f::Function,
opname::AbstractString,
ns::Tuple{Vararg{Integer}};
kwargs...,
)
return f(op(opname, s, ns...; kwargs...))

Check warning on line 124 in src/itensor/op.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/op.jl#L124

Added line #L124 was not covered by tests
end

function op(

Check warning on line 127 in src/itensor/op.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/op.jl#L127

Added line #L127 was not covered by tests
s::Vector{<:Index}, f::Function, opname::AbstractString, ns::Integer...; kwargs...
)
return f(op(opname, s, ns; kwargs...))

Check warning on line 130 in src/itensor/op.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/op.jl#L130

Added line #L130 was not covered by tests
end

# Here, Ref is used to not broadcast over the vector of indices
# TODO: consider overloading broadcast for `op` with the example
# here: https://discourse.julialang.org/t/how-to-broadcast-over-only-certain-function-arguments/19274/5
# so that `Ref` isn't needed.
ops(s::Vector{<:Index}, os::AbstractArray) = [op(oₙ, s) for oₙ in os]
ops(os::AbstractVector, s::Vector{<:Index}) = [op(oₙ, s) for oₙ in os]

Check warning on line 138 in src/itensor/op.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/op.jl#L137-L138

Added lines #L137 - L138 were not covered by tests
78 changes: 78 additions & 0 deletions src/itensor/siteinds.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using ITensorBase: Index, addtags

function siteind(st::SiteType; addtags="", kwargs...)
sp = space(st; kwargs...)
isnothing(sp) && return nothing
return Index(sp, "Site, $(value(st)), $addtags")
end

function siteind(st::SiteType, n; kwargs...)
s = siteind(st; kwargs...)
!isnothing(s) && return addtags(s, "n=$n")
sp = space(st, n; kwargs...)
isnothing(sp) && error(space_error_message(st))
return Index(sp, "Site, $(value(st)), n=$n")

Check warning on line 14 in src/itensor/siteinds.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/siteinds.jl#L12-L14

Added lines #L12 - L14 were not covered by tests
end

siteind(tag::String; kwargs...) = siteind(SiteType(tag); kwargs...)

siteind(tag::String, n; kwargs...) = siteind(SiteType(tag), n; kwargs...)

Check warning on line 19 in src/itensor/siteinds.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/siteinds.jl#L19

Added line #L19 was not covered by tests

# Special case of `siteind` where integer (dim) provided
# instead of a tag string
#siteind(d::Integer, n::Integer; kwargs...) = Index(d, "Site,n=$n")
function siteind(d::Integer, n::Integer; addtags="", kwargs...)
return Index(d, "Site,n=$n, $addtags")

Check warning on line 25 in src/itensor/siteinds.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/siteinds.jl#L24-L25

Added lines #L24 - L25 were not covered by tests
end

siteinds(::SiteType, N; kwargs...) = nothing

"""
siteinds(tag::String, N::Integer; kwargs...)
Create an array of `N` physical site indices of type `tag`.
Keyword arguments can be used to specify quantum number conservation,
see the `space` function corresponding to the site type `tag` for
supported keyword arguments.
# Example
```julia
N = 10
s = siteinds("S=1/2", N; conserve_qns=true)
```
"""
function siteinds(tag::String, N::Integer; kwargs...)
st = SiteType(tag)

si = siteinds(st, N; kwargs...)
if !isnothing(si)
return si

Check warning on line 50 in src/itensor/siteinds.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/siteinds.jl#L50

Added line #L50 was not covered by tests
end

return [siteind(st, j; kwargs...) for j in 1:N]
end

"""
siteinds(f::Function, N::Integer; kwargs...)
Create an array of `N` physical site indices where the site type at site `n` is given
by `f(n)` (`f` should return a string).
"""
function siteinds(f::Function, N::Integer; kwargs...)
return [siteind(f(n), n; kwargs...) for n in 1:N]

Check warning on line 63 in src/itensor/siteinds.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/siteinds.jl#L62-L63

Added lines #L62 - L63 were not covered by tests
end

# Special case of `siteinds` where integer (dim)
# provided instead of a tag string
"""
siteinds(d::Integer, N::Integer; kwargs...)
Create an array of `N` site indices, each of dimension `d`.
# Keywords
- `addtags::String`: additional tags to be added to all indices
"""
function siteinds(d::Integer, N::Integer; kwargs...)
return [siteind(d, n; kwargs...) for n in 1:N]

Check warning on line 77 in src/itensor/siteinds.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/siteinds.jl#L76-L77

Added lines #L76 - L77 were not covered by tests
end
24 changes: 24 additions & 0 deletions src/itensor/state.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using ITensorBase: ITensor, Index, onehot

state(::StateName, ::SiteType, ::Index; kwargs...) = nothing

Check warning on line 3 in src/itensor/state.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/state.jl#L3

Added line #L3 was not covered by tests

# Syntax `state("Up", Index(2, "S=1/2"))`
state(sn::String, i::Index; kwargs...) = state(i, sn; kwargs...)

function state(s::Index, name::AbstractString; kwargs...)::ITensor
stypes = _sitetypes(s)
sname = StateName(name)
for st in stypes
v = state(sname, st; kwargs...)
!isnothing(v) && return ITensor(v, (s,))
end
return throw(

Check warning on line 15 in src/itensor/state.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/state.jl#L14-L15

Added lines #L14 - L15 were not covered by tests
ArgumentError(
"Overload of \"state\" functions not found for state name \"$name\" and Index tags $(tags(s))",
),
)
end

state(s::Index, n::Integer) = onehot(s => n)

Check warning on line 22 in src/itensor/state.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/state.jl#L22

Added line #L22 was not covered by tests

state(sset::Vector{<:Index}, j::Integer, st; kwargs...) = state(sset[j], st; kwargs...)

Check warning on line 24 in src/itensor/state.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/state.jl#L24

Added line #L24 was not covered by tests
20 changes: 20 additions & 0 deletions src/itensor/val.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using ITensorBase: Index

function val(s::Index, name::AbstractString)::Int
stypes = _sitetypes(s)
sname = ValName(name)

# Try calling val(::StateName"Name",::SiteType"Tag",)
for st in stypes
res = val(sname, st)
!isnothing(res) && return res
end

Check warning on line 11 in src/itensor/val.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/val.jl#L11

Added line #L11 was not covered by tests

return throw(

Check warning on line 13 in src/itensor/val.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/val.jl#L13

Added line #L13 was not covered by tests
ArgumentError("Overload of \"val\" function not found for Index tags $(tags(s))")
)
end

val(s::Index, n::Integer) = n

Check warning on line 18 in src/itensor/val.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/val.jl#L18

Added line #L18 was not covered by tests

val(sset::Vector{<:Index}, j::Integer, st) = val(sset[j], st)

Check warning on line 20 in src/itensor/val.jl

View check run for this annotation

Codecov / codecov/patch

src/itensor/val.jl#L20

Added line #L20 was not covered by tests
24 changes: 24 additions & 0 deletions src/op.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# TODO: Add `params<:NamedTuple` field.
struct OpName{Name} end
OpName(s::AbstractString) = OpName{Symbol(s)}()
OpName(s::Symbol) = OpName{s}()
name(::OpName{N}) where {N} = N

Check warning on line 5 in src/op.jl

View check run for this annotation

Codecov / codecov/patch

src/op.jl#L4-L5

Added lines #L4 - L5 were not covered by tests
macro OpName_str(s)
return OpName{Symbol(s)}
end

# Default implementations of op
op(::OpName; kwargs...) = nothing
op(::OpName, ::SiteType; kwargs...) = nothing

Check warning on line 12 in src/op.jl

View check run for this annotation

Codecov / codecov/patch

src/op.jl#L11-L12

Added lines #L11 - L12 were not covered by tests

function _sitetypes(ts::Set)
return collect(SiteType, SiteType.(ts))
end

op(name::AbstractString; kwargs...) = error("Must input indices when creating an `op`.")

Check warning on line 18 in src/op.jl

View check run for this annotation

Codecov / codecov/patch

src/op.jl#L18

Added line #L18 was not covered by tests

# To ease calling of other op overloads,
# allow passing a string as the op name
op(opname::AbstractString, t::SiteType; kwargs...) = op(OpName(opname), t; kwargs...)

Check warning on line 22 in src/op.jl

View check run for this annotation

Codecov / codecov/patch

src/op.jl#L22

Added line #L22 was not covered by tests

op(f::Function, args...; kwargs...) = f(op(args...; kwargs...))

Check warning on line 24 in src/op.jl

View check run for this annotation

Codecov / codecov/patch

src/op.jl#L24

Added line #L24 was not covered by tests
Loading

0 comments on commit 21b1e78

Please sign in to comment.