量子プログラミング入門→量子コンピューティングサービス構築入門

量子コンピューター初心者の筆者が日々学びながら、量子コンピュータ上で量子プログラミングできるようなるまでの学習日記を記録していきます。 内容は量子コンピューター入門者向けで、専門家の方からするとおかしな内容があるかもしれません。その際はコメント等でお知らせください!

カテゴリ:量子ゲート > Q# / Qsharp

チュートリアル Linear Algebra Part1解答例


Sample Answers for QuantumKatas Linear Algebra part I
https://github.com/microsoft/QuantumKatas/tree/master/tutorials/LinearAlgebra 

(いきなりこのページに飛んできた人で最初から勉強されたい方はこちらをご参照ください)

ここではQ#による量子プログラミングにあたっての数学的前提知識の学習を行います。
2つ目のチュートリアルは線形代数です。(Linear Algebra=線形代数) Part 1からPart 3までそれぞれのPartに分けて解説します。

(この記事を書くにあたっていろいろ調べていて知ったのですが、現在は高校の数学で行列を学ばないんですね。)

Exercise 1: Matrix addition. (行列の足し算)

まずは行列の足し算です。ここは単純に同じ位置(i, j)にある値を足し合わせるだけなので簡単ですね。

@exercise
def matrix_add(a : Matrix, b : Matrix) -> Matrix:
    # You can get the size of a matrix like this:
    n = len(a)
    m = len(a[0])
    
    # You can use the following function to initialize an n×m matrix filled with 0s to store your answer
    c = create_empty_matrix(n, m)
    
    # You can use a for loop to execute its body several times;
    # in this loop variable i will take on each value from 0 to n-1, inclusive
    for i in range(n):
        # Loops can be nested
        for j in range(m):
            # You can access elements of a matrix like this:
            x = a[i][j]
            y = b[i][j]
            
            # You can modify the elements of a matrix like this:
            c[i][j] = x + y
    
    return c



Exercise 2: Scalar multiplication (行列の整数倍)

行列の整数倍です。これも各成分を整数倍するだけなので簡単にできます。

@exercise
def scalar_mult(x : complex, a : Matrix) -> Matrix:
    n = len(a)
    m = len(a[0])    
    c = create_empty_matrix(n, m)
    
    for i in range(n):
        for j in range(m):
            c[i][j] = a[i][j] * x
            
    return c

Exercise 3: Matrix multiplication (行列の掛け算)

行列同士の掛け算です。行列同士の掛け算は行x列で各成分を計算していきます。
@exercise
def matrix_mult(a : Matrix, b : Matrix) -> Matrix:
    n = len(a)
    m = len(a[0])
    l = len(b[0])

    
    c = create_empty_matrix(n, l)
    
    for i in range(n):
        for j in range(l):
            for k in range(m):
                x = a[i][k]
                y = b[k][j]
                c[i][j] += x * y
    
    return c


Exercise 4: Matrix Inversion.  (逆行列)

Inverse Matricesとは逆行列のことです。逆行列とはかけると単位行列になる行列のことを言います。
単位行列とはその対角成分に 1 が並んで他は全て 0 となる行列です。
例えば、
\[ \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\
0 & 0 & 1 \\
\end{bmatrix} \] のような行列を言います。
\(I_n\)を単位行列とすると、行列\(A\)の逆行列\(A^{-1}\)は下記のようにあらわせます。
\[AA^{-1} = A^{-1}A = I_n\]

ここでは逆行列を生成してみます。
@exercise
def matrix_inverse(a : Matrix) -> Matrix:
    n = len(a)
    m = len(a[0])

    c = create_empty_matrix(n, m)
    d = (a[0][0]*a[1][1] - a[0][1]*a[1][0])

    c[0][0] = a[1][1] / d
    c[0][1] = a[0][1] / d * -1
    c[1][0] = a[1][0] / d * -1
    c[1][1] = a[0][0] / d
    
    return c
