Skip to content

Instantly share code, notes, and snippets.

@jlapeyre
Created May 16, 2022 15:50
Show Gist options
  • Save jlapeyre/a906b7cec6c556104cd1e06422367a33 to your computer and use it in GitHub Desktop.
Save jlapeyre/a906b7cec6c556104cd1e06422367a33 to your computer and use it in GitHub Desktop.
using MacroTools
using MacroTools: striplines
###
### Macros
###
"""
@qc code
Translate every expression of the form
`f.g(args...)` to `add!(f, g, args...)`.
For example, it translates `circ.cx(i, j)` to `add!(circ, cx, i, j)`.
In case there is code inside the block of this form (i.e. `q.r(args...)`
where `q` is *not* of type `Circ`, we have defined a fallback method for `add!`
to translate back to the meaning of the original syntax.
"""
macro qc(ex)
return _qcirc(ex)
end
"""
@qc circ code
Translate every expression of the form `g(args...)` to `add!(circ,
g, args...)`. For example, it translates `cx(i, j)` to `add!(circ, cx, i, j)`.
"""
macro qc(incirc, ex)
_qcirc(incirc, ex)
end
function _qcirc(ex)
MacroTools.postwalk(ex) do x
(@capture(x, f_.g_(args__))) || return x
return :(add!($f, $g, $(args...)))
end
end
const GateList = (:x, :sx, :y, :z, :h, :cx, :s, :sdg, :t, :tdg, :u, :u3, :rx, :ry, :rz, :rzx, :u4)
function _qcirc(incirc, ex)
MacroTools.postwalk(ex) do x
(@capture(x, f_(args__)) && f in GateList) || return x
return :(add!($incirc, $f, $(args...)))
end
end
###
### Circ: a dummy circuit type
###
struct Circ{T}
data::Vector{T}
end
Circ() = Circ([])
function Base.show(io::IO, m::MIME"text/plain", circ::Circ)
println(io, "Circ with data:")
show(io, m, circ.data)
end
add!(circ::Circ, gate, args...) = (push!(circ.data, gate(args...)); circ)
# Restore original syntax in the generic case
add!(x, y, args...) = x.y(args...)
# Another option is the following
#add!(x, y, args...) = y(x, args...) # standard dot call meaning
for gate in (:x, :h, :cx)
@eval ($gate)(args...) = ($(QuoteNode(gate)), args...)
end
# paramaterized gates
for (gate, nparams) in ((:rz, 1), (:ry, 1))
@eval ($gate)(args...) = (($(QuoteNode(gate)), args[1:$nparams]...), args[$nparams+1:end]...)
end
###
### Examples
###
@show x(1)
@show cx(2, 3)
@show rz(0.5, 1)
circ = Circ()
k = 1
@qc begin
circ.h(k).x(1)
foreach(i -> circ.h(i), 1:3)
foreach(i -> circ.cx(i[1],i[2]), zip(1:2, 2:3))
end
@show circ
i = -1
j = -1
circ = Circ()
@qc circ begin
i = 2
j = 3
x(i)
h(j)
cx(j, i)
end
@show circ
i = -1
j = -1
circ = Circ()
@qc circ begin
x(i)
h(j)
cx(j, i)
end
@show circ
@jlapeyre
Copy link
Author

Running circmacro_examples.jl gives:

x(1) = (:x, 1)
cx(2, 3) = (:cx, 2, 3)
rz(0.5, 1) = ((:rz, 0.5), 1)
circ = Circ{Any}(Any[(:h, 1), (:x, 1), (:h, 1), (:h, 2), (:h, 3), (:cx, 1, 2), (:cx, 2, 3)])
circ = Circ{Any}(Any[(:x, 2), (:h, 3), (:cx, 3, 2)])
circ = Circ{Any}(Any[(:x, -1), (:h, -1), (:cx, -1, -1)])

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment