Skip to content
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 = "QuantumOperatorDefinitions"
uuid = "826dd319-6fd5-459a-a990-3a4f214664bf"
authors = ["ITensor developers <[email protected]> and contributors"]
version = "0.1.3"
version = "0.1.4"

[deps]
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Expand Down
11 changes: 11 additions & 0 deletions src/op.jl
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,17 @@ end

@op_alias "CCCNOT" "Controlled" ncontrol = 3 op = OpName"X"()

## # 1-qudit rotation around generic axis n̂.
## # exp(-im * α / 2 * n̂ ⋅ σ⃗)
## function (n::OpName"Rn")(domain)
## # TODO: Is this a good parametrization?
## n̂ = (sin(n.θ/2) * cos(n.ϕ), sin(n.θ/2) * sin(n.ϕ/2), cos(n.θ/2))
## σ⃗ = (OpName"X"(domain), OpName"Y"(domain), OpName"Z"(domain))
## n̂σ⃗ = mapreduce(*, +, n̂, σ⃗)
## return cis(-(n.λ/2) * n̂σ⃗)
## end
## @op_alias "Rn̂" "Rn"

# Version of `sign` that returns one
# if `x == 0`.
function nonzero_sign(x)
Expand Down
129 changes: 68 additions & 61 deletions src/sitetypes/qubit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,39 @@ alias(::SiteType"SpinHalf=1/2") = SiteType"Qubit"()

Base.length(::SiteType"Qubit") = 2

(::StateName"↑")(::SiteType"Qubit") = StateName"0"()(2)
(::StateName"Up")(::SiteType"Qubit") = StateName"0"()(2)
# Avoid aliases since these aren't generic
# to Qudits/higher spin.
(::StateName"Z+")(::SiteType"Qubit") = StateName"0"()(2)
(::StateName"Zp")(::SiteType"Qubit") = StateName"0"()(2)
(::StateName"Emp")(::SiteType"Qubit") = StateName"0"()(2)
(::StateName"Zp")(domain::SiteType"Qubit") = StateName"Z+"()(domain)
(::StateName"↑")(domain::SiteType"Qubit") = StateName"Z+"()(domain)
(::StateName"Up")(domain::SiteType"Qubit") = StateName"Z+"()(domain)
(::StateName"Emp")(domain::SiteType"Qubit") = StateName"Z+"()(domain)

(::StateName"↓")(::SiteType"Qubit") = StateName"1"()(2)
(::StateName"Dn")(::SiteType"Qubit") = StateName"1"()(2)
# Avoid aliases since these aren't generic
# to Qudits/higher spin.
(::StateName"Z-")(::SiteType"Qubit") = StateName"1"()(2)
(::StateName"Zm")(::SiteType"Qubit") = StateName"1"()(2)
(::StateName"Occ")(::SiteType"Qubit") = StateName"1"()(2)
(::StateName"Zm")(domain::SiteType"Qubit") = StateName"Z-"()(domain)
(::StateName"↓")(domain::SiteType"Qubit") = StateName"Z-"()(domain)
(::StateName"Dn")(domain::SiteType"Qubit") = StateName"Z-"()(domain)
(::StateName"Occ")(domain::SiteType"Qubit") = StateName"Z-"()(domain)

# `eigvecs(X)`
alias(::StateName"+") = (StateName"0"() + StateName"1"()) / √2
@state_alias "X+" "+"
@state_alias "Xp" "+"
(::StateName"X+")(::SiteType"Qubit") = ((StateName"0"() + StateName"1"()) / √2)(2)
(::StateName"Xp")(domain::SiteType"Qubit") = StateName"X+"()(domain)
(::StateName"+")(domain::SiteType"Qubit") = StateName"X+"()(domain)

alias(::StateName"-") = (StateName"0"() - StateName"1"()) / √2
@state_alias "X-" "-"
@state_alias "Xm" "-"
(::StateName"X-")(::SiteType"Qubit") = ((StateName"0"() - StateName"1"()) / √2)(2)
(::StateName"Xm")(domain::SiteType"Qubit") = StateName"X-"()(domain)
(::StateName"-")(domain::SiteType"Qubit") = StateName"X-"()(domain)

# `eigvecs(Y)`
alias(::StateName"i") = (StateName"0"() + im * StateName"1"()) / √2
@state_alias "Y+" "i"
@state_alias "Yp" "i"
(::StateName"Y+")(::SiteType"Qubit") = ((StateName"0"() + im * StateName"1"()) / √2)(2)
(::StateName"Yp")(domain::SiteType"Qubit") = StateName"Y+"()(domain)
(::StateName"i")(domain::SiteType"Qubit") = StateName"Y+"()(domain)

alias(::StateName"-i") = (StateName"0"() - im * StateName"1"()) / √2
@state_alias "Y-" "-i"
@state_alias "Ym" "-i"
(::StateName"Y-")(::SiteType"Qubit") = ((StateName"0"() - im * StateName"1"()) / √2)(2)
(::StateName"Ym")(domain::SiteType"Qubit") = StateName"Y-"()(domain)
(::StateName"-i")(domain::SiteType"Qubit") = StateName"Y-"()(domain)