参考リンク
https://linear-algebra.com/entry/inverse-matrix
https://mathtrain.jp/inversematrix

Exercise 5: Transpose. (転置行列)

Transposeとは転置行列のことです。転置行列とは行列成分を対角線で折り返した行列のことです。言葉で言うと難しいですが、行列の各要素を添え字\(i, j\)で表した場合、\(i, j\)をひっくり返したものが転置行列になります。 \[A = \begin{bmatrix} x_{0,0} & x_{0,1} & \dotsb & x_{0,m-1} \\ x_{1,0} & x_{1,1} & \dotsb & x_{1,m-1} \\ \vdots & \vdots & \ddots & \vdots \\ x_{n-1,0} & x_{n-1,1} & \dotsb & x_{n-1,m-1} \end{bmatrix}\] Aの転置行列\(A^T\)は \[A^T = \begin{bmatrix} x_{0,0} & x_{1,0} & \dotsb & x_{n-1,0} \\ x_{0,1} & x_{1,1} & \dotsb & x_{n-1,1} \\ \vdots & \vdots & \ddots & \vdots \\ x_{0,m-1} & x_{1,m-1} & \dotsb & x_{n-1,m-1} \end{bmatrix}\] となります。
プログラムで書くと配列の要素番号の入れ替えなので非常に簡単ですね。

@exercise
def transpose(a : Matrix) -> Matrix:
    n = len(a)
    m = len(a[0])    
    c = create_empty_matrix(m, n)
    
    for i in range(m):
        for j in range(n):
            c[i][j] = a[j][i]
            
    return c

Exercise 6: Conjugate. (共役行列)

Conjugateは複素数でも出てきましたが、共役(きょうやく)行列のことです。
共役行列とは行列A の成分を複素共役にした行列 A です。
複素共役とは複素数\(a+bi\) (\(a, b\)は実数)に対して虚数部をマイナスにした\(a-bi\)を共役複素数でしたね。(詳しくはこちら)
ここでは共役行列を生成します。
@exercise
def conjugate(a : Matrix) -> Matrix:
    n = len(a)
    m = len(a[0])
    
    c = create_empty_matrix(n, m)
    
    for i in range(n):
        for j in range(m):
            c[i][j] = a[i][j].real - a[i][j].imag * 1j
    
    return c

Exercise 7: Adjoint. (随伴行列)

Adjointとは随伴行列のことです。随伴行列とは転置行列+共役行列のことで、行列 A に対して、A の転置およびその成分の複素共役をとったものが随伴行列\(A^\dagger\)(† ダガーと読む、Aのダガーはエーダガー)となります。
つまり、\(A^\dagger = \overline{(A^T)} = (\overline{A})^T\)となります。
随伴行列は\((AB)^\dagger = B^\dagger A^\dagger\)のように計算することができます。

ここでは随伴行列を生成してみます。
@exercise
def adjoint(a : Matrix) -> Matrix:
    n = len(a)
    m = len(a[0])

    c = create_empty_matrix(n, m)
    c = transpose(conjugate(a))
    return c

Exercise 8: Unitary Verification (ユニタリー行列)

ユニタリー行列は量子コンピュータにおいて非常に重要です。
ユニタリー行列とは逆行列変換可能でかつその逆行列が随伴行列と一致する行列のことを指します。つまり\(U^{-1} = U^\dagger\)であり\(UU^\dagger = U^\dagger U = I_n\)となります。
下記\(U\)はユニタリー行列の1つの例です。
\[U = \begin{bmatrix} \frac{1}{\sqrt{2}} & \frac{1}{\sqrt{2}} \\ \frac{i}{\sqrt{2}} & \frac{-i}{\sqrt{2}} \\ \end{bmatrix}\] \[U\dagger = \begin{bmatrix} \frac{1}{\sqrt{2}} & \frac{-i}{\sqrt{2}} \\ \frac{1}{\sqrt{2}} & \frac{i}{\sqrt{2}} \\ \end{bmatrix}\] \[UU\dagger = \begin{bmatrix} \frac{1}{\sqrt{2}} & \frac{1}{\sqrt{2}} \\ \frac{i}{\sqrt{2}} & \frac{-i}{\sqrt{2}} \\ \end{bmatrix}\ \begin{bmatrix} \frac{1}{\sqrt{2}} & \frac{-i}{\sqrt{2}} \\ \frac{1}{\sqrt{2}} & \frac{i}{\sqrt{2}} \\ \end{bmatrix} = \begin{bmatrix} 1 & 0 \\ 0 & 1 \\ \end{bmatrix}\]

