幺

Extensible Efficient Quantum Algorithm Design for Humans.

rogerluo.me

Install Julia:

official compiler: julialang.org/downloads

julia pro (annaconda for julia): juliacomputing.com

Install our package:

lastest:

julia> Pkg.clone("https://github.com/QuantumBFS/Yao.jl.git")

stable:

julia> Pkg.add("Yao")

Quantum Computing

Potential Applications for Near Term Small Quantum Computers:

  • Quantum Chemistry
  • Quantum Co-Processor
  • Secret Sharing
  • Machine Learning

Ref: Technical Roadmap for Fault-Tolerant Quantum Computing

Quantum Chemistry

O’Malley, P. J. J., et al. "Scalable quantum simulation of molecular energies." Physical Review X 6.3 (2016): 031007.

Quantum Co-processor

Kreula, Juha M., et al. "Few-qubit quantum-classical simulation of strongly correlated lattice fermions." EPJ Quantum Technology 3.1 (2016): 11.

Machine Learning

Xandadu AI, Quantum Machine Learning 1.0

Gao, Xun, Zhengyu Zhang, and Luming Duan. "An efficient quantum algorithm for generative machine learning." arXiv preprint arXiv:1711.02038 (2017).

Liu, Jin-Guo, and Lei Wang. "Differentiable learning of quantum circuit Born machine." arXiv preprint arXiv:1804.04168 (2018).

Mitarai, Kosuke, et al. "Quantum circuit learning." arXiv preprint arXiv:1803.00745 (2018).

Quantum Computing is Approaching

Source: © By Thomas A. Campbell, Ph.D., FutureGrasp, LLC

roadmap

J. Ignacio Cirac & H. Jeff Kimble. "Quantum optics, what next?" Nature Photonics volume 11, pages 18–20 (2017).

Google IBM

Source: © By Nick Summers, engadget / Google AI lab

What is 幺?

幺(Yao) is a Extensible, Efficient framework for quantum algorithm design.

What can 幺 do?

Quantum Computing: Basics

Review: Linear Algebra

Matrix Vector Multiplication

\begin{pmatrix} a & b\\ c & d \end{pmatrix} \begin{pmatrix} x \\ y \end{pmatrix} = \begin{pmatrix} ax + by \\ cx + dy \end{pmatrix}

Matrix Matrix Multiplication

\begin{pmatrix} a & b\\ c & d \end{pmatrix}\begin{pmatrix} w & x\\ y & z \end{pmatrix} = \begin{pmatrix} aw + by & ax + bz\\ cw + dy & cx + dz \end{pmatrix}

Identity Matrix

I\cdot \begin{pmatrix} a\\ b\\ c\\ d \end{pmatrix} = \begin{pmatrix} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & 1\\ \end{pmatrix}\begin{pmatrix} a\\ b\\ c\\ d \end{pmatrix} = \begin{pmatrix} a\\ b\\ c\\ d \end{pmatrix}

Swap Matrix

\begin{pmatrix} 1 & 0 & 0 &0\\ 0 & 0 & 1 &0\\ 0 & 1 & 0 &0\\ 0 & 0 & 0 &1 \end{pmatrix}\begin{pmatrix} 0\\ 1\\ 0\\ 0 \end{pmatrix} = \begin{pmatrix} 0\\ 0\\ 1\\ 0 \end{pmatrix}
\begin{pmatrix} x_0 \\ x_1 \end{pmatrix}\otimes\begin{pmatrix} y_0 \\ y_1 \end{pmatrix} = \begin{pmatrix} x_0 \begin{pmatrix} y_0\\ y_1 \end{pmatrix} \\ x_1 \begin{pmatrix} y_0\\ y_1 \end{pmatrix} \end{pmatrix} = \begin{pmatrix} x_0 y_0 \\ x_0 y_1 \\ x_1 y_0 \\ x_1 y_1 \end{pmatrix}
|00\rangle = \begin{pmatrix} 1\\ 0 \end{pmatrix} \otimes \begin{pmatrix} 1\\ 0 \end{pmatrix} = \begin{pmatrix} 1\\ 0\\ 0\\ 0 \end{pmatrix}
|10\rangle = \begin{pmatrix} 0\\ 1 \end{pmatrix} \otimes \begin{pmatrix} 1\\ 0 \end{pmatrix} = \begin{pmatrix} 0\\ 0\\ 1\\ 0 \end{pmatrix}
|01\rangle = ?

Try this

register(bit"01") |> statevec
name function matrix
Identity f(x) = x \begin{pmatrix} 1 & 0\\0 & 1\end{pmatrix}
Negation f(x) = \neg x \begin{pmatrix} 0 & 1\\1 & 0\end{pmatrix}
Const-0 f(x) = 0 \begin{pmatrix} 1 & 1\\0 & 0\end{pmatrix}
Const-1 f(x) = 1 \begin{pmatrix} 0 & 0\\1 & 1\end{pmatrix}

Negation

with!(X, register(bit"0")) |> statevec

Operations on multiple Bits: CNOT

\begin{pmatrix} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 0 & 1\\ 0 & 0 & 1 & 0 \end{pmatrix}

Try

g = control(2, [1, ], 2=>X)
with!(g, register(bit"10")) |> statevec

with!(g, register(bit"00")) |> statevec

quantum bits

\begin{pmatrix} \frac{1}{\sqrt{2}}\\ \frac{1}{\sqrt{2}} \end{pmatrix}\quad \begin{pmatrix} \frac{-1}{\sqrt{2}}\\ \frac{1}{\sqrt{2}} \end{pmatrix}\quad \begin{pmatrix} im\\ 0 \end{pmatrix}

construct a quantum bit: \frac{|0000\rangle + |1111\rangle}{\sqrt{2}}

r = register(bit"0000") + register(bit"1111")
normalize!(r)

Then measure it:

measure(r, 5)

We have constrain:

||a||^2 + ||b||^2 = 1 \Rightarrow \begin{pmatrix} cos(\frac{\theta}{2})\\ e^{im\phi} sin(\frac{\theta}{2}) \end{pmatrix}

Bloch-sphere

name matrix
Identity \begin{pmatrix} 1 & 0\\0 & 1\end{pmatrix}
X (Negation) \begin{pmatrix} 0 & 1\\1 & 0\end{pmatrix}
Y \begin{pmatrix} 0 & -im\\im & 0\end{pmatrix}
Z \begin{pmatrix} 1 & 0\\0 & -1\end{pmatrix}

Try them see what happens

r = register(bit"0000") + register(bit"0000")
normalize!(r)
apply!(r, X)

Demo 1: Preparing GHZ state

A GHZ state is a quantum state looks like:

\frac{|0\cdots 0\rangle - |1\cdots 1\rangle}{\sqrt{2}}

We will use a quantum circuit to prepare a GHZ state from |0\cdots 0\rangle

GHZ-Circuit

GHZ-Circuit

circuit = chain(
    4,
    kron(i==1?i=>X:i=>H for i in 1:4),
    control([2, ], 1=>X),
    control([4, ], 3=>X),
    control([3, ], 1=>X),
    control([4, ], 3=>X),
    kron(i=>H for i in 1:4),
)
help?> X

  X

  The Pauli-X gate acts on a single qubit. It is the quantum equivalent of the NOT gate
  for classical computers (with respect to the standard basis |0\rangle, |1\rangle). It
  is represented by the Pauli X matrix:

X = \begin{pmatrix}
0 & 1\\
1 & 0
\end{pmatrix}

Define initial state of a quantum register: |0000\rangle

julia> r = register(bit"0000")

You can define how to apply several blocks inside a context with julia's do block:

# creates a new register
new = with(r) do r
  r |> kron(i==1?i=>X:i=>H for i in 1:4)
  r |> control([2, ], 1=>X) |> control([4, ], 3=>X)
  r |> control([3, ], 1=>X) |> control([4, ], 3=>X)
  r |> kron(i=>H for i in 1:4)
end

# apply blocks in-place
with!(r) do r
  r |> kron(i==1?i=>X:i=>H for i in 1:4)
  r |> control([2, ], 1=>X) |> control([4, ], 3=>X)
  r |> control([3, ], 1=>X) |> control([4, ], 3=>X)
  r |> kron(i=>H for i in 1:4)
end

Or use a wrapped quantum circuit.

# creates a new register
new = with(circuit, r)
# in-place
with!(circuit, r)
using PyPlot
plt[:hist](measure(r, 1000))

kronecker = kron(4, 1=>X, H, H, H)
roller = roll(4, 1=>X, H, H, H)
julia> using BenchmarkTools

julia> @benchmark with!(roller, $(register(bit"0000")))
BenchmarkTools.Trial:
  memory estimate:  4.80 KiB
  allocs estimate:  55
  --------------
  minimum time:     2.328 μs (0.00% GC)
  median time:      2.428 μs (0.00% GC)
  mean time:        2.990 μs (12.86% GC)
  maximum time:     288.347 μs (94.90% GC)
  --------------
  samples:          10000
  evals/sample:     9
julia> @benchmark with!(kronecker, $(register(bit"0000")))
BenchmarkTools.Trial:
  memory estimate:  18.55 KiB
  allocs estimate:  120
  --------------
  minimum time:     47.241 μs (0.00% GC)
  median time:      51.462 μs (0.00% GC)
  mean time:        56.150 μs (3.51% GC)
  maximum time:     2.768 ms (95.15% GC)
  --------------
  samples:          10000
  evals/sample:     1

roller = roll(4, 1=>X, H, H, H)

Demo 2: Quantum Circuit Born Machine

Please open the notebook

julia> using IJulia

julia> notebook(joinpath(Pkg.dir("Yao"), "examples"))

Hierarchical APIs

structre

bench-xyz bench-rxyz

bench-cxyz bench-repeatxyz

bench-toffoli bench-crot

Flexible Block System

block tree

Make use of Multiple Dispatch

1.the matrix form

2.how to apply on a quantum state

julia> @const_gate MyConstGate = ComplexF64[0.5 0;-0.2 0.2]
function apply!(r::AbstractRegister, g::MyConstGate)
  # some better way to apply
  # this operator to quantum register
  r
end
using Yao, Yao.Blocks # use 3rd hierarchy API: Blocks

import Yao.Blocks: mat, dispatch!, parameters # this is the mimimal methods you will need to overload

mutable struct NewPrimitive{T} <: PrimitiveBlock{1, T}
   theta::T
end
mat(g::NewPrimitive{T}) where T = Complex{T}[sin(g.theta) 0; cos(g.theta) 0]
import Yao.Blocks: apply!
apply!(r::AbstractRegister, x::NewPrimitive) = # some efficient way to simulate this block
dispatch!(g::NewPrimitive, theta) = (g.theta = theta; g)
parameters(x::NewPrimitive) = x.theta
mutable struct MultiParam{N, T} <: PrimitiveBlock{N, Complex{T}}
  theta::T
  phi::T
end

just write

dispatch!(x::MultiParam, theta, phi) = (x.theta = theta; x.phi = phi; x)

Low abstraction

Each block represents a different approach of calculation

  • kron -> kronecker product
  • roll -> reshape & roll dims
  • repeat -> repeat a block on given lines

ROADMAPs

  • More fine-tuned optimizations
  • GPU support
  • Special register states support: Stabilizers, MPS, etc.
  • real quantum devices acceleration (like GPUs)

Follow us on Github: Yao.jl