From 8b8aa82fc0b1a65556897a825ba2e97472ff36f2 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Tue, 25 Jul 2023 15:51:01 -0400 Subject: [PATCH] fix: Support arbitrary angle Molmer-Sorenson gate. --- src/gate_applicators.jl | 34 +++++++++++++++++++++++----------- src/gates.jl | 37 +++++++++++++++++++------------------ src/raw_schema.jl | 9 ++++++++- test/gates.jl | 24 +++++++++++++----------- 4 files changed, 63 insertions(+), 41 deletions(-) diff --git a/src/gate_applicators.jl b/src/gate_applicators.jl index c5f9254d..70e0c1c3 100644 --- a/src/gate_applicators.jl +++ b/src/gate_applicators.jl @@ -6,46 +6,58 @@ for (G, IRG) in zip((:H,:I,:X,:Y,:Z,:S,:Si,:T,:Ti,:V,:Vi,:CNot,:Swap,:ISwap,:CV, end apply_gate!(::IR.NonAngled, ::IR.NoControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, arg::IntOrQubit) where {G<:Gate} = add_instruction!(c, Instruction(G(), arg)) apply_gate!(::IR.Angled, ::IR.NoControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, arg::IntOrQubit, angle) where {G<:Gate} = add_instruction!(c, Instruction(G(angle), arg)) -apply_gate!(::IR.DoubleAngled, ::IR.NoControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, arg::IntOrQubit, angle1, angle2) where {G<:Gate} = add_instruction!(c, Instruction(G(angle1, angle2), arg)) +#apply_gate!(::IR.DoubleAngled, ::IR.NoControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, arg::IntOrQubit, angle1, angle2) where {G<:Gate} = add_instruction!(c, Instruction(G(angle1, angle2), arg)) +apply_gate!(::IR.TripleAngled, ::IR.NoControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, arg::IntOrQubit, angle1, angle2, angle3) where {G<:Gate} = add_instruction!(c, Instruction(G(angle1, angle2, angle3), arg)) + apply_gate!(::IR.NonAngled, ::IR.NoControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, arg::VecOrQubitSet) where {G<:Gate} = (foreach(i->add_instruction!(c, Instruction(G(), i)), arg); return c) apply_gate!(::IR.Angled, ::IR.NoControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, v::VecOrQubitSet, angle) where {G<:Gate} = (foreach(i->add_instruction!(c, Instruction(G(angle), i)), v); return c) -apply_gate!(::IR.DoubleAngled, ::IR.NoControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, v::VecOrQubitSet, angle1, angle2) where {G<:Gate} = (foreach(i->add_instruction!(c, Instruction(G(angle1, angle2), i)), v); return c) +#apply_gate!(::IR.DoubleAngled, ::IR.NoControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, v::VecOrQubitSet, angle1, angle2) where {G<:Gate} = (foreach(i->add_instruction!(c, Instruction(G(angle1, angle2), i)), v); return c) +apply_gate!(::IR.TripleAngled, ::IR.NoControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, v::VecOrQubitSet, angle1, angle2, angle3) where {G<:Gate} = (foreach(i->add_instruction!(c, Instruction(G(angle1, angle2, angle3), i)), v); return c) apply_gate!(::IR.NonAngled, ::IR.NoControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, args...) where {G<:Gate} = (foreach(i->add_instruction!(c, Instruction(G(), i)), args); return c) apply_gate!(::IR.Angled, ::IR.NoControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, args...) where {G<:Gate} = (foreach(i->add_instruction!(c, Instruction(G(args[end]), i)), args[1:end-1]); return c) -apply_gate!(::IR.DoubleAngled, ::IR.NoControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, args...) where {G<:Gate} = (foreach(i->add_instruction!(c, Instruction(G(args[end-1], args[end]), i)), args[1:end-2]); return c) +#apply_gate!(::IR.DoubleAngled, ::IR.NoControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, args...) where {G<:Gate} = (foreach(i->add_instruction!(c, Instruction(G(args[end-1], args[end]), i)), args[1:end-2]); return c) +apply_gate!(::IR.TripleAngled, ::IR.NoControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, args...) where {G<:Gate} = (foreach(i->add_instruction!(c, Instruction(G(args[end-2], args[end-1], args[end]), i)), args[1:end-2]); return c) apply_gate!(::IR.NonAngled, ::IR.NoControl, ::IR.DoubleTarget, ::Type{G}, c::Circuit, args::VecOrQubitSet) where {G<:Gate} = add_instruction!(c, Instruction(G(), args[1:2])) apply_gate!(::IR.Angled, ::IR.NoControl, ::IR.DoubleTarget, ::Type{G}, c::Circuit, args::VecOrQubitSet, angle) where {G<:Gate} = add_instruction!(c, Instruction(G(angle), args[1:2])) -apply_gate!(::IR.DoubleAngled, ::IR.NoControl, ::IR.DoubleTarget, ::Type{G}, c::Circuit, args::VecOrQubitSet, angle1, angle2) where {G<:Gate} = add_instruction!(c, Instruction(G(angle1, angle2), args[1:2])) +#apply_gate!(::IR.DoubleAngled, ::IR.NoControl, ::IR.DoubleTarget, ::Type{G}, c::Circuit, args::VecOrQubitSet, angle1, angle2) where {G<:Gate} = add_instruction!(c, Instruction(G(angle1, angle2), args[1:2])) +apply_gate!(::IR.TripleAngled, ::IR.NoControl, ::IR.DoubleTarget, ::Type{G}, c::Circuit, args::VecOrQubitSet, angle1, angle2, angle3) where {G<:Gate} = add_instruction!(c, Instruction(G(angle1, angle2, angle3), args[1:3])) apply_gate!(::IR.NonAngled, ::IR.NoControl, ::IR.DoubleTarget, ::Type{G}, c::Circuit, args...) where {G<:Gate} = add_instruction!(c, Instruction(G(), [args[1:2]...])) apply_gate!(::IR.Angled, ::IR.NoControl, ::IR.DoubleTarget, ::Type{G}, c::Circuit, args...) where {G<:Gate} = add_instruction!(c, Instruction(G(args[end]), [args[1:2]...])) -apply_gate!(::IR.DoubleAngled, ::IR.NoControl, ::IR.DoubleTarget, ::Type{G}, c::Circuit, args...) where {G<:Gate} = add_instruction!(c, Instruction(G(args[end-1], args[end]), [args[1:2]...])) +#apply_gate!(::IR.DoubleAngled, ::IR.NoControl, ::IR.DoubleTarget, ::Type{G}, c::Circuit, args...) where {G<:Gate} = add_instruction!(c, Instruction(G(args[end-1], args[end]), [args[1:2]...])) +apply_gate!(::IR.TripleAngled, ::IR.NoControl, ::IR.DoubleTarget, ::Type{G}, c::Circuit, args...) where {G<:Gate} = add_instruction!(c, Instruction(G(args[end-2], args[end-1], args[end]), [args[1:2]...])) apply_gate!(::IR.NonAngled, ::IR.SingleControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, args::VecOrQubitSet) where {G<:Gate} = add_instruction!(c, Instruction(G(), args[1:2])) apply_gate!(::IR.Angled, ::IR.SingleControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, args::VecOrQubitSet, angle) where {G<:Gate} = add_instruction!(c, Instruction(G(angle), args[1:2])) -apply_gate!(::IR.DoubleAngled, ::IR.SingleControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, args::VecOrQubitSet, angle1, angle2) where {G<:Gate} = add_instruction!(c, Instruction(G(angle1, angle2), args[1:2])) +#apply_gate!(::IR.DoubleAngled, ::IR.SingleControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, args::VecOrQubitSet, angle1, angle2) where {G<:Gate} = add_instruction!(c, Instruction(G(angle1, angle2), args[1:2])) +apply_gate!(::IR.TripleAngled, ::IR.SingleControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, args::VecOrQubitSet, angle1, angle2, angle3) where {G<:Gate} = add_instruction!(c, Instruction(G(angle1, angle2, angle3), args[1:2])) apply_gate!(::IR.NonAngled, ::IR.SingleControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, args...) where {G<:Gate} = add_instruction!(c, Instruction(G(), [args[1:2]...])) apply_gate!(::IR.Angled, ::IR.SingleControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, args...) where {G<:Gate} = add_instruction!(c, Instruction(G(args[end]), [args[1:2]...])) -apply_gate!(::IR.DoubleAngled, ::IR.SingleControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, args...) where {G<:Gate} = add_instruction!(c, Instruction(G(args[end-1], args[end]), [args[1:2]...])) +#apply_gate!(::IR.DoubleAngled, ::IR.SingleControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, args...) where {G<:Gate} = add_instruction!(c, Instruction(G(args[end-1], args[end]), [args[1:2]...])) +apply_gate!(::IR.TripleAngled, ::IR.SingleControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, args...) where {G<:Gate} = add_instruction!(c, Instruction(G(args[end-2], args[end-1], args[end]), [args[1:2]...])) apply_gate!(::IR.NonAngled, ::IR.SingleControl, ::IR.DoubleTarget, ::Type{G}, c::Circuit, args::VecOrQubitSet) where {G<:Gate} = add_instruction!(c, Instruction(G(), args[1:3])) apply_gate!(::IR.Angled, ::IR.SingleControl, ::IR.DoubleTarget, ::Type{G}, c::Circuit, args::VecOrQubitSet, angle) where {G<:Gate} = add_instruction!(c, Instruction(G(angle), args[1:3])) -apply_gate!(::IR.DoubleAngled, ::IR.SingleControl, ::IR.DoubleTarget, ::Type{G}, c::Circuit, args::VecOrQubitSet, angle1, angle2) where {G<:Gate} = add_instruction!(c, Instruction(G(angle1, angle2), args[1:3])) +#apply_gate!(::IR.DoubleAngled, ::IR.SingleControl, ::IR.DoubleTarget, ::Type{G}, c::Circuit, args::VecOrQubitSet, angle1, angle2) where {G<:Gate} = add_instruction!(c, Instruction(G(angle1, angle2), args[1:3])) +apply_gate!(::IR.TripleAngled, ::IR.SingleControl, ::IR.DoubleTarget, ::Type{G}, c::Circuit, args::VecOrQubitSet, angle1, angle2, angle3) where {G<:Gate} = add_instruction!(c, Instruction(G(angle1, angle2, angle3), args[1:3])) apply_gate!(::IR.NonAngled, ::IR.SingleControl, ::IR.DoubleTarget, ::Type{G}, c::Circuit, args...) where {G<:Gate} = add_instruction!(c, Instruction(G(), [args[1:3]...])) apply_gate!(::IR.Angled, ::IR.SingleControl, ::IR.DoubleTarget, ::Type{G}, c::Circuit, args...) where {G<:Gate} = add_instruction!(c, Instruction(G(args[end]), [args[1:3]...])) -apply_gate!(::IR.DoubleAngled, ::IR.SingleControl, ::IR.DoubleTarget, ::Type{G}, c::Circuit, args...) where {G<:Gate} = add_instruction!(c, Instruction(G(args[end-1], args[end]), [args[1:3]...])) +#apply_gate!(::IR.DoubleAngled, ::IR.SingleControl, ::IR.DoubleTarget, ::Type{G}, c::Circuit, args...) where {G<:Gate} = add_instruction!(c, Instruction(G(args[end-1], args[end]), [args[1:3]...])) +apply_gate!(::IR.TripleAngled, ::IR.SingleControl, ::IR.DoubleTarget, ::Type{G}, c::Circuit, args...) where {G<:Gate} = add_instruction!(c, Instruction(G(args[end-2], args[end-1], args[end]), [args[1:3]...])) apply_gate!(::IR.NonAngled, ::IR.DoubleControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, args::VecOrQubitSet) where {G<:Gate} = add_instruction!(c, Instruction(G(), args[1:3])) apply_gate!(::IR.Angled, ::IR.DoubleControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, args::VecOrQubitSet, angle) where {G<:Gate} = add_instruction!(c, Instruction(G(angle), args[1:3])) -apply_gate!(::IR.DoubleAngled, ::IR.DoubleControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, args::VecOrQubitSet, angle1, angle2) where {G<:Gate} = add_instruction!(c, Instruction(G(angle1, angle2), args[1:3])) +#apply_gate!(::IR.DoubleAngled, ::IR.DoubleControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, args::VecOrQubitSet, angle1, angle2) where {G<:Gate} = add_instruction!(c, Instruction(G(angle1, angle2), args[1:3])) +apply_gate!(::IR.TripleAngled, ::IR.DoubleControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, args::VecOrQubitSet, angle1, angle2, angle3) where {G<:Gate} = add_instruction!(c, Instruction(G(angle1, angle2, angle3), args[1:3])) apply_gate!(::IR.NonAngled, ::IR.DoubleControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, args...) where {G<:Gate} = add_instruction!(c, Instruction(G(), [args[1:3]...])) apply_gate!(::IR.Angled, ::IR.DoubleControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, args...) where {G<:Gate} = add_instruction!(c, Instruction(G(args[end]), [args[1:3]...])) -apply_gate!(::IR.DoubleAngled, ::IR.DoubleControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, args...) where {G<:Gate} = add_instruction!(c, Instruction(G(args[end-1], args[end]), [args[1:3]...])) +#apply_gate!(::IR.DoubleAngled, ::IR.DoubleControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, args...) where {G<:Gate} = add_instruction!(c, Instruction(G(args[end-1], args[end]), [args[1:3]...])) +apply_gate!(::IR.TripleAngled, ::IR.DoubleControl, ::IR.SingleTarget, ::Type{G}, c::Circuit, args...) where {G<:Gate} = add_instruction!(c, Instruction(G(args[end-2], args[end-1], args[end]), [args[1:3]...])) apply_gate!(::IR.NonAngled, ::IR.NoControl, ::IR.MultiTarget, ::Type{Unitary}, c::Circuit, v::VecOrQubitSet, m::Matrix{ComplexF64}) = add_instruction!(c, Instruction(Unitary(m), v)) apply_gate!(::IR.NonAngled, ::IR.NoControl, ::IR.MultiTarget, ::Type{Unitary}, c::Circuit, args...) = add_instruction!(c, Instruction(Unitary(args[end]), [args[1:end-1]...])) diff --git a/src/gates.jl b/src/gates.jl index 84b754d3..72392bbe 100644 --- a/src/gates.jl +++ b/src/gates.jl @@ -1,4 +1,4 @@ -export Gate,AngledGate,DoubleAngledGate,H,I,X,Y,Z,S,Si,T,Ti,V,Vi,CNot,Swap,ISwap,CV,CY,CZ,ECR,CCNot,CSwap,Unitary,Rx,Ry,Rz,PhaseShift,PSwap,XY,CPhaseShift,CPhaseShift00,CPhaseShift01,CPhaseShift10,XX,YY,ZZ,GPi,GPi2,MS +export Gate,AngledGate,TripleAngledGate,H,I,X,Y,Z,S,Si,T,Ti,V,Vi,CNot,Swap,ISwap,CV,CY,CZ,ECR,CCNot,CSwap,Unitary,Rx,Ry,Rz,PhaseShift,PSwap,XY,CPhaseShift,CPhaseShift00,CPhaseShift01,CPhaseShift10,XX,YY,ZZ,GPi,GPi2,MS """ Gate <: QuantumOperator @@ -6,7 +6,7 @@ Abstract type representing a quantum gate. """ abstract type Gate <: QuantumOperator end StructTypes.StructType(::Type{Gate}) = StructTypes.AbstractType() -StructTypes.subtypes(::Type{Gate}) = (angledgate=AngledGate, doubleangledgate=DoubleAngledGate, h=H, i=I, x=X, y=Y, z=Z, s=S, si=Si, t=T, ti=Ti, v=V, vi=Vi, cnot=CNot, swap=Swap, iswap=ISwap, cv=CV, cy=CY, cz=CZ, ecr=ECR, ccnot=CCNot, cswap=CSwap, unitary=Unitary, rx=Rx, ry=Ry, rz=Rz, phaseshift=PhaseShift, pswap=PSwap, xy=XY, cphaseshift=CPhaseShift, cphaseshift00=CPhaseShift00, cphaseshift01=CPhaseShift01, cphaseshift10=CPhaseShift10, xx=XX, yy=YY, zz=ZZ, gpi=GPi, gpi2=GPi2, ms=MS) +StructTypes.subtypes(::Type{Gate}) = (angledgate=AngledGate, tripleangledgate=TripleAngledGate, h=H, i=I, x=X, y=Y, z=Z, s=S, si=Si, t=T, ti=Ti, v=V, vi=Vi, cnot=CNot, swap=Swap, iswap=ISwap, cv=CV, cy=CY, cz=CZ, ecr=ECR, ccnot=CCNot, cswap=CSwap, unitary=Unitary, rx=Rx, ry=Ry, rz=Rz, phaseshift=PhaseShift, pswap=PSwap, xy=XY, cphaseshift=CPhaseShift, cphaseshift00=CPhaseShift00, cphaseshift01=CPhaseShift01, cphaseshift10=CPhaseShift10, xx=XX, yy=YY, zz=ZZ, gpi=GPi, gpi2=GPi2, ms=MS) """ AngledGate <: Gate @@ -18,13 +18,13 @@ StructTypes.StructType(::Type{AngledGate}) = StructTypes.AbstractType() StructTypes.subtypes(::Type{AngledGate}) = (rx=Rx, ry=Ry, rz=Rz, phaseshift=PhaseShift, pswap=PSwap, xy=XY, cphaseshift=CPhaseShift, cphaseshift00=CPhaseShift00, cphaseshift01=CPhaseShift01, cphaseshift10=CPhaseShift10, xx=XX, yy=YY, zz=ZZ, gpi=GPi, gpi2=GPi2) """ - DoubleAngledGate <: Gate + TripleAngledGate <: Gate -Abstract type representing a quantum gate with two `angle` parameters. +Abstract type representing a quantum gate with three `angle` parameters. """ -abstract type DoubleAngledGate <: Gate end -StructTypes.StructType(::Type{DoubleAngledGate}) = StructTypes.AbstractType() -StructTypes.subtypes(::Type{DoubleAngledGate}) = (ms=MS) +abstract type TripleAngledGate <: Gate end +StructTypes.StructType(::Type{TripleAngledGate}) = StructTypes.AbstractType() +StructTypes.subtypes(::Type{TripleAngledGate}) = (ms=MS) for (G, IRG, label, qc, c) in zip((:Rx, :Ry, :Rz, :PhaseShift, :PSwap, :XY, :CPhaseShift, :CPhaseShift00, :CPhaseShift01, :CPhaseShift10, :XX, :YY, :ZZ, :GPi, :GPi2), (:(IR.Rx), :(IR.Ry), :(IR.Rz), :(IR.PhaseShift), :(IR.PSwap), :(IR.XY), :(IR.CPhaseShift), :(IR.CPhaseShift00), :(IR.CPhaseShift01), :(IR.CPhaseShift10), :(IR.XX), :(IR.YY), :(IR.ZZ), :(IR.GPi), :(IR.GPi2)), ("rx", "ry", "rz", "phaseshift", "pswap", "xy", "cphaseshift", "cphaseshift00", "cphaseshift01", "cphaseshift10", "xx", "yy", "zz", "gpi", "gpi2"), (:1, :1, :1, :1, :2, :2, :2, :2, :2, :2, :2, :2, :2, :1, :1), (["Rx(ang)"], ["Ry(ang)"], ["Rz(ang)"], ["PHASE(ang)"], ["PSWAP(ang)", "PSWAP(ang)"], ["XY(ang)", "XY(ang)"], ["C", "PHASE(ang)"], ["C", "PHASE00(ang)"], ["C", "PHASE01(ang)"], ["C", "PHASE10(ang)"], ["XX(ang)", "XX(ang)"], ["YY(ang)", "YY(ang)"], ["ZZ(ang)", "ZZ(ang)"], ["GPi(ang)"], ["GPi2(ang)"])) @eval begin @@ -51,29 +51,30 @@ for (G, IRG, label, qc, c) in zip((:Rx, :Ry, :Rz, :PhaseShift, :PSwap, :XY, :CPh end end end -for (G, IRG, label, qc, c) in zip((:MS,), (:(IR.MS),), ("ms",), (:2,), (["MS(ang1, ang2)", "MS(ang1, ang2)"],)) +for (G, IRG, label, qc, c) in zip((:MS,), (:(IR.MS),), ("ms",), (:2,), (["MS(ang1, ang2, ang3)", "MS(ang1, ang2, ang3)"],)) @eval begin @doc """ - $($G) <: DoubleAngledGate - $($G)(angle1::Union{Float64, FreeParameter}, angle2::Union{Float64, FreeParameter}) -> $($G) + $($G) <: TripleAngledGate + $($G)(angle1::Union{Float64, FreeParameter}, angle2::Union{Float64, FreeParameter}, angle3::Union{Float64, FreeParameter}) -> $($G) $($G) gate. """ - struct $G <: DoubleAngledGate + struct $G <: TripleAngledGate angle1::Union{Float64, FreeParameter} angle2::Union{Float64, FreeParameter} + angle3::Union{Float64, FreeParameter} end - chars(g::$G) = map(char->replace(string(char), "ang1"=>string(g.angle1), "ang2"=>string(g.angle2)), $c) + chars(g::$G) = map(char->replace(string(char), "ang1"=>string(g.angle1), "ang2"=>string(g.angle2), "ang3"=>string(g.angle3)), $c) qubit_count(g::$G) = $qc qubit_count(::Type{$G}) = $qc function ir(g::$G, target::QubitSet, ::Val{:JAQCD}; kwargs...) t_c = IR._generate_control_and_target(IR.ControlAndTarget($IRG)..., target) - return $IRG(g.angle1, g.angle2, collect(t_c)..., $label) + return $IRG(g.angle1, g.angle2, g.angle3, collect(t_c)..., $label) end function ir(g::$G, target::QubitSet, ::Val{:OpenQASM}; serialization_properties=OpenQASMSerializationProperties()) t_c = IR._generate_control_and_target(IR.ControlAndTarget($IRG)..., target) t = format_qubits(t_c, serialization_properties) - return $label*"($(g.angle1), $(g.angle2)) $t;" + return $label*"($(g.angle1), $(g.angle2), $(g.angle3)) $t;" end end end @@ -129,18 +130,18 @@ abstract type Parametrizable end struct Parametrized end struct NonParametrized end -Parametrizable(g::DoubleAngledGate) = Parametrized() +Parametrizable(g::TripleAngledGate) = Parametrized() Parametrizable(g::AngledGate) = Parametrized() Parametrizable(g::Gate) = NonParametrized() -parameters(g::DoubleAngledGate) = filter(a->a isa FreeParameter, [g.angle1, g.angle2]) +parameters(g::TripleAngledGate) = filter(a->a isa FreeParameter, [g.angle1, g.angle2, g.angle3]) parameters(g::AngledGate) = g.angle isa FreeParameter ? [g.angle] : FreeParameter[] parameters(g::Gate) = FreeParameter[] bind_value!(g::G, params::Dict{Symbol, Number}) where {G<:Gate} = bind_value!(Parametrizable(g), g, params) bind_value!(::NonParametrized, g::G, params::Dict{Symbol, Number}) where {G<:Gate} = g -function bind_value!(::Parametrized, g::G, params::Dict{Symbol, Number}) where {G<:DoubleAngledGate} - new_angles = map([g.angle2, g.angle2]) do angle +function bind_value!(::Parametrized, g::G, params::Dict{Symbol, Number}) where {G<:TripleAngledGate} + new_angles = map([g.angle1, g.angle2, g.angle3]) do angle angle isa FreeParameter || return angle return get(params, angle.name, angle) end diff --git a/src/raw_schema.jl b/src/raw_schema.jl index 39b11f59..c83729e9 100644 --- a/src/raw_schema.jl +++ b/src/raw_schema.jl @@ -434,6 +434,7 @@ StructTypes.defaults(::Type{GeneralizedAmplitudeDamping}) = Dict{Symbol, Any}(:t struct MS <: AbstractIR angle1::Float64 angle2::Float64 + angle3::Float64 targets::Vector{Int} type::String end @@ -713,11 +714,17 @@ for g in [:Rx, :Ry, :Rz, :PhaseShift, :CPhaseShift, :CPhaseShift00, :CPhaseShift end end struct DoubleAngled <: Angle end -for g in [:MS] +for g in [] @eval begin Angle(::Type{$g}) = DoubleAngled() end end +struct TripleAngled <: Angle end +for g in [:MS] + @eval begin + Angle(::Type{$g}) = TripleAngled() + end +end struct NonAngled <: Angle end Angle(::Type{G}) where {G<:AbstractIR} = NonAngled() abstract type ProbabilityCount end diff --git a/test/gates.jl b/test/gates.jl index 256449f1..f8bbeea6 100644 --- a/test/gates.jl +++ b/test/gates.jl @@ -86,7 +86,7 @@ T_mat = round.(reduce(hcat, [[1.0, 0], [0, 0.70710678 + 0.70710678im]]), digits= pg = g(α) @test Braket.parameters(pg) == [α] end - @testset for g in (MS(angle, angle),) + @testset for g in (MS(angle, angle, angle),) @test qubit_count(g) == 2 ix = Instruction(g, [0, 1]) @test JSON3.read(JSON3.write(ix), Instruction) == ix @@ -96,16 +96,18 @@ T_mat = round.(reduce(hcat, [[1.0, 0], [0, 0.70710678 + 0.70710678im]]), digits= @testset for g in (MS,) @test qubit_count(g) == 2 c = Circuit() - c = g(c, 0, 1, angle, angle) - @test c.instructions == [Instruction(g(angle, angle), [0, 1])] + c = g(c, 0, 1, angle, angle, angle) + @test c.instructions == [Instruction(g(angle, angle, angle), [0, 1])] c = Circuit() - c = g(c, 10, 1, angle, angle) - @test c.instructions == [Instruction(g(angle, angle), [10, 1])] + c = g(c, 10, 1, angle, angle, angle) + @test c.instructions == [Instruction(g(angle, angle, angle), [10, 1])] α = FreeParameter(:alpha) β = FreeParameter(:beta) - pg = g(α, β) - @test Braket.parameters(pg) == [α, β] - pg = Braket.bind_value!(Braket.Parametrized(), pg, Dict{Symbol, Number}(:α=>0.1, :β=>0.5)) + γ = FreeParameter(:gamma) + pg = g(α, β, γ) + @test Braket.parameters(pg) == [α, β, γ] + pg = Braket.bind_value!(Braket.Parametrized(), pg, Dict{Symbol, Number}(:α=>0.1, :β=>0.5, :γ=>0.2)) + #@test pg == g(0.1, 0.5, 0.2) end @testset for g in (CCNot(), CSwap()) @test qubit_count(g) == 3 @@ -239,8 +241,8 @@ T_mat = round.(reduce(hcat, [[1.0, 0], [0, 0.70710678 + 0.70710678im]]), digits= (Ti(), [4], OpenQASMSerializationProperties(qubit_reference_type=PHYSICAL), "ti \$4;",), (PhaseShift(0.17), [4], OpenQASMSerializationProperties(qubit_reference_type=VIRTUAL), "phaseshift(0.17) q[4];",), (PhaseShift(0.17), [4], OpenQASMSerializationProperties(qubit_reference_type=PHYSICAL), "phaseshift(0.17) \$4;",), - (MS(0.17, 0.2), [4, 5], OpenQASMSerializationProperties(qubit_reference_type=VIRTUAL), "ms(0.17, 0.2) q[4], q[5];",), - (MS(0.17, 0.2), [4, 5], OpenQASMSerializationProperties(qubit_reference_type=PHYSICAL), "ms(0.17, 0.2) \$4, \$5;",), + (MS(0.17, 0.2, 0.1), [4, 5], OpenQASMSerializationProperties(qubit_reference_type=VIRTUAL), "ms(0.17, 0.2, 0.1) q[4], q[5];",), + (MS(0.17, 0.2, 0.1), [4, 5], OpenQASMSerializationProperties(qubit_reference_type=PHYSICAL), "ms(0.17, 0.2, 0.1) \$4, \$5;",), (CNot(), [4, 5], OpenQASMSerializationProperties(qubit_reference_type=VIRTUAL), "cnot q[4], q[5];",), (CNot(), [4, 5], OpenQASMSerializationProperties(qubit_reference_type=PHYSICAL), "cnot \$4, \$5;",), (PSwap(0.17), [4, 5], OpenQASMSerializationProperties(qubit_reference_type=VIRTUAL), "pswap(0.17) q[4], q[5];",), @@ -305,6 +307,6 @@ T_mat = round.(reduce(hcat, [[1.0, 0], [0, 0.70710678 + 0.70710678im]]), digits= end @test StructTypes.StructType(X) == StructTypes.Struct() @test StructTypes.StructType(Gate) == StructTypes.AbstractType() - @test StructTypes.StructType(DoubleAngledGate) == StructTypes.AbstractType() + ##@test StructTypes.StructType(DoubleAngledGate) == StructTypes.AbstractType() @test StructTypes.StructType(AngledGate) == StructTypes.AbstractType() end