ここでは各行列がユニタリー行列かをチェックするプログラムを作成します。
from pytest import approx

@exercise
def is_matrix_unitary(a : Matrix) -> bool:
    n = len(a)

    c = create_empty_matrix(n, n)
    d = create_empty_matrix(n, n)

    c = adjoint(a)

    d = matrix_mult(a,c)
    for i in range(n):
        for j in range(n):
            if i == j:
                if d[i][j] != approx(1):
                    return False
            else:
                if d[i][j] != approx(0):
                    return False
    return True


次はLinear algebra Part 2です。 Go to Part 2

QuantumKatas チュートリアルComplexArithmetic の解答例

Sample Answers for QuantumKatas ComplexArithmetic tutorial.
https://github.com/microsoft/QuantumKatas/tree/master/tutorials/ComplexArithmetic

(いきなりこのページに飛んできた人で最初から勉強されたい方はこちらをご参照ください)

Microsoft Q#のQuantumKatasのチュートリアルの解説、解答例を紹介します。
初回はComplex Arithmetic(複素数)です。ここではQ#による量子プログラミングにあたっての数学的前提知識の学習を行います。この段階ではQ#は使用せずPythonのみの使用となります。
ここでは量子プログラミングを学ぶための基礎知識の習得であって、数学的にはあまり深く考えずに、そういうものだと理解して進めばよいと思います。日本語でも聞きなれないのに英語になるとさらに聞きなれない単語がたくさん出てくると思いますが、ここではなるべく丁寧に解説していきます。間違い等あればコメントいただけると助かります。

Exercise 1: Powers of  𝑖 

まずは虚数(imaginary number)について学んでいきます。虚数とは二乗すると-1になる値です。
あまり深く考えずに\(i\)をそのように定義すると考えて先に進みましょう。
ここでは虚数\(i\)をn乗するプログラムを作成します。
@exercise
def imaginary_power(n : int) -> int:
    # If n is divisible by 4
    if n % 4 == 0:
        return 1
    else:
        return -1
pythonのmathパッケージには虚数の定義があり、虚数\(i\)がjとして定義されています。使用する際はjの前に係数を必ず置く必要がありますが、jを使うとわざわざ条件分岐しなくても下記でも動かすことができます。(jを1jとして使うところがポイントです)
@exercise
def imaginary_power(n : int) -> int:
    return 1j**n

Exercise 2: Complex addition (複素数の足し算)

Complexとは複素数のことです。ここでは複素数(Complex)の足し算を学びます。複素数の定義はこちらです。簡単に言うと実数(Real Number)と虚数(Imaginary Number)を足し合わせたものを複素数と呼びます。複素数の足し算は単純に実部(Real Pat)と虚部(Imaginary Part)を足せばよいです。
@exercise
def complex_add(x : Complex, y : Complex) -> Complex:
    # You can extract elements from a tuple like this
    a = x[0]
    b = x[1]
    
    c = y[0]
    d = y[1]
    
    # This creates a new variable and stores the real component into it
    real = a + c
    # Replace the ... with code to calculate the imaginary component
    imaginary = b + d
    
    # You can create a tuple like this
    ans = (real, imaginary)
    
    return ans

Exercise 3: Complex multiplication (複素数の掛け算)