# SIC-POVMs
(::StateName"Tetra0")(::SiteType"Qubit") = [
Expand All @@ -55,48 +59,51 @@ alias(::StateName"-i") = (StateName"0"() - im * StateName"1"()) / √2
]

# TODO: Define as `(I + σᶻ) / 2`?
alias(::OpName"ProjUp") = OpName"Proj"(; index=1)
@op_alias "projUp" "ProjUp"
@op_alias "Proj↑" "ProjUp"
@op_alias "proj↑" "ProjUp"
@op_alias "Proj0" "ProjUp"
@op_alias "proj0" "ProjUp"
(::OpName"ProjUp")(::SiteType"Qubit") = OpName"Proj"(; index=1)(2)
(::OpName"projUp")(domain::SiteType"Qubit") = OpName"ProjUp"()(domain)
(::OpName"Proj↑")(domain::SiteType"Qubit") = OpName"ProjUp"()(domain)
(::OpName"proj↑")(domain::SiteType"Qubit") = OpName"ProjUp"()(domain)
(::OpName"Proj0")(domain::SiteType"Qubit") = OpName"ProjUp"()(domain)
(::OpName"proj0")(domain::SiteType"Qubit") = OpName"ProjUp"()(domain)

# TODO: Define as `σ⁺ * σ⁻`?
# TODO: Define as `(I - σᶻ) / 2`?
alias(::OpName"ProjDn") = OpName"Proj"(; index=2)
@op_alias "projDn" "ProjDn"
@op_alias "Proj↓" "ProjDn"
@op_alias "proj↓" "ProjDn"
@op_alias "Proj1" "ProjDn"
@op_alias "proj1" "ProjDn"
(::OpName"ProjDn")(::SiteType"Qubit") = OpName"Proj"(; index=2)(2)
(::OpName"projDn")(domain::SiteType"Qubit") = OpName"ProjDn"()(domain)
(::OpName"Proj↓")(domain::SiteType"Qubit") = OpName"ProjDn"()(domain)
(::OpName"proj↓")(domain::SiteType"Qubit") = OpName"ProjDn"()(domain)
(::OpName"Proj1")(domain::SiteType"Qubit") = OpName"ProjDn"()(domain)
(::OpName"proj1")(domain::SiteType"Qubit") = OpName"ProjDn"()(domain)

# Rotation around generic axis n̂
# exp(-im * n.θ / 2 * n̂ ⋅ σ⃗)
#=
TODO: Define R-gate when `λ == -ϕ`, i.e.:
```julia
function Base.AbstractArray(n::OpName"R", ::Tuple{SiteType"Qubit"})
return [
cos(n.θ / 2) -exp(-im * n.ϕ)*sin(n.θ / 2)
exp(im * n.ϕ)*sin(n.θ / 2) cos(n.θ / 2)
]
end
```
or:
```julia
alias(n::OpName"R") = OpName"Rn"(; θ=n.θ, ϕ=n.ϕ, λ=-n.ϕ)
=#
# https://docs.quantum.ibm.com/api/qiskit/qiskit.circuit.library.UGate
# TODO: Generalize to `"Qudit"`, see:
# https://quantumcomputing.stackexchange.com/questions/16251/how-does-a-general-rotation-r-hatn-theta-related-to-u-3-gate
# https://quantumcomputing.stackexchange.com/questions/4249/decomposition-of-an-arbitrary-1-qubit-gate-into-a-specific-gateset
# https://en.wikipedia.org/wiki/List_of_quantum_logic_gates#Other_named_gates
# https://en.wikipedia.org/wiki/Spin_(physics)#Higher_spins
function (n::OpName"Rn")(::SiteType"Qubit")
return [
cos(n.θ / 2) -exp(im * n.λ)*sin(n.θ / 2)
exp(im * n.ϕ)*sin(n.θ / 2) exp(im * (n.ϕ + n.λ))*cos(n.θ / 2)
]
end
@op_alias "Rn̂" "Rn"
## TODO: Bring this back, decide on names and angle conventions.
## # Related to rotation `"Rn"` around generic axis n̂:
## # exp(-im * n.θ / 2 * n̂ ⋅ σ⃗)
## #=
## TODO: Define R-gate when `λ == -ϕ`, i.e.:
## ```julia
## function Base.AbstractArray(n::OpName"R", ::Tuple{SiteType"Qubit"})
## return [
## cos(n.θ / 2) -exp(-im * n.ϕ)*sin(n.θ / 2)
## exp(im * n.ϕ)*sin(n.θ / 2) cos(n.θ / 2)
## ]
## end
## ```
## or:
## ```julia
## alias(n::OpName"R") = OpName"Rn"(; θ=n.θ, ϕ=n.ϕ, λ=-n.ϕ)
## =#
## # https://docs.quantum.ibm.com/api/qiskit/qiskit.circuit.library.UGate
## # TODO: Generalize to `"Qudit"`, see:
## # https://quantumcomputing.stackexchange.com/questions/16251/how-does-a-general-rotation-r-hatn-theta-related-to-u-3-gate
## # https://quantumcomputing.stackexchange.com/questions/4249/decomposition-of-an-arbitrary-1-qubit-gate-into-a-specific-gateset
## # https://en.wikipedia.org/wiki/List_of_quantum_logic_gates#Other_named_gates
## # https://en.wikipedia.org/wiki/Spin_(physics)#Higher_spins
## # https://qudev.phys.ethz.ch/static/content/courses/QSIT07/presentations/Schmassmann.pdf
## # http://theory.caltech.edu/~preskill/ph219/chap5_15.pdf
## # https://almuhammadi.com/sultan/books_2020/Nielsen_Chuang.pdf (Chapter 4)
## function (n::OpName"GeneralRotation")(::SiteType"Qubit")
## return [
## cos(n.θ / 2) -exp(im * n.λ)*sin(n.θ / 2)
## exp(im * n.ϕ)*sin(n.θ / 2) exp(im * (n.ϕ + n.λ))*cos(n.θ / 2)
## ]
## end
10 changes: 5 additions & 5 deletions src/sitetypes/spinone.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ alias(::SiteType"SpinOne") = SiteType"S=1"()
(::StateName"Z-")(::SiteType"S=1") = [0, 0, 1]

