diff --git a/src/Boost/Control.jl b/src/Boost/Control.jl index 52a7f4feb..8669d8dd7 100644 --- a/src/Boost/Control.jl +++ b/src/Boost/Control.jl @@ -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 diff --git a/src/Boost/gates.jl b/src/Boost/gates.jl index f14c3f589..f25489451 100644 --- a/src/Boost/gates.jl +++ b/src/Boost/gates.jl @@ -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<testval(i, mask, onemask) ? MT(-1) : MT(1), basis(num_bit)) Diagonal(vals) end @@ -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<(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 diff --git a/src/Intrinsics/Basis.jl b/src/Intrinsics/Basis.jl index 6d5e49b91..9381949ba 100644 --- a/src/Intrinsics/Basis.jl +++ b/src/Intrinsics/Basis.jl @@ -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) diff --git a/test/Blocks/Control.jl b/test/Blocks/Control.jl index 074ed02b1..f6978bbd2 100644 --- a/test/Blocks/Control.jl +++ b/test/Blocks/Control.jl @@ -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 diff --git a/test/Boost/Gates.jl b/test/Boost/Gates.jl index d52db2bce..1fcee4190 100644 --- a/test/Boost/Gates.jl +++ b/test/Boost/Gates.jl @@ -1,3 +1,4 @@ +using Compat using Compat.Test using Yao using Yao.Blocks @@ -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