次は複素数の掛け算です。こちらも難しくはないです。\(i^2=-1\)であることを考慮すると
\[ (a+bi)(c+di) = (a\times c + b\times d\times i^2) + (b\times c\times i + a\times d\times i) = (ac -bd) + (ad + bc)i \]
となります。
@exercise
def complex_mult(x : Complex, y : Complex) -> Complex:
    # Fill in your own code
    a = x[0]
    b = x[1]
    
    c = y[0]
    d = y[1]
    # This creates a new variable and stores the real component into it
    real = a*c - b*d
    # Replace the ... with code to calculate the imaginary component
    imaginary = a*d + b*c
    
    ans = (real, imaginary)
    return ans

Exercise 4: Complex conjugate (複素共役)

Complex Conjugateとは複素共役 (ふくそきょうやく)のことです。
複素共役とは複素数\(a+bi\) (\(a, b\)は実数)に対して虚数部をマイナスにした\(a-bi\)を共役複素数と言います。
共役複素数の特徴の1つとして、元の複素数にに複素共役をかけることで実数になることをここでは理解します。
\[(a + bi)(a - bi) = a^2 + b^2\] 
@exercise
def conjugate(x : Complex) -> Complex:
    a = x[0]
    b = x[1]
    ans = (a, -b)
    return ans

Exercise 5: Complex division (複素数の割り算)

次に複素数の割り算を理解します。ここで複素共役を使います。
分母の複素数の複素共役を分母分子それぞれにかけると分母が実数になり割り算できます。
\[\frac{x}{y} = \frac{a + bi}{c + di} = \frac{(a + bi)(c - di)}{(c + di)(c - di)} = \frac{(a + bi)(c - di)}{c^2 + d^2} \]
@exercise
def complex_div(x : Complex, y : Complex) -> Complex:
    a = x[0]
    b = x[1]
    
    c = y[0]
    d = y[1]

    r = (a*c + b*d) / (c**2 + d**2)
    i = (b*c - a*d) / (c**2 + d**2)
    ans = (r, i)
    return ans

Exercise 6: Modulus. (複素数の絶対値)

complex_plane

Modulusとは絶対値です。英語でAbsolute Valueと呼ぶことが多いですが、Quantum KatasではModulusと呼んでいます。ここでは複素数の絶対値(大きさ)について学びます。この辺りはベクトルの考え方と同じなのでベクトルを理解していれば問題はないでしょう。a, bそれぞれのの要素を2乗して足し合わせて、その和の平方根(Square Root)をとります。
@exercise
def modulus(x : Complex) -> float:
    a = x[0]
    b = x[1]
    
    ans = (math.sqrt(a**2 + b**2))
    return ans

Exercise 7: Complex exponents (複素数の指数演算)

次に実数の複素数乗について考えます。
ここでは自然対数の底eの複素数乗について学びます。Tutorialでは"Euler's constant"と書いてありますが、オイラーの定数ではなくネイピア数です。(Pythonではmath.eとして呼び出すことができます。)
あまり深く考えずに\(e^{i\theta} = \cos \theta + i\sin \theta\)を適用していきます。
@exercise
def complex_exp(x : Complex) -> Complex:
    a = x[0]
    b = x[1]

    ans = (math.pow(math.e, a) * math.cos(b), math.pow(math.e, a) * math.sin(b)) 
    return ans

Exercise 8*: Complex powers of real numbers (複素数の指数演算)

ここではeを使わずに任意の実数の複素数乗を考えます。rが0の場合だけ例外処理を追加し、その他の場合は\(log(r)\)をとればよいです。
@exercise
def complex_exp_real(r : float, x : Complex) -> Complex:
    a = x[0]
    b = x[1]

    if r==0:
        return (0, 0)
    else:
        c = math.log(r)
    
    ans = (math.pow(math.e, c*a) * math.cos(c*b), math.pow(math.e, c*a) * math.sin(c*b))
    return ans

Exercise 9: Cartesian to polar conversion (極座標系)

直交座標(Cartesian)⇒極座標(polar)変換について学びます。
complex_polar



