1/15(木)『Yokohama Innovation Showcase』(@みなとみらい) に出展します☆彡
量子ゲート

New!! 量子ゲートでピクセルアートを作る(③8✕8サイズ完成編)

AI要約

量子ゲートのサンプリング結果を用いて8×8サイズのピクセルアート(ネコ)を描画する最終編です。アーキテクチャ変更の理由やサンプリング結果の扱いを丁寧に解説し、試行錯誤の末に完成形へ到達する過程をまとめました。

はじめに

前回はネコを論理合成しました(表現あってる?)

今回はシリーズの完結編。量子ゲートのサンプリングで8✕8サイズのネコを描画します。

全体アーキテクチャの変更

これまでの構造から少し変更しました。

量子回路の出力が7ビットになっていますね。ざっくり言うと、「乱数」と「その乱数に対応するマスを塗るかどうかの判定」を出すということです。

量子回路の中を詳しく見ます。

量子回路の最初で6ビットの乱数を生成します。その値を使って各ブロックの塗り判定をします。ブロックの判定をORしたものを総合判定とします。量子回路の出力は6ビット乱数と総合判定のあわせて7ビット。

この方法は大きなイラストに対応できます。その反面、判定が0のときは塗らないので塗り効率が悪いです。まあでもしゃーない。

総合判定ビット

前回の量子回路の続きです。6ブロックの判定をORして総合判定ビットとします。

#塗るかどうかの総合判定ビット
OR(13, 15, 32)
OR(32, 20, 33)
OR(33, 24, 34)
OR(34, 28, 35)
OR(35, 31, 36)

サンプリングして解の統計を見てみます。

#サンプリング
qc.measure_all()
backend = AerSimulator(method='matrix_product_state')
result = backend.run(qc, shots=2000).result().get_counts()

#解の統計
pos = (0, 1, 2, 3, 4, 5, 13, 15 ,20, 24, 28, 31, 36)

for i in range(2):
    for j in range(2):
        for k in range(2):
            for l in range(2):
                for m in range(2):
                    for n in range(2):
                        for r in result:
                            # print(r)
                            sel = ''.join(r[::-1][p] for p in pos)
                            if f'{i}{j}{k}{l}{m}{n}' == sel[:6]:
                                print(f'{sel[:6]} | {sel[6:12]} | {sel[12]} | {result[r]}/500')
000000 | 000000 | 0 | 34/500
000001 | 000000 | 0 | 27/500
000010 | 000000 | 0 | 26/500
000011 | 010000 | 1 | 32/500
000100 | 000000 | 0 | 35/500
000101 | 000000 | 0 | 29/500
000110 | 000000 | 0 | 28/500
000111 | 010000 | 1 | 31/500
001000 | 000100 | 1 | 25/500
001001 | 000000 | 0 | 35/500
001010 | 000000 | 0 | 31/500
001011 | 010000 | 1 | 28/500
001100 | 000001 | 1 | 39/500
001101 | 001001 | 1 | 33/500
001110 | 000001 | 1 | 36/500
001111 | 010001 | 1 | 27/500
010000 | 000100 | 1 | 25/500
010001 | 000000 | 0 | 32/500
010010 | 000000 | 0 | 23/500
010011 | 010000 | 1 | 34/500
010100 | 000000 | 0 | 32/500
010101 | 001000 | 1 | 33/500
010110 | 000000 | 0 | 30/500
010111 | 010000 | 1 | 39/500
011000 | 000100 | 1 | 32/500
011001 | 000000 | 0 | 36/500
011010 | 000000 | 0 | 46/500
011011 | 010000 | 1 | 35/500
011100 | 000000 | 0 | 20/500
011101 | 001000 | 1 | 33/500
011110 | 000000 | 0 | 37/500
011111 | 010000 | 1 | 35/500
100000 | 100000 | 1 | 20/500
100001 | 100000 | 1 | 30/500
100010 | 100000 | 1 | 31/500
100011 | 100000 | 1 | 23/500
100100 | 100000 | 1 | 30/500
100101 | 100000 | 1 | 30/500
100110 | 100000 | 1 | 26/500
100111 | 100000 | 1 | 29/500
101000 | 000000 | 0 | 24/500
101001 | 001000 | 1 | 33/500
101010 | 000010 | 1 | 33/500
101011 | 000010 | 1 | 30/500
101100 | 000010 | 1 | 31/500
101101 | 001010 | 1 | 28/500
101110 | 000000 | 0 | 43/500
101111 | 000000 | 0 | 32/500
110000 | 000000 | 0 | 30/500
110001 | 001000 | 1 | 28/500
110010 | 000010 | 1 | 35/500
110011 | 000010 | 1 | 36/500
110100 | 000010 | 1 | 31/500
110101 | 001010 | 1 | 33/500
110110 | 000000 | 0 | 28/500
110111 | 000000 | 0 | 28/500
111000 | 000000 | 0 | 35/500
111001 | 001000 | 1 | 30/500
111010 | 000000 | 0 | 32/500
111011 | 000000 | 0 | 30/500
111100 | 000000 | 0 | 31/500
111101 | 001000 | 1 | 35/500
111110 | 000000 | 0 | 26/500
111111 | 000000 | 0 | 41/500

