diff --git a/qiskit/ignis/state-tomography.ipynb b/qiskit/ignis/state-tomography.ipynb index 93bd3fbfd..00dbe0c9f 100644 --- a/qiskit/ignis/state-tomography.ipynb +++ b/qiskit/ignis/state-tomography.ipynb @@ -26,13 +26,14 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "# Needed for functions\n", "import numpy as np\n", "import time\n", + "from copy import deepcopy\n", "\n", "# Import Qiskit classes\n", "import qiskit \n", @@ -61,7 +62,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 2, "metadata": {}, "outputs": [ { @@ -69,9 +70,9 @@ "output_type": "stream", "text": [ " ┌───┐ \n", - "q8_0: |0>┤ H ├──■──\n", + "q0_0: |0>┤ H ├──■──\n", " └───┘┌─┴─┐\n", - "q8_1: |0>─────┤ X ├\n", + "q0_1: |0>─────┤ X ├\n", " └───┘\n", "[0.70710678+0.j 0. +0.j 0. +0.j 0.70710678+0.j]\n" ] @@ -92,7 +93,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -100,17 +101,17 @@ "output_type": "stream", "text": [ " \n", - "q9_0: |0>──────────\n", + "q1_0: |0>──────────\n", " \n", - "q9_1: |0>──────────\n", + "q1_1: |0>──────────\n", " \n", - "q9_2: |0>──────────\n", + "q1_2: |0>──────────\n", " ┌───┐ \n", - "q9_3: |0>┤ H ├──■──\n", + "q1_3: |0>┤ H ├──■──\n", " └───┘ │ \n", - "q9_4: |0>───────┼──\n", + "q1_4: |0>───────┼──\n", " ┌─┴─┐\n", - "q9_5: |0>─────┤ X ├\n", + "q1_5: |0>─────┤ X ├\n", " └───┘\n" ] } @@ -133,14 +134,14 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Time taken: 0.4744570255279541\n" + "Time taken: 0.2808539867401123\n" ] } ], @@ -168,14 +169,14 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Fit Fidelity = 0.9999000849303845\n" + "Fit Fidelity = 0.9999605319385123\n" ] } ], @@ -196,15 +197,15 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Fit Fidelity (no correction) = 0.5769036647742336\n", - "Fit Fidelity (w/ correction) = 0.9967713813311038\n" + "Fit Fidelity (no correction) = 0.5742657677768489\n", + "Fit Fidelity (w/ correction) = 0.999824431926327\n" ] } ], @@ -253,7 +254,7 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -281,7 +282,7 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": 8, "metadata": {}, "outputs": [ { @@ -289,20 +290,20 @@ "output_type": "stream", "text": [ "Random single-qubit unitaries: set 0\n", - "F fit (CVX) = 0.9982342978400156\n", - "F fit (LSTSQ) = 0.9955699556857641\n", + "F fit (CVX) = 0.999150958176627\n", + "F fit (LSTSQ) = 0.9949127903772803\n", "Random single-qubit unitaries: set 1\n", - "F fit (CVX) = 0.9997462856276226\n", - "F fit (LSTSQ) = 0.9981847872964353\n", + "F fit (CVX) = 0.9930446937928088\n", + "F fit (LSTSQ) = 0.989849832684077\n", "Random single-qubit unitaries: set 2\n", - "F fit (CVX) = 0.9968201908496568\n", - "F fit (LSTSQ) = 0.9923331569383647\n", + "F fit (CVX) = 0.998824288959602\n", + "F fit (LSTSQ) = 0.9945787779787962\n", "Random single-qubit unitaries: set 3\n", - "F fit (CVX) = 0.9993092033884361\n", - "F fit (LSTSQ) = 0.995875515175604\n", + "F fit (CVX) = 0.9961308975072494\n", + "F fit (LSTSQ) = 0.9929845786532249\n", "Random single-qubit unitaries: set 4\n", - "F fit (CVX) = 0.9957937064209796\n", - "F fit (LSTSQ) = 0.9932656872439047\n" + "F fit (CVX) = 0.9975931183831814\n", + "F fit (LSTSQ) = 0.997224800651653\n" ] } ], @@ -321,14 +322,14 @@ }, { "cell_type": "code", - "execution_count": 36, + "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Time taken: 11.79207706451416\n" + "Time taken: 8.388687133789062\n" ] } ], @@ -356,7 +357,7 @@ }, { "cell_type": "code", - "execution_count": 37, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -364,8 +365,8 @@ "output_type": "stream", "text": [ "Least-Sq Reconstruction\n", - "Time taken: 6.593528985977173\n", - "Fit Fidelity: 0.9934254969851912\n" + "Time taken: 7.422188997268677\n", + "Fit Fidelity: 0.9942293159914606\n" ] } ], @@ -379,7 +380,7 @@ }, { "cell_type": "code", - "execution_count": 38, + "execution_count": 11, "metadata": {}, "outputs": [ { @@ -387,8 +388,8 @@ "output_type": "stream", "text": [ "CVX Reconstruction\n", - "Time taken: 73.93138408660889\n", - "Fidelity: 0.9999122713296319\n" + "Time taken: 65.69908094406128\n", + "Fidelity: 0.9999139886227795\n" ] } ], @@ -399,6 +400,196 @@ "print('Time taken:', time.time() - t)\n", "print('Fidelity:', state_fidelity(psi_bell5, rho_cvx_bell5))" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2-Qubit Conditional State Tomography " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this example, we have a three qubit system where one of the qubits will be an ancilla for performing state tomography, i.e., only perform tomography when the third qubit is in the state \"1\". The circuit is setup in such a way that after conditional tomography we will get a Bell state on the first two qubits.\n", + "\n", + "First make a 3Q GHZ State with no classical measurements." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " ┌───┐ \n", + "q9_0: |0>┤ H ├──■────────────\n", + " └───┘┌─┴─┐ \n", + "q9_1: |0>─────┤ X ├──■───────\n", + " └───┘┌─┴─┐┌───┐\n", + "q9_2: |0>──────────┤ X ├┤ H ├\n", + " └───┘└───┘\n" + ] + } + ], + "source": [ + "# Create the actual circuit \n", + "q2 = QuantumRegister(3)\n", + "ghz = QuantumCircuit(q2)\n", + "ghz.h(q2[0])\n", + "ghz.cx(q2[0], q2[1])\n", + "ghz.cx(q2[1], q2[2])\n", + "ghz.h(q2[2])\n", + "print(ghz)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here we are going to generate and run the state tomography circuits. Only pass the registers we want to perform state tomography on. The code will generate a new classical register for ony those measurements." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " ┌───┐ ░ ┌───┐┌─┐ \n", + "q9_0: |0>┤ H ├──■─────────────░─┤ H ├┤M├────\n", + " └───┘┌─┴─┐ ░ ├───┤└╥┘┌─┐ \n", + "q9_1: |0>─────┤ X ├──■────────░─┤ H ├─╫─┤M├─\n", + " └───┘┌─┴─┐┌───┐ ░ └───┘ ║ └╥┘ \n", + "q9_2: |0>──────────┤ X ├┤ H ├─░───────╫──╫──\n", + " └───┘└───┘ ░ ║ ║ \n", + " c8_0: 0 ═════════════════════════════╩══╬══\n", + " ║ \n", + " c8_1: 0 ════════════════════════════════╩══\n", + " \n" + ] + } + ], + "source": [ + "qst_ghz = state_tomography_circuits(ghz, [q2[0],q2[1]])\n", + "print(qst_ghz[0])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now make a copy of this circuit (we will need it for the fitter) and make a new circuit with an ancilla measurement attached (this is what will be run)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "#Make a copy without the ancilla register\n", + "qst_ghz_no_anc = deepcopy(qst_ghz)\n", + "ca = ClassicalRegister(1)\n", + "for qst_ghz_circ in qst_ghz:\n", + " qst_ghz_circ.add_register(ca)\n", + " qst_ghz_circ.measure(q2[2],ca[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "#Run in Aer\n", + "job = qiskit.execute(qst_ghz, Aer.get_backend('qasm_simulator'), shots=10000)\n", + "raw_results = job.result()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Before sending the results to the state tomography fitter we must strip the register for the Q2 measurement and only keep the results when that register is 1." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "new_result = deepcopy(raw_results)\n", + "\n", + "for resultidx, _ in enumerate(raw_results.results):\n", + " old_counts = raw_results.get_counts(resultidx)\n", + " new_counts = {}\n", + " \n", + " #change the size of the classical register\n", + " new_result.results[resultidx].header.creg_sizes = [new_result.results[resultidx].header.creg_sizes[0]]\n", + " new_result.results[resultidx].header.clbit_labels = new_result.results[resultidx].header.clbit_labels[0:-1]\n", + " new_result.results[resultidx].header.memory_slots = 2\n", + " \n", + " for reg_key in old_counts:\n", + " reg_bits = reg_key.split(' ')\n", + " if reg_bits[0]=='1':\n", + " new_counts[reg_bits[1]]=old_counts[reg_key]\n", + "\n", + " new_result.results[resultidx].data.counts = \\\n", + " new_result.results[resultidx]. \\\n", + " data.counts.from_dict(new_counts)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [], + "source": [ + "tomo_bell = StateTomographyFitter(new_result, qst_ghz_no_anc)\n", + "# Perform the tomography fit\n", + "# which outputs a density matrix\n", + "rho_bell = tomo_bell.fit()" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 0.504+0.j , 0.001-0.007j, 0.004+0.002j, -0.5 +0.006j],\n", + " [ 0.001+0.007j, 0. +0.j , -0. +0.j , -0.001-0.007j],\n", + " [ 0.004-0.002j, -0. -0.j , 0. +0.j , -0.004+0.002j],\n", + " [-0.5 -0.006j, -0.001+0.007j, -0.004-0.002j, 0.496+0.j ]])" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.around(rho_bell,3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": {