極座標への変換は\( e^{i\theta} = \cos\theta + i\sin\theta \)を使えば解けます。
\(\theta\)を求めるには逆三角関数Arc Tangentを使います。横軸がReal Part, 縦軸がImaginary Partなので、\(\arctan{\frac{x}{y}}\)で\(\theta\)が求まります。Pythonではmath.atan2関数を使います。math.atanもありますが、aが0になることがあるので場合分けがめんどくさくなります。

@exercise
def polar_convert(x : Complex) -> Polar:
    a = x[0]
    b = x[1]

    theta = math.atan2(b,a)
    r = a / math.cos(theta)
        
    return (r, theta)

Exercise 10: Polar to Cartesian conversion (極座標系)

極座標(polar)⇒直交座標(Cartesian)変換について学びます。
\( e^{i\theta} = \cos\theta + i\sin\theta \)を使えば解けます。
@exercise
def cartesian_convert(x : Polar) -> Complex:
    r = x[0]
    theta = x[1]
    
    ans = (r * math.cos(theta), r * math.sin(theta))
    return ans

Exercise 11: Polar multiplication (極座標系の掛け算)

極座標系の掛け算
またまた\( e^{i\theta} = \cos\theta + i\sin\theta \)を使えば解けます。
極座標を\( (a + bi) (c + di) \)の形に変換すれば、\( (ac -bd) + (ad + bc)i \)となり、実数部と虚数部からそれぞれ解を求められます。
@exercise
def polar_mult(x : Polar, y : Polar) -> Polar:
    r1 = x[0]
    t1 = x[1]
    r2 = y[0]
    t2 = y[1]

    a = r1 * math.cos(t1)
    b = r1 * math.sin(t1)
    c = r2 * math.cos(t2)
    d = r2 * math.sin(t2)
    
    theta = math.atan2((a*d + b*c), (a*c - b*d))
    r = (a*c - b*d) / math.cos(theta)
    return (r, theta)

と思ったら、"Try to avoid converting the numbers into Cartesian form."ですね....  係数は単純な足し算、指数も足し算ですが、\( -\pi < \theta_3 \leq \pi \)の条件に気を付けて答えを返せば大丈夫です。
@exercise
def polar_mult(x : Polar, y : Polar) -> Polar:
    r1 = x[0]
    t1 = x[1]
    r2 = y[0]
    t2 = y[1]

    t3 = (t1 + t2) % (2 * math.pi)
    if t3 > math.pi:
        t3 = t3 - 2*math.pi     
    return ((r1 * r2), t3)

Exercise 12**: Arbitrary complex exponents (任意の複素数の指数演算)

複素数の複素数乗を算出する問題です。

公式

複素数の複素数乗に関しては公式がありますのでこの公式を使います。
複素数\(z\)、実数\( p,q \)について、
\[ \begin{cases} \alpha=p {\rm Log}|z|-q\arg{z}\\ \beta=q {\rm Log}|z|+p\arg{z} \end{cases} \]
として、
\[ z^{p+qi}=e^{\alpha} (\cos{\beta}+i\sin{\beta}) \]
が成り立ちます。ここで\( { \rm Log}(x) \) は実数\( x \)の自然対数を、\( {\rm \arg}(z) \) は複素数\( z \)の偏角(多価関数)をそれぞれ表します。

公式があることに気が付けばすぐに解くことができます。

@exercise
def complex_exp_arbitrary(x : Complex, y : Complex) -> Complex:
    a = x[0]
    b = x[1]
    p = y[0]
    q = y[1]
    
    modulus = (math.sqrt(a**2 + b**2))
    if a == 0 and b == 0:
        return(0, 0)
    theta = math.atan2(b,a)
    alpha = p * math.log(modulus) - q * theta
    beta  = q * math.log(modulus) + p * theta

    real = math.pow(math.e, alpha) * math.cos(beta)
    imag = math.pow(math.e, alpha) * math.sin(beta)

    return(real, imag)