表示は左から順に「乱数」「6ブロック判定」「総合判定」「ヒット数」です。ブロック判定に1が一つでもあれば総合判定が1になります。下に目的の真理値表を再掲しますが、同じになったでしょうか?

量子譜はこうなりました。思ったよりコンパクト!!

ネコのサンプリング描画

shots=1ずつ繰り返しサンプリングすると遅いので、一括サンプリングした結果を再生します。memory=True で get_memory() すると統計処理前の結果が取り出せます。

#一括サンプリングしてピクセル点灯で再生
pos = (0, 1, 2, 3, 4, 5, 36)
box = np.zeros(64, 'uint8')
base = np.array([2**5, 2**4, 2**3, 2**2, 2**1, 2**0], int)

#一括サンプリング
qc.measure_all()
backend = AerSimulator(method='matrix_product_state')
result = backend.run(qc, shots=100, memory=True).result().get_memory()

for r in result:
    sel = ''.join(r[::-1][p] for p in pos)
    #出力ビット
    bit = np.array(list(sel[:6]), int)
    #判定ビット
    judge = bool(int(sel[-1]))
    #判定が1のときだけ描画
    if judge:
        #10進数ワンホットに戻す
        box = box // 1.0001 # 過去の色を減衰させる
        idx = np.sum(base * bit)
        box[idx] = 255
        
        #表示
        img = box.reshape(8, 8)
        plt.imshow(img, vmin=0, vmax=255)
        plt.title(bit)
        plt.show()
        plt.close()

【朗報】量子ネコアート、ついに完成

そして皆さん気がついたでしょうか。使っている量子ビット数は37個です。64マスの画像を生成するのに37量子ビットしか使っていない。人類はついに量子ビットの損益分岐点を越えたのです。

おわりに

元となった量子猫ジャンプは2パターン生成でしたが、ここでは1パターンのみに絞っています。元気のある方は2パターンに拡張してみてください。すると、「両パターンに共通するブロックは再利用できるな~」とか、見えてくる世界がきっとあると思います(教科書のあとがき的な言い方)。

「量子コンピュータって結局どんな計算ができるの?」と聞かれたときはこのシリーズを紹介していただけると嬉しいですね。好きなピクセルアートが生成できるってステキ。量子ゲート教材として販売できねーかなーと思っています ( ˶´⚰︎`˵ )

リアクションのお願い

「参考になった!」「刺激された!」と思ったらぜひリアクションをしましょう。エンジニアの世界はGive and Takeによって成り立っています。これからも無料で良質な情報にアクセスできるよう、Giveする人への感謝をリアクションで示しましょう!

この記事をシェアする

自身のブログ等で使用する場合は引用を忘れずに!

また、寄付も受け付けています。コーヒー1杯でとても喜びます(*˘︶˘*)

 Amazonでギフト券(アマギフ)を贈る

こちらのリンク から金額を指定してお贈りください。(デフォルトで10000円になっているのでご変更ください)

配送:Eメール
受取人:staffあっとvigne-cla.com
贈り主:あなたのお名前やニックネーム
メッセージ:◯◯の記事が参考になりました。など

のようにご入力ください。見返りはありませんのでご了承ください。

 Amazonで食事券(すかいらーく優待券)を贈る

500円 1000円 2000円 5000円 からお贈りください。

配送:Eメール
受取人:staffあっとvigne-cla.com
贈り主:あなたのお名前やニックネーム
メッセージ:◯◯の記事が参考になりました。など

のようにご入力ください。見返りはありませんのでご了承ください。

 その他、ギフト券やクーポン券をメールで贈る

デジタルのギフト券/クーポン券はメールアドレス(staffあっとvigne-cla.com)までお送りください。受領の返信をいたします。
紙のギフト券/クーポン券は 「郵便物はこちらへ」の住所 まで送付してください。名刺やメールアドレスを同封していただければ受領の連絡をいたします。
余った株主優待券等の処理におすすめです。
いずれも見返りはありませんのでご了承ください。

不明点はSNSでお気軽にご連絡ください

ビネクラのTwitter・Youtubeでコメントをください!


Slack・Discordの場合はこちらの公開グループに参加してShoya YasudaまでDMをください!


※当ブログに関することは何でもご相談・ご依頼可能です。

この記事を書いた人
Yasuda

博士(理学)。専門は免疫細胞、数理モデル、シミュレーション。米国、中国で研究に携わった。遺伝的アルゴリズム信者。物価上昇のため半額弁当とともに絶滅寸前。

タイトルとURLをコピーしました