1+ using Random: randstring
2+
13struct OpName{Name,Params}
2- params:: Params
4+ function OpName {Name,Params} (params:: NamedTuple ) where {Name,Params}
5+ return new {Name,(; Params..., params...)} ()
6+ end
37end
4- params (n:: OpName ) = getfield (n, :params )
8+ name (:: OpName{Name} ) where {Name} = Name
9+ params (:: OpName{<:Any,Params} ) where {Params} = Params
510
611Base. getproperty (n:: OpName , name:: Symbol ) = getfield (params (n), name)
712
8- OpName {N} (params) where {N} = OpName {N,typeof(params)} (params)
13+ OpName {Name,Params} (; kwargs... ) where {Name,Params} = OpName {Name,Params} ((; kwargs... ))
14+
15+ OpName {N} (params:: NamedTuple ) where {N} = OpName {N,params} ()
916OpName {N} (; kwargs... ) where {N} = OpName {N} ((; kwargs... ))
1017
18+ const DAGGER_STRING = randstring ()
19+ const UPARROW_STRING = randstring ()
20+ const DOWNARROW_STRING = randstring ()
21+ const OPEXPR_REPLACEMENTS = (
22+ " †" => DAGGER_STRING, " ↑" => UPARROW_STRING, " ↓" => DOWNARROW_STRING
23+ )
24+
1125# This compiles operator expressions, such as:
1226# ```julia
1327# opexpr("X + Y") == OpName("X") + OpName("Y")
1428# opexpr("Ry{θ=π/2}") == OpName("Ry"; θ=π/2)
1529# ```
16- function opexpr (n:: String )
17- return opexpr (Meta. parse (n))
30+ function opexpr (n:: String ; kwargs... )
31+ n = replace (n, OPEXPR_REPLACEMENTS... )
32+ return opexpr (Meta. parse (n); kwargs... )
1833end
1934opexpr (n:: Number ) = n
20- function opexpr (n:: Symbol )
35+ function opexpr (n:: Symbol ; kwargs ... )
2136 n === :im && return im
2237 n === :π && return π
23- return OpName {n} ()
38+ n = Symbol (replace (String (n), reverse .(OPEXPR_REPLACEMENTS)... ))
39+ return OpName {n} (; kwargs... )
2440end
2541function opexpr (ex:: Expr )
2642 if Meta. isexpr (ex, :call )
@@ -41,12 +57,107 @@ function opexpr(ex::Expr)
4157 return error (" Can't parse expression $ex ." )
4258end
4359
60+ # TODO : Should this parse the string?
4461OpName (s:: AbstractString ; kwargs... ) = OpName {Symbol(s)} (; kwargs... )
4562OpName (s:: Symbol ; kwargs... ) = OpName {s} (; kwargs... )
46- name ( :: OpName{N} ) where {N} = N
63+ # TODO : Should this parse the string?
4764macro OpName_str (s)
48- return OpName{Symbol (s)}
65+ return :(OpName{$ (Expr (:quote , Symbol (s)))})
66+ end
67+
68+ # This version parses. Disabled for now until
69+ # it is written better, there is a compelling
70+ # use case, and the name is decided.
71+ # TODO : Write this in terms of expressions, avoid
72+ # `eval`.
73+ # macro opexpr_str(s)
74+ # return :(typeof(opexpr($s)))
75+ # end
76+
77+ for f in (
78+ :(Base. sqrt),
79+ :(Base. real),
80+ :(Base. imag),
81+ :(Base. complex),
82+ :(Base. exp),
83+ :(Base. cis),
84+ :(Base. cos),
85+ :(Base. sin),
86+ :(Base. adjoint),
87+ :(Base.:+ ),
88+ :(Base.:- ),
89+ )
90+ @eval begin
91+ $ f (n:: OpName ) = OpName " f" (; f= $ f, op= n)
92+ end
93+ end
94+
95+ # Unary operations
96+ nsites (n:: OpName"f" ) = nsites (n. op)
97+ function Base. AbstractArray (n:: OpName"f" , domain_size:: Tuple{Vararg{Int}} )
98+ return n. f (AbstractArray (n. op, domain_size))
99+ end
100+
101+ nsites (n:: OpName"^" ) = nsites (n. op)
102+ function Base. AbstractArray (n:: OpName"^" , domain_size:: Tuple{Vararg{Int}} )
103+ return AbstractArray (n. op, domain_size)^ n. exponent
49104end
105+ Base.:^ (n:: OpName , exponent) = OpName " ^" (; op= n, exponent)
106+
107+ nsites (n:: OpName"kron" ) = nsites (n. op1) + nsites (n. op2)
108+ function Base. AbstractArray (n:: OpName"kron" , domain_size:: Tuple{Vararg{Int}} )
109+ domain_size1 = domain_size[1 : nsites (n. op1)]
110+ domain_size2 = domain_size[(nsites (n. op1) + 1 ): end ]
111+ @assert length (domain_size2) == nsites (n. op2)
112+ return kron (AbstractArray (n. op1, domain_size1), AbstractArray (n. op2, domain_size2))
113+ end
114+ Base. kron (n1:: OpName , n2:: OpName ) = OpName " kron" (; op1= n1, op2= n2)
115+ ⊗ (n1:: OpName , n2:: OpName ) = kron (n1, n2)
116+
117+ function nsites (n:: OpName"+" )
118+ @assert nsites (n. op1) == nsites (n. op2)
119+ return nsites (n. op1)
120+ end
121+ function Base. AbstractArray (n:: OpName"+" , domain_size:: Tuple{Vararg{Int}} )
122+ return AbstractArray (n. op1, domain_size) + AbstractArray (n. op2, domain_size)
123+ end
124+ Base.:+ (n1:: OpName , n2:: OpName ) = OpName " +" (; op1= n1, op2= n2)
125+ Base.:- (n1:: OpName , n2:: OpName ) = n1 + (- n2)
126+
127+ function nsites (n:: OpName"*" )
128+ @assert nsites (n. op1) == nsites (n. op2)
129+ return nsites (n. op1)
130+ end
131+ function Base. AbstractArray (n:: OpName"*" , domain_size:: Tuple{Vararg{Int}} )
132+ return AbstractArray (n. op1, domain_size) * AbstractArray (n. op2, domain_size)
133+ end
134+ Base.:* (n1:: OpName , n2:: OpName ) = OpName " *" (; op1= n1, op2= n2)
135+
136+ nsites (n:: OpName"scaled" ) = nsites (n. op)
137+ function Base. AbstractArray (n:: OpName"scaled" , domain_size:: Tuple{Vararg{Int}} )
138+ return AbstractArray (n. op, domain_size) * n. c
139+ end
140+ function Base.:* (c:: Number , n:: OpName )
141+ return OpName " scaled" (; op= n, c)
142+ end
143+ function Base.:* (n:: OpName , c:: Number )
144+ return OpName " scaled" (; op= n, c)
145+ end
146+ function Base.:/ (n:: OpName , c:: Number )
147+ return OpName " scaled" (; op= n, c= inv (c))
148+ end
149+
150+ function Base.:* (c:: Number , n:: OpName"scaled" )
151+ return OpName " scaled" (; op= n. op, c= (c * n. c))
152+ end
153+ function Base.:* (n:: OpName"scaled" , c:: Number )
154+ return OpName " scaled" (; op= n. op, c= (n. c * c))
155+ end
156+ function Base.:/ (n:: OpName"scaled" , c:: Number )
157+ return OpName " scaled" (; op= n. op, c= (n. c / c))
158+ end
159+
160+ controlled (n:: OpName ; ncontrol= 1 ) = OpName " Controlled" (; ncontrol, op= n)
50161
51162function op_alias_expr (name1, name2, pars... )
52163 return :(function alias (n:: OpName{Symbol($name1)} )
@@ -117,7 +228,7 @@ function (arrtype::Type{<:AbstractArray})(n::OpName)
117228end
118229
119230function op (arrtype:: Type{<:AbstractArray} , n:: String , domain... ; kwargs... )
120- return arrtype (OpName (n; kwargs... ), domain... )
231+ return arrtype (opexpr (n; kwargs... ), domain... )
121232end
122233function op (elt:: Type{<:Number} , n:: String , domain... ; kwargs... )
123234 return op (AbstractArray{elt}, n, domain... ; kwargs... )
@@ -136,26 +247,6 @@ function nsites(n::Union{StateName,OpName})
136247 return nsites (n′)
137248end
138249
139- # # TODO : Delete.
140- # # # Default implementations of op
141- # # op(::OpName; kwargs...) = nothing
142- # # op(::OpName, ::SiteType; kwargs...) = nothing
143-
144- function _sitetypes (ts:: Set )
145- return collect (SiteType, SiteType .(ts))
146- end
147-
148- # # TODO : Delete.
149- # # op(name::AbstractString; kwargs...) = error("Must input indices when creating an `op`.")
150-
151- # To ease calling of other op overloads,
152- # allow passing a string as the op name
153- # # TODO : Bring this back?
154- # # op(opname::AbstractString, t::SiteType; kwargs...) = op(OpName(opname), t; kwargs...)
155-
156- # TODO : Bring this back?
157- # op(f::Function, args...; kwargs...) = f(op(args...; kwargs...))
158-
159250using LinearAlgebra: Diagonal
160251function Base. AbstractArray (:: OpName"Id" , domain_size:: Tuple{Int} )
161252 return Diagonal (trues (only (domain_size)))
@@ -214,15 +305,13 @@ function Base.AbstractArray(n::OpName"σ⁺", domain_size::Tuple{Int})
214305 return [2 * δ (i + 1 , j) * √ ((s + 1 ) * (i + j - 1 ) - i * j) for i in 1 : d, j in 1 : d]
215306end
216307alias (:: OpName"S⁺" ) = OpName (" σ⁺" ) / 2
217- @op_alias " S+" " S⁺"
218- @op_alias " Splus" " S+"
219- @op_alias " Sp" " S+"
308+ @op_alias " Splus" " S⁺"
309+ @op_alias " Sp" " S⁺"
220310
221311alias (:: OpName"σ⁻" ) = OpName " σ⁺" ()'
222312alias (:: OpName"S⁻" ) = OpName (" σ⁻" ) / 2
223- @op_alias " S-" " S⁻"
224- @op_alias " Sminus" " S-"
225- @op_alias " Sm" " S-"
313+ @op_alias " Sminus" " S⁻"
314+ @op_alias " Sm" " S⁻"
226315
227316alias (:: OpName"X" ) = (OpName " σ⁺" () + OpName " σ⁻" ()) / 2
228317@op_alias " σx" " X"
@@ -383,91 +472,6 @@ alias(::OpName"√iSWAP") = √(OpName"iSWAP"())
383472# # return op!(o, OpName("RandomUnitary"), st, s...; kwargs...)
384473# # end
385474
386- # Unary operations
387- nsites (n:: OpName"f" ) = nsites (n. op)
388- function Base. AbstractArray (n:: OpName"f" , domain_size:: Tuple{Vararg{Int}} )
389- return n. f (AbstractArray (n. op, domain_size))
390- end
391-
392- for f in (
393- :(Base. sqrt),
394- :(Base. real),
395- :(Base. imag),
396- :(Base. complex),
397- :(Base. exp),
398- :(Base. cis),
399- :(Base. cos),
400- :(Base. sin),
401- :(Base. adjoint),
402- :(Base.:+ ),
403- :(Base.:- ),
404- )
405- @eval begin
406- $ f (n:: OpName ) = OpName " f" (; f= $ f, op= n)
407- end
408- end
409-
410- nsites (n:: OpName"^" ) = nsites (n. op)
411- function Base. AbstractArray (n:: OpName"^" , domain_size:: Tuple{Vararg{Int}} )
412- return AbstractArray (n. op, domain_size)^ n. exponent
413- end
414- Base.:^ (n:: OpName , exponent) = OpName " ^" (; op= n, exponent)
415-
416- nsites (n:: OpName"kron" ) = nsites (n. op1) + nsites (n. op2)
417- function Base. AbstractArray (n:: OpName"kron" , domain_size:: Tuple{Vararg{Int}} )
418- domain_size1 = domain_size[1 : nsites (n. op1)]
419- domain_size2 = domain_size[(nsites (n. op1) + 1 ): end ]
420- @assert length (domain_size2) == nsites (n. op2)
421- return kron (AbstractArray (n. op1, domain_size1), AbstractArray (n. op2, domain_size2))
422- end
423- Base. kron (n1:: OpName , n2:: OpName ) = OpName " kron" (; op1= n1, op2= n2)
424- ⊗ (n1:: OpName , n2:: OpName ) = kron (n1, n2)
425-
426- function nsites (n:: OpName"+" )
427- @assert nsites (n. op1) == nsites (n. op2)
428- return nsites (n. op1)
429- end
430- function Base. AbstractArray (n:: OpName"+" , domain_size:: Tuple{Vararg{Int}} )
431- return AbstractArray (n. op1, domain_size) + AbstractArray (n. op2, domain_size)
432- end
433- Base.:+ (n1:: OpName , n2:: OpName ) = OpName " +" (; op1= n1, op2= n2)
434- Base.:- (n1:: OpName , n2:: OpName ) = n1 + (- n2)
435-
436- function nsites (n:: OpName"*" )
437- @assert nsites (n. op1) == nsites (n. op2)
438- return nsites (n. op1)
439- end
440- function Base. AbstractArray (n:: OpName"*" , domain_size:: Tuple{Vararg{Int}} )
441- return AbstractArray (n. op1, domain_size) * AbstractArray (n. op2, domain_size)
442- end
443- Base.:* (n1:: OpName , n2:: OpName ) = OpName " *" (; op1= n1, op2= n2)
444-
445- nsites (n:: OpName"scaled" ) = nsites (n. op)
446- function Base. AbstractArray (n:: OpName"scaled" , domain_size:: Tuple{Vararg{Int}} )
447- return AbstractArray (n. op, domain_size) * n. c
448- end
449- function Base.:* (c:: Number , n:: OpName )
450- return OpName " scaled" (; op= n, c)
451- end
452- function Base.:* (n:: OpName , c:: Number )
453- return OpName " scaled" (; op= n, c)
454- end
455- function Base.:/ (n:: OpName , c:: Number )
456- return OpName " scaled" (; op= n, c= inv (c))
457- end
458-
459- function Base.:* (c:: Number , n:: OpName"scaled" )
460- return OpName " scaled" (; op= n. op, c= (c * n. c))
461- end
462- function Base.:* (n:: OpName"scaled" , c:: Number )
463- return OpName " scaled" (; op= n. op, c= (n. c * c))
464- end
465- function Base.:/ (n:: OpName"scaled" , c:: Number )
466- return OpName " scaled" (; op= n. op, c= (n. c / c))
467- end
468-
469- controlled (n:: OpName ; ncontrol= 1 ) = OpName " Controlled" (; ncontrol, op= n)
470-
471475# Expand the operator in a new basis.
472476using LinearAlgebra: ⋅
473477function expand (v:: AbstractArray , basis)
0 commit comments