Skip to content

Commit

Permalink
add docstrings
Browse files Browse the repository at this point in the history
  • Loading branch information
GiggleLiu committed Dec 16, 2021
1 parent a48e99d commit e3fc22b
Show file tree
Hide file tree
Showing 14 changed files with 125 additions and 129 deletions.
28 changes: 24 additions & 4 deletions src/EasyBuild/block_extension/FSimGate.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
export FSimGate
export FSimGate, fsim_block

# https://arxiv.org/pdf/1711.04789.pdf
# Google supremacy paper
"""
FSimGate{T<:Number} <: PrimitiveBlock{2}
The two parameter `FSim` gate.
References
-------------------------
* Arute, Frank, et al. "Quantum supremacy using a programmable superconducting processor." Nature 574.7779 (2019): 505-510.
"""
mutable struct FSimGate{T<:Number} <: PrimitiveBlock{2}
theta::T
phi::T
Expand All @@ -28,4 +35,17 @@ function YaoAPI.setiparams!(fs::FSimGate{T}, θ, ϕ) where T
end

YaoBlocks.@dumpload_fallback FSimGate FSimGate
YaoBlocks.Optimise.to_basictypes(fs::FSimGate) = fsim_block(fs.theta, fs.phi)
YaoBlocks.Optimise.to_basictypes(fs::FSimGate) = fsim_block(fs.theta, fs.phi)

"""
fsim_block(θ::Real, ϕ::Real)
The circuit representation of FSim gate.
"""
function fsim_block::Real, ϕ::Real)
if θ π/2
return cphase(2,2,1,-ϕ)*SWAP*rot(kron(Z,Z), -π/2)*put(2,1=>phase(-π/4))
else
return cphase(2,2,1,-ϕ)*rot(SWAP,2*θ)*rot(kron(Z,Z), -θ)*put(2,1=>phase/2))
end
end
18 changes: 5 additions & 13 deletions src/EasyBuild/block_extension/shortcuts.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export cphase, ISWAP, SqrtX, SqrtY, SqrtW
export ISWAPGate, SqrtXGate, SqrtYGate, SqrtWGate
export ISWAP, SqrtX, SqrtY, SqrtW, singlet_block
export ISWAPGate, SqrtXGate, SqrtYGate, SqrtWGate, CPhaseGate

const CPhaseGate{N, T} = ControlBlock{N,<:ShiftGate{T},<:Any}

Expand All @@ -9,17 +9,9 @@ const CPhaseGate{N, T} = ControlBlock{N,<:ShiftGate{T},<:Any}
# √W is a non-Clifford gate
@const_gate SqrtW = mat(rot((X+Y)/sqrt(2), π/2))

singlet_block() = chain(put(2, 1=>chain(X, H)), control(2, -1, 2=>X))

"""
fsim_block(θ::Real, ϕ::Real)
singlet_block(θ::Real, ϕ::Real)
The circuit representation of FSim gate.
The circuit block for initialzing a singlet state.
"""
function fsim_block::Real, ϕ::Real)
if θ π/2
return cphase(2,2,1,-ϕ)*SWAP*rot(kron(Z,Z), -π/2)*put(2,1=>phase(-π/4))
else
return cphase(2,2,1,-ϕ)*rot(SWAP,2*θ)*rot(kron(Z,Z), -θ)*put(2,1=>phase/2))
end
end
singlet_block() = chain(put(2, 1=>chain(X, H)), control(2, -1, 2=>X))
6 changes: 6 additions & 0 deletions src/EasyBuild/general_U4.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ Impliments PRA 69.062321.

export general_U2, general_U4

"""
general_U2(θ1, θ2, θ3; ϕ=nothing)
A general single qubits gate: ``e^(iϕ)R_z(θ_3)R_y(θ_2)R_z(θ_1)``.
Leave `ϕ` as `nothing` to fix the global phase.
"""
function general_U2(θ1, θ2, θ3; ϕ=nothing)
gate = Rz(θ3) * Ry(θ2) * Rz(θ1)
if ϕ !== nothing
Expand Down
6 changes: 5 additions & 1 deletion src/EasyBuild/google53.jl
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,11 @@ end
"""
rand_google53(depth::Int; nbits=53) -> AbstactBlock
random google supremacy circuit with 53 qubits.
Google supremacy circuit with 53 qubits, also know as the Sycamore quantum supremacy circuits.
References
-------------------------
* Arute, Frank, et al. "Quantum supremacy using a programmable superconducting processor." Nature 574.7779 (2019): 505-510.
"""
function rand_google53(depth::Int; nbits::Int=53)
c = chain(nbits)
Expand Down
18 changes: 15 additions & 3 deletions src/EasyBuild/hadamardtest.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
export hadamard_test, hadamard_test_circuit, swap_test_circuit