次はLinear Algebra=線形代数の学習です。もう少し数学のお勉強が続きます。


Microsoft Q# (qsharp)とは


Q# (キューシャープ) は、量子コンピューターのためにマイクロソフトが開発した、プログラミング言語です。古典コンピュータ上のホストプログラムから量子コンピュータ上で実行されるサブルーチンを呼び出す形で使用される量子プログラミング言語です。 Q#は量子シミュレーターが実装されており実際の量子コンピュータを使わなくても量子プログラミングを始めることができます。

Microsoft Quantum Katasとは

Quantum Katasはマイクロソフトが作成した量子コンピューティングとQ#プログラミングを学習するためのチュートリアルです。Github上で問題や解答、Jupyter notebookが公開されており、量子プログラミングに必要な基礎知識からQ#を使ったコーディングまで習得できるように構成されています。
https://github.com/microsoft/QuantumKatas

The Quantum Katas are a series of self-paced tutorials to help you learn quantum computing and Q# programming.

QuantumKatasはTutorialやKatasなどから構成されており、歴史的にはKatasのほうが古いですが、Tutorial(チュートリアル)から始めることで、量子プログラミングに必要な数学的基礎知識から習得することができます。
チュートリアルのメニューは以下です。数学の基礎的な知識から入るのでこれから量子プログラミングを始めるとい自分のような超初心者にもちょうどいい感じです。逆に言うと数学的な基礎知識がないと現時点では量子プログラミングを学ぶのは難しいです。ただこれらの数学は普段は見慣れないのでとっつきにくいところもありますが、論理的にはそれほど難しいものではないので、順を追ってしっかり学習していけば問題ありません。


Quantum Katasを動かすための環境設定

Quantum Katasをonline動かす

一番手っ取り早いのが、こちらのリンクから動かすことです。
ちょっと使いづづけてないとすぐにセッションが切れてしまいますが、環境を自分で用意しなくてよいので非常に便利です。

Quantum Katasを自分のJupyterで動かす

jupyterインストール&起動

Katasのチュートリアルを動かすためにはjupyter notebookが必要です。
自分でJupyterを動かす場合は、こちらを参考にAnacondaをインストール

gitからクローン


自分で動かす場合、下記コマンドでQuantumKatasをJupyterから見えるフォルダにクローンしてきます。
git clone https://github.com/microsoft/QuantumKatas.git


チュートリアルは
QuantumKatas/tutorials
にあります。

スクリーンショット (31)
ではこれから学習を始めていきたいと思います。

基本的な量子処理を動かしてみる

MS QDKのQuickstartsにある「 Quantum basics with Q#」で量子コンピュータの基本的な処理を動かしてみる。今回は、量子コンピューティングの学習というよりもQ#の文法の勉強の要素が強い。

Q# Operationの定義

Q#のOperationは量子サブルーチンで、外部から呼び出し可能な量子操作です。
引数は()内にタプル型で定義され、戻り値はコロンの後に定義します。
下記のソースの例で言うと、
Q#のoperationの引数はタプルで宣言され、"Set"の引数は、Result型のdesiredとQubit型のq1のタプル、戻り値は引数の後ろにコロン(:)を付けて宣言されUnit型です。
Unit型はvoid型みたいなものと考えていいようです。

namespace Quantum.Bell {
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Canon;

    operation Set(desired : Result, q1 : Qubit) : Unit {
        if (desired != M(q1)) {
            X(q1);
        }
    }
}

Setオペレーション についての解説

Setオペレーションは量子ビットを観測し、期待値と異なれば反転させる量子オペレーションです。(関数と言ってはいけない?量子オペレーション?)
量子ビットは実際には中間的な値を取っているのですが、観測時は0か1にしか見えないもので、反転とは0を1に、1を0にする操作を意味します。

Setの入力はResult型のdesiredです。Result型とは量子ビットを観測した時に読める値のことで、取りうる値はZeroかOneです。Q#で使えるデータの型についてはこちらを参照

