-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
241 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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" | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)), ]) |