From 5a9d91c00c6f73d220e0aeff4954ac23f591f0d9 Mon Sep 17 00:00:00 2001 From: Arsh <184517@nith.ac.in> Date: Wed, 19 May 2021 21:11:02 +0530 Subject: [PATCH 01/12] Better optional arguments syntax --- src/YaoBlocksQobj.jl | 3 ++- src/qobj.jl | 52 ++++++++++++++++++-------------------------- test/runtests.jl | 2 +- 3 files changed, 24 insertions(+), 33 deletions(-) diff --git a/src/YaoBlocksQobj.jl b/src/YaoBlocksQobj.jl index a336e81..45c0a1b 100644 --- a/src/YaoBlocksQobj.jl +++ b/src/YaoBlocksQobj.jl @@ -1,7 +1,8 @@ module YaoBlocksQobj -export create_qobj +export convert_to_qobj +using IBMQClient using IBMQClient.Schema using YaoBlocks diff --git a/src/qobj.jl b/src/qobj.jl index da514df..a4e0605 100644 --- a/src/qobj.jl +++ b/src/qobj.jl @@ -1,7 +1,15 @@ using Random +IBMQClient.@option struct ExpOptions + id::String + header::IBMQClient.Maybe{Dict} = nothing + nshots::Int = 1024 + exp_header::IBMQClient.Maybe{Vector} = nothing + exp_config::IBMQClient.Maybe{Vector} = nothing +end + """ - create_qobj(qc, id, header, nshots, exp_header, exp_config) +convert_to_qobj(qc, id, header, nshots, exp_header, exp_config) Creates a `Qobj` based on the IBMQClient schema. @@ -20,10 +28,13 @@ using Random - `exp_config` (optional): An Array of Configuration structure for user settings that can be different in each experiment. These will override the configuration settings of the whole job. """ -function create_qobj(qc::Array{<:AbstractBlock{N}}; id::String = randstring(), header = nothing, nshots::Int = 1024, exp_header = nothing, exp_config = nothing) where N - experiments = create_experiment(qc, exp_header, exp_config) - config = ExpConfig(shots = nshots, memory_slots = length(experiments)) - Qobj(;qobj_id = id, type = "QASM", schema_version = v"1", header, experiments = experiments, config = config) + +convert_to_qobj(qc::Vector{<:AbstractBlock}; kw...) = convert_to_qobj(qc, ExpOptions(;kw...)) + +function convert_to_qobj(qc::Vector{<:AbstractBlock{N}}, options::ExpOptions) where N + experiments = create_experiment(qc, options.exp_header, options.exp_config) + config = ExpConfig(shots = options.nshots, memory_slots = length(experiments)) #from the schema + Qobj(;qobj_id = options.id, type = "QASM", schema_version = v"1", options.header, experiments, config) end """ @@ -41,33 +52,12 @@ end - `exp_config` (optional): An Array of Configuration structure for user settings that can be different in each experiment. These will override the configuration settings of the whole job. """ -function create_experiment(qc::Array{<:AbstractBlock{N}}, exp_header = nothing, exp_config = nothing) where N - experiments = Experiment[] - head = false - config = false - if exp_header !== nothing - head = true - elseif exp_config !== nothing - config = true - end - - for i in 1:length(qc) - if head && config - exp = create_experiment!(qc[i], exp_header[i], exp_config[i]) - elseif head && !config - exp = create_experiment!(qc[i], exp_header[i], exp_config) - elseif !head && config - exp = create_experiment!(qc[i], exp_header, exp_config[i]) - else - exp = create_experiment!(qc[i], exp_header, exp_config) - end - - push!(experiments, exp) - end - return experiments -end +create_experiment(qc::Vector{<:AbstractBlock{N}}, exp_header::Nothing, exp_config::Nothing) where N = collect(create_experiment!(qc[i], nothing, nothing) for i in 1:length(qc)) +create_experiment(qc::Vector{<:AbstractBlock{N}}, exp_header::Array, exp_config::Array) where N = collect(create_experiment!(qc[i], exp_header[i], exp_config[i]) for i in 1:length(qc)) +create_experiment(qc::Vector{<:AbstractBlock{N}}, exp_header::Nothing, exp_config::Array) where N = collect(create_experiment!(qc[i], nothing, exp_config[i]) for i in 1:length(qc)) +create_experiment(qc::Vector{<:AbstractBlock{N}}, exp_header::Array, exp_config::Nothing) where N = collect(create_experiment!(qc[i], exp_header[i], nothing) for i in 1:length(qc)) -function create_experiment!(qc::AbstractBlock{N}, exp_header = nothing, exp_config = nothing) where N +function create_experiment!(qc::AbstractBlock{N}, exp_header, exp_config) where N exp_inst = generate_inst(qc) experiment = Experiment(;header = exp_header, config = exp_config, instructions = exp_inst) return experiment diff --git a/test/runtests.jl b/test/runtests.jl index a2373fa..8d42c4d 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -14,7 +14,7 @@ include("qobjtoqbir.jl") exp_header = [Dict("description"=>"1"), Dict("description"=>"2")] circuits = [qc, qc1] - q = create_qobj(circuits, id = "test", header = header, exp_header = exp_header) + q = convert_to_qobj(circuits, id = "test", header = header, exp_header = exp_header) experiments = q.experiments for i in 1:length(experiments) From 0fe632a77ccbc26c605aee2f61737702824dc2d2 Mon Sep 17 00:00:00 2001 From: Arsh <184517@nith.ac.in> Date: Wed, 19 May 2021 21:36:28 +0530 Subject: [PATCH 02/12] use UUID instead of randstring --- Project.toml | 2 +- src/qobj.jl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Project.toml b/Project.toml index 9f84a41..8de30ec 100644 --- a/Project.toml +++ b/Project.toml @@ -5,7 +5,7 @@ version = "0.1.0" [deps] IBMQClient = "02860bad-daa6-4506-8736-4a3616c18085" -Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" YaoBlocks = "418bc28f-b43b-5e0b-a6e7-61bbc1a2c1df" [compat] diff --git a/src/qobj.jl b/src/qobj.jl index a4e0605..c6865b7 100644 --- a/src/qobj.jl +++ b/src/qobj.jl @@ -1,7 +1,7 @@ -using Random +using UUIDs IBMQClient.@option struct ExpOptions - id::String + id::String = uuid1() header::IBMQClient.Maybe{Dict} = nothing nshots::Int = 1024 exp_header::IBMQClient.Maybe{Vector} = nothing From eb7fd9feb4e9a60373623704e66be1130785517d Mon Sep 17 00:00:00 2001 From: Arsh <184517@nith.ac.in> Date: Wed, 19 May 2021 21:54:50 +0530 Subject: [PATCH 03/12] Use configurations.jl --- Project.toml | 1 + src/YaoBlocksQobj.jl | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 8de30ec..0388734 100644 --- a/Project.toml +++ b/Project.toml @@ -4,6 +4,7 @@ authors = ["Arsh Sharma and contributors"] version = "0.1.0" [deps] +Comfigurations = "5218b696-f38b-4ac9-8b61-a12ec717816d" IBMQClient = "02860bad-daa6-4506-8736-4a3616c18085" UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" YaoBlocks = "418bc28f-b43b-5e0b-a6e7-61bbc1a2c1df" diff --git a/src/YaoBlocksQobj.jl b/src/YaoBlocksQobj.jl index 45c0a1b..5886e33 100644 --- a/src/YaoBlocksQobj.jl +++ b/src/YaoBlocksQobj.jl @@ -2,7 +2,7 @@ module YaoBlocksQobj export convert_to_qobj -using IBMQClient +using Configurations using IBMQClient.Schema using YaoBlocks From 100dd195669c169c86f12f1f4e0f86fd244eed3d Mon Sep 17 00:00:00 2001 From: Arsh <184517@nith.ac.in> Date: Wed, 19 May 2021 21:55:10 +0530 Subject: [PATCH 04/12] Add type specification --- src/qobj.jl | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/qobj.jl b/src/qobj.jl index c6865b7..0899aa4 100644 --- a/src/qobj.jl +++ b/src/qobj.jl @@ -1,11 +1,11 @@ -using UUIDs +using Configurations, UUIDs -IBMQClient.@option struct ExpOptions - id::String = uuid1() - header::IBMQClient.Maybe{Dict} = nothing +@option struct ExpOptions + id::String = "$(uuid1())" + header::Maybe{Dict{String, Any}} = nothing nshots::Int = 1024 - exp_header::IBMQClient.Maybe{Vector} = nothing - exp_config::IBMQClient.Maybe{Vector} = nothing + exp_header::Maybe{Vector{Dict{String, Any}}} = nothing + exp_config::Maybe{Vector{Dict{String, Any}}} = nothing end """ @@ -52,12 +52,12 @@ end - `exp_config` (optional): An Array of Configuration structure for user settings that can be different in each experiment. These will override the configuration settings of the whole job. """ -create_experiment(qc::Vector{<:AbstractBlock{N}}, exp_header::Nothing, exp_config::Nothing) where N = collect(create_experiment!(qc[i], nothing, nothing) for i in 1:length(qc)) -create_experiment(qc::Vector{<:AbstractBlock{N}}, exp_header::Array, exp_config::Array) where N = collect(create_experiment!(qc[i], exp_header[i], exp_config[i]) for i in 1:length(qc)) -create_experiment(qc::Vector{<:AbstractBlock{N}}, exp_header::Nothing, exp_config::Array) where N = collect(create_experiment!(qc[i], nothing, exp_config[i]) for i in 1:length(qc)) -create_experiment(qc::Vector{<:AbstractBlock{N}}, exp_header::Array, exp_config::Nothing) where N = collect(create_experiment!(qc[i], exp_header[i], nothing) for i in 1:length(qc)) +create_experiment(qc::Vector{<:AbstractBlock{N}}, exp_header::Nothing, exp_config::Nothing) where N = collect(create_experiment(qc[i], nothing, nothing) for i in 1:length(qc)) +create_experiment(qc::Vector{<:AbstractBlock{N}}, exp_header::Array, exp_config::Array) where N = collect(create_experiment(qc[i], exp_header[i], exp_config[i]) for i in 1:length(qc)) +create_experiment(qc::Vector{<:AbstractBlock{N}}, exp_header::Nothing, exp_config::Array) where N = collect(create_experiment(qc[i], nothing, exp_config[i]) for i in 1:length(qc)) +create_experiment(qc::Vector{<:AbstractBlock{N}}, exp_header::Array, exp_config::Nothing) where N = collect(create_experiment(qc[i], exp_header[i], nothing) for i in 1:length(qc)) -function create_experiment!(qc::AbstractBlock{N}, exp_header, exp_config) where N +function create_experiment(qc::AbstractBlock{N}, exp_header, exp_config) where N exp_inst = generate_inst(qc) experiment = Experiment(;header = exp_header, config = exp_config, instructions = exp_inst) return experiment From d3b19eb3a4d085716e1cc63793e89f456730faa6 Mon Sep 17 00:00:00 2001 From: Arsh <184517@nith.ac.in> Date: Wed, 19 May 2021 21:56:42 +0530 Subject: [PATCH 05/12] Run formatter --- docs/make.jl | 25 +++++------ src/qobj.jl | 107 +++++++++++++++++++++++++++++++++------------ test/qobjtoqbir.jl | 88 +++++++++++++++++++++---------------- test/runtests.jl | 27 +++++++----- 4 files changed, 157 insertions(+), 90 deletions(-) diff --git a/docs/make.jl b/docs/make.jl index b1aa1c0..f1cf725 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -4,21 +4,16 @@ indigo = DocThemeIndigo.install(YaoBlocksQobj) makedocs(; - modules=[YaoBlocksQobj], - authors="Arsh Sharma and contributors", - repo="https://github.com/QuantumBFS/YaoBlocksQobj.jl/blob/{commit}{path}#{line}", - sitename="YaoBlocksQobj.jl", - format=Documenter.HTML(; - prettyurls=get(ENV, "CI", "false") == "true", - canonical="https://QuantumBFS.github.io/YaoBlocksQobj.jl", - assets=String[indigo, "assets/default.css"], + modules = [YaoBlocksQobj], + authors = "Arsh Sharma and contributors", + repo = "https://github.com/QuantumBFS/YaoBlocksQobj.jl/blob/{commit}{path}#{line}", + sitename = "YaoBlocksQobj.jl", + format = Documenter.HTML(; + prettyurls = get(ENV, "CI", "false") == "true", + canonical = "https://QuantumBFS.github.io/YaoBlocksQobj.jl", + assets = String[indigo, "assets/default.css"], ), - pages=[ - "Quickstart" => "index.md", - "API References" => "refs.md", - ], + pages = ["Quickstart" => "index.md", "API References" => "refs.md"], ) -deploydocs(; - repo="github.com/QuantumBFS/YaoBlocksQobj.jl",devbranch = "main", -) +deploydocs(; repo = "github.com/QuantumBFS/YaoBlocksQobj.jl", devbranch = "main") diff --git a/src/qobj.jl b/src/qobj.jl index 0899aa4..d10da60 100644 --- a/src/qobj.jl +++ b/src/qobj.jl @@ -2,10 +2,10 @@ using Configurations, UUIDs @option struct ExpOptions id::String = "$(uuid1())" - header::Maybe{Dict{String, Any}} = nothing + header::Maybe{Dict{String,Any}} = nothing nshots::Int = 1024 - exp_header::Maybe{Vector{Dict{String, Any}}} = nothing - exp_config::Maybe{Vector{Dict{String, Any}}} = nothing + exp_header::Maybe{Vector{Dict{String,Any}}} = nothing + exp_config::Maybe{Vector{Dict{String,Any}}} = nothing end """ @@ -29,12 +29,20 @@ convert_to_qobj(qc, id, header, nshots, exp_header, exp_config) experiment. These will override the configuration settings of the whole job. """ -convert_to_qobj(qc::Vector{<:AbstractBlock}; kw...) = convert_to_qobj(qc, ExpOptions(;kw...)) +convert_to_qobj(qc::Vector{<:AbstractBlock}; kw...) = + convert_to_qobj(qc, ExpOptions(; kw...)) -function convert_to_qobj(qc::Vector{<:AbstractBlock{N}}, options::ExpOptions) where N +function convert_to_qobj(qc::Vector{<:AbstractBlock{N}}, options::ExpOptions) where {N} experiments = create_experiment(qc, options.exp_header, options.exp_config) config = ExpConfig(shots = options.nshots, memory_slots = length(experiments)) #from the schema - Qobj(;qobj_id = options.id, type = "QASM", schema_version = v"1", options.header, experiments, config) + Qobj(; + qobj_id = options.id, + type = "QASM", + schema_version = v"1", + options.header, + experiments, + config, + ) end """ @@ -52,14 +60,32 @@ end - `exp_config` (optional): An Array of Configuration structure for user settings that can be different in each experiment. These will override the configuration settings of the whole job. """ -create_experiment(qc::Vector{<:AbstractBlock{N}}, exp_header::Nothing, exp_config::Nothing) where N = collect(create_experiment(qc[i], nothing, nothing) for i in 1:length(qc)) -create_experiment(qc::Vector{<:AbstractBlock{N}}, exp_header::Array, exp_config::Array) where N = collect(create_experiment(qc[i], exp_header[i], exp_config[i]) for i in 1:length(qc)) -create_experiment(qc::Vector{<:AbstractBlock{N}}, exp_header::Nothing, exp_config::Array) where N = collect(create_experiment(qc[i], nothing, exp_config[i]) for i in 1:length(qc)) -create_experiment(qc::Vector{<:AbstractBlock{N}}, exp_header::Array, exp_config::Nothing) where N = collect(create_experiment(qc[i], exp_header[i], nothing) for i in 1:length(qc)) - -function create_experiment(qc::AbstractBlock{N}, exp_header, exp_config) where N +create_experiment( + qc::Vector{<:AbstractBlock{N}}, + exp_header::Nothing, + exp_config::Nothing, +) where {N} = collect(create_experiment(qc[i], nothing, nothing) for i = 1:length(qc)) +create_experiment( + qc::Vector{<:AbstractBlock{N}}, + exp_header::Array, + exp_config::Array, +) where {N} = + collect(create_experiment(qc[i], exp_header[i], exp_config[i]) for i = 1:length(qc)) +create_experiment( + qc::Vector{<:AbstractBlock{N}}, + exp_header::Nothing, + exp_config::Array, +) where {N} = collect(create_experiment(qc[i], nothing, exp_config[i]) for i = 1:length(qc)) +create_experiment( + qc::Vector{<:AbstractBlock{N}}, + exp_header::Array, + exp_config::Nothing, +) where {N} = collect(create_experiment(qc[i], exp_header[i], nothing) for i = 1:length(qc)) + +function create_experiment(qc::AbstractBlock{N}, exp_header, exp_config) where {N} exp_inst = generate_inst(qc) - experiment = Experiment(;header = exp_header, config = exp_config, instructions = exp_inst) + experiment = + Experiment(; header = exp_header, config = exp_config, instructions = exp_inst) return experiment end @@ -70,7 +96,7 @@ end - `qc`: A `ChainBlock`(circuit that is to be run). """ -function generate_inst(qc::AbstractBlock{N}) where N +function generate_inst(qc::AbstractBlock{N}) where {N} inst = Instruction[] generate_inst!(inst, basicstyle(qc), [0:N-1...], Int[]) return inst @@ -87,11 +113,16 @@ function generate_inst!(inst, blk::PutBlock{N,M}, locs, controls) where {N,M} end function generate_inst!(inst, blk::ControlBlock{N,GT,C}, locs, controls) where {N,GT,C} - any(==(0),blk.ctrl_config) && error("Inverse Control used in Control gate context") - generate_inst!(inst, blk.content, sublocs(blk.locs, locs), [controls..., sublocs(blk.ctrl_locs, locs)...]) + any(==(0), blk.ctrl_config) && error("Inverse Control used in Control gate context") + generate_inst!( + inst, + blk.content, + sublocs(blk.locs, locs), + [controls..., sublocs(blk.ctrl_locs, locs)...], + ) end -function generate_inst!(inst, m::YaoBlocks.Measure{N}, locs, controls) where N +function generate_inst!(inst, m::YaoBlocks.Measure{N}, locs, controls) where {N} # memory: List of memory slots in which to store the measurement results (mustbe the same length as qubits). mlocs = sublocs(m.locations isa AllLocs ? [1:N...] : [m.locations...], locs) (m.operator isa ComputationalBasis) || error("measuring an operator is not supported") @@ -102,11 +133,23 @@ end # IBMQ Chip only supports ["id", "u1", "u2", "u3", "cx"] # x, y, z and control x, y, z, id, t, swap and other primitive gates -for (GT, NAME, MAXC) in [(:XGate, "x", 2), (:YGate, "y", 2), (:ZGate, "z", 2), - (:I2Gate, "id", 0), (:TGate, "t", 0), (:SWAPGate, "swap", 0)] +for (GT, NAME, MAXC) in [ + (:XGate, "x", 2), + (:YGate, "y", 2), + (:ZGate, "z", 2), + (:I2Gate, "id", 0), + (:TGate, "t", 0), + (:SWAPGate, "swap", 0), +] @eval function generate_inst!(inst, ::$GT, locs, controls) if length(controls) <= $MAXC - push!(inst, Gate(name = "c"^(length(controls))*$NAME, qubits = [controls..., locs...])) + push!( + inst, + Gate( + name = "c"^(length(controls)) * $NAME, + qubits = [controls..., locs...], + ), + ) else error("too many control bits!") end @@ -114,15 +157,23 @@ for (GT, NAME, MAXC) in [(:XGate, "x", 2), (:YGate, "y", 2), (:ZGate, "z", 2), end # rotation gates -for (GT, NAME, PARAMS, MAXC) in [(:(RotationGate{1, T, XGate} where T), "u3", :([b.theta, -π/2, π/2]), 0), - (:(RotationGate{1, T, YGate} where T), "u3", :([b.theta, 0, 0]), 0), - (:(RotationGate{1, T, ZGate} where T), "u1", :([b.theta]), 0), - (:(ShiftGate), "u1", :([b.theta]), 1), - (:(HGate), "u2", :([0, π]), 0), - ] +for (GT, NAME, PARAMS, MAXC) in [ + (:(RotationGate{1,T,XGate} where {T}), "u3", :([b.theta, -π / 2, π / 2]), 0), + (:(RotationGate{1,T,YGate} where {T}), "u3", :([b.theta, 0, 0]), 0), + (:(RotationGate{1,T,ZGate} where {T}), "u1", :([b.theta]), 0), + (:(ShiftGate), "u1", :([b.theta]), 1), + (:(HGate), "u2", :([0, π]), 0), +] @eval function generate_inst!(inst, b::$GT, locs, controls) if length(controls) <= $MAXC - push!(inst, Gate(name = "c"^(length(controls))*$NAME, qubits = [controls..., locs...], params = $PARAMS)) + push!( + inst, + Gate( + name = "c"^(length(controls)) * $NAME, + qubits = [controls..., locs...], + params = $PARAMS, + ), + ) else error("too many control bits! got $controls (length > $($(MAXC)))") end @@ -132,5 +183,5 @@ end sublocs(subs, locs) = [locs[i] for i in subs] function basicstyle(blk::AbstractBlock) - YaoBlocks.Optimise.simplify(blk, rules=[YaoBlocks.Optimise.to_basictypes]) + YaoBlocks.Optimise.simplify(blk, rules = [YaoBlocks.Optimise.to_basictypes]) end diff --git a/test/qobjtoqbir.jl b/test/qobjtoqbir.jl index cece470..9467aca 100644 --- a/test/qobjtoqbir.jl +++ b/test/qobjtoqbir.jl @@ -17,49 +17,56 @@ end Base.:(==)(u1_1::U1, u1_2::U1) = u1_1.lambda == u1_2.lambda Base.:(==)(u2_1::U2, u2_2::U2) = u2_1.phi == u2_2.phi && u2_1.lambda == u2_2.lambda -Base.:(==)(u3_1::U3, u3_2::U3) = u3_1.theta == u3_2.theta && u3_1.phi == u3_2.phi && u3_1.lambda == u3_2.lambda +Base.:(==)(u3_1::U3, u3_2::U3) = + u3_1.theta == u3_2.theta && u3_1.phi == u3_2.phi && u3_1.lambda == u3_2.lambda -function Yao.mat(::Type{T}, u1::U1) where T +function Yao.mat(::Type{T}, u1::U1) where {T} λ = u1.lambda - - T[1 0; - 0 exp(im*λ)] + + T[ + 1 0 + 0 exp(im * λ) + ] end -function Yao.mat(::Type{T}, u2::U2) where T +function Yao.mat(::Type{T}, u2::U2) where {T} ϕ, λ = u2.phi, u2.lambda - - T[1/√2 (-exp(im*λ))/√2; - (exp(im*ϕ))/√2 (exp(im*(ϕ+λ)))/√2] + + T[ + 1/√2 (-exp(im * λ))/√2 + (exp(im * ϕ))/√2 (exp(im * (ϕ + λ)))/√2 + ] end -function Yao.mat(::Type{T}, u3::U3) where T +function Yao.mat(::Type{T}, u3::U3) where {T} θ, ϕ, λ = u3.theta, u3.phi, u3.lambda - - T[cos(θ/2) -sin(θ/2)*exp(im*λ) ; - sin(θ/2)*exp(im*ϕ) cos(θ/2)*exp(im*(ϕ+λ))] + + T[ + cos(θ / 2) -sin(θ / 2)*exp(im * λ) + sin(θ / 2)*exp(im * ϕ) cos(θ / 2)*exp(im * (ϕ + λ)) + ] end -Yao.iparams_eltype(::U1{T}) where T = T -Yao.iparams_eltype(::U2{T}) where T = T -Yao.iparams_eltype(::U3{T}) where T = T +Yao.iparams_eltype(::U1{T}) where {T} = T +Yao.iparams_eltype(::U2{T}) where {T} = T +Yao.iparams_eltype(::U3{T}) where {T} = T -Yao.getiparams(u1::U1{T}) where T = (u1.lambda) -Yao.getiparams(u2::U2{T}) where T = (u2.phi, u2.lambda) -Yao.getiparams(u3::U3{T}) where T = (u3.theta, u3.phi, u3.lambda) +Yao.getiparams(u1::U1{T}) where {T} = (u1.lambda) +Yao.getiparams(u2::U2{T}) where {T} = (u2.phi, u2.lambda) +Yao.getiparams(u3::U3{T}) where {T} = (u3.theta, u3.phi, u3.lambda) -function Yao.setiparams!(u1::U1{T}, λ) where T +function Yao.setiparams!(u1::U1{T}, λ) where {T} u1.lambda = λ return u1 end -function Yao.setiparams!(u2::U2{T}, ϕ, λ) where T +function Yao.setiparams!(u2::U2{T}, ϕ, λ) where {T} u2.phi = ϕ u2.lambda = λ return u2 end -function Yao.setiparams!(u3::U3{T}, θ, ϕ, λ) where T +function Yao.setiparams!(u3::U3{T}, θ, ϕ, λ) where {T} u3.theta = θ u3.phi = ϕ u3.lambda = λ @@ -71,22 +78,29 @@ YaoBlocks.@dumpload_fallback U2 U2 YaoBlocks.@dumpload_fallback U3 U3 function inst2qbir(inst) - n = maximum(x->maximum(x.qubits), inst) + 1 - chain(n, map(inst) do x - name, locs = x.name, x.qubits .+ 1 - nc = 0 - while name[nc+1] == 'c' && nc 0 - control(n, locs[1:nc], locs[nc+1:end]=>name_index(name[nc+1:end], x.params)) - else - put(n, locs=>name_index(name, x.params)) - end - end) + n = maximum(x -> maximum(x.qubits), inst) + 1 + chain( + n, + map(inst) do x + name, locs = x.name, x.qubits .+ 1 + nc = 0 + while name[nc+1] == 'c' && nc < length(name) + nc += 1 + end + if nc > 0 + control( + n, + locs[1:nc], + locs[nc+1:end] => name_index(name[nc+1:end], x.params), + ) + else + put(n, locs => name_index(name, x.params)) + end + end, + ) end -function name_index(name, params=nothing) +function name_index(name, params = nothing) if name == "u1" U1(params...) elseif name == "u2" @@ -96,7 +110,7 @@ function name_index(name, params=nothing) U2(params...) end elseif name == "u3" - if isapprox(params[2], -π/2) && isapprox(params[3], π/2) + if isapprox(params[2], -π / 2) && isapprox(params[3], π / 2) Rx(params[1]) elseif params[2] == 0 && params[3] == 0 Ry(params[1]) diff --git a/test/runtests.jl b/test/runtests.jl index 8d42c4d..35e216a 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -4,20 +4,27 @@ using Test include("qobjtoqbir.jl") @testset "YaoBlocksQobj.jl" begin - qc = chain(3, put(1=>X), put(2=>Y) ,put(3=>Z), - put(2=>T), swap(1,2), put(3=>Ry(0.7)), - control(2, 1=>Y), control(3, 2=>Z)) - qc1 = chain(3, put(3=>Rx(0.7)), - control(2, 1=>Y), control(3, 2=>Z)) + qc = chain( + 3, + put(1 => X), + put(2 => Y), + put(3 => Z), + put(2 => T), + swap(1, 2), + put(3 => Ry(0.7)), + control(2, 1 => Y), + control(3, 2 => Z), + ) + qc1 = chain(3, put(3 => Rx(0.7)), control(2, 1 => Y), control(3, 2 => Z)) + + header = Dict("description" => "test circuits") + exp_header = [Dict("description" => "1"), Dict("description" => "2")] - header = Dict("description"=>"test circuits") - exp_header = [Dict("description"=>"1"), Dict("description"=>"2")] - circuits = [qc, qc1] q = convert_to_qobj(circuits, id = "test", header = header, exp_header = exp_header) - + experiments = q.experiments - for i in 1:length(experiments) + for i = 1:length(experiments) exp = experiments[i] @test exp isa YaoBlocksQobj.Schema.Experiment @test exp.header == Dict("description" => "$i") From 78231f785d5aff2eab53b07cde9086a42fae9aa7 Mon Sep 17 00:00:00 2001 From: Arsh <184517@nith.ac.in> Date: Wed, 19 May 2021 22:00:11 +0530 Subject: [PATCH 06/12] Format doc strings --- src/qobj.jl | 58 ++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/qobj.jl b/src/qobj.jl index d10da60..12f4580 100644 --- a/src/qobj.jl +++ b/src/qobj.jl @@ -9,24 +9,24 @@ using Configurations, UUIDs end """ -convert_to_qobj(qc, id, header, nshots, exp_header, exp_config) + convert_to_qobj(qc, id, header, nshots, exp_header, exp_config) - Creates a `Qobj` based on the IBMQClient schema. +Creates a `Qobj` based on the IBMQClient schema. - - `qc`: An `Array` of `ChainBlock`(circuits that are to be run). - - `id`(optional): User generated run identifier. - - `header` (optional): User-defined structure that contains metadata on the job and is not used. - - `nshots`: Number of times to repeat the experiment (for some simulators this may - be limited to 1, e.g., a unitary simulator). - Each unitary gate has an efficient representation in this basis. - - `exp_header`(optional): Array of User-defined structure that contains metadata on each experiment and - is not used by the backend. The header will be passed through to the result data structure unchanged. - For example, this may contain a fitting parameters for the experiment. In addition, this header can - contain a mapping of backend memory and backend qubits to OpenQASM registers. - This is because an OpenQASM circuit may contain multiple classical and quantum registers, - but Qobj flattens them into a single memory and single set of qubits. - - `exp_config` (optional): An Array of Configuration structure for user settings that can be different in each - experiment. These will override the configuration settings of the whole job. +- `qc`: An `Array` of `ChainBlock`(circuits that are to be run). +- `id`(optional): User generated run identifier. +- `header` (optional): User-defined structure that contains metadata on the job and is not used. +- `nshots`: Number of times to repeat the experiment (for some simulators this may +be limited to 1, e.g., a unitary simulator). +Each unitary gate has an efficient representation in this basis. +- `exp_header`(optional): Array of User-defined structure that contains metadata on each experiment and +is not used by the backend. The header will be passed through to the result data structure unchanged. +For example, this may contain a fitting parameters for the experiment. In addition, this header can +contain a mapping of backend memory and backend qubits to OpenQASM registers. +This is because an OpenQASM circuit may contain multiple classical and quantum registers, +but Qobj flattens them into a single memory and single set of qubits. +- `exp_config` (optional): An Array of Configuration structure for user settings that can be different in each +experiment. These will override the configuration settings of the whole job. """ convert_to_qobj(qc::Vector{<:AbstractBlock}; kw...) = @@ -48,17 +48,17 @@ end """ create_experiment(qc, exp_header, exp_config) - Returns and experiment type that consits of instructions. - - - `qc`: An `Array` of `ChainBlock`(circuits that are to be run). - - `exp_header`(optional): Array of User-defined structure that contains metadata on each experiment and - is not used by the backend. The header will be passed through to the result data structure unchanged. - For example, this may contain a fitting parameters for the experiment. In addition, this header can - contain a mapping of backend memory and backend qubits to OpenQASM registers. - This is because an OpenQASM circuit may contain multiple classical and quantum registers, - but Qobj flattens them into a single memory and single set of qubits. - - `exp_config` (optional): An Array of Configuration structure for user settings that can be different in each - experiment. These will override the configuration settings of the whole job. +Returns and experiment type that consits of instructions. + +- `qc`: An `Array` of `ChainBlock`(circuits that are to be run). +- `exp_header`(optional): Array of User-defined structure that contains metadata on each experiment and +is not used by the backend. The header will be passed through to the result data structure unchanged. +For example, this may contain a fitting parameters for the experiment. In addition, this header can +contain a mapping of backend memory and backend qubits to OpenQASM registers. +This is because an OpenQASM circuit may contain multiple classical and quantum registers, +but Qobj flattens them into a single memory and single set of qubits. +- `exp_config` (optional): An Array of Configuration structure for user settings that can be different in each +experiment. These will override the configuration settings of the whole job. """ create_experiment( qc::Vector{<:AbstractBlock{N}}, @@ -92,9 +92,9 @@ end """ generate_inst(qc) - Parses the YaoIR into a list of IBMQ supported instructions +Parses the YaoIR into a list of IBMQ supported instructions - - `qc`: A `ChainBlock`(circuit that is to be run). +- `qc`: A `ChainBlock`(circuit that is to be run). """ function generate_inst(qc::AbstractBlock{N}) where {N} inst = Instruction[] From dbaf2deff21d3b30402f56468c57980099f7b782 Mon Sep 17 00:00:00 2001 From: Arsh <184517@nith.ac.in> Date: Wed, 19 May 2021 22:04:09 +0530 Subject: [PATCH 07/12] typo fix --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 0388734..14096f8 100644 --- a/Project.toml +++ b/Project.toml @@ -4,7 +4,7 @@ authors = ["Arsh Sharma and contributors"] version = "0.1.0" [deps] -Comfigurations = "5218b696-f38b-4ac9-8b61-a12ec717816d" +Configurations = "5218b696-f38b-4ac9-8b61-a12ec717816d" IBMQClient = "02860bad-daa6-4506-8736-4a3616c18085" UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" YaoBlocks = "418bc28f-b43b-5e0b-a6e7-61bbc1a2c1df" From 8b2169d2257f6ee8cbf596e42bc87b148444d43b Mon Sep 17 00:00:00 2001 From: Arsh <184517@nith.ac.in> Date: Thu, 20 May 2021 11:22:24 +0530 Subject: [PATCH 08/12] Include the qbir conversion --- Project.toml | 4 ++-- src/YaoBlocksQobj.jl | 3 ++- test/qobjtoqbir.jl => src/qbir.jl | 17 ++++++++++++++++- test/runtests.jl | 4 +--- 4 files changed, 21 insertions(+), 7 deletions(-) rename test/qobjtoqbir.jl => src/qbir.jl (91%) diff --git a/Project.toml b/Project.toml index 14096f8..1bc11da 100644 --- a/Project.toml +++ b/Project.toml @@ -7,6 +7,7 @@ version = "0.1.0" Configurations = "5218b696-f38b-4ac9-8b61-a12ec717816d" IBMQClient = "02860bad-daa6-4506-8736-4a3616c18085" UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" +Yao = "5872b779-8223-5990-8dd0-5abbb0748c8c" YaoBlocks = "418bc28f-b43b-5e0b-a6e7-61bbc1a2c1df" [compat] @@ -16,7 +17,6 @@ julia = "1.6" [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" -Yao = "5872b779-8223-5990-8dd0-5abbb0748c8c" [targets] -test = ["Test", "Yao"] +test = ["Test"] diff --git a/src/YaoBlocksQobj.jl b/src/YaoBlocksQobj.jl index 5886e33..51c8f59 100644 --- a/src/YaoBlocksQobj.jl +++ b/src/YaoBlocksQobj.jl @@ -1,11 +1,12 @@ module YaoBlocksQobj -export convert_to_qobj +export convert_to_qobj, convert_to_qbir using Configurations using IBMQClient.Schema using YaoBlocks include("qobj.jl") +include("qbir.jl") end diff --git a/test/qobjtoqbir.jl b/src/qbir.jl similarity index 91% rename from test/qobjtoqbir.jl rename to src/qbir.jl index 9467aca..e84c981 100644 --- a/test/qobjtoqbir.jl +++ b/src/qbir.jl @@ -1,3 +1,5 @@ +using Yao + mutable struct U1{T<:Number} <: PrimitiveBlock{1} lambda::T end @@ -77,7 +79,20 @@ YaoBlocks.@dumpload_fallback U1 U1 YaoBlocks.@dumpload_fallback U2 U2 YaoBlocks.@dumpload_fallback U3 U3 -function inst2qbir(inst) +""" + convert_to_qbir(inst) + +Converts Qobj based instructions back to YaoIR. + +- `inst`: The Qobj based instructions. + +For Example: +```julia +q = convert_to_qobj(chain(1, put(1 => H))) +ir = q.experiments[1].instructions |> convert_to_qbir +``` +""" +function convert_to_qbir(inst) n = maximum(x -> maximum(x.qubits), inst) + 1 chain( n, diff --git a/test/runtests.jl b/test/runtests.jl index 35e216a..bf6addf 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,8 +1,6 @@ using Yao, YaoBlocksQobj using Test -include("qobjtoqbir.jl") - @testset "YaoBlocksQobj.jl" begin qc = chain( 3, @@ -30,7 +28,7 @@ include("qobjtoqbir.jl") @test exp.header == Dict("description" => "$i") @test exp.config === nothing inst = exp.instructions - ir = inst2qbir(inst) + ir = convert_to_qbir(inst) @test ir == circuits[i] end From abacd23edf81a2523ecb87ea040a17d2466f450f Mon Sep 17 00:00:00 2001 From: Arsh Sharma <43717431+Sov-trotter@users.noreply.github.com> Date: Fri, 21 May 2021 13:00:18 +0530 Subject: [PATCH 09/12] convert to string Co-authored-by: Rogerluo --- src/qobj.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qobj.jl b/src/qobj.jl index 12f4580..ea5e046 100644 --- a/src/qobj.jl +++ b/src/qobj.jl @@ -1,7 +1,7 @@ using Configurations, UUIDs @option struct ExpOptions - id::String = "$(uuid1())" + id::String = string(uuid1()) header::Maybe{Dict{String,Any}} = nothing nshots::Int = 1024 exp_header::Maybe{Vector{Dict{String,Any}}} = nothing From 895e4ec3bf71d1401450f825af8511f645b85d30 Mon Sep 17 00:00:00 2001 From: Arsh <184517@nith.ac.in> Date: Fri, 21 May 2021 14:10:04 +0530 Subject: [PATCH 10/12] Increase coverage --- src/qbir.jl | 2 ++ test/runtests.jl | 44 ++++++++++++++++++++++++++++++-------------- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/qbir.jl b/src/qbir.jl index e84c981..e1ad531 100644 --- a/src/qbir.jl +++ b/src/qbir.jl @@ -108,6 +108,8 @@ function convert_to_qbir(inst) locs[1:nc], locs[nc+1:end] => name_index(name[nc+1:end], x.params), ) + elseif name == "measure" + put(n, locs =>Yao.Measure(locs...)) else put(n, locs => name_index(name, x.params)) end diff --git a/test/runtests.jl b/test/runtests.jl index bf6addf..2773d35 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,4 +1,4 @@ -using Yao, YaoBlocksQobj +using IBMQClient.Schema, Yao, YaoBlocksQobj using Test @testset "YaoBlocksQobj.jl" begin @@ -13,23 +13,39 @@ using Test control(2, 1 => Y), control(3, 2 => Z), ) - qc1 = chain(3, put(3 => Rx(0.7)), control(2, 1 => Y), control(3, 2 => Z)) + qc1 = chain(3, put(1 => H), put(3 => Rx(0.7)), control(2, 1 => Y), control(3, 2 => Z), put(1=>Yao.Measure(1))) header = Dict("description" => "test circuits") exp_header = [Dict("description" => "1"), Dict("description" => "2")] - - circuits = [qc, qc1] + circuits = [qc, qc1] + q = convert_to_qobj(circuits, id = "test", header = header, exp_header = exp_header) + q1 = convert_to_qobj(circuits) + q2 = convert_to_qobj(circuits, exp_header = exp_header) + + set = [q, q1, q2] + for i in set + experiments = i.experiments + for i = 1:length(experiments) + exp = experiments[i] + @test exp isa YaoBlocksQobj.Schema.Experiment + @test exp.header == Dict("description" => "$i") || exp.header === nothing + @test exp.config === nothing + inst = exp.instructions + ir = convert_to_qbir(inst) + @test ir == circuits[i] + end + + qc_inst = chain(1, put(1 => YaoBlocksQobj.U1{Float64}(2)), + put(1 => YaoBlocksQobj.U2{Float64}(1, 0.7)), + put(1 => YaoBlocksQobj.U3{Float64}(0, 1, 0.7))) - experiments = q.experiments - for i = 1:length(experiments) - exp = experiments[i] - @test exp isa YaoBlocksQobj.Schema.Experiment - @test exp.header == Dict("description" => "$i") - @test exp.config === nothing - inst = exp.instructions - ir = convert_to_qbir(inst) - @test ir == circuits[i] - end + inst = [ + IBMQClient.Schema.Gate("u1", [0], [2], nothing, nothing), + IBMQClient.Schema.Gate("u2", [0], [1 , 0.7], nothing, nothing), + IBMQClient.Schema.Gate("u3", [0],[0,1, 0.7], nothing, nothing), + ] + @test qc_inst == convert_to_qbir(inst) +end end From c093eb7c22a73a8127058a80bef162a0923f1a80 Mon Sep 17 00:00:00 2001 From: Arsh <184517@nith.ac.in> Date: Fri, 21 May 2021 14:19:04 +0530 Subject: [PATCH 11/12] Fix import --- test/runtests.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runtests.jl b/test/runtests.jl index 2773d35..46b989e 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,4 +1,4 @@ -using IBMQClient.Schema, Yao, YaoBlocksQobj +using IBMQClient, Yao, YaoBlocksQobj using Test @testset "YaoBlocksQobj.jl" begin From 7b448d4a031ea033db69b86da87264d629bc88c6 Mon Sep 17 00:00:00 2001 From: Arsh <184517@nith.ac.in> Date: Fri, 21 May 2021 14:53:45 +0530 Subject: [PATCH 12/12] more tests --- src/qbir.jl | 2 +- test/runtests.jl | 64 +++++++++++++++++++++++++++++++++++++----------- 2 files changed, 51 insertions(+), 15 deletions(-) diff --git a/src/qbir.jl b/src/qbir.jl index e1ad531..cec744d 100644 --- a/src/qbir.jl +++ b/src/qbir.jl @@ -109,7 +109,7 @@ function convert_to_qbir(inst) locs[nc+1:end] => name_index(name[nc+1:end], x.params), ) elseif name == "measure" - put(n, locs =>Yao.Measure(locs...)) + put(n, locs => Yao.Measure(locs...)) else put(n, locs => name_index(name, x.params)) end diff --git a/test/runtests.jl b/test/runtests.jl index 46b989e..ccd38ee 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -8,21 +8,29 @@ using Test put(2 => Y), put(3 => Z), put(2 => T), + put(2 => I2), swap(1, 2), put(3 => Ry(0.7)), control(2, 1 => Y), control(3, 2 => Z), ) - qc1 = chain(3, put(1 => H), put(3 => Rx(0.7)), control(2, 1 => Y), control(3, 2 => Z), put(1=>Yao.Measure(1))) + qc1 = chain( + 3, + put(1 => H), + put(3 => Rx(0.7)), + control(2, 1 => Y), + control(3, 2 => Z), + put(1 => Yao.Measure(1)), + ) header = Dict("description" => "test circuits") exp_header = [Dict("description" => "1"), Dict("description" => "2")] - circuits = [qc, qc1] - + circuits = [qc, qc1] + q = convert_to_qobj(circuits, id = "test", header = header, exp_header = exp_header) q1 = convert_to_qobj(circuits) q2 = convert_to_qobj(circuits, exp_header = exp_header) - + set = [q, q1, q2] for i in set experiments = i.experiments @@ -35,17 +43,45 @@ using Test ir = convert_to_qbir(inst) @test ir == circuits[i] end - - qc_inst = chain(1, put(1 => YaoBlocksQobj.U1{Float64}(2)), - put(1 => YaoBlocksQobj.U2{Float64}(1, 0.7)), - put(1 => YaoBlocksQobj.U3{Float64}(0, 1, 0.7))) - inst = [ + qc_inst = chain( + 1, + put(1 => YaoBlocksQobj.U1{Float64}(2)), + put(1 => YaoBlocksQobj.U2{Float64}(1, 0.7)), + put(1 => YaoBlocksQobj.U3{Float64}(0, 1, 0.7)), + ) + + inst = [ IBMQClient.Schema.Gate("u1", [0], [2], nothing, nothing), - IBMQClient.Schema.Gate("u2", [0], [1 , 0.7], nothing, nothing), - IBMQClient.Schema.Gate("u3", [0],[0,1, 0.7], nothing, nothing), - ] + IBMQClient.Schema.Gate("u2", [0], [1, 0.7], nothing, nothing), + IBMQClient.Schema.Gate("u3", [0], [0, 1, 0.7], nothing, nothing), + ] - @test qc_inst == convert_to_qbir(inst) -end + @test qc_inst == convert_to_qbir(inst) + end + + @testset "qbir misc." begin + @test YaoBlocksQobj.mat(Number, YaoBlocksQobj.U1(0.7)) ≈ Number[ + 1 0 + 0 exp(im * 0.7) + ] + + @test YaoBlocksQobj.mat(Number, YaoBlocksQobj.U2(0.7, 0.5)) ≈ Number[ + 1/√2 (-exp(im * 0.5))/√2 + (exp(im * 0.7))/√2 (exp(im * (1.2)))/√2 + ] + + @test YaoBlocksQobj.mat(Number, YaoBlocksQobj.U3(0.7, 0.5, 0.2)) ≈ Number[ + cos(0.7 / 2) -sin(0.7 / 2)*exp(im * 0.2) + sin(0.7 / 2)*exp(im * 0.5) cos(0.7 / 2)*exp(im * (0.7)) + ] + + @test YaoBlocksQobj.iparams_eltype(YaoBlocksQobj.U1(0.7)) == Float64 + @test YaoBlocksQobj.iparams_eltype(YaoBlocksQobj.U2(0.7, 0.5)) == Float64 + @test YaoBlocksQobj.iparams_eltype(YaoBlocksQobj.U3(0.7, 0.5, 0.2)) == Float64 + + @test YaoBlocksQobj.getiparams(YaoBlocksQobj.U1(0.7)) == (0.7) + @test YaoBlocksQobj.getiparams(YaoBlocksQobj.U2(0.7, 0.5)) == (0.7, 0.5) + @test YaoBlocksQobj.getiparams(YaoBlocksQobj.U3(0.7, 0.5, 0.2)) == (0.7, 0.5, 0.2) + end end