M()は量子ビットの値を観測するQ#の量子オペレーションです。
X()は量子ビットを反転させるQ#の量子オペレーションです。
今回はこのM()とX()を動かすことがメインのテーマですが、サンプルコード通りにやらされてる感は満載です...

実際に動かしてみる


先ほどのSet Operationにテストコードを追加し実際に動かしてみる。
テストプログラムは期待値0と1それぞれで1000回 Set Operationを動かして
期待値をきちんと返すかを確認するプログラムです。
Bell.qsというファイル名で下記を作成
namespace Quantum.Bell {                                                                                                    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Canon;

    operation Set(desired : Result, q1 : Qubit) : Unit {
            if (desired != M(q1)) {
                    X(q1);
            }
    }

    operation TestBellState(count : Int, initial : Result) : (Int, Int) {
        mutable numOnes = 0;
        using (qubit = Qubit()) {
            for (test in 1..count) {
                 Set(initial, qubit);
                 let res = M(qubit);
                 // Count the number of ones we saw:
                 if (res == One) {
                     set numOnes += 1;
                }
            }
            Set(Zero, qubit);

            // Return number of times we saw a |0> and number of times we saw a |1>
            return (count-numOnes, numOnes);
        }
    }
}
host.pyというファイル名で下記を作成

import qsharp

from qsharp import Result
from Quantum.Bell import TestBellState

initials = (Result.Zero, Result.One)

for i in initials:
    res = TestBellState.simulate(count=1000, initial=i)
    (num_zeros, num_ones) = res
    print(f'Init:{i: <4} 0s={num_zeros: <4} 1s={num_ones: <4}')

下記コマンドを実行し動作確認
$ python host.py
Preparing Q# environment... ..Init:0 0s=1000 1s=0 Init:1 0s=0 1s=1000
初期値が0なら0(期待値)を100%(1000回)観測
初期値が1なら1(期待値)を100%(1000回)観測

コピペなんでちゃんと動きますよね。


Microsoft Quantum Development Kit環境構築

ゲート型量子コンピュータのプログラミング環境としてMicrosoftがプログラミング言語Q#とその開発キットQDK(Quantum Development Kit)を提供しています。 ゲート型のプログラミングの学習環境としてまずはAzure QuantumのQ#/QDK環境を構築したいと思います。

ここではMSのQDKインストール手順に従って環境構築を実施していきます。 https://docs.microsoft.com/en-us/quantum/install-guide/index?view=qsharp-preview#develop-with-jupyter-notebooks

MS QDK環境構築のための必要パッケージ

Q#/QDKを動かすためにはPythonまたはC#などの.Net言語環境が必要です。 自分の場合はC#よりもPythonのほうがなじみがあるのでPython環境を構築していきます。

MS QDKをPythonで動かすためには下記の環境が必要

  • Python 3.6 or later
  • The PIP Python package manager
  • .NET Core SDK 3.0 or later

ベース環境の構築

自分は普段はWindowsで作業するのですがPython等のプログラミングとなると Windowsはちょっと不便なところもあるのでubuntuの環境を用意したい。 Azure上に構築しようかと考えましたが、Windows Subsystem for Linux(WSL)で Ubuntuが一番お手軽に構築できそうなのでWSL上に環境構築しました。

Window Subsystem for Linuxの有効化とUbuntuのインストール

設定から"アプリ"を開く。
スクリーンショット (5)

右側のメニューから"プログラムと機能"をクリック


スクリーンショット (6)

左のメニューから"Windows機能の有効化または無効化を"クリック

スクリーンショット (7)

Windows Subsystem for Linuxにチェックを入れる。
(再起動が必要)
スクリーンショット (8)
スタートメニューから"Microsoft Store"を起動し、"Ubuntu"を検索しインストール。
スクリーンショット (11)



Host Application環境の構築 (Python環境)

ubuntuの起動と更新

