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

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回)観測

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