## TODO: Decide on these aliases.
(::StateName"↑")(::SiteType"S=1") = StateName"Z+"()(domain)
(::StateName"Up")(::SiteType"S=1") = StateName"Z+"()(domain)
(::StateName"0")(::SiteType"S=1") = StateName"Z0"()(domain)
(::StateName"↓")(::SiteType"S=1") = StateName"Z-"()(domain)
(::StateName"Dn")(::SiteType"S=1") = StateName"Z-"()(domain)
(::StateName"↑")(domain::SiteType"S=1") = StateName"Z+"()(domain)
(::StateName"Up")(domain::SiteType"S=1") = StateName"Z+"()(domain)
(::StateName"0")(domain::SiteType"S=1") = StateName"Z0"()(domain)
(::StateName"↓")(domain::SiteType"S=1") = StateName"Z-"()(domain)
(::StateName"Dn")(domain::SiteType"S=1") = StateName"Z-"()(domain)

# TODO: Make these more general, define as something like:
# `(n::StateName"X")(::SiteType"S=1") = eigvecs(OpName"X"())[n.eigval]`
Expand Down
13 changes: 9 additions & 4 deletions src/state.jl
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,16 @@ function (n::StateName"StandardBasis")(domain)
a[n.index] = one(Bool)
return a
end
function (n::StateName{N})(domain) where {N}
function (n::StateName{N})(domain...) where {N}
# TODO: Try one alias at a time?
# TODO: First call `alias(n, domain...)`
# to allow for aliases specific to certain
# SiteTypes?
n′ = alias(n)
if n == n′
domain′ = alias.(domain)
if n == n′ && domain′ == domain
index = parse(Int, String(N)) + 1
return StateName"StandardBasis"(; index)(domain)
return StateName"StandardBasis"(; index)(domain...)
end
return n′(domain)
return n′(domain′...)
end
28 changes: 25 additions & 3 deletions test/test_basics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,31 @@ const elts = (real_elts..., complex_elts...)
end

for t in (SiteType("S=1"), SiteType("SpinOne"))
@test state("Z+", SiteType("S=1")) == [1, 0, 0]
@test state("Z0", SiteType("S=1")) == [0, 1, 0]
@test state("Z-", SiteType("S=1")) == [0, 0, 1]
for (ns, x) in (
(("Z+", "↑", "Up"), [1, 0, 0]),
(("Z0", "0"), [0, 1, 0]),
(("Z-", "↓", "Dn"), [0, 0, 1]),
(("X+",), [1 / 2, 1 / sqrt(2), 1 / 2]),
(("X0",), [-1 / sqrt(2), 0, 1 / sqrt(2)]),
(("X-",), [1 / 2, -1 / sqrt(2), 1 / 2]),
(("Y+",), [-1 / 2, -im / sqrt(2), 1 / 2]),
(("Y0",), [1 / sqrt(2), 0, 1 / sqrt(2)]),
(("Y-",), [-1 / 2, im / sqrt(2), 1 / 2]),
)
for n in ns
@test state(n, t) ≈ x
end
end
end

# Check they are eigenvalues
(λ⁺, λ⁰, λ⁻) = (2, 0, -2)
for t in (SiteType("S=1"), SiteType("SpinOne"))
for n in ("X", "Y", "Z")
@test op(n, t) * state("$(n)+", t) ≈ λ⁺ * state("$(n)+", t) atol = eps()
@test op(n, t) * state("$(n)0", t) ≈ λ⁰ * state("$(n)0", t) atol = eps()
@test op(n, t) * state("$(n)-", t) ≈ λ⁻ * state("$(n)-", t) atol = eps()
end
end
end
end