"""
see WiKi.
hadamard_test_circuit(U::AbstractBlock, ϕ::Real)
The Hadamard test circuit.
References
-----------------------
* [Wiki](https://en.wikipedia.org/wiki/Hadamard_test_(quantum_computation))
"""
function hadamard_test_circuit(U::AbstractBlock{N}, ϕ::Real) where N
chain(N+1, put(N+1, 1=>H),
Expand All @@ -18,8 +24,14 @@ function hadamard_test(U::AbstractBlock{N}, reg::AbstractRegister, ϕ::Real) whe
end

"""
Estimation of overlap between multiple density matrices.
PRL 88.217901
swap_test_circuit(nbit::Int, nstate::Int, ϕ::Real)
The swap test circuit for computing the overlap between multiple density matrices.
The `nbit` and `nstate` specifies the number of qubit in each state and how many state we want to compare.
References
-----------------------
* Ekert, Artur K., et al. "Direct estimations of linear and nonlinear functionals of a quantum state." Physical review letters 88.21 (2002): 217901.
"""
function swap_test_circuit(nbit::Int, nstate::Int, ϕ::Real)
N = nstate*nbit + 1
Expand Down
16 changes: 11 additions & 5 deletions src/EasyBuild/hamiltonians.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ export heisenberg, transverse_ising
"""
heisenberg(nbit::Int; periodic::Bool=true)
1D heisenberg hamiltonian, for its ground state, refer `PRB 48, 6141`.
1D Heisenberg hamiltonian defined as ``\\sum_{i=1}^{n} X_{i}X_{i+1} + Y_{i}Y_{i+1} + Z_{i}Z_{i+1}``, where ``n`` is specified by `nbit`.
`periodic` means the boundary condition is periodic.
References
----------------------
* de Oliveira, Mário J. "Ground-state properties of the spin-1/2 antiferromagnetic Heisenberg chain obtained by use of a Monte Carlo method." Physical Review B 48.9 (1993): 6141-6143.
"""
function heisenberg(nbit::Int; periodic::Bool=true)
map(1:(periodic ? nbit : nbit-1)) do i
Expand All @@ -13,13 +18,14 @@ function heisenberg(nbit::Int; periodic::Bool=true)
end

"""
transverse_ising(nbit::Int; periodic::Bool=true)
transverse_ising(nbit::Int, h::Number; periodic::Bool=true)
1D transverse ising hamiltonian.
1D transverse Ising hamiltonian defined as ``\\sum_{i=1}^{n} hX_{i} + Z_{i}Z_{i+1}``, where ``n`` is specified by `nbit`.
`periodic` means the boundary condition is periodic.
"""
function transverse_ising(nbit::Int; periodic::Bool=true)
function transverse_ising(nbit::Int, h::Number; periodic::Bool=true)
ising_term = map(1:(periodic ? nbit : nbit-1)) do i
repeat(nbit,Z,(i,i%nbit+1))
end |> sum
ising_term + sum(map(i->put(nbit,i=>X), 1:nbit))
ising_term + h*sum(map(i->put(nbit,i=>X), 1:nbit))
end
35 changes: 22 additions & 13 deletions src/EasyBuild/phaseestimation.jl
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
export phase_estimation_circuit, projection_analysis
export phase_estimation_circuit, phase_estimation_analysis

"""
phase_estimation_circuit(UG, n_reg, n_b) -> ChainBlock
phase estimation circuit.
* `UG`: the input unitary matrix.
* `n_reg`: the number of bits to store phases,
* `n_b`: the number of bits to store vector.
phase_estimation_circuit(unitarygate::GeneralMatrixBlock, n_reg, n_b) -> ChainBlock
Phase estimation circuit. Input arguments are
* `unitarygate`: the input unitary matrix.
* `n_reg`: the number of bits to store phases,
* `n_b`: the number of bits to store vector.
References
----------------------
[Wiki](https://en.wikipedia.org/wiki/Quantum_phase_estimation_algorithm)
"""
function phase_estimation_circuit(UG::GeneralMatrixBlock, n_reg::Int, n_b::Int)
function phase_estimation_circuit(unitarygate::GeneralMatrixBlock, n_reg::Int, n_b::Int)
nbit = n_b + n_reg
# Apply Hadamard Gate.
hs = repeat(nbit, H, 1:n_reg)

# Construct a control circuit.
control_circuit = chain(nbit)
for i = 1:n_reg
push!(control_circuit, control(nbit, (i,), (n_reg+1:nbit...,)=>UG))
push!(control_circuit, control(nbit, (i,), (n_reg+1:nbit...,)=>unitarygate))
if i != n_reg
UG = matblock(mat(UG) * mat(UG))
unitarygate = matblock(mat(unitarygate) * mat(unitarygate))
end
end

Expand All @@ -26,12 +33,14 @@ function phase_estimation_circuit(UG::GeneralMatrixBlock, n_reg::Int, n_b::Int)
end

"""
projection_analysis(evec::Matrix, reg::ArrayReg) -> Tuple
Analyse using state projection.
phase_estimation_analysis(eigenvectors::Matrix, reg::ArrayReg) -> Tuple
Analyse phase estimation result using state projection.
It returns a tuple of (most probable configuration, the overlap matrix, the relative probability for this configuration)
`eigenvectors` is the eigen vectors of the unitary gate matrix, while `reg` is the result of phase estimation.
"""
function projection_analysis(evec::Matrix, reg::ArrayReg)
overlap = evec'*state(reg)
function phase_estimation_analysis(eigenvectors::AbstractMatrix, reg::ArrayReg)
overlap = eigenvectors'*state(reg)
amp_relative = Float64[]
bs = Int[]

Expand Down
6 changes: 5 additions & 1 deletion src/EasyBuild/qft_circuit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ cphase(nbits::Int, i::Int, j::Int, θ::T) where T = control(nbits, i, j=>shift(
"""
qft_circuit(n)
Create a Quantum Fourer Transform circuit. See also [`QFT`](@ref).
The quantum Fourer transformation (QFT) circuit.
References
------------------------
* [Wiki](https://en.wikipedia.org/wiki/Quantum_Fourier_transform)
"""
qft_circuit(n::Int) = chain(n, hcphases(n, i) for i = 1:n)
hcphases(n, i) = chain(n, i==j ? put(i=>H) : cphase(n, j, i, 2π/(2^(j-i+1))) for j in i:n);
37 changes: 12 additions & 25 deletions src/EasyBuild/supremacy_circuit.jl
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
export rand_supremacy2d
export pair_supremacy, print_square_bond, cz_entangler
"""
control-Z entangler.
"""

# control-Z entangler.
cz_entangler(n::Int, pairs) = chain(n, control(n, [ctrl], target=>Z) for (ctrl, target) in pairs)

"""
rand_supremacy2d(nx::Int, ny::Int, depth::Int) -> AbstactBlock
random supremacy circuit.
The circuit proposed for realizing quantum supermacy in a near-term device.
NOTE: the restriction to `T` gate is removed.
References
-------------------------------
* Boixo, Sergio, et al. "Characterizing quantum supremacy in near-term devices." Nature Physics 14.6 (2018): 595-600.
!!! note
Some restrictions are loosed, please check this circuit carefully.
"""
function rand_supremacy2d(nx::Int, ny::Int, depth::Int)
nbits = nx*ny
Expand All @@ -36,7 +40,7 @@ function rand_supremacy2d(nx::Int, ny::Int, depth::Int)
return c
end

"""obtain supremacy pairing patterns"""
# obtain supremacy pairing patterns
function pair_supremacy(nx::Int, ny::Int; periodic=false)
Kx = [0.25 0.5; 0.25 -0.5]
Ky = [0.5 0.25; -0.5 0.25]
Expand All @@ -57,21 +61,4 @@ function pair_supremacy(nx::Int, ny::Int; periodic=false)
end

return out
end

print_square_bond(nx::Int, ny::Int, bonds) = print_square_bond(stdout, nx, ny, bonds)
function print_square_bond(io::IO, nx::Int, ny::Int, bonds)
li = LinearIndices((nx, ny))
for j=1:ny
for i=1:nx
print(io, "")
i!=nx && print(io, ((li[i,j] => li[i+1,j]) in bonds || (li[i+1,j] => li[i,j]) in bonds) ? "---" : " ")
end
println(io)
j!=ny && for i=1:nx
print(io, ((li[i,j] => li[i,j+1]) in bonds || (li[i,j] => li[i,j+1]) in bonds) ? "|" : " ")
j!=ny && print(io, " ")
end
println(io)
end
end
end
68 changes: 16 additions & 52 deletions src/EasyBuild/variational_circuit.jl
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
using YaoArrayRegister.StatsBase: sample

export pair_ring, pair_square
export rotor, merged_rotor, rotorset
export variational_circuit
export rand_single_gate, rand_gate, rand_circuit

################## Entangler ###################
"""
pair_ring(n::Int) -> Vector
Pair ring.
Pair ring entanglement layout.
"""
pair_ring(n::Int) = [i=>mod(i, n)+1 for i=1:n]

"""
pair_square(m::Int, n::Int) -> Vector
Pair square.
Pair square entanglement layout.
"""
function pair_square(m::Int, n::Int; periodic=false)
res = Vector{Pair{Int, Int}}(undef, (m-!periodic)*n+m*(n-!periodic))
Expand Down Expand Up @@ -83,17 +80,19 @@ rotorset(mode::Symbol, nbit::Int, noleading::Bool=false, notrailing::Bool=false)
variational_circuit(nbit[, nlayer][, pairs]; mode=:Split, do_cache=false, entangler=cnot)
A kind of widely used differentiable quantum circuit, angles in the circuit is randomely initialized.
* pairs: list of `Pair`s for entanglers in a layer, default to `pair_ring` structure,
* mode: :Split or :Merged,
* do_cache: cache the entangler matrix,
* entangler: a constructor returns a two qubit gate, `f(n,i,j) -> gate`.
The default value is `cnot(n,i,j)`.
ref:
1. Kandala, A., Mezzacapo, A., Temme, K., Takita, M., Chow, J. M., & Gambetta, J. M. (2017).
Hardware-efficient Quantum Optimizer for Small Molecules and Quantum Magnets. Nature Publishing Group, 549(7671), 242–246.
https://doi.org/10.1038/nature23879.
Input arguments are
* `pairs` is list of `Pair`s for entanglers in a layer, default to `pair_ring` structure,
* `mode` can be :Split or :Merged,
* `do_cache` decides whether cache the entangler matrix or not,
* `entangler` is a constructor returns a two qubit gate, `f(n,i,j) -> gate`.
The default value is `cnot(n,i,j)`.
References
-------------------------
1. Kandala, A., Mezzacapo, A., Temme, K., Takita, M., Chow, J. M., & Gambetta, J. M. (2017).
Hardware-efficient Quantum Optimizer for Small Molecules and Quantum Magnets. Nature Publishing Group, 549(7671), 242–246.
https://doi.org/10.1038/nature23879.
"""
function variational_circuit(nbit, nlayer, pairs; mode=:Split, do_cache=false, entangler=cnot)
circuit = chain(nbit)
Expand All @@ -112,39 +111,4 @@ end

variational_circuit(n::Int; kwargs...) = variational_circuit(n, 3, pair_ring(n); kwargs...)

variational_circuit(nbit::Int, nlayer::Int; kwargs...) = variational_circuit(nbit, nlayer, pair_ring(nbit), kwargs...)

############### Completely random circuits (for testing and demo) ################
randlocs(nbit::Int, mbit::Int) = sample(1:nbit, mbit, replace=false)
const SINGLE_GATES = [X, Y, Z, H, Rx, Ry, Rz, shift, phase]

rand_single_gate(ngate::Int) = [rand_single_gates() for i=1:ngate]
function rand_single_gate()
gate = rand(SINGLE_GATES)
gate isa AbstractBlock ? gate : gate(rand()*2π)
end

"""
rand_gate(nbit::Int, mbit::Int, [ngate::Int]) -> AbstractBlock
random nbit gate.
"""
rand_gate(nbit::Int, mbit::Int) = rand_gate(nbit, Val(mbit))
rand_gate(nbit::Int, mbit::Int, ngate::Int) = [rand_gate(nbit, mbit) for i=1:ngate]
rand_gate(nbit::Int, ::Val{1}) = put(nbit, rand(1:nbit)=>rand_single_gate())
function rand_gate(nbit::Int, ::Val{M}) where M
locs = randlocs(nbit, M)
control(nbit, locs[1:M-1], last(locs)=>rand_single_gate())
end

function rand_circuit(nbit::Int; p1 = (nbit==1 ? 1.0 : 0.66), ngate=5*nbit)
c = chain(nbit)
for i=1:ngate
if rand() < p1
push!(c, rand_gate(nbit, 1))
else
push!(c, rand_gate(nbit, 2))
end
end
c
end
variational_circuit(nbit::Int, nlayer::Int; kwargs...) = variational_circuit(nbit, nlayer, pair_ring(nbit), kwargs...)
2 changes: 1 addition & 1 deletion test/easybuild/hamiltonians.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ using Yao.ConstGate
nbit = 8
h = heisenberg(nbit) |> cache
@test ishermitian(h)
h = transverse_ising(nbit)
h = transverse_ising(nbit, 1.0)
@test ishermitian(h)
end
Loading

0 comments on commit e3fc22b

Please sign in to comment.