Skip to content

Commit

Permalink
Merge pull request #62 from QuantumBFS/inversecontrol
Browse files Browse the repository at this point in the history
Inversecontrol
  • Loading branch information
Roger-luo authored Jun 5, 2018
2 parents 953a503 + a5ce710 commit f98e660
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 52 deletions.
3 changes: 2 additions & 1 deletion src/Boost/Control.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
function mat(ctrl::ControlBlock{BT, N, T}) where {N, T, BT <: MatrixBlock{1, T}}
controlled_U1(N, mat(ctrl.block), ctrl.ctrl_qubits, ctrl.addr)
ctrl_vals = @. div(sign(ctrl.ctrl_qubits) + 1, 2)
controlled_U1(N, mat(ctrl.block), abs.(ctrl.ctrl_qubits), ctrl_vals, ctrl.addr)
end
78 changes: 39 additions & 39 deletions src/Boost/gates.jl
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,11 @@ end
Single (Multiple) Controlled-X Gate on single (multiple) bits.
"""
function cxgate(::Type{MT}, num_bit::Int, b1::Ints, b2::Ints) where MT<:Number
mask = bmask(b1)
function cxgate(::Type{MT}, num_bit::Int, cbits::Vector{Int}, cvals::Vector{Int}, b2::Ints) where MT<:Number
mask = bmask(cbits...)
onemask = bmask(cbits[cvals.==1]...)
mask2 = bmask(b2)
order = map(i->testall(i, mask) ? flip(i, mask2)+1 : i+1, basis(num_bit))
order = map(i->testval(i, mask, onemask) ? flip(i, mask2)+1 : i+1, basis(num_bit))
PermMatrix(order, ones(MT, 1<<num_bit))
end

Expand All @@ -81,17 +82,20 @@ end
Single Controlled-Y Gate on single bit.
"""
function cygate(::Type{MT}, num_bit::Int, b1::Int, b2::Int) where MT<:Complex
function cygate(::Type{MT}, num_bit::Int, cbits::Vector{Int}, cvals::Vector{Int}, b2::Int) where MT<:Complex
mask = bmask(cbits...)
onemask = bmask(cbits[cvals.==1]...)
mask2 = bmask(b2)
order = collect(1:1<<num_bit)
vals = ones(MT, 1<<num_bit)
step = 1<<(b1-1)
step_2 = 1<<b1
for j = step:step_2:1<<num_bit-1
@simd for i = j+1:j+step
b = i-1
order = Vector{Int}(1<<num_bit)
vals = Vector{MT}(1<<num_bit)
@simd for b = 0:1<<num_bit-1
i = b+1
if testval(b, mask, onemask)
@inbounds order[i] = flip(b, mask2) + 1
@inbounds vals[i] = (2*takebit(b, b2)-1)*MT(im)
@inbounds vals[i] = testany(b, mask2) ? MT(im) : -MT(im)
else
@inbounds order[i] = i
@inbounds vals[i] = MT(1)
end
end
PermMatrix(order, vals)
Expand All @@ -102,16 +106,10 @@ end
Single Controlled-Z Gate on single bit.
"""
function czgate(::Type{MT}, num_bit::Int, b1::Int, b2::Int) where MT<:Number
mask2 = bmask(b2)
vals = ones(MT, 1<<num_bit)
step = 1<<(b1-1)
step_2 = 1<<b1
for j = step:step_2:1<<num_bit-1
@simd for i = j+1:j+step
@inbounds vals[i] = 1-2*takebit(i-1, b2)
end
end
function czgate(::Type{MT}, num_bit::Int, cbits::Vector{Int}, cvals::Vector{Int}, b2::Int) where MT<:Number
mask = bmask(cbits..., b2)
onemask = bmask(cbits[cvals.==1]..., b2)
vals = map(i->testval(i, mask, onemask) ? MT(-1) : MT(1), basis(num_bit))
Diagonal(vals)
end

Expand All @@ -127,42 +125,44 @@ function controlled_U1 end


# general multi-control single-gate
function controlled_U1(num_bit::Int, gate::PermMatrix{T}, cbits::Vector{Int}, b2::Int) where {T}
vals = ones(T, 1<<num_bit)
order = collect(1:1<<num_bit)
function controlled_U1(num_bit::Int, gate::PermMatrix{T}, cbits::Vector{Int}, cvals::Vector{Int}, b2::Int) where {T}
vals = Vector{T}(1<<num_bit)
order = Vector{Int}(1<<num_bit)
mask = bmask(cbits...)
onemask = bmask(cbits[cvals.==1]...)
mask2 = bmask(b2)
@simd for b in basis(num_bit)
if testall(b, mask)
bind = b+1
bind = b+1
if testval(b, mask, onemask)
@inbounds vals[bind] = gate.vals[gate.perm[2-takebit(b, b2)]]
@inbounds order[bind] = (gate.perm[1] == 1) ? bind : flip(b, mask2)+1
else
@inbounds vals[bind] = 1
@inbounds order[bind] = bind
end
end
PermMatrix(order, vals)
end

function controlled_U1(num_bit::Int, gate::SparseMatrixCSC, b1::Vector{Int}, b2::Int)
general_controlled_gates(2, [P1], b1, [gate], [b2])
end

function controlled_U1(num_bit::Int, gate::Diagonal{T}, cbits::Vector{Int}, b2::Int) where {T}
function controlled_U1(num_bit::Int, gate::Diagonal{T}, cbits::Vector{Int}, cvals::Vector{Int}, b2::Int) where {T}
mask = bmask(cbits...)
onemask = bmask(cbits[cvals.==1]...)

a, b = gate.diag
######### LW's version ###########
vals = ones(T, 1<<num_bit)
vals = Vector{T}(1<<num_bit)
@simd for i in basis(num_bit)
if testall(i, mask)
if testval(i, mask, onemask)
@inbounds vals[i+1] = gate.diag[1+takebit(i, b2)]
else
@inbounds vals[i+1] = 1
end
end
######### simple version ###########
#a, b = gate.diag
#vals = map(i->(testall(i, mask) ? (testany(i, b2) ? b : a) : T(1))::T, basis(num_bit))
Diagonal(vals)
end

function controlled_U1(num_bit::Int, gate::StridedMatrix, b1::Vector{Int}, b2::Int)
general_controlled_gates(2, [P1], b1, [gate], [b2])
function controlled_U1(num_bit::Int, gate::AbstractMatrix, cbits::Vector{Int}, cvals::Vector{Int}, b2::Int)
general_controlled_gates(num_bit, [c==1 ? mat(P1) : mat(P0) for c in cvals], cbits, [gate], [b2])
end

# arbituary control PermMatrix gate: SparseMatrixCSC
Expand Down
1 change: 1 addition & 0 deletions src/Intrinsics/Basis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ Return an integer with specific position masked, which is offten used as a mask
"""
function bmask end

