├── .gitignore ├── README.md ├── img ├── .gitkeep ├── logo_chodai.png ├── logo_jqca.png └── logo_vc_f_sk.png └── tutorial ├── old_tutorial2.ipynb ├── tutorial00_networkx.ipynb ├── tutorial01_qubo.ipynb ├── tutorial02_maxcut.ipynb ├── tutorial03_bil.ipynb ├── tutorial04_graphcoloring.ipynb ├── tutorial05_cliques.ipynb ├── tutorial06_job_sequencing_problem.ipynb ├── tutorial07_setcover_setpacking.ipynb ├── tutorial08_clustering_vertex_cover.ipynb ├── tutorial09_trafficflow_optimization.ipynb └── tutorial10_liner_reg.ipynb /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | .pytest_cache 3 | *.egg-info 4 | dist 5 | build 6 | *.DS_Store 7 | .venv 8 | .ipynb_checkpoints 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 情報 2 | 3 | TYTANパッケージの基本的な使い方 → [TYTANトップページ](https://github.com/tytansdk/tytan)
4 | TYTANパッケージの本格的な使い方 → [TYTANドキュメント](https://github.com/tytansdk/tytan/blob/main/document%20.md)
5 | 質問やご意見などはコミュニティへ → [Discord「TYTAN」](https://discord.gg/qT5etstPW8)
6 | 勉強会の予定・告知 → [connpass「一般社団法人日本量子コンピューティング協会」](https://jqca2023.connpass.com/) 7 |
8 | 勉強会のレコーディング → [再生リスト「【第3世代】QUBOアニーリング TYTANチュートリアル」](https://www.youtube.com/playlist?list=PLQOGM0zeI92Sfk7L9yS8xoLDBRemHmxmj) 9 | 10 |
11 | 12 | ## 量子エンジニア講座(アニーリング)エントリーコース 13 | 14 | |第1回|第2回|第3回| 15 | |:--|:--|:--| 16 | |教材(事前学習用)|教材(事前学習用)|教材(事前学習用)| 17 | |演習問題①|演習問題②
演習問題③|演習問題④
演習問題⑤| 18 | 19 | ※ 「認定試験」についてはQAI-Zen一般社団法人日本量子コンピューティング協会のサイトでご確認ください。
20 | ※「教材」は事前学習用に一部公開しています。完全版の「教材」は講座にてご確認いただけます。
21 | ※ 講座受講後に「アンケート」にご協力頂けますと幸いです。

22 | 23 | ## 量子エンジニア講座(アニーリング)アドバンスコース 24 | 25 | |第1回|第2回|第3回| 26 | |:--|:--|:--| 27 | |教材(事前学習用)|教材(事前学習用)|教材(事前学習用)| 28 | |演習問題①|演習問題②
演習問題③|演習問題④| 29 | 30 | ※ 「認定試験」についてはQAI-Zen一般社団法人日本量子コンピューティング協会のサイトでご確認ください。
31 | ※「教材」は事前学習用に一部公開しています。完全版の「教材」は講座にてご確認いただけます。
32 | ※ 講座受講後に「アンケート」にご協力頂けますと幸いです。

33 | 34 |
35 | 36 | 37 | ## 第3世代基礎コースと認定試験問題 38 |
39 | 開く
40 | 41 | 2024年4月~7月まで運用されていた教材です。 42 | 43 | |実施日|Title|学習内容|おまけ| 44 | |:--|:--|:--|:--| 45 | |1|はじめに||| 46 | |1|No.1 最大カット問題|制約の基礎|| 47 | |2|No.2 マインスイーパ|制約の基礎|| 48 | |2|No.3 数字を2組に分ける|方程式制約|イジングモデル| 49 | |3|No.4 カクラス|方程式制約|演習| 50 | |3|No.5 お席へどうぞ|臨時報酬/ペナルティ、強弱|| 51 | |4|No.6 お絵かきロジック|臨時報酬/ペナルティ、強弱|演習| 52 | |4|No.7 経路分散|One-hotエンコーディング、コスト|| 53 | |5|No.8 巡回セールスマン問題|One-hotエンコーディング、コスト|演習| 54 | 55 | ここまででQUBOでできる基本的なことは一通り学べたので、あとは問題を言い換えて知っているテクニックに落とし込めるかの勝負だ。 56 | 57 |
58 | 59 | ## 「量子エンジニア(アニーリング式)」認定試験問題 60 | 61 | 基礎コース修了レベルを対象とした、日本量子コンピューティング協会公認の認定試験です。 62 | 63 | **受験から認定まで無料ですが、正式な資格認定証(紙・デジタル)の発行申し込みには手数料(9,800円)がかかります。正式な認定証を要する場合はあらかじめご了承ください。** 64 | 65 | |形式|Title|合格基準| 66 | |:--|:--|:--| 67 | |選択肢・記述|問題 A(※受付を終了しました)|ほぼ完答| 68 | |コーディング|問題 B-1(※受付を終了しました)|ほぼ完答| 69 | |コーディング|問題 B-2(※受付を終了しました)|ほぼ完答| 70 | 71 | 「量子エンジニア(アニーリング式)」認定試験に挑戦される方は上記の3問を解いてShoya Yasudaまでご提出ください。事前の申し込みは不要です。提出方法や注意事項はファイル内に書かれています。 72 | 73 | 提出・問い合わせ先
74 | ・[Discord(TYTAN)](https://discord.gg/qT5etstPW8) -> Shoya YasudaへDM(※公開チャンネルに投稿しないようご注意ください)
75 | ・[Slack(AI FASHION)](https://join.slack.com/t/ai-fashion/shared_invite/zt-5ew03uzn-Sh0fho5wQMUTUC2IE01gPg) -> Shoya YasudaへDM
76 | ・yasudaあっとvigne-cla.com 77 | 78 | **※3日以内に受領の返事がない場合は、別ルートで「届きましたか?」の連絡をください!(公開チャンネルでも構いません!)** 79 | 80 |
81 | 82 | ## 第3世代発展コース 83 | 準備中です。 84 | 85 | |実施日|Title|学習内容|おまけ| 86 | |:--|:--|:--|:--| 87 | |1|ドミノサ||| 88 | |1|クラスタリング||| 89 | |2|連立方程式||| 90 | |2|線形回帰||| 91 | |3|ナップサック問題||| 92 | 93 |
94 | 95 | ## 解き方募集中 96 | 2023年7月4日更新 97 | 98 |
99 | 100 |
101 | 102 | 103 | ## 第2世代基礎コースと認定試験問題 104 |
105 | 開く
106 | 107 | 2024年3月まで運用されていた教材です。 108 | 109 | |No.|Title|難度|学習内容|おまけ|実施日| 110 | |:--|:--|:--|:--|:--|:--| 111 | |0|はじめに||||1| 112 | |1|最大カット問題|#|制約の基礎||1| 113 | |2|温度計パズル|##|制約の基礎、降順|便利関数|2| 114 | |3|数字を均等に2組に分ける|#|方程式制約|イジング版|2| 115 | |4|シフト最適化|#|方程式制約||3| 116 | |5|お絵かきロジック|###|条件報酬、条件ペナルティ|便利関数|3| 117 | |6|巡回セールスマン問題|###|ワンホット、コスト|演習|4| 118 | |7|クラスタリング|###|ワンホット、コスト||4| 119 | |8|連立方程式を解く|###|2進数(N-bit)表現|便利関数|5| 120 | |9|線形回帰|###|2進数(N-bit)表現|便利関数|5| 121 | |10|ナップサック問題|####|コスト、補助変数と不等式制約||6| 122 |
123 | 124 | 「量子エンジニア(アニーリング式)」認定試験問題 125 | 126 | |No.|Title|難度|ジャンル|作問協力| 127 | |:--|:--|:--|:--|:--| 128 | |1|スターバトル|####|パズル|yasuda| 129 | |2|ピタゴラス数|####|数学|derwind| 130 | |3|ジョブシーケンス問題|####|工程|yasuda| 131 | |4|ばねにはたらく力|####|高校物理|derwind| 132 | |5|クリティカルパス問題|#####|工程|derwind| 133 | 134 | 「量子エンジニア(アニーリング式)」認定試験に挑戦される方は、上記から任意の2問を解いて.ipynbまたは.pyをShoya Yasudaまでメール・DM等でご提出ください。 135 | 136 | ▼注意事項
137 | テキスト欄やコメントアウトにより最低限の説明や思考過程を含めてください
138 | その際、チュートリアルの「おすすめコース」のどれと関連があるかにも触れてください
139 | 説明のための図は必ずしも必要ありません
140 | アニーリングのソルバーには必ずTYTANパッケージを使用してください
141 | 必ずしも1回の実行で正解が得られる必要はなく、正解が得られることが期待できるコードであれば問題ありません
142 | 143 | ▼合格条件
144 | QUBO条件式が妥当であること
145 | 説明や思考過程が妥当であること
146 | 十分な可読性のPythonコードであること
147 | チュートリアル「おすすめコース」を把握していること
148 | 149 | 連絡先
150 | ・DiscordのDM(※公開チャンネルに投稿しないようご注意ください)
151 | ・SlackのDM
152 | ・yasudaあっとvigne-cla.com 153 | 154 |
155 | 156 |
157 | 158 | 159 | ## 初代基礎コース 160 |
161 | 開く
162 | 163 | TYTANパッケージ修正にともない、コードが動作しなくなった場合があります。 164 | 165 | |File|Title|実施日| 166 | |:--|:--|:--| 167 | |tutorial00.|ネットワークX|2023/04/11| 168 | |tutorial01.|イジングとQUBO|2023/04/14| 169 | |tutorial02.|マックスカット問題、自然数分割問題|2023/05/17| 170 | |tutorial03.|整数計画問題|2023/05/17| 171 | |tutorial04.|グラフ分割問題、グラフカラーリング問題|2023/05/17| 172 | |tutorial05.|クリーク判定問題、クリークカバー問題|| 173 | |tutorial06.|ジョブシークエンス、ナップザック問題|★一部間違いがあります。実力テストの参考にされる場合はご注意ください!| 174 | |tutorial07.|セットカバー、セットパッキング|| 175 | |tutorial08.|クラスタリング、頂点被覆問題|| 176 | |tutorial09.|交通最適化問題|| 177 | |tutorial10.|イジング線形回帰|| 178 |
179 | 180 |
181 | 182 | ## 公認・推奨 183 | 184 | 185 |
186 | 187 | ## 運営協力 188 | 運営 
189 | 教材作成・採点  190 | 191 | -------------------------------------------------------------------------------- /img/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /img/logo_chodai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tytansdk/tytan_tutorial/511de2411c2f6d1e13ad2b710bb0b3b89420b451/img/logo_chodai.png -------------------------------------------------------------------------------- /img/logo_jqca.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tytansdk/tytan_tutorial/511de2411c2f6d1e13ad2b710bb0b3b89420b451/img/logo_jqca.png -------------------------------------------------------------------------------- /img/logo_vc_f_sk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tytansdk/tytan_tutorial/511de2411c2f6d1e13ad2b710bb0b3b89420b451/img/logo_vc_f_sk.png -------------------------------------------------------------------------------- /tutorial/old_tutorial2.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": { 7 | "id": "EtT6QPPGL2-7" 8 | }, 9 | "outputs": [], 10 | "source": [] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": { 15 | "id": "c21OW4osL3hd" 16 | }, 17 | "source": [ 18 | "## 大規模SAアニーリングTYTANチュートリアル 2回目\n", 19 | "\n", 20 | "### シュミレイテッドアニーリング\n", 21 | "シュミレイテッドアニーリングは、量子アニーリングとは異なり、古典コンピュータでシュミレーションを行います。 \n", 22 | "量子アニーリングでは、実際の量子ビットとの相互作用が隣接する量子ビットに限られますが、シュミレイテッドアニーリングでは、すべてのビット変数が相互作用する状況で計算を行うことができます。 \n", 23 | "ただし、実際の量子ビットが持つ重ね合わせ(もつれも?)は使うことが出来ません。 \n", 24 | "\n", 25 | "### QUBO式\n", 26 | "シュミレイテッドアニーリングでは、QUBO式と呼ばれる、コスト関数と制約条件を合わせたものを用意します。このQUBO式が最小(極小)になる状態をシュミレイテッドアニーリングで求まります。\n", 27 | " \n", 28 | "QUBO関数 = コスト関数 + 制約条件\n", 29 | "\n", 30 | "さらに、QUBO式は、2次式と呼ばれる下記の数式である必要があります。 \n", 31 | "\n", 32 | "$$\n", 33 | "QUBO = -\\sum_{i,j} w_{i,j} q_i q_j\n", 34 | "$$\n", 35 | "\n", 36 | "$w_{i,j}$は問題によって決まる、変数間の相互作用に対応します。 \n", 37 | "\n", 38 | "### コスト関数や制約条件の重み付け\n", 39 | "問題によっては、コスト関数や制約条件の重み付けを行う場合もあります。 \n", 40 | "コスト関数に多く重みを付けるとコストが小さくなるように働き、制約条件に多く重みを付けると、制約条件をより制約条件を満たすように働きます。 \n", 41 | "\n", 42 | "### 相互作用のシュミレーション\n", 43 | "\n", 44 | "\n", 45 | "### 大規模計算の例\n", 46 | "組合せ最適化問題の例題として巡回セールスマン問題(TSP問題)を上げます。 \n" 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": null, 52 | "metadata": { 53 | "id": "VFnJm0sEQZd7" 54 | }, 55 | "outputs": [], 56 | "source": [] 57 | } 58 | ], 59 | "metadata": { 60 | "colab": { 61 | "provenance": [] 62 | }, 63 | "kernelspec": { 64 | "display_name": "Python 3 (ipykernel)", 65 | "language": "python", 66 | "name": "python3" 67 | }, 68 | "language_info": { 69 | "codemirror_mode": { 70 | "name": "ipython", 71 | "version": 3 72 | }, 73 | "file_extension": ".py", 74 | "mimetype": "text/x-python", 75 | "name": "python", 76 | "nbconvert_exporter": "python", 77 | "pygments_lexer": "ipython3", 78 | "version": "3.9.12" 79 | } 80 | }, 81 | "nbformat": 4, 82 | "nbformat_minor": 1 83 | } 84 | -------------------------------------------------------------------------------- /tutorial/tutorial00_networkx.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "b02af6ab-2a06-46d1-bd95-3934a8dee157", 6 | "metadata": {}, 7 | "source": [ 8 | "ここでは、NetworkXを利用してグラフ問題をQUBO形式に変換して計算を行います。" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": 24, 14 | "id": "cf74fabc-aff3-40f9-b140-f2ef37339a6e", 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "import networkx as nx\n", 19 | "import numpy as np\n", 20 | "from tytan import *" 21 | ] 22 | }, 23 | { 24 | "cell_type": "markdown", 25 | "id": "72ba2827-e48c-40f4-81df-57f3ef6e07ae", 26 | "metadata": {}, 27 | "source": [ 28 | "まずはGraphオブジェクトを生成し、ノードを定義し追加、その後エッジを追加していきます。" 29 | ] 30 | }, 31 | { 32 | "cell_type": "code", 33 | "execution_count": 22, 34 | "id": "7f186293-08be-4ad0-a1c4-2843e34c3875", 35 | "metadata": {}, 36 | "outputs": [], 37 | "source": [ 38 | "# Graphオブジェクトを生成\n", 39 | "G = nx.Graph()\n", 40 | "\n", 41 | "# ノードを定義\n", 42 | "node_list = [\"x0\", \"x1\"]\n", 43 | "\n", 44 | "# グラフのノードを追加\n", 45 | "G.add_nodes_from(node_list)\n", 46 | "\n", 47 | "# グラフのエッジを追加\n", 48 | "G.add_edge(node_list[0], node_list[1], weight=1)\n", 49 | "\n", 50 | "# ノードのリストを取得\n", 51 | "node_list = list(G.nodes())\n", 52 | "\n", 53 | "# QUBO行列の要素を計算\n", 54 | "qubo = {(i, j): 0 for i in node_list for j in node_list}\n", 55 | "for (i, j) in G.edges:\n", 56 | " qubo[(i, j)] += G.edges[(i, j)]['weight']" 57 | ] 58 | }, 59 | { 60 | "cell_type": "markdown", 61 | "id": "bc2a53ee-f35e-4faa-ac09-f2245c08cda2", 62 | "metadata": {}, 63 | "source": [ 64 | "QUBO形式が作成できたので、計算をします。\n" 65 | ] 66 | }, 67 | { 68 | "cell_type": "code", 69 | "execution_count": 25, 70 | "id": "a568469a-fdb7-4b2c-9c91-3e4d1bf2487f", 71 | "metadata": {}, 72 | "outputs": [ 73 | { 74 | "name": "stdout", 75 | "output_type": "stream", 76 | "text": [ 77 | "[[{'x1': 0, 'x0': 0}, 0.0, 24], [{'x1': 0, 'x0': 1}, 0.0, 23], [{'x1': 1, 'x0': 0}, 0.0, 27], [{'x1': 1, 'x0': 1}, 1.0, 26]]\n" 78 | ] 79 | } 80 | ], 81 | "source": [ 82 | "# サンプラーを選択\n", 83 | "sampler = sampler.SASampler()\n", 84 | "\n", 85 | "# 計算\n", 86 | "result = sampler.run(qubo, shots=100)\n", 87 | "print(result)" 88 | ] 89 | }, 90 | { 91 | "cell_type": "markdown", 92 | "id": "9e361c99-5e22-483b-b754-19b5ab84ef82", 93 | "metadata": {}, 94 | "source": [ 95 | "完了しました。" 96 | ] 97 | } 98 | ], 99 | "metadata": { 100 | "kernelspec": { 101 | "display_name": "Python 3 (ipykernel)", 102 | "language": "python", 103 | "name": "python3" 104 | }, 105 | "language_info": { 106 | "codemirror_mode": { 107 | "name": "ipython", 108 | "version": 3 109 | }, 110 | "file_extension": ".py", 111 | "mimetype": "text/x-python", 112 | "name": "python", 113 | "nbconvert_exporter": "python", 114 | "pygments_lexer": "ipython3", 115 | "version": "3.10.5" 116 | } 117 | }, 118 | "nbformat": 4, 119 | "nbformat_minor": 5 120 | } 121 | -------------------------------------------------------------------------------- /tutorial/tutorial03_bil.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "afd500c8", 6 | "metadata": {}, 7 | "source": [ 8 | "## 二値整数計画問題\n", 9 | "連立方程式を満たしたうえである計算を最小化する、制約付きの最小値問題です。 \n", 10 | "より正確には、$Sx = b$を満たすベクトル$x$のうち、$cx$を最小にするxを探します" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "id": "2d140a6d", 16 | "metadata": {}, 17 | "source": [ 18 | "### QUBO\n", 19 | "この問題は二つの式から成り立ちます。連立方程式の制約を満たすための$H_A$と最小コストを求めるための$H_B$です。\n", 20 | "\n", 21 | "連立方程式を満たす式\n", 22 | "$$\n", 23 | "H_A = \\sum_{j=1}^m[b_j - \\sum_{i=1}^NS_{ji}x_i]^2\n", 24 | "$$\n", 25 | "\n", 26 | "ベクトルの計算を最小化する式\n", 27 | "$$\n", 28 | "H_B = - \\sum_{i=1}^Nc_ix_i\n", 29 | "$$\n", 30 | "\n", 31 | "つないだ式。つなぐときには調整パラメーターが必要になりますので、$\\lambda$を付けました。\n", 32 | "$$\n", 33 | "H = H_A + \\lambda*H_B = \\sum_{j=1}^m[b_j - \\sum_{i=1}^NS_{ji}x_i]^2 - \\lambda*\\sum_{i=1}^Nc_ix_i\n", 34 | "$$" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "id": "076bc0c0", 40 | "metadata": {}, 41 | "source": [ 42 | "### 例題\n", 43 | "\n", 44 | "下記を満たすxのうち、\n", 45 | "\n", 46 | "$$\n", 47 | "\\begin{bmatrix}\n", 48 | "3 & 2 & 1 \\\\\n", 49 | "5 & 2 & 3\n", 50 | "\\end{bmatrix}\n", 51 | "\\begin{bmatrix}\n", 52 | "x_0\\\\x_1\\\\x_2\n", 53 | "\\end{bmatrix}\n", 54 | "=\n", 55 | "\\begin{bmatrix}\n", 56 | "3\\\\5\n", 57 | "\\end{bmatrix}\n", 58 | "$$\n", 59 | "\n", 60 | "次の式を最小にするようなxを求める。\n", 61 | "\n", 62 | "$$\n", 63 | "\\begin{bmatrix}\n", 64 | "1&2&1\n", 65 | "\\end{bmatrix}\n", 66 | "\\begin{bmatrix}\n", 67 | "x_0\\\\x_1\\\\x_2\n", 68 | "\\end{bmatrix}\n", 69 | "$$\n", 70 | "\n", 71 | "制約条件を満たすとき、QUBO式は0になります。 \n", 72 | "そのため、0にならなかったら制約を満たしていないというのがすぐにわかります。 \n", 73 | "制約を満たしてなかったらそもそも答えとして成立しません。" 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": 3, 79 | "id": "6e3647f3", 80 | "metadata": { 81 | "tags": [] 82 | }, 83 | "outputs": [ 84 | { 85 | "name": "stdout", 86 | "output_type": "stream", 87 | "text": [ 88 | "{('q_{0}', 'q_{0}'): -44, ('q_{1}', 'q_{1}'): -44, ('q_{2}', 'q_{2}'): -36, ('q_{1}', 'q_{2}'): 16, ('q_{0}', 'q_{1}'): 32, ('q_{0}', 'q_{2}'): 36} 34\n", 89 | "[[{'q_{0}': 0.0, 'q_{1}': 1.0, 'q_{2}': 1.0}, -64.0, 42], [{'q_{0}': 1.0, 'q_{1}': 1.0, 'q_{2}': 0.0}, -56.0, 58]]\n" 90 | ] 91 | } 92 | ], 93 | "source": [ 94 | "from tytan import *\n", 95 | "import sympy as sym\n", 96 | "\n", 97 | "# 変数を定義 q_0, q_1, q_2\n", 98 | "q = sym.symbols(\"q_{0:3}\")\n", 99 | "\n", 100 | "#式を別々に用意します。\n", 101 | "HA = (3*q[0]+2*q[1]+q[2]-3)**2 + (5*q[0]+2*q[1]+3*q[2]-5)**2\n", 102 | "HB = -(q[0]+2*q[1]+q[2])\n", 103 | "\n", 104 | "#つけるときに今回はConstraint関数を使うことであとで簡単に確かめができます。Constraintは制約条件の方だけにつけます。\n", 105 | "M = 10\n", 106 | "H = HA + M*HB\n", 107 | "\n", 108 | "# Compileクラスを使用して、QUBOを取得\n", 109 | "Q, offset = qubo.Compile(H).get_qubo()\n", 110 | "\n", 111 | "print(Q,offset)\n", 112 | "\n", 113 | "# サンプラーを選択\n", 114 | "solver = sampler.SASampler()\n", 115 | "\n", 116 | "#クラウドサンプラーの場合\n", 117 | "#API_KEY = \"API key\"\n", 118 | "#solver = sampler.NQSSampler()\n", 119 | "#result = solver.run(Q, api_key=API_KEY)\n", 120 | "\n", 121 | "# 計算\n", 122 | "result = solver.run(Q, shots=100)\n", 123 | "print(result)" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": 4, 129 | "id": "e6b438fe-8d10-4663-8a79-65f9a1b9ac59", 130 | "metadata": { 131 | "tags": [] 132 | }, 133 | "outputs": [ 134 | { 135 | "name": "stdout", 136 | "output_type": "stream", 137 | "text": [ 138 | "Sample = {'q_{0}': 0.0, 'q_{1}': 1.0, 'q_{2}': 1.0}\n", 139 | "Cost = -30.0000000000000\n" 140 | ] 141 | } 142 | ], 143 | "source": [ 144 | "print(\"Sample =\", result[0][0])\n", 145 | "print(\"Cost =\", result[0][1] + offset)" 146 | ] 147 | }, 148 | { 149 | "cell_type": "markdown", 150 | "id": "2a0d17c6", 151 | "metadata": {}, 152 | "source": [ 153 | "011が正解で、コストが-30.0となりました。" 154 | ] 155 | } 156 | ], 157 | "metadata": { 158 | "kernelspec": { 159 | "display_name": "Python 3 (ipykernel)", 160 | "language": "python", 161 | "name": "python3" 162 | }, 163 | "language_info": { 164 | "codemirror_mode": { 165 | "name": "ipython", 166 | "version": 3 167 | }, 168 | "file_extension": ".py", 169 | "mimetype": "text/x-python", 170 | "name": "python", 171 | "nbconvert_exporter": "python", 172 | "pygments_lexer": "ipython3", 173 | "version": "3.9.12" 174 | } 175 | }, 176 | "nbformat": 4, 177 | "nbformat_minor": 5 178 | } 179 | -------------------------------------------------------------------------------- /tutorial/tutorial04_graphcoloring.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "c86013cf", 6 | "metadata": {}, 7 | "source": [ 8 | "## グラフ分割問題とグラフカラーリング問題 \n", 9 | "あるグラフ$G=(E,V)$が与えられたときに、そのグラフを2つのグループに分割する問題であるグラフ分割問題と、グラフを複数のグラフに分割するグラフカラーリング問題についてのチュートリアルを説明します。" 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "id": "0fa09fe8", 15 | "metadata": {}, 16 | "source": [ 17 | "### グラフ分割問題\n", 18 | "頂点と辺からなるグラフを二つのグループの頂点の数がなるべく同じになるように分け、異なるグループ同士の頂点を結ぶ辺の数を最小にする。" 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "id": "9e841be1", 24 | "metadata": {}, 25 | "source": [ 26 | "### イジング式\n", 27 | "グラフを2つに分割するために、最適化したい変数は、+1と-1にするとコスト関数がシンプルになります。 \n", 28 | "今回の問題では、グラフの頂点に+1と-1の変数を割り当てて、その和が0に近づくときに、よりよく2分割できたといえるので、 \n", 29 | "この和を、コスト$H_A$とします。 \n", 30 | " \n", 31 | " \n", 32 | "次に、問題では異なるグループ同士の頂点を結ぶ点の個数も最小化したいので、このコストを$H_B$としています。\n", 33 | "\n", 34 | "\n", 35 | "コスト$H_A$はグラフの頂点の個数$N$だけある、+1と-1をとる変数$z_i$を用意して、その和をとります。\n", 36 | "\n", 37 | "$$\n", 38 | "H_A = (\\sum^N_{i=1} z_i)^2\n", 39 | "$$\n", 40 | "\n", 41 | "\n", 42 | "コスト$H_B$はグラフの頂点同士$i,j$が接続されているときに$\\frac{1 - z_i z_j}{2}$の和を取ります。\n", 43 | "$$\n", 44 | "H_B = \\sum_{i,j \\in E} \\frac{1 - z_i z_j}{2}\n", 45 | "$$\n", 46 | "\n", 47 | "$\\frac{1 - z_i z_j}{2}$を見てみましょう。 \n", 48 | "グラフの頂点$i,j$が接続されているときに、$i,j$は異なるグループだとしましょう。 \n", 49 | "これは$z_i=+1,z_j=-1$とかけるので、 \n", 50 | "$\\frac{1 - z_i z_j}{2}=1$となります。 \n", 51 | "これがもし、同じグループだとしたら、これは$z_i=-1,z_j=-1$とかけるので、 \n", 52 | "$\\frac{1 - z_i z_j}{2}=0$となります。 \n", 53 | "つまり、このコスト$H_B$は異なるグループ同士が辺で結ばれているときに+1となるコスト関数となっており、 \n", 54 | "その和をとることで、異なるグループ同士の頂点を結ぶ辺の数を最小にしています。 " 55 | ] 56 | }, 57 | { 58 | "cell_type": "markdown", 59 | "id": "fd2158dc", 60 | "metadata": {}, 61 | "source": [ 62 | "### イジング式からQUBO式に変更する\n", 63 | "\n", 64 | "TYTAN SDKは、最適化変数として、0と1のQUBO変数を採用しています。 \n", 65 | "+1と-1の変数を0と1に変換するためには、\n", 66 | "$$\n", 67 | "q_i = \\frac{1-z_i}2\n", 68 | "$$\n", 69 | "\n", 70 | "$$\n", 71 | "z_i = 1-2q_i\n", 72 | "$$\n", 73 | "\n", 74 | "の変数変換を行います。\n", 75 | "これにより、先ほど説明した$H_A$と$H_B$のコストは下記に変更されます。\n", 76 | "\n", 77 | "$$\n", 78 | "H_A = (\\sum^N_{i=1} z_i)^2 \\\\\n", 79 | "=(\\sum^N_{i=1} 1-2q_i)^2\n", 80 | "$$\n", 81 | "\n", 82 | "$$\n", 83 | "H_B = \\sum_{i,j \\in E} \\frac{1 - z_i z_j}{2} \\\\\n", 84 | "=\\sum_{i,j \\in E} \\frac{1 - (1-2q_i)(1-2q_j)}{2} \\\\\n", 85 | "=\\sum_{i,j \\in E} (q_i q_j +q_i +q_j)\n", 86 | "$$" 87 | ] 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "id": "3dff4899", 92 | "metadata": {}, 93 | "source": [ 94 | "### 練習問題\n", 95 | "4点からなる下記グラフでグラフ分割問題を解きます。" 96 | ] 97 | }, 98 | { 99 | "cell_type": "code", 100 | "execution_count": null, 101 | "id": "3370fe04", 102 | "metadata": {}, 103 | "outputs": [], 104 | "source": [ 105 | "# TYTAN SDKのインストール\n", 106 | "!pip install -q git+https://github.com/tytansdk/tytan.git" 107 | ] 108 | }, 109 | { 110 | "cell_type": "code", 111 | "execution_count": null, 112 | "id": "a6e403ac", 113 | "metadata": {}, 114 | "outputs": [], 115 | "source": [ 116 | "# グラフ表示用変数のインストール\n", 117 | "!pip install --quiet networkx matplotlib" 118 | ] 119 | }, 120 | { 121 | "cell_type": "code", 122 | "execution_count": 8, 123 | "id": "d4f4e973", 124 | "metadata": { 125 | "scrolled": true, 126 | "tags": [] 127 | }, 128 | "outputs": [ 129 | { 130 | "data": { 131 | "image/png": "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\n", 132 | "text/plain": [ 133 | "
" 134 | ] 135 | }, 136 | "metadata": {}, 137 | "output_type": "display_data" 138 | } 139 | ], 140 | "source": [ 141 | "import networkx as nx\n", 142 | "import matplotlib.pyplot as plt\n", 143 | "\n", 144 | "options = {'node_color': '#efefef','node_size': 1200,'with_labels':'True'}\n", 145 | "\n", 146 | "N = 4\n", 147 | "\n", 148 | "G = nx.Graph()\n", 149 | "G.add_nodes_from(nx.path_graph(N))\n", 150 | "G.add_edges_from([(0,1), (0,2), (0,3),(1,2),(2,3)])\n", 151 | "nx.draw(G, **options)" 152 | ] 153 | }, 154 | { 155 | "cell_type": "markdown", 156 | "id": "6106fa34", 157 | "metadata": {}, 158 | "source": [ 159 | "グラフの頂点と辺の接続を隣接行列として書き出して、TYTAN SDKに渡します。" 160 | ] 161 | }, 162 | { 163 | "cell_type": "code", 164 | "execution_count": 12, 165 | "id": "79718232", 166 | "metadata": { 167 | "scrolled": true, 168 | "tags": [] 169 | }, 170 | "outputs": [ 171 | { 172 | "name": "stdout", 173 | "output_type": "stream", 174 | "text": [ 175 | "[[0. 1. 1. 1.]\n", 176 | " [0. 0. 1. 0.]\n", 177 | " [0. 0. 0. 0.]\n", 178 | " [0. 0. 0. 0.]]\n" 179 | ] 180 | } 181 | ], 182 | "source": [ 183 | "import numpy as np\n", 184 | "\n", 185 | "#隣接行列\n", 186 | "A = np.triu(nx.to_numpy_array(G))\n", 187 | "print(A)" 188 | ] 189 | }, 190 | { 191 | "cell_type": "markdown", 192 | "id": "7d3bd935", 193 | "metadata": {}, 194 | "source": [ 195 | "コスト関数を作成します。" 196 | ] 197 | }, 198 | { 199 | "cell_type": "code", 200 | "execution_count": 15, 201 | "id": "5023b981", 202 | "metadata": {}, 203 | "outputs": [ 204 | { 205 | "name": "stdout", 206 | "output_type": "stream", 207 | "text": [ 208 | "[[{'q_{0}': 1.0, 'q_{10}': 1.0, 'q_{11}': 1.0, 'q_{1}': 1.0, 'q_{2}': 1.0, 'q_{3}': 1.0, 'q_{4}': 1.0, 'q_{5}': 1.0, 'q_{6}': 1.0, 'q_{7}': 1.0, 'q_{8}': 1.0, 'q_{9}': 1.0}, -14388.0, 100]]\n" 209 | ] 210 | } 211 | ], 212 | "source": [ 213 | "#式A\n", 214 | "HA = sum([(1-q[i]) for i in range(N)])\n", 215 | "\n", 216 | "#式B\n", 217 | "HB = 0.0\n", 218 | "for i in range(n):\n", 219 | " for j in range(i+1,n):\n", 220 | " if(A[i,j] == 1):\n", 221 | " HB += (q[i]*q[j]+q[i]+q[j])\n", 222 | "\n", 223 | "#式をつなげます。調整変数を100にしています。\n", 224 | "M = 100\n", 225 | "H = M*HA**2 + HB\n", 226 | "\n", 227 | "# Compileクラスを使用して、QUBOを取得\n", 228 | "Q, offset = qubo.Compile(H).get_qubo()\n", 229 | "\n", 230 | "# サンプラーを選択\n", 231 | "solver = sampler.SASampler()\n", 232 | "\n", 233 | "#クラウドサンプラーの場合\n", 234 | "#API_KEY = \"API key\"\n", 235 | "#solver = sampler.NQSSampler()\n", 236 | "#result = solver.run(Q, api_key=API_KEY)\n", 237 | "\n", 238 | "# 計算\n", 239 | "result = solver.run(Q, shots=100)\n", 240 | "print(result)" 241 | ] 242 | }, 243 | { 244 | "cell_type": "markdown", 245 | "id": "5a59a18b", 246 | "metadata": {}, 247 | "source": [ 248 | "4つの頂点が2つのグループに分かれました。異なるグループの間を結ぶ辺の数は最小で3となっています。答えが1010の場合にはコストが上がっており、辺の数は4となるので、最適ではなくなることから確認できます。以上です。" 249 | ] 250 | }, 251 | { 252 | "cell_type": "markdown", 253 | "id": "8a7c5981", 254 | "metadata": {}, 255 | "source": [ 256 | "## グラフカラーリング\n", 257 | "グラフ分割問題を拡張して、あるn頂点と辺からなるグラフにおいて、 \n", 258 | "グラフをm個の種類に分割する問題を見ていきます。 \n", 259 | "この問題は、グラフをm個に分割するときにグラフの頂点をmに色分けすると考えることもできるために、 \n", 260 | "グラフカラーリング問題とも呼ばれています。" 261 | ] 262 | }, 263 | { 264 | "cell_type": "markdown", 265 | "id": "4d52a656", 266 | "metadata": {}, 267 | "source": [ 268 | "### QUBO式の作成\n", 269 | "一つの頂点につきm色を割り当てる制約条件と、隣接する色同士が選ばれないようにペナルティを課す条件を結合します。 \n", 270 | "最適化する変数は、グラフの頂点$v$を色$m$で塗分けるときに、$q_{v,m}=1$となり、そうでない場合は0をとる変数です。 \n", 271 | "必要な量子ビット数はm色はn頂点で$m*n$となります。 \n", 272 | "\n", 273 | "一つの頂点に対して、色がただ1つ選ばれる制約式$H_A$\n", 274 | "$$\n", 275 | "H_A = \\sum_{v} (1 - \\sum_{i=1}^{m}q_{v,i})^2\n", 276 | "$$\n", 277 | "\n", 278 | "異なる色同士の頂点を結ぶ辺の数を最小にするコスト関数$H_B$\n", 279 | "$$\n", 280 | "H_B = \\sum_{(uv) \\in E}^{n} \\sum_{i=1}^{m} q_{u,i}*q_{v,i}\n", 281 | "$$" 282 | ] 283 | }, 284 | { 285 | "cell_type": "code", 286 | "execution_count": 10, 287 | "id": "49958da4", 288 | "metadata": { 289 | "tags": [] 290 | }, 291 | "outputs": [ 292 | { 293 | "data": { 294 | "image/png": "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\n", 295 | "text/plain": [ 296 | "
" 297 | ] 298 | }, 299 | "metadata": {}, 300 | "output_type": "display_data" 301 | } 302 | ], 303 | "source": [ 304 | "import networkx as nx\n", 305 | "import matplotlib.pyplot as plt\n", 306 | "\n", 307 | "options = {'node_color': '#efefef','node_size': 1200,'with_labels':'True'}\n", 308 | "\n", 309 | "n = 4 #頂点数\n", 310 | "m = 3 #塗分ける色の数\n", 311 | "\n", 312 | "G = nx.Graph()\n", 313 | "G.add_nodes_from(nx.path_graph(n))\n", 314 | "G.add_edges_from([(0,1), (0,2), (0,3),(1,2)])\n", 315 | "nx.draw(G, **options)" 316 | ] 317 | }, 318 | { 319 | "cell_type": "code", 320 | "execution_count": 17, 321 | "id": "bcf6c51a", 322 | "metadata": { 323 | "tags": [] 324 | }, 325 | "outputs": [], 326 | "source": [ 327 | "from tytan import *\n", 328 | "import sympy as sym\n", 329 | "\n", 330 | "#今回は12量子ビット\n", 331 | "N = n*m\n", 332 | "q = sym.symbols(\"q_{0:12}\")\n", 333 | "\n", 334 | "#隣接行列\n", 335 | "A = np.triu(nx.to_numpy_array(G))\n", 336 | "\n", 337 | "#色の通し番号を格納\n", 338 | "b = np.zeros((n,m))\n", 339 | "\n", 340 | "#後で利用するノードの色を表示するための辞書\n", 341 | "my_dict = {}\n", 342 | "\n", 343 | "#色を格納\n", 344 | "num = 0\n", 345 | "for v in range(n):\n", 346 | " for i in range(m):\n", 347 | " b[v][i] = num\n", 348 | " my_dict[num] = [str(v),i]\n", 349 | " num += 1\n", 350 | "\n", 351 | "#色を選択するQUBO\n", 352 | "h_1= 0.0\n", 353 | "const_h = 0.0\n", 354 | "for v in range (n):\n", 355 | " for i in range(m):\n", 356 | " const_h += q[int(b[v,i])]\n", 357 | " \n", 358 | " h_1 += (1 - const_h)**2\n", 359 | " const_h = 0.0\n", 360 | "\n", 361 | "#隣接するノードで同じ色が選択されないQUBO\n", 362 | "h_2 = 0.0 \n", 363 | "for u in range(n):\n", 364 | " for v in range(n):\n", 365 | " for i in range(m):\n", 366 | " if(A[u,v]==1):\n", 367 | " h_2 += q[int(b[u,i])]*q[int(b[v,i])]\n", 368 | "\n", 369 | "#QUBOを統合\n", 370 | "H = h_1 + h_2" 371 | ] 372 | }, 373 | { 374 | "cell_type": "code", 375 | "execution_count": 18, 376 | "id": "128aa504-3f08-4c59-88cc-fc7471162049", 377 | "metadata": { 378 | "tags": [] 379 | }, 380 | "outputs": [ 381 | { 382 | "name": "stdout", 383 | "output_type": "stream", 384 | "text": [ 385 | "Sample = {'q_{0}': 0.0, 'q_{10}': 0.0, 'q_{11}': 0.0, 'q_{1}': 0.0, 'q_{2}': 1.0, 'q_{3}': 0.0, 'q_{4}': 1.0, 'q_{5}': 0.0, 'q_{6}': 1.0, 'q_{7}': 0.0, 'q_{8}': 0.0, 'q_{9}': 1.0}\n", 386 | "Cost = 0\n" 387 | ] 388 | } 389 | ], 390 | "source": [ 391 | "# Compileクラスを使用して、QUBOを取得\n", 392 | "Q, offset = qubo.Compile(H).get_qubo()\n", 393 | "\n", 394 | "# サンプラーを選択\n", 395 | "solver = sampler.SASampler()\n", 396 | "\n", 397 | "#クラウドサンプラーの場合\n", 398 | "#API_KEY = \"API key\"\n", 399 | "#solver = sampler.NQSSampler()\n", 400 | "#result = solver.run(Q, api_key=API_KEY)\n", 401 | "\n", 402 | "# 計算\n", 403 | "result = solver.run(Q, shots=100)\n", 404 | "#print(result)\n", 405 | "\n", 406 | "print(\"Sample =\", result[0][0])\n", 407 | "print(\"Cost =\", result[0][1] + offset)" 408 | ] 409 | }, 410 | { 411 | "cell_type": "code", 412 | "execution_count": 19, 413 | "id": "0e6d9b4a-e22a-4470-9878-47fed994b7b7", 414 | "metadata": { 415 | "tags": [] 416 | }, 417 | "outputs": [ 418 | { 419 | "name": "stdout", 420 | "output_type": "stream", 421 | "text": [ 422 | "['0', 2]\n", 423 | "['1', 1]\n", 424 | "['2', 0]\n", 425 | "['3', 0]\n" 426 | ] 427 | } 428 | ], 429 | "source": [ 430 | "values_list = [0,0,1,0,1,0,1,0,0,1,0,0]\n", 431 | "\n", 432 | "for i in range(N):\n", 433 | " if(values_list[i]==1):\n", 434 | " print(my_dict[i])" 435 | ] 436 | }, 437 | { 438 | "cell_type": "code", 439 | "execution_count": null, 440 | "id": "ab570601", 441 | "metadata": {}, 442 | "outputs": [], 443 | "source": [] 444 | } 445 | ], 446 | "metadata": { 447 | "kernelspec": { 448 | "display_name": "Python 3 (ipykernel)", 449 | "language": "python", 450 | "name": "python3" 451 | }, 452 | "language_info": { 453 | "codemirror_mode": { 454 | "name": "ipython", 455 | "version": 3 456 | }, 457 | "file_extension": ".py", 458 | "mimetype": "text/x-python", 459 | "name": "python", 460 | "nbconvert_exporter": "python", 461 | "pygments_lexer": "ipython3", 462 | "version": "3.9.12" 463 | } 464 | }, 465 | "nbformat": 4, 466 | "nbformat_minor": 5 467 | } 468 | -------------------------------------------------------------------------------- /tutorial/tutorial06_job_sequencing_problem.ipynb: -------------------------------------------------------------------------------- 1 | {"cells":[{"cell_type":"markdown","id":"00e11159","metadata":{"id":"00e11159"},"source":["## ジョブシーケンス問題\n","計算時間が知られている$N$個のジョブをM個のコンピュータに処理させるときに、ジョブを各コンピュータに配分して、各コンピュータの実行時間を最小にする問題です。"]},{"cell_type":"markdown","id":"d4e33f8f","metadata":{"id":"d4e33f8f"},"source":["TAYTAN SDKのインストール"]},{"cell_type":"code","execution_count":null,"id":"225337df","metadata":{"id":"225337df"},"outputs":[],"source":["!pip install -q git+https://github.com/tytansdk/tytan.git"]},{"cell_type":"code","execution_count":null,"id":"90824380","metadata":{"id":"90824380"},"outputs":[],"source":["!pip install --quiet networkx matplotlib"]},{"cell_type":"markdown","id":"971cbecf","metadata":{"id":"971cbecf"},"source":["### 問題設定について\n","コンピュータはN個あります。また、コンピュータの番号を指定する文字を$a$とします。\n","ジョブはM個あり、ジョブを指定する文字を$i$とします。 $i$番目のジョブというような言い方を使います。 \n","各ジョブの実行時間は$L_i$で表します。$i$はジョブの番号です。この$L_i$はあらかじめ知られているとします。 \n","最適化したい変数は、$a$番目のコンピュータで$i$番目のジョブを行うときに1となり、 \n","そうでないときに0となる変数$x_{a,i}$とします。\n","\n","問題は、各コンピューターの実行時間を最小化したいのですが、QUBO式で表現するために工夫が入ります。 \n","問題を実行時間が最大のコンピュータの実行時間を最小化する問題として考え、 さらに、 \n","1番目のコンピュータの実行時間が最大の時間になるとして、1番目のコンピュータの実行時間を最小化する問題に変換します.\n"]},{"cell_type":"markdown","id":"ceb7439e","metadata":{"id":"ceb7439e"},"source":["### QUBO式\n","コスト関数について、説明します。 \n","コスト関数は、大きく分けて4つの構成となります。\n","\n","1つ目は、1番目のコンピュータの実行時間です。 \n","2つ目は、コンピュータ1が最大の実行時間となるコンピュータである条件です。 \n","3つ目は、ジョブ$i$はただ一つのコンピュータでのみ実行される条件です。 \n","4つ目は、2つ目の制約条件を満たすために追加する変数に関する制約条件です。 \n","\n","\n","\n","1つ目の、1番目のコンピュータの実行時間を定式化すると以下になります。\n","$$\n","H_A = \\sum_{i} L_i x_{1,i}\n","$$\n","\n","2つ目は、コンピュータ1が最大の実行時間となるコンピュータである条件は、\n","$$\n","H_B =\\sum_{a=2} \\{ \\sum_n^M n y_{n,a} - \\sum_{i}( L_i x_{1,i} - L_i x_{a,i})\\}^2\n","$$\n","\n"," \n","ここで、補助変数$y_{n,a}$は、コンピュータ1とコンピュータ$a$の実行時間の差が$n$であるときに1、そうでない場合は0となる補助変数です。 \n","定数$M$はノード1との実行時間の差の最大値で, 任意で決めるハイパーパラメータです。 \n","\n","\n","3つ目は、ジョブ$i$はただ一つのコンピュータでのみ実行される条件\n","$$\n","H_C = \\sum_{i} (1 - \\sum_{a} x_{a,i})^2\n","$$\n","\n","4つ目は、変数$y_{n,a}$がaに対してただ1つだけ1になる条件です。 \n","また、変数の一つだけが1となる変数をone-hot変数といいます。 \n","$$\n","H_D = \\sum_{a} (1 - \\sum_{n} y_{n,a})^2\n","$$\n"]},{"cell_type":"markdown","id":"4445e16d","metadata":{"id":"4445e16d"},"source":["## 問題設定\n","$10$個のジョブがある.\n","各ジョブの実行時間は,\n","\n","|ジョブ | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |\n","| ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |\n","| 時間 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |\n","\n","上記のジョブを3つのノードに分けて実行するときに, 最大実行時間のノードを最小化する.\n","\n","| COM| 1 | 2 | 3 | 4 | 合計 |\n","| ---- | ---- | ---- | ---- | ---- | ---- |\n","|COM1| 4 | 7 | 8 | 0 | 19 |\n","|COM2| 1 | 2 | 5 | 10 | 18 |\n","|COM3| 3 | 6 | 9 | 0 | 18 |"]},{"cell_type":"code","execution_count":90,"id":"9354e6ac","metadata":{"scrolled":true,"colab":{"base_uri":"https://localhost:8080/"},"id":"9354e6ac","executionInfo":{"status":"ok","timestamp":1688884085127,"user_tz":-540,"elapsed":1543,"user":{"displayName":"ビネットクラリティ","userId":"09491866446551609298"}},"outputId":"68f57677-d3c7-432b-ce03-093214b37c1e"},"outputs":[{"output_type":"stream","name":"stdout","text":["Cost = 19.0000000000000\n","[1. 0. 1. 0. 1. 0. 0. 0. 0. 1. 0. 0. 0. 1. 0. 1. 0. 1. 0. 0. 0. 1. 0. 0.\n"," 0. 0. 1. 0. 1. 0. 0. 1. 0. 0. 0. 0. 1. 0. 0. 0.]\n","コンピュータ1 [1. 0. 1. 0. 1. 0. 0. 0. 0. 1.] 19.0\n","コンピュータ2 [0. 0. 0. 1. 0. 1. 0. 1. 0. 0.] 18.0\n","コンピュータ3 [0. 1. 0. 0. 0. 0. 1. 0. 1. 0.] 18.0\n","onehot1 [0. 1. 0. 0. 0.]\n","onehot2 [0. 1. 0. 0. 0.]\n","制約B 2.0\n"]}],"source":["import numpy as np\n","import sympy as sym\n","from tytan import symbols, Compile, sampler\n","\n","#40量子ビット\n","J=10 #ジョブの数\n","N=3 #コンピュータの数\n","M=5 #最大実行時間の差 #5であれば差が0,1,2,3,4のどれかということ\n","\n","#量子ビットJ*N=30\n","#one hot用の量子ビット (N-1)*M=10\n","q = symbols(\"q_{0:40}\") # qubo\n","\n","#ジョブの実行時間\n","L=np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])\n","\n","\n","#式A 1番目のCOMの実行時間\n","HA=0\n","for i in range(J):#ジョブ数\n"," HA += L[i]*q[i]\n","\n","#式B\n","HB=0\n","for a in range(1,N): #コンピュータ数\n"," tmp=0\n"," for n in range(M):#最大実行時間\n"," tmp += n*q[J*N+(a-1)*M+n]\n","\n"," for i in range(J):#ジョブ数\n"," tmp += -L[i]*(q[i]-q[a*J+i])\n"," HB += tmp**2\n","\n","#式C onehot\n","HC=0\n","for i in range(J):#ジョブ数\n"," tmp=0\n"," for a in range(N):#コンピュータ数\n"," tmp += q[a*J+i]\n"," HC += (1-tmp)**2\n","\n","#式D onehot\n","HD=0\n","for i in range(N-1):#コンピュータ数\n"," tmp=0\n"," for a in range(M):\n"," tmp += q[J*N+i*M+a]\n"," HD += (1-tmp)**2\n","\n","#式をつなげる\n","H = 1*HA + 10*HB + 10*HC + 10*HD\n","\n","# Compileクラスを使用して、QUBOを取得\n","Q, offset = Compile(H).get_qubo()\n","\n","#print(Q)\n","\n","# サンプラーを選択\n","solver = sampler.SASampler()\n","\n","#クラウドサンプラーの場合\n","#API_KEY = \"KjGh2i75pUNXvihIMgNiQfMAQmbU8iVe01tjStnYJWMb8AS1SSys3SPpMN_q_8gl\"\n","#solver = sampler.NQSSampler()\n","#result = solver.run(Q, api_key=API_KEY)\n","\n","# 計算\n","result = solver.run(Q, shots=1000)\n","\n","#print(\"Sample =\", result[0][0])\n","print(\"Cost =\", result[0][1] + offset)\n","\n","#量子ビットの取り出し\n","qbit=np.zeros(40)\n","i=0\n","for key, value in result[0][0].items():\n"," key=key.replace('q_{', '')\n"," key=key.replace('}', '')\n"," qbit[int(key)]=value\n"," i=i+1\n","print(qbit)\n","print('コンピュータ1',qbit[0:10], np.sum(L*qbit[0:10]))\n","print('コンピュータ2',qbit[10:20], np.sum(L*qbit[10:20]))\n","print('コンピュータ3',qbit[20:30], np.sum(L*qbit[20:30]))\n","\n","print('onehot1',qbit[30:35])\n","print('onehot2',qbit[35:40])\n","#制約条件\n","B=0\n","for a in range(1,N): #コンピュータ数\n"," tmp=0\n"," for n in range(M):#最大実行時間\n"," tmp += (n+1)*qbit[J*N+(a-1)*M+n]\n","\n"," for i in range(J):#ジョブ数\n"," tmp += -L[i]*(qbit[i]-qbit[a*J+i])\n"," B += tmp\n","print('制約B',B)"]},{"cell_type":"markdown","source":["[19, 18, 18] と [19, 19, 17] が同じエネルギーで得られます(ランダムに)"],"metadata":{"id":"J3whNuQMSFyG"},"id":"J3whNuQMSFyG"},{"cell_type":"code","execution_count":null,"id":"b839f3c9","metadata":{"scrolled":true,"id":"b839f3c9","outputId":"73fa7c67-af3d-454e-ce32-e61969133a96"},"outputs":[{"name":"stdout","output_type":"stream","text":["Cost = -42.0\n","Break = {}\n","[1. 0. 1. 0. 0. 0. 1. 0. 0. 1. 0. 1. 0. 0. 0. 1. 0. 0. 1. 0. 0. 0. 0. 1.\n"," 1. 0. 0. 1. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 1. 0.]\n","コンピュータ1 [1. 0. 1. 0. 0. 0. 1. 0. 0. 1.]\n","コンピュータ2 [0. 1. 0. 0. 0. 1. 0. 0. 1. 0.]\n","コンピュータ3 [0. 0. 0. 1. 1. 0. 0. 1. 0. 0.]\n","onehot1 [0. 0. 0. 1. 0.]\n","onehot2 [0. 0. 0. 1. 0.]\n","制約B 0.0\n"]}],"source":["# D-wave シュミレーション例\n","import numpy as np\n","import sympy as sym\n","#from tytan import *\n","from pyqubo import Array, Constraint\n","import neal\n","q = Array.create('q', shape=40, vartype='BINARY')\n","\n","#今回は4量子ビットのみ\n","J=10 #ジョブの数\n","N=3 #コンピュータの数\n","M=5 #最大実行時間の差\n","\n","#量子ビットJ*N\n","#one hot用の量子ビット (N-1)*M=6\n","#q = sym.symbols(\"q_{0:36}\") # qubo\n","\n","#ジョブの実行時間\n","L=np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])\n","\n","\n","#式A 1番目のCOMの実行時間\n","HA=0\n","for i in range(J):#ジョブ数\n"," HA += -L[i]*q[i]\n","\n","#式B\n","HB=0\n","for a in range(1,N): #コンピュータ数\n"," tmp=0\n"," for n in range(M):#最大実行時間\n"," tmp += (n+1)*q[J*N+(a-1)*M+n]\n","\n"," for i in range(J):#ジョブ数\n"," tmp += -L[i]*(q[i]-q[a*J+i])\n"," HB += tmp**2\n","\n","#式C\n","HC=0\n","for i in range(J):#ジョブ数\n"," tmp=0\n"," for a in range(N):#コンピュータ数\n"," tmp += q[a*J+i]\n"," HC += (1-tmp)**2\n","\n","\n","#式D onehot\n","HD=0\n","for i in range(N-1):#コンピュータ数\n"," tmp=0\n"," for a in range(M):\n"," tmp += q[J*N+i*M+a]\n"," HD += (1-tmp)**2\n","\n","#式をつなげる\n","H = 2*HA+2*Constraint(HB,'HB')+7*Constraint(HC,'HC')+3*Constraint(HD,'HD')\n","\n","#D-Waveの形式に変換\n","model = H.compile()\n","bqm = model.to_bqm()\n","\n","#計算実行\n","sa = neal.SimulatedAnnealingSampler()\n","sampleset = sa.sample(bqm, num_reads=10)\n","#print(sampleset)\n","\n","decoded_samples = model.decode_sampleset(sampleset)\n","best_sample = min(decoded_samples, key=lambda x: x.energy)\n","#print(\"Sample =\", best_sample.sample)\n","print(\"Cost =\", best_sample.energy)\n","print(\"Break =\", best_sample.constraints(only_broken=True))\n","\n","#量子ビットの取り出し\n","qbit=np.zeros(40)\n","i=0\n","for key, value in best_sample.sample.items():\n"," key=key.replace('q[', '')\n"," key=key.replace(']', '')\n"," qbit[int(key)]=value\n"," i=i+1\n","\n","print(qbit)\n","print('コンピュータ1',qbit[0:10])\n","print('コンピュータ2',qbit[10:20])\n","print('コンピュータ3',qbit[20:30])\n","\n","print('onehot1',qbit[30:35])\n","print('onehot2',qbit[35:40])\n","\n","#制約条件\n","B=0\n","for a in range(1,N): #コンピュータ数\n"," tmp=0\n"," for n in range(M):#最大実行時間\n"," tmp += (n+1)*qbit[J*N+(a-1)*M+n]\n","\n"," for i in range(J):#ジョブ数\n"," tmp += -L[i]*(qbit[i]-qbit[a*J+i])\n"," B += tmp\n","print('制約B',B)"]},{"cell_type":"markdown","id":"035842f4","metadata":{"id":"035842f4"},"source":["コンピューター1 = {1,3,7,10} 実行時間21 \n","コンピューター2 = {2,6,9}   実行時間17 \n","コンピューター3 = {4,5,8} 実行時間17 "]},{"cell_type":"markdown","id":"b93db51d","metadata":{"id":"b93db51d"},"source":["## ナップザック問題\n","価値が分かっている$N$個の荷物があります. この荷物をナップザックの最大容量$W$を超えない範囲で入れるときに, 価値の合計を最大化する組み合わせを探す問題です.\n","\n","| 荷物 | 1 | 2 | 3 | 4 | 5 |\n","| ---- | ---- | ---- | ---- | ---- | ---- |\n","| 重さ | 4 | 7 | 1 | 3 | 5 |\n","| 価値 | 10 | 13 | 7 | 9 | 8 |\n","\n","ナップザックの最大容量が10のとき,\n","荷物1,3,4を入れると容量が8で価値26となります.\n","総当たりで探索すると$2^N$回の探索が必要になります. (NP困難)"]},{"cell_type":"markdown","id":"03a84ebe","metadata":{"id":"03a84ebe"},"source":["### QUBO式\n","\n","$i$番目の荷物をナップザックに入れる場合は, $x_i=1$, 入れない場合は, $x_i=0$とします.\n","\n","$i$番目の荷物の容量を$w_i$, 荷物の価値を$c_i$とします.\n","\n","ナップザックに入れる荷物の価値を最大化したいので, QUBOコスト関数は,\n","$$\n","H_A = -\\sum^N_{i=1} c_i x_i\n","$$\n","です.\n","\n","QUBO式にマイナスがついているのは, QUBO関数は最小に向かうために, 関数を最大化したいときにはマイナスを付けます.\n","\n","制約式は, ナップザックに入れる荷物が総体積以下になる条件\n","$$\n","\\sum^N_{i=1} w_i x_i < W\n","$$\n","ですが, QUBO式は不等式を扱えません.\n","\n","そのために補助バイナリ変数$y_n$を導入します.\n","$y_n$はナップザックに入れる荷物の容量の合計が, $n$のときに$y_n=1$となる変数です.\n","ナップザックの最大容量は$W$なので$n$は0から$N$までの値を取ります.\n","\n","$y_n$は荷物の容量の合計値なので, $N$個ある$y_n$はただ1つのみ1になる制約があります.\n","制約式を書くと,\n","\n","$$\n","H_B = (1-\\sum^W_{n=1} y_n)^2\n","$$\n","\n","$y_n=1$になるときに, ナップザックの荷物の容量の合計$ \\sum^N_{i=1} w_i x_i = n$になるような条件式を追加します.\n","$$\n","H_C = (\\sum^W_{n=1}n y_n - \\sum^N_{i=1} w_i x_i)^2\n","$$\n","変数$y_{n,a}$がaに対してただ1つだけ1になる条件です。 \n","また、変数の一つだけが1となる変数をone-hot変数といいます。 \n"]},{"cell_type":"markdown","id":"bba715f4","metadata":{"id":"bba715f4"},"source":["## 問題設定\n","\n","ナップザックの最大容量$W=12$のとき, 以下の$N=5$個の荷物を考えます.\n","\n","| 荷物 | 1 | 2 | 3 | 4 | 5 |\n","| ---- | ---- | ---- | ---- | ---- | ---- |\n","| 重さ | 3 | 4 | 6 | 1 | 5 |\n","| 価値 | 6 | 7 | 8 | 1 | 4 |\n","\n","必要なビット変数は, $N+W=5+12=17$"]},{"cell_type":"code","execution_count":null,"id":"b696f0ff","metadata":{"id":"b696f0ff","outputId":"4080f53a-fd62-4581-9074-7141747aea9e"},"outputs":[{"name":"stdout","output_type":"stream","text":["Cost = -2.0\n","q= [1. 1. 0. 0. 1.]\n","重さ 12.0\n","コスト 17.0\n","onehot= [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1.]\n"]}],"source":["import numpy as np\n","from tytan import *\n","import sympy as sym\n","\n","#17量子ビットのみ\n","N=5\n","W=12\n","\n","M=N+W\n","q = sym.symbols(\"q_{0:17}\")\n","\n","#重さ\n","w=np.array([3, 4, 6, 1, 5])\n","\n","#価値\n","c=np.array([6 ,7, 8, 1, 4])\n","\n","#式A\n","HA=0\n","for i in range(N):\n"," HA += -c[i]*q[i]\n","\n","#式B\n","HB=0\n","for i in range(N,N+W):\n"," HB +=q[i]\n","HB = HB**2\n","\n","#式C\n","HC=0\n","for i in range(N,N+W):\n"," HC += (i-4)*q[i]\n","for j in range(N):\n"," HC += -w[j]*q[j]\n","\n","HC=(HC)**2\n","\n","\n","#式をつなげる\n","H = 1*HA+15*HB+7*HC\n","\n","# Compileクラスを使用して、QUBOを取得\n","Q, offset = qubo.Compile(H).get_qubo()\n","\n","#print(Q)\n","\n","# サンプラーを選択\n","solver = sampler.SASampler()\n","\n","#クラウドサンプラーの場合\n","#API_KEY = \"KjGh2i75pUNXvihIMgNiQfMAQmbU8iVe01tjStnYJWMb8AS1SSys3SPpMN_q_8gl\"\n","#solver = sampler.NQSSampler()\n","#result = solver.run(Q, api_key=API_KEY)\n","\n","# 計算\n","result = solver.run(Q, shots=1000)\n","\n","#print(\"Sample =\", result[0][0])\n","print(\"Cost =\", result[0][1] + offset)\n","\n","#量子ビットの取り出し\n","qbit=np.zeros(40)\n","i=0\n","for key, value in result[0][0].items():\n"," key=key.replace('q_{', '')\n"," key=key.replace('}', '')\n"," qbit[int(key)]=value\n"," i=i+1\n","print('q=',qbit[0:N])\n","print('重さ',w[0]*qbit[0]+w[1]*qbit[1]+w[2]*qbit[2]+w[3]*qbit[3]+w[4]*qbit[4])\n","print('コスト',c[0]*qbit[0]+c[1]*qbit[1]+c[2]*qbit[2]+c[3]*qbit[3]+c[4]*qbit[4])\n","print('onehot=',qbit[N:N+W])"]},{"cell_type":"code","execution_count":null,"id":"f3b0564b","metadata":{"id":"f3b0564b"},"outputs":[],"source":[" 荷物1,2,5を入れるときに制約を満たす結果が得られました。その時の価値は17となっています。"]},{"cell_type":"code","execution_count":null,"id":"44628408","metadata":{"id":"44628408","outputId":"a39494f1-c61c-468b-8768-441afe6feac5"},"outputs":[{"name":"stdout","output_type":"stream","text":["Cost = -15.0\n","Break = {}\n","q= [1. 0. 1. 1. 0.]\n","重さ 10.0\n","コスト 15.0\n","onehot= [0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]\n"]}],"source":["# D-WAVEシュミレータ\n","import numpy as np\n","from tytan import *\n","import sympy as sym\n","from pyqubo import Array, Constraint\n","import neal\n","\n","#17量子ビット\n","N=5\n","W=12\n","\n","M=N+W\n","q = Array.create('q', shape=17, vartype='BINARY')\n","#重さ\n","w=np.array([3, 4, 6, 1, 5])\n","\n","#価値\n","c=np.array([6 ,7, 8, 1, 4])\n","\n","#式A\n","HA=0\n","for i in range(N):\n"," HA += -c[i]*q[i]\n","\n","#式B\n","HB=0\n","for i in range(N,N+W):\n"," HB +=q[i]\n","HB = (HB-1)**2\n","\n","#式C\n","HC=0\n","for i in range(N,N+W):\n"," HC += (i-4)*q[i]\n","for j in range(N):\n"," HC += -w[j]*q[j]\n","\n","HC=(HC)**2\n","\n","\n","#式をつなげる\n","H = 1*HA+15*Constraint(HB,'HB')+7*Constraint(HC,'HC')\n","\n","#D-Waveの形式に変換\n","model = H.compile()\n","bqm = model.to_bqm()\n","\n","#計算実行\n","sa = neal.SimulatedAnnealingSampler()\n","sampleset = sa.sample(bqm, num_reads=10)\n","#print(sampleset)\n","\n","decoded_samples = model.decode_sampleset(sampleset)\n","best_sample = min(decoded_samples, key=lambda x: x.energy)\n","#print(\"Sample =\", best_sample.sample)\n","print(\"Cost =\", best_sample.energy)\n","print(\"Break =\", best_sample.constraints(only_broken=True))\n","\n","#量子ビットの取り出し\n","qbit=np.zeros(40)\n","i=0\n","for key, value in best_sample.sample.items():\n"," key=key.replace('q[', '')\n"," key=key.replace(']', '')\n"," qbit[int(key)]=value\n"," i=i+1\n","print('q=',qbit[0:N])\n","print('重さ',w[0]*qbit[0]+w[1]*qbit[1]+w[2]*qbit[2]+w[3]*qbit[3]+w[4]*qbit[4])\n","print('コスト',c[0]*qbit[0]+c[1]*qbit[1]+c[2]*qbit[2]+c[3]*qbit[3]+c[4]*qbit[4])\n","print('onehot=',qbit[N:N+W])"]},{"cell_type":"markdown","id":"1e697797","metadata":{"id":"1e697797"},"source":[" 荷物1,3,4を入れるときに制約を満たす結果が得られました。そのときの価値は15となりました。"]},{"cell_type":"code","execution_count":null,"id":"12db1bf0","metadata":{"id":"12db1bf0"},"outputs":[],"source":[]}],"metadata":{"kernelspec":{"display_name":"Python 3 (ipykernel)","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.10.9"},"colab":{"provenance":[]}},"nbformat":4,"nbformat_minor":5} -------------------------------------------------------------------------------- /tutorial/tutorial07_setcover_setpacking.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "4e458f57", 6 | "metadata": {}, 7 | "source": [ 8 | "## 組合せ最適化問題\n", 9 | "量子コンピュータで最適化問題を解くには、イジングモデルといわれる物理モデルを利用する。" 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "id": "22d56ee1", 15 | "metadata": {}, 16 | "source": [ 17 | "## QUBO定式化\n", 18 | "QUBOは問題の答えが小さいほうが正解になるように設定された式です。式の形は、\n", 19 | "\n", 20 | "$$\n", 21 | "QUBO = -\\sum_i h_i q_i -\\sum_{i,j}J_{ij}q_iq_j\n", 22 | "$$\n", 23 | "\n", 24 | "となっている。iとjは点を表し、hはバイアス(局所磁場)、Jは相互作用と呼ばれます。この式ではqは量子ビットを表し0か1を取ります(イジングの場合は+1か-1)。\n", 25 | "私たちはhとJを問題として設定し、qの値を求めます。" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "id": "a3fb7f40", 31 | "metadata": {}, 32 | "source": [ 33 | "## 問題設定の仕方\n", 34 | "問題の設定の仕方は、グラフ問題というものに問題を落とすことで計算できますが、いくつか問題を解くことでコツをつかめます。\n", 35 | "\n", 36 | "主に問題のコスト関数は二種類の式を考える必要があります。\n", 37 | "\n", 38 | "1.小さくしたいコスト関数 \n", 39 | "2.満たすべき条件(制約条件)\n", 40 | "\n", 41 | "この二つを別々に設計し、つなげることで実装できます。片方しかない式もあります。" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": 1, 47 | "id": "126af32f", 48 | "metadata": { 49 | "scrolled": true, 50 | "tags": [] 51 | }, 52 | "outputs": [], 53 | "source": [ 54 | "!pip install --quiet matplotlib" 55 | ] 56 | }, 57 | { 58 | "cell_type": "markdown", 59 | "id": "d9e22808", 60 | "metadata": {}, 61 | "source": [ 62 | "## set cover(集合被覆問題)\n", 63 | "\n", 64 | "全体集合$U=\\{e_1,e_2,e_3,e_4\\}$の部分集合$S= \\{S_1,S_2,S_3,S_4 \\}$\n", 65 | "のうち、全体集合Uの要素をすべてカバーする部分集合のうち最小のものを求める。\n" 66 | ] 67 | }, 68 | { 69 | "cell_type": "markdown", 70 | "id": "f1dd786a", 71 | "metadata": {}, 72 | "source": [ 73 | "## QUBO式\n", 74 | "\n", 75 | "問題をバイナリ変数で表す。 \n", 76 | "バイナリ変数$y_i$は, 部分集合$S_i$を選択する場合は1、それ以外は0になる変数 \n", 77 | "バイナリ変数$x_{a,m}$は、選択した部分集合のうち、要素$a$が$m$個のときは1、そうでない場合は0とする。\n", 78 | "\n", 79 | "QUBO最適化関数は、\n", 80 | "\n", 81 | "$$H = H _ A + H _ B$$\n", 82 | "$$\n", 83 | "H_{A}=A\\sum_{a=1}^{n} (1-\\sum_{m}^N x_{a,m})^2 + A\\sum_{a=1}^{n} (\\sum_{m}^N mx_{a,m}-\\sum_{i:a \\in V_i}y_{i})^2\n", 84 | "$$\n", 85 | "$$H_B = B \\sum_{i=1}^{N}x_i$$\n", 86 | "\n", 87 | "$n$は部分集合の個数 \n", 88 | "$N$は要素の数\n", 89 | "\n", 90 | "### QUBO式の解説\n", 91 | "\n", 92 | "$$\n", 93 | "A\\sum_{a=1}^{n} (1-\\sum_{m}^N x_{a,m})^2\n", 94 | "$$\n", 95 | "\n", 96 | "要素数$m$が各要素に対して、ただ1つのみ$x_{a,m}=1$になる条件\n", 97 | "\n", 98 | "$$\n", 99 | "A\\sum_{a=1}^{n} (\\sum_{m}^N mx_{a,m}-\\sum_{i:a \\in V_i}y_{i})^2\n", 100 | "$$\n", 101 | "選択した集合がの各要素数が$m$個になる条件\n", 102 | "\n", 103 | "$$\n", 104 | "B \\sum_{i=1}^{N}x_i\n", 105 | "$$\n", 106 | "\n", 107 | "選択する集合を最小化する条件" 108 | ] 109 | }, 110 | { 111 | "cell_type": "markdown", 112 | "id": "192a9688", 113 | "metadata": {}, 114 | "source": [ 115 | "## 例題\n", 116 | "\n", 117 | "全体集合$U= \\{1,2,3,4 \\}$ \n", 118 | "部分集合 \n", 119 | "$S_0=\\{1,2\\}$ \n", 120 | "$S_1=\\{2,3\\}$ \n", 121 | "$S_2=\\{3,4\\}$ \n", 122 | "\n", 123 | "集合$U$の要素をすべてカバーする、最小の部分集合$S$を選ぶ" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": 1, 129 | "id": "f062333e", 130 | "metadata": {}, 131 | "outputs": [ 132 | { 133 | "name": "stdout", 134 | "output_type": "stream", 135 | "text": [ 136 | "Sample = {'q[9]': 0, 'q[7]': 0, 'q[8]': 1, 'q[4]': 1, 'q[17]': 0, 'q[6]': 0, 'q[12]': 1, 'q[16]': 1, 'q[11]': 0, 'q[0]': 1, 'q[3]': 0, 'q[10]': 0, 'q[14]': 0, 'q[5]': 0, 'q[2]': 0, 'q[18]': 1, 'q[13]': 0, 'q[15]': 0, 'q[1]': 0}\n", 137 | "Cost = 2.0\n", 138 | "Break = {}\n" 139 | ] 140 | } 141 | ], 142 | "source": [ 143 | "\n", 144 | "import numpy as np\n", 145 | "\n", 146 | "#量子ビット\n", 147 | "N=3 #部分集合の数\n", 148 | "M=4 #Uの要素数\n", 149 | "\n", 150 | "#q = Array.create('q', shape=M*M+N, vartype='BINARY')\n", 151 | "\n", 152 | "#集合U\n", 153 | "U=np.array([1, 2, 3, 4])\n", 154 | "\n", 155 | "#部分集合\n", 156 | "S=np.array([[1, 2], #S0\n", 157 | " [2, 3], #S1\n", 158 | " [3, 4]]) #S2\n", 159 | "\n", 160 | "\n", 161 | "#QUBO式\n", 162 | "HA = 0\n", 163 | "for a in range(M): #要素数\n", 164 | " tmp=0\n", 165 | " for m in range(M): \n", 166 | " tmp += q[M*a+m]\n", 167 | " HA+=(1-tmp)**2\n", 168 | " \n", 169 | "HB = 0\n", 170 | "for a in range(M):\n", 171 | " tmp = 0\n", 172 | " for m in range(M):\n", 173 | " tmp += (m+1)*q[M*a+m]\n", 174 | " \n", 175 | " for i in range(N):\n", 176 | " for j in range(2):\n", 177 | " if S[i,j]==U[a]:\n", 178 | " tmp += -q[M*M+i]\n", 179 | " HB+=tmp**2\n", 180 | " \n", 181 | "HC =0\n", 182 | "for i in range(N):\n", 183 | " HC += q[M*M+i]\n", 184 | "\n", 185 | "\n", 186 | "#式をつなげる\n", 187 | "H = HA + HB + HC" 188 | ] 189 | }, 190 | { 191 | "cell_type": "markdown", 192 | "id": "c2afbcaf", 193 | "metadata": {}, 194 | "source": [ 195 | "結果を確認すると、$S_0$と$S_1$を選択すると、全体集合の要素数をカバーできることが分かる。" 196 | ] 197 | }, 198 | { 199 | "cell_type": "markdown", 200 | "id": "e61de0bd", 201 | "metadata": {}, 202 | "source": [ 203 | "## set packing(集合パッキング問題)\n", 204 | "\n", 205 | "全体集合$U=\\{e_1,e_2,e_3,e_4\\}$の部分集合$S= \\{S_1,S_2,S_3,S_4 \\}$\n", 206 | "のうち、共通の要素を持たない部分集合のうち最大のものを求める。 \n" 207 | ] 208 | }, 209 | { 210 | "cell_type": "markdown", 211 | "id": "f0488c27", 212 | "metadata": {}, 213 | "source": [ 214 | "### QUBO式\n", 215 | "\n", 216 | "$$\n", 217 | "\\large\n", 218 | "H_A = A\\sum_{i,j:V_i \\cap V_j \\neq \\emptyset} x_ix_j \n", 219 | "$$\n", 220 | "\n", 221 | "$$\n", 222 | "H_B= -B \\sum_i x_i\n", 223 | "$$" 224 | ] 225 | }, 226 | { 227 | "cell_type": "markdown", 228 | "id": "90d6bc9d", 229 | "metadata": {}, 230 | "source": [ 231 | "## 問題設定\n", 232 | "\n" 233 | ] 234 | }, 235 | { 236 | "cell_type": "code", 237 | "execution_count": 3, 238 | "id": "fc535dd9", 239 | "metadata": {}, 240 | "outputs": [ 241 | { 242 | "name": "stdout", 243 | "output_type": "stream", 244 | "text": [ 245 | "Sample = {'q[2]': 1, 'q[0]': 1, 'q[1]': 0}\n", 246 | "Cost = -2.0\n", 247 | "Break = {}\n" 248 | ] 249 | } 250 | ], 251 | "source": [ 252 | "import numpy as np\n", 253 | "\n", 254 | "#量子ビット\n", 255 | "N=3 #部分集合の数\n", 256 | "\n", 257 | "#q = Array.create('q', shape=N, vartype='BINARY')\n", 258 | "\n", 259 | "#集合U\n", 260 | "U=np.array([1, 2, 3, 4])\n", 261 | "\n", 262 | "#部分集合\n", 263 | "S=np.array([[1, 2], #S0\n", 264 | " [2, 3], #S1\n", 265 | " [3, 4]]) #S2\n", 266 | "\n", 267 | "#QUBO式\n", 268 | "HA = 0\n", 269 | "for i in range(N):\n", 270 | " for j in range(N):\n", 271 | " c =np.intersect1d(S[i], S[j]) #共通要素\n", 272 | " if i!=j and c.size != 0:\n", 273 | " HA += q[i]*q[j] \n", 274 | " \n", 275 | "HB = 0\n", 276 | "for i in range(N):\n", 277 | " HB += -q[i]\n", 278 | "\n", 279 | "\n", 280 | "#式をつなげる\n", 281 | "H = HA + HB" 282 | ] 283 | }, 284 | { 285 | "cell_type": "markdown", 286 | "id": "9ed32338", 287 | "metadata": {}, 288 | "source": [ 289 | "$S_0, S_2$を選択する、先ほどと同じ解が得られました。" 290 | ] 291 | }, 292 | { 293 | "cell_type": "markdown", 294 | "id": "6d932e8f", 295 | "metadata": {}, 296 | "source": [ 297 | "### 問題2\n", 298 | "\n", 299 | "全体集合$U= \\{1,2,3,4,5,6,7,8,9 \\}$ \n", 300 | "部分集合 \n", 301 | "$S_0=\\{1,2,3,6,9 \\}$ \n", 302 | "$S_1=\\{1,2,5,8 \\}$ \n", 303 | "$S_2=\\{4,7 \\}$ \n", 304 | "$S_3=\\{4,5 \\}$ \n", 305 | "$S_4=\\{6,9 \\}$ " 306 | ] 307 | }, 308 | { 309 | "cell_type": "code", 310 | "execution_count": 111, 311 | "id": "f64f4157", 312 | "metadata": {}, 313 | "outputs": [ 314 | { 315 | "name": "stdout", 316 | "output_type": "stream", 317 | "text": [ 318 | "Sample = {'q[0]': 0, 'q[1]': 1, 'q[2]': 1, 'q[3]': 0, 'q[4]': 1}\n", 319 | "Cost = -3.0\n", 320 | "Break = {}\n" 321 | ] 322 | }, 323 | { 324 | "name": "stderr", 325 | "output_type": "stream", 326 | "text": [ 327 | "C:\\Users\\005087\\AppData\\Local\\Temp\\ipykernel_1748\\4142535172.py:14: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.\n", 328 | " S=np.array([[1,2,3,6,9],[1,2,5,8],[4,7],[4,5],[6,9]])\n" 329 | ] 330 | } 331 | ], 332 | "source": [ 333 | "import numpy as np\n", 334 | "\n", 335 | "#量子ビット\n", 336 | "N=5 #部分集合の数\n", 337 | "\n", 338 | "#q = Array.create('q', shape=N, vartype='BINARY')\n", 339 | "\n", 340 | "#集合U\n", 341 | "U=np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])\n", 342 | "\n", 343 | "#部分集合\n", 344 | "S=np.array([[1,2,3,6,9],[1,2,5,8],[4,7],[4,5],[6,9]])\n", 345 | "\n", 346 | "#QUBO式\n", 347 | "HA = 0\n", 348 | "for i in range(N):\n", 349 | " for j in range(N):\n", 350 | " c =np.intersect1d(S[i], S[j]) #共通要素\n", 351 | " if i!=j and c.size != 0:\n", 352 | " HA += q[i]*q[j] \n", 353 | " \n", 354 | "HB = 0\n", 355 | "for i in range(N):\n", 356 | " HB += -q[i]\n", 357 | "\n", 358 | "\n", 359 | "#式をつなげる\n", 360 | "H = HA + HB" 361 | ] 362 | }, 363 | { 364 | "cell_type": "code", 365 | "execution_count": 2, 366 | "id": "3558cc76", 367 | "metadata": {}, 368 | "outputs": [ 369 | { 370 | "name": "stdout", 371 | "output_type": "stream", 372 | "text": [ 373 | "Sample = {'q[5]': 1, 'q[6]': 0, 'q[1]': 1, 'q[4]': 0, 'q[0]': 1, 'q[3]': 0, 'q[2]': 1}\n", 374 | "Cost = -4.0\n", 375 | "Break = {}\n" 376 | ] 377 | }, 378 | { 379 | "name": "stderr", 380 | "output_type": "stream", 381 | "text": [ 382 | "/home/ec2-user/anaconda3/envs/python3/lib/python3.6/site-packages/ipykernel/__main__.py:14: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray\n" 383 | ] 384 | } 385 | ], 386 | "source": [ 387 | "import numpy as np\n", 388 | "\n", 389 | "#量子ビット\n", 390 | "N=7 #部分集合の数\n", 391 | "\n", 392 | "#q = Array.create('q', shape=N, vartype='BINARY')\n", 393 | "\n", 394 | "#集合U\n", 395 | "U=np.array([1, 2, 3, 4, 5, 6, 7, 8, 9 ,10,11,12])\n", 396 | "\n", 397 | "#部分集合\n", 398 | "S=np.array([[1,4],[2,5],[3,6],[1,2,3,4,6,7,9],[4,5,7,8],[7,8,9,10,11,12],[6,11]])\n", 399 | "\n", 400 | "#QUBO式\n", 401 | "HA = 0\n", 402 | "for i in range(N):\n", 403 | " for j in range(N):\n", 404 | " c =np.intersect1d(S[i], S[j]) #共通要素\n", 405 | " if i!=j and c.size != 0:\n", 406 | " HA += q[i]*q[j] \n", 407 | " \n", 408 | "HB = 0\n", 409 | "for i in range(N):\n", 410 | " HB += -q[i]\n", 411 | "\n", 412 | "\n", 413 | "#式をつなげる\n", 414 | "H = HA + HB\n" 415 | ] 416 | } 417 | ], 418 | "metadata": { 419 | "kernelspec": { 420 | "display_name": "Python 3 (ipykernel)", 421 | "language": "python", 422 | "name": "python3" 423 | }, 424 | "language_info": { 425 | "codemirror_mode": { 426 | "name": "ipython", 427 | "version": 3 428 | }, 429 | "file_extension": ".py", 430 | "mimetype": "text/x-python", 431 | "name": "python", 432 | "nbconvert_exporter": "python", 433 | "pygments_lexer": "ipython3", 434 | "version": "3.10.10" 435 | } 436 | }, 437 | "nbformat": 4, 438 | "nbformat_minor": 5 439 | } 440 | -------------------------------------------------------------------------------- /tutorial/tutorial08_clustering_vertex_cover.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "825032b6", 6 | "metadata": {}, 7 | "source": [ 8 | "## 組合せ最適化問題\n", 9 | "量子コンピュータで最適化問題を解くには、イジングモデルといわれる物理モデルを利用する。" 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "id": "0e4801e6", 15 | "metadata": {}, 16 | "source": [ 17 | "## QUBO定式化\n", 18 | "QUBOは問題の答えが小さいほうが正解になるように設定された式です。式の形は、\n", 19 | "\n", 20 | "$$\n", 21 | "QUBO = -\\sum_i h_i q_i -\\sum_{i,j}J_{ij}q_iq_j\n", 22 | "$$\n", 23 | "\n", 24 | "となっている。iとjは点を表し、hはバイアス(局所磁場)、Jは相互作用と呼ばれます。この式ではqは量子ビットを表し0か1を取ります(イジングの場合は+1か-1)。\n", 25 | "私たちはhとJを問題として設定し、qの値を求めます。" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "id": "0d401f7c", 31 | "metadata": {}, 32 | "source": [ 33 | "## 問題設定の仕方\n", 34 | "問題の設定の仕方は、グラフ問題というものに問題を落とすことで計算できますが、いくつか問題を解くことでコツをつかめます。\n", 35 | "\n", 36 | "主に問題のコスト関数は二種類の式を考える必要があります。\n", 37 | "\n", 38 | "1.小さくしたいコスト関数 \n", 39 | "2.満たすべき条件(制約条件)\n", 40 | "\n", 41 | "この二つを別々に設計し、つなげることで実装できます。片方しかない式もあります。" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": 1, 47 | "id": "9aeca88c", 48 | "metadata": { 49 | "tags": [] 50 | }, 51 | "outputs": [], 52 | "source": [ 53 | "!pip install --quiet matplotlib" 54 | ] 55 | }, 56 | { 57 | "cell_type": "markdown", 58 | "id": "4c86325f", 59 | "metadata": {}, 60 | "source": [ 61 | "## クラスター分割問題\n", 62 | "与えられたデータを$n$個のデータに分割する問題. \n", 63 | "\n", 64 | "### イジング式\n", 65 | "データを2個のクラスターに分割する場合を考える. \n", 66 | "スピン変数を$q_i=+1$のときクラスター1に属しているとして, $q_i=-1$のときにクラスター2に属しているとする. \n", 67 | "\n", 68 | "$i$番目と$j$番目のデータの距離を$d_{i,j}$とするときに, 距離を最小化するようにイジング式を作ります. \n", 69 | "\n", 70 | "$$\n", 71 | "H = \\sum^N_{i,j} d_{i,j} q_i q_j\n", 72 | "$$\n", 73 | "\n", 74 | "### 問題設定\n", 75 | "下記のように10個のデータを考えます. " 76 | ] 77 | }, 78 | { 79 | "cell_type": "code", 80 | "execution_count": 1, 81 | "id": "03be69ae", 82 | "metadata": {}, 83 | "outputs": [ 84 | { 85 | "name": "stdout", 86 | "output_type": "stream", 87 | "text": [ 88 | "Sample = {'q[0]': 0, 'q[1]': 0, 'q[2]': 0, 'q[3]': 0, 'q[4]': 1, 'q[5]': 1, 'q[6]': 0, 'q[7]': 0, 'q[8]': 1, 'q[9]': 0}\n", 89 | "Cost = -101.64913151974383\n" 90 | ] 91 | }, 92 | { 93 | "data": { 94 | "image/png": "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\n", 95 | "text/plain": [ 96 | "
" 97 | ] 98 | }, 99 | "metadata": { 100 | "needs_background": "light" 101 | }, 102 | "output_type": "display_data" 103 | } 104 | ], 105 | "source": [ 106 | "import numpy as np\n", 107 | "from matplotlib import pyplot as plt\n", 108 | "from tytan import *\n", 109 | "import sympy as sym\n", 110 | "\n", 111 | "\n", 112 | "\n", 113 | "x=np.array([0.456418,1.902223,0.512496,1.049233,-1.338122,-1.582395,1.433849,0.574857,-1.388644,1.120863])\n", 114 | "y=np.array([0.681894,0.598139,0.493532,0.485759,-1.001241,-2.094026,0.346436,1.007253,-1.406806,0.97977])\n", 115 | "\n", 116 | "plt.scatter(x, y)\n", 117 | "\n", 118 | "#今回は10量子ビット\n", 119 | "N = 10\n", 120 | "#q = Array.create('q', shape=(N), vartype='SPIN')\n", 121 | "\n", 122 | "def dist(i,j):\n", 123 | " z=np.sqrt((x[i]-x[j])**2+(y[i]-y[j])**2)\n", 124 | " return z\n", 125 | " \n", 126 | "#式A\n", 127 | "HA=0\n", 128 | "for i in range(N):\n", 129 | " for j in range(N):\n", 130 | " HA += dist(i,j)*q[i]*q[j]\n", 131 | "\n", 132 | "#式をつなげる\n", 133 | "H=HA" 134 | ] 135 | }, 136 | { 137 | "cell_type": "code", 138 | "execution_count": 2, 139 | "id": "95cd2c51", 140 | "metadata": { 141 | "scrolled": true 142 | }, 143 | "outputs": [ 144 | { 145 | "data": { 146 | "image/png": "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\n", 147 | "text/plain": [ 148 | "
" 149 | ] 150 | }, 151 | "metadata": { 152 | "needs_background": "light" 153 | }, 154 | "output_type": "display_data" 155 | } 156 | ], 157 | "source": [ 158 | "x=np.array([0.456418,1.902223,0.512496,1.049233,-1.338122,-1.582395,1.433849,0.574857,-1.388644,1.120863])\n", 159 | "y=np.array([0.681894,0.598139,0.493532,0.485759,-1.001241,-2.094026,0.346436,1.007253,-1.406806,0.97977])\n", 160 | "c=np.array([0,0,0,0,1,1,0,0,1,0])\n", 161 | "for i in range(N):\n", 162 | " if c[i]==0:\n", 163 | " plt.scatter(x[i], y[i],c=\"red\")\n", 164 | " else:\n", 165 | " plt.scatter(x[i], y[i],c=\"blue\")" 166 | ] 167 | }, 168 | { 169 | "cell_type": "markdown", 170 | "id": "01a7ea8b", 171 | "metadata": {}, 172 | "source": [ 173 | "## Nクラスター分割問題\n", 174 | "データ数$n$、クラスタ数$k$として、$n*k$の量子ビット数が必要。\n", 175 | "データ数に対してクラスタ数だけコピーを作る。\n", 176 | "\n", 177 | "### QUBO式\n", 178 | "2値クラスターでは, $+1$と$-1$のイジングモデルを用いたが, $N$クラスターでは$0,1$のQUBO関数を用いる. \n", 179 | "バイナリ変数$q_{i,l}$は$i$番目のデータが$l$番目のクラスターのとき$1$, それで無ければ$0$\n", 180 | "コスト関数は, 各クラスター毎に距離を計算すればよい. \n", 181 | "異なるクラスター同士は考慮しなくてよい. \n", 182 | "\n", 183 | "$$\n", 184 | "Cost = \\sum_l^k\\sum_{ij}^n d_{ij} q_{i,l} q_{j,l}\\ \\ \\ \\ (q_i \\in \\{0, 1\\})\n", 185 | "$$\n", 186 | "\n", 187 | "制約として, データはただ$1$つのクラスターに属する条件\n", 188 | "$$\n", 189 | "Constraint = \\sum_i^n(\\sum_{l}^k q_{i,l} - 1)^2\n", 190 | "$$\n", 191 | "\n", 192 | "$0$番目のデータが4クラスターのどれに分類されるか調べるときに\n", 193 | "$$\n", 194 | "q_{0,0}+q_{0,1}+q_{0,2}+q_{0,3}\n", 195 | "$$\n", 196 | "のどれか1つが1になればよいので\n", 197 | "$$\n", 198 | "(q_{0,0}+q_{0,1}+q_{0,2}+q_{0,3}-1)^2\n", 199 | "$$\n", 200 | "を制約式とする. " 201 | ] 202 | }, 203 | { 204 | "cell_type": "code", 205 | "execution_count": 4, 206 | "id": "f61168f7", 207 | "metadata": {}, 208 | "outputs": [ 209 | { 210 | "name": "stdout", 211 | "output_type": "stream", 212 | "text": [ 213 | "Cost = 3087.519864936692\n", 214 | "Break = {}\n" 215 | ] 216 | }, 217 | { 218 | "data": { 219 | "image/png": "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\n", 220 | "text/plain": [ 221 | "
" 222 | ] 223 | }, 224 | "metadata": { 225 | "needs_background": "light" 226 | }, 227 | "output_type": "display_data" 228 | } 229 | ], 230 | "source": [ 231 | "import numpy as np\n", 232 | "from matplotlib import pyplot as plt\n", 233 | "\n", 234 | "np.random.seed(0)\n", 235 | "\n", 236 | "n_node = 100\n", 237 | "n_cluster = 4\n", 238 | "\n", 239 | "#color = [np.random.randint(0,4) for _ in range(n_node)]\n", 240 | "\n", 241 | "x=np.array([1.46810698,3.3613398,2.80133699,-1.46591682,1.42513263,-0.22703581,-0.15482828,0.61589775,0.21606536,2.18141026,1.14155659,0.18251252,0.66579485,0.50051149,2.24111861,-0.3077374,0.46960155,-1.28114361,-3.82948472,0.98042789,1.2966543,-1.11324753,3.40463194,-2.18154851,0.06863778,36.67956794,34.31311637,35.6380901,34.95804322,37.21398475,35.97017015,34.45349853,33.98183392,34.46955822,33.88887879,33.98746725,34.80082362,35.92970159,37.68675269,35.25650066,32.41149297,35.24098781,33.71152202,34.69036859,35.7326397,33.74250355,35.57174562,33.51364508,36.52682007,35.51238109,19.51161368,22.51692798,23.10066013,20.01751247,20.61631396,19.92842159,20.24874185,21.08346801,20.26655733,20.43011633,21.38960198,18.47797704,19.62480779,20.82116385,20.33058408,17.78496684,21.01505665,20.16266612,21.72135848,20.13878698,20.6212986,22.55977018,20.96478071,21.13413343,20.10850894,10.97159387,9.96397541,12.19964247,14.32121179,11.65830712,11.95738955,14.02376208,10.63452087,13.30075348,12.14712535,7.31498147,8.44452693,11.63022961,10.55277639,11.39540328,12.09689889,11.34210563,7.95721413,12.4492856,10.7196173,10.29151275,13.90498381,13.21601063,10.87266484,11.64154486])\n", 242 | "y=np.array([37.71922422,37.18862555,36.01515895,37.83080162,39.36101891,39.22290486,38.34364692,36.46073183,38.7162882,39.93904734,36.90281265,35.59189662,39.48421426,38.16622192,37.42860288,38.17243876,38.51796896,35.39756185,40.48752666,41.44965729,37.29329711,39.89407323,36.24422683,39.5986838,36.95009392,11.12367068,14.38787613,11.64282076,15.7655373,15.28826086,10.83169663,13.56574092,12.89416416,13.90623956,13.7082235,14.22987594,14.36127943,12.12126569,14.40633826,12.61808786,14.46039807,13.31092416,14.64946296,14.40984547,13.9095835,13.00264126,11.51475979,15.80859112,12.63838961,13.08001736,2.84145481,1.84512589,3.80887379,1.98850101,3.04774584,2.04623088,4.01464994,3.86488622,2.68755187,3.59401007,1.36040774,0.76311361,3.65908755,3.25001024,3.95254716,6.57471716,4.41671923,1.63076666,4.67552443,1.02613888,2.30762309,2.89763759,5.57001408,1.88286777,1.76034219,27.54358061,28.14150143,25.77114421,25.14912361,26.2936312,25.35694167,27.56706517,29.57197334,28.37493631,28.07035669,26.45163544,28.60477852,26.97391112,29.89348328,24.99166511,27.50195441,27.5558494,24.67245887,27.72474568,28.58846208,28.36245221,28.15590387,26.75564322,28.73913909,28.13516919])\n", 243 | "\n", 244 | "# 散布図を描画\n", 245 | "#plt.scatter(x,y,c=color)\n", 246 | "\n", 247 | "N=100\n", 248 | "K=4\n", 249 | "#100*4量子ビット\n", 250 | "#q = Array.create('q', shape=N*K, vartype='BINARY')\n", 251 | "\n", 252 | "#距離\n", 253 | "def dist(i,j):\n", 254 | " z=np.sqrt((x[i]-x[j])**2+(y[i]-y[j])**2)\n", 255 | " return z\n", 256 | " \n", 257 | "#式A\n", 258 | "HA=0\n", 259 | "for l in range(K):\n", 260 | " for i in range(N-1):\n", 261 | " for j in range(i+1,N):\n", 262 | " HA += dist(i,j)*q[l*N+i]*q[l*N+j]\n", 263 | "\n", 264 | "HB=0\n", 265 | "for i in range(N):\n", 266 | " tmp=0\n", 267 | " for l in range(K):\n", 268 | " tmp += q[i+N*l]\n", 269 | " HB += (tmp -1)**2\n", 270 | "\n", 271 | "#式をつなげる\n", 272 | "H = HA + 140*HB\n", 273 | "\n", 274 | "#data = sampleset.record[0][0] # 結果を1次元配列に保存\n", 275 | "data = sampleset.record[0][0]\n", 276 | "np.set_printoptions(threshold=np.inf)\n", 277 | "#print(data)\n", 278 | "\n", 279 | "data=np.array([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])\n", 280 | "\n", 281 | "cls = np.zeros(N)\n", 282 | "for l in range(K):\n", 283 | " for i in range(N):\n", 284 | " if data[i+N*l]==1:\n", 285 | " cls[i]=l\n", 286 | "#print(data)\n", 287 | "#print(cls)\n", 288 | "for i in range(N):\n", 289 | " if cls[i]==0:\n", 290 | " plt.scatter(x[i], y[i],c=\"red\")\n", 291 | " elif cls[i]==1:\n", 292 | " plt.scatter(x[i], y[i],c=\"blue\")\n", 293 | " elif cls[i]==2:\n", 294 | " plt.scatter(x[i], y[i],c=\"yellow\")\n", 295 | " else:\n", 296 | " plt.scatter(x[i], y[i],c=\"green\")\n", 297 | " " 298 | ] 299 | }, 300 | { 301 | "cell_type": "markdown", 302 | "id": "c91bf25e", 303 | "metadata": {}, 304 | "source": [ 305 | "## vertex cover(頂点被覆問題)\n", 306 | "\n", 307 | "あるグラフ$G=(V,E)$について、すべての頂点とつながる最小の頂点集合$V'$を求める問題 \n" 308 | ] 309 | }, 310 | { 311 | "cell_type": "markdown", 312 | "id": "bcb4ef0f", 313 | "metadata": {}, 314 | "source": [ 315 | "## QUBO式\n", 316 | "\n", 317 | "ノード$i$が集合$V'$含まれるときは$x_i=1$とする. \n", 318 | "QUBO最適化関数は、\n", 319 | "\n", 320 | "$$\n", 321 | "H = H _ A + H _ B\n", 322 | "$$\n", 323 | "\n", 324 | "\n", 325 | "ノード$v$とノード$u$が接続されているときに、2つのノード間のうちいずれか1つは1になる条件。(2つとも1になるのも含む)\n", 326 | "\n", 327 | "$$\n", 328 | "H_{A}=A\\sum_{u,v \\in E} (1-x_u) (1-x_v)\n", 329 | "$$\n", 330 | "\n", 331 | "$V'$の要素数を最小化する条件\n", 332 | "\n", 333 | "$$\n", 334 | "H_B = B \\sum_{v \\in V} x_v\n", 335 | "$$\n" 336 | ] 337 | }, 338 | { 339 | "cell_type": "markdown", 340 | "id": "53f45970", 341 | "metadata": {}, 342 | "source": [ 343 | "## 例題\n", 344 | "$V={1,2,3,4,5}$ \n", 345 | "$E={(0,1),(0,3),(1,2),(2,3),(3,4)}$ \n", 346 | "のグラフ$G=(V,E)$\n", 347 | "について、最小被覆頂点集合$V'$をもとめる。" 348 | ] 349 | }, 350 | { 351 | "cell_type": "code", 352 | "execution_count": 13, 353 | "id": "081c2962", 354 | "metadata": {}, 355 | "outputs": [ 356 | { 357 | "data": { 358 | "image/png": "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\n", 359 | "text/plain": [ 360 | "
" 361 | ] 362 | }, 363 | "metadata": {}, 364 | "output_type": "display_data" 365 | } 366 | ], 367 | "source": [ 368 | "import networkx as nx\n", 369 | "import matplotlib.pyplot as plt\n", 370 | "\n", 371 | "options = {'node_color': '#efefef','node_size': 1200,'with_labels':'True'}\n", 372 | "\n", 373 | "N = 5\n", 374 | "\n", 375 | "G = nx.Graph()\n", 376 | "G.add_nodes_from(nx.path_graph(N))\n", 377 | "G.add_edges_from([(0,1),(0,3),(1,2),(2,3),(3,4)])\n", 378 | "nx.draw(G, **options)\n", 379 | "#隣接行列\n", 380 | "A = np.array(nx.to_numpy_matrix(G))" 381 | ] 382 | }, 383 | { 384 | "cell_type": "code", 385 | "execution_count": 12, 386 | "id": "55fa2b17", 387 | "metadata": {}, 388 | "outputs": [ 389 | { 390 | "name": "stdout", 391 | "output_type": "stream", 392 | "text": [ 393 | "Sample = {'q[0]': 0, 'q[1]': 1, 'q[2]': 0, 'q[3]': 1, 'q[4]': 0}\n", 394 | "Cost = 2.0\n", 395 | "Break = {}\n" 396 | ] 397 | } 398 | ], 399 | "source": [ 400 | "import numpy as np\n", 401 | "\n", 402 | "#量子ビット\n", 403 | "N=5 \n", 404 | "#q = Array.create('q', shape=N, vartype='BINARY')\n", 405 | "\n", 406 | "#集合V\n", 407 | "V=np.array([0,1, 2, 3, 4])\n", 408 | "\n", 409 | "#QUBO式\n", 410 | "HA = 0\n", 411 | "for v in range(N):\n", 412 | " for u in range(N):\n", 413 | " if A[u,v]==1:\n", 414 | " HA += (1-q[u])*(1-q[v])\n", 415 | " \n", 416 | "HB = 0\n", 417 | "for v in range(N):\n", 418 | " HB+=q[v]\n", 419 | "\n", 420 | "#式をつなげる\n", 421 | "H = 2*HA + HB" 422 | ] 423 | }, 424 | { 425 | "cell_type": "markdown", 426 | "id": "cbe42f2b", 427 | "metadata": {}, 428 | "source": [ 429 | "結果を確認すると、$S_0$と$S_1$を選択すると、全体集合の要素数をカバーできることが分かる。" 430 | ] 431 | } 432 | ], 433 | "metadata": { 434 | "kernelspec": { 435 | "display_name": "Python 3 (ipykernel)", 436 | "language": "python", 437 | "name": "python3" 438 | }, 439 | "language_info": { 440 | "codemirror_mode": { 441 | "name": "ipython", 442 | "version": 3 443 | }, 444 | "file_extension": ".py", 445 | "mimetype": "text/x-python", 446 | "name": "python", 447 | "nbconvert_exporter": "python", 448 | "pygments_lexer": "ipython3", 449 | "version": "3.10.10" 450 | } 451 | }, 452 | "nbformat": 4, 453 | "nbformat_minor": 5 454 | } 455 | -------------------------------------------------------------------------------- /tutorial/tutorial09_trafficflow_optimization.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "df647b57", 6 | "metadata": {}, 7 | "source": [ 8 | "## 組合せ最適化問題\n", 9 | "量子コンピュータで最適化問題を解くには、イジングモデルといわれる物理モデルを利用する。" 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "id": "f6e338bb", 15 | "metadata": {}, 16 | "source": [ 17 | "## QUBO定式化\n", 18 | "QUBOは問題の答えが小さいほうが正解になるように設定された式です。式の形は、\n", 19 | "\n", 20 | "$$\n", 21 | "QUBO = -\\sum_i h_i q_i -\\sum_{i,j}J_{ij}q_iq_j\n", 22 | "$$\n", 23 | "\n", 24 | "となっている。iとjは点を表し、hはバイアス(局所磁場)、Jは相互作用と呼ばれます。この式ではqは量子ビットを表し0か1を取ります(イジングの場合は+1か-1)。\n", 25 | "私たちはhとJを問題として設定し、qの値を求めます。" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "id": "604397aa", 31 | "metadata": {}, 32 | "source": [ 33 | "## 問題設定の仕方\n", 34 | "問題の設定の仕方は、グラフ問題というものに問題を落とすことで計算できますが、いくつか問題を解くことでコツをつかめます。\n", 35 | "\n", 36 | "主に問題のコスト関数は二種類の式を考える必要があります。\n", 37 | "\n", 38 | "1.小さくしたいコスト関数 \n", 39 | "2.満たすべき条件(制約条件)\n", 40 | "\n", 41 | "この二つを別々に設計し、つなげることで実装できます。片方しかない式もあります。" 42 | ] 43 | }, 44 | { 45 | "cell_type": "markdown", 46 | "id": "c58f0af2", 47 | "metadata": {}, 48 | "source": [ 49 | "## 使うツール\n", 50 | "\n", 51 | "networkx(ネットワークグラフを書く) \n", 52 | "matplotlib(各種のグラフを書く) \n", 53 | "numpy(数値ライブラリ) " 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": 1, 59 | "id": "a71a10e3", 60 | "metadata": { 61 | "scrolled": true, 62 | "tags": [] 63 | }, 64 | "outputs": [], 65 | "source": [ 66 | "!pip install --quiet networkx matplotlib" 67 | ] 68 | }, 69 | { 70 | "cell_type": "markdown", 71 | "id": "842353de", 72 | "metadata": {}, 73 | "source": [ 74 | "## 交通経路最適化問題\n", 75 | "交通渋滞の緩和のために, 経路が集中しないように車の経路を選択して, 渋滞が起きないように最適化する. \n", 76 | "\n" 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": 3, 82 | "id": "0672f168-d7dd-4846-a964-9037dcc6ce31", 83 | "metadata": { 84 | "tags": [] 85 | }, 86 | "outputs": [ 87 | { 88 | "data": { 89 | "image/png": "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", 90 | "text/plain": [ 91 | "
" 92 | ] 93 | }, 94 | "metadata": {}, 95 | "output_type": "display_data" 96 | } 97 | ], 98 | "source": [ 99 | "import networkx as nx\n", 100 | "import matplotlib.pyplot as plt\n", 101 | "\n", 102 | "G = nx.Graph()\n", 103 | "G.add_nodes_from([i for i in range(9)])\n", 104 | "G.add_edges_from([(0,1,),(1,2),(0,3),(1,4),(2,5),(3,4),(4,5),(3,6),(4,7),(5,8),(6,7),(7,8)])\n", 105 | "options = {'node_size': 1200,'with_labels':'True'}\n", 106 | "pos = nx.spring_layout(G)\n", 107 | "nx.draw(G, pos, **options, node_color='#efefef')\n", 108 | "\n", 109 | "edge_labels={(0,1):'s0',(1,2):'s1',(0,3):'s2',(1,4):'s3',(2,5):'s4',(3,4):'s5',(4,5):'s6',(3,6):'s7',(4,7):'s8',(5,8):'s9',(6,7):'s10',(7,8):'s11'}\n", 110 | "nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels)\n", 111 | "plt.show()" 112 | ] 113 | }, 114 | { 115 | "cell_type": "markdown", 116 | "id": "cc9f64d2", 117 | "metadata": {}, 118 | "source": [ 119 | "### QUBO式\n", 120 | "$i$番目の車が$j$番目の経路を通るときに$1$をとるバイナリ変数を$q_{i,j}$\n", 121 | "とする. \n", 122 | "\n", 123 | "経路は道路をまとめた集合$S$とする. \n", 124 | "$$\n", 125 | "S=[s_0,s_1,s_2,s_3,s_4,s_5,s_6,s_7,s_8,s_9,s_{10},s_{11}]\n", 126 | "$$\n", 127 | "\n", 128 | "集合$S$を用いて経路を作成する. \n", 129 | "\n", 130 | "最小化したいQUBOコスト関数は, \n", 131 | "\n", 132 | "$$\n", 133 | "QUBO=\\sum_{s} (\\sum_{s \\in S_{i,j}} q_{i,j})^2\n", 134 | "$$\n", 135 | "\n", 136 | "$\\sum_{s \\in S_{i,j}} q_{i,j}$は車$i$が経路$j$を通過するときに地点$s$を通る経路について和をとります. \n", 137 | "\n", 138 | "\n", 139 | "道路$s$を通るすべての車の台数を表しており, $s$について和をとるQUBO式により, 地点$s$を通過する車の台数を最小化しています. \n", 140 | "\n", 141 | "\n", 142 | "たとえば, 下経路があるときに, \n", 143 | "\n", 144 | "$経路1 : s_0,s_3,s_8,s_{11}$ \n", 145 | "$経路2 : s_2,s_7,s_{10},s_{11}$ \n", 146 | "$経路3 : s_0,s_1,s_4,s_9$ \n", 147 | "\n", 148 | "$s_0$が含まれるのは経路1と3なので, $s_0$のみのコスト関数は, \n", 149 | "$$\n", 150 | "(q_{1,1}+q_{2,1}+q_{1,3}+q_{2,3})^2\n", 151 | "$$\n", 152 | "\n", 153 | "これをすべての道路についての和を取ることで, 道路を被らないように経路選択できる. \n", 154 | "\n", 155 | "制約式は, 各車は一つの経路のみ通る事ができる条件. \n", 156 | "$$\n", 157 | "const=\\sum_i (\\sum_j q_{i,j} -1)^2\n", 158 | "$$" 159 | ] 160 | }, 161 | { 162 | "cell_type": "markdown", 163 | "id": "23cda47c", 164 | "metadata": {}, 165 | "source": [ 166 | "### 問題設定\n", 167 | "\n", 168 | "地点0から地点8までを車が移動するときに, 経路がなるべく被らないように経路分散を計る. \n", 169 | "車は2台あり, それぞれ下の経路をとる可能性がある. \n", 170 | "\n", 171 | "経路1 : s0,s3,s8,s11 \n", 172 | "経路2 : s2,s7,s10,s11 \n", 173 | "経路3 : s0,s1,s4,s9 " 174 | ] 175 | }, 176 | { 177 | "cell_type": "code", 178 | "execution_count": 51, 179 | "id": "3a3bd51a", 180 | "metadata": {}, 181 | "outputs": [ 182 | { 183 | "name": "stdout", 184 | "output_type": "stream", 185 | "text": [ 186 | " q[0][0] q[0][1] q[0][2] q[1][0] q[1][1] q[1][2] energy num_oc.\n", 187 | "2 0 1 0 0 0 1 8.0 1\n", 188 | "3 0 1 0 0 0 1 8.0 1\n", 189 | "4 0 1 0 0 0 1 8.0 1\n", 190 | "6 0 1 0 0 0 1 8.0 1\n", 191 | "7 0 0 1 0 1 0 8.0 1\n", 192 | "8 0 1 0 0 0 1 8.0 1\n", 193 | "9 0 1 0 0 0 1 8.0 1\n", 194 | "0 1 0 0 0 1 0 10.0 1\n", 195 | "1 0 1 0 1 0 0 10.0 1\n", 196 | "5 1 0 0 0 0 1 10.0 1\n", 197 | "['BINARY', 10 rows, 10 samples, 6 variables]\n", 198 | "Sample = {'q[0][0]': 0, 'q[0][1]': 0, 'q[0][2]': 1, 'q[1][0]': 0, 'q[1][1]': 1, 'q[1][2]': 0}\n", 199 | "Cost = 8.0\n", 200 | "Break = {}\n" 201 | ] 202 | } 203 | ], 204 | "source": [ 205 | "\n", 206 | "import numpy as np\n", 207 | "\n", 208 | "N=2\n", 209 | "W=3\n", 210 | "#q = Array.create('q', shape=(N,W), vartype='BINARY')\n", 211 | "\n", 212 | "#通過地点\n", 213 | "s=np.array([[0,3,8,11],[2,7,10,11],[0,1,4,9]])\n", 214 | "\n", 215 | "S=12#道路数\n", 216 | "\n", 217 | "\n", 218 | "#式A\n", 219 | "HA=0\n", 220 | "for k in range(S):#道路\n", 221 | " tmp=0\n", 222 | " for j in range(W):#経路\n", 223 | " for i in range(N):#車\n", 224 | " for l in range(4):\n", 225 | " if s[j,l]==k:\n", 226 | " tmp += q[i,j]\n", 227 | " HA += tmp**2\n", 228 | "\n", 229 | "\n", 230 | "#式C\n", 231 | "HC=0\n", 232 | "for i in range(N):#車\n", 233 | " tmp=0\n", 234 | " for j in range(W):#経路\n", 235 | " tmp+=q[i,j]\n", 236 | " HC += (tmp-1)**2\n", 237 | "\n", 238 | "\n", 239 | "#式をつなげる\n", 240 | "H = HA + 10*HC\n" 241 | ] 242 | } 243 | ], 244 | "metadata": { 245 | "kernelspec": { 246 | "display_name": "Python 3 (ipykernel)", 247 | "language": "python", 248 | "name": "python3" 249 | }, 250 | "language_info": { 251 | "codemirror_mode": { 252 | "name": "ipython", 253 | "version": 3 254 | }, 255 | "file_extension": ".py", 256 | "mimetype": "text/x-python", 257 | "name": "python", 258 | "nbconvert_exporter": "python", 259 | "pygments_lexer": "ipython3", 260 | "version": "3.10.10" 261 | } 262 | }, 263 | "nbformat": 4, 264 | "nbformat_minor": 5 265 | } 266 | -------------------------------------------------------------------------------- /tutorial/tutorial10_liner_reg.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "e9fb259e", 6 | "metadata": {}, 7 | "source": [ 8 | "## 組合せ最適化問題\n", 9 | "量子コンピュータで最適化問題を解くには、イジングモデルといわれる物理モデルを利用する。" 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "id": "e9bdfeac", 15 | "metadata": {}, 16 | "source": [ 17 | "## QUBO定式化\n", 18 | "QUBOは問題の答えが小さいほうが正解になるように設定された式です。式の形は、\n", 19 | "\n", 20 | "$$\n", 21 | "QUBO = -\\sum_i h_i q_i -\\sum_{i,j}J_{ij}q_iq_j\n", 22 | "$$\n", 23 | "\n", 24 | "となっている。iとjは点を表し、hはバイアス(局所磁場)、Jは相互作用と呼ばれます。この式ではqは量子ビットを表し0か1を取ります(イジングの場合は+1か-1)。\n", 25 | "私たちはhとJを問題として設定し、qの値を求めます。" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "id": "c94dc739", 31 | "metadata": {}, 32 | "source": [ 33 | "## 問題設定の仕方\n", 34 | "問題の設定の仕方は、グラフ問題というものに問題を落とすことで計算できますが、いくつか問題を解くことでコツをつかめます。\n", 35 | "\n", 36 | "主に問題のコスト関数は二種類の式を考える必要があります。\n", 37 | "\n", 38 | "1.小さくしたいコスト関数 \n", 39 | "2.満たすべき条件(制約条件)\n", 40 | "\n", 41 | "この二つを別々に設計し、つなげることで実装できます。片方しかない式もあります。" 42 | ] 43 | }, 44 | { 45 | "cell_type": "markdown", 46 | "id": "246ac169", 47 | "metadata": {}, 48 | "source": [ 49 | "## 使うツール\n", 50 | "\n", 51 | "networkx(ネットワークグラフを書く) \n", 52 | "matplotlib(各種のグラフを書く) \n", 53 | "numpy(数値ライブラリ)" 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": 1, 59 | "id": "87d5196a", 60 | "metadata": { 61 | "scrolled": true, 62 | "tags": [] 63 | }, 64 | "outputs": [], 65 | "source": [ 66 | "!pip install --quiet networkx matplotlib" 67 | ] 68 | }, 69 | { 70 | "cell_type": "markdown", 71 | "id": "0820e81a", 72 | "metadata": {}, 73 | "source": [ 74 | "## 線形回帰\n", 75 | "2次元のデータの組み合わせ$x_i,y_i(i=1,2,3,...,N)$があるときに, \n", 76 | "データをよくフィッティングする直線の方程式\n", 77 | "$$\n", 78 | "y=ax+b\n", 79 | "$$\n", 80 | "を求める問題\n", 81 | "$i$番目のデータを当てはめると, \n", 82 | "$$\n", 83 | "y_i = ax_i+b\n", 84 | "$$\n", 85 | "の式を得る. 右辺を移行して, 2乗すると, \n", 86 | "$$\n", 87 | "\\lbrace y_i-(ax_i+b)\\rbrace^2=0\n", 88 | "$$\n", 89 | "$x_i, y_i$はデータなので上の式は0にならないが, 上式が最小になるような$a,b$を求める. \n", 90 | "\n", 91 | "$$\n", 92 | "\\sum_i \\lbrace y_i-(ax_i+b)\\rbrace^2\n", 93 | "$$\n", 94 | "\n", 95 | "$a,b$は実数なので, QUBO式にするために精度ベクトル\n", 96 | "$$\n", 97 | "p=(-1,-0.5,0.5,1)\n", 98 | "$$\n", 99 | "を用意して実数を作る. \n", 100 | "$$\n", 101 | "a=\\sum p_j a_j\n", 102 | "$$\n", 103 | "\n", 104 | "$$\n", 105 | "b=\\sum p_j b_j\n", 106 | "$$\n", 107 | "\n", 108 | "以上より, QUBO式は, \n", 109 | "最小化したいコスト関数\n", 110 | "$$\n", 111 | "COST=\\sum_i \\lbrace y_i-(ax_i+b)\\rbrace^2\n", 112 | "$$\n", 113 | "$$\n", 114 | "=\\sum_i \\lbrace y_i-(\\sum_j p_j a_j x_i+\\sum_j p_j b_j)\\rbrace^2\n", 115 | "$$\n", 116 | "$a_j,b_j$のバイナリ変数を求める. " 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "execution_count": 13, 122 | "id": "df8db8d5", 123 | "metadata": {}, 124 | "outputs": [ 125 | { 126 | "data": { 127 | "image/png": "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\n", 128 | "text/plain": [ 129 | "
" 130 | ] 131 | }, 132 | "metadata": { 133 | "needs_background": "light" 134 | }, 135 | "output_type": "display_data" 136 | } 137 | ], 138 | "source": [ 139 | "import matplotlib.pyplot as plt\n", 140 | "\n", 141 | "x = np.array([1,2,4,6,7])\n", 142 | "y = np.array([1,3,3,5,4])\n", 143 | "\n", 144 | "plt.scatter(x, y)\n", 145 | "plt.show()" 146 | ] 147 | }, 148 | { 149 | "cell_type": "code", 150 | "execution_count": 51, 151 | "id": "f18bd844", 152 | "metadata": {}, 153 | "outputs": [ 154 | { 155 | "name": "stdout", 156 | "output_type": "stream", 157 | "text": [ 158 | " q[0] q[1] q[2] q[3] q[4] q[5] q[6] q[7] energy num_oc.\n", 159 | "0 1 0 1 1 0 0 0 1 -0.0 1\n", 160 | "1 0 0 1 0 0 1 1 1 -0.0 1\n", 161 | "2 0 0 1 0 0 1 1 1 -0.0 1\n", 162 | "3 0 0 1 0 0 0 0 1 -0.0 1\n", 163 | "4 0 0 1 0 0 1 1 1 -0.0 1\n", 164 | "5 1 0 1 1 0 1 1 1 -0.0 1\n", 165 | "6 0 1 0 1 0 1 1 1 -0.0 1\n", 166 | "8 0 0 1 0 0 1 1 1 -0.0 1\n", 167 | "9 1 0 1 1 0 0 0 1 -0.0 1\n", 168 | "7 0 1 0 1 0 0 0 1 0.0 1\n", 169 | "['BINARY', 10 rows, 10 samples, 8 variables]\n" 170 | ] 171 | } 172 | ], 173 | "source": [ 174 | "import numpy as np\n", 175 | "from matplotlib import pyplot as plt\n", 176 | "\n", 177 | "N=8\n", 178 | "#量子ビット\n", 179 | "#q = Array.create('q', shape=N, vartype='BINARY')\n", 180 | "\n", 181 | "p=np.array([-1,-0.5,0.5,1.0])\n", 182 | "\n", 183 | "HA=0\n", 184 | "for i in range(5):\n", 185 | " a=0\n", 186 | " b=0\n", 187 | " for j in range(4):\n", 188 | " a += p[j]*q[j]*x[i]\n", 189 | " b += p[j]*q[j+4]\n", 190 | " HA += (y[i]-a-b)**2\n", 191 | "\n", 192 | "H = HA" 193 | ] 194 | }, 195 | { 196 | "cell_type": "code", 197 | "execution_count": 49, 198 | "id": "ecf79444", 199 | "metadata": {}, 200 | "outputs": [ 201 | { 202 | "name": "stdout", 203 | "output_type": "stream", 204 | "text": [ 205 | "0.5 1.0\n" 206 | ] 207 | } 208 | ], 209 | "source": [ 210 | "a=np.array([1,0,1,1])\n", 211 | "b=np.array([0,0,0,1])\n", 212 | "\n", 213 | "A=0\n", 214 | "B=0\n", 215 | "for i in range(4):\n", 216 | " A+=p[i]*a[i]\n", 217 | " B+=p[j]*b[i]\n", 218 | "print(A,B)" 219 | ] 220 | }, 221 | { 222 | "cell_type": "code", 223 | "execution_count": 45, 224 | "id": "79771264", 225 | "metadata": {}, 226 | "outputs": [ 227 | { 228 | "data": { 229 | "image/png": "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\n", 230 | "text/plain": [ 231 | "
" 232 | ] 233 | }, 234 | "metadata": { 235 | "needs_background": "light" 236 | }, 237 | "output_type": "display_data" 238 | } 239 | ], 240 | "source": [ 241 | "import matplotlib.pyplot as plt\n", 242 | "\n", 243 | "x = np.array([1,2,4,6,7])\n", 244 | "y = np.array([1,3,3,5,4])\n", 245 | "\n", 246 | "plt.scatter(x, y)\n", 247 | "\n", 248 | "x = np.arange(0, 10, 0.1)\n", 249 | "y = x * 0.5 + 1.0\n", 250 | "plt.plot(x, y)\n", 251 | "plt.show()" 252 | ] 253 | }, 254 | { 255 | "cell_type": "code", 256 | "execution_count": null, 257 | "id": "07e58448", 258 | "metadata": {}, 259 | "outputs": [], 260 | "source": [] 261 | } 262 | ], 263 | "metadata": { 264 | "kernelspec": { 265 | "display_name": "Python 3 (ipykernel)", 266 | "language": "python", 267 | "name": "python3" 268 | }, 269 | "language_info": { 270 | "codemirror_mode": { 271 | "name": "ipython", 272 | "version": 3 273 | }, 274 | "file_extension": ".py", 275 | "mimetype": "text/x-python", 276 | "name": "python", 277 | "nbconvert_exporter": "python", 278 | "pygments_lexer": "ipython3", 279 | "version": "3.10.10" 280 | } 281 | }, 282 | "nbformat": 4, 283 | "nbformat_minor": 5 284 | } 285 | --------------------------------------------------------------------------------