Skip to content

Commit

Permalink
initial draft
Browse files Browse the repository at this point in the history
  • Loading branch information
Roger-luo committed Apr 30, 2021
1 parent fc46d43 commit ece7119
Show file tree
Hide file tree
Showing 6 changed files with 241 additions and 1 deletion.
5 changes: 5 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ uuid = "6769671a-fce8-4286-b3f7-6099e1b1298a"
authors = ["Roger-Luo <[email protected]> and contributors"]
version = "0.1.0"

[deps]
Expronicon = "6b7a57c9-7cc1-4fdf-b7f5-e857abae3636"
MLStyle = "d8e11817-5142-5d16-987a-aa16d5891078"
YaoLocations = "66df03fb-d475-48f7-b449-3d9064bf085b"

[compat]
julia = "1.6.1"

Expand Down
14 changes: 13 additions & 1 deletion src/YaoHIR.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
module YaoHIR

# Write your package code here.
export GenericRoutine, Routine,
IntrinsicRoutine,
Operation,
AdjointOperation,
Chain, Gate, Ctrl

using MLStyle
using Expronicon
using Core: CodeInfo

include("types.jl")
include("intrinsic.jl")
include("printing.jl")

end
63 changes: 63 additions & 0 deletions src/intrinsic.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
macro intrinsic(ex)
esc(intrinsic_m(ex))
end

macro intrinsic(n::Int, ex)
esc(intrinsic_m(ex, n))
end

function intrinsic_m(ex, n::Int=1)
if ex isa Symbol
def = JLStruct(;name=Symbol(ex, :Gate), supertype=IntrinsicRoutine)
binding_name = ex
binding = :(Core.@__doc__ const $ex = $(def.name)())
else
name, args, kw, whereparams, rettype = split_function_head(ex)
kw === nothing || error("cannot have kwargs in intrinsic operation")
rettype === nothing || error("cannot have rettype in intrinsic operation")

typevars=whereparams
fields = JLField[]
for each in args
field = @match each begin
:($fname::$type) => JLField(;name=fname, type)
::Symbol => JLField(;name=each)
_ => error("cannot handle $each")
end
push!(fields, field)
end
def = JLStruct(;name, fields, supertype=IntrinsicRoutine, typevars)
binding_name = name
binding = nothing
end

quote
Core.@__doc__ $(codegen_ast(def))
$(codegen_helpers(def, n, binding_name))
$binding
end
end

nqubits(::Type{T}) where {T <: Routine} = error("YaoHIR.nqubits is not defined for $T")
isintrinsic(::Type{T}) where T = false

function codegen_helpers(def::JLStruct, n::Int, name::Symbol)
quote
$YaoHIR.nqubits(::Type{<:$(def.name)}) = $n
$YaoHIR.isintrinsic(::Type{<:$(def.name)}) = true
$YaoHIR.routine_name(::Type{<:$(def.name)}) = $(QuoteNode(name))
$MLStyle.@as_record $(def.name)
end
end

@intrinsic X
@intrinsic Y
@intrinsic Z
@intrinsic H
@intrinsic S
@intrinsic T
@intrinsic shift::T) where {T <: Real}
@intrinsic Rx::T) where {T <: Real}
@intrinsic Ry::T) where {T <: Real}
@intrinsic Rz::T) where {T <: Real}
@intrinsic UGate::T, β::T, γ::T) where {T <: Real}
45 changes: 45 additions & 0 deletions src/printing.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const COLOR_SCHEME = Dict(:intrinsic => :blue, :routine => :blue)

function print_routine(io::IO, x::IntrinsicRoutine)
print(io, routine_name(x))
fnames = fieldnames(typeof(x))
if !isempty(fnames)
print(io, "(")
for k in 1:length(fnames)
print(io, getfield(x, fnames[k]))
if k != length(fnames)
print(io, ", ")
end
end
print(io, ")")
end
end

Base.show(io::IO, x::IntrinsicRoutine) = print_routine(io, x)

function Base.show(io::IO, ::MIME"text/plain", x::IntrinsicRoutine)
print_routine(io, x)
printstyled(io, " (intrinsic operation)"; color = COLOR_SCHEME[:intrinsic])
end

function Base.show(io::IO, ::GenericRoutine{name}) where {name}
print(io, name)
end

function Base.show(io::IO, ::MIME"text/plain", fn::GenericRoutine{name}) where {name}
print(io, name)
printstyled(
io,
" (generic routine with ",
length(methods(fn).ms),
" methods)";
color = COLOR_SCHEME[:routine],
)
end

function Base.show(io::IO, ::Type{T}) where {name,T<:GenericRoutine{name}}
mod = T.name.module
print(io, "typeof(")
mod === Main || print(io, mod, ".")
print(io, name, ")")
end
108 changes: 108 additions & 0 deletions src/types.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
"""
GenericRoutine{name} <: Function
A `GenericRoutine` cannot be directly execute on a quantum
device. It is a Julia `Function` that returns `Operation`,
and `Operation` can be executed on quanutm device.
!!! note
An instance of `GenericRoutine` should be treated like
`Function`.
"""
abstract type GenericRoutine{name} <: Function end

"""
abstract type Routine end
This defines operations that one can execute on a quantum device.
"""
abstract type Routine end

"""
abstract type IntrinsicRoutine <: Routine end
`IntrinsicRoutine` are the routine that can be executed
by the compile target that is pre-defined in the compiler.
"""
abstract type IntrinsicRoutine <: Routine end

"""
Operation{P, Args} <: Routine
An `Operation` is a user defined composite routine
that can be called in other `Operation` or execute
on target device.
"""
struct Operation{P,Args} <: Routine
parent::P
args::Args
end

"""
AdjointOperation{P} <: Routine
An `AdjointOperation` is the adjoint of another
`Routine`.
"""
struct AdjointOperation{P} <: Routine
parent::P
end

Base.adjoint(x::Routine) = AdjointOperation(x)
Base.adjoint(x::AdjointOperation) = x.parent

routine_name(::Type) = nothing
routine_name(x) = routine_name(typeof(x))
routine_name(::Type{<:GenericRoutine{name}}) where {name} = name
routine_name(::Type{T}) where {T<:IntrinsicRoutine} = nameof(T)
routine_name(::Type{<:Operation{P}}) where {P} = routine_name(P)
routine_name(::Type{<:AdjointOperation{P}}) where {P} = Symbol("adjoint_", routine_name(P))

# this is only a place holder
# we are not using struct because
# singleton types will get const prop
struct MeasureResult{T}
result::T
end

@inline function Base.:(==)(lhs::MeasureResult, rhs)
measure_cmp(lhs, rhs)
end

@inline function Base.:(==)(lhs, rhs::MeasureResult)
measure_cmp(lhs, rhs)
end

@inline function Base.:(==)(lhs::MeasureResult, rhs::MeasureResult)
measure_cmp(lhs, rhs)
end

@noinline function measure_cmp(lhs, rhs)
throw(IntrinsicError("cannot compare measurement result outside @device"))
end

struct Chain <: Routine
args::Vector{Any}
Chain(args...) = new(collect(Any, args))
end

struct Gate <: Routine
operation # SSAValue/Routine
locations # SSAValue/Locations
end

struct Ctrl <: Routine
gate::Gate
ctrl # SSAValue/CtrlLocation
end

struct HIR
parent::CodeInfo
circuit::Chain
end

@as_record Chain
@as_record Gate
@as_record Ctrl
@as_record Operation
@as_record AdjointOperation
7 changes: 7 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
using YaoLocations
using MLStyle
using YaoHIR
using Test

@testset "YaoHIR.jl" begin
# Write your tests here.
end
using YaoHIR: intrinsic_m
intrinsic_m(:X)
intrinsic_m(:(Rx(theta::T) where {T <: Real}))

Chain([Gate(YaoHIR.X, Locations(1)), ])

0 comments on commit ece7119

Please sign in to comment.