Skip to content

Commit 3b7e037

Browse files
committed
Operator expression parsing
1 parent 4ba3e8c commit 3b7e037

File tree

4 files changed

+47
-5
lines changed

4 files changed

+47
-5
lines changed

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ julia> Pkg.add("QuantumOperatorDefinitions")
3232
## Examples
3333

3434
````julia
35-
using QuantumOperatorDefinitions:
36-
OpName, SiteType, StateName, , controlled, op, state
35+
using QuantumOperatorDefinitions: OpName, SiteType, StateName, , controlled, op, state
3736
using LinearAlgebra: Diagonal
3837
using SparseArrays: SparseMatrixCSC, SparseVector
3938
using Test: @test

examples/README.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ julia> Pkg.add("QuantumOperatorDefinitions")
3737

3838
# ## Examples
3939

40-
using QuantumOperatorDefinitions:
41-
OpName, SiteType, StateName, , controlled, op, state
40+
using QuantumOperatorDefinitions: OpName, SiteType, StateName, , controlled, op, state
4241
using LinearAlgebra: Diagonal
4342
using SparseArrays: SparseMatrixCSC, SparseVector
4443
using Test: @test

src/op.jl

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,39 @@ Base.getproperty(n::OpName, name::Symbol) = getfield(params(n), name)
88
OpName{N}(params) where {N} = OpName{N,typeof(params)}(params)
99
OpName{N}(; kwargs...) where {N} = OpName{N}((; kwargs...))
1010

11+
# This compiles operator expressions, such as:
12+
# ```julia
13+
# opexpr("X + Y") == OpName("X") + OpName("Y")
14+
# opexpr("Ry{θ=π/2}") == OpName("Ry"; θ=π/2)
15+
# ```
16+
function opexpr(n::String)
17+
return opexpr(Meta.parse(n))
18+
end
19+
opexpr(n::Number) = n
20+
function opexpr(n::Symbol)
21+
n === :im && return im
22+
n === && return π
23+
return OpName{n}()
24+
end
25+
function opexpr(ex::Expr)
26+
if Meta.isexpr(ex, :call)
27+
return eval(ex.args[1])(opexpr.(ex.args[2:end])...)
28+
end
29+
if Meta.isexpr(ex, :curly)
30+
# Syntax for parametrized gates, i.e.
31+
# `opexpr("Ry{θ=π/2}")`.
32+
params = ex.args[2:end]
33+
kwargs = Dict(
34+
map(params) do param
35+
@assert Meta.isexpr(param, :(=))
36+
return param.args[1] => eval(param.args[2])
37+
end,
38+
)
39+
return OpName{ex.args[1]}(; kwargs...)
40+
end
41+
return error("Can't parse expression $ex.")
42+
end
43+
1144
OpName(s::AbstractString; kwargs...) = OpName{Symbol(s)}(; kwargs...)
1245
OpName(s::Symbol; kwargs...) = OpName{s}(; kwargs...)
1346
name(::OpName{N}) where {N} = N

test/test_basics.jl

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using QuantumOperatorDefinitions: OpName, SiteType, , expand, op, state, nsites
1+
using QuantumOperatorDefinitions: OpName, SiteType, , expand, op, opexpr, state, nsites
22
using LinearAlgebra: Diagonal
33
using Test: @test, @testset
44

@@ -118,4 +118,15 @@ const elts = (real_elts..., complex_elts...)
118118
end
119119
end
120120
end
121+
@testset "Parsing" begin
122+
# TODO: Should this be called in the `OpName`/`op` constructor?
123+
@test Matrix(opexpr("X * Y")) == op("X") * op("Y")
124+
@test Matrix(opexpr("X * Y + Z")) == op("X") * op("Y") + op("Z")
125+
@test Matrix(opexpr("X * Y + 2 * Z")) == op("X") * op("Y") + 2 * op("Z")
126+
@test Matrix(opexpr("exp(im * (X * Y + 2 * Z))")) ==
127+
exp(im * (op("X") * op("Y") + 2 * op("Z")))
128+
@test Matrix(opexpr("exp(im * (X ⊗ Y + Z ⊗ Z))")) ==
129+
exp(im * (kron(op("X"), op("Y")) + kron(op("Z"), op("Z"))))
130+
@test Matrix(opexpr("Ry{θ=π/2}")) == op("Ry"; θ=π / 2)
131+
end
121132
end

0 commit comments

Comments
 (0)