スタートメニューからubuntuを起動 端末から下記のコマンドを実行

sudo apt update
sudo apt -yV upgrade

ubuntuの再起動

WSL上のUbuntuではshutdownコマンドが使えません。Ubuntuのアップデートを有効にするためWindows側からWSLのUbuntuを再起動させます。

スタートメニューからWindowsシステムツール-> コマンドプロンプトを右クリック->その他から管理者として実行

管理者として開いたコマンドプロンプトで下記のコマンドを実行

net stop LxssManager
net start LxssManager

Pythonとpipのインストール

git, cmake, wget, p7zip-full のインストール

bash上で下記コマンドを実行

sudo apt -yV install git cmake cmake-curses-gui cmake-gui wget p7zip-full

Anaconnda3のダウンロードとインストール

Anacondaは入れる必要はないが、jupyter notebookが使えた方が便利な場合があると思いインストール

ホストのWindowsからAnaconda(Linux版)を下記からダウンロード https://www.anaconda.com/download

WindowsとWSL上のUbuntuは下記フォルダを共有しています。

  • Windows側: C:\Users\ユーザー名
  • WSL(Ubuntu)側: /mnt/c/ユーザー名/

ダウンロードしたファイルをこの共有フォルダに移動するとWSL側から利用することができます。
共有フォルダに移動し下記コマンドを実行。(ダウンロードする版数によりコマンド名は異なります)

Anaconda3-2019.10-Linux-x86_64.sh

途中いくつか入力が必要なので内容を確認し適切に入力

Do you wish the installer to initialize Anaconda3 by running conda init? [yes|no]

PATH環境変数の更新が入ってるので、それを反映させるためいったん端末を閉じて、再度Ubuntuを起動 Pathが変わる。

user@hostname$ which python
/usr/bin/python
(base) user@hostname:~$ which python
/home/user/anaconda3/bin/python
(base) user@hostname:~$

.NET Core SDKのインストール

下記リンクから.NET Core SDK(Linux版)(Build/Run Appsと書いてあるやつ)を選択 https://dotnet.microsoft.com/download 自分の場合はUbuntu 18.04なので左のメニューから下記リンクにジャンプ https://docs.microsoft.com/ja-jp/dotnet/core/install/linux-package-manager-ubuntu-1804


スクリーンショット (29)


ubuntu上で下記コマンドを実行

wget -q https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
sudo add-apt-repository universe
sudo apt-get update
sudo apt-get install apt-transport-https
sudo apt-get update
sudo apt-get install dotnet-sdk-3.0

MS QDKのインストール

qsharpパッケージのインストール

pip install qsharp

iqsharpパッケージのインストール

dotnet tool install -g Microsoft.Quantum.IQSharp

.NET有効化のためいったん端末を閉じて再度新しい端末を開く

MSのページには--userオプション無しで書いてあるがWSL環境のせいか--userを付けないとうまく入らない

dotnet iqsharp install --user

環境構築完了!

TutorialにあるHello Worldサンプルコードを動かしてみる

MSページからのコピペなので中身はよくわからないがとにかく動かしてみる

まずQ#のコードを作成。Hello from quantum worldを表示するSayHello() Operationの定義
Operation.qsというファイル名で下記のコードを作成

namespace HelloWorld
{
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Canon;

    operation SayHello() : Result {
        Message("Hello from quantum world!");
        return Zero;
    }
}

SayHello()を呼び出すためのPythonプログラムをhello_world.pyというファイル名で作成

import qsharp
from HelloWorld import SayHello
SayHello.simulate()

下記コマンドを実行(Pathが通るように、Operation.qsとhello_world.pyを同じフォルダに置きそのフォルダで実行する)

$ python hello_world.py
Preparing Q# environment...
....Hello from quantum world!

けっこう時間がかかるがきちんとメッセージが表示される。環境は構築できHello Worldは表示されるところまでは来たのでここからしっかりとQ#/QDKについて学習していきます。

↑このページのトップヘ