Skip to content

Commit c04f2fc

Browse files
authored
Reorganize and simplify code (#2)
1 parent 871aabb commit c04f2fc

20 files changed

+614
-1119
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "ITensorQuantumOperatorDefinitions"
22
uuid = "fd9b415b-e710-4e2a-b407-cba023081494"
33
authors = ["ITensor developers <[email protected]> and contributors"]
4-
version = "0.1.1"
4+
version = "0.1.2"
55

66
[deps]
77
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"

src/ITensorQuantumOperatorDefinitions.jl

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
module ITensorQuantumOperatorDefinitions
22

33
include("sitetype.jl")
4-
include("ITensorQuantumOperatorDefinitionsChainRulesCoreExt.jl")
4+
include("space.jl")
5+
include("val.jl")
6+
include("state.jl")
7+
include("op.jl")
8+
include("has_fermion_string.jl")
9+
510
include("sitetypes/aliases.jl")
611
include("sitetypes/generic_sites.jl")
712
include("sitetypes/qubit.jl")
@@ -13,4 +18,12 @@ include("sitetypes/tj.jl")
1318
include("sitetypes/qudit.jl")
1419
include("sitetypes/boson.jl")
1520

21+
include("ITensorQuantumOperatorDefinitionsChainRulesCoreExt.jl")
22+
23+
include("itensor/siteinds.jl")
24+
include("itensor/val.jl")
25+
include("itensor/state.jl")
26+
include("itensor/op.jl")
27+
include("itensor/has_fermion_string.jl")
28+
1629
end

src/has_fermion_string.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
has_fermion_string(::OpName, ::SiteType) = nothing

src/itensor/has_fermion_string.jl

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using ITensorBase: Index
2+
3+
has_fermion_string(operator::AbstractArray{<:Number}, s::Index; kwargs...)::Bool = false
4+
5+
function has_fermion_string(opname::AbstractString, s::Index; kwargs...)::Bool
6+
opname = strip(opname)
7+
8+
# Interpret operator names joined by *
9+
# as acting sequentially on the same site
10+
starpos = findfirst(isequal('*'), opname)
11+
if !isnothing(starpos)
12+
op1 = opname[1:prevind(opname, starpos)]
13+
op2 = opname[nextind(opname, starpos):end]
14+
return xor(has_fermion_string(op1, s; kwargs...), has_fermion_string(op2, s; kwargs...))
15+
end
16+
17+
Ntags = length(tags(s))
18+
stypes = _sitetypes(s)
19+
opn = OpName(opname)
20+
for st in stypes
21+
res = has_fermion_string(opn, st)
22+
!isnothing(res) && return res
23+
end
24+
return false
25+
end

src/itensor/op.jl

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
using ITensorBase: Index, ITensor, dag, prime, tags
2+
3+
op(::OpName, ::SiteType, ::Index...; kwargs...) = nothing
4+
function op(
5+
::OpName, ::SiteType, ::SiteType, sitetypes_inds::Union{SiteType,Index}...; kwargs...
6+
)
7+
return nothing
8+
end
9+
10+
_sitetypes(i::Index) = _sitetypes(tags(i))
11+
12+
function commontags(i::Index...)
13+
return union(tags.(i)...)
14+
end
15+
16+
op(X::AbstractArray, s::Index...) = ITensor(X, (prime.(s)..., dag.(s)...))
17+
18+
# TODO: Delete these.
19+
op(opname, s::Vector{<:Index}; kwargs...) = op(opname, s...; kwargs...)
20+
op(s::Vector{<:Index}, opname; kwargs...) = op(opname, s...; kwargs...)
21+
22+
function op(name::AbstractString, s::Index...; adjoint::Bool=false, kwargs...)
23+
name = strip(name)
24+
# TODO: filter out only commons tags
25+
# if there are multiple indices
26+
commontags_s = commontags(s...)
27+
# first we handle the + and - algebra, which requires a space between ops to avoid clashing
28+
name_split = nothing
29+
@ignore_derivatives name_split = String.(split(name, " "))
30+
oplocs = findall(x -> x ("+", "-"), name_split)
31+
if !isempty(oplocs)
32+
@ignore_derivatives !isempty(kwargs) &&
33+
error("Lazy algebra on parametric gates not allowed")
34+
# the string representation of algebra ops: ex ["+", "-", "+"]
35+
labels = name_split[oplocs]
36+
# assign coefficients to each term: ex [+1, -1, +1]
37+
coeffs = [1, [(-1)^Int(label == "-") for label in labels]...]
38+
# grad the name of each operator block separated by an algebra op, and do so by
39+
# making sure blank spaces between opnames are kept when building the new block.
40+
start, opnames = 0, String[]
41+
for oploc in oplocs
42+
finish = oploc
43+
opnames = vcat(
44+
opnames, [prod([name_split[k] * " " for k in (start + 1):(finish - 1)])]
45+
)
46+
start = oploc
47+
end
48+
opnames = vcat(
49+
opnames, [prod([name_split[k] * " " for k in (start + 1):length(name_split)])]
50+
)
51+
# build the vector of blocks and sum
52+
op_list = [
53+
coeff * (op(opname, s...; kwargs...)) for (coeff, opname) in zip(coeffs, opnames)
54+
]
55+
return sum(op_list)
56+
end
57+
# the the multiplication come after
58+
oploc = findfirst("*", name)
59+
if !isnothing(oploc)
60+
op1, op2 = nothing, nothing
61+
@ignore_derivatives begin
62+
op1 = name[1:prevind(name, oploc.start)]
63+
op2 = name[nextind(name, oploc.start):end]
64+
if !(op1[end] == ' ' && op2[1] == ' ')
65+
@warn "($op1*$op2) composite op definition `A*B` deprecated: please use `A * B` instead (with spaces)"
66+
end
67+
end
68+
return product(op(op1, s...; kwargs...), op(op2, s...; kwargs...))
69+
end
70+
common_stypes = _sitetypes(commontags_s)
71+
@ignore_derivatives push!(common_stypes, SiteType("Generic"))
72+
opn = OpName(name)
73+
for st in common_stypes
74+
op_mat = op(opn, st; kwargs...)
75+
if !isnothing(op_mat)
76+
rs = reverse(s)
77+
res = ITensor(op_mat, (prime.(rs)..., dag.(rs)...))
78+
adjoint && return swapprime(dag(res), 0 => 1)
79+
return res
80+
end
81+
end
82+
return throw(
83+
ArgumentError(
84+
"Overload of \"op\" or \"op!\" functions not found for operator name \"$name\" and Index tags: $(tags.(s)).",
85+
),
86+
)
87+
end
88+
89+
function op(opname, s::Vector{<:Index}, ns::NTuple{N,Integer}; kwargs...) where {N}
90+
return op(opname, ntuple(n -> s[ns[n]], Val(N))...; kwargs...)
91+
end
92+
93+
function op(opname, s::Vector{<:Index}, ns::Vararg{Integer}; kwargs...)
94+
return op(opname, s, ns; kwargs...)
95+
end
96+
97+
function op(s::Vector{<:Index}, opname, ns::Tuple{Vararg{Integer}}; kwargs...)
98+
return op(opname, s, ns...; kwargs...)
99+
end
100+
101+
function op(s::Vector{<:Index}, opname, ns::Integer...; kwargs...)
102+
return op(opname, s, ns; kwargs...)
103+
end
104+
105+
function op(s::Vector{<:Index}, opname, ns::Tuple{Vararg{Integer}}, kwargs::NamedTuple)
106+
return op(opname, s, ns; kwargs...)
107+
end
108+
109+
function op(s::Vector{<:Index}, opname, ns::Integer, kwargs::NamedTuple)
110+
return op(opname, s, (ns,); kwargs...)
111+
end
112+
113+
op(s::Vector{<:Index}, o::Tuple) = op(s, o...)
114+
115+
op(o::Tuple, s::Vector{<:Index}) = op(s, o...)
116+
117+
function op(
118+
s::Vector{<:Index},
119+
f::Function,
120+
opname::AbstractString,
121+
ns::Tuple{Vararg{Integer}};
122+
kwargs...,
123+
)
124+
return f(op(opname, s, ns...; kwargs...))
125+
end
126+
127+
function op(
128+
s::Vector{<:Index}, f::Function, opname::AbstractString, ns::Integer...; kwargs...
129+
)
130+
return f(op(opname, s, ns; kwargs...))
131+
end
132+
133+
# Here, Ref is used to not broadcast over the vector of indices
134+
# TODO: consider overloading broadcast for `op` with the example
135+
# here: https://discourse.julialang.org/t/how-to-broadcast-over-only-certain-function-arguments/19274/5
136+
# so that `Ref` isn't needed.
137+
ops(s::Vector{<:Index}, os::AbstractArray) = [op(oₙ, s) for oₙ in os]
138+
ops(os::AbstractVector, s::Vector{<:Index}) = [op(oₙ, s) for oₙ in os]

src/itensor/siteinds.jl

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
using ITensorBase: Index, addtags
2+
3+
function siteind(st::SiteType; addtags="", kwargs...)
4+
sp = space(st; kwargs...)
5+
isnothing(sp) && return nothing
6+
return Index(sp, "Site, $(value(st)), $addtags")
7+
end
8+
9+
function siteind(st::SiteType, n; kwargs...)
10+
s = siteind(st; kwargs...)
11+
!isnothing(s) && return addtags(s, "n=$n")
12+
sp = space(st, n; kwargs...)
13+
isnothing(sp) && error(space_error_message(st))
14+
return Index(sp, "Site, $(value(st)), n=$n")
15+
end
16+
17+
siteind(tag::String; kwargs...) = siteind(SiteType(tag); kwargs...)
18+
19+
siteind(tag::String, n; kwargs...) = siteind(SiteType(tag), n; kwargs...)
20+
21+
# Special case of `siteind` where integer (dim) provided
22+
# instead of a tag string
23+
#siteind(d::Integer, n::Integer; kwargs...) = Index(d, "Site,n=$n")
24+
function siteind(d::Integer, n::Integer; addtags="", kwargs...)
25+
return Index(d, "Site,n=$n, $addtags")
26+
end
27+
28+
siteinds(::SiteType, N; kwargs...) = nothing
29+
30+
"""
31+
siteinds(tag::String, N::Integer; kwargs...)
32+
33+
Create an array of `N` physical site indices of type `tag`.
34+
Keyword arguments can be used to specify quantum number conservation,
35+
see the `space` function corresponding to the site type `tag` for
36+
supported keyword arguments.
37+
38+
# Example
39+
40+
```julia
41+
N = 10
42+
s = siteinds("S=1/2", N; conserve_qns=true)
43+
```
44+
"""
45+
function siteinds(tag::String, N::Integer; kwargs...)
46+
st = SiteType(tag)
47+
48+
si = siteinds(st, N; kwargs...)
49+
if !isnothing(si)
50+
return si
51+
end
52+
53+
return [siteind(st, j; kwargs...) for j in 1:N]
54+
end
55+
56+
"""
57+
siteinds(f::Function, N::Integer; kwargs...)
58+
59+
Create an array of `N` physical site indices where the site type at site `n` is given
60+
by `f(n)` (`f` should return a string).
61+
"""
62+
function siteinds(f::Function, N::Integer; kwargs...)
63+
return [siteind(f(n), n; kwargs...) for n in 1:N]
64+
end
65+
66+
# Special case of `siteinds` where integer (dim)
67+
# provided instead of a tag string
68+
"""
69+
siteinds(d::Integer, N::Integer; kwargs...)
70+
71+
Create an array of `N` site indices, each of dimension `d`.
72+
73+
# Keywords
74+
- `addtags::String`: additional tags to be added to all indices
75+
"""
76+
function siteinds(d::Integer, N::Integer; kwargs...)
77+
return [siteind(d, n; kwargs...) for n in 1:N]
78+
end

src/itensor/state.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using ITensorBase: ITensor, Index, onehot
2+
3+
state(::StateName, ::SiteType, ::Index; kwargs...) = nothing
4+
5+
# Syntax `state("Up", Index(2, "S=1/2"))`
6+
state(sn::String, i::Index; kwargs...) = state(i, sn; kwargs...)
7+
8+
function state(s::Index, name::AbstractString; kwargs...)::ITensor
9+
stypes = _sitetypes(s)
10+
sname = StateName(name)
11+
for st in stypes
12+
v = state(sname, st; kwargs...)
13+
!isnothing(v) && return ITensor(v, (s,))
14+
end
15+
return throw(
16+
ArgumentError(
17+
"Overload of \"state\" functions not found for state name \"$name\" and Index tags $(tags(s))",
18+
),
19+
)
20+
end
21+
22+
state(s::Index, n::Integer) = onehot(s => n)
23+
24+
state(sset::Vector{<:Index}, j::Integer, st; kwargs...) = state(sset[j], st; kwargs...)

src/itensor/val.jl

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using ITensorBase: Index
2+
3+
function val(s::Index, name::AbstractString)::Int
4+
stypes = _sitetypes(s)
5+
sname = ValName(name)
6+
7+
# Try calling val(::StateName"Name",::SiteType"Tag",)
8+
for st in stypes
9+
res = val(sname, st)
10+
!isnothing(res) && return res
11+
end
12+
13+
return throw(
14+
ArgumentError("Overload of \"val\" function not found for Index tags $(tags(s))")
15+
)
16+
end
17+
18+
val(s::Index, n::Integer) = n
19+
20+
val(sset::Vector{<:Index}, j::Integer, st) = val(sset[j], st)

src/op.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# TODO: Add `params<:NamedTuple` field.
2+
struct OpName{Name} end
3+
OpName(s::AbstractString) = OpName{Symbol(s)}()
4+
OpName(s::Symbol) = OpName{s}()
5+
name(::OpName{N}) where {N} = N
6+
macro OpName_str(s)
7+
return OpName{Symbol(s)}
8+
end
9+
10+
# Default implementations of op
11+
op(::OpName; kwargs...) = nothing
12+
op(::OpName, ::SiteType; kwargs...) = nothing
13+
14+
function _sitetypes(ts::Set)
15+
return collect(SiteType, SiteType.(ts))
16+
end
17+
18+
op(name::AbstractString; kwargs...) = error("Must input indices when creating an `op`.")
19+
20+
# To ease calling of other op overloads,
21+
# allow passing a string as the op name
22+
op(opname::AbstractString, t::SiteType; kwargs...) = op(OpName(opname), t; kwargs...)
23+
24+
op(f::Function, args...; kwargs...) = f(op(args...; kwargs...))

0 commit comments

Comments
 (0)