├── README.md ├── problems ├── final │ ├── Final.ipynb │ ├── Final_en.ipynb │ ├── Leader_Board.ipynb │ ├── answer_and_comment_by_judges.ipynb │ ├── answer_and_comment_by_judges_en.ipynb │ ├── fig │ │ ├── 4bit_hyper_cube.png │ │ ├── all_answers.png │ │ ├── hyper_cube_ccx.png │ │ ├── konbini_oracle.png │ │ ├── konbini_oracle_hyper_cube.png │ │ ├── konbini_oracle_simple.png │ │ ├── oracle.png │ │ ├── step2.png │ │ └── white_map.png │ ├── logo2.png │ ├── tokyo_map.png │ └── tokyo_map_pic.png ├── how_to_calculate_quantum_cost.ipynb ├── how_to_calculate_quantum_cost_en.ipynb ├── week0 │ ├── .ipynb_checkpoints │ │ └── week0-checkpoint.ipynb │ ├── fig │ │ ├── composer01.png │ │ ├── composer02.png │ │ ├── composer03.png │ │ ├── composer04.png │ │ ├── composer05.png │ │ ├── histogram01.png │ │ └── histogram02.png │ └── week0.ipynb ├── week1 │ ├── fig │ │ └── adder.png │ ├── week1.ipynb │ └── week1_en.ipynb ├── week2 │ ├── .ipynb_checkpoints │ │ ├── week2-checkpoint.ipynb │ │ └── week2_en-checkpoint.ipynb │ ├── fig │ │ ├── grover_algorithm.png │ │ ├── oracle.png │ │ ├── step0.png │ │ ├── step1.png │ │ ├── step2.png │ │ └── unstructured_search.png │ ├── week2.ipynb │ └── week2_en.ipynb └── week3 │ ├── maxcut.png │ ├── week3.ipynb │ └── week3_en.ipynb ├── qcc_banner.png └── top ten submissions ├── 42Robotics └── readme.txt ├── Costs > 100k ├── optimized_triangle_compare_v10.py └── readme.txt ├── DokiDokiQuantumClub └── readme.txt ├── Gate42 ├── Final challenge write up - Gate42.ipynb └── Gate42_3_final_output.txt ├── IIQ@QIC ├── IIQ@QIC-WriteUp.ipynb ├── fig │ ├── side.png │ └── value_xor.png └── readme.txt ├── QunaVillage ├── QunaVillage_commented.ipynb └── readme.txt ├── Sorin ├── Sorin_6_final.ipynb ├── readme.txt └── tokyo_map_colored.png ├── TheAxiom ├── TheAxiom.ipynb └── readme.txt ├── Tofolli Pizza ├── Toffoli Pizza.ipynb └── readme.txt ├── Whit3z ├── Final Challenge - Whit3z.ipynb └── readme.txt ├── rainy_day_hackers └── readme.txt ├── readme.txt └── rp_cc_sqrt_2 ├── (rp+cc)_sqrt(2)_final.py └── readme.txt /README.md: -------------------------------------------------------------------------------- 1 | ![image of qcchallenge logo](qcc_banner.png) 2 | # Welcome to IBM Quantum Challenge! 3 | [日本語はこちら](#ibm-quantum-challengeへようこそ)
4 | 5 | ### Thank you! We have completed this challenge on Oct 14th, 2019. 6 | 7 | ## Leaderboard 8 | The [Leaderboard](https://github.com/quantum-challenge/2019/blob/master/problems/final/Leader_Board.ipynb) shows the scores and standings of contestants who have submitted their code to the final challenge. 9 | 10 | -------------------------------- 11 | First of all, thank you for signing up for the competition! We are excited to see you take interest in this challenge. 12 | Before you get started, we have a few important notices to remind you. 13 | 14 | ## Registration 15 | If you have not gone through the registration process yet, please make sure to go to the IBM Quantum Challenge [Official Website](https://ibmquantum.angelhack.com/) and complete this [Registration Form](https://angelhack.typeform.com/to/UA44d9) before you get started. You won't be permitted to participate & win prizes without completing the registration! 16 | 17 | The challenge period goes on for four weeks from September 16th to October 14th, 2019. The first three weeks will be a series of learning challenges during which anyone who is eligible may register to join the competition. Registration closes when the final challenge starts on October 7th, 2019. 18 | 19 | Assuming you are all set, let's get started! 20 | 21 | ## Installation 22 | In IBM Quantum Challenge, you will need to code with **Qiskit**. Qiskit is a Python based opensource framework for working with quantum computers at the level of pulses, circuits, and algorithms. Please see the [Qiskit.org](https://qiskit.org) page for more details. 23 | 24 | Qiskit can be installed by using *pip*: 25 | 26 | ``` 27 | $ pip install qiskit 28 | ``` 29 | 30 | Please check out [Install Qiskit](https://qiskit.org/documentation/install.html) or watch this [YouTube video](https://www.youtube.com/watch?v=M4EkW4VwhcI) for a step by step installaion guide. 31 | 32 | ## Challenge Index 33 | The challenge content has been shared with the public on the following dates.
34 | 35 | | Week | Challenge | Scheduled Update Date | 36 | | --- | --- | --- | 37 | | Week 0 |[For Beginners: The atoms of computation](https://github.com/qiskit-community/qiskit-textbook/blob/main/content/ch-states/atoms-computation.ipynb) | Sept 16th, 2019 | 38 | | Week 1 |[Learning Challenge Exercise I](https://github.com/quantum-challenge/2019/blob/master/problems/week1/week1_en.ipynb) | Sept 16th, 2019 | 39 | | Week 2 |[Learning Challenge Exercise II](https://github.com/quantum-challenge/2019/blob/master/problems/week2/week2_en.ipynb) | Sept 23rd, 2019 | 40 | | Week 3 |[Learning Challenge Exercise III](https://github.com/quantum-challenge/2019/blob/master/problems/week3/week3_en.ipynb)| Sept 30th, 2019 | 41 | | Week 4 |[Final Challenge](https://github.com/quantum-challenge/2019/blob/master/problems/final/Final_en.ipynb) | Oct 7th, 2019 | 42 | 43 | ## Sample Solution 44 | Judges share a sample solution [here](https://github.com/quantum-challenge/2019/blob/master/problems/final/answer_and_comment_by_judges_en.ipynb) to the final challenge. Our contestants came up with even more creative and imaginative solutions which was very cool! 45 | 46 | ## Top Team's Submissions 47 | Check out some of the top team's write-ups on how they were able to solve the problem and achieve lower quantum costs [here](https://github.com/quantum-challenge/2019/tree/master/top%20ten%20submissions)! 48 | 49 | -------------------------------- 50 | # IBM Quantum Challengeへようこそ! 51 | 当チャレンジへの参加ありがとうございます。 52 | コンテストの参加にあたって、いくつか重要なお知らせがありますので、必ずご確認ください。 53 | 54 | ### 当コンテストは2019年10月14日に終了しました。 55 | 56 | ## 順位表 57 | [順位表](https://github.com/quantum-challenge/2019/blob/master/problems/final/Leader_Board.ipynb):ファイナルチャレンジにコードを提出した競技者のスコアと順位。 58 | 59 | ## ファイナルチャレンジの解法解説 60 | [チャレンジ解説](https://github.com/quantum-challenge/2019/blob/master/problems/final/answer_and_comment_by_judges.ipynb):ジャッジによるファイナルチャレンジの解説をご紹介しています。競技者の皆さんの独創的で素晴らしい解法↓↓↓もぜひチェックしてください。 61 | 62 | ## トップチームの解法解説 63 | [トップチームの解法解説](https://github.com/quantum-challenge/2019/tree/master/top%20ten%20submissions):トップチームの皆さんが今回の問題にどう挑んだのか。アプローチ、駆使したテクニックなどを各チームが公開しています。 64 | 65 | ## 参加登録 66 | [公式サイト](https://quantumchallenge19.com/)からの参加登録がまだお済みでない方は、必ずコンテストに取りかかる前に[参加登録](https://angelhack.typeform.com/to/UA44d9)の完了をお願いいたします。登録が完了していない場合は、参加の権利、および入賞時のアワード取得ができませんのでご注意ください。 67 | 68 | IBM Quantum Challengeは2019年9月16日〜10月14日の4週間が開催期間です。最終週の本戦開始までは、ラーニングチャレンジと呼ばれる演習問題を毎週公開します。この期間中はどなたでも途中から参加登録が可能です。10月7日の本戦開始とともに登録の受付を終了いたします。 69 | 70 | 上記お済みでしたら、早速インストールからはじめて参りましょう! 71 | 72 | ## インストール方法 73 | Quantum Challengeでは、**Qiskit** を使ってプログラムを作成します。Qiskitは量子コンピューターを使うためのPythonのオープンソース フレームワークです。パルスや回路、アルゴリズムといった様々なレイヤーで活用することができます。Qiskitの詳細は[Qiskit.org](https://qiskit.org)のページを参照して下さい。 74 | 75 | Qiskitは *pip* を用いてインストールできます。 76 | 77 | ``` 78 | $ pip install qiskit 79 | ``` 80 | インストールの詳細な手順については[Qiskitのインストール](https://qiskit.org/documentation/locale/ja/install.html)または[インストール動画](https://www.youtube.com/watch?v=M4EkW4VwhcI)を参照してください。 81 | 82 | ## チャレンジ内容 83 | 毎週以下の日付にそれぞれのチャレンジ内容を更新します。
84 | 85 | | ウィーク | チャレンジ | 更新予定日 | 86 | | --- | --- | --- | 87 | | Week 0 |[初心者向け:量子計算の基礎](https://github.com/quantum-challenge/2019/blob/master/problems/week0/week0.ipynb) | Sept 16th, 2019 | 88 | | Week 1 |[ラーニングチャレンジ演習 I](https://github.com/quantum-challenge/2019/blob/master/problems/week1/week1.ipynb) | Sept 16th, 2019 | 89 | | Week 2 |[ラーニングチャレンジ演習 II](https://github.com/quantum-challenge/2019/blob/master/problems/week2/week2.ipynb) | Sept 23rd, 2019 | 90 | | Week 3 |[ラーニングチャレンジ演習 III](https://github.com/quantum-challenge/2019/blob/master/problems/week3/week3.ipynb)| Sept 30th, 2019 | 91 | | Week 4 |[ファイナルチャレンジ(本戦)](https://github.com/quantum-challenge/2019/blob/master/problems/final/Final.ipynb) | Oct 7th, 2019 | 92 | -------------------------------------------------------------------------------- /problems/final/Final.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "# Week 4: ファイナルチャレンジ\n", 15 | "最終週へようこそ。これまでのラーニングチャレンジで学んだことを活かして、ぜひ最終問題に挑戦してください。
\n", 16 | "尚、最終問題は当プログラミングコンテストにおける皆さんの順位を決めるベースとなります。そのため、主催者側は解法に関する質問には回答できません。Slackチャネルでのご質問はルールや提出ガイドライン等に関わるものに限定をお願いします。\n", 17 | "***\n", 18 | "\n", 19 | "# 最終問題:自治体のコンビニ出店プランを提示せよ\n", 20 | "東京のZ市は11の区域からなる自治体で、すでに4社のコンビニ(A社,B社,C社,D社)が本社の1店舗を別々の区域に展開しています。 \n", 21 | "現在の出店状況は地図の通りです。地図上の各ノードはそれぞれの区域を表しており、地図上のエッジは、エッジの両端の区域が隣り合っていることを表しています。\n", 22 | "\n", 23 | "市長のあなたは、残りの7区域にもコンビニを誘致しようとしましたが、4社から以下の条件が提示されました。\n", 24 | "* 1つの区域に出店出来るのは1社のコンビニのみ\n", 25 | "* 自社のコンビニは、隣接する区域に自社のコンビニが既に出店している場合は出店しない。\n", 26 | "\n", 27 | "あなたはこれらの条件を満たす出店案を提示できるでしょうか? \n", 28 | "**week2,3で使ったグローバーのアルゴリズムをiteration回数=5で用いて、条件を満たす全ての出店案を列挙してみてください。**\n", 29 | "

\n", 30 | "***************************" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "metadata": {}, 36 | "source": [ 37 | "# 実行時の注意\n", 38 | "- バックエンドは **32-qubitシミュレーター**を指定してください. (e.g. backend = provider.get_backend('ibmq_qasm_simulator'))\n", 39 | "- 回路の規模が大き過ぎる場合、実行時間が長くなる可能性があります(具体的には30分から60分等。ジャッジが作成した回答例はもっと短い時間で処理が完了します)。自分のジョブが正しく実行されているか確認したい場合は、下記のページで確認してください。 \n", 40 | "https://quantum-computing.ibm.com/results \n", 41 | "**実行出来ているか心配だからといって何度も同じjobを投げないでください**\n", 42 | "- シミュレーター実行時は下記のコードを用いて実行してください。下記のコード内ではサンプル数を増やすために`shots`を8000に、シードを固定するために`seed_simulator`を12345に、シミュレーターの実行速度を向上させるために`backend_options={\"fusion_enable\":True}`を設定しています。\n", 43 | "- 回路のなかでリセットのオペレーション (i.e. qc.reset()) は使用しないでください。" 44 | ] 45 | }, 46 | { 47 | "cell_type": "code", 48 | "execution_count": null, 49 | "metadata": {}, 50 | "outputs": [], 51 | "source": [ 52 | "provider = IBMQ.load_account()\n", 53 | "backend = provider.get_backend('ibmq_qasm_simulator')\n", 54 | "job = execute(qc, backend=backend, shots=8000, seed_simulator=12345, backend_options={\"fusion_enable\":True})\n", 55 | "result = job.result()\n", 56 | "count = result.get_counts()\n", 57 | "print(count)" 58 | ] 59 | }, 60 | { 61 | "cell_type": "markdown", 62 | "metadata": {}, 63 | "source": [ 64 | "# 提出時の注意\n", 65 | "- それぞれの会社については、A社を$00$、B社を$01$、C社を$10$、D社を$11$とマッピングするものとします。 \n", 66 | "- 古典レジスタc[2n], c[2n+1]にn番目の区域に出店するコンビニをマッピングしてください。\n", 67 | "- 答えを知らない状態でも作成できるオラクルを用いてください(言い換えると、古典の最適化ソルバ等で答えを計算して、それを基にオラクルを作成しないでください!)\n", 68 | "- Unroller以外のtranspilerのpassを用いないでください(言い換えると、既存の最適化用等のpassを使わず、自分の力で戦ってください)\n", 69 | "\n", 70 | "例:0番目の区域に出店するコンビニがB社の場合、古典レジスタc[0], c[1]にそれぞれ$0$と$1$をマッピングします。 \n", 71 | "\n", 72 | "上記提出時の注意を踏まえて、シミュレーターでの実行結果から、**確率が高いビット列上位9個**を基に作成したコンビニの配置案とUnrollerを用いて回路をu3とCXに分解した結果を提出してください。 \n", 73 | "\n", 74 | "### 提出物は回答ファイル(.txtファイル)とプログラム(.pyファイル)の二種類を提出してください\n", 75 | "提出物は以下の二つを提出してください。回答ファイルは採点用に使用し、プログラムはどのような回路を作成したかの確認用に用います。\n", 76 | "- 回答ファイル(.txtファイル)\n", 77 | "- プログラム(.pyファイル)\n", 78 | "\n", 79 | "## 重要: 提出用の回答ファイルは下記のプログラムを用いて作成してください。\n", 80 | "下記の`circuit`と`results`と`name`と`times`に作成した回路と実行結果と名前と提出回数を代入すれば自動で回答ファイルが作成されます。 \n", 81 | "回答ファイル内ではA社、B社、C社、D社は0、1、2、3にマッピングされています。\n", 82 | "### フォーマットに沿っていないものは自動的にRejectされます。\n", 83 | "自分の回答ファイルがフォーマットに沿っているか心配な場合、回答ファイルVerify用プログラムを実行し正しいフォーマットになっているか確認してください\n", 84 | "\n", 85 | "#### 回答ファイルのサンプル\n", 86 | "下記のプログラムで作成される回答ファイルはこのようなファイルになります(実際の値は下記とは異なります)。\n", 87 | "```\n", 88 | "{\"ans\": [[\"01230123012\", 30], [\"01230123012\", 30], [\"01230123012\", 30], [\"01230123012\", 30], [\"01230123012\", 30], [\"01230123012\", 30], [\"01230123012\", 30], [\"01230123012\", 30], [\"01230123012\", 30], \"costs\": {\"u3\": 20000, \"cx\": 10000, \"barrier\": 20, \"measure\": 20}}\n", 89 | "```\n", 90 | "\n", 91 | "**ファイナルチャレンジ用の[回答提出フォーム](https://angelhack.typeform.com/to/MpHd9o)をつかって提出をお願いします。**" 92 | ] 93 | }, 94 | { 95 | "cell_type": "markdown", 96 | "metadata": {}, 97 | "source": [ 98 | "## 回答ファイル作成用プログラム" 99 | ] 100 | }, 101 | { 102 | "cell_type": "markdown", 103 | "metadata": {}, 104 | "source": [ 105 | "**回路が大きい場合、Unrollerの処理に時間がかかる可能性があります。** \n", 106 | "もし、処理が終わらない場合、使用していないウィンドウを閉じたりJupyter NotebookのKernelを再起動する等し、Unrollerの処理を再実行してください。" 107 | ] 108 | }, 109 | { 110 | "cell_type": "code", 111 | "execution_count": null, 112 | "metadata": {}, 113 | "outputs": [], 114 | "source": [ 115 | "# Input your quantum circuit\n", 116 | "circuit='Input your circuit'\n", 117 | "# Input your result of the execute(groverCircuit, backend=backend, shots=shots).result()\n", 118 | "results = 'Input your result'\n", 119 | "count=results.get_counts()\n", 120 | "# Input your name or your team name ('Team details form'に記入した通りにチーム名を入力してください)\n", 121 | "name='Input your team name as exactly as you inputted it in the team details form'\n", 122 | "# Please indicate the number of times you have submitted your answer so far.\n", 123 | "# For example, If it's your 1st time to submit your answer, write times='1'. If it's your 5th time to submit your answer, write times='5'.\n", 124 | "# Do not forget to put single quotations to make the variable 'Str'' type\n", 125 | "times='Input the number of times you have submitted your answer so far'" 126 | ] 127 | }, 128 | { 129 | "cell_type": "code", 130 | "execution_count": null, 131 | "metadata": {}, 132 | "outputs": [], 133 | "source": [ 134 | "import json\n", 135 | "from qiskit.transpiler import PassManager\n", 136 | "from qiskit.transpiler.passes import Unroller\n", 137 | "\n", 138 | "# Unroll the circuit\n", 139 | "pass_ = Unroller(['u3', 'cx'])\n", 140 | "pm = PassManager(pass_)\n", 141 | "new_circuit = pm.run(circuit) \n", 142 | "\n", 143 | "# obtain gates\n", 144 | "gates=new_circuit.count_ops()\n", 145 | "\n", 146 | "#sort count\n", 147 | "count_sorted = sorted(count.items(), key=lambda x:x[1], reverse=True)\n", 148 | "\n", 149 | "# collect answers with Top 9 probability\n", 150 | "ans_list = count_sorted[0:9]\n", 151 | "\n", 152 | "# reverse ans_list\n", 153 | "ans_reversed = []\n", 154 | "for i in ans_list:\n", 155 | " ans_temp=[i[0][::-1],i[1]]\n", 156 | " ans_reversed.append(ans_temp)\n", 157 | "\n", 158 | "# convert each 2 bits into corresponding color. Add node0(0),node3(1),node8(2) and node11(3)\n", 159 | "ans_shaped = []\n", 160 | "for j in ans_reversed:\n", 161 | " ans_temp=j[0]\n", 162 | " nodeA = 0\n", 163 | " node0 = int(ans_temp[0] + ans_temp[1], 2)\n", 164 | " node1 = int(ans_temp[2] + ans_temp[3], 2)\n", 165 | " nodeB = 1\n", 166 | " node2 = int(ans_temp[4] + ans_temp[5], 2)\n", 167 | " node3 = int(ans_temp[6] + ans_temp[7], 2)\n", 168 | " node4 = int(ans_temp[8] + ans_temp[9], 2)\n", 169 | " nodeC = 2\n", 170 | " node5 = int(ans_temp[10] + ans_temp[11], 2)\n", 171 | " node6 = int(ans_temp[12] + ans_temp[13], 2)\n", 172 | " nodeD = 3\n", 173 | " nodes_color = str(nodeA) + str(node0) + str(node1) + str(nodeB) + str(node2) + str(node3) + str(node4) + str(nodeC) + str(node5) + str(node6) + str(nodeD) \n", 174 | " ans_shaped.append([nodes_color,j[1]])\n", 175 | "\n", 176 | "# write the result into '[your name]_final_output.txt'\n", 177 | "filename=name+'_'+times+'_final_output.txt'\n", 178 | "dct={'ans':ans_shaped,'costs':gates}\n", 179 | "with open(filename, 'w') as f:\n", 180 | " json.dump(dct, f)" 181 | ] 182 | }, 183 | { 184 | "cell_type": "markdown", 185 | "metadata": {}, 186 | "source": [ 187 | "### 回答ファイルVerify用プログラム" 188 | ] 189 | }, 190 | { 191 | "cell_type": "code", 192 | "execution_count": 38, 193 | "metadata": {}, 194 | "outputs": [], 195 | "source": [ 196 | "# Input a path of your submitted file\n", 197 | "your_path='Input a path of your submitted file'" 198 | ] 199 | }, 200 | { 201 | "cell_type": "code", 202 | "execution_count": null, 203 | "metadata": {}, 204 | "outputs": [], 205 | "source": [ 206 | "import json\n", 207 | "from pathlib import Path\n", 208 | "\n", 209 | "p= Path(your_path)\n", 210 | "\n", 211 | "# Verify your information\n", 212 | "f_name=p.name\n", 213 | "your_info=f_name.split('_')\n", 214 | "print('Your name: ', your_info[0])\n", 215 | "print('The number of times you have submitted your answer: ', your_info[1])\n", 216 | "\n", 217 | "with open(p, 'r') as f:\n", 218 | " print(f)\n", 219 | " your_ans=json.load(f)\n", 220 | "\n", 221 | "print('Does your submission file have 9 answers?')\n", 222 | "if (len(your_ans['ans'])!=9):\n", 223 | " print('- No, make sure you have 9 answers with top 9 probabilities')\n", 224 | "else:\n", 225 | " print('- Yes')\n", 226 | " print('- Your plan: ', your_ans['ans'])\n", 227 | "\n", 228 | "print('What is your cost?')\n", 229 | "your_cost=your_ans['costs']['u3'] + 10*your_ans['costs']['cx']\n", 230 | "print('- ', your_cost)" 231 | ] 232 | } 233 | ], 234 | "metadata": { 235 | "kernelspec": { 236 | "display_name": "Python 3", 237 | "language": "python", 238 | "name": "python3" 239 | }, 240 | "language_info": { 241 | "codemirror_mode": { 242 | "name": "ipython", 243 | "version": 3 244 | }, 245 | "file_extension": ".py", 246 | "mimetype": "text/x-python", 247 | "name": "python", 248 | "nbconvert_exporter": "python", 249 | "pygments_lexer": "ipython3", 250 | "version": "3.7.3" 251 | } 252 | }, 253 | "nbformat": 4, 254 | "nbformat_minor": 2 255 | } 256 | -------------------------------------------------------------------------------- /problems/final/Final_en.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "# Week 4: Final Challenge\n", 15 | "**Welcome to the final challenge!**
\n", 16 | "Congratulations for coming thus far. In the final challenge, you will get to utilize what you learned in the past three weeks.
\n", 17 | "\n", 18 | "As this final challenge will serve as the basis for the actual competition, please note that the organizers will not be able to assist you in getting the right answers. Please limit questions only pertaining to clarification of rules or guidelines.
\n", 19 | "Thank you and good luck with the challenge! \n", 20 | "\n", 21 | "***************************\n", 22 | "# The Final Challenge Problem\n", 23 | "\n", 24 | "Zed City is a newly established (fictitious) municipality in Tokyo and is made up of 11 districts.
\n", 25 | "Four convenience store ( _konbini_ ) chains A, B, C and D have each established their first store in this new city in non-overlapping districts.\n", 26 | "The map (or graph) below shows the 11 districts of Zed City and which district has a konbini already.\n", 27 | "\n", 28 | "Since this map looks different from a conventional one, let us explain how you should look at it once more just in case.
\n", 29 | "If you count the number of nodes in this map (or graph), you'll notice that there are 11 of them. So, you should be able to tell that each node in this map (or graph) represents one of the 11 districts of Zed city. The colored nodes are the districts that have konbinis already with each color representing a different konbini chain. In this graph, konbini chain A is represented in Red, B in Blue, C in Yellow and D in Green. Next, you should take notice of the edges that connect these nodes. Any node (district) connected to each other by an edge means that they are districts adjacent to each other.\n", 30 | "\n", 31 | "As the mayor of Zed City, you want to establish konbinis in the rest of the districts that still don't have one yet.
\n", 32 | "Upon your request, all four konbini chains discussed with each other and agreed to establish their konbinis in Zed City under the following two conditions:\n", 33 | "\n", 34 | "**-Only one konbini is allowed in one district.**
\n", 35 | "**-No two adjacent districts can have konbinis from the same chain.**
\n", 36 | "\n", 37 | "Can you come up with a plan that satisfies the above conditions? You must provide all store plan combinations that meet the conditions above.
\n", 38 | "\n", 39 | "**For solving this problem:**
\n", 40 | "- You must use the 32-qubit simulator as your backend. (i.e. backend = provider.get_backend('ibmq_qasm_simulator'))\n", 41 | "- Use **Grover's algorithm** you learned in Week2 & 3 with **iteration = 5.**\n", 42 | "- Each konbini chain A, B, C and D should be described (mapped) as **A: $00$、B:$01$、C:$10$、D:$11$**.\n", 43 | "- A konbini you are establishing in **district _n_**, should be mapped into classical registers **c[2n]** and **c[2n+1]**.\n", 44 | "(For example, let's say you want to establish konbini chain B:$01$ into district n=1. In this case, you should map $0$ and $1$ into classical registers c[2] and c[3].)\n", 45 | "- Make sure you **create an oracle** that **doesn't require any knowledge of what the answers are**. (For example, you are not allowed to create an oracle by using a classical optimization solver to get your answers for it.) \n", 46 | "- With the exception of the Unroller, which is required for decomposing your circuit to calculate quantum costs, you are not allowed to use any existing transpiler passes nor original transpilers for making simple simplifications in this competition.\n", 47 | "- You are not allowed to use the reset operation (i.e. qc.reset()) in your circuit for this competition.\n", 48 | "

\n", 49 | "***************************" 50 | ] 51 | }, 52 | { 53 | "cell_type": "markdown", 54 | "metadata": {}, 55 | "source": [ 56 | "# IMPORTANT\n", 57 | "- Depending on your circuit size, **execution time can get quite long**. Sometimes even up to 60 minutes. So please be patient. \n", 58 | "- Please **do not throw jobs in succession** even if you are worried whether your job is running properly or not. This can create a long queue and clog the backend. You can check if your job is properly running from:
\n", 59 | "https://quantum-computing.ibm.com/results \n", 60 | "- **For the final challenge submission**, please make sure to **use the following code for running your circuit** on the 32-qubit QASM simulator. " 61 | ] 62 | }, 63 | { 64 | "cell_type": "code", 65 | "execution_count": null, 66 | "metadata": {}, 67 | "outputs": [], 68 | "source": [ 69 | "provider = IBMQ.load_account()\n", 70 | "backend = provider.get_backend('ibmq_qasm_simulator')\n", 71 | "job = execute(qc, backend=backend, shots=8000, seed_simulator=12345, backend_options={\"fusion_enable\":True})\n", 72 | "result = job.result()\n", 73 | "count = result.get_counts()\n", 74 | "print(count)\n", 75 | "#`shots` are set to 8000 to increase sampling\n", 76 | "#`seed_simulator`` is set to 12345 to 'lock' its value, and \n", 77 | "#`backend_options={\"fusion_enable\":True}` is specified to improve simulator performance." 78 | ] 79 | }, 80 | { 81 | "cell_type": "markdown", 82 | "metadata": {}, 83 | "source": [ 84 | "# SUBMISSION GUIDELINES\n", 85 | "### Expected output:\n", 86 | "While making sure you adhere to all the rules, please obtain the following results:
\n", 87 | "(1)Figure out the possible store plans by extracting the top nine bit-strings that give you the highest probabilities.
\n", 88 | "(2)Find out the elementary gate (u3 and CX) counts by applying the Unroller to the circuit you built.\n", 89 | "\n", 90 | "### For Submission:\n", 91 | "#### Use the following program to create your submission file\n", 92 | "Using the **Submission File Creation Program** below, input your circuit, its result, your team name and the number of times you have made your submissions each into `circuit`, `results`, `name` and `times`. This will create a single submission file that will provide the above (1) and (2) in one file. \n", 93 | "Please note that the generated submission file will show konbini chains A, B, C and D described as 0, 1, 2, 3.\n", 94 | "\n", 95 | "#### You need to submit:\n", 96 | "#### File 1. The ouput file created by the file creation program (.txt file)\n", 97 | "#### File 2. The program of the circuit you built (.py file)\n", 98 | "\n", 99 | "#### Submissions that do not comply with the above format will be rejected. \n", 100 | "If you want to check if your submission file is compliant with the specified format, you can always verify this by using the **Verification Program** provided in the last section of this page.\n", 101 | "\n", 102 | "#### Example Output for File 1\n", 103 | "The Submission File Creation Program will give you an output text file that will look something like:
\n", 104 | "(Note: These are not the actual answers! Just a sample to show you how your output should look like.) \n", 105 | "\n", 106 | "```\n", 107 | "{\"ans\": [[\"01230123012\", 30], [\"01230123012\", 30], [\"01230123012\", 30], [\"01230123012\", 30], [\"01230123012\", 30], [\"01230123012\", 30], [\"01230123012\", 30], [\"01230123012\", 30], [\"01230123012\", 30], \"costs\": {\"u3\": 20000, \"cx\": 10000, \"barrier\": 20, \"measure\": 20}}\n", 108 | "```\n", 109 | "**Use this [Submission Form](https://angelhack.typeform.com/to/MpHd9o) to make submissions for the Final Challenge.**" 110 | ] 111 | }, 112 | { 113 | "cell_type": "markdown", 114 | "metadata": {}, 115 | "source": [ 116 | "## Submission File Creation Program" 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "execution_count": null, 122 | "metadata": {}, 123 | "outputs": [], 124 | "source": [ 125 | "# Input your quantum circuit\n", 126 | "circuit='Input your circuit'\n", 127 | "# Input your result of the execute(groverCircuit, backend=backend, shots=shots).result()\n", 128 | "results = 'Input your result'\n", 129 | "count=results.get_counts()\n", 130 | "# Provide your team name\n", 131 | "name='Input your team name as exactly as you inputted it in the team details form'\n", 132 | "# Please indicate the number of times you have made a submission so far. \n", 133 | "# For example, if it's your 1st time to submit your answer, write 1. If it's your 5th time to submit your answer, write 5.\n", 134 | "times='Input the number of times you have made your submissions so far'" 135 | ] 136 | }, 137 | { 138 | "cell_type": "code", 139 | "execution_count": null, 140 | "metadata": {}, 141 | "outputs": [], 142 | "source": [ 143 | "import json\n", 144 | "from qiskit.transpiler import PassManager\n", 145 | "from qiskit.transpiler.passes import Unroller\n", 146 | "\n", 147 | "# Unroll the circuit\n", 148 | "pass_ = Unroller(['u3', 'cx'])\n", 149 | "pm = PassManager(pass_)\n", 150 | "new_circuit = pm.run(circuit) \n", 151 | "\n", 152 | "# obtain gates\n", 153 | "gates=new_circuit.count_ops()\n", 154 | "\n", 155 | "#sort count\n", 156 | "count_sorted = sorted(count.items(), key=lambda x:x[1], reverse=True)\n", 157 | "\n", 158 | "# collect answers with Top 9 probability\n", 159 | "ans_list = count_sorted[0:9]\n", 160 | "\n", 161 | "# reverse ans_list\n", 162 | "ans_reversed = []\n", 163 | "for i in ans_list:\n", 164 | " ans_temp=[i[0][::-1],i[1]]\n", 165 | " ans_reversed.append(ans_temp)\n", 166 | "\n", 167 | "# convert each 2 bits into corresponding color. Add node0(0),node3(1),node8(2) and node11(3)\n", 168 | "ans_shaped = []\n", 169 | "for j in ans_reversed:\n", 170 | " ans_temp=j[0]\n", 171 | " nodeA = 0\n", 172 | " node0 = int(ans_temp[0] + ans_temp[1], 2)\n", 173 | " node1 = int(ans_temp[2] + ans_temp[3], 2)\n", 174 | " nodeB = 1\n", 175 | " node2 = int(ans_temp[4] + ans_temp[5], 2)\n", 176 | " node3 = int(ans_temp[6] + ans_temp[7], 2)\n", 177 | " node4 = int(ans_temp[8] + ans_temp[9], 2)\n", 178 | " nodeC = 2\n", 179 | " node5 = int(ans_temp[10] + ans_temp[11], 2)\n", 180 | " node6 = int(ans_temp[12] + ans_temp[13], 2)\n", 181 | " nodeD = 3\n", 182 | " nodes_color = str(nodeA) + str(node0) + str(node1) + str(nodeB) + str(node2) + str(node3) + str(node4) + str(nodeC) + str(node5) + str(node6) + str(nodeD) \n", 183 | " ans_shaped.append([nodes_color,j[1]])\n", 184 | "\n", 185 | "# write the result into '[your name]_final_output.txt'\n", 186 | "filename=name+'_'+times+'_final_output.txt'\n", 187 | "dct={'ans':ans_shaped,'costs':gates}\n", 188 | "with open(filename, 'w') as f:\n", 189 | " json.dump(dct, f)" 190 | ] 191 | }, 192 | { 193 | "cell_type": "markdown", 194 | "metadata": {}, 195 | "source": [ 196 | "## Verification Program" 197 | ] 198 | }, 199 | { 200 | "cell_type": "code", 201 | "execution_count": null, 202 | "metadata": {}, 203 | "outputs": [], 204 | "source": [ 205 | "# Input the path of your submission file\n", 206 | "your_path='./output/bob_1_final_output.txt'" 207 | ] 208 | }, 209 | { 210 | "cell_type": "code", 211 | "execution_count": null, 212 | "metadata": {}, 213 | "outputs": [], 214 | "source": [ 215 | "import json\n", 216 | "from pathlib import Path\n", 217 | "\n", 218 | "p= Path(your_path)\n", 219 | "\n", 220 | "# Verify your information\n", 221 | "f_name=p.name\n", 222 | "your_info=f_name.split('_')\n", 223 | "print('Your name: ', your_info[0])\n", 224 | "print('The number of times you have submitted your answer: ', your_info[1])\n", 225 | "\n", 226 | "with open(p, 'r') as f:\n", 227 | " print(f)\n", 228 | " your_ans=json.load(f)\n", 229 | "\n", 230 | "print('Does your submission file have 9 answers?')\n", 231 | "if (len(your_ans['ans'])!=9):\n", 232 | " print('- No, make sure you have 9 answers with top 9 probabilities')\n", 233 | "else:\n", 234 | " print('- Yes')\n", 235 | " print('- Your plan: ', your_ans['ans'])\n", 236 | "\n", 237 | "print('What is your cost?')\n", 238 | "your_cost=your_ans['costs']['u3'] + 10*your_ans['costs']['cx']" 239 | ] 240 | } 241 | ], 242 | "metadata": { 243 | "kernelspec": { 244 | "display_name": "Python 3", 245 | "language": "python", 246 | "name": "python3" 247 | }, 248 | "language_info": { 249 | "codemirror_mode": { 250 | "name": "ipython", 251 | "version": 3 252 | }, 253 | "file_extension": ".py", 254 | "mimetype": "text/x-python", 255 | "name": "python", 256 | "nbconvert_exporter": "python", 257 | "pygments_lexer": "ipython3", 258 | "version": "3.7.3" 259 | } 260 | }, 261 | "nbformat": 4, 262 | "nbformat_minor": 2 263 | } 264 | -------------------------------------------------------------------------------- /problems/final/Leader_Board.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "# Final Challenge Leaderboard" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "Thank you to everyone who submitted their code to the final challenge!
\n", 22 | "The following shows final standings of contestants who submitted their code to the final challenge (2019/10/23 16:00 JST)
\n", 23 | "*(Note: All code has been verified by judges and scores are finalized. Their decision will be final and no further discussions will be held.)*" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "## **Congratulations to the winners!**" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "metadata": {}, 36 | "source": [ 37 | "**A note on the awards:** In addition to the first, second and third place winners, we want to recognize a few teams with **Special Oracle Awards**. These teams didn't qualify for winning the main competition, nevertheless came up with a very creative oracle design to solve the problem." 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": {}, 43 | "source": [ 44 | "\n", 45 | " \n", 46 | " \n", 47 | " \n", 48 | " \n", 49 | " \n", 50 | " \n", 51 | " \n", 52 | " \n", 53 | " \n", 54 | " \n", 55 | " \n", 56 | " \n", 57 | " \n", 58 | " \n", 59 | " \n", 60 | " \n", 61 | " \n", 62 | " \n", 63 | " \n", 64 | " \n", 65 | " \n", 66 | " \n", 67 | " \n", 68 | " \n", 69 | " \n", 70 | " \n", 71 | " \n", 72 | " \n", 73 | " \n", 74 | " \n", 75 | " \n", 76 | " \n", 77 | " \n", 78 | " \n", 79 | " \n", 80 | " \n", 81 | " \n", 82 | " \n", 83 | " \n", 84 | " \n", 85 | " \n", 86 | " \n", 87 | " \n", 88 | " \n", 89 | " \n", 90 | " \n", 91 | " \n", 92 | " \n", 93 | " \n", 94 | " \n", 95 | " \n", 96 | " \n", 97 | " \n", 98 | " \n", 99 | " \n", 100 | " \n", 101 | " \n", 102 | " \n", 103 | " \n", 104 | " \n", 105 | " \n", 106 | " \n", 107 | " \n", 108 | " \n", 109 | " \n", 110 | " \n", 111 | " \n", 112 | " \n", 113 | " \n", 114 | " \n", 115 | " \n", 116 | " \n", 117 | " \n", 118 | " \n", 119 | " \n", 120 | " \n", 121 | " \n", 122 | " \n", 123 | " \n", 124 | " \n", 125 | " \n", 126 | " \n", 127 | " \n", 128 | " \n", 129 | " \n", 130 | " \n", 131 | " \n", 132 | " \n", 133 | " \n", 134 | " \n", 135 | " \n", 136 | " \n", 137 | " \n", 138 | " \n", 139 | " \n", 140 | " \n", 141 | " \n", 142 | " \n", 143 | " \n", 144 | " \n", 145 | " \n", 146 | " \n", 147 | " \n", 148 | " \n", 149 | " \n", 150 | " \n", 151 | " \n", 152 | " \n", 153 | " \n", 154 | " \n", 155 | " \n", 156 | " \n", 157 | " \n", 158 | " \n", 159 | " \n", 160 | " \n", 161 | " \n", 162 | " \n", 163 | " \n", 164 | " \n", 165 | " \n", 166 | " \n", 167 | " \n", 168 | " \n", 169 | " \n", 170 | " \n", 171 | " \n", 172 | " \n", 173 | " \n", 174 | " \n", 175 | " \n", 176 | " \n", 177 | " \n", 178 | " \n", 179 | " \n", 180 | " \n", 181 | " \n", 182 | " \n", 183 | " \n", 184 | " \n", 185 | " \n", 186 | " \n", 187 | " \n", 188 | " \n", 189 | " \n", 190 | " \n", 191 | " \n", 192 | " \n", 193 | " \n", 194 | " \n", 195 | " \n", 196 | " \n", 197 | " \n", 198 | " \n", 199 | " \n", 200 | " \n", 201 | " \n", 202 | " \n", 203 | " \n", 204 | " \n", 205 | " \n", 206 | " \n", 207 | " \n", 208 | " \n", 209 | " \n", 210 | " \n", 211 | " \n", 212 | " \n", 213 | " \n", 214 | " \n", 215 | " \n", 216 | " \n", 217 | " \n", 218 | " \n", 219 | " \n", 220 | " \n", 221 | " \n", 222 | " \n", 223 | " \n", 224 | " \n", 225 | " \n", 226 | " \n", 227 | " \n", 228 | " \n", 229 | " \n", 230 | " \n", 231 | " \n", 232 | " \n", 233 | " \n", 234 | " \n", 235 | " \n", 236 | " \n", 237 | " \n", 238 | " \n", 239 | " \n", 240 | " \n", 241 | " \n", 242 | " \n", 243 | " \n", 244 | " \n", 245 | " \n", 246 | " \n", 247 | " \n", 248 | " \n", 249 | " \n", 250 | " \n", 251 | " \n", 252 | " \n", 253 | " \n", 254 | " \n", 255 | " \n", 256 | " \n", 257 | " \n", 258 | " \n", 259 | " \n", 260 | " \n", 261 | " \n", 262 | " \n", 263 | " \n", 264 | " \n", 265 | " \n", 266 | " \n", 267 | " \n", 268 | " \n", 269 | " \n", 270 | " \n", 271 | " \n", 272 | " \n", 273 | " \n", 274 | " \n", 275 | " \n", 276 | " \n", 277 | " \n", 278 | " \n", 279 | " \n", 280 | " \n", 281 | " \n", 282 | " \n", 283 | " \n", 284 | " \n", 285 | " \n", 286 | " \n", 287 | " \n", 288 | " \n", 289 | " \n", 290 | " \n", 291 | " \n", 292 | " \n", 293 | " \n", 294 | " \n", 295 | " \n", 296 | " \n", 297 | " \n", 298 | " \n", 299 | " \n", 300 | " \n", 301 | " \n", 302 | " \n", 303 | " \n", 304 | " \n", 305 | " \n", 306 | " \n", 307 | " \n", 308 | " \n", 309 | " \n", 310 | " \n", 311 | " \n", 312 | " \n", 313 | " \n", 314 | " \n", 315 | " \n", 316 | " \n", 317 | " \n", 318 | " \n", 319 | " \n", 320 | " \n", 321 | " \n", 322 | " \n", 323 | " \n", 324 | " \n", 325 | " \n", 326 | " \n", 327 | " \n", 328 | " \n", 329 | " \n", 330 | " \n", 331 | " \n", 332 | " \n", 333 | " \n", 334 | " \n", 335 | " \n", 336 | " \n", 337 | " \n", 338 | " \n", 339 | " \n", 340 | " \n", 341 | " \n", 342 | " \n", 343 | " \n", 344 | " \n", 345 | " \n", 346 | " \n", 347 | " \n", 348 | " \n", 349 | " \n", 350 | " \n", 351 | " \n", 352 | " \n", 353 | " \n", 354 | " \n", 355 | " \n", 356 | " \n", 357 | " \n", 358 | " \n", 359 | " \n", 360 | " \n", 361 | "
rankingteam_namestatuscostnumber_of_submissionmessage
1st PlaceWhit3zpass1661315congratulations on winning 1st place in the challenge!
2nd PlaceQunaVillagepass170533congratulations on winning 2nd place in the challenge!
3rd PlaceIIQ@QICpass254903congratulations on winning 3rd place in the challenge!
4DokiDokiQuantumClubpass276566congratulations on getting the correct answer!
542Roboticspass284979congratulations on getting the correct answer!
6Toffoli_Pizzapass286993congratulations on getting the correct answer!
7TheAxiompass301055congratulations on getting the correct answer!
8Deus_Ex_Machinapass314291congratulations on getting the correct answer!
9_rp_cc_sqrt_2_pass332415congratulations on getting the correct answer!
10Gate42pass342694congratulations on getting the correct answer!
11moyanpass349025congratulations on getting the correct answer!
12jijipass407154congratulations on getting the correct answer!
13xenoicwycepass415563congratulations on getting the correct answer!
14E_bitspass442343congratulations on getting the correct answer!
15Untitled_NTU_Teampass444211congratulations on getting the correct answer!
16EPFL_Eliaspass486751congratulations on getting the correct answer!
17rainy_day_hackerspass491563congratulations on getting the correct answer!
18Guardians_of_the_Hilbert_Spacepass496561congratulations on getting the correct answer!
19qwalkerspass517343congratulations on getting the correct answer!
20Quemixpass538462congratulations on getting the correct answer!
21Toffoli Pizzapass543351congratulations on getting the correct answer!
22konbini_optimizerpass710551congratulations on getting the correct answer!
2381uemanpass1208644congratulations on getting the correct answer!
24SpoonBoyAndThePotentialspass3821652congratulations on getting the correct answer!
25AmoryfailNone1you are doing a great job, but answers were incorrect.
25B3noRumfailNone3you are doing a great job, but answers were incorrect.
25ERIQCfailNone5you are doing a great job, but answers were incorrect.
25Keiichiro_HigafailNone1you are doing a great job, but answers were incorrect.
25MLgoQuantumfailNone1you are doing a great job, but answers were incorrect.
25NGCfailNone1you are doing a great job, but answers were incorrect.
25PolemanfailNone5you are doing a great job, but answers were incorrect.
25Schrodingers_Cube_ItfailNone1you are doing a great job, but answers were incorrect.
25WoodyfailNone1you are doing a great job, but answers were incorrect.
25ZedFastMappersfailNone1you are doing a great job, but answers were incorrect.
25ccrgroupfailNone2you are doing a great job, but answers were incorrect.
25coscosfailNone1you are doing a great job, but answers were incorrect.
25mellamokylefailNone1you are doing a great job, but answers were incorrect.
25twcoloringfailNone1you are doing a great job, but answers were incorrect.
" 362 | ] 363 | }, 364 | { 365 | "cell_type": "markdown", 366 | "metadata": {}, 367 | "source": [ 368 | "# Special Oracle Award\n", 369 | "Some teams' initialization was partially incomplete and unable to generate equal probability distributions for the correct answers. However, among these teams, some came up with very creative oracles to solve the problem and reduce quantum cost. We would like to recognize these teams and award them with Special Oracle Awards. " 370 | ] 371 | }, 372 | { 373 | "cell_type": "markdown", 374 | "metadata": {}, 375 | "source": [ 376 | "\n", 377 | " \n", 378 | " \n", 379 | " \n", 380 | " \n", 381 | " \n", 382 | " \n", 383 | " \n", 384 | " \n", 385 | " \n", 386 | " \n", 387 | " \n", 388 | " \n", 389 | " \n", 390 | " \n", 391 | " \n", 392 | " \n", 393 | " \n", 394 | " \n", 395 | " \n", 396 | " \n", 397 | " \n", 398 | " \n", 399 | " \n", 400 | " \n", 401 | " \n", 402 | " \n", 403 | " " 404 | ] 405 | } 406 | ], 407 | "metadata": { 408 | "kernelspec": { 409 | "display_name": "Python 3", 410 | "language": "python", 411 | "name": "python3" 412 | }, 413 | "language_info": { 414 | "codemirror_mode": { 415 | "name": "ipython", 416 | "version": 3 417 | }, 418 | "file_extension": ".py", 419 | "mimetype": "text/x-python", 420 | "name": "python", 421 | "nbconvert_exporter": "python", 422 | "pygments_lexer": "ipython3", 423 | "version": "3.6.5" 424 | } 425 | }, 426 | "nbformat": 4, 427 | "nbformat_minor": 2 428 | } 429 | -------------------------------------------------------------------------------- /problems/final/fig/4bit_hyper_cube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/problems/final/fig/4bit_hyper_cube.png -------------------------------------------------------------------------------- /problems/final/fig/all_answers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/problems/final/fig/all_answers.png -------------------------------------------------------------------------------- /problems/final/fig/hyper_cube_ccx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/problems/final/fig/hyper_cube_ccx.png -------------------------------------------------------------------------------- /problems/final/fig/konbini_oracle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/problems/final/fig/konbini_oracle.png -------------------------------------------------------------------------------- /problems/final/fig/konbini_oracle_hyper_cube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/problems/final/fig/konbini_oracle_hyper_cube.png -------------------------------------------------------------------------------- /problems/final/fig/konbini_oracle_simple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/problems/final/fig/konbini_oracle_simple.png -------------------------------------------------------------------------------- /problems/final/fig/oracle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/problems/final/fig/oracle.png -------------------------------------------------------------------------------- /problems/final/fig/step2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/problems/final/fig/step2.png -------------------------------------------------------------------------------- /problems/final/fig/white_map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/problems/final/fig/white_map.png -------------------------------------------------------------------------------- /problems/final/logo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/problems/final/logo2.png -------------------------------------------------------------------------------- /problems/final/tokyo_map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/problems/final/tokyo_map.png -------------------------------------------------------------------------------- /problems/final/tokyo_map_pic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/problems/final/tokyo_map_pic.png -------------------------------------------------------------------------------- /problems/week0/.ipynb_checkpoints/week0-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# IBM Quantum Challenge 基礎の学習" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "本学習は初心者向けに、まずは量子回路をつかった演算の基礎を学ぶことを目的としています。すでに内容を理解されている方は、この教材は飛ばしていただいてかまいません。(当ドキュメントはIBM Q Experienceの[The weird and wonderful world of the qubit](https://quantum-computing.ibm.com/support/guides/introduction-to-quantum-circuits?section=5cae618666c1694be21df8cd)の抄訳です。)" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "## 量子計算とは?古典計算との比較\n", 22 | "量子計算とは何かを理解するために、まずは私たちが日頃つかっているデジタルコンピューターと比較して考えてみましょう。
\n", 23 | "デジタルコンピューターの計算の仕組みもまた、私たちはほとんど意識することはなくなってきています。そこで、デジタルコンピューター(古典コンピューター)がどのように情報を扱っているのかについてみていきましょう。" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "## すべての情報はビットである\n", 31 | "ビットは世の中のありとあらゆる情報を0または1で表現する情報の最小単位のことです。例えば、私たちが日常的に使用する十進数記法の数字は0, 1, 2, 3, 4, 5, 6, 7, 8. 9の10個の数字の組合せで表現します。各位の値は10の累乗をそれぞれいくつ含んでいるのかを表しています。
\n", 32 | "
\n", 33 | "例として **9213** という数字をみてみましょう。

この数字は9000 + 200 + 10 + 3に分解できます。0~9までの各数字に対して、10の累乗をそれぞれいくつ含んでいるのかをみてみますと、
\n", 34 | "**9213** = **9 x 103 + 2 x 102 + 1 x 101+ 3 x 100** として表現できます。" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "つづいて、同じ数字を二進数をベースに分解してみましょう。0と1の数字に対して、2の累乗をそれぞれいくつ含んでいるかをみてみますと、
\n", 42 | "**9213 = 1 x 213 + 0 x 212 + 0 x 211 + 0 x 210 + 1 x 29 + 1 x 28 + 1 x 27 + 1 x 26 + 1 x 25 + 1 x 24 + 1 x 23 + 1 x 22 + 0 x 21 + 1 x 20**
\n", 43 | "に分解することができることから、9213という数字はバイナリで表現すると **10001111111101** になります。" 44 | ] 45 | }, 46 | { 47 | "cell_type": "markdown", 48 | "metadata": {}, 49 | "source": [ 50 | "任意の数だけではなく、こちらの[テーブル](https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/network/conversion_table.html)にあるように、様々な文字や記号も0と1のバイナリで表すことができます。この対応表は業界の標準として広く採用されており、この記事がインターネットを通じて読者である皆さんに届けられる際にも用いられています。私たちが知っているコンピューターが扱うすべての情報(e.g. 数字、文字、画像、音声, etc.)は、実はこうしたビット列のかたまりであることを改めて覚えておきましょう。" 51 | ] 52 | }, 53 | { 54 | "cell_type": "markdown", 55 | "metadata": {}, 56 | "source": [ 57 | "## 8-bitのコンピューターをIBM Q Experienceでつくってみよう" 58 | ] 59 | }, 60 | { 61 | "cell_type": "markdown", 62 | "metadata": {}, 63 | "source": [ 64 | "量子回路を作成して実行するためのツールにIBM Q Experienceがあります。GUIが五線譜に似ていることから、通称Composerとも呼ばれています。このComposerをつかって8-bitのコンピューターをつくってみましょう。" 65 | ] 66 | }, 67 | { 68 | "cell_type": "markdown", 69 | "metadata": {}, 70 | "source": [ 71 | "1. (まだお済みでない方は)IBM Q Experienceのページから[アカウント作成](https://quantum-computing.ibm.com/)を行います。\n", 72 | "2. 中央のCreate a circuitボタンを押してComposerをたちあげます。\n", 73 | "3. 量子ゲートを直接ドラッグ&ドロップして回路を構築できます。\n", 74 | "4. 左側のエディターを直接編集して回路を構築することも可能です。" 75 | ] 76 | }, 77 | { 78 | "cell_type": "markdown", 79 | "metadata": {}, 80 | "source": [ 81 | "![image of composer](./fig/composer01.png)" 82 | ] 83 | }, 84 | { 85 | "cell_type": "markdown", 86 | "metadata": {}, 87 | "source": [ 88 | "では、量子レジスタと古典レジスタをそれぞれ8個用意して(i.e. qreg[8], creg[8] )、測定用のオペレーター(メーター模様のピンクのゲート)を各量子ビットからのびている線に順番に配置してみましょう。\n", 89 | "![image of composer2](./fig/composer02.png)" 90 | ] 91 | }, 92 | { 93 | "cell_type": "markdown", 94 | "metadata": {}, 95 | "source": [ 96 | "この図で示されているのが、「回路」と呼ばれるものです。回路は線の左から右へと時間発展的に量子ビットの状態を操作するものですが、私たちに馴染みのある古典コンピューターの論理回路も量子回路をつかって同じようにつくることができます。\n", 97 | "ここの例では大したことは起きていません。8個の量子ビットが準備され、それぞれ0から7番目までの番号が割り振られています。各量子ビットに「測定」のオペレーションが適用されており、この「測定」によって'0'または'1'の値が読み取られます。" 98 | ] 99 | }, 100 | { 101 | "cell_type": "markdown", 102 | "metadata": {}, 103 | "source": [ 104 | "量子ビットは常に0の状態を取るよう初期化されます。そのため、上記回路のように「測定」以外何もしないときは、すべての測定結果は当然'0'になります。Composer左側の'Visualizations'というタブに入って'Status Probabilities'をドロップダウンから選んでください。すると、下記のようなヒストグラムが表示され、すべての量子ビットが'0'を返している様子 (i.e. '00000000')を確認することができます。\n", 105 | "\"image" 107 | ] 108 | }, 109 | { 110 | "cell_type": "markdown", 111 | "metadata": {}, 112 | "source": [ 113 | "'0'以外のビットをエンコードするには、NOTゲートを使います。コンピューターの演算において最も基本的なオペレーションであるNOTゲートは'0'を'1'に、'1'を'0'に反転します。Composerでこれを適用するには、表示されている量子ゲートの中から、Xと表示されている緑色のアイコンを選んで五線譜の上にドラッグ&ドロップします。\n", 114 | "![image of composer3](./fig/composer03.png)" 115 | ] 116 | }, 117 | { 118 | "cell_type": "markdown", 119 | "metadata": {}, 120 | "source": [ 121 | "さきほどのヒストグラムが、今度は'10000000'を出力しているのが確認できます。この回路は8-bitのコンピューターと同じです。\n", 122 | "\"image" 124 | ] 125 | }, 126 | { 127 | "cell_type": "markdown", 128 | "metadata": {}, 129 | "source": [ 130 | "ここで反転させているビットは、量子ビット7番に対してであることにもう一度着目してください。そして出力されたビット列の一番左がそれに対応して'1'に反転しています。(i.e., '10000000') つまり、Composerでは番号の大きい量子ビットほど高い位のビット数に対応しています。こうすることで、,7番目の量子ビットは27がいくつあるのか、6番目の量子ビットは26がいくつあるのか、5番目の量子ビットは25がいくつあるのか、という具合に、量子ビットで数を表現しやすくなります。ここでは7番目の量子ビットを反転させて'1'にするで、27 = 128をこの8-bitコンピューター上で表現することができました。\n", 131 | "(量子計算に関する他のサイトや教科書では、逆の表記方法を提示していることも多くありますが、上記表記法には量子ビットで整数を表現する上でメリットがあるので、Composerを使っているときは番号の大きな量子ビット=高い位のビット数と覚えておきましょう。)" 132 | ] 133 | }, 134 | { 135 | "cell_type": "markdown", 136 | "metadata": {}, 137 | "source": [ 138 | "# 任意の数値を同じ回路でエンコードしてみよう\n" 139 | ] 140 | }, 141 | { 142 | "cell_type": "markdown", 143 | "metadata": {}, 144 | "source": [ 145 | "さて、ここで任意の整数をエンコードしてみましょう。その数字がバイナリではどのように表現されるのかは検索して予め確認しておきましょう。(もし結果に'0b'が含まれていた場合はその2桁は切り捨てて左側に'0'を足して全体を8桁にしましょう)
\n", 146 | "以下は'34'を入力値としてエンコードした場合の回路です。\n", 147 | "![image of composer4](./fig/composer04.png)" 148 | ] 149 | }, 150 | { 151 | "cell_type": "markdown", 152 | "metadata": {}, 153 | "source": [ 154 | "ここまで、量子回路をつかって量子コンピューターにどのように情報を入力(エンコード)できるかをみてきました。次のステップ(Week1の演習)ではどのように実際の演算を行う(入力を組み合わせて出力させる)かについてみていきます。" 155 | ] 156 | } 157 | ], 158 | "metadata": { 159 | "kernelspec": { 160 | "display_name": "Python (Qiskitenv)", 161 | "language": "python", 162 | "name": "qiskitenv" 163 | }, 164 | "language_info": { 165 | "codemirror_mode": { 166 | "name": "ipython", 167 | "version": 3 168 | }, 169 | "file_extension": ".py", 170 | "mimetype": "text/x-python", 171 | "name": "python", 172 | "nbconvert_exporter": "python", 173 | "pygments_lexer": "ipython3", 174 | "version": "3.7.3" 175 | } 176 | }, 177 | "nbformat": 4, 178 | "nbformat_minor": 2 179 | } 180 | -------------------------------------------------------------------------------- /problems/week0/fig/composer01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/problems/week0/fig/composer01.png -------------------------------------------------------------------------------- /problems/week0/fig/composer02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/problems/week0/fig/composer02.png -------------------------------------------------------------------------------- /problems/week0/fig/composer03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/problems/week0/fig/composer03.png -------------------------------------------------------------------------------- /problems/week0/fig/composer04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/problems/week0/fig/composer04.png -------------------------------------------------------------------------------- /problems/week0/fig/composer05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/problems/week0/fig/composer05.png -------------------------------------------------------------------------------- /problems/week0/fig/histogram01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/problems/week0/fig/histogram01.png -------------------------------------------------------------------------------- /problems/week0/fig/histogram02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/problems/week0/fig/histogram02.png -------------------------------------------------------------------------------- /problems/week0/week0.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# IBM Quantum Challenge 基礎の学習" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "本学習は初心者向けに、まずは量子回路をつかった演算の基礎を学ぶことを目的としています。すでに内容を理解されている方は、この教材は飛ばしていただいてかまいません。(当ドキュメントはIBM Q Experienceの[The atoms of computation](https://quantum-computing.ibm.com/support/guides/introduction-to-quantum-circuits?page=5cae6b9d35dafb4c01214bb1#)の抄訳です。)" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "## 量子計算とは?古典計算との比較\n", 22 | "量子計算とは何かを理解するために、まずは私たちが日頃つかっているデジタルコンピューターと比較して考えてみましょう。
\n", 23 | "デジタルコンピューターの計算の仕組みもまた、私たちはほとんど意識することはなくなってきています。そこで、デジタルコンピューター(古典コンピューター)がどのように情報を扱っているのかについてみていきましょう。" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "## すべての情報はビットである\n", 31 | "ビットは世の中のありとあらゆる情報を0または1で表現する情報の最小単位のことです。例えば、私たちが日常的に使用する十進数記法の数字は0, 1, 2, 3, 4, 5, 6, 7, 8. 9の10個の数字の組合せで表現します。各位の値は10の累乗をそれぞれいくつ含んでいるのかを表しています。
\n", 32 | "
\n", 33 | "例として **9213** という数字をみてみましょう。

この数字は9000 + 200 + 10 + 3に分解できます。0~9までの各数字に対して、10の累乗をそれぞれいくつ含んでいるのかをみてみますと、
\n", 34 | "**9213** = **9 x 103 + 2 x 102 + 1 x 101+ 3 x 100** として表現できます。" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "つづいて、同じ数字を二進数をベースに分解してみましょう。0と1の数字に対して、2の累乗をそれぞれいくつ含んでいるかをみてみますと、
\n", 42 | "**9213 = 1 x 213 + 0 x 212 + 0 x 211 + 0 x 210 + 1 x 29 + 1 x 28 + 1 x 27 + 1 x 26 + 1 x 25 + 1 x 24 + 1 x 23 + 1 x 22 + 0 x 21 + 1 x 20**
\n", 43 | "に分解することができることから、9213という数字はバイナリで表現すると **10001111111101** になります。" 44 | ] 45 | }, 46 | { 47 | "cell_type": "markdown", 48 | "metadata": {}, 49 | "source": [ 50 | "任意の数だけではなく、こちらの[テーブル](https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/network/conversion_table.html)にあるように、様々な文字や記号も0と1のバイナリで表すことができます。この対応表は業界の標準として広く採用されており、この記事がインターネットを通じて読者である皆さんに届けられる際にも用いられています。私たちが知っているコンピューターが扱うすべての情報(e.g. 数字、文字、画像、音声, etc.)は、実はこうしたビット列のかたまりであることを改めて覚えておきましょう。" 51 | ] 52 | }, 53 | { 54 | "cell_type": "markdown", 55 | "metadata": {}, 56 | "source": [ 57 | "## 8-bitのコンピューターをIBM Q Experienceでつくってみよう" 58 | ] 59 | }, 60 | { 61 | "cell_type": "markdown", 62 | "metadata": {}, 63 | "source": [ 64 | "量子回路を作成して実行するためのツールにIBM Q Experienceがあります。GUIが五線譜に似ていることから、通称Composerとも呼ばれています。このComposerをつかって8-bitのコンピューターをつくってみましょう。" 65 | ] 66 | }, 67 | { 68 | "cell_type": "markdown", 69 | "metadata": {}, 70 | "source": [ 71 | "1. (まだお済みでない方は)IBM Q Experienceのページから[アカウント作成](https://quantum-computing.ibm.com/)を行います。\n", 72 | "2. 中央のCreate a circuitボタンを押してComposerをたちあげます。\n", 73 | "3. 量子ゲートを直接ドラッグ&ドロップして回路を構築できます。\n", 74 | "4. 左側のエディターを直接編集して回路を構築することも可能です。" 75 | ] 76 | }, 77 | { 78 | "cell_type": "markdown", 79 | "metadata": {}, 80 | "source": [ 81 | "![image of composer](./fig/composer01.png)" 82 | ] 83 | }, 84 | { 85 | "cell_type": "markdown", 86 | "metadata": {}, 87 | "source": [ 88 | "では、量子レジスタと古典レジスタをそれぞれ8個用意して(i.e. qreg[8], creg[8] )、測定用のオペレーター(メーター模様のピンクのゲート)を各量子ビットからのびている線に順番に配置してみましょう。" 89 | ] 90 | }, 91 | { 92 | "cell_type": "markdown", 93 | "metadata": {}, 94 | "source": [ 95 | "![image of composer2](./fig/composer02.png)" 96 | ] 97 | }, 98 | { 99 | "cell_type": "markdown", 100 | "metadata": {}, 101 | "source": [ 102 | "この図で示されているのが、「回路」と呼ばれるものです。回路は線の左から右へと時間発展的に量子ビットの状態を操作するものですが、私たちに馴染みのある古典コンピューターの論理回路も量子回路をつかって同じようにつくることができます。\n", 103 | "ここの例では大したことは起きていません。8個の量子ビットが準備され、それぞれ0から7番目までの番号が割り振られています。各量子ビットに「測定」のオペレーションが適用されており、この「測定」によって'0'または'1'の値が読み取られます。" 104 | ] 105 | }, 106 | { 107 | "cell_type": "markdown", 108 | "metadata": {}, 109 | "source": [ 110 | "量子ビットは常に0の状態を取るよう初期化されます。そのため、上記回路のように「測定」以外何もしないときは、すべての測定結果は当然'0'になります。Composer左側の'Visualizations'というタブに入って'Status Probabilities'をドロップダウンから選んでください。すると、下記のようなヒストグラムが表示され、すべての量子ビットが'0'を返している様子 (i.e. '00000000')を確認することができます。" 111 | ] 112 | }, 113 | { 114 | "cell_type": "markdown", 115 | "metadata": {}, 116 | "source": [ 117 | "\"image" 119 | ] 120 | }, 121 | { 122 | "cell_type": "markdown", 123 | "metadata": {}, 124 | "source": [ 125 | "'0'以外のビットをエンコードするには、NOTゲートを使います。コンピューターの演算において最も基本的なオペレーションであるNOTゲートは'0'を'1'に、'1'を'0'に反転します。Composerでこれを適用するには、表示されている量子ゲートの中から、Xと表示されている緑色のアイコンを選んで五線譜の上にドラッグ&ドロップします。\n", 126 | "\"image" 128 | ] 129 | }, 130 | { 131 | "cell_type": "markdown", 132 | "metadata": {}, 133 | "source": [ 134 | "さきほどのヒストグラムが、今度は'10000000'を出力しているのが確認できます。この回路は8-bitのコンピューターと同じです。\n", 135 | "\"image" 137 | ] 138 | }, 139 | { 140 | "cell_type": "markdown", 141 | "metadata": {}, 142 | "source": [ 143 | "ここで反転させているビットは、量子ビット7番に対してであることにもう一度着目してください。そして出力されたビット列の一番左がそれに対応して'1'に反転しています。(i.e., '10000000') つまり、Composerでは番号の大きい量子ビットほど高い位のビット数に対応しています。こうすることで、7番目の量子ビットは27がいくつあるのか、6番目の量子ビットは26がいくつあるのか、5番目の量子ビットは25がいくつあるのか、という具合に、量子ビットで数を表現しやすくなります。ここでは7番目の量子ビットを反転させて'1'にすることで、27 = 128をこの8-bitコンピューター上で表現することができました。\n", 144 | "(量子計算に関する他のサイトや教科書では、逆の表記方法を提示していることも多くありますが、上記表記法は量子ビットで整数値のバイナリ表現を行う上でメリットがあるため、Composerを使っているときは番号の大きな量子ビット=高い位のビット数と覚えておきましょう。)" 145 | ] 146 | }, 147 | { 148 | "cell_type": "markdown", 149 | "metadata": {}, 150 | "source": [ 151 | "## 任意の数値を同じ回路でエンコードしてみよう" 152 | ] 153 | }, 154 | { 155 | "cell_type": "markdown", 156 | "metadata": {}, 157 | "source": [ 158 | "さて、ここで任意の整数をエンコードしてみましょう。その数字がバイナリではどのように表現されるのかは検索して予め確認しておきましょう。(もし結果に'0b'が含まれていた場合はその2桁は切り捨てて左側に'0'を足して全体を8桁にしましょう)
\n", 159 | "以下は'34'を入力値としてエンコードした場合の回路です。5番目の量子ビットと1番目の量子ビットを反転しています。(i.e. 34 = 1 x 25 + 1 x 21)\n", 160 | "\n", 161 | "\"image" 163 | ] 164 | }, 165 | { 166 | "cell_type": "markdown", 167 | "metadata": {}, 168 | "source": [ 169 | "## Week1の演習に向けて\n", 170 | "ここまで、量子回路をつかって量子コンピューターにどのように情報を入力(エンコード)できるかをみてきました。次のステップ(Week1の演習)ではどのように実際の演算を行うのか(入力を組み合わせて出力させる)についてみていきます。具体的には 1+1といった量子回路における加算器の作り方を学びます。[Week1の演習へ](https://github.com/quantum-challenge/2019/blob/master/problems/week1/week1.ipynb)" 171 | ] 172 | } 173 | ], 174 | "metadata": { 175 | "kernelspec": { 176 | "display_name": "Python (Qiskitenv)", 177 | "language": "python", 178 | "name": "qiskitenv" 179 | }, 180 | "language_info": { 181 | "codemirror_mode": { 182 | "name": "ipython", 183 | "version": 3 184 | }, 185 | "file_extension": ".py", 186 | "mimetype": "text/x-python", 187 | "name": "python", 188 | "nbconvert_exporter": "python", 189 | "pygments_lexer": "ipython3", 190 | "version": "3.7.3" 191 | } 192 | }, 193 | "nbformat": 4, 194 | "nbformat_minor": 2 195 | } 196 | -------------------------------------------------------------------------------- /problems/week1/fig/adder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/problems/week1/fig/adder.png -------------------------------------------------------------------------------- /problems/week2/fig/grover_algorithm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/problems/week2/fig/grover_algorithm.png -------------------------------------------------------------------------------- /problems/week2/fig/oracle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/problems/week2/fig/oracle.png -------------------------------------------------------------------------------- /problems/week2/fig/step0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/problems/week2/fig/step0.png -------------------------------------------------------------------------------- /problems/week2/fig/step1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/problems/week2/fig/step1.png -------------------------------------------------------------------------------- /problems/week2/fig/step2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/problems/week2/fig/step2.png -------------------------------------------------------------------------------- /problems/week2/fig/unstructured_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/problems/week2/fig/unstructured_search.png -------------------------------------------------------------------------------- /problems/week3/maxcut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/problems/week3/maxcut.png -------------------------------------------------------------------------------- /qcc_banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/qcc_banner.png -------------------------------------------------------------------------------- /top ten submissions/42Robotics/readme.txt: -------------------------------------------------------------------------------- 1 | #IBM Quantum Challenge 2019 2 | #Instructions for top ten teams for preparing their illustrative explanation of their submissions. 3 | 4 | Dear Team, 5 | 6 | Congratulations for making it into the top ten teams of IBM Quantum Challenge! 7 | 8 | Judges have reviewed your submissions and have verified your final score. We will be making an official announcement next week to show the final standings. 9 | 10 | In the meantime, we are asking all top ten teams to: 11 | 12 | 13 | -Prepare a write-up on how your team obtained the answers for the final challenge. 14 | 15 | -You may either add explanations to your ipynb file OR provide detailed comments in your .py file. 16 | 17 | -While we do not have a specific format for you to follow, we would like to ask you to focus on providing an illustrative explanation of your strategy, approach, techniques (creativity) you used to achieve lower quantum costs. 18 | 19 | -A folder saying 'top ten submissions' will be prepared in the github repository containing another set of folders each named after your teams. Please push your write-ups into these folders by Monday Oct 21st, noon JST. 20 | 21 | 22 | IBM Quantum Challenge Organizers -------------------------------------------------------------------------------- /top ten submissions/Costs > 100k/optimized_triangle_compare_v10.py: -------------------------------------------------------------------------------- 1 | # Team name: Costs > 100k 2 | # Team Members: 3 | # Ji Liu (jliu45@ncsu.edu) and Zachary Johnston (ztjohnst@ncsu.edu) 4 | from qiskit import IBMQ 5 | from qiskit.compiler import transpile 6 | from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister 7 | from qiskit.transpiler import PassManager 8 | from qiskit.transpiler.passes import Unroller 9 | from qiskit import execute 10 | from qiskit import BasicAer 11 | from qiskit.tools.visualization import plot_state_city 12 | from qiskit.tools.visualization import plot_histogram 13 | from qiskit.tools.visualization import circuit_drawer 14 | from qiskit.aqua.circuits.gates import mct 15 | import sys 16 | import numpy as np 17 | from collections import Counter 18 | from qiskit.quantum_info.operators import Operator, Pauli 19 | np.set_printoptions(threshold=sys.maxsize) 20 | 21 | 22 | def bit_compare(circ,q): 23 | ''' 24 | Logic to see if two vertices are colored differently. 25 | ''' 26 | circ.cx(q[0],q[4]) 27 | circ.cx(q[2],q[4]) 28 | circ.cx(q[1],q[5]) 29 | circ.cx(q[3],q[5]) 30 | 31 | def bit_compare_inverse(circ,q): 32 | ''' 33 | This inverts bit_compare 34 | ''' 35 | circ.cx(q[3],q[5]) 36 | circ.cx(q[1],q[5]) 37 | circ.cx(q[2],q[4]) 38 | circ.cx(q[0],q[4]) 39 | 40 | def and_gate(circ,q): 41 | circ.ccx(q[0],q[1],q[2]) 42 | return q[2] 43 | 44 | def triangle_compare_2edge_dirty(circ,v1,v2,v3,ancilla_bits,output_bit): 45 | ''' 46 | Does the triangle compare optimization, but only for two edges. It also leaves the ancilla bits dirty. 47 | ''' 48 | ancilla_list = [ancilla_bits[0],ancilla_bits[1],output_bit] 49 | circ.x(output_bit) 50 | vertex_compare(circ, v1 + v3, ancilla_bits, output_bit) 51 | vertex_compare_dirty(circ, v2 + v3, ancilla_bits, output_bit) 52 | 53 | 54 | 55 | def triangle_compare_2edge_dirty_inverse(circ,v1,v2,v3,ancilla_bits,output_bit): 56 | ''' 57 | Inverts triangle_compare_2edge_dirty 58 | ''' 59 | ancilla_list = [ancilla_bits[0],ancilla_bits[1],output_bit] 60 | vertex_compare_dirty_inverse(circ, v2 + v3, ancilla_bits, output_bit) 61 | vertex_compare(circ, v1 + v3, ancilla_bits, output_bit) 62 | circ.x(output_bit) 63 | 64 | def triangle_compare_dirty(circ,v1,v2,v3,ancilla_bits,output_bit): 65 | ''' 66 | Performs triangle compare for all edges in a triangle, and leaves the ancilla bits dirty. 67 | ''' 68 | ancilla_list = [ancilla_bits[0],ancilla_bits[1],output_bit] 69 | bit_compare(circ,v1+v2+ancilla_bits[0:2]) 70 | and_gate(circ,ancilla_list) 71 | bit_compare_inverse(circ,v1+v2+ancilla_bits[0:2]) 72 | 73 | bit_compare(circ,v1+v3+ancilla_bits[0:2]) 74 | and_gate(circ,ancilla_list) 75 | bit_compare_inverse(circ,v1+v3+ancilla_bits[0:2]) 76 | 77 | bit_compare(circ,v3+v2+ancilla_bits[0:2]) 78 | and_gate(circ,ancilla_list) 79 | return output_bit[0] 80 | 81 | 82 | def triangle_compare_dirty_inverse(circ,v1,v2,v3,ancilla_bits,output_bit): 83 | ''' 84 | Inverts triangle_compare_dirty 85 | ''' 86 | ancilla_list = [ancilla_bits[0],ancilla_bits[1],output_bit] 87 | and_gate(circ,ancilla_list) 88 | bit_compare_inverse(circ,v3+v2+ancilla_bits[0:2]) 89 | 90 | bit_compare(circ,v1+v3+ancilla_bits[0:2]) 91 | and_gate(circ,ancilla_list) 92 | bit_compare_inverse(circ,v1+v3+ancilla_bits[0:2]) 93 | 94 | bit_compare(circ,v1+v2+ancilla_bits[0:2]) 95 | and_gate(circ,ancilla_list) 96 | bit_compare_inverse(circ,v1+v2+ancilla_bits[0:2]) 97 | 98 | def vertex_compare(circ,q,ancilla_bits,output_bit): 99 | ''' 100 | This compares two vertices that are connected with an edge. 101 | The output bit is 0 when the two vertices are the same. 102 | ''' 103 | bit_compare(circ,q[0:4]+ancilla_bits[0:2]) 104 | circ.x(ancilla_bits[0]) 105 | circ.x(ancilla_bits[1]) 106 | circ.ccx(ancilla_bits[0], ancilla_bits[1],output_bit) 107 | circ.x(ancilla_bits[0]) 108 | circ.x(ancilla_bits[1]) 109 | circ.x(output_bit) 110 | bit_compare_inverse(circ,q[0:4]+ancilla_bits[0:2]) 111 | return output_bit 112 | 113 | def vertex_compare_inverse(circ,q,ancilla_bits,output_bit): 114 | ''' 115 | Inverts vertex_compare 116 | ''' 117 | bit_compare(circ,q[0:4]+ancilla_bits[0:2]) 118 | circ.x(output_bit) 119 | circ.x(ancilla_bits[0]) 120 | circ.x(ancilla_bits[1]) 121 | circ.ccx(ancilla_bits[0], ancilla_bits[1],output_bit) 122 | circ.x(ancilla_bits[0]) 123 | circ.x(ancilla_bits[1]) 124 | bit_compare_inverse(circ,q[0:4]+ancilla_bits[0:2]) 125 | return output_bit 126 | 127 | def vertex_compare_dirty(circ,q,ancilla_bits,output_bit): 128 | ''' 129 | This is the same as vertex_compare, but it leaves the ancilla bits dirty. 130 | ''' 131 | bit_compare(circ,q[0:4]+ancilla_bits[0:2]) 132 | circ.x(ancilla_bits[0]) 133 | circ.x(ancilla_bits[1]) 134 | circ.ccx(ancilla_bits[0], ancilla_bits[1],output_bit) 135 | circ.x(output_bit) 136 | return output_bit 137 | 138 | def vertex_compare_dirty_inverse(circ,q,ancilla_bits,output_bit): 139 | ''' 140 | Inverts vertex_compare_dirty 141 | ''' 142 | circ.x(output_bit) 143 | circ.ccx(ancilla_bits[0], ancilla_bits[1],output_bit) 144 | circ.x(ancilla_bits[0]) 145 | circ.x(ancilla_bits[1]) 146 | bit_compare_inverse(circ,q[0:4]+ancilla_bits[0:2]) 147 | return output_bit 148 | 149 | def B_triangle(circ,v,output_bit): 150 | ''' 151 | This is the logic for the edges around the B vertex initial condition. 152 | ''' 153 | circ.x(v[0]) 154 | circ.ccx(v[0],v[1],output_bit) 155 | circ.x(v[0]) 156 | 157 | def D_triangle(circ,v,output_bit): 158 | ''' 159 | This is the logic for the edges around the D vertex initial condition. 160 | ''' 161 | circ.ccx(v[0],v[1],output_bit) 162 | 163 | def triangle_compare_B_dirty(circ,v0,v2,ancilla_bits,output_bit): 164 | ''' 165 | This is the logic for the triangle around the B vertex initial condition. 166 | This function also leaves the ancilla bits dirty. 167 | ''' 168 | B_triangle(circ,v0,output_bit) 169 | B_triangle(circ,v2,output_bit) 170 | vertex_compare_dirty(circ,v0+v2,ancilla_bits,output_bit) 171 | 172 | def triangle_compare_B_dirty_inverse(circ,v0,v2,ancilla_bits,output_bit): 173 | ''' 174 | Inverts triangle_compare_B_dirty 175 | ''' 176 | vertex_compare_dirty_inverse(circ,v0+v2,ancilla_bits,output_bit) 177 | B_triangle(circ,v2,output_bit) 178 | B_triangle(circ,v0,output_bit) 179 | 180 | def triangle_compare_D_dirty(circ,v0,v2,ancilla_bits,output_bit): 181 | ''' 182 | This is the logic for the triangle around the D vertex initial condition. 183 | ''' 184 | D_triangle(circ,v0,output_bit) 185 | D_triangle(circ,v2,output_bit) 186 | vertex_compare_dirty(circ,v0+v2,ancilla_bits,output_bit) 187 | 188 | def triangle_compare_D_dirty_inverse(circ,v0,v2,ancilla_bits,output_bit): 189 | ''' 190 | Inverts triangle_compare_D_dirty 191 | ''' 192 | vertex_compare_dirty_inverse(circ,v0+v2,ancilla_bits,output_bit) 193 | D_triangle(circ,v2,output_bit) 194 | D_triangle(circ,v0,output_bit) 195 | 196 | def inversion_about_average(circ,q,ancilla_bits): 197 | ''' 198 | This is the inversion about the average amplitude in Grover's alorithm. 199 | ''' 200 | circ.h(q[8:]) 201 | circ.x(q[8:]) 202 | circ.h(q[13]) 203 | circ.mct(q[8:13],q[13],ancilla_bits,mode="basic") 204 | circ.h(q[13]) 205 | circ.x(q[8:]) 206 | circ.h(q[8:]) 207 | 208 | def encode_0123(circ, v0,v1, v2, v3): 209 | ''' 210 | This function propagates the initial conditions by creating a constrained 211 | superposition of colors for certain vertices. 212 | ''' 213 | # Contraints for vertex 2 214 | circ.x(v2[1]) 215 | circ.h(v2[0]) 216 | 217 | # Contraints for vertex 0 and 3 218 | circ.h(v0[1]) 219 | circ.cx(v0[1], v3[0]) 220 | circ.x(v0[1]) 221 | circ.cx(v0[1], v0[0]) 222 | circ.x(v0[1]) 223 | circ.cx(v0[0], v3[1]) 224 | circ.x(v2[0]) 225 | circ.ccx(v2[0], v0[1], v0[0]) 226 | circ.ccx(v2[0], v3[1], v3[0]) 227 | circ.x(v2[0]) 228 | 229 | # Contraints for vertex 1 230 | circ.ch(v2[0],v1[1]) 231 | circ.cx(v1[1],v1[0]) 232 | 233 | 234 | q = QuantumRegister(14,'q') 235 | ancilla_bits = QuantumRegister(11,'ab') 236 | input_bit = QuantumRegister(1,'i') 237 | output_bit = QuantumRegister(4,'o') 238 | check_bit = QuantumRegister(2,'cb') 239 | c = ClassicalRegister(14,'c') 240 | 241 | circ = QuantumCircuit(q,ancilla_bits,input_bit,output_bit,check_bit,c) 242 | 243 | circ.h(q[8:]) # Create equal superposition for vertices with no constraints. 244 | 245 | encode_0123(circ, q[0:2],q[2:4], q[4:6], q[6:8]) # Apply constraints 246 | 247 | # Explaination of the optimizations we used 248 | ''' 249 | Triangle optimization explaination: 250 | We noticed that when the graph creates a triangle there is either 1 edge with an error, or all edges have an error. 251 | So, our triangle_compare functions use this assumption to reduce the number of output qubits needed. 252 | Each traingle only needs 1 output qubit that represents error (0) or no error (1). 253 | This ultimate shrinks the MCT comparison that is made after the edge compare to detect if there are any errors. 254 | ''' 255 | 256 | ''' 257 | Graph Reduction optimization: 258 | Since we were given initial condition in this problem. You can propagate those condition inward on the graph, 259 | and not have to check as many edges. For example, if you look at the A,2,C part of the graph, vertex 2 260 | can only be B or D. So, you can Hadamard the LSB and NOT gate the MSB. Then you don't have to check the 261 | edges between 2,A and 2,C. 262 | ''' 263 | 264 | ''' 265 | Other optimizations: 266 | Since the two optimization above freed up a lot of qubits. We were able to leave a lot of dirty ancilla qubits. 267 | This reduces the cost since we don't have to invert the computation to clean up ancilla bits. 268 | ''' 269 | 270 | for i in range(0,5): 271 | # Comparison for triangle 5,6,D. 272 | triangle_compare_D_dirty(circ,q[10:12],q[12:14],check_bit[0:2],output_bit[0]) 273 | # Comparison for triangle 1,4,B. 274 | triangle_compare_B_dirty(circ,q[2:4],q[8:10],[output_bit[1]] + [output_bit[3]],output_bit[2]) 275 | # Comparison for 2 edges 1,5 and 2,5 in the triangle 1,2,5. 276 | triangle_compare_2edge_dirty(circ,q[4:6],q[6:8],q[10:12],ancilla_bits[6:8],ancilla_bits[10]) 277 | # Comparison for last triangle left over, which is 3,4,6. 278 | triangle_compare_dirty(circ,q[6:8],q[8:10],q[12:14],ancilla_bits[4:6],ancilla_bits[9]) 279 | 280 | # Comparison for egde between 2 and 6. 281 | vertex_compare_dirty(circ,q[4:6]+q[12:14],ancilla_bits[2:4],ancilla_bits[8]) 282 | 283 | # Invert the phase for the correct colorings. 284 | circ.h(ancilla_bits[8]) 285 | circ.mct([output_bit[0],output_bit[2],ancilla_bits[10],ancilla_bits[9]],ancilla_bits[8],[ancilla_bits[0], ancilla_bits[1]],mode='basic') 286 | circ.h(ancilla_bits[8]) 287 | 288 | # Invert the comparison 289 | vertex_compare_dirty_inverse(circ,q[4:6]+q[12:14],ancilla_bits[2:4],ancilla_bits[8]) 290 | triangle_compare_dirty_inverse(circ,q[6:8],q[8:10],q[12:14],ancilla_bits[4:6],ancilla_bits[9]) 291 | triangle_compare_2edge_dirty_inverse(circ,q[4:6],q[6:8],q[10:12],ancilla_bits[6:8],ancilla_bits[10]) 292 | triangle_compare_B_dirty_inverse(circ,q[2:4],q[8:10],[output_bit[1]] + [output_bit[3]],output_bit[2]) 293 | triangle_compare_D_dirty_inverse(circ,q[10:12],q[12:14],check_bit[0:2],output_bit[0]) 294 | 295 | # Perform inversion about the average amplitude. 296 | inversion_about_average(circ,q,ancilla_bits) 297 | 298 | for x in range(0, 7): 299 | circ.measure(q[2*x],c[2*x]) 300 | circ.measure(q[(2*x)+1],c[2*x + 1]) 301 | 302 | 303 | provider = IBMQ.load_account() 304 | backend = provider.get_backend('ibmq_qasm_simulator') 305 | job = execute(circ, backend=backend, shots=8000, seed_simulator=12345, backend_options={"fusion_enable":True}) 306 | result = job.result() 307 | count = result.get_counts() 308 | print(count) 309 | 310 | print(circ) 311 | 312 | k = Counter(count) 313 | 314 | high = k.most_common(9) 315 | 316 | 317 | print(high) 318 | 319 | 320 | # Cost 321 | pass_ = Unroller(['u3','cx']) 322 | pm = PassManager(pass_) 323 | new_circuit = pm.run(circ) 324 | unrolled = new_circuit.count_ops() 325 | print(unrolled) 326 | 327 | cost = unrolled['u3']*1 + unrolled['cx']*10 328 | print("Circuit cost: ",cost) 329 | 330 | 331 | # Input your quantum circuit 332 | #circuit='Input your circuit' 333 | circuit=circ 334 | # Input your result of the execute(groverCircuit, backend=backend, shots=shots).result() 335 | #results = 'Input your result' 336 | results = result 337 | count=results.get_counts() 338 | # Provide your team name 339 | name='Costs > 100k' 340 | # Please indicate the number of times you have made a submission so far. 341 | # For example, if it's your 1st time to submit your answer, write 1. If it's your 5th time to submit your answer, write 5. 342 | times='14' 343 | 344 | import json 345 | from qiskit.transpiler import PassManager 346 | from qiskit.transpiler.passes import Unroller 347 | 348 | # Unroll the circuit 349 | pass_ = Unroller(['u3', 'cx']) 350 | pm = PassManager(pass_) 351 | new_circuit = pm.run(circuit) 352 | 353 | # obtain gates 354 | gates=new_circuit.count_ops() 355 | 356 | #sort count 357 | count_sorted = sorted(count.items(), key=lambda x:x[1], reverse=True) 358 | 359 | # collect answers with Top 9 probability 360 | ans_list = count_sorted[0:9] 361 | 362 | # reverse ans_list 363 | ans_reversed = [] 364 | for i in ans_list: 365 | ans_temp=[i[0][::-1],i[1]] 366 | ans_reversed.append(ans_temp) 367 | 368 | # convert each 2 bits into corresponding color. Add node0(0),node3(1),node8(2) and node11(3) 369 | ans_shaped = [] 370 | for j in ans_reversed: 371 | ans_temp=j[0] 372 | nodeA = 0 373 | node0 = int(ans_temp[0] + ans_temp[1], 2) 374 | node1 = int(ans_temp[2] + ans_temp[3], 2) 375 | nodeB = 1 376 | node2 = int(ans_temp[4] + ans_temp[5], 2) 377 | node3 = int(ans_temp[6] + ans_temp[7], 2) 378 | node4 = int(ans_temp[8] + ans_temp[9], 2) 379 | nodeC = 2 380 | node5 = int(ans_temp[10] + ans_temp[11], 2) 381 | node6 = int(ans_temp[12] + ans_temp[13], 2) 382 | nodeD = 3 383 | nodes_color = str(nodeA) + str(node0) + str(node1) + str(nodeB) + str(node2) + str(node3) + str(node4) + str(nodeC) + str(node5) + str(node6) + str(nodeD) 384 | if node0 == 0 or node0 == node1 or node0 == node2 or node0 == node3 or node1 == 1 or node1 == node4 or node1 == node3 or node2 == 0 or node2 == node3 or node2 == node5 or node2 == node6 or node2 == 2 or node5 == node3 or node5 == 3 or node5 == node6 or node6 == 3 or node6 == node3 or node6 == node4 or node4 == node3 or node4 == 1: 385 | print("ERROR! " + nodes_color) 386 | ans_shaped.append([nodes_color,j[1]]) 387 | 388 | # write the result into '[your name]_final_output.txt' 389 | 390 | filename=name+'_'+times+'_final_output.txt' 391 | dct={'ans':ans_shaped,'costs':gates} 392 | with open(filename, 'w') as f: 393 | json.dump(dct, f) 394 | -------------------------------------------------------------------------------- /top ten submissions/Costs > 100k/readme.txt: -------------------------------------------------------------------------------- 1 | #IBM Quantum Challenge 2019 2 | #Instructions for top ten teams for preparing their illustrative explanation of their submissions. 3 | 4 | Dear Team, 5 | 6 | Congratulations for making it into the top ten teams of IBM Quantum Challenge! 7 | 8 | Judges have reviewed your submissions and have verified your final score. We will be making an official announcement next week to show the final standings. 9 | 10 | In the meantime, we are asking all top ten teams to: 11 | 12 | 13 | -Prepare a write-up on how your team obtained the answers for the final challenge. 14 | 15 | -You may either add explanations to your ipynb file OR provide detailed comments in your .py file. 16 | 17 | -While we do not have a specific format for you to follow, we would like to ask you to focus on providing an illustrative explanation of your strategy, approach, techniques (creativity) you used to achieve lower quantum costs. 18 | 19 | -A folder saying 'top ten submissions' will be prepared in the github repository containing another set of folders each named after your teams. Please push your write-ups into these folders by Monday Oct 21st, noon JST. 20 | 21 | 22 | IBM Quantum Challenge Organizers -------------------------------------------------------------------------------- /top ten submissions/DokiDokiQuantumClub/readme.txt: -------------------------------------------------------------------------------- 1 | #IBM Quantum Challenge 2019 2 | #Instructions for top ten teams for preparing their illustrative explanation of their submissions. 3 | 4 | Dear Team, 5 | 6 | Congratulations for making it into the top ten teams of IBM Quantum Challenge! 7 | 8 | Judges have reviewed your submissions and have verified your final score. We will be making an official announcement next week to show the final standings. 9 | 10 | In the meantime, we are asking all top ten teams to: 11 | 12 | 13 | -Prepare a write-up on how your team obtained the answers for the final challenge. 14 | 15 | -You may either add explanations to your ipynb file OR provide detailed comments in your .py file. 16 | 17 | -While we do not have a specific format for you to follow, we would like to ask you to focus on providing an illustrative explanation of your strategy, approach, techniques (creativity) you used to achieve lower quantum costs. 18 | 19 | -A folder saying 'top ten submissions' will be prepared in the github repository containing another set of folders each named after your teams. Please push your write-ups into these folders by Monday Oct 21st, noon JST. 20 | 21 | 22 | IBM Quantum Challenge Organizers -------------------------------------------------------------------------------- /top ten submissions/Gate42/Gate42_3_final_output.txt: -------------------------------------------------------------------------------- 1 | {"ans": [["02313102023", 241], ["02013132023", 234], ["02013122203", 233], ["02011322203", 231], ["02013132203", 225], ["01013232013", 224], ["02313122203", 218], ["01313202013", 218], ["01013232103", 217]], "costs": {"u3": 5905, "cx": 3155, "measure": 14}} 2 | -------------------------------------------------------------------------------- /top ten submissions/IIQ@QIC/IIQ@QIC-WriteUp.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Submission of Team *IIQ@QIC*\n", 8 | "\n", 9 | "We are the team \"IIQ@QIC\" from the [Johannes Kepler University Linz (JKU)](http://iic.jku.at/eda/research/quantum/). \n", 10 | "This jupyter notebook describes the essential parts of our submitted Python script, i.e., the code building the circuit without the parts that submit the circuit to IBMQ and create the answer file. \n", 11 | "We would like to thank the people at IBM and Anglehack for organizing the challenge, which was great fun and deepened our understanding of quantum computing.\n", 12 | "\n", 13 | "\n", 14 | "For the problem at hand, we organized the 32 available qubits in the following layout `[start:end)`:\n", 15 | "```\n", 16 | " 0:14 input qubits representing the color of each node\n", 17 | " 14:17 \"tree\" ancillae\n", 18 | " 15:22 \"mct ancillae\"\n", 19 | " 22:31 interim targets\n", 20 | " 31:32 final target (a single qubit)\n", 21 | "(18:29 ancillae for the diffusion phase)\n", 22 | "```\n", 23 | "## Python Preparation\n", 24 | "\n", 25 | "The following snippet shows the preparations required to run the code.\n", 26 | "\n", 27 | "First, the necessary packages are imported from Qiskit and the standard library." 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": 1, 33 | "metadata": {}, 34 | "outputs": [], 35 | "source": [ 36 | "from qiskit import execute, IBMQ\n", 37 | "from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit\n", 38 | "from qiskit.qasm import pi\n", 39 | "from qiskit.transpiler import PassManager\n", 40 | "from qiskit.transpiler.passes import Unroller\n", 41 | "\n", 42 | "from typing import Tuple, Sequence" 43 | ] 44 | }, 45 | { 46 | "cell_type": "markdown", 47 | "metadata": {}, 48 | "source": [ 49 | "In order to have meaningful type hints and to avoid magic numbers, the following constants are defined." 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "execution_count": 2, 55 | "metadata": {}, 56 | "outputs": [], 57 | "source": [ 58 | "# Type names\n", 59 | "Node = int\n", 60 | "Qubit = int\n", 61 | "# Constants to distinguish kombini brands\n", 62 | "A = 10\n", 63 | "B = 11\n", 64 | "C = 12\n", 65 | "D = 13\n", 66 | "AC = 14" 67 | ] 68 | }, 69 | { 70 | "cell_type": "markdown", 71 | "metadata": {}, 72 | "source": [ 73 | "## Building Blocks of our Approach\n", 74 | "\n", 75 | "The methods provided by Qiskit have to work in the general case, which wasn't what we strictly needed in our approach.\n", 76 | "Therefore we optimized these methods to suit our needs while incurring less costs.\n", 77 | "\n", 78 | "In the following, we have implemented the [CCX](https://github.com/Qiskit/qiskit-terra/blob/e0e6da5b293807fa1a264e1b29b33fb6188d010e/qiskit/extensions/standard/ccx.py#L85) and [MCT](https://github.com/Qiskit/qiskit-aqua/blob/b9bfa31d01d2cb87475aae077ee52fe2c12775e9/qiskit/aqua/circuits/gates/multi_control_toffoli_gate.py#L32) operations, that ensure the correct phase, based on the code available in Qiskit." 79 | ] 80 | }, 81 | { 82 | "cell_type": "code", 83 | "execution_count": 3, 84 | "metadata": {}, 85 | "outputs": [], 86 | "source": [ 87 | "def ccx_opt(qc: QuantumCircuit, a: Qubit, b: Qubit, target: Qubit) -> None:\n", 88 | " qc.cx(b, target)\n", 89 | " qc.tdg(target)\n", 90 | " qc.cx(a, target)\n", 91 | " qc.t(target)\n", 92 | " qc.cx(b, target)\n", 93 | " qc.tdg(target)\n", 94 | " qc.cx(a, target)\n", 95 | " qc.t(b)\n", 96 | " qc.t(target)\n", 97 | " qc.cx(a, b)\n", 98 | " qc.t(a)\n", 99 | " qc.tdg(b)\n", 100 | " qc.cx(a, b)" 101 | ] 102 | }, 103 | { 104 | "cell_type": "code", 105 | "execution_count": 4, 106 | "metadata": {}, 107 | "outputs": [], 108 | "source": [ 109 | "def my_mct_v_chain(qc: QuantumCircuit, control_qubits: Sequence[Qubit], target_qubit: Qubit, ancillary_qubits: Sequence[Qubit]) -> None:\n", 110 | " if len(ancillary_qubits) < len(control_qubits) - 2:\n", 111 | " raise ValueError('Insufficient number of ancillary qubits.')\n", 112 | "\n", 113 | " anci_idx = 0\n", 114 | " qc.z(ancillary_qubits[anci_idx])\n", 115 | " rccx_opt(qc, control_qubits[0], control_qubits[1], ancillary_qubits[anci_idx], \"left\")\n", 116 | " for idx in range(2, len(control_qubits) - 1):\n", 117 | " if anci_idx == 0:\n", 118 | " qc.z(ancillary_qubits[anci_idx + 1])\n", 119 | " rccx_opt(qc, control_qubits[idx], ancillary_qubits[anci_idx], ancillary_qubits[anci_idx + 1], \"left\")\n", 120 | " else:\n", 121 | " rccx_opt(qc, control_qubits[idx], ancillary_qubits[anci_idx], ancillary_qubits[anci_idx + 1], \"left\")\n", 122 | " anci_idx += 1\n", 123 | "\n", 124 | " ccx_opt(qc, control_qubits[len(control_qubits) - 1], ancillary_qubits[anci_idx], target_qubit)\n", 125 | "\n", 126 | " for idx in reversed(range(2, len(control_qubits) - 1)):\n", 127 | " if anci_idx == 1:\n", 128 | " rccx_opt(qc, control_qubits[idx], ancillary_qubits[anci_idx - 1], ancillary_qubits[anci_idx], \"right\")\n", 129 | " qc.z(ancillary_qubits[anci_idx])\n", 130 | " else:\n", 131 | " rccx_opt(qc, control_qubits[idx], ancillary_qubits[anci_idx - 1], ancillary_qubits[anci_idx], \"right\")\n", 132 | " anci_idx -= 1\n", 133 | " rccx_opt(qc, control_qubits[0], control_qubits[1], ancillary_qubits[anci_idx], \"right\")\n", 134 | " qc.z(ancillary_qubits[anci_idx])" 135 | ] 136 | }, 137 | { 138 | "attachments": {}, 139 | "cell_type": "markdown", 140 | "metadata": {}, 141 | "source": [ 142 | "In addition to CCX/MCT above, we also took the Qiskit code and implemented versions of those functions that are cheaper but are only correct up to the relative phase ([`rccx`](https://github.com/Qiskit/qiskit-aqua/blob/b9bfa31d01d2cb87475aae077ee52fe2c12775e9/qiskit/aqua/circuits/gates/relative_phase_toffoli.py#L60)).\n", 143 | "These implementations take an additional parameter which describes the `side`it is applied on. \n", 144 | "\n", 145 | "Consider the following illustration, which shows how to check that nodes 0 and 1 as well as 2 and 3 are different, respectively. Specifying the side allows to omit the gates highlighted in red, as they would cancel each other anyway.\n", 146 | "\n", 147 | "**Figure 1**: ![side.png](fig/side.png)" 148 | ] 149 | }, 150 | { 151 | "cell_type": "code", 152 | "execution_count": 5, 153 | "metadata": {}, 154 | "outputs": [], 155 | "source": [ 156 | "def rccx_opt(qc: QuantumCircuit, a: Qubit, b: Qubit, target: Qubit, side:str=\"both\") -> None:\n", 157 | " if side in (\"both\", \"right\"):\n", 158 | " qc.u2(pi / 4, pi, target) # -H-T-\n", 159 | " qc.cx(b, target)\n", 160 | " qc.tdg(target)\n", 161 | " qc.cx(a, target)\n", 162 | " qc.t(target)\n", 163 | " qc.cx(b, target)\n", 164 | " if side in (\"both\", \"left\"):\n", 165 | " qc.u2(0, 3 * pi / 4, target) # -Tdg-H-" 166 | ] 167 | }, 168 | { 169 | "cell_type": "code", 170 | "execution_count": 6, 171 | "metadata": {}, 172 | "outputs": [], 173 | "source": [ 174 | "def my_rmct_v_chain(qc: QuantumCircuit, control_qubits: Sequence[Qubit], target_qubit: Qubit, ancillary_qubits: Sequence[Qubit], side: str=\"both\") -> None:\n", 175 | " if len(ancillary_qubits) < len(control_qubits) - 2:\n", 176 | " raise ValueError('Insufficient number of ancillary qubits.')\n", 177 | " \n", 178 | " anci_idx = 0\n", 179 | " rccx_opt(qc, control_qubits[0], control_qubits[1], ancillary_qubits[anci_idx], \"left\")\n", 180 | " for idx in range(2, len(control_qubits) - 1):\n", 181 | " rccx_opt(qc, control_qubits[idx], ancillary_qubits[anci_idx], ancillary_qubits[anci_idx + 1])\n", 182 | " anci_idx += 1\n", 183 | "\n", 184 | " rccx_opt(qc, control_qubits[len(control_qubits) - 1], ancillary_qubits[anci_idx], target_qubit, side)\n", 185 | "\n", 186 | " for idx in reversed(range(2, len(control_qubits) - 1)):\n", 187 | " rccx_opt(qc, control_qubits[idx], ancillary_qubits[anci_idx - 1], ancillary_qubits[anci_idx])\n", 188 | " anci_idx -= 1\n", 189 | " rccx_opt(qc, control_qubits[0], control_qubits[1], ancillary_qubits[anci_idx], \"right\")" 190 | ] 191 | }, 192 | { 193 | "cell_type": "markdown", 194 | "metadata": {}, 195 | "source": [ 196 | "## Constraining Possible Results\n", 197 | "\n", 198 | "Given the building blocks introduced above, the following functions encode the constraints of the problem in a bottom-up fashion. \n", 199 | "First we define functions that ensure a node is different from a fixed *A*, *B*, *C*, or *D* (or *AC* for node 2) as well as a function that ensures two given nodes are assigned different colors/brands." 200 | ] 201 | }, 202 | { 203 | "cell_type": "code", 204 | "execution_count": 7, 205 | "metadata": {}, 206 | "outputs": [], 207 | "source": [ 208 | "def aXor(a: Sequence[Qubit], target: Qubit, side: str) -> None:\n", 209 | " rccx_opt(qc, a[0], a[1], target, side)\n", 210 | "\n", 211 | "\n", 212 | "def bXor(a: Sequence[Qubit], target: Qubit, side: str) -> None:\n", 213 | " if side in (\"left\"):\n", 214 | " qc.x(a[0])\n", 215 | "\n", 216 | " rccx_opt(qc, a[0], a[1], target, side)\n", 217 | "\n", 218 | " if side in (\"right\"):\n", 219 | " qc.x(a[0])\n", 220 | "\n", 221 | "\n", 222 | "def cXor(a: Sequence[Qubit], target: Qubit, side: str) -> None:\n", 223 | " if side in (\"left\"):\n", 224 | " qc.x(a[1])\n", 225 | "\n", 226 | " rccx_opt(qc, a[0], a[1], target, side)\n", 227 | "\n", 228 | " if side in (\"right\"):\n", 229 | " qc.x(a[1])\n", 230 | "\n", 231 | "\n", 232 | "def dXor(a: Sequence[Qubit], target: Qubit, side: str) -> None:\n", 233 | " rccx_opt(qc, a[0], a[1], target, side)\n", 234 | "\n", 235 | "\n", 236 | "def acXor(a: Sequence[Qubit], target: Qubit, side: str) -> None:\n", 237 | " if side in (\"left\"):\n", 238 | " qc.x(a[1])\n", 239 | " qc.cx(a[1], target)\n", 240 | " if side in (\"right\"):\n", 241 | " qc.x(a[1])" 242 | ] 243 | }, 244 | { 245 | "attachments": {}, 246 | "cell_type": "markdown", 247 | "metadata": {}, 248 | "source": [ 249 | "Given qubits representing nodes *a* and *b*, their colors/brands are different if $(a_0 \\oplus b_0) \\lor (a_1 \\oplus b_1)$. \n", 250 | "The circuit representation is shown in the following:\n", 251 | "\n", 252 | "**Figure 2**: ![value_xor.png](fig/value_xor.png)\n", 253 | "\n", 254 | "Note this does not require any ancillary qubits and the effects of the computation are *uncomputed* afterwards to restore the previous state.\n", 255 | "The function below has an additional parameter `side` to save gates in the same fashion as explained for the building blocks above." 256 | ] 257 | }, 258 | { 259 | "cell_type": "code", 260 | "execution_count": 8, 261 | "metadata": {}, 262 | "outputs": [], 263 | "source": [ 264 | "def valueXor_noancilla(a: Sequence[Qubit], b: Sequence[Qubit], target: Qubit, side: str):\n", 265 | " if side == \"left\":\n", 266 | " qc.cx(a[0], b[0])\n", 267 | " qc.cx(a[1], b[1])\n", 268 | "\n", 269 | " if b != [q[6], q[7]]:\n", 270 | " qc.x(b[0])\n", 271 | " qc.x(b[1])\n", 272 | "\n", 273 | " rccx_opt(qc, b[0], b[1], target, side)\n", 274 | " elif side == \"right\":\n", 275 | " rccx_opt(qc, b[0], b[1], target, side)\n", 276 | "\n", 277 | " if b != [q[6], q[7]]:\n", 278 | " qc.x(b[1])\n", 279 | " qc.x(b[0])\n", 280 | "\n", 281 | " qc.cx(a[1], b[1])\n", 282 | " qc.cx(a[0], b[0])\n", 283 | " else:\n", 284 | " raise ValueError(\"side was neither left nor right\")" 285 | ] 286 | }, 287 | { 288 | "cell_type": "markdown", 289 | "metadata": {}, 290 | "source": [ 291 | "The functions defined above are now composed to handle the general case, where (at least) one parameter is an actual node and the second parameter possibly is one of the preassigned nodes." 292 | ] 293 | }, 294 | { 295 | "cell_type": "code", 296 | "execution_count": 9, 297 | "metadata": {}, 298 | "outputs": [], 299 | "source": [ 300 | "def constrain_nodes(a: Node, b: Node, target: Qubit, side: str) -> None:\n", 301 | " c, d = sorted((a, b))\n", 302 | " if c < 0 or c > 6 or d < 0 or (d > 6 and d not in (A, B, C, D, AC)):\n", 303 | " raise ValueError()\n", 304 | " a_slice = slice(2 * a, 2 * a + 2)\n", 305 | " b_slice = slice(2 * b, 2 * b + 2)\n", 306 | " if d < A:\n", 307 | " valueXor_noancilla(q[a_slice], q[b_slice], q[target], side)\n", 308 | " elif b == A:\n", 309 | " aXor(q[a_slice], q[target], side)\n", 310 | " elif b == B:\n", 311 | " bXor(q[a_slice], q[target], side)\n", 312 | " elif b == C:\n", 313 | " cXor(q[a_slice], q[target], side)\n", 314 | " elif b == D:\n", 315 | " dXor(q[a_slice], q[target], side)\n", 316 | " elif b == AC:\n", 317 | " acXor(q[a_slice], q[target], side)\n", 318 | " else:\n", 319 | " raise ValueError()" 320 | ] 321 | }, 322 | { 323 | "cell_type": "markdown", 324 | "metadata": {}, 325 | "source": [ 326 | "Due to the restricted number of qubits in the competition, we constrain two pairs of nodes at once and save the result on another qubit (cf. Figure 1).\n", 327 | "For our implementation, we need 8 of these target qubits to save the result.\n", 328 | "Furthermore, we use ancillary qubits to store the interim results.\n", 329 | "\n", 330 | "After determining whether the nodes are different, the computation has to be reversed to ensure the inputs are not altered and may be re-used." 331 | ] 332 | }, 333 | { 334 | "cell_type": "code", 335 | "execution_count": 10, 336 | "metadata": {}, 337 | "outputs": [], 338 | "source": [ 339 | "def constrain_pair(pair_a: Tuple[Node, Node], pair_b: Tuple[Node, Node], target: Qubit, side=\"both\") -> None:\n", 340 | " if len({pair_a[0], pair_a[1], pair_b[0], pair_b[1]}) != 4:\n", 341 | " raise ValueError('Nodes need to be different.')\n", 342 | "\n", 343 | " constrain_nodes(pair_a[0], pair_a[1], ANC_1, \"left\")\n", 344 | " constrain_nodes(pair_b[0], pair_b[1], ANC_2, \"left\")\n", 345 | " rccx_opt(qc, q[ANC_1], q[ANC_2], q[target], side)\n", 346 | " constrain_nodes(pair_b[0], pair_b[1], ANC_2, \"right\")\n", 347 | " constrain_nodes(pair_a[0], pair_a[1], ANC_1, \"right\")" 348 | ] 349 | }, 350 | { 351 | "cell_type": "markdown", 352 | "metadata": {}, 353 | "source": [ 354 | "Node 2 is special in the sense that it cannot assume the colors/brands *A* and *C*. This property is exploited to save costs since due to the representation required in the challenge `q[5]` simply has to be *1*." 355 | ] 356 | }, 357 | { 358 | "cell_type": "code", 359 | "execution_count": 11, 360 | "metadata": {}, 361 | "outputs": [], 362 | "source": [ 363 | "def constrain_pair_ac(pair_a: Tuple[Node, Node], target: Qubit, side=\"both\") -> None:\n", 364 | " constrain_nodes(pair_a[0], pair_a[1], ANC_1, \"left\")\n", 365 | " rccx_opt(qc, q[ANC_1], q[5], q[target], side)\n", 366 | " constrain_nodes(pair_a[0], pair_a[1], ANC_1, \"right\")" 367 | ] 368 | }, 369 | { 370 | "cell_type": "markdown", 371 | "metadata": {}, 372 | "source": [ 373 | "Another exploitable property that is obvious by just looking at the graph, is the edge between nodes 0 and 1 can be replaced by introducing two \"virtual\" edges $(0,D)$ and $(1,C)$." 374 | ] 375 | }, 376 | { 377 | "cell_type": "code", 378 | "execution_count": 12, 379 | "metadata": {}, 380 | "outputs": [], 381 | "source": [ 382 | "def constrain_pair_0a_1b(target: Qubit, side=\"both\") -> None:\n", 383 | " qc.cx(q[0], q[1])\n", 384 | " qc.cx(q[2], q[3])\n", 385 | " if side in (\"right\", \"both\"):\n", 386 | " qc.x(q[3])\n", 387 | " rccx_opt(qc, q[1], q[3], q[target], side)\n", 388 | " if side in (\"left\", \"both\"):\n", 389 | " qc.x(q[3])\n", 390 | " qc.cx(q[2], q[3])\n", 391 | " qc.cx(q[0], q[1])" 392 | ] 393 | }, 394 | { 395 | "cell_type": "markdown", 396 | "metadata": {}, 397 | "source": [ 398 | "The `oracle` calls the functions defined above with the appropriate parameters as defined by the graph given in the problem description.\n", 399 | "\n", 400 | "First, node 0 and 1 are constrained as per the property described above -- followed by the constraints for node 2.\n", 401 | "The calls to `constrain_pair(...)` correspond to the edges in the graph. \n", 402 | "The last three edges are handled as a triple instead of a pair to reduce the costs. \n", 403 | "Note that it suffices to calculate these intermediate results up to relative phase.\n", 404 | "\n", 405 | "The call to `my_mct_v_chain(...)` negates our final target qubit. Due to the qubit preparation shown below, this results in a phase flip as required by Grover's algorithm." 406 | ] 407 | }, 408 | { 409 | "cell_type": "code", 410 | "execution_count": 13, 411 | "metadata": {}, 412 | "outputs": [], 413 | "source": [ 414 | "def oracle() -> None:\n", 415 | " constrain_pair_0a_1b(22, \"left\")\n", 416 | " qc.barrier()\n", 417 | " constrain_pair_ac((4, B), 23, \"left\")\n", 418 | " qc.barrier()\n", 419 | " constrain_pair((3, A), (6, D), 24, \"left\")\n", 420 | " qc.barrier()\n", 421 | " constrain_pair((2, 3), (5, D), 25, \"left\")\n", 422 | " qc.barrier()\n", 423 | " constrain_pair((6, 3), (0, 2), 26, \"left\")\n", 424 | " qc.barrier()\n", 425 | " constrain_pair((5, 2), (4, 3), 27, \"left\")\n", 426 | " qc.barrier()\n", 427 | " constrain_pair((5, 6), (0, 3), 28, \"left\")\n", 428 | " qc.barrier()\n", 429 | " constrain_pair((4, 6), (1, 3), 29, \"left\")\n", 430 | " qc.barrier()\n", 431 | "\n", 432 | " constrain_nodes(5, 3, ANC_1, \"left\")\n", 433 | " constrain_nodes(2, 6, ANC_2, \"left\")\n", 434 | " constrain_nodes(4, 1, ANC_3, \"left\")\n", 435 | " my_rmct_v_chain(qc, [q[ANC_1], q[ANC_2], q[ANC_3]], q[30], q[17:22], \"left\")\n", 436 | "\n", 437 | " rccx_opt(qc, q[2], q[3], q[ANC_2], \"right\")\n", 438 | " rccx_opt(qc, q[12], q[13], q[ANC_3], \"right\")\n", 439 | " qc.barrier()\n", 440 | "\n", 441 | " my_mct_v_chain(qc, q[22:31], q[31], q[15:22])\n", 442 | "\n", 443 | " qc.barrier()\n", 444 | " rccx_opt(qc, q[12], q[13], q[ANC_3], \"left\")\n", 445 | " rccx_opt(qc, q[2], q[3], q[ANC_2], \"left\")\n", 446 | "\n", 447 | " my_rmct_v_chain(qc, [q[ANC_1], q[ANC_2], q[ANC_3]], q[30], q[17:22], \"right\")\n", 448 | " constrain_nodes(4, 1, ANC_3, \"right\")\n", 449 | " constrain_nodes(2, 6, ANC_2, \"right\")\n", 450 | " constrain_nodes(5, 3, ANC_1, \"right\")\n", 451 | "\n", 452 | " qc.barrier()\n", 453 | " constrain_pair((4, 6), (1, 3), 29, \"right\")\n", 454 | " qc.barrier()\n", 455 | " constrain_pair((5, 6), (0, 3), 28, \"right\")\n", 456 | " qc.barrier()\n", 457 | " constrain_pair((5, 2), (4, 3), 27, \"right\")\n", 458 | " qc.barrier()\n", 459 | " constrain_pair((6, 3), (0, 2), 26, \"right\")\n", 460 | " qc.barrier()\n", 461 | " constrain_pair((2, 3), (5, D), 25, \"right\")\n", 462 | " qc.barrier()\n", 463 | " constrain_pair((3, A), (6, D), 24, \"right\")\n", 464 | " qc.barrier()\n", 465 | " constrain_pair_ac((4, B), 23, \"right\")\n", 466 | " qc.barrier()\n", 467 | " constrain_pair_0a_1b(22, \"right\")\n", 468 | " qc.barrier()" 469 | ] 470 | }, 471 | { 472 | "cell_type": "markdown", 473 | "metadata": {}, 474 | "source": [ 475 | "The diffusion is the default Grover diffusion with single qubit gates fused where appropriate." 476 | ] 477 | }, 478 | { 479 | "cell_type": "code", 480 | "execution_count": 14, 481 | "metadata": {}, 482 | "outputs": [], 483 | "source": [ 484 | "def diffusion() -> None:\n", 485 | " qc.u2(0, 0, q[0:3]) # -H-X-\n", 486 | " qc.u3(3 * pi / 2, 0, pi, q[3]) # -X-H-X\n", 487 | " qc.u2(0, 0, q[4:6]) # -H-X-\n", 488 | " qc.u3(3 * pi / 2, 0, pi, q[6:8]) # -X-H-X\n", 489 | " qc.u2(0, 0, q[8:13]) # -H-X-\n", 490 | " qc.u2(0, 0, q[13]) # -Z-H-\n", 491 | "\n", 492 | " anci_idx = 0\n", 493 | " rccx_opt(qc, q[0], q[1], q[18+anci_idx], \"left\")\n", 494 | " for idx in range(2, 12):\n", 495 | " rccx_opt(qc, q[idx], q[18+anci_idx], q[18+anci_idx+1], \"left\")\n", 496 | " anci_idx += 1\n", 497 | "\n", 498 | " qc.cx(q[18+anci_idx], q[13])\n", 499 | " qc.tdg(q[13])\n", 500 | " qc.cx(q[12], q[13])\n", 501 | " qc.t(q[13])\n", 502 | " qc.cx(q[18+anci_idx], q[13])\n", 503 | " qc.tdg(q[13])\n", 504 | " qc.cx(q[12], q[13])\n", 505 | " qc.t(q[18+anci_idx])\n", 506 | " qc.cx(q[12], q[18+anci_idx])\n", 507 | " qc.t(q[12])\n", 508 | " qc.tdg(q[18+anci_idx])\n", 509 | " qc.cx(q[12], q[18+anci_idx])\n", 510 | "\n", 511 | " for idx in reversed(range(2, 12)):\n", 512 | " rccx_opt(qc, q[idx], q[18+anci_idx - 1], q[18+anci_idx], \"right\")\n", 513 | " anci_idx -= 1\n", 514 | " rccx_opt(qc, q[0], q[1], q[18+anci_idx], \"right\")\n", 515 | "\n", 516 | " qc.u2(pi, 5*pi/4, q[13]) # -T-H-Z-\n", 517 | " qc.u2(pi, pi, q[8:13]) # -X-H-\n", 518 | " qc.u3(3 * pi / 2, 0, pi, q[6:8]) # -X-H-X-\n", 519 | " qc.u2(pi, pi, q[4:6]) # -X-H-\n", 520 | " qc.u3(3 * pi / 2, 0, pi, q[3]) # -X-H-X-\n", 521 | " qc.u2(pi, pi, q[0:3]) # -X-H-" 522 | ] 523 | }, 524 | { 525 | "cell_type": "markdown", 526 | "metadata": {}, 527 | "source": [ 528 | "The challenge required to use Grover's algorithm with 5 iterations.\n", 529 | "In the code below we prepare the qubits for the algorithm and fuse consecutive single qubit gates." 530 | ] 531 | }, 532 | { 533 | "cell_type": "code", 534 | "execution_count": 15, 535 | "metadata": {}, 536 | "outputs": [ 537 | { 538 | "data": { 539 | "text/plain": [ 540 | "" 541 | ] 542 | }, 543 | "execution_count": 15, 544 | "metadata": {}, 545 | "output_type": "execute_result" 546 | } 547 | ], 548 | "source": [ 549 | "q = QuantumRegister(32, 'q')\n", 550 | "c = ClassicalRegister(14, 'c')\n", 551 | "qc = QuantumCircuit(q, c)\n", 552 | "ANC_1 = 14\n", 553 | "ANC_2 = 15\n", 554 | "ANC_3 = 16\n", 555 | "\n", 556 | "# preparation\n", 557 | "qc.h(q[0:3]) # -H-\n", 558 | "qc.u2(0, 0, q[3]) # -H-X- implicitly negate q[3]\n", 559 | "qc.h(q[4:6]) # -H-\n", 560 | "qc.u2(0, 0, q[6:8]) # -H-X- implicitly negate the '3' qubits\n", 561 | "qc.h(q[8:14]) # -H-\n", 562 | "qc.u2(5 * pi / 4, pi, q[14:17]) # -X-H-T- prepare \"tree\" ancilla\n", 563 | "qc.u2(pi / 4, pi, q[17:31]) # -H-T- prepare \"mct\" ancilla\n", 564 | "qc.x(q[31]) # -X- prepare target\n", 565 | "\n", 566 | "for _ in range(5):\n", 567 | " oracle()\n", 568 | " diffusion()\n", 569 | "\n", 570 | "qc.x(q[6:8]) # reverse the negation of the '3' qubits\n", 571 | "qc.x(q[3]) # reverse the negation of q[3]\n", 572 | "\n", 573 | "# final measurement\n", 574 | "qc.measure(q[0:14], c[0:14])" 575 | ] 576 | }, 577 | { 578 | "cell_type": "markdown", 579 | "metadata": {}, 580 | "source": [ 581 | "## Costs of our Approach\n", 582 | "\n", 583 | "While we omitted the code to submit the circuit to IBM Q, calculating the cost is fast and, thus, included in this write-up." 584 | ] 585 | }, 586 | { 587 | "cell_type": "code", 588 | "execution_count": 16, 589 | "metadata": {}, 590 | "outputs": [ 591 | { 592 | "name": "stdout", 593 | "output_type": "stream", 594 | "text": [ 595 | "gates: {'cx': 2320, 'u3': 2290, 'barrier': 95, 'measure': 14}\n", 596 | "costs: 25490\n" 597 | ] 598 | } 599 | ], 600 | "source": [ 601 | "pass_ = Unroller(['u3', 'cx'])\n", 602 | "pm = PassManager(pass_)\n", 603 | "unrolled_circuit = pm.run(qc)\n", 604 | "uc_gates = unrolled_circuit.count_ops()\n", 605 | "print('gates: {}'.format(dict(uc_gates)))\n", 606 | "print('costs: {}'.format(uc_gates['cx'] * 10 + uc_gates['u3']))" 607 | ] 608 | } 609 | ], 610 | "metadata": { 611 | "kernelspec": { 612 | "display_name": "Python 3", 613 | "language": "python", 614 | "name": "python3" 615 | }, 616 | "language_info": { 617 | "codemirror_mode": { 618 | "name": "ipython", 619 | "version": 3 620 | }, 621 | "file_extension": ".py", 622 | "mimetype": "text/x-python", 623 | "name": "python", 624 | "nbconvert_exporter": "python", 625 | "pygments_lexer": "ipython3", 626 | "version": "3.6.8" 627 | }, 628 | "pycharm": { 629 | "stem_cell": { 630 | "cell_type": "raw", 631 | "metadata": { 632 | "collapsed": false 633 | }, 634 | "source": [] 635 | } 636 | } 637 | }, 638 | "nbformat": 4, 639 | "nbformat_minor": 4 640 | } 641 | -------------------------------------------------------------------------------- /top ten submissions/IIQ@QIC/fig/side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/top ten submissions/IIQ@QIC/fig/side.png -------------------------------------------------------------------------------- /top ten submissions/IIQ@QIC/fig/value_xor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/top ten submissions/IIQ@QIC/fig/value_xor.png -------------------------------------------------------------------------------- /top ten submissions/IIQ@QIC/readme.txt: -------------------------------------------------------------------------------- 1 | #IBM Quantum Challenge 2019 2 | #Instructions for top ten teams for preparing their illustrative explanation of their submissions. 3 | 4 | Dear Team, 5 | 6 | Congratulations for making it into the top ten teams of IBM Quantum Challenge! 7 | 8 | Judges have reviewed your submissions and have verified your final score. We will be making an official announcement next week to show the final standings. 9 | 10 | In the meantime, we are asking all top ten teams to: 11 | 12 | 13 | -Prepare a write-up on how your team obtained the answers for the final challenge. 14 | 15 | -You may either add explanations to your ipynb file OR provide detailed comments in your .py file. 16 | 17 | -While we do not have a specific format for you to follow, we would like to ask you to focus on providing an illustrative explanation of your strategy, approach, techniques (creativity) you used to achieve lower quantum costs. 18 | 19 | -A folder saying 'top ten submissions' will be prepared in the github repository containing another set of folders each named after your teams. Please push your write-ups into these folders by Monday Oct 21st, noon JST. 20 | 21 | 22 | IBM Quantum Challenge Organizers -------------------------------------------------------------------------------- /top ten submissions/QunaVillage/QunaVillage_commented.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Submission code with comments (QunaVillage)" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## Basic Idea\n", 15 | "\n", 16 | "### Saving number of qubits via constraints\n", 17 | "Node 2 is constrained to take either B or D, due to the adjacent nodes. \n", 18 | "So we assign only one qubit for node 2 as B=|0>, D=|1>. \n", 19 | "\n", 20 | "On the other hand, if we put D on node 0, node 2, 3, and 1 are automatically fixed, but node 6 becomes inconsistent eventually. \n", 21 | "Thus we can only put B or C on node 0 (assume B=|0>, C=|1>). \n", 22 | "\n", 23 | "In the same way, node 1 is constrained to either A(=|0>) or D(=|1>).\n", 24 | "\n", 25 | "Consequently, non-trivial edges are as follows. \n", 26 | "We number them consecutively.\n", 27 | "\n", 28 | "```\n", 29 | "edge 0 = (node A, node 3) # and so forth\n", 30 | "edge 1 = (0, 2) \n", 31 | "edge 2 = (0, 3) \n", 32 | "edge 3 = (1, 3) \n", 33 | "edge 4 = (1, 4) \n", 34 | "edge 5 = (B, 4) \n", 35 | "edge 6 = (2, 3) \n", 36 | "edge 7 = (3, 4) \n", 37 | "edge 8 = (2, 5) \n", 38 | "edge 9 = (2, 6) \n", 39 | "edge 10 = (3, 5) \n", 40 | "edge 11 = (3, 6) \n", 41 | "edge 12 = (4, 6) \n", 42 | "edge 13 = (5, 6) \n", 43 | "edge 14 = (5, D) \n", 44 | "edge 15 = (6, D)\n", 45 | "```\n", 46 | "\n", 47 | "### Dividing edges to seven parts\n", 48 | "Furthermore, we divide these edges to seven groups which we call \"parts\". \n", 49 | "Edges in the same part will be judged if the qubits meet the condition at the same time.\n", 50 | "```\n", 51 | "part0 = edge 1 # and so forth\n", 52 | "part1 = 0\n", 53 | "part2 = (2,3)\n", 54 | "part3 = (4,5)\n", 55 | "part4 = (6,8,9,10)\n", 56 | "part5 = (7,11,12)\n", 57 | "part6 = (13,14,15)\n", 58 | "```" 59 | ] 60 | }, 61 | { 62 | "cell_type": "markdown", 63 | "metadata": {}, 64 | "source": [ 65 | "### Table of qubit usages\n", 66 | "In total, we use 27 qubits.\n", 67 | "\n", 68 | "|qubit|node|\n", 69 | "|---|---|\n", 70 | "|0|0 (one qubit to represent B/C)| \n", 71 | "|1|1 (one qubit to represent A/D)|\n", 72 | "|2|2 (one qubit to represent B/D)|\n", 73 | "|3|3 (the right digit of node 3 e.g., \\|1> if \\|node3>=\\|B>=\\|01> and so forth) |\n", 74 | "|4|3 (the left digit of node 3 e.g., \\|0> if \\|node3>=\\|B>=\\|01> and so forth) |\n", 75 | "|5|4|\n", 76 | "|6|4|\n", 77 | "|7|5|\n", 78 | "|8|5|\n", 79 | "|9|6|\n", 80 | "|10|6|\n", 81 | "|11| target for part0 and diffusion MCT ancilla 0|\n", 82 | "|12| target for part1 and diffusion MCT ancilla 1|\n", 83 | "|13| target for part2 and diffusion MCT ancilla 2|\n", 84 | "|14| target for part3 and diffusion MCT ancilla 3|\n", 85 | "|15| target for part4 and diffusion MCT ancilla 4|\n", 86 | "|16| target for part4 and diffusion MCT ancilla 5|\n", 87 | "|17| target for part5 and diffusion MCT ancilla 6|\n", 88 | "|18| target for part6 and diffusion MCT ancilla 7|\n", 89 | "|19|part4, ancillary|\n", 90 | "|20|part5, ancillary|\n", 91 | "|21|part6, ancillary|\n", 92 | "|22|phase MCT ancilla0|\n", 93 | "|23|phase MCT ancilla1|\n", 94 | "|24|phase MCT ancilla2|\n", 95 | "|25|phase MCT ancilla3|\n", 96 | "|26|phase MCT ancilla4|" 97 | ] 98 | }, 99 | { 100 | "cell_type": "markdown", 101 | "metadata": {}, 102 | "source": [ 103 | "### Other points\n", 104 | "* Using RCCX gates (Relative-phase Toffoli gates) instead of CCX to save CX gates\n", 105 | "* Thinking carefully the order to apply gates to reduce redundant gate operations, especially parts gates for the oracle." 106 | ] 107 | }, 108 | { 109 | "cell_type": "code", 110 | "execution_count": 1, 111 | "metadata": {}, 112 | "outputs": [], 113 | "source": [ 114 | "import matplotlib.pyplot as plt\n", 115 | "import numpy as np\n", 116 | "import time \n", 117 | "\n", 118 | "from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit\n", 119 | "from qiskit import IBMQ, Aer, execute\n", 120 | "from qiskit.tools.visualization import plot_histogram\n", 121 | "import json\n", 122 | "from qiskit.transpiler import PassManager\n", 123 | "from qiskit.transpiler.passes import Unroller" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": 2, 129 | "metadata": {}, 130 | "outputs": [], 131 | "source": [ 132 | "def part0(circuit, q0, q1, t0):\n", 133 | " \"\"\"\n", 134 | " for nodes 0, 2\n", 135 | " :param circuit:\n", 136 | " :param q0: node 0\n", 137 | " :param q1: node 2\n", 138 | " :param t0: target\n", 139 | " :return:\n", 140 | " \"\"\"\n", 141 | " circuit.x(q0)\n", 142 | " circuit.x(q1)\n", 143 | " circuit.rccx(q0, q1, t0)\n", 144 | " circuit.x(t0)\n", 145 | "\n", 146 | "def part0_inv(circuit, q0, q1, t0):\n", 147 | " circuit.x(t0)\n", 148 | " circuit.rccx(q0, q1, t0)\n", 149 | " circuit.x(q1)\n", 150 | " circuit.x(q0)\n", 151 | " \n", 152 | "\n", 153 | "def part1(circuit, q0, q1, t0):\n", 154 | " \"\"\"\n", 155 | " for nodes A, 3\n", 156 | " :param circuit: \n", 157 | " :param q0: node 3\n", 158 | " :param q1: node 3\n", 159 | " :param t0: target\n", 160 | " :return: \n", 161 | " \"\"\"\n", 162 | " circuit.x(q0)\n", 163 | " circuit.x(q1)\n", 164 | " circuit.rccx(q0, q1, t0)\n", 165 | " circuit.x(t0)\n", 166 | " circuit.x(q1)\n", 167 | " circuit.x(q0)\n", 168 | "\n", 169 | "def part1_inv(circuit, q0, q1, t0):\n", 170 | " circuit.x(q0)\n", 171 | " circuit.x(q1)\n", 172 | " circuit.x(t0)\n", 173 | " circuit.rccx(q0, q1, t0)\n", 174 | " circuit.x(q1)\n", 175 | " circuit.x(q0)\n", 176 | " \n", 177 | "\n", 178 | "def part2(circuit, q0, q1, q2, q3, t0):\n", 179 | " \"\"\"\n", 180 | " for nodes 0, 1, 3\n", 181 | " :param circuit:\n", 182 | " :param q0: node 0 (|0> = B, |1> = C)\n", 183 | " :param q1: node 1 (|0> = A, |1> = D)\n", 184 | " :param q2: node 3\n", 185 | " :param q3: node 3\n", 186 | " :param t0:\n", 187 | " :return:\n", 188 | " \"\"\"\n", 189 | " # q0 XOR q1 -> q0\n", 190 | " circuit.cx(q1, q0)\n", 191 | "\n", 192 | " # cswap\n", 193 | " circuit.cx(q2, q3)\n", 194 | " circuit.rccx(q0, q3, q2)\n", 195 | " circuit.cx(q2, q3)\n", 196 | "\n", 197 | " circuit.cx(q1, t0)\n", 198 | " circuit.cx(q3, t0) \n", 199 | "\n", 200 | " circuit.cx(q2, q3)\n", 201 | " circuit.rccx(q0, q3, q2)\n", 202 | " circuit.cx(q2, q3)\n", 203 | "\n", 204 | " circuit.cx(q1, q0)\n", 205 | "\n", 206 | "def part2_inv(circuit, q0, q1, q2, q3, t0):\n", 207 | " circuit.cx(q1, q0)\n", 208 | "\n", 209 | " circuit.cx(q2, q3)\n", 210 | " circuit.rccx(q0, q3, q2)\n", 211 | " circuit.cx(q2, q3)\n", 212 | "\n", 213 | " circuit.cx(q3, t0)\n", 214 | " circuit.cx(q1, t0)\n", 215 | "\n", 216 | " circuit.cx(q2, q3)\n", 217 | " circuit.rccx(q0, q3, q2)\n", 218 | " circuit.cx(q2, q3)\n", 219 | "\n", 220 | " circuit.cx(q1, q0)\n", 221 | "\n", 222 | " \n", 223 | "def part3(circuit, q0, q1, q2, t0):\n", 224 | " \"\"\"\n", 225 | " for nodes 1, 4, B\n", 226 | " :param circuit:\n", 227 | " :param q0: node 1\n", 228 | " :param q1: node 4\n", 229 | " :param q2: node 4\n", 230 | " :param t0: target\n", 231 | " :return:\n", 232 | " \"\"\"\n", 233 | " circuit.x(q1)\n", 234 | " circuit.rccx(q0, q1, t0)\n", 235 | " circuit.x(q0)\n", 236 | " circuit.rccx(q0, q2, t0)\n", 237 | "\n", 238 | "def part3_inv(circuit, q0, q1, q2, t0):\n", 239 | " circuit.rccx(q0, q2, t0)\n", 240 | " circuit.x(q0)\n", 241 | " circuit.rccx(q0, q1, t0)\n", 242 | " circuit.x(q1)\n", 243 | " \n", 244 | " \n", 245 | "def part4(circuit, q0, q1, q2, q3, q4, q5, q6, t0, t1, a0):\n", 246 | " \"\"\"\n", 247 | " for the triangle (cons. of nodes 2, 3, 5) and the edge (cons. of nodes 2, 6)\n", 248 | "\n", 249 | " :param circuit: \n", 250 | " :param q0: node 2\n", 251 | " :param q1: node 3\n", 252 | " :param q2: node 3\n", 253 | " :param q3: node 5\n", 254 | " :param q4: node 5\n", 255 | " :param q5: node 6\n", 256 | " :param q6: node 6\n", 257 | " :param t0: target for triangle (cons. of nodes 2, 3, 5)\n", 258 | " :param t1: target for the edge (cons. of nodes 2, 6)\n", 259 | " :param a0: ancillary qubit\n", 260 | " :return: \n", 261 | " \"\"\"\n", 262 | "\n", 263 | " ### triangle\n", 264 | " circuit.x(q1)\n", 265 | " circuit.x(q3)\n", 266 | " circuit.cx(q0, q2)\n", 267 | " circuit.cx(q0, q4)\n", 268 | "\n", 269 | " circuit.rccx(q2, q3, t0)\n", 270 | " circuit.rccx(q1, q4, t0)\n", 271 | " circuit.rccx(q1, q3, t0)\n", 272 | " circuit.rccx(q2, q4, t0)\n", 273 | " circuit.rccx(q1, q3, a0)\n", 274 | " circuit.rccx(q2, q4, a0)\n", 275 | " circuit.cx(a0, t0)\n", 276 | "\n", 277 | " ### edge\n", 278 | " circuit.cx(q0, q6)\n", 279 | " circuit.x(q6)\n", 280 | " circuit.rccx(q5, q6, t1)\n", 281 | " circuit.x(t1)\n", 282 | "\n", 283 | "def part4_inv(circuit, q0, q1, q2, q3, q4, q5, q6, t0, t1, a0):\n", 284 | "\n", 285 | " circuit.x(t1)\n", 286 | " circuit.rccx(q5, q6, t1)\n", 287 | " circuit.x(q6)\n", 288 | " circuit.cx(q0, q6)\n", 289 | "\n", 290 | " circuit.cx(a0, t0)\n", 291 | " circuit.rccx(q2, q4, a0)\n", 292 | " circuit.rccx(q1, q3, a0)\n", 293 | " circuit.rccx(q2, q4, t0)\n", 294 | " circuit.rccx(q1, q3, t0)\n", 295 | " circuit.rccx(q1, q4, t0)\n", 296 | " circuit.rccx(q2, q3, t0)\n", 297 | "\n", 298 | " circuit.cx(q0, q4)\n", 299 | " circuit.cx(q0, q2)\n", 300 | " circuit.x(q3)\n", 301 | " circuit.x(q1)\n", 302 | "\n", 303 | "\n", 304 | "def part5(circuit, q0, q1, q2, q3, q4, q5, t0, a0):\n", 305 | " \"\"\"\n", 306 | " for nodes 3, 4, 6\n", 307 | " :param circuit:\n", 308 | " :param q0: node 3\n", 309 | " :param q1: node 3\n", 310 | " :param q2: node 4\n", 311 | " :param q3: node 4\n", 312 | " :param q4: node 6\n", 313 | " :param q5: node 6\n", 314 | " \"\"\"\n", 315 | " circuit.cx(q0, q2)\n", 316 | " circuit.cx(q0, q4)\n", 317 | " circuit.cx(q1, q3)\n", 318 | " circuit.cx(q1, q5)\n", 319 | "\n", 320 | " circuit.rccx(q3, q4, t0)\n", 321 | " circuit.rccx(q2, q5, t0)\n", 322 | " circuit.rccx(q2, q4, t0)\n", 323 | " circuit.rccx(q3, q5, t0)\n", 324 | " circuit.rccx(q2, q4, a0)\n", 325 | " circuit.rccx(q3, q5, a0)\n", 326 | " circuit.cx(a0, t0)\n", 327 | "\n", 328 | " #circuit.barrier()\n", 329 | " circuit.cx(q1, q5)\n", 330 | " circuit.cx(q1, q3)\n", 331 | " circuit.cx(q0, q4)\n", 332 | " circuit.cx(q0, q2)\n", 333 | "\n", 334 | "def part5_inv(circuit, q0, q1, q2, q3, q4, q5, t0, a0):\n", 335 | " circuit.cx(q0, q2)\n", 336 | " circuit.cx(q0, q4)\n", 337 | " circuit.cx(q1, q3)\n", 338 | " circuit.cx(q1, q5)\n", 339 | " #circuit.barrier()\n", 340 | "\n", 341 | " circuit.cx(a0, t0)\n", 342 | " circuit.rccx(q3, q5, a0)\n", 343 | " circuit.rccx(q2, q4, a0)\n", 344 | " circuit.rccx(q3, q5, t0)\n", 345 | " circuit.rccx(q2, q4, t0)\n", 346 | " circuit.rccx(q2, q5, t0)\n", 347 | " circuit.rccx(q3, q4, t0)\n", 348 | " \n", 349 | " circuit.cx(q1, q5)\n", 350 | " circuit.cx(q1, q3)\n", 351 | " circuit.cx(q0, q4)\n", 352 | " circuit.cx(q0, q2)\n", 353 | "\n", 354 | " \n", 355 | "def part6(circuit, q0, q1, q2, q3, t0, a0):\n", 356 | " \"\"\"\n", 357 | " for nodes 5, 6, D\n", 358 | " :param circuit:\n", 359 | " :param q0: node 5\n", 360 | " :param q1: node 5\n", 361 | " :param q2: node 6\n", 362 | " :param q3: node 6\n", 363 | " \"\"\"\n", 364 | " circuit.x(q0)\n", 365 | " circuit.x(q1)\n", 366 | " circuit.x(q2)\n", 367 | " circuit.x(q3)\n", 368 | " circuit.rccx(q1, q2, t0)\n", 369 | " circuit.rccx(q0, q3, t0)\n", 370 | " circuit.rccx(q0, q2, t0)\n", 371 | " circuit.rccx(q1, q3, t0)\n", 372 | " circuit.rccx(q0, q2, a0)\n", 373 | " circuit.rccx(q1, q3, a0)\n", 374 | " circuit.cx(a0, t0)\n", 375 | "\n", 376 | " circuit.x(q3)\n", 377 | " circuit.x(q2)\n", 378 | " circuit.x(q1)\n", 379 | " circuit.x(q0)\n", 380 | "\n", 381 | "def part6_inv(circuit, q0, q1, q2, q3, t0, a0):\n", 382 | " circuit.x(q0)\n", 383 | " circuit.x(q1)\n", 384 | " circuit.x(q2)\n", 385 | " circuit.x(q3)\n", 386 | " \n", 387 | " circuit.cx(a0, t0)\n", 388 | " circuit.rccx(q1, q3, a0)\n", 389 | " circuit.rccx(q0, q2, a0)\n", 390 | " circuit.rccx(q1, q3, t0)\n", 391 | " circuit.rccx(q0, q2, t0)\n", 392 | " circuit.rccx(q0, q3, t0)\n", 393 | " circuit.rccx(q1, q2, t0)\n", 394 | " circuit.x(q3)\n", 395 | " circuit.x(q2)\n", 396 | " circuit.x(q1)\n", 397 | " circuit.x(q0)" 398 | ] 399 | }, 400 | { 401 | "cell_type": "code", 402 | "execution_count": 3, 403 | "metadata": {}, 404 | "outputs": [], 405 | "source": [ 406 | "def phase(circuit, q0, q1, q2, q3, q4, q5, q6, q7, a0, a1, a2, a3, a4):\n", 407 | " \"\"\"\n", 408 | " q0, q1, ..., q7: target qubits for part0 ~ part6 (note that part4 has two targets)\n", 409 | " We multiply phase factor (-1) when q0=q1=...=q7=1, i.e., all edges satisfy the condition.\n", 410 | " \"\"\"\n", 411 | " circuit.h(q7)\n", 412 | " circuit.mct([q0, q1, q2, q3, q4, q5, q6], q7, [a0, a1, a2, a3, a4], mode=\"basic\")\n", 413 | " circuit.h(q7)" 414 | ] 415 | }, 416 | { 417 | "cell_type": "code", 418 | "execution_count": 4, 419 | "metadata": {}, 420 | "outputs": [], 421 | "source": [ 422 | "def oracle(circuit, q):\n", 423 | " \n", 424 | " # test each part -> encode result to target qubits\n", 425 | " # the order of applying each part is decided so that the number of qubits \n", 426 | " # which have to be applied inverse-operation to be minimized\n", 427 | " part1(circuit, q[3], q[4], q[12]) \n", 428 | " part2(circuit, q[0], q[1], q[3], q[4], q[13]) \n", 429 | " part5(circuit, q[3], q[4], q[5], q[6], q[9], q[10], q[17], q[20])\n", 430 | " part6(circuit, q[7], q[8], q[9], q[10], q[18], q[21])\n", 431 | " part3(circuit, q[1], q[5], q[6], q[14])\n", 432 | " part4(circuit, q[2], q[3], q[4], q[7], q[8], q[9], q[10], q[15], q[16], q[19]) \n", 433 | " part0(circuit, q[0], q[2], q[11])\n", 434 | "\n", 435 | " # phase flip\n", 436 | " phase(circuit, \n", 437 | " q[11], q[12], q[13], q[14], q[15], q[16], q[17], q[18], \n", 438 | " q[22], q[23], q[24], q[25], q[26]) \n", 439 | " \n", 440 | " # apply inverse-operation for each part\n", 441 | " part0_inv(circuit, q[0], q[2], q[11])\n", 442 | " part4_inv(circuit, q[2], q[3], q[4], q[7], q[8], q[9], q[10], q[15], q[16], q[19])\n", 443 | " part3_inv(circuit, q[1], q[5], q[6], q[14])\n", 444 | " part6_inv(circuit, q[7], q[8], q[9], q[10], q[18], q[21])\n", 445 | " part5_inv(circuit, q[3], q[4], q[5], q[6], q[9], q[10], q[17], q[20])\n", 446 | " part2_inv(circuit, q[0], q[1], q[3], q[4], q[13]) \n", 447 | " part1_inv(circuit, q[3], q[4], q[12]) " 448 | ] 449 | }, 450 | { 451 | "cell_type": "code", 452 | "execution_count": 5, 453 | "metadata": {}, 454 | "outputs": [], 455 | "source": [ 456 | "def diffusion(circuit, qr, anc):\n", 457 | " \"\"\"\n", 458 | " diffusion (inversion about the mean) circuit.\n", 459 | " note that this implementation gives H^{\\otimes n} (Id - |0..0><0...0|) H^{\\otimes n} \n", 460 | " :param circuit:\n", 461 | " :param qr: QuantumRegister on nodes\n", 462 | " :param anc: ancillary qubits\n", 463 | " :return:\n", 464 | " \"\"\"\n", 465 | " circuit.h(qr)\n", 466 | " circuit.x(qr)\n", 467 | "\n", 468 | " # apply multi-control CZ\n", 469 | " circuit.h(qr[-1])\n", 470 | " circuit.mct(qr[:-1], qr[-1], anc, mode='basic')\n", 471 | " circuit.h(qr[-1])\n", 472 | "\n", 473 | " circuit.x(qr)\n", 474 | " circuit.h(qr)" 475 | ] 476 | }, 477 | { 478 | "cell_type": "code", 479 | "execution_count": 6, 480 | "metadata": {}, 481 | "outputs": [], 482 | "source": [ 483 | "def map2c(circuit, qs, cs, a0, a1):\n", 484 | " \"\"\"\n", 485 | " measurement of qubits so that the result is stored on c-bits,\n", 486 | " following the required format. \n", 487 | " \"\"\"\n", 488 | " circuit.x(a0)\n", 489 | " circuit.x(a1)\n", 490 | " circuit.cx(qs[0], a1)\n", 491 | " circuit.measure([qs[0], a1, qs[1], qs[1], qs[2], a0, qs[3], qs[4], qs[5], qs[6], qs[7], qs[8], qs[9], qs[10]], \n", 492 | " [cs[0], cs[1], cs[2], cs[3], cs[4], cs[5], cs[7], cs[6], cs[9], cs[8], cs[11], cs[10], cs[13], cs[12]])" 493 | ] 494 | }, 495 | { 496 | "cell_type": "code", 497 | "execution_count": 7, 498 | "metadata": {}, 499 | "outputs": [], 500 | "source": [ 501 | "def grover_single_iter(circuit, q):\n", 502 | " oracle(circuit, q)\n", 503 | " diffusion(circuit, q[:11], q[11:(11+8)])" 504 | ] 505 | }, 506 | { 507 | "cell_type": "code", 508 | "execution_count": 8, 509 | "metadata": {}, 510 | "outputs": [], 511 | "source": [ 512 | "# circuit construction \n", 513 | "q = QuantumRegister(27) \n", 514 | "c = ClassicalRegister(14)\n", 515 | "circuit = QuantumCircuit(q, c)\n", 516 | "\n", 517 | "## prepare superposition\n", 518 | "circuit.h(q[:11])\n", 519 | "\n", 520 | "## Grover iteration\n", 521 | "for _ in range(5):\n", 522 | " grover_single_iter(circuit, q)\n", 523 | "\n", 524 | "# measurement and formatting\n", 525 | "map2c(circuit, q[:11], c[:14], q[11], q[12])" 526 | ] 527 | }, 528 | { 529 | "cell_type": "code", 530 | "execution_count": 9, 531 | "metadata": {}, 532 | "outputs": [ 533 | { 534 | "name": "stdout", 535 | "output_type": "stream", 536 | "text": [ 537 | "OrderedDict([('u3', 2843), ('cx', 1421), ('measure', 14)])\n", 538 | "cost: 17053\n" 539 | ] 540 | } 541 | ], 542 | "source": [ 543 | "# Unroll the circuit\n", 544 | "pass_ = Unroller(['u3', 'cx'])\n", 545 | "pm = PassManager(pass_)\n", 546 | "new_circuit = pm.run(circuit) \n", 547 | "\n", 548 | "# obtain gates\n", 549 | "gates=new_circuit.count_ops()\n", 550 | "print(gates)\n", 551 | "cost = gates[\"u3\"] + 10 * gates[\"cx\"]\n", 552 | "print(\"cost:\", cost)" 553 | ] 554 | }, 555 | { 556 | "cell_type": "code", 557 | "execution_count": 10, 558 | "metadata": {}, 559 | "outputs": [ 560 | { 561 | "name": "stdout", 562 | "output_type": "stream", 563 | "text": [ 564 | "shots: 8000\n", 565 | "Calculations took 99.07090997695923 sec.\n" 566 | ] 567 | } 568 | ], 569 | "source": [ 570 | "### Execution\n", 571 | "time0 = time.time()\n", 572 | "shots = 8000\n", 573 | "print(\"shots:\", shots)\n", 574 | "\n", 575 | "## local simulator\n", 576 | "# backend = Aer.get_backend('qasm_simulator')\n", 577 | "## cloud simulator\n", 578 | "provider = IBMQ.load_account()\n", 579 | "backend = provider.get_backend('ibmq_qasm_simulator')\n", 580 | "\n", 581 | "job = execute(circuit, backend=backend, shots=shots, seed_simulator=12345, backend_options={\"fusion_enable\":True})\n", 582 | "result = job.result()\n", 583 | "time1 = time.time()\n", 584 | "print(f\"Calculations took {time1-time0} sec.\")" 585 | ] 586 | }, 587 | { 588 | "cell_type": "code", 589 | "execution_count": 11, 590 | "metadata": {}, 591 | "outputs": [ 592 | { 593 | "name": "stdout", 594 | "output_type": "stream", 595 | "text": [ 596 | "Your name: QunaVillage\n", 597 | "The number of times you have submitted your answer: 3\n", 598 | "<_io.TextIOWrapper name='QunaVillage_3_final_output.txt' mode='r' encoding='UTF-8'>\n", 599 | "Does your submission file have 9 answers?\n", 600 | "- Yes\n", 601 | "- Your plan: [['02013132203', 425], ['01013232013', 407], ['02313102023', 402], ['01313202013', 402], ['02013132023', 396], ['01013232103', 391], ['02011322203', 388], ['02313122203', 388], ['02013122203', 386]]\n", 602 | "What is your cost?\n", 603 | "- 17053\n" 604 | ] 605 | } 606 | ], 607 | "source": [ 608 | "### ----------- Data Formatting -------------\n", 609 | "# Input your quantum circuit\n", 610 | "circuit = circuit\n", 611 | "# Input your result of the execute(groverCircuit, backend=backend, shots=shots).result()\n", 612 | "results = result\n", 613 | "count = results.get_counts()\n", 614 | "# Input your name or your team name\n", 615 | "name='QunaVillage'\n", 616 | "# Please indicate the number of times you have submitted your answer so far.\n", 617 | "# For example, If it's your 1st time to submit your answer, write times='1'. If it's your 5th time to submit your answer, write times='5'.\n", 618 | "# Do not forget to put single quotations to make the variable 'Str'' type\n", 619 | "times= '3'\n", 620 | "\n", 621 | "# Unroll the circuit\n", 622 | "pass_ = Unroller(['u3', 'cx'])\n", 623 | "pm = PassManager(pass_)\n", 624 | "new_circuit = pm.run(circuit) \n", 625 | "\n", 626 | "# obtain gates\n", 627 | "gates=new_circuit.count_ops()\n", 628 | "\n", 629 | "#sort count\n", 630 | "count_sorted = sorted(count.items(), key=lambda x:x[1], reverse=True)\n", 631 | "\n", 632 | "# collect answers with Top 9 probability\n", 633 | "ans_list = count_sorted[0:9]\n", 634 | "\n", 635 | "# reverse ans_list\n", 636 | "ans_reversed = []\n", 637 | "for i in ans_list:\n", 638 | " ans_temp=[i[0][::-1],i[1]]\n", 639 | " ans_reversed.append(ans_temp)\n", 640 | "\n", 641 | "# convert each 2 bits into corresponding color. Add node0(0),node3(1),node8(2) and node11(3)\n", 642 | "ans_shaped = []\n", 643 | "for j in ans_reversed:\n", 644 | " ans_temp=j[0]\n", 645 | " nodeA = 0\n", 646 | " node0 = int(ans_temp[0] + ans_temp[1], 2)\n", 647 | " node1 = int(ans_temp[2] + ans_temp[3], 2)\n", 648 | " nodeB = 1\n", 649 | " node2 = int(ans_temp[4] + ans_temp[5], 2)\n", 650 | " node3 = int(ans_temp[6] + ans_temp[7], 2)\n", 651 | " node4 = int(ans_temp[8] + ans_temp[9], 2)\n", 652 | " nodeC = 2\n", 653 | " node5 = int(ans_temp[10] + ans_temp[11], 2)\n", 654 | " node6 = int(ans_temp[12] + ans_temp[13], 2)\n", 655 | " nodeD = 3\n", 656 | " nodes_color = str(nodeA) + str(node0) + str(node1) + str(nodeB) + str(node2) + str(node3) + str(node4) + str(nodeC) + str(node5) + str(node6) + str(nodeD) \n", 657 | " ans_shaped.append([nodes_color,j[1]])\n", 658 | "\n", 659 | "# write the result into '[your name]_final_output.txt'\n", 660 | "filename = name +'_'+times+'_final_output.txt'\n", 661 | "dct={'ans':ans_shaped,'costs':gates}\n", 662 | "with open(filename, 'w') as f:\n", 663 | " json.dump(dct, f)\n", 664 | "\n", 665 | "### ----------- verification -------------\n", 666 | "from pathlib import Path\n", 667 | "your_path = filename\n", 668 | "p= Path(your_path)\n", 669 | "\n", 670 | "# Verify your information\n", 671 | "f_name=p.name\n", 672 | "your_info=f_name.split('_')\n", 673 | "print('Your name: ', your_info[0])\n", 674 | "print('The number of times you have submitted your answer: ', your_info[1])\n", 675 | "\n", 676 | "with open(p, 'r') as f:\n", 677 | " print(f)\n", 678 | " your_ans=json.load(f)\n", 679 | "\n", 680 | "print('Does your submission file have 9 answers?')\n", 681 | "if (len(your_ans['ans'])!=9):\n", 682 | " print('- No, make sure you have 9 answers with top 9 probabilities')\n", 683 | "else:\n", 684 | " print('- Yes')\n", 685 | " print('- Your plan: ', your_ans['ans'])\n", 686 | "\n", 687 | "print('What is your cost?')\n", 688 | "your_cost=your_ans['costs']['u3'] + 10*your_ans['costs']['cx']\n", 689 | "print('- ', your_cost)" 690 | ] 691 | } 692 | ], 693 | "metadata": { 694 | "kernelspec": { 695 | "display_name": "Python 3", 696 | "language": "python", 697 | "name": "python3" 698 | }, 699 | "language_info": { 700 | "codemirror_mode": { 701 | "name": "ipython", 702 | "version": 3 703 | }, 704 | "file_extension": ".py", 705 | "mimetype": "text/x-python", 706 | "name": "python", 707 | "nbconvert_exporter": "python", 708 | "pygments_lexer": "ipython3", 709 | "version": "3.7.3" 710 | }, 711 | "varInspector": { 712 | "cols": { 713 | "lenName": 16, 714 | "lenType": 16, 715 | "lenVar": 40 716 | }, 717 | "kernels_config": { 718 | "python": { 719 | "delete_cmd_postfix": "", 720 | "delete_cmd_prefix": "del ", 721 | "library": "var_list.py", 722 | "varRefreshCmd": "print(var_dic_list())" 723 | }, 724 | "r": { 725 | "delete_cmd_postfix": ") ", 726 | "delete_cmd_prefix": "rm(", 727 | "library": "var_list.r", 728 | "varRefreshCmd": "cat(var_dic_list()) " 729 | } 730 | }, 731 | "types_to_exclude": [ 732 | "module", 733 | "function", 734 | "builtin_function_or_method", 735 | "instance", 736 | "_Feature" 737 | ], 738 | "window_display": false 739 | } 740 | }, 741 | "nbformat": 4, 742 | "nbformat_minor": 2 743 | } 744 | -------------------------------------------------------------------------------- /top ten submissions/QunaVillage/readme.txt: -------------------------------------------------------------------------------- 1 | #IBM Quantum Challenge 2019 2 | #Instructions for top ten teams for preparing their illustrative explanation of their submissions. 3 | 4 | Dear Team, 5 | 6 | Congratulations for making it into the top ten teams of IBM Quantum Challenge! 7 | 8 | Judges have reviewed your submissions and have verified your final score. We will be making an official announcement next week to show the final standings. 9 | 10 | In the meantime, we are asking all top ten teams to: 11 | 12 | 13 | -Prepare a write-up on how your team obtained the answers for the final challenge. 14 | 15 | -You may either add explanations to your ipynb file OR provide detailed comments in your .py file. 16 | 17 | -While we do not have a specific format for you to follow, we would like to ask you to focus on providing an illustrative explanation of your strategy, approach, techniques (creativity) you used to achieve lower quantum costs. 18 | 19 | -A folder saying 'top ten submissions' will be prepared in the github repository containing another set of folders each named after your teams. Please push your write-ups into these folders by Monday Oct 21st, noon JST. 20 | 21 | 22 | IBM Quantum Challenge Organizers -------------------------------------------------------------------------------- /top ten submissions/Sorin/Sorin_6_final.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "**Representation**\n", 8 | "\n", 9 | "I represented each district (0 to 6) with a set of 2 qubits. The value of the qubits represented the konbini chains $A:|00\\rangle, B:|01\\rangle, C:|10\\rangle, D:|11\\rangle$. A superposition $ 1 = \\frac{|00\\rangle + |01\\rangle}{\\sqrt 2}$ means that district 1 (represented by qubits 2 and 3) is equaly lightly to have a kobini store from either chain A or B.\n", 10 | "\n", 11 | "Since there are 7 districts of interest we use 14 qubits to represent them. We use Grover search so we need another qubit to store the result of the oracle. Since the simulator has 32 qubits we are left with 17 qubits to use as ancillas." 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "**Initialization**\n", 19 | "\n", 20 | "By looking at the initial restrictions commming from districts A, B, C and D it's clear that the initial state of the system can be set to a space that is a fraction of the maximum superposition space. I will then use the general form of Gover's Search also known as Amplitude Amplification to get the right answers.\n", 21 | "\n", 22 | "\n", 23 | "The initial superpositions are (I am omitting the normalization values):\n", 24 | "$$0 = |01> + |10> + |11>$$\n", 25 | "$$1 = |00\\rangle + |10\\rangle + |11\\rangle$$\n", 26 | "$$2 = |01\\rangle + |11\\rangle$$\n", 27 | "$$3 = |01\\rangle + |10\\rangle + |11\\rangle$$\n", 28 | "$$4 = |00\\rangle + |10\\rangle + |11\\rangle$$\n", 29 | "$$5 = |00\\rangle + |01\\rangle + |10\\rangle$$\n", 30 | "$$6 = |00\\rangle + |01\\rangle + |10\\rangle$$\n", 31 | "After a little thought you can see that these initial superpositions can be created using the methods below `set123()` to `set13()`. The method `A()` then incorporates these methods to set the whole initial state. The method `ADag()` is the adjoint operation." 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": 1, 37 | "metadata": {}, 38 | "outputs": [], 39 | "source": [ 40 | "from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit\n", 41 | "from qiskit import IBMQ, Aer, execute\n", 42 | "\n", 43 | "def set123(a0, a1): \n", 44 | " qc.x(q[a1])\n", 45 | " qc.h(q[a0])\n", 46 | " qc.cx(q[a0], q[a1])\n", 47 | " qc.ch(q[a0], q[a1])\n", 48 | "\n", 49 | "def set023(a0, a1): \n", 50 | " qc.h(q[a0])\n", 51 | " qc.ch(q[a0], q[a1])\n", 52 | "\n", 53 | "def set012(a0, a1): \n", 54 | " qc.h(q[a1])\n", 55 | " qc.x(q[a1])\n", 56 | " qc.ch(q[a1], q[a0])\n", 57 | " qc.x(q[a1])\n", 58 | "\n", 59 | "def set13(a0, a1): \n", 60 | " qc.h(q[a0])\n", 61 | " qc.x(q[a1])\n", 62 | "\n", 63 | "def set123Dag(a0, a1):\n", 64 | " qc.ch(q[a0], q[a1])\n", 65 | " qc.cx(q[a0], q[a1])\n", 66 | " qc.h(q[a0])\n", 67 | " qc.x(q[a1])\n", 68 | "\n", 69 | "def set023Dag(a0, a1):\n", 70 | " qc.ch(q[a0], q[a1])\n", 71 | " qc.h(q[a0])\n", 72 | "\n", 73 | "def set012Dag(a0, a1): \n", 74 | " qc.x(q[a1])\n", 75 | " qc.ch(q[a1], q[a0])\n", 76 | " qc.x(q[a1])\n", 77 | " qc.h(q[a1])\n", 78 | "\n", 79 | "def A():\n", 80 | " set123(0, 1)\n", 81 | " set023(2, 3)\n", 82 | " set13(4, 5)\n", 83 | " set123(6, 7)\n", 84 | " set023(8, 9)\n", 85 | " set012(10, 11)\n", 86 | " set012(12, 13)\n", 87 | "\n", 88 | "def ADag():\n", 89 | " set012Dag(12, 13)\n", 90 | " set012Dag(10, 11)\n", 91 | " set023Dag(8, 9)\n", 92 | " set123Dag(6, 7)\n", 93 | " set13(4, 5)\n", 94 | " set023Dag(2, 3)\n", 95 | " set123Dag(0, 1)" 96 | ] 97 | }, 98 | { 99 | "cell_type": "markdown", 100 | "metadata": {}, 101 | "source": [ 102 | "**The Oracle**\n", 103 | "\n", 104 | "The idea of the orcle is to compare for equality the states of the districts (pair of qubits) that are linked by an edge in the graph. The oracle should mark as valid those superpositions in which all compared states are different.\n", 105 | "\n", 106 | "As stated above we have 17 qubits that we can use as ancillas. There are 13 edges between the 0..6 districts. We store the results of the 13 comparisons in 13 of the ancilla qubits. In order to make sure all comparisons resulted in the states being different we need a Multiple Controlled Toffoli (mct) gate to mark the state only if all of the 3 qubits that store the comparison results are in the $|0\\rangle$ state. The mct gate need a number of ancilla qubits that is equal to `number_of_controll_qubits` - 2. In our case 13-2 = 11. But we already used 13 of our 17 ancillas and we only have 4 left. To get arround this we use the mct gate in the `mode='basic-dirty-ancilla'`. This means that the gate can use ancillas that are not in the 0 state. The gate, after doing its job, leaves the states of the ancillas as they were so we can use our main qubits (used for storing the districts) as the dirty ancillas.\n", 107 | "\n", 108 | "*Optimisations*\n", 109 | "There are a number of ways of checking the equality of qubit states but many are complicated and some use ripple carry method or subtraction. As we don't need a general comparer we can create our own custom one that only works for 2 on 2 qubits. This is done in the `equalsNoCcx()` method. The method compares the states in qubits a0 and a1 to b0 and b1 and leaves the result in qubits b0 and b1 (if both are $|1\\rangle$ then the states are equal)\n", 110 | "\n", 111 | "Tipically each comparison must be done 4 times: One to get the result and store it in an ancilla, second reverse the comparison in order to restore the qubits for another comparison, then, after the oracle marked the state we need to repeat the process to clear the ancilla. For each of the 7 disctict we can avoid doing 2 comparisons: when doing the last comparison for that district do not restore the state - this way, after the oracle marked the entire superposition of the system, our district qubits are in the correct state for clearing the ancilla.\n", 112 | "\n", 113 | "Since we use our main qubits as the ancillas for the mct gate we are left with 4 unused qubits. We can use those to reduce the number of controll qubits for the mct by storing intermediate results in them.\n", 114 | "\n" 115 | ] 116 | }, 117 | { 118 | "cell_type": "code", 119 | "execution_count": 2, 120 | "metadata": {}, 121 | "outputs": [], 122 | "source": [ 123 | "def equalsNoCcx(a0, a1, b0, b1): \n", 124 | " qc.cx(q[a0], q[b0])\n", 125 | " qc.x(q[b0])\n", 126 | " qc.cx(q[a1], q[b1])\n", 127 | " qc.x(q[b1])\n", 128 | "\n", 129 | "def equalsNoCcxDag(a0, a1, b0, b1): \n", 130 | " qc.x(q[b1])\n", 131 | " qc.cx(q[a1], q[b1])\n", 132 | " qc.x(q[b0])\n", 133 | " qc.cx(q[a0], q[b0])\n", 134 | " \n", 135 | "def computeEqualities():\n", 136 | " equalsNoCcx(2,3,6,7)\n", 137 | " qc.rccx(q[6], q[7], q[14])\n", 138 | " equalsNoCcxDag(2,3,6,7)\n", 139 | " \n", 140 | " equalsNoCcx(2,3,8,9)\n", 141 | " qc.rccx(q[8], q[9], q[15])\n", 142 | " equalsNoCcxDag(2,3,8,9)\n", 143 | " \n", 144 | " equalsNoCcx(4,5,6,7)\n", 145 | " qc.rccx(q[6], q[7], q[16])\n", 146 | " equalsNoCcxDag(4,5,6,7)\n", 147 | " \n", 148 | " equalsNoCcx(4,5,10,11)\n", 149 | " qc.rccx(q[10], q[11], q[17])\n", 150 | " equalsNoCcxDag(4,5,10,11)\n", 151 | " \n", 152 | " equalsNoCcx(4,5,12,13)\n", 153 | " qc.rccx(q[12], q[13], q[18])\n", 154 | " equalsNoCcxDag(4,5,12,13)\n", 155 | " \n", 156 | " equalsNoCcx(6,7,12,13)\n", 157 | " qc.rccx(q[12], q[13], q[19])\n", 158 | " equalsNoCcxDag(6,7,12,13)\n", 159 | " \n", 160 | " equalsNoCcx(8,9,12,13)\n", 161 | " qc.rccx(q[12], q[13], q[20])\n", 162 | " equalsNoCcxDag(8,9,12,13)\n", 163 | " \n", 164 | " equalsNoCcx(10,11,12,13)\n", 165 | " qc.rccx(q[12], q[13], q[21])\n", 166 | " \n", 167 | " equalsNoCcx(0,1,2,3)\n", 168 | " qc.rccx(q[2], q[3], q[22])\n", 169 | " \n", 170 | " equalsNoCcx(0,1,4,5)\n", 171 | " qc.rccx(q[4], q[5], q[23])\n", 172 | " \n", 173 | " equalsNoCcx(6,7,8,9)\n", 174 | " qc.rccx(q[8], q[9], q[24])\n", 175 | " \n", 176 | " equalsNoCcx(6,7,10,11)\n", 177 | " qc.rccx(q[10], q[11], q[25])\n", 178 | " \n", 179 | " equalsNoCcx(0,1,6,7)\n", 180 | " qc.rccx(q[6], q[7], q[26])\n", 181 | " \n", 182 | "def computeEqualitiesDag():\n", 183 | " qc.rccx(q[6], q[7], q[26])\n", 184 | " equalsNoCcxDag(0,1,6,7)\n", 185 | " \n", 186 | " qc.rccx(q[10], q[11], q[25])\n", 187 | " equalsNoCcxDag(6,7,10,11)\n", 188 | " \n", 189 | " qc.rccx(q[8], q[9], q[24])\n", 190 | " equalsNoCcxDag(6,7,8,9)\n", 191 | " \n", 192 | " qc.rccx(q[4], q[5], q[23])\n", 193 | " equalsNoCcxDag(0,1,4,5)\n", 194 | " \n", 195 | " qc.rccx(q[2], q[3], q[22])\n", 196 | " equalsNoCcxDag(0,1,2,3)\n", 197 | " \n", 198 | " qc.rccx(q[12], q[13], q[21])\n", 199 | " equalsNoCcxDag(10,11,12,13)\n", 200 | " \n", 201 | " equalsNoCcx(8,9,12,13)\n", 202 | " qc.rccx(q[12], q[13], q[20])\n", 203 | " equalsNoCcxDag(8,9,12,13)\n", 204 | " \n", 205 | " equalsNoCcx(6,7,12,13)\n", 206 | " qc.rccx(q[12], q[13], q[19])\n", 207 | " equalsNoCcxDag(6,7,12,13)\n", 208 | " \n", 209 | " equalsNoCcx(4,5,12,13)\n", 210 | " qc.rccx(q[12], q[13], q[18])\n", 211 | " equalsNoCcxDag(4,5,12,13)\n", 212 | " \n", 213 | " equalsNoCcx(4,5,10,11)\n", 214 | " qc.rccx(q[10], q[11], q[17])\n", 215 | " equalsNoCcxDag(4,5,10,11)\n", 216 | " \n", 217 | " equalsNoCcx(4,5,6,7)\n", 218 | " qc.rccx(q[6], q[7], q[16])\n", 219 | " equalsNoCcxDag(4,5,6,7)\n", 220 | " \n", 221 | " equalsNoCcx(2,3,8,9)\n", 222 | " qc.rccx(q[8], q[9], q[15])\n", 223 | " equalsNoCcxDag(2,3,8,9)\n", 224 | " \n", 225 | " equalsNoCcx(2,3,6,7)\n", 226 | " qc.rccx(q[6], q[7], q[14])\n", 227 | " equalsNoCcxDag(2,3,6,7)\n", 228 | " \n", 229 | "def oracle():\n", 230 | " computeEqualities()\n", 231 | " \n", 232 | " qc.x(q[14:27])\n", 233 | " qc.rccx(q[14], q[15], q[28])\n", 234 | " qc.rccx(q[16], q[17], q[29])\n", 235 | " qc.rccx(q[18], q[19], q[30])\n", 236 | " qc.rccx(q[20], q[21], q[31])\n", 237 | " qc.mct([q[22],q[23],q[24],q[25],q[26],q[28],q[29],q[30],q[31]], q[27] , [q[0], q[1], q[2], q[3], q[4], q[5], q[6]], mode='basic-dirty-ancilla')\n", 238 | " qc.rccx(q[14], q[15], q[28])\n", 239 | " qc.rccx(q[16], q[17], q[29])\n", 240 | " qc.rccx(q[18], q[19], q[30])\n", 241 | " qc.rccx(q[20], q[21], q[31])\n", 242 | " qc.x(q[14:27])\n", 243 | " \n", 244 | " computeEqualitiesDag()" 245 | ] 246 | }, 247 | { 248 | "cell_type": "markdown", 249 | "metadata": {}, 250 | "source": [ 251 | "**Phase Shift**\n", 252 | "\n", 253 | "The phase shift operation is tipical: a multiple controlled Z gate sandwitched between X gates. This time we do have enough free ancillas for the mct gate." 254 | ] 255 | }, 256 | { 257 | "cell_type": "code", 258 | "execution_count": 3, 259 | "metadata": {}, 260 | "outputs": [], 261 | "source": [ 262 | "def phaseShift():\n", 263 | " qc.x(q[0:14])\n", 264 | " qc.barrier()\n", 265 | " qc.h(q[13])\n", 266 | " qc.mct(q[0:13], q[13] , q[14:25], mode='basic')\n", 267 | " qc.h(q[13])\n", 268 | " qc.barrier()\n", 269 | " qc.x(q[0:14])" 270 | ] 271 | }, 272 | { 273 | "cell_type": "markdown", 274 | "metadata": {}, 275 | "source": [ 276 | "**Final Optimizations**\n", 277 | "\n", 278 | "As a final optimization notice that when using toffoli gates we only need them up to a relative phase so we can replace all the `ccx()` gates with `rccx()`" 279 | ] 280 | }, 281 | { 282 | "cell_type": "code", 283 | "execution_count": 4, 284 | "metadata": {}, 285 | "outputs": [ 286 | { 287 | "data": { 288 | "text/plain": [ 289 | "" 290 | ] 291 | }, 292 | "execution_count": 4, 293 | "metadata": {}, 294 | "output_type": "execute_result" 295 | } 296 | ], 297 | "source": [ 298 | "q = QuantumRegister(32)\n", 299 | "c = ClassicalRegister(32)\n", 300 | "qc = QuantumCircuit(q,c)\n", 301 | "\n", 302 | "qc.x(q[27])\n", 303 | "qc.h(q[27])\n", 304 | "A()\n", 305 | "#qc.barrier()\n", 306 | "\n", 307 | "def groverIteration():\n", 308 | " oracle()\n", 309 | " ADag()\n", 310 | " phaseShift()\n", 311 | " A()\n", 312 | "\n", 313 | "for i in range(0,5):\n", 314 | " groverIteration()\n", 315 | "\n", 316 | "qc.measure(q[0:14], c[0:14])" 317 | ] 318 | }, 319 | { 320 | "cell_type": "code", 321 | "execution_count": null, 322 | "metadata": {}, 323 | "outputs": [], 324 | "source": [ 325 | "#provider = IBMQ.load_account()\n", 326 | "backend = provider.get_backend('ibmq_qasm_simulator')\n", 327 | "job = execute(qc, backend=backend, shots=8000, seed_simulator=12345, backend_options={\"fusion_enable\":True})\n", 328 | "result = job.result()\n", 329 | "count = result.get_counts()\n", 330 | "print(count)" 331 | ] 332 | }, 333 | { 334 | "cell_type": "code", 335 | "execution_count": 8, 336 | "metadata": {}, 337 | "outputs": [], 338 | "source": [ 339 | "# Input your quantum circuit\n", 340 | "circuit=qc\n", 341 | "# Input your result of the execute(groverCircuit, backend=backend, shots=shots).result()\n", 342 | "results = result\n", 343 | "count=results.get_counts()\n", 344 | "# Provide your team name\n", 345 | "name='Sorin'\n", 346 | "# Please indicate the number of times you have made a submission so far. \n", 347 | "# For example, if it's your 1st time to submit your answer, write 1. If it's your 5th time to submit your answer, write 5.\n", 348 | "times='6'" 349 | ] 350 | }, 351 | { 352 | "cell_type": "code", 353 | "execution_count": 9, 354 | "metadata": {}, 355 | "outputs": [], 356 | "source": [ 357 | "import json\n", 358 | "from qiskit.transpiler import PassManager\n", 359 | "from qiskit.transpiler.passes import Unroller\n", 360 | "\n", 361 | "# Unroll the circuit\n", 362 | "pass_ = Unroller(['u3', 'cx'])\n", 363 | "pm = PassManager(pass_)\n", 364 | "new_circuit = pm.run(circuit) \n", 365 | "\n", 366 | "# obtain gates\n", 367 | "gates=new_circuit.count_ops()\n", 368 | "\n", 369 | "#sort count\n", 370 | "count_sorted = sorted(count.items(), key=lambda x:x[1], reverse=True)\n", 371 | "\n", 372 | "# collect answers with Top 9 probability\n", 373 | "ans_list = count_sorted[0:9]\n", 374 | "\n", 375 | "# reverse ans_list\n", 376 | "ans_reversed = []\n", 377 | "for i in ans_list:\n", 378 | " ans_temp=[i[0][::-1],i[1]]\n", 379 | " ans_reversed.append(ans_temp)\n", 380 | "\n", 381 | "# convert each 2 bits into corresponding color. Add node0(0),node3(1),node8(2) and node11(3)\n", 382 | "ans_shaped = []\n", 383 | "for j in ans_reversed:\n", 384 | " ans_temp=j[0]\n", 385 | " nodeA = 0\n", 386 | " node0 = int(ans_temp[0] + ans_temp[1], 2)\n", 387 | " node1 = int(ans_temp[2] + ans_temp[3], 2)\n", 388 | " nodeB = 1\n", 389 | " node2 = int(ans_temp[4] + ans_temp[5], 2)\n", 390 | " node3 = int(ans_temp[6] + ans_temp[7], 2)\n", 391 | " node4 = int(ans_temp[8] + ans_temp[9], 2)\n", 392 | " nodeC = 2\n", 393 | " node5 = int(ans_temp[10] + ans_temp[11], 2)\n", 394 | " node6 = int(ans_temp[12] + ans_temp[13], 2)\n", 395 | " nodeD = 3\n", 396 | " nodes_color = str(nodeA) + str(node0) + str(node1) + str(nodeB) + str(node2) + str(node3) + str(node4) + str(nodeC) + str(node5) + str(node6) + str(nodeD) \n", 397 | " ans_shaped.append([nodes_color,j[1]])\n", 398 | "\n", 399 | "# write the result into '[your name]_final_output.txt'\n", 400 | "filename=name+'_'+times+'_final_output.txt'\n", 401 | "dct={'ans':ans_shaped,'costs':gates}\n", 402 | "with open(filename, 'w') as f:\n", 403 | " json.dump(dct, f)\n" 404 | ] 405 | }, 406 | { 407 | "cell_type": "code", 408 | "execution_count": 10, 409 | "metadata": {}, 410 | "outputs": [], 411 | "source": [ 412 | "# Input the path of your submission file\n", 413 | "your_path='./Sorin_6_final_output.txt'" 414 | ] 415 | }, 416 | { 417 | "cell_type": "code", 418 | "execution_count": 11, 419 | "metadata": {}, 420 | "outputs": [ 421 | { 422 | "name": "stdout", 423 | "output_type": "stream", 424 | "text": [ 425 | "Your name: Sorin\n", 426 | "The number of times you have submitted your answer: 6\n", 427 | "<_io.TextIOWrapper name='Sorin_6_final_output.txt' mode='r' encoding='cp1252'>\n", 428 | "Does your submission file have 9 answers?\n", 429 | "- Yes\n", 430 | "- Your plan: [['01313202013', 792], ['01013232103', 754], ['01013232013', 720], ['02013132023', 389], ['02313102023', 389], ['02013132203', 365], ['02013122203', 356], ['02011322203', 187], ['02313122203', 179]]\n", 431 | "What is your cost?\n" 432 | ] 433 | }, 434 | { 435 | "data": { 436 | "text/plain": [ 437 | "21667" 438 | ] 439 | }, 440 | "execution_count": 11, 441 | "metadata": {}, 442 | "output_type": "execute_result" 443 | } 444 | ], 445 | "source": [ 446 | "import json\n", 447 | "from pathlib import Path\n", 448 | "\n", 449 | "p= Path(your_path)\n", 450 | "\n", 451 | "# Verify your information\n", 452 | "f_name=p.name\n", 453 | "your_info=f_name.split('_')\n", 454 | "print('Your name: ', your_info[0])\n", 455 | "print('The number of times you have submitted your answer: ', your_info[1])\n", 456 | "\n", 457 | "with open(p, 'r') as f:\n", 458 | " print(f)\n", 459 | " your_ans=json.load(f)\n", 460 | "\n", 461 | "print('Does your submission file have 9 answers?')\n", 462 | "if (len(your_ans['ans'])!=9):\n", 463 | " print('- No, make sure you have 9 answers with top 9 probabilities')\n", 464 | "else:\n", 465 | " print('- Yes')\n", 466 | " print('- Your plan: ', your_ans['ans'])\n", 467 | "\n", 468 | "print('What is your cost?')\n", 469 | "your_cost=your_ans['costs']['u3'] + 10*your_ans['costs']['cx']\n", 470 | "your_cost" 471 | ] 472 | } 473 | ], 474 | "metadata": { 475 | "kernelspec": { 476 | "display_name": "Python 3", 477 | "language": "python", 478 | "name": "python3" 479 | } 480 | }, 481 | "nbformat": 4, 482 | "nbformat_minor": 2 483 | } 484 | -------------------------------------------------------------------------------- /top ten submissions/Sorin/readme.txt: -------------------------------------------------------------------------------- 1 | #IBM Quantum Challenge 2019 2 | #Instructions for top ten teams for preparing their illustrative explanation of their submissions. 3 | 4 | Dear Team, 5 | 6 | Congratulations for making it into the top ten teams of IBM Quantum Challenge! 7 | 8 | Judges have reviewed your submissions and have verified your final score. We will be making an official announcement next week to show the final standings. 9 | 10 | In the meantime, we are asking all top ten teams to: 11 | 12 | 13 | -Prepare a write-up on how your team obtained the answers for the final challenge. 14 | 15 | -You may either add explanations to your ipynb file OR provide detailed comments in your .py file. 16 | 17 | -While we do not have a specific format for you to follow, we would like to ask you to focus on providing an illustrative explanation of your strategy, approach, techniques (creativity) you used to achieve lower quantum costs. 18 | 19 | -A folder saying 'top ten submissions' will be prepared in the github repository containing another set of folders each named after your teams. Please push your write-ups into these folders by Monday Oct 21st, noon JST. 20 | 21 | 22 | IBM Quantum Challenge Organizers -------------------------------------------------------------------------------- /top ten submissions/Sorin/tokyo_map_colored.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantum-challenge/2019/0d6b7c5e6c878c885b9619ac84dfdc5e287ce9a6/top ten submissions/Sorin/tokyo_map_colored.png -------------------------------------------------------------------------------- /top ten submissions/TheAxiom/readme.txt: -------------------------------------------------------------------------------- 1 | #IBM Quantum Challenge 2019 2 | #Instructions for top ten teams for preparing their illustrative explanation of their submissions. 3 | 4 | Dear Team, 5 | 6 | Congratulations for making it into the top ten teams of IBM Quantum Challenge! 7 | 8 | Judges have reviewed your submissions and have verified your final score. We will be making an official announcement next week to show the final standings. 9 | 10 | In the meantime, we are asking all top ten teams to: 11 | 12 | 13 | -Prepare a write-up on how your team obtained the answers for the final challenge. 14 | 15 | -You may either add explanations to your ipynb file OR provide detailed comments in your .py file. 16 | 17 | -While we do not have a specific format for you to follow, we would like to ask you to focus on providing an illustrative explanation of your strategy, approach, techniques (creativity) you used to achieve lower quantum costs. 18 | 19 | -A folder saying 'top ten submissions' will be prepared in the github repository containing another set of folders each named after your teams. Please push your write-ups into these folders by Monday Oct 21st, noon JST. 20 | 21 | 22 | IBM Quantum Challenge Organizers -------------------------------------------------------------------------------- /top ten submissions/Tofolli Pizza/Toffoli Pizza.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 41, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit\n", 10 | "from qiskit import IBMQ, Aer, execute\n", 11 | "import numpy as np\n", 12 | "\n", 13 | "# IBMQ.load_account()" 14 | ] 15 | }, 16 | { 17 | "cell_type": "markdown", 18 | "metadata": {}, 19 | "source": [ 20 | "# Overview" 21 | ] 22 | }, 23 | { 24 | "cell_type": "markdown", 25 | "metadata": {}, 26 | "source": [ 27 | "We have to apply Grover's algorithm to 7 nodes, each encoded with a number from 00 to 11, and thus requiring two qubits. Note, however, that the graph's structure fixes the LSB of node 2 to \"1\", since it cannot be equal to A = 00 nor C = 10. This means that we have 13 input qubits to feed our Grover's algorithm.\n", 28 | "\n", 29 | "The idea behind the oracle is to test all 19 remaining edges of the graph, each test representing whether the connected nodes are equal (outcome=0) or different (outcome=1). We then mark the corresponding state with a phase only if all tests are \"1\".\n", 30 | "\n", 31 | "Each test is performed as described in function \"two_group\" further down below. The main point is that we cannot store all the tests into qubits for lack of space. Therefore, we do two tests at a time, and then do an AND between the outcomes: only if both tests were 1 is the overall result also 1, which we then store in a qubit." 32 | ] 33 | }, 34 | { 35 | "cell_type": "markdown", 36 | "metadata": {}, 37 | "source": [ 38 | "The functions below are condensed versions of the basic operations needed throughout the circuit. They are optimized to condense adjacent single-qubit gates into single U3 gates." 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": 29, 44 | "metadata": {}, 45 | "outputs": [], 46 | "source": [ 47 | "#Optimized AND and OR\n", 48 | "def AND(qc,a,b,out):\n", 49 | " qc.ry(np.pi/4,out)\n", 50 | " qc.cx(a,out)\n", 51 | " #qc.ry(-np.pi/4,out)\n", 52 | " qc.u3(3*np.pi/4,0,np.pi,out)\n", 53 | " #qc.h(out)\n", 54 | " qc.cx(b,out)\n", 55 | " #qc.h(out)\n", 56 | " qc.u3(3*np.pi/4,0,np.pi,out)\n", 57 | " #qc.ry(np.pi/4,out)\n", 58 | " qc.cx(a,out)\n", 59 | " qc.ry(-np.pi/4,out)\n", 60 | " \n", 61 | " \n", 62 | "def OR(qc,a,b,out, safe=False): #This flips the input states if safe=False, but leaves them unchanged if safe=TRUE\n", 63 | " qc.x(a)\n", 64 | " qc.x(b)\n", 65 | " \n", 66 | " qc.ry(np.pi/4,out)\n", 67 | " qc.cx(a,out)\n", 68 | " #qc.ry(-np.pi/4,out)\n", 69 | " qc.u3(3*np.pi/4,0,np.pi,out)\n", 70 | " #qc.h(out)\n", 71 | " qc.cx(b,out)\n", 72 | " #qc.h(out)\n", 73 | " qc.u3(3*np.pi/4,0,np.pi,out)\n", 74 | " #qc.ry(np.pi/4,out)\n", 75 | " qc.cx(a,out)\n", 76 | " \n", 77 | " #qc.ry(-np.pi/4,out)\n", 78 | " #qc.x(out)\n", 79 | " qc.u3(3*np.pi/4,-np.pi,0,out)\n", 80 | " \n", 81 | " if safe == True:\n", 82 | " qc.x(a)\n", 83 | " qc.x(b)\n", 84 | " \n", 85 | " \n", 86 | "def iOR(qc,a,b,out,safe = False): #Reverse of the OR function\n", 87 | " \n", 88 | " if safe == True:\n", 89 | " qc.x(b)\n", 90 | " qc.x(a)\n", 91 | " \n", 92 | " qc.u3(3*np.pi/4,np.pi,0,out)\n", 93 | " \n", 94 | " qc.cx(a,out)\n", 95 | " #qc.ry(-np.pi/4,out)\n", 96 | " qc.u3(3*np.pi/4,0,np.pi,out)\n", 97 | " #qc.h(out)\n", 98 | " qc.cx(b,out)\n", 99 | " #qc.h(out)\n", 100 | " qc.u3(3*np.pi/4,0,np.pi,out)\n", 101 | " #qc.ry(np.pi/4,out)\n", 102 | " qc.cx(a,out)\n", 103 | " \n", 104 | " qc.ry(-np.pi/4,out)\n", 105 | " \n", 106 | " qc.x(b)\n", 107 | " qc.x(a)\n", 108 | " \n", 109 | " \n", 110 | "#Building blocks of a multi-controll-toffoli gate \n", 111 | "\n", 112 | "def block1(qc,a,b,target): \n", 113 | " qc.cx(b,target)\n", 114 | " qc.u3(0,0,-np.pi/4,target)\n", 115 | " qc.cx(a,target)\n", 116 | " qc.u3(0,0,np.pi/4,target)\n", 117 | " qc.cx(b,target)\n", 118 | " qc.u3(np.pi/2,0,3*np.pi/4,target)\n", 119 | " \n", 120 | "def block2(qc,a,b,target):\n", 121 | " qc.cx(b,target)\n", 122 | " qc.u3(0,0,-np.pi/4,target)\n", 123 | " qc.cx(a,target)\n", 124 | " qc.u3(0,0,np.pi/4,target)\n", 125 | " qc.cx(b,target)\n", 126 | " qc.u3(np.pi/2,np.pi/4,np.pi,b)\n", 127 | " qc.u3(np.pi/2,0,3*np.pi/4,target)\n", 128 | " \n", 129 | "#--------------------------------------\n", 130 | "\n", 131 | "#Optimized version of the mct, adapted for the average inversion part of Grover's algorithm (if avg_inv=True)\n", 132 | " \n", 133 | "def mct(qc,ctrl,target,anc,avg_inv=False):\n", 134 | " nctrl=len(ctrl)\n", 135 | " nanc=len(anc)\n", 136 | " \n", 137 | " if avg_inv == False:\n", 138 | " qc.u3(np.pi/2,0,np.pi,target)\n", 139 | " \n", 140 | " qc.u3(np.pi/2,np.pi/4,np.pi,anc)\n", 141 | " \n", 142 | " block1(qc,ctrl[0],ctrl[1],anc[0])\n", 143 | " \n", 144 | " for i in range(1,nanc):\n", 145 | " block1(qc,ctrl[i+1],anc[i-1],anc[i])\n", 146 | " \n", 147 | " qc.cx(anc[-1],target)\n", 148 | " qc.u3(0,0,-np.pi/4,target)\n", 149 | " qc.cx(ctrl[-1],target)\n", 150 | " qc.u3(0,0,np.pi/4,target)\n", 151 | " qc.cx(anc[-1],target)\n", 152 | " qc.u3(0,0,-np.pi/4,target)\n", 153 | " qc.u3(0,0,np.pi/4,anc[-1])\n", 154 | " qc.cx(ctrl[-1],target)\n", 155 | " qc.cx(ctrl[-1],anc[-1])\n", 156 | " qc.u3(np.pi/2,np.pi*avg_inv,5*np.pi/4,target) #Changes if avg_inv = True\n", 157 | " qc.u3(0,0,np.pi/4,ctrl[-1])\n", 158 | " qc.u3(0,0,-np.pi/4,anc[-1])\n", 159 | " qc.cx(ctrl[-1],anc[-1])\n", 160 | " qc.u3(np.pi/2,np.pi/4,np.pi,anc[-1])\n", 161 | " \n", 162 | " for i in range(1,nanc)[::-1]:\n", 163 | " block2(qc,ctrl[i+1],anc[i-1],anc[i])\n", 164 | " \n", 165 | " qc.cx(ctrl[1],anc[0])\n", 166 | " qc.u3(0,0,-np.pi/4,anc[0])\n", 167 | " qc.cx(ctrl[0],anc[0])\n", 168 | " qc.u3(0,0,np.pi/4,anc[0])\n", 169 | " qc.cx(ctrl[1],anc[0])\n", 170 | " qc.u3(np.pi/2,0,3*np.pi/4,anc[0])\n", 171 | " \n", 172 | "#Optimized multi-controlled-Z gate \n", 173 | "def mcz(qc,ctrl,target,anc):\n", 174 | " nctrl=len(ctrl)\n", 175 | " nanc=len(anc)\n", 176 | " \n", 177 | " #qc.u3(np.pi/2,0,np.pi,target)\n", 178 | " \n", 179 | " qc.u3(np.pi/2,np.pi/4,np.pi,anc)\n", 180 | " \n", 181 | " block1(qc,ctrl[0],ctrl[1],anc[0])\n", 182 | " \n", 183 | " for i in range(1,nanc):\n", 184 | " block1(qc,ctrl[i+1],anc[i-1],anc[i])\n", 185 | " \n", 186 | " qc.cx(anc[-1],target)\n", 187 | " qc.u3(0,0,-np.pi/4,target)\n", 188 | " qc.cx(ctrl[-1],target)\n", 189 | " qc.u3(0,0,np.pi/4,target)\n", 190 | " qc.cx(anc[-1],target)\n", 191 | " qc.u3(0,0,-np.pi/4,target)\n", 192 | " qc.u3(0,0,np.pi/4,anc[-1])\n", 193 | " qc.cx(ctrl[-1],target)\n", 194 | " qc.cx(ctrl[-1],anc[-1])\n", 195 | " qc.u3(0,0,np.pi/4,target)\n", 196 | " qc.u3(0,0,np.pi/4,ctrl[-1])\n", 197 | " qc.u3(0,0,-np.pi/4,anc[-1])\n", 198 | " qc.cx(ctrl[-1],anc[-1])\n", 199 | " qc.u3(np.pi/2,np.pi/4,np.pi,anc[-1])\n", 200 | " \n", 201 | " for i in range(1,nanc)[::-1]:\n", 202 | " block2(qc,ctrl[i+1],anc[i-1],anc[i])\n", 203 | " \n", 204 | " qc.cx(ctrl[1],anc[0])\n", 205 | " qc.u3(0,0,-np.pi/4,anc[0])\n", 206 | " qc.cx(ctrl[0],anc[0])\n", 207 | " qc.u3(0,0,np.pi/4,anc[0])\n", 208 | " qc.cx(ctrl[1],anc[0])\n", 209 | " qc.u3(np.pi/2,0,3*np.pi/4,anc[0])" 210 | ] 211 | }, 212 | { 213 | "cell_type": "code", 214 | "execution_count": 30, 215 | "metadata": {}, 216 | "outputs": [], 217 | "source": [ 218 | "#Average inversion part of Grover's algorithm: standard form, just simplified by merging neighbouring single-qubit gates\n", 219 | "def average_inversion2(qc,q):\n", 220 | " idx = [i for i in range(13)]\n", 221 | " idx.remove(4)\n", 222 | " \n", 223 | " # qc.barrier()\n", 224 | " \n", 225 | " qc.u3(np.pi/2,0,0,q[0:4])\n", 226 | " qc.u3(np.pi/2,0,0,q[5:14])\n", 227 | " \n", 228 | " mct(qc,[q[i] for i in idx], q[13], q[15:25],avg_inv=True)\n", 229 | " \n", 230 | " qc.u3(np.pi/2,np.pi,np.pi,q[0:4])\n", 231 | " qc.u3(np.pi/2,np.pi,np.pi,q[5:13]) " 232 | ] 233 | }, 234 | { 235 | "cell_type": "markdown", 236 | "metadata": {}, 237 | "source": [ 238 | "# Oracle\n", 239 | "\n", 240 | "As stated above, we test two edges at a time and then store the result in a single qubit. In the following explanation node 1 is connected to node 2 and node 1 is connected to node 3. \n", 241 | "\n", 242 | "The test of the two edges is performed as follows:\n", 243 | "\n", 244 | "1. A cnot from the lsb of node 1 to node 2\n", 245 | "2. A cnot from the msb of node 1 to node 2\n", 246 | "3. An OR between the lsb and msb of node 2 temporarily storing the result in what we call an operational ancilla.\n", 247 | "4. A cnot from the lsb of node 3 to node 1\n", 248 | "5. A cnot from the msb of node 3 to node 1\n", 249 | "6. An OR between the lsb and msb of node 1 temporarily storing the result in another operational ancilla.\n", 250 | "7. An AND between both operational ancillas storing the result in what we refer to as a storage quibit. This storage quibit will only be |1> when the two edges are valid" 251 | ] 252 | }, 253 | { 254 | "cell_type": "code", 255 | "execution_count": 31, 256 | "metadata": {}, 257 | "outputs": [], 258 | "source": [ 259 | "# Two-group function\n", 260 | "def two_group(qc, base_node, t1, t2, ancilla, target, dirty=[]):\n", 261 | " \"\"\"\n", 262 | " The two_group function is the basic element of the oracle. It performs two tests, first comparing the base_node with t1, \n", 263 | " with stored results in t1, and then comparing base_node with t2, storing the results in base_node. \n", 264 | " An OR is made between the qubits of the nodes that hold the results, returning whether they were equal or different to \n", 265 | " the \"ancilla\" qubits. Then, an AND is performed between the ancillas, to store the combined result of both tests\n", 266 | " \n", 267 | " All these operations, except the AND, are then reversed, unless otherwise stated in the \"dirty\" list.\n", 268 | " \n", 269 | " Parameters\n", 270 | " ----------\n", 271 | " qc: QuantumCircuit\n", 272 | " Quantum circuit.\n", 273 | " \n", 274 | " base_node: list of 2 QuantumRegister \n", 275 | " Origin node for three-group comparison. |lsb, msb>\n", 276 | " \n", 277 | " t1, t2: list of 2 QuantumRegister\n", 278 | " First, second target nodes for comparison |lsb, msb>\n", 279 | " \n", 280 | " ancilla: list of 2 QuantumRegister\n", 281 | " Two ancillas are needed for intermediate computations. |0> afterwards\n", 282 | " \n", 283 | " target: QuantumRegister\n", 284 | " Target quantum register for the result. \n", 285 | " Target should be set to the ground state |0>.\n", 286 | " Target will change to |1> when all the target nodes are different from the base node\n", 287 | " but not necessarily different from each other. \n", 288 | " \n", 289 | " dirty: list\n", 290 | " Flag which QuantumRegisters should not be reverted.\n", 291 | " Possible elements of the list are:\n", 292 | " 'base_node', 't1', 'ancilla_1', 'ancilla_2'\n", 293 | " \n", 294 | " \"\"\"\n", 295 | " possible_flags = ['base_node', 't1', 'ancilla_1', 'ancilla_2']\n", 296 | " for _ in dirty:\n", 297 | " if _ not in possible_flags:\n", 298 | " raise ValueError('Wrong flags!')\n", 299 | " \n", 300 | " qc.cx(base_node[0], t1[0])\n", 301 | " qc.cx(base_node[1], t1[1])\n", 302 | " \n", 303 | " qc.cx(t2[0], base_node[0])\n", 304 | " qc.cx(t2[1], base_node[1])\n", 305 | " \n", 306 | " qc.barrier()\n", 307 | " \n", 308 | " OR(qc, t1[0], t1[1], ancilla[0], safe = ('ancilla_1' in dirty))\n", 309 | "\n", 310 | " OR(qc, base_node[0], base_node[1], ancilla[1], safe = ('ancilla_2' in dirty) )\n", 311 | " \n", 312 | " qc.barrier()\n", 313 | " \n", 314 | " AND(qc,ancilla[0],ancilla[1],target)\n", 315 | " \n", 316 | " qc.barrier()\n", 317 | " \n", 318 | " if 'ancilla_1' not in dirty:\n", 319 | " iOR(qc, t1[0], t1[1], ancilla[0])\n", 320 | "\n", 321 | " if 'ancilla_2' not in dirty:\n", 322 | " iOR(qc, base_node[0], base_node[1], ancilla[1])\n", 323 | " \n", 324 | " qc.barrier()\n", 325 | " \n", 326 | " if 'base_node' not in dirty:\n", 327 | " qc.cx(t2[1], base_node[1])\n", 328 | " qc.cx(t2[0], base_node[0])\n", 329 | " \n", 330 | " if 't1' not in dirty:\n", 331 | " qc.cx(base_node[1], t1[1])\n", 332 | " qc.cx(base_node[0], t1[0])\n", 333 | " \n", 334 | " \n", 335 | "# Two-group function\n", 336 | "def two_group_inverse(qc, base_node, t1, t2, ancilla, target, dirty=[]):\n", 337 | " \"\"\"\n", 338 | " This is just an inverted version of the two_group function, used to restore the target qubits back to their original\n", 339 | " state.\n", 340 | " \n", 341 | " \n", 342 | " Parameters\n", 343 | " ----------\n", 344 | " qc: QuantumCircuit\n", 345 | " Quantum circuit.\n", 346 | " \n", 347 | " base_node: list of 2 QuantumRegister \n", 348 | " Origin node for three-group comparison. |lsb, msb>\n", 349 | " \n", 350 | " t1, t2: list of 2 QuantumRegister\n", 351 | " First, second target nodes for comparison |lsb, msb>\n", 352 | " \n", 353 | " ancilla: list of 2 QuantumRegister\n", 354 | " Two ancillas are needed for intermediate computations. |0> afterwards\n", 355 | " \n", 356 | " target: QuantumRegister\n", 357 | " Target quantum register for the result. \n", 358 | " Target should be set to the ground state |0>.\n", 359 | " Target will change to |1> when all the target nodes are different from the base node\n", 360 | " but not necessarily different from each other. \n", 361 | " \n", 362 | " dirty: list\n", 363 | " Flag which QuantumRegisters should not be reverted.\n", 364 | " Possible elements of the list are:\n", 365 | " 'base_node', 't1', 'ancilla_1', 'ancilla_2'\n", 366 | " \n", 367 | " \"\"\"\n", 368 | " possible_flags = ['base_node', 't1', 'ancilla_1', 'ancilla_2']\n", 369 | " for _ in dirty:\n", 370 | " if _ not in possible_flags:\n", 371 | " raise ValueError('Wrong flags!')\n", 372 | " \n", 373 | " if 't1' not in dirty:\n", 374 | " qc.cx(base_node[0], t1[0])\n", 375 | " qc.cx(base_node[1], t1[1])\n", 376 | " \n", 377 | " if 'base_node' not in dirty:\n", 378 | " qc.cx(t2[0], base_node[0])\n", 379 | " qc.cx(t2[1], base_node[1])\n", 380 | " \n", 381 | " qc.barrier()\n", 382 | " \n", 383 | " if 'ancilla_1' not in dirty:\n", 384 | " OR(qc, t1[0], t1[1], ancilla[0])\n", 385 | "\n", 386 | " if 'ancilla_2' not in dirty:\n", 387 | " OR(qc, base_node[0], base_node[1], ancilla[1])\n", 388 | " \n", 389 | " qc.barrier()\n", 390 | " \n", 391 | " AND(qc,ancilla[0],ancilla[1],target)\n", 392 | " \n", 393 | " qc.barrier()\n", 394 | " \n", 395 | " \n", 396 | " iOR(qc, t1[0], t1[1], ancilla[0],safe = ('ancilla_1' in dirty))\n", 397 | "\n", 398 | " \n", 399 | " iOR(qc, base_node[0], base_node[1], ancilla[1], safe = ('ancilla_2' in dirty))\n", 400 | " \n", 401 | " qc.barrier()\n", 402 | " \n", 403 | " \n", 404 | " qc.cx(t2[1], base_node[1])\n", 405 | " qc.cx(t2[0], base_node[0])\n", 406 | " \n", 407 | "\n", 408 | " qc.cx(base_node[1], t1[1])\n", 409 | " qc.cx(base_node[0], t1[0])\n", 410 | " \n", 411 | " " 412 | ] 413 | }, 414 | { 415 | "cell_type": "code", 416 | "execution_count": 32, 417 | "metadata": {}, 418 | "outputs": [], 419 | "source": [ 420 | "def full_oracle2(qc,q):\n", 421 | " '''\n", 422 | " Constructs the entire oracle. The tests in \"edges2\" are organized in such a way that the last time a node is tested, \n", 423 | " the result of the comparison is left stored in its quibits, only being reversed after the phase has been applied.\n", 424 | " The last time the operational ancillas are used, they are also left \"dirty\" to spare operations.\n", 425 | " \n", 426 | " \n", 427 | " Qubit setup :\n", 428 | " \n", 429 | " q[0:4],q[5:14] : State qubits, from node 0 to 6\n", 430 | " q[4] : |1>\n", 431 | " q[14] : |0>\n", 432 | " q[15:17] : Operational ancillas\n", 433 | " q[17:26]: Storage ancillas\n", 434 | " q[26:] : Ancillas\n", 435 | " \n", 436 | " '''\n", 437 | " #Each tuple represents two tests: base_node-t1 and base_node-t2. Only one test is left after these.\n", 438 | " edges2 = [ # (base_node, t1, t2, dirty) \n", 439 | " ('3','0','1', []),\n", 440 | " ('0','2','a', []), #_________ last '0'\n", 441 | " ('1','0','b', ['t1']),\n", 442 | " ('4','1','b', ['t1']), #_________ last '1'\n", 443 | " ('3','4','5', []), #_________ last '4'\n", 444 | " ('6','4','d', ['t1']),\n", 445 | " ('5','6','d', []), #_________ last '6'\n", 446 | " ('2','5','6', ['t1']), #_________ last '2'\n", 447 | " ('3','6','2', ['t1','ancilla_1', 'ancilla_2']) #_________ last '5'\n", 448 | " ] #Last one: 3-A ________________________ last '3'\n", 449 | " \n", 450 | " nodes = {\n", 451 | " 'a': [q[14], q[14]],\n", 452 | " 'b': [q[4], q[14]],\n", 453 | " 'c': [q[14], q[4]],\n", 454 | " 'd': [q[4], q[4]],\n", 455 | " '0': q[0:2],\n", 456 | " '1': q[2:4],\n", 457 | " '2': q[4:6],\n", 458 | " '3': q[6:8],\n", 459 | " '4': q[8:10],\n", 460 | " '5': q[10:12],\n", 461 | " '6': q[12:14],\n", 462 | " }\n", 463 | " \n", 464 | " op_ancillas= q[15:17]\n", 465 | " storage = q[17:26]\n", 466 | " ancillas = q[26:32] \n", 467 | " \n", 468 | " for i, (base, t1_n, t2_n, dirty) in enumerate(edges2): #Runs through all the tests in edges2\n", 469 | " two_group(qc, nodes[base], nodes[t1_n], nodes[t2_n], op_ancillas, storage[i], dirty)\n", 470 | " \n", 471 | " #Last test (from node A to node 3)\n", 472 | " qc.cx(nodes['a'][0], nodes['3'][0])\n", 473 | " qc.cx(nodes['a'][1], nodes['3'][1])\n", 474 | " \n", 475 | " OR(qc, nodes['3'][0], nodes['3'][1], q[14]) # Use q[14] that holds a |0>\n", 476 | " \n", 477 | " \n", 478 | " qc.x(q[4]) # Clean q4 to use as ancilla\n", 479 | " \n", 480 | " #Flips the phase of a state if all qubits in storage, plus the last test's result, are \"1\"\n", 481 | " mcz(qc,[q[14]]+storage[:-1], storage[-1], ancillas+[q[4]])\n", 482 | " \n", 483 | " qc.x(q[4])\n", 484 | " \n", 485 | " \n", 486 | " iOR(qc, nodes['3'][0], nodes['3'][1], q[14]) # Revert the state of q[14]\n", 487 | " \n", 488 | " qc.cx(nodes['a'][1], nodes['3'][1])\n", 489 | " qc.cx(nodes['a'][0], nodes['3'][0])\n", 490 | " \n", 491 | " for i, (base, t1_n, t2_n, dirty) in enumerate(edges2[::-1]): # Revert all the tests in edges2\n", 492 | " j = len(edges2)-i-1\n", 493 | " two_group_inverse(qc, nodes[base], nodes[t1_n], nodes[t2_n], op_ancillas, storage[j], dirty)" 494 | ] 495 | }, 496 | { 497 | "cell_type": "markdown", 498 | "metadata": {}, 499 | "source": [ 500 | "# Overview of the creative steps\n", 501 | "\n", 502 | "Our strategy began with identifying that we would need to test the edges two by two to have enough quibits left to use as ancillas for the phase inversion mct. The most significant simplifications were:\n", 503 | "1. Identifying that the lsb of node 2 had to be |1>\n", 504 | "2. Wait until after the phase flip to revert some of the previous operations\n", 505 | "3. Use the quibits that represented the fixed nodes (q[4] and q[14]) during the phase flip\n", 506 | "\n", 507 | "\n", 508 | "# Constructing the full circuit" 509 | ] 510 | }, 511 | { 512 | "cell_type": "code", 513 | "execution_count": 33, 514 | "metadata": {}, 515 | "outputs": [ 516 | { 517 | "data": { 518 | "text/plain": [ 519 | "" 520 | ] 521 | }, 522 | "execution_count": 33, 523 | "metadata": {}, 524 | "output_type": "execute_result" 525 | } 526 | ], 527 | "source": [ 528 | "q = QuantumRegister(32)\n", 529 | "c = ClassicalRegister(14)\n", 530 | "qc = QuantumCircuit(q,c)\n", 531 | "\n", 532 | "#State preparation\n", 533 | "\n", 534 | "qc.h(q[0:4])\n", 535 | "qc.h(q[5:14])\n", 536 | "qc.x(q[4])\n", 537 | "\n", 538 | "\n", 539 | "#Five complete iterations of Grover's algorithm\n", 540 | "for _ in range(5):\n", 541 | " full_oracle2(qc,q)\n", 542 | " average_inversion2(qc,q)\n", 543 | " \n", 544 | "\n", 545 | "#Measurement\n", 546 | "# qc.measure(q[0:14],c[0:14]) # Our notation\n", 547 | "# IMB Challenge notation. Convert our storage logic to the one required by the contest\n", 548 | "qc.measure(q[0], c[1])\n", 549 | "qc.measure(q[1], c[0])\n", 550 | "\n", 551 | "qc.measure(q[2], c[3])\n", 552 | "qc.measure(q[3], c[2])\n", 553 | "\n", 554 | "qc.measure(q[4], c[5])\n", 555 | "qc.measure(q[5], c[4])\n", 556 | "\n", 557 | "qc.measure(q[6], c[7])\n", 558 | "qc.measure(q[7], c[6])\n", 559 | "\n", 560 | "qc.measure(q[8], c[9])\n", 561 | "qc.measure(q[9], c[8])\n", 562 | "\n", 563 | "qc.measure(q[10], c[11])\n", 564 | "qc.measure(q[11], c[10])\n", 565 | "\n", 566 | "qc.measure(q[12], c[13])\n", 567 | "qc.measure(q[13], c[12])" 568 | ] 569 | }, 570 | { 571 | "cell_type": "code", 572 | "execution_count": 34, 573 | "metadata": {}, 574 | "outputs": [ 575 | { 576 | "data": { 577 | "text/plain": [ 578 | "OrderedDict([('u3', 3399), ('cx', 2530), ('barrier', 360), ('measure', 14)])" 579 | ] 580 | }, 581 | "execution_count": 34, 582 | "metadata": {}, 583 | "output_type": "execute_result" 584 | } 585 | ], 586 | "source": [ 587 | "from qiskit.transpiler.passes import Unroller\n", 588 | "from qiskit.transpiler import PassManager\n", 589 | "\n", 590 | "pass_ = Unroller(['u3', 'cx'])\n", 591 | "pm = PassManager(pass_)\n", 592 | "new_circuit = pm.run(qc) \n", 593 | "new_circuit.count_ops()" 594 | ] 595 | } 596 | ], 597 | "metadata": { 598 | "kernelspec": { 599 | "display_name": "Python 3", 600 | "language": "python", 601 | "name": "python3" 602 | }, 603 | "language_info": { 604 | "codemirror_mode": { 605 | "name": "ipython", 606 | "version": 3 607 | }, 608 | "file_extension": ".py", 609 | "mimetype": "text/x-python", 610 | "name": "python", 611 | "nbconvert_exporter": "python", 612 | "pygments_lexer": "ipython3", 613 | "version": "3.7.3" 614 | } 615 | }, 616 | "nbformat": 4, 617 | "nbformat_minor": 2 618 | } 619 | -------------------------------------------------------------------------------- /top ten submissions/Tofolli Pizza/readme.txt: -------------------------------------------------------------------------------- 1 | #IBM Quantum Challenge 2019 2 | #Instructions for top ten teams for preparing their illustrative explanation of their submissions. 3 | 4 | Dear Team, 5 | 6 | Congratulations for making it into the top ten teams of IBM Quantum Challenge! 7 | 8 | Judges have reviewed your submissions and have verified your final score. We will be making an official announcement next week to show the final standings. 9 | 10 | In the meantime, we are asking all top ten teams to: 11 | 12 | 13 | -Prepare a write-up on how your team obtained the answers for the final challenge. 14 | 15 | -You may either add explanations to your ipynb file OR provide detailed comments in your .py file. 16 | 17 | -While we do not have a specific format for you to follow, we would like to ask you to focus on providing an illustrative explanation of your strategy, approach, techniques (creativity) you used to achieve lower quantum costs. 18 | 19 | -A folder saying 'top ten submissions' will be prepared in the github repository containing another set of folders each named after your teams. Please push your write-ups into these folders by Monday Oct 21st, noon JST. 20 | 21 | 22 | IBM Quantum Challenge Organizers -------------------------------------------------------------------------------- /top ten submissions/Whit3z/readme.txt: -------------------------------------------------------------------------------- 1 | #IBM Quantum Challenge 2019 2 | #Instructions for top ten teams for preparing their illustrative explanation of their submissions. 3 | 4 | Dear Team, 5 | 6 | Congratulations for making it into the top ten teams of IBM Quantum Challenge! 7 | 8 | Judges have reviewed your submissions and have verified your final score. We will be making an official announcement next week to show the final standings. 9 | 10 | In the meantime, we are asking all top ten teams to: 11 | 12 | 13 | -Prepare a write-up on how your team obtained the answers for the final challenge. 14 | 15 | -You may either add explanations to your ipynb file OR provide detailed comments in your .py file. 16 | 17 | -While we do not have a specific format for you to follow, we would like to ask you to focus on providing an illustrative explanation of your strategy, approach, techniques (creativity) you used to achieve lower quantum costs. 18 | 19 | -A folder saying 'top ten submissions' will be prepared in the github repository containing another set of folders each named after your teams. Please push your write-ups into these folders by Monday Oct 21st, noon JST. 20 | 21 | 22 | IBM Quantum Challenge Organizers -------------------------------------------------------------------------------- /top ten submissions/rainy_day_hackers/readme.txt: -------------------------------------------------------------------------------- 1 | #IBM Quantum Challenge 2019 2 | #Instructions for top ten teams for preparing their illustrative explanation of their submissions. 3 | 4 | Dear Team, 5 | 6 | Congratulations for making it into the top ten teams of IBM Quantum Challenge! 7 | 8 | Judges have reviewed your submissions and have verified your final score. We will be making an official announcement next week to show the final standings. 9 | 10 | In the meantime, we are asking all top ten teams to: 11 | 12 | 13 | -Prepare a write-up on how your team obtained the answers for the final challenge. 14 | 15 | -You may either add explanations to your ipynb file OR provide detailed comments in your .py file. 16 | 17 | -While we do not have a specific format for you to follow, we would like to ask you to focus on providing an illustrative explanation of your strategy, approach, techniques (creativity) you used to achieve lower quantum costs. 18 | 19 | -A folder saying 'top ten submissions' will be prepared in the github repository containing another set of folders each named after your teams. Please push your write-ups into these folders by Monday Oct 21st, noon JST. 20 | 21 | 22 | IBM Quantum Challenge Organizers -------------------------------------------------------------------------------- /top ten submissions/readme.txt: -------------------------------------------------------------------------------- 1 | #IBM Quantum Challenge 2019 2 | #Instructions for top ten teams for preparing their illustrative explanation of their submissions. 3 | 4 | Dear Team, 5 | 6 | Congratulations for making it into the top ten teams of IBM Quantum Challenge! 7 | 8 | Judges have reviewed your submissions and have verified your final score. We will be making an official announcement next week to show the final standings. 9 | 10 | In the meantime, we are asking all top ten teams to: 11 | 12 | 13 | -Prepare a write-up on how your team obtained the answers for the final challenge. 14 | 15 | -You may either add explanations to your ipynb file OR provide detailed comments in your .py file. 16 | 17 | -While we do not have a specific format for you to follow, we would like to ask you to focus on providing an illustrative explanation of your strategy, approach, techniques (creativity) you used to achieve lower quantum costs. 18 | 19 | -A folder saying 'top ten submissions' will be prepared in the github repository containing another set of folders each named after your teams. Please push your write-ups into these folders by Monday Oct 21st, noon JST. 20 | 21 | 22 | IBM Quantum Challenge Organizers -------------------------------------------------------------------------------- /top ten submissions/rp_cc_sqrt_2/(rp+cc)_sqrt(2)_final.py: -------------------------------------------------------------------------------- 1 | from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit 2 | from qiskit import IBMQ, Aer, execute 3 | 4 | # importing Qiskit 5 | from qiskit import IBMQ, BasicAer 6 | from qiskit.providers.ibmq import least_busy 7 | from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister, execute 8 | 9 | 10 | #################################################### 11 | # For the search problem there are 7 unset districts with id's from 0 to 6 and to encode it directly we need 14 qubits 12 | # (7 * 2). But there are some constraints: 13 | # 1. the 2 districts cannot be A and C so the only possible values are 01 and 11 so we can encode it in 1 qubit 14 | # 2. for 0 and 3 we know that both of them cannot be equal to 00 so there are 9=3*3 possibilities for bot of this 15 | # districts but because this boot is connected they cannot be equal so we have only 6 possibilities 16 | # 3. similar is for districts 1 and 4, and 5 and 6 so in total there are 2 * 6 * 6 * 6 = 432 possible combinations and 17 | # we can store the whole problem in 9 qubits ( log2(432) ), but regarding the encoding/decoding issues I've decided 18 | # to use 10 qubits (1 for 2 districts, 3 for 0 and 3 districts, 3 for 1 and 4, and 3 for 5 and 6 19 | # 20 | # So, the main idea of my solution is: 21 | # 1. encode the problem in 10 qubits 22 | # 2. create oracle function and constraint on 10 qubits search space 23 | # 3. do the Grover search 24 | # 4. decode the 10 qubits used in the algorithm to 14 qubits final solution required by the problem definition 25 | # 26 | # What we gain in this case, the original problem definition has 2^14 search space (16384) so the optimal number of the 27 | # Grover iteration is 33 (but we can find the answer in 5 iterations). After the search space reduction, there is only 28 | # 2^10 (1024) possible state so the optimal Grover iteration is 8 (and we can see the answer in 3 iterations only). 29 | # 30 | # The main problem, which I have was the to less number of the ancilla qubits, so in the constraints, after the calculate 31 | # the boolean function I have to revert the operation on the temporary qubits to avoid entanglements. 32 | # 33 | # 34 | #################################################### 35 | # The mapping 36 | # q[0] => district 2 37 | # 0 -> B 38 | # 1 -> D 39 | # q[1:3] => district 0 and 3 40 | # 03 41 | # 000 -> BC 42 | # 001 -> BD 43 | # 011 -> DB 44 | # 100 -> DC 45 | # 101 -> CD 46 | # 111 -> CB 47 | # 48 | # q[4:6] => district 1 and 4 49 | # 14 50 | # 000 -> AD 51 | # 001 -> AC 52 | # 011 -> CA 53 | # 100 -> CD 54 | # 101 -> DC 55 | # 111 -> DA 56 | # 57 | # q[7:9] => district 5 and 6 58 | # 56 59 | # 000 -> AB 60 | # 001 -> AC 61 | # 011 -> CA 62 | # 100 -> CB 63 | # 101 -> BC 64 | # 111 -> BA 65 | # 66 | #################################################### 67 | 68 | #################################################### 69 | # # 70 | # Example function definitions # 71 | # # 72 | #################################################### 73 | def check_allowed_state(qc, idx, out): 74 | """ 75 | There are only two states which are not allowed 010 and 110 so to calculate this we need the boolean function 76 | below: 77 | not (idx[1] and not(idx[0]) 78 | 79 | we assume that the 'out' cubit is in |1> state so ccx work for us as the NAND gate 80 | 81 | :param qc: Quantum Circuit 82 | :param idx: the index of the first qubit in the 2 districts node: 83 | 1 for districts 0 and 3 84 | 4 for districts 1 and 4 85 | 7 for districts 5 and 6 86 | :param out: the qubit where the calculated value will be stored, it has to be in |1> state before the function is 87 | called 88 | """ 89 | # the state 010 and 110 are not allowed 90 | qc.x(idx) 91 | qc.ccx(idx, idx + 1, out) # NAND 92 | # reverse x 93 | qc.x(idx) 94 | 95 | 96 | def check_356(qc, _03, _56, out, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8): 97 | """ 98 | For all constraint we have to do the same algorithm, I will show it on the check of node 3, 5 and 6. It is one of 99 | the most complicated checks. The other can be done similarly. 100 | 101 | 1. First, we create the truth table for the constraint. 102 | hint: when you look on the mapping for node 03 you will see that the value of 3 districts is independent of the 103 | value in index 0, so we can skip this in the true table 104 | 105 | 3 | 56 | 3 | 56 | value 106 | ---+-----+---+----|------- 107 | 00 | 000 | C | AB | 1 108 | 00 | 001 | C | AC | 0 109 | 00 | 011 | C | CA | 0 110 | ---+-----+---+----|------- 111 | 00 | 100 | C | CB | 0 112 | 00 | 101 | C | BC | 0 113 | 00 | 111 | C | BA | 1 114 | ---+-----+---+----|------- 115 | 11 | 000 | B | AB | 0 116 | 11 | 001 | B | AC | 1 117 | 11 | 011 | B | CA | 1 118 | ---+-----+---+----|------- 119 | 11 | 100 | B | CB | 0 120 | 11 | 101 | B | BC | 0 121 | 11 | 111 | B | BA | 0 122 | ---+-----+---+----|------- 123 | 01 | XXX | D | | 1 124 | ---+-----+---+----|------- 125 | 126 | So the needed fuction is: 127 | or ( 128 | and ( not(_03[1]), _03[2]) 129 | and ( not(_03[1]), 130 | or ( 131 | and( not(_56[0]), not(_56[1])) 132 | and (_56[0], _56[1]) 133 | ) 134 | ) 135 | and (_03[1], 136 | and (not(_56[0]), _56[2]) 137 | ) 138 | ) 139 | 140 | 141 | :param qc: Quantum Circuit 142 | :param _03: The index of for districts 0 and 3 143 | :param _56: 4 for districts 1 and 4 144 | :param out: the qubit where the calculated value will be stored 145 | :param tmp1-tmp8: the temporary qubits, we have to invert all changes of it after the calculate the output cubit 146 | """ 147 | # 3 - D 148 | qc.x(_03 + 1) 149 | qc.ccx(q[_03 + 1], q[_03 + 0], tmp1) 150 | 151 | # 3 - C 152 | # 56 - AB 153 | qc.x(_56 + 0) 154 | qc.x(_56 + 2) 155 | qc.ccx(q[_56 + 0], q[_56 + 2], tmp2) 156 | qc.x(_56 + 2) 157 | qc.x(_56 + 0) 158 | # 56 -BA 159 | qc.ccx(q[_56 + 1], q[_56 + 2], tmp3) 160 | gate_or(qc, tmp2, tmp3, tmp4) 161 | qc.ccx(_03 + 1, tmp4, tmp5) 162 | qc.x(_03 + 1) 163 | 164 | # 3 - B 165 | # 56 - AC, CA 166 | qc.x(_56 + 2) 167 | qc.ccx(_56 + 2, _56 + 0, tmp6) 168 | qc.x(_56 + 2) 169 | qc.ccx(_03 + 1, tmp6, tmp7) 170 | 171 | gate_or(qc, tmp1, tmp5, tmp8) 172 | 173 | ####################################### 174 | # Calculate the output cubit # 175 | ####################################### 176 | gate_or(qc, tmp7, tmp8, out) 177 | 178 | ####################################### 179 | # Invert all changes on temporary # 180 | # qubits # 181 | ####################################### 182 | inv_gate_or(qc, tmp1, tmp5, tmp8) 183 | qc.ccx(_03 + 1, tmp6, tmp7) 184 | qc.x(_56 + 2) 185 | qc.ccx(_56 + 2, _56 + 0, tmp6) 186 | qc.x(_56 + 2) 187 | qc.x(_03 + 1) 188 | qc.ccx(_03 + 1, tmp4, tmp5) 189 | inv_gate_or(qc, tmp2, tmp3, tmp4) 190 | qc.ccx(q[_56 + 1], q[_56 + 2], tmp3) 191 | qc.x(_56 + 0) 192 | qc.x(_56 + 2) 193 | qc.ccx(q[_56 + 0], q[_56 + 2], tmp2) 194 | qc.x(_56 + 2) 195 | qc.x(_56 + 0) 196 | qc.ccx(q[_03 + 1], q[_03 + 0], tmp1) 197 | qc.x(_03 + 1) 198 | 199 | 200 | #################################################### 201 | # # 202 | # Other function definitions # 203 | # # 204 | #################################################### 205 | def gate_or(qc, in0, in1, out): 206 | qc.x(in0) 207 | qc.x(in1) 208 | qc.ccx(in0, in1, out) 209 | qc.x(out) 210 | qc.x(in0) 211 | qc.x(in1) 212 | 213 | 214 | def inv_gate_or(qc, in0, in1, out): 215 | qc.x(in1) 216 | qc.x(in0) 217 | qc.x(out) 218 | qc.ccx(in0, in1, out) 219 | qc.x(in1) 220 | qc.x(in0) 221 | 222 | 223 | 224 | 225 | def inv_check_allowed_state(qc, idx, out): 226 | qc.x(idx) 227 | qc.ccx(idx, idx + 1, out) 228 | qc.x(idx) 229 | 230 | 231 | def check_203(qc, _2, _03, out, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6): 232 | # not(2) and _03 == 10 233 | qc.x(_2) 234 | qc.x(_03 + 1) 235 | qc.ccx(_03 + 2, _03 + 1, tmp1) 236 | qc.ccx(tmp1, _2, tmp2) 237 | qc.x(_2) 238 | qc.x(_03 + 1) 239 | 240 | # 2 and (_03 == 00 or _03 == 11) 241 | qc.x(_03 + 2) 242 | qc.x(_03 + 0) 243 | qc.ccx(_03 + 2, _03 + 0, tmp3) 244 | qc.x(_03 + 0) 245 | qc.x(_03 + 2) 246 | qc.ccx(_03 + 2, _03 + 1, tmp4) 247 | gate_or(qc, tmp3, tmp4, tmp5) 248 | qc.ccx(_2, tmp5, tmp6) 249 | ### 250 | gate_or(qc, tmp2, tmp6, out) 251 | ### 252 | qc.ccx(_2, tmp5, tmp6) 253 | inv_gate_or(qc, tmp3, tmp4, tmp5) 254 | qc.ccx(_03 + 2, _03 + 1, tmp4) 255 | qc.x(_03 + 2) 256 | qc.x(_03 + 0) 257 | qc.ccx(_03 + 2, _03 + 0, tmp3) 258 | qc.x(_03 + 0) 259 | qc.x(_03 + 2) 260 | qc.x(_03 + 1) 261 | qc.x(_2) 262 | qc.ccx(tmp1, _2, tmp2) 263 | qc.ccx(_03 + 2, _03 + 1, tmp1) 264 | qc.x(_03 + 1) 265 | qc.x(_2) 266 | 267 | 268 | def inv_check_203(qc, _2, _03, out, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6): 269 | # not(2) and _03 == 10 270 | qc.x(_2) 271 | qc.x(_03 + 1) 272 | qc.ccx(_03 + 2, _03 + 1, tmp1) 273 | qc.ccx(tmp1, _2, tmp2) 274 | qc.x(_2) 275 | qc.x(_03 + 1) 276 | 277 | # 2 and (_03 == 00 or _03 == 11) 278 | qc.x(_03 + 2) 279 | qc.x(_03 + 0) 280 | qc.ccx(_03 + 2, _03 + 0, tmp3) 281 | qc.x(_03 + 0) 282 | qc.x(_03 + 2) 283 | qc.ccx(_03 + 2, _03 + 1, tmp4) 284 | gate_or(qc, tmp3, tmp4, tmp5) 285 | qc.ccx(_2, tmp5, tmp6) 286 | ### 287 | inv_gate_or(qc, tmp2, tmp6, out) 288 | ### 289 | qc.ccx(_2, tmp5, tmp6) 290 | inv_gate_or(qc, tmp3, tmp4, tmp5) 291 | qc.ccx(_03 + 2, _03 + 1, tmp4) 292 | qc.x(_03 + 2) 293 | qc.x(_03 + 0) 294 | qc.ccx(_03 + 2, _03 + 0, tmp3) 295 | qc.x(_03 + 0) 296 | qc.x(_03 + 2) 297 | qc.x(_03 + 1) 298 | qc.x(_2) 299 | qc.ccx(tmp1, _2, tmp2) 300 | qc.ccx(_03 + 2, _03 + 1, tmp1) 301 | qc.x(_03 + 1) 302 | qc.x(_2) 303 | 304 | def check_01(qc, _03, _14, out, tmp1, tmp2, tmp3, tmp4, tmp5): 305 | gate_or(qc, q[_03 + 2], q[_03 + 1], tmp1) 306 | gate_or(qc, q[_14 + 2], q[_14 + 1], tmp2) 307 | qc.x(tmp1) 308 | qc.x(tmp2) 309 | gate_or(qc, tmp1, tmp2, tmp3) 310 | qc.ccx(q[_03 + 2], q[_03 + 0], tmp4) 311 | qc.ccx(q[_14 + 2], q[_14 + 0], tmp5) 312 | qc.cx(tmp4, tmp5) 313 | qc.x(tmp5) 314 | gate_or(qc, tmp3, tmp5, out) 315 | qc.x(tmp5) 316 | qc.cx(tmp4, tmp5) 317 | qc.ccx(q[_14 + 2], q[_14 + 0], tmp5) 318 | qc.ccx(q[_03 + 2], q[_03 + 0], tmp4) 319 | inv_gate_or(qc, tmp1, tmp2, tmp3) 320 | qc.x(tmp2) 321 | qc.x(tmp1) 322 | inv_gate_or(qc, q[_14 + 2], q[_14 + 1], tmp2) 323 | inv_gate_or(qc, q[_03 + 2], q[_03 + 1], tmp1) 324 | 325 | 326 | def inv_check_01(qc, _03, _14, out, tmp1, tmp2, tmp3, tmp4, tmp5): 327 | gate_or(qc, q[_03 + 2], q[_03 + 1], tmp1) 328 | gate_or(qc, q[_14 + 2], q[_14 + 1], tmp2) 329 | qc.x(tmp1) 330 | qc.x(tmp2) 331 | gate_or(qc, tmp1, tmp2, tmp3) 332 | qc.ccx(q[_03 + 2], q[_03 + 0], tmp4) 333 | qc.ccx(q[_14 + 2], q[_14 + 0], tmp5) 334 | qc.cx(tmp4, tmp5) 335 | qc.x(tmp5) 336 | inv_gate_or(qc, tmp3, tmp5, out) 337 | qc.x(tmp5) 338 | qc.cx(tmp4, tmp5) 339 | qc.ccx(q[_14 + 2], q[_14 + 0], tmp5) 340 | qc.ccx(q[_03 + 2], q[_03 + 0], tmp4) 341 | inv_gate_or(qc, tmp1, tmp2, tmp3) 342 | qc.x(tmp2) 343 | qc.x(tmp1) 344 | inv_gate_or(qc, q[_14 + 2], q[_14 + 1], tmp2) 345 | inv_gate_or(qc, q[_03 + 2], q[_03 + 1], tmp1) 346 | 347 | 348 | def inv_check_356(qc, _03, _56, out, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8): 349 | # 3 - D 350 | qc.x(_03 + 1) 351 | qc.ccx(q[_03 + 1], q[_03 + 0], tmp1) 352 | 353 | # 3 - C 354 | # 56 - AB 355 | qc.x(_56 + 0) 356 | qc.x(_56 + 2) 357 | qc.ccx(q[_56 + 0], q[_56 + 2], tmp2) 358 | qc.x(_56 + 2) 359 | qc.x(_56 + 0) 360 | # 56 -BA 361 | qc.ccx(q[_56 + 1], q[_56 + 2], tmp3) 362 | gate_or(qc, tmp2, tmp3, tmp4) 363 | qc.ccx(_03 + 1, tmp4, tmp5) 364 | qc.x(_03 + 1) 365 | 366 | # 3 - B 367 | # 56 - AC, CA 368 | qc.x(_56 + 2) 369 | qc.ccx(_56 + 2, _56 + 0, tmp6) 370 | qc.x(_56 + 2) 371 | qc.ccx(_03 + 1, tmp6, tmp7) 372 | 373 | gate_or(qc, tmp1, tmp5, tmp8) 374 | #### 375 | inv_gate_or(qc, tmp7, tmp8, out) 376 | ### 377 | inv_gate_or(qc, tmp1, tmp5, tmp8) 378 | qc.ccx(_03 + 1, tmp6, tmp7) 379 | qc.x(_56 + 2) 380 | qc.ccx(_56 + 2, _56 + 0, tmp6) 381 | qc.x(_56 + 2) 382 | qc.x(_03 + 1) 383 | qc.ccx(_03 + 1, tmp4, tmp5) 384 | inv_gate_or(qc, tmp2, tmp3, tmp4) 385 | qc.ccx(q[_56 + 1], q[_56 + 2], tmp3) 386 | qc.x(_56 + 0) 387 | qc.x(_56 + 2) 388 | qc.ccx(q[_56 + 0], q[_56 + 2], tmp2) 389 | qc.x(_56 + 2) 390 | qc.x(_56 + 0) 391 | qc.ccx(q[_03 + 1], q[_03 + 0], tmp1) 392 | qc.x(_03 + 1) 393 | 394 | def check_314(qc, _03, _14, out, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8): 395 | # 3 - B 396 | qc.ccx(q[_03 + 1], q[_03 + 0], tmp1) 397 | 398 | # 3 - C 399 | # 14 - AB 400 | qc.x(_14 + 0) 401 | qc.x(_14 + 2) 402 | qc.ccx(q[_14 + 0], q[_14 + 2], tmp2) 403 | qc.x(_14 + 2) 404 | qc.x(_14 + 0) 405 | # 56 -BA 406 | qc.ccx(q[_14 + 1], q[_14 + 2], tmp3) 407 | gate_or(qc, tmp2, tmp3, tmp4) 408 | qc.x(_03 + 0) 409 | qc.ccx(_03 + 0, tmp4, tmp5) 410 | qc.x(_03 + 0) 411 | 412 | # 3 - D 413 | # 56 - AC, CA 414 | qc.x(_14 + 2) 415 | qc.ccx(_14 + 2, _14 + 0, tmp6) 416 | qc.x(_14 + 2) 417 | qc.ccx(_03 + 0, tmp6, tmp7) 418 | 419 | gate_or(qc, tmp1, tmp5, tmp8) 420 | #### 421 | gate_or(qc, tmp7, tmp8, out) 422 | ### 423 | inv_gate_or(qc, tmp1, tmp5, tmp8) 424 | qc.ccx(_03 + 0, tmp6, tmp7) 425 | qc.x(_14 + 2) 426 | qc.ccx(_14 + 2, _14 + 0, tmp6) 427 | qc.x(_14 + 2) 428 | qc.x(_03 + 0) 429 | qc.ccx(_03 + 0, tmp4, tmp5) 430 | qc.x(_03 + 0) 431 | inv_gate_or(qc, tmp2, tmp3, tmp4) 432 | qc.ccx(q[_14 + 1], q[_14 + 2], tmp3) 433 | qc.x(_14 + 0) 434 | qc.x(_14 + 2) 435 | qc.ccx(q[_14 + 0], q[_14 + 2], tmp2) 436 | qc.x(_14 + 2) 437 | qc.x(_14 + 0) 438 | qc.ccx(q[_03 + 1], q[_03 + 0], tmp1) 439 | 440 | 441 | def inv_check_314(qc, _03, _14, out, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8): 442 | # 3 - B 443 | qc.ccx(q[_03 + 1], q[_03 + 0], tmp1) 444 | 445 | # 3 - C 446 | # 14 - AB 447 | qc.x(_14 + 0) 448 | qc.x(_14 + 2) 449 | qc.ccx(q[_14 + 0], q[_14 + 2], tmp2) 450 | qc.x(_14 + 2) 451 | qc.x(_14 + 0) 452 | # 56 -BA 453 | qc.ccx(q[_14 + 1], q[_14 + 2], tmp3) 454 | gate_or(qc, tmp2, tmp3, tmp4) 455 | qc.x(_03 + 0) 456 | qc.ccx(_03 + 0, tmp4, tmp5) 457 | qc.x(_03 + 0) 458 | 459 | # 3 - D 460 | # 56 - AC, CA 461 | qc.x(_14 + 2) 462 | qc.ccx(_14 + 2, _14 + 0, tmp6) 463 | qc.x(_14 + 2) 464 | qc.ccx(_03 + 0, tmp6, tmp7) 465 | 466 | gate_or(qc, tmp1, tmp5, tmp8) 467 | #### 468 | inv_gate_or(qc, tmp7, tmp8, out) 469 | ### 470 | inv_gate_or(qc, tmp1, tmp5, tmp8) 471 | qc.ccx(_03 + 0, tmp6, tmp7) 472 | qc.x(_14 + 2) 473 | qc.ccx(_14 + 2, _14 + 0, tmp6) 474 | qc.x(_14 + 2) 475 | qc.x(_03 + 0) 476 | qc.ccx(_03 + 0, tmp4, tmp5) 477 | qc.x(_03 + 0) 478 | inv_gate_or(qc, tmp2, tmp3, tmp4) 479 | qc.ccx(q[_14 + 1], q[_14 + 2], tmp3) 480 | qc.x(_14 + 0) 481 | qc.x(_14 + 2) 482 | qc.ccx(q[_14 + 0], q[_14 + 2], tmp2) 483 | qc.x(_14 + 2) 484 | qc.x(_14 + 0) 485 | qc.ccx(q[_03 + 1], q[_03 + 0], tmp1) 486 | 487 | 488 | def check_46(qc, _14, _56, out, tmp1, tmp2, tmp3): 489 | # 4 -> D 490 | qc.x(_14 + 0) 491 | qc.x(_14 + 1) 492 | qc.ccx(_14 + 0, _14 + 1, tmp1) 493 | # 6 -> B 494 | qc.x(_56 + 0) 495 | qc.x(_56 + 1) 496 | qc.ccx(_56 + 0, _56 + 1, tmp2) 497 | gate_or(qc, tmp1, tmp2, tmp3) 498 | # 4 code xor 6 code 499 | qc.cx(_14 + 1, _56 + 1) 500 | ### 501 | gate_or(qc, tmp3, _56 + 1, out) 502 | ### 503 | qc.cx(_14 + 1, _56 + 1) 504 | # inv_gate_or(qc, tmp1, tmp2, tmp3) 505 | # qc.ccx(_56 + 0, _56 + 1, tmp2) 506 | qc.x(_56 + 1) 507 | qc.x(_56 + 0) 508 | # qc.ccx(_14 + 0, _14 + 1, tmp1) 509 | qc.x(_14 + 1) 510 | qc.x(_14 + 0) 511 | 512 | 513 | def inv_check_46(qc, _14, _56, out, tmp1, tmp2, tmp3): 514 | # # 4 -> D 515 | qc.x(_14 + 0) 516 | qc.x(_14 + 1) 517 | # qc.ccx(_14 + 0, _14 + 1, tmp1) 518 | # # 6 -> B 519 | qc.x(_56 + 0) 520 | qc.x(_56 + 1) 521 | # qc.ccx(_56 + 0, _56 + 1, tmp2) 522 | # gate_or(qc, tmp1, tmp2, tmp3) 523 | # # 4 code xor 6 code 524 | qc.cx(_14 + 1, _56 + 1) 525 | ### 526 | inv_gate_or(qc, tmp3, _56 + 1, out) 527 | ### 528 | qc.cx(_14 + 1, _56 + 1) 529 | inv_gate_or(qc, tmp1, tmp2, tmp3) 530 | qc.ccx(_56 + 0, _56 + 1, tmp2) 531 | qc.x(_56 + 1) 532 | qc.x(_56 + 0) 533 | qc.ccx(_14 + 0, _14 + 1, tmp1) 534 | qc.x(_14 + 1) 535 | qc.x(_14 + 0) 536 | 537 | 538 | def check_256(qc, _2, _56, out, tmp1): 539 | qc.x(_56 + 2) 540 | qc.ccx(_56 + 2, _56 + 0, tmp1) 541 | gate_or(qc, tmp1, _2, out) 542 | #qc.ccx(_56 + 2, _56 + 0, tmp1) 543 | qc.x(_56 + 2) 544 | 545 | 546 | def inv_check_256(qc, _2, _56, out, tmp1): 547 | qc.x(_56 + 2) 548 | #qc.ccx(_56 + 2, _56 + 0, tmp1) 549 | inv_gate_or(qc, tmp1, _2, out) 550 | qc.ccx(_56 + 2, _56 + 0, tmp1) 551 | qc.x(_56 + 2) 552 | 553 | 554 | 555 | #################################################### 556 | # # 557 | # Circuit definitions # 558 | # # 559 | #################################################### 560 | from datetime import datetime 561 | print(datetime.today()) 562 | 563 | n_qubits = 32 564 | q = QuantumRegister(n_qubits) 565 | c = ClassicalRegister(14) 566 | qc = QuantumCircuit(q, c) 567 | 568 | # Circuit config 569 | n = 10 # The number of data qubits 570 | ite = 3 #number of iteration 571 | 572 | 573 | _2 = 0 574 | _03 = 1 575 | _14 = 4 576 | _56 = 7 577 | oracle = n 578 | 579 | # Temporary values 580 | val_reg_id = oracle + 1 581 | val_allowed_state_03 = val_reg_id 582 | val_reg_id += 1 583 | val_check_203 = val_reg_id 584 | val_reg_id += 1 585 | val_allowed_state_14 = val_reg_id 586 | val_reg_id += 1 587 | val_check_01 = val_reg_id 588 | val_reg_id += 1 589 | val_check_314 = val_reg_id 590 | val_reg_id += 1 591 | val_allowed_state_56 = val_reg_id 592 | val_reg_id += 1 593 | val_check_356 = val_reg_id 594 | val_reg_id += 1 595 | val_check_46 = val_reg_id 596 | val_reg_id += 1 597 | val_check_256 = val_reg_id 598 | val_reg_id += 1 599 | print("Veriable reg: ", val_reg_id) 600 | 601 | # Temporary registers 602 | tmp_reg_id = val_reg_id 603 | # Zeros registers 604 | _0_tmp1 = tmp_reg_id 605 | tmp_reg_id += 1 606 | _0_tmp2 = tmp_reg_id 607 | tmp_reg_id += 1 608 | _0_tmp3 = tmp_reg_id 609 | tmp_reg_id += 1 610 | _0_tmp4 = tmp_reg_id 611 | tmp_reg_id += 1 612 | _0_tmp5 = tmp_reg_id 613 | tmp_reg_id += 1 614 | _0_tmp6 = tmp_reg_id 615 | tmp_reg_id += 1 616 | _0_tmp7 = tmp_reg_id 617 | tmp_reg_id += 1 618 | _0_tmp8 = tmp_reg_id 619 | tmp_reg_id += 1 620 | _0_tmp9 = tmp_reg_id 621 | tmp_reg_id += 1 622 | _0_tmp10 = tmp_reg_id 623 | tmp_reg_id += 1 624 | _0_tmp11 = tmp_reg_id 625 | tmp_reg_id += 1 626 | print("Temporary reg: ", tmp_reg_id) 627 | 628 | 629 | 630 | # Initialization of data qubits 631 | qc.h(q[0:n]) 632 | qc.x(q[val_allowed_state_03]) 633 | qc.x(q[val_allowed_state_14]) 634 | qc.x(q[val_allowed_state_56]) 635 | 636 | for i in range(ite): 637 | # oracle part 638 | check_allowed_state(qc, _03, val_allowed_state_03) # 71 639 | check_allowed_state(qc, _14, val_allowed_state_14) # 71 640 | check_allowed_state(qc, _56, val_allowed_state_56) # 71 641 | check_01(qc, _03, _14, val_check_01, _0_tmp1, _0_tmp2, _0_tmp3, _0_tmp4, _0_tmp5) # 820 642 | check_203(qc, _2, _03, val_check_203, _0_tmp1, _0_tmp2, _0_tmp3, _0_tmp4, _0_tmp5, _0_tmp6) # 928 643 | check_356(qc, _03, _56, val_check_356, _0_tmp1, _0_tmp2, _0_tmp3, _0_tmp4, _0_tmp5, _0_tmp6, _0_tmp7, _0_tmp8) #1214 644 | check_314(qc, _03, _14, val_check_314, _0_tmp1, _0_tmp2, _0_tmp3, _0_tmp4, _0_tmp5, _0_tmp6, _0_tmp7, _0_tmp8) # 1214 645 | check_256(qc, _2, _56, val_check_256, _0_tmp11) # 214 646 | check_46(qc, _14, _56, val_check_46, _0_tmp8, _0_tmp9, _0_tmp10) # 526 647 | 648 | # 573 649 | qc.mct([q[val_allowed_state_03], q[val_allowed_state_14], q[val_allowed_state_56], q[val_check_256], 650 | q[val_check_46], q[val_check_356], q[val_check_314], q[val_check_01], q[val_check_203]], 651 | q[oracle], 652 | [q[_0_tmp1], q[_0_tmp2], q[_0_tmp3], q[_0_tmp4], q[_0_tmp5], q[_0_tmp6], q[_0_tmp7]], 653 | mode='basic') 654 | 655 | # inverse 656 | inv_check_46(qc, _14, _56, val_check_46, _0_tmp8, _0_tmp9, _0_tmp10) # 526 657 | inv_check_256(qc, _2, _56, val_check_256, _0_tmp11) # 214 658 | inv_check_314(qc, _03, _14, val_check_314, _0_tmp1, _0_tmp2, _0_tmp3, _0_tmp4, _0_tmp5, _0_tmp6, _0_tmp7, _0_tmp8) # 1214 659 | inv_check_356(qc, _03, _56, val_check_356, _0_tmp1, _0_tmp2, _0_tmp3, _0_tmp4, _0_tmp5, _0_tmp6, _0_tmp7, _0_tmp8) # 1214 660 | inv_check_203(qc, _2, _03, val_check_203, _0_tmp1, _0_tmp2, _0_tmp3, _0_tmp4, _0_tmp5, _0_tmp6) # 928 661 | inv_check_01(qc, _03, _14, val_check_01, _0_tmp1, _0_tmp2, _0_tmp3, _0_tmp4, _0_tmp5) # 820 662 | inv_check_allowed_state(qc, _56, val_allowed_state_56) # 71 663 | inv_check_allowed_state(qc, _14, val_allowed_state_14) # 71 664 | inv_check_allowed_state(qc, _03, val_allowed_state_03) # 71 665 | 666 | 667 | 668 | # diffusion part 669 | qc.h(q[0:n]) 670 | qc.x(q[0:n]) 671 | qc.h(q[n - 1]) 672 | 673 | # reuse qubits 674 | tmp7 = val_check_01 675 | 676 | qc.mct([q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8]], q[9], 677 | [q[_0_tmp1], q[_0_tmp2], q[_0_tmp3], q[_0_tmp4], q[_0_tmp5], q[_0_tmp6], q[tmp7]], mode='basic') 678 | qc.h(q[n - 1]) 679 | qc.x(q[0:n]) 680 | qc.h(q[0:n]) 681 | 682 | 683 | #################################################### 684 | # # 685 | # Decode the solution # 686 | # # 687 | #################################################### 688 | cl_reg_idx = 0 689 | 690 | #################################################### 691 | # 692 | # The decode part is similar to the constraint check, we have to find to boolean function to map our internal state 693 | # to the state required by the final solution. This is done in the code below. 694 | # 695 | #################################################### 696 | 697 | ###### 698 | qc.x(_0_tmp1) 699 | gate_or(qc, _03 + 1, _03 + 2, _0_tmp2) 700 | qc.ccx(q[_03 + 2], q[_03 + 0], _0_tmp3) 701 | qc.x(_0_tmp3) 702 | qc.x(q[_03 + 1]) 703 | ###### 704 | gate_or(qc, _14 + 1, _14 + 2, _0_tmp4) 705 | qc.ccx(q[_14 + 2], q[_14 + 0], _0_tmp5) 706 | qc.x(q[_14 + 0]) 707 | qc.x(q[_14 + 1]) 708 | ###### 709 | # reuse qubits 710 | tmp7 = val_check_01 711 | tmp8 = _0_tmp8 712 | tmp9 = _0_tmp9 713 | # end of reuse 714 | qc.ccx(q[_56 + 2], q[_56 + 0], _0_tmp6) 715 | gate_or(qc, _56 + 1, _56 + 2, tmp7) 716 | qc.x(_0_tmp6) 717 | qc.ccx(_0_tmp6, tmp7, tmp8) 718 | qc.x(_0_tmp6) 719 | qc.x(_56 + 1) 720 | qc.ccx(q[_56 + 1], q[_56 + 0], tmp9) 721 | qc.x(_56) 722 | ###### 723 | 724 | 725 | # 0 726 | qc.measure(q[_0_tmp2], c[cl_reg_idx]) 727 | cl_reg_idx += 1 728 | qc.measure(q[_0_tmp3], c[cl_reg_idx]) 729 | cl_reg_idx += 1 730 | # 1 731 | qc.measure(q[_0_tmp4], c[cl_reg_idx]) 732 | cl_reg_idx += 1 733 | qc.measure(q[_0_tmp5], c[cl_reg_idx]) 734 | cl_reg_idx += 1 735 | # 2 736 | qc.measure(q[_2], c[cl_reg_idx]) 737 | cl_reg_idx += 1 738 | qc.measure(_0_tmp1, c[cl_reg_idx]) 739 | cl_reg_idx += 1 740 | # 3 741 | qc.measure(q[_03 + 1], c[cl_reg_idx]) 742 | cl_reg_idx += 1 743 | qc.measure(q[_03], c[cl_reg_idx]) 744 | cl_reg_idx += 1 745 | # 4 746 | qc.measure(q[_14 + 1], c[cl_reg_idx]) 747 | cl_reg_idx += 1 748 | qc.measure(q[_14 + 0], c[cl_reg_idx]) 749 | cl_reg_idx += 1 750 | # 5 751 | qc.measure(q[tmp8], c[cl_reg_idx]) 752 | cl_reg_idx += 1 753 | qc.measure(q[_0_tmp6], c[cl_reg_idx]) 754 | cl_reg_idx += 1 755 | # 6 756 | qc.measure(q[tmp9], c[cl_reg_idx]) 757 | cl_reg_idx += 1 758 | qc.measure(q[_56], c[cl_reg_idx]) 759 | cl_reg_idx += 1 760 | 761 | 762 | #################################################### 763 | # # 764 | # Execute the JOB # 765 | # # 766 | #################################################### 767 | #print(cost(qc)) 768 | 769 | #provider = IBMQ.load_account() 770 | 771 | backend = provider.get_backend('ibmq_qasm_simulator') 772 | job = execute(qc, backend=backend, shots=8000, seed_simulator=12345, backend_options={"fusion_enable":True}) 773 | result = job.result() 774 | count = result.get_counts() 775 | print(count) 776 | 777 | #`shots` are set to 8000 to increase sampling 778 | #`seed_simulator`` is set to 12345 to 'lock' its value, and 779 | #`backend_options={"fusion_enable":True}` is specified to improve simulator performance. 780 | 781 | 782 | 783 | 784 | -------------------------------------------------------------------------------- /top ten submissions/rp_cc_sqrt_2/readme.txt: -------------------------------------------------------------------------------- 1 | #IBM Quantum Challenge 2019 2 | #Instructions for top ten teams for preparing their illustrative explanation of their submissions. 3 | 4 | Dear Team, 5 | 6 | Congratulations for making it into the top ten teams of IBM Quantum Challenge! 7 | 8 | Judges have reviewed your submissions and have verified your final score. We will be making an official announcement next week to show the final standings. 9 | 10 | In the meantime, we are asking all top ten teams to: 11 | 12 | 13 | -Prepare a write-up on how your team obtained the answers for the final challenge. 14 | 15 | -You may either add explanations to your ipynb file OR provide detailed comments in your .py file. 16 | 17 | -While we do not have a specific format for you to follow, we would like to ask you to focus on providing an illustrative explanation of your strategy, approach, techniques (creativity) you used to achieve lower quantum costs. 18 | 19 | -A folder saying 'top ten submissions' will be prepared in the github repository containing another set of folders each named after your teams. Please push your write-ups into these folders by Monday Oct 21st, noon JST. 20 | 21 | 22 | IBM Quantum Challenge Organizers --------------------------------------------------------------------------------
Special Oracle Awardteam_namestatuscostnumber_of_submissionmessage
1Costs___100kinitialization partially incomplete≈1573713you got the correct answers but Grover implementation is incomplete.
2Sorininitialization partially incomplete≈216675you got the correct answers but Grover implementation is incomplete.