bmask() = DInt(0)
bmask(ibit::Int...)::DInt = sum([one(DInt) << (b-1) for b in ibit])
bmask(bits::UnitRange{Int})::DInt = ((one(DInt) << (bits.stop - bits.start + 1)) - one(DInt)) << (bits.start-1)

Expand Down
11 changes: 5 additions & 6 deletions test/Blocks/Control.jl
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,11 @@ end
@test mat(g) == op
end

# FIXME:
# @testset "inverse control" begin
# g = ControlBlock{2}([-1, ], X, 2)
@testset "inverse control" begin
g = ControlBlock{2}([-1, ], X, 2)

# op = U ⊗ mat(P0) + IMatrix(U) ⊗ mat(P1)
# @test mat(g) ≈ op
# end
op = U mat(P0) + IMatrix(U) mat(P1)
@test mat(g) op
end

end # control matrix form
23 changes: 17 additions & 6 deletions test/Boost/Gates.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Compat
using Compat.Test
using Yao
using Yao.Blocks
Expand All @@ -13,13 +14,23 @@ using Yao.Boost
end

@testset "controlled gates" begin
@test cxgate(ComplexF64, 2, [2], [1], 1) == [1 0 0 0; 0 1 0 0; 0 0 0 1; 0 0 1 0] == controlled_U1(2, Matrix(mat(X)), [2], [1], 1)
@test cxgate(ComplexF64, 2, [2], [0], 1) == [0 1 0 0; 1 0 0 0; 0 0 1 0; 0 0 0 1] == controlled_U1(2, Matrix(mat(X)), [2], [0], 1)
@test general_controlled_gates(2, [mat(P1)], [2], [mat(X)], [1]) == mat(CNOT)
@test controlled_U1(3, mat(Z), [3], 2) == czgate(ComplexF64, 3, 3, 2)
@test czgate(ComplexF64, 2, 1, 2) == [1 0 0 0; 0 1 0 0; 0 0 1 0; 0 0 0 -1]
@test general_controlled_gates(12, [mat(P1)], [7], [mat(Z)], [3]) == czgate(ComplexF64, 12, 7, 3)
@test cxgate(ComplexF64, 2, 2, 1) == [1 0 0 0; 0 1 0 0; 0 0 0 1; 0 0 1 0]
@test general_controlled_gates(12, [mat(P1)], [7], [mat(X)], [3]) == cxgate(ComplexF64, 12, 7, 3)
@test general_controlled_gates(3, [mat(P1)], [3], [mat(Y)], [2]) == controlled_U1(3, mat(Y), [3], 2) == cygate(ComplexF64, 3, 3, 2)
@test controlled_U1(3, mat(Z), [3], [1], 2) == czgate(ComplexF64, 3, [3], [1], 2)
@test czgate(ComplexF64, 2, [1], [1], 2) == [1 0 0 0; 0 1 0 0; 0 0 1 0; 0 0 0 -1] == controlled_U1(2, mat(Z), [2], [1], 1)
@test general_controlled_gates(12, [mat(P1)], [7], [mat(Z)], [3]) == czgate(ComplexF64, 12, [7], [1], 3)
@test cxgate(ComplexF64, 2, [2], [1], 1) == [1 0 0 0; 0 1 0 0; 0 0 0 1; 0 0 1 0]
@test general_controlled_gates(12, [mat(P1)], [7], [mat(X)], [3]) == cxgate(ComplexF64, 12, [7], [1], 3)

