I’ve decided to go thorough the collection of quantum computing exercises Quantum Katas which was created by Microsoft. However, instead of Q# language, I’ll write them in Julia language, and Yao quantum computing library.
The exercises designed to give a basic concepts on quantum computing, and quantum algorithms which include complex number arithmetic, linear algebra, qubits, measurements, and etc.
I’ll start with basic concepts using the Julia language at the beginning, and then gradually introduce features from linear algebra and quantum libraries for more complex exercises.
Following exercises come from Complex arithmetic and Linear algebra tutorials.
TOC
- Complex Arithmetic
- Exercise 1: Powers of $i$
- Exercise 2: Complex Addition
- Exercise 3: Complex Multiplication
- Exercise 4: Complex Conjugate
- Exercise 5: Complex Division
- Exercise 6: Modulus
- Exercise 7: Complex exponents
- Exercise 8: Complex powers of real numbers
- Exercise 9: Cartesian to polar conversion
- Exercise 10: Polar to Cartesian conversion
- Exercise 11: Polar multiplication
- Exercise 12: Arbitrary complex exponents
- Linear Algebra
- Advanced Operations
Complex Arithmetic
We start with complex arithmetic. This topic isn’t difficult, but it’s important to understand it to be able to work with quantum computing. The following exersises are easily solved as Julia provides build-in Complex
type for representing the complex numbers, and a variety of operations and functions for this type.
Exercise 1: Powers of $i$
- Input: An even integer.
- Goal: Return the $n$th power of $i$, or $i^n$.
imaginary_power(n) = (0 + 1im)^n
imaginary_power(0), imaginary_power(1), imaginary_power(2), imaginary_power(3), imaginary_power(4)
(1 + 0im, 0 + 1im, -1 + 0im, 0 - 1im, 1 + 0im)
Exercise 2: Complex Addition
- Input: A complex numbers $x$ and $y$.
- Goal: Return the sum of these two numbers.
complex_add(x::Complex,y::Complex) = x + y
complex_add(1 + 3im, 2 - 1im)
3 + 2im
Exercise 3: Complex Multiplication
- Input: A complex numbers $x$ and $y$.
- Goal: Return the product of these two numbers.
complex_mult(x::Complex,y::Complex) = x * y
complex_mult(1 + 3im, 2 - 1im)
5 + 5im
Exercise 4: Complex Conjugate
- Input: A complex number $x$.
- Goal: Return its conjugate.
conjugate(x::Complex) = adjoint(x)
conjugate(1 + 3im)
1 - 3im
Exercise 5: Complex Division
- Input: A complex numbers $x$ and $y$.
- Goal: Return the quotient of these two numbers.
complex_div(x::Complex,y::Complex) = x / y
complex_div(1 + 3im, 2 - 1im)
-0.2 + 1.4im
Exercise 6: Modulus
- Input: A complex number $x$.
- Goal: Return the modulus of this number, $|x|$.
modulus(x::Complex) = abs(x)
modulus(3 + 4im)
5.0
Exercise 7: Complex exponents
- Input: A complex number $x$.
- Goal: Return the complex number $e^x$.
complex_exp(x::Complex) = exp(x)
complex_exp(1 + 1im)
1.4686939399158851 + 2.2873552871788423im
Exercise 8: Complex powers of real numbers
- Input: A non-negative real number $r$ and a complex number $x$.
- Goal: Return the complex number $r^x$.
complex_exp_real(r::Real, x::Complex) = r^x
complex_exp_real(2.0, 2-1im)
3.0769556054558884 - 2.555845105254539im
Exercise 9: Cartesian to polar conversion
- Input: A complex number $x$.
- Goal: Return the polar representation of $x = r e^{i\theta}$, i.e., the distance from origin and phase as a tuple $(r, \theta)$.
function polar_convert(x::Complex)
θ = atan(x.im, x.re)
r = abs(x)
(r, θ)
end
polar_convert(-3 + 2im)
(3.605551275463989, 2.5535900500422257)
Exercise 10: Polar to Cartesian conversion
- Input: A complex number $x$, represented in polar form as a tuple $(r, \theta)$.
- Goal: Return the Cartesian representation of $x$.
function cartesian_convert(p::Tuple{Real, Real})
r, θ = p
complex(r*cos(θ), r*sin(θ))
end
cartesian_convert(polar_convert(-3 + 2im))
-3.0 + 2.0im
Exercise 11: Polar multiplication
- Input: A non-negative real number $r$ and a complex number $x$.
- Goal: Return the complex number $r^x$.
function polar_mult(p::Tuple{Real, Real}, q::Tuple{Real, Real})
r₁, θ₁ = p
r₂, θ₂ = q
θ = θ₁ + θ₂
θ = θ > π ? θ - π : θ
θ = θ <= -π ? θ + π : θ
(r₁*r₂, θ)
end
polar_mult((2.0, 0.7853981633974483), (3.0, 0.7853981633974483))
(6.0, 1.5707963267948966)
Exercise 12: Arbitrary complex exponents
- Input: A complex numbers $x$ and $y$.
- Goal: Return the result of raising $x$ to the power of $y$: $x^y$.
complex_exp_arbitrary(x::Complex, y::Complex) = x^y
complex_exp_arbitrary(1+2im, -1+1im)
0.14109608324475698 - 0.0440220513678384im
Linear Algebra
Next collection of exercises is on linear algebra related to quantum computing, in particular, the various properties of matrices and vectors, which are used extensively in quantum computing to represent quantum states and operations on them.
And again, most of the required functionality is provided in Julia standard libraries, i.e. LinearAlgebra
package which provides the vector and matrix types, and corresponding operations and functions.
using LinearAlgebra # use linear algebra package from Julia stdlib
X = [1 2; 3 4]
2×2 Matrix{Int64}:
1 2
3 4
Y = [4 3 ; 2 1]
2×2 Matrix{Int64}:
4 3
2 1
Exercise 1: Matrix addition
- Input: Two $m \times n$-matrices $A$ and $B$.
- Goal: Return the sum of the matrices $A+B$ as an $m \times n$-matrix.
matrix_add(A::Matrix, B::Matrix) = A + B # quite trivial
matrix_add(X, Y)
2×2 Matrix{Int64}:
5 5
5 5
Exercise 2: Scalar multiplication
- Input: A scalar $x$ and an $m \times n$ matrix $A$.
- Goal: Return an $m \times n$ matrix $x \cdot A$.
scalar_mult(x::Real, A::Matrix) = x*A
scalar_mult(2, X)
2×2 Matrix{Int64}:
2 4
6 8
Exercise 3: Matrix multiplication
- Input: An $m \times n$-matrix $A$ and an $n \times k$-matrix $B$.
- Goal: Return the product of the matrices $A \times B$ as a $m \times k$ matrix.
matrix_mult(A::Matrix, B::Matrix) = A*B
matrix_mult(X, Y)
2×2 Matrix{Int64}:
8 5
20 13
Exercise 4: Matrix inversion
- Input: An invertible $2 \times 2$ matrix $A$.
- Goal: Return the inverse of $A$, a $2 \times 2$ matrix $A^{-1}$.
matrix_inverse(A::Matrix) = inv(A)
matrix_inverse(X) |> display # A⁻¹
matrix_mult(matrix_inverse(X), X) # A⁻¹*A = I
2×2 Matrix{Float64}:
-2.0 1.0
1.5 -0.5
2×2 Matrix{Float64}:
1.0 0.0
2.22045e-16 1.0
Exercise 5: Matrix transpose
- Input: An $m \times n$ matrix $A$.
- Goal: Return the transpose of $A$, a $n \times m$ matrix $A^{T}$.
matrix_transpose(A::Matrix) = transpose(A) # or A'
[1 2; 3 4; 5 6] |> display
matrix_transpose([1 2; 3 4; 5 6])
3×2 Matrix{Int64}:
1 2
3 4
5 6
2×3 transpose(::Matrix{Int64}) with eltype Int64:
1 3 5
2 4 6
For following exercises, we need some complex matrices.
Z = [1+2im 2+0im; -1-2im 1.5-1im]
2×2 Matrix{ComplexF64}:
1.0+2.0im 2.0+0.0im
-1.0-2.0im 1.5-1.0im
U = [1/√2 1/√2; 1im/√2 -1im/√2]
2×2 Matrix{ComplexF64}:
0.707107+0.0im 0.707107+0.0im
0.0+0.707107im 0.0-0.707107im
Exercise 6: Conjugate
- Input: An $m \times n$ matrix $A$.
- Goal: Return the conjugate of $A$, a $m \times n$ matrix $\bar{A}$.
conjugate(A::Matrix) = adjoint.(A)
conjugate(Z)
2×2 Matrix{ComplexF64}:
1.0-2.0im 2.0-0.0im
-1.0+2.0im 1.5+1.0im
Exercise 7: Adjoint
- Input: An $m \times n$ matrix $A$.
- Goal: Return the adjoint of $A$, a $m \times n$ matrix $A^\dagger$.
adjoint(Z) # build-in function
2×2 adjoint(::Matrix{ComplexF64}) with eltype ComplexF64:
1.0-2.0im -1.0+2.0im
2.0-0.0im 1.5+1.0im
Exercise 8: Unitary Verification
- Input: An $n \times n$ matrix $A$.
- Goal: Check if the matrix is unitary and return
true
if it is, orfalse
if it isn’t.
is_matrix_unitary(A::Matrix) = isapprox(sum(inv(A) - adjoint(A)), 0, atol=eps())
is_matrix_unitary(U)
true
Advanced Operations
Following exercises cover advanced linear algebra operations with complex vectors and matrices.
V = [1-2im, 2+1im, -2-1im]
3-element Vector{Complex{Int64}}:
1 - 2im
2 + 1im
-2 - 1im
W = [3-2im, -1+2im, -1-2im]
3-element Vector{Complex{Int64}}:
3 - 2im
-1 + 2im
-1 - 2im
Exercise 9: Inner product
- Input: Two $n \times 1$-vectors $V$ and $W$.
- Goal: Return a complex number - the inner product $\langle V, W \rangle$.
inner_prod(V::Vector, W::Vector) = dot(V, W)
inner_prod(V, W)
11 + 12im
Exercise 10: Normalized vectors
- Input: A non-zero $n \times 1$-vector $V$.
- Goal: Return a vector $\frac{V}{||V||}$ - the normalized version of the vector $V$.
normalize(V) # build-in function
3-element Vector{ComplexF64}:
0.2581988897471611 - 0.5163977794943222im
0.5163977794943222 + 0.2581988897471611im
-0.5163977794943222 - 0.2581988897471611im
Exercise 11: Outer product
- Input: An $n \times 1$-vector $V$ and an $m \times 1$-vector $W$.
- Goal: Return an $n \times m$ matrix that represents the outer product of $V$ and $W$.
V = [-3im, 9]
2-element Vector{Complex{Int64}}:
0 - 3im
9 + 0im
W = [9im, 2, 7]
3-element Vector{Complex{Int64}}:
0 + 9im
2 + 0im
7 + 0im
outer_prod(V::Vector, W::Vector) = V*W' # V*adjoint(W)
outer_prod(V, W)
2×3 Matrix{Complex{Int64}}:
-27+0im 0-6im 0-21im
0-81im 18+0im 63+0im
Exercise 12: Tensor Product
- Input: An $n \times m$-matrix $A$, and a $k \times l$-matrix $B$
- Goal: Return an $(n\cdot k) \times (m \cdot l)$-matrix $A \otimes B$, the tensor product of $A$ and $B$.
A = [1 2; 3 4]
2×2 Matrix{Int64}:
1 2
3 4
B = [5 6; 7 8]
2×2 Matrix{Int64}:
5 6
7 8
function ⊗(A::Matrix, B::Matrix)
n,m = size(A)
k,l = size(B)
C = zeros(eltype(A), n*k, m*l)
for i in 1:n
for j in 1:m
C[((i-1)*k+1):(i*k), ((j-1)*l+1):(j*l)] .= A[i,j] .* B
end
end
C
end
A ⊗ B
4×4 Matrix{Int64}:
5 6 10 12
7 8 14 16
15 18 20 24
21 24 28 32