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.

Bloch

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

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$

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

complex_add(x::Complex,y::Complex) = x + y

complex_add(1 + 3im, 2 - 1im)
3 + 2im

Exercise 3: Complex Multiplication

complex_mult(x::Complex,y::Complex) = x * y

complex_mult(1 + 3im, 2 - 1im)
5 + 5im

Exercise 4: Complex Conjugate

conjugate(x::Complex) = adjoint(x)

conjugate(1 + 3im)
1 - 3im

Exercise 5: Complex Division

complex_div(x::Complex,y::Complex) = x / y

complex_div(1 + 3im, 2 - 1im)
-0.2 + 1.4im

Exercise 6: Modulus

modulus(x::Complex) = abs(x)

modulus(3 + 4im)
5.0

Exercise 7: Complex exponents

complex_exp(x::Complex) = exp(x)

complex_exp(1 + 1im)
1.4686939399158851 + 2.2873552871788423im

Exercise 8: Complex powers of real numbers

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

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

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

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

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

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

scalar_mult(x::Real, A::Matrix) = x*A

scalar_mult(2, X)
2×2 Matrix{Int64}:
 2  4
 6  8

Exercise 3: Matrix multiplication

matrix_mult(A::Matrix, B::Matrix) = A*B

matrix_mult(X, Y)
2×2 Matrix{Int64}:
  8   5
 20  13

Exercise 4: Matrix inversion

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

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

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

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

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

inner_prod(V::Vector, W::Vector) = dot(V, W)

inner_prod(V, W)
11 + 12im

Exercise 10: Normalized vectors

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

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

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