@test general_controlled_gates(3, [mat(P1)], [3], [mat(X)], [2]) == controlled_U1(3, mat(X), [3], [1], 2) == cxgate(ComplexF64, 3, [3], [1], 2)
@test general_controlled_gates(3, [mat(P1)], [3], [mat(Y)], [2]) == controlled_U1(3, mat(Y), [3], [1], 2) == cygate(ComplexF64, 3, [3], [1], 2)
@test general_controlled_gates(3, [mat(P1)], [3], [mat(Z)], [2]) == controlled_U1(3, mat(Z), [3], [1], 2) == czgate(ComplexF64, 3, [3], [1], 2)

# NC
@test general_controlled_gates(3, [mat(P1), mat(P0)], [3, 1], [mat(X)], [2]) == controlled_U1(3, mat(X), [3, 1], [1, 0], 2) == cxgate(ComplexF64, 3, [3, 1], [1, 0], 2)
@test general_controlled_gates(3, [mat(P1), mat(P0)], [3, 1], [mat(Y)], [2]) == controlled_U1(3, mat(Y), [3, 1], [1, 0], 2) == cygate(ComplexF64, 3, [3, 1], [1, 0], 2)
@test general_controlled_gates(3, [mat(P1), mat(P0)], [3, 1], [mat(Z)], [2]) == controlled_U1(3, mat(Z), [3, 1], [1, 0], 2) == czgate(ComplexF64, 3, [3, 1], [1, 0], 2)
end

@testset "single gate" begin
Expand Down

0 comments on commit f98e660

Please sign in to comment.