Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reorganize and simplify code #2

Merged
merged 3 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "ITensorQuantumOperatorDefinitions"
uuid = "fd9b415b-e710-4e2a-b407-cba023081494"
authors = ["ITensor developers <[email protected]> and contributors"]
version = "0.1.1"
version = "0.1.2"

[deps]
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
Expand Down
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
Loading