From a710e0f19c4db0a9dbe859c517e694a7edf4c461 Mon Sep 17 00:00:00 2001 From: Leo Date: Fri, 19 Jul 2019 13:10:34 -0400 Subject: [PATCH] new-parametrized SWAP gate, remove Swap type (#52) * new-parametrized SWAP gate, remove Swap type * fix printing for swap, export swap correctly * update benchmarks --- benchmark/benchmarks.jl | 2 + src/composite/put_block.jl | 59 +++++++++++++++++++- src/layout.jl | 2 - src/primitive/const_gate.jl | 6 +- src/primitive/primitive.jl | 1 - src/primitive/swap_gate.jl | 64 ---------------------- test/composite/put.jl | 6 ++ test/{primitive => composite}/swap_gate.jl | 16 ++++++ test/primitive/primitive.jl | 6 +- 9 files changed, 86 insertions(+), 76 deletions(-) delete mode 100644 src/primitive/swap_gate.jl rename test/{primitive => composite}/swap_gate.jl (54%) diff --git a/benchmark/benchmarks.jl b/benchmark/benchmarks.jl index ab2d26cb9..a621b2ea2 100644 --- a/benchmark/benchmarks.jl +++ b/benchmark/benchmarks.jl @@ -25,6 +25,8 @@ end for n in 5:5:25 SUITE["composite"]["kron(rand_const)"] = bench(kron(rand([X, Y, Z, H]) for _ in 1:n)) SUITE["composite"]["kron(sparse_const)"] = bench(kron(n, k=>rand([X, Y, Z, H]) for k in randperm(n)[1:n÷5])) + SUITE["composite"]["swap"] = bench(swap(n,2,4)) + SUITE["composite"]["swap"] = bench(pswap(n,2,4,0.5)) end function heisenberg(n::Int; periodic::Bool=true) diff --git a/src/composite/put_block.jl b/src/composite/put_block.jl index d9ee5ab47..4abfaf1ce 100644 --- a/src/composite/put_block.jl +++ b/src/composite/put_block.jl @@ -1,4 +1,4 @@ -export PutBlock, put +export PutBlock, put, Swap, swap, PSwap, pswap """ PutBlock <: AbstractContainer @@ -104,3 +104,60 @@ function YaoBase.iscommute(x::PutBlock{N}, y::PutBlock{N}) where N return iscommute_fallback(x, y) end end + +const Swap{N} = PutBlock{N,2,G} where G<:ConstGate.SWAPGate +const PSwap{N, T} = PutBlock{N,2,RotationGate{2,T,G}} where G<:ConstGate.SWAPGate +Swap{N}(locs::Tuple{Int, Int}) where N = PutBlock{N}(ConstGate.SWAPGate(), locs) +PSwap{N}(locs::Tuple{Int, Int}, θ::Real) where N = PutBlock{N}(rot(ConstGate.SWAPGate(), θ), locs) + +""" + swap(n, loc1, loc2) + +Create a `n`-qubit [`Swap`](@ref) gate which swap `loc1` and `loc2`. + +# Example + +```jldoctest +julia> swap(4, 1, 2) +swap(1, 2) +``` +""" +swap(n::Int, loc1::Int, loc2::Int) = Swap{n}((loc1, loc2)) + +""" + swap(loc1, loc2) -> f(n) + +Create a lambda that takes the total number of active qubits as input. Lazy curried +version of `swap(n, loc1, loc2)`. See also [`Swap`](@ref). + +# Example + +```jldoctest +julia> swap(1, 2) +(n -> swap(n, 1, 2)) +``` +""" +swap(loc1::Int, loc2::Int) = @λ(n -> swap(n, loc1, loc2)) + +function mat(::Type{T}, g::Swap{N}) where {T, N} + mask = bmask(g.locs[1], g.locs[2]) + orders = map(b->swapbits(b, mask) + 1, basis(N)) + return PermMatrix(orders, ones(T, 1< f(n) + +parametrized swap gate. +""" +pswap(n::Int, i::Int, j::Int, α::Real) = PSwap{n}((i,j), α) +pswap(i::Int, j::Int, α::Real) = n->pswap(n,i,j,α) + +function apply!(reg::ArrayReg, g::PSwap{N, T}) where {N,T} + instruct!(matvec(state(reg)), Val(:PSWAP), g.locs, g.content.theta) + return reg +end diff --git a/src/layout.jl b/src/layout.jl index 5384b265d..126a41d95 100644 --- a/src/layout.jl +++ b/src/layout.jl @@ -153,7 +153,6 @@ end # Custom layouts color(m::AbstractBlock) = color(typeof(m)) -color(::Type{<:Swap}) = :magenta color(::Type{<:ControlBlock}) = :red color(::Type{<:ChainBlock}) = :blue color(::Type{<:MathGate}) = :red @@ -168,7 +167,6 @@ color(::Type{<:GeneralMatrixBlock}) = :red print_block(io::IO, g::PhaseGate) = print(io, "phase(", g.theta, ")") print_block(io::IO, S::ShiftGate) = print(io, "shift(", S.theta, ")") print_block(io::IO, R::RotationGate) = print(io, "rot(", content(R), ", ", R.theta, ")") -print_block(io::IO, swap::Swap) = printstyled(io, "swap", swap.locs; bold=true, color=color(Swap)) print_block(io::IO, x::KronBlock) = printstyled(io, "kron"; bold=true, color=color(KronBlock)) print_block(io::IO, x::ChainBlock) = printstyled(io, "chain"; bold=true, color=color(ChainBlock)) print_block(io::IO, x::ReflectGate{N}) where N = print(io, "reflect($(summary(x.psi)))") diff --git a/src/primitive/const_gate.jl b/src/primitive/const_gate.jl index 50c7f31e0..c2da5e8d6 100644 --- a/src/primitive/const_gate.jl +++ b/src/primitive/const_gate.jl @@ -1,6 +1,6 @@ export @const_gate, ConstantGate, ConstGate, - X, Y, Z, H, I2, - XGate, YGate, ZGate, HGate, I2Gate + X, Y, Z, H, I2, SWAP, + XGate, YGate, ZGate, HGate, I2Gate, SWAPGate """ ConstGate @@ -36,5 +36,5 @@ end # import some frequently-used objects import .ConstGate: - XGate, YGate, ZGate, HGate, I2Gate, X, Y, Z, H, I2, + XGate, YGate, ZGate, HGate, I2Gate, SWAPGate, X, Y, Z, H, I2, SWAP, @const_gate, ConstantGate, PauliGate diff --git a/src/primitive/primitive.jl b/src/primitive/primitive.jl index 492a9e2a7..d6f803b8a 100644 --- a/src/primitive/primitive.jl +++ b/src/primitive/primitive.jl @@ -25,7 +25,6 @@ include("const_gate.jl") include("phase_gate.jl") include("shift_gate.jl") include("rotation_gate.jl") -include("swap_gate.jl") include("time_evolution.jl") include("reflect_gate.jl") include("general_matrix_gate.jl") diff --git a/src/primitive/swap_gate.jl b/src/primitive/swap_gate.jl deleted file mode 100644 index 499e80dff..000000000 --- a/src/primitive/swap_gate.jl +++ /dev/null @@ -1,64 +0,0 @@ -using YaoBase, BitBasis -using YaoArrayRegister: swaprows! - -export Swap, swap - -""" - Swap{N, T} <: PrimitiveBlock{N, T} - -Swap block, which will swap two locations given. -""" -struct Swap{N} <: PrimitiveBlock{N} - locs::Tuple{Int, Int} - - function Swap{N}(locs::Tuple{Int, Int}) where N - @assert_locs_safe N locs - return new{N}(locs) - end -end - -Swap{N}(loc1::Int, loc2::Int) where N = Swap{N}((loc1, loc2)) - -""" - swap(n, loc1, loc2) - -Create a `n`-qubit [`Swap`](@ref) gate which swap `loc1` and `loc2`. - -# Example - -```jldoctest -julia> swap(4, 1, 2) -swap(1, 2) -``` -""" -swap(n::Int, loc1::Int, loc2::Int) = Swap{n}((loc1, loc2)) - -""" - swap(loc1, loc2) -> f(n) - -Create a lambda that takes the total number of active qubits as input. Lazy curried -version of `swap(n, loc1, loc2)`. See also [`Swap`](@ref). - -# Example - -```jldoctest -julia> swap(1, 2) -(n -> swap(n, 1, 2)) -``` -""" -swap(loc1::Int, loc2::Int) = @λ(n -> swap(n, loc1, loc2)) - -function mat(::Type{T}, g::Swap{N}) where {T, N} - mask = bmask(g.locs[1], g.locs[2]) - orders = map(b->swapbits(b, mask) + 1, basis(N)) - return PermMatrix(orders, ones(T, 1< isunitary @test pb |> isreflexive end + +@testset "test swap gate" begin + include("swap_gate.jl") +end + + diff --git a/test/primitive/swap_gate.jl b/test/composite/swap_gate.jl similarity index 54% rename from test/primitive/swap_gate.jl rename to test/composite/swap_gate.jl index 43b334eaa..4e314f533 100644 --- a/test/primitive/swap_gate.jl +++ b/test/composite/swap_gate.jl @@ -16,3 +16,19 @@ end @test isunitary(swap(3, 1, 2)) @test ishermitian(swap(3, 1, 2)) @test isreflexive(swap(3, 1, 2)) + +@testset "pswap gate" begin + pb = pswap(6, 2, 4, 0.0) + @test pb isa PSwap{6, Float64} + @test pb == pswap(2, 4, 0.0)(6) + reg = rand_state(6) + @test copy(reg) |> pb ≈ invoke(apply!, Tuple{ArrayReg, PutBlock}, copy(reg), pb) + @test copy(reg) |> pb ≈ reg + + dispatch!(pb, π) + @test copy(reg) |> pb ≈ -im*(copy(reg) |> swap(6, 2, 4)) + @test copy(reg) |> pb |> isnormalized + + dispatch!(pb, :random) + @test copy(reg) |> pb ≈ invoke(apply!, Tuple{ArrayReg, PutBlock}, copy(reg), pb) +end diff --git a/test/primitive/primitive.jl b/test/primitive/primitive.jl index 3369246a1..f1439be80 100644 --- a/test/primitive/primitive.jl +++ b/test/primitive/primitive.jl @@ -16,10 +16,6 @@ end include("rotation_gate.jl") end -@testset "test swap gate" begin - include("swap_gate.jl") -end - @testset "test time evolution" begin include("time_evolution.jl") end @@ -41,4 +37,4 @@ end end # it does nothing -@test chsubblocks(X, Y) === X \ No newline at end of file +@test chsubblocks(X, Y) === X