diff --git a/docs/tutorials/qst_example.ipynb b/docs/tutorials/qst_example.ipynb deleted file mode 100644 index 631b00028f..0000000000 --- a/docs/tutorials/qst_example.ipynb +++ /dev/null @@ -1,421 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "source": [ - "# Quantum State Tomography" - ], - "metadata": {} - }, - { - "cell_type": "code", - "execution_count": 1, - "source": [ - "from pprint import pprint\n", - "import qiskit\n", - "from qiskit_experiments.framework import ParallelExperiment\n", - "from qiskit_experiments.library import StateTomography\n", - "\n", - "# For simulation\n", - "from qiskit.providers.aer import AerSimulator\n", - "from qiskit.test.mock import FakeParis\n", - "\n", - "# Noisy simulator backend\n", - "backend = AerSimulator.from_backend(FakeParis())" - ], - "outputs": [], - "metadata": {} - }, - { - "cell_type": "markdown", - "source": [ - "## State Tomography Experiment\n", - "\n", - "To run a state tomography experiment we initialize the experiment with a circuit to prepare the state to be measured. We can also pass in an `Operator`, or a `Statevector` to describe the preparation circuit." - ], - "metadata": {} - }, - { - "cell_type": "code", - "execution_count": 2, - "source": [ - "# Run experiments\n", - "\n", - "# GHZ State preparation circuit\n", - "nq = 2\n", - "qc_ghz = qiskit.QuantumCircuit(nq)\n", - "qc_ghz.h(0)\n", - "qc_ghz.s(0)\n", - "for i in range(1, nq):\n", - " qc_ghz.cx(0, i)\n", - "\n", - "# QST Experiment\n", - "qstexp1 = StateTomography(qc_ghz)\n", - "qstdata1 = qstexp1.run(backend, seed_simulation=100)\n", - "qstresult = qstdata1.analysis_result(-1)\n", - "\n", - "print('FIT RESULT')\n", - "pprint(qstresult)" - ], - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "FIT RESULT\n", - "{'fitter_metadata': {'fitter': 'linear_inversion',\n", - " 'fitter_time': 0.0015842914581298828},\n", - " 'state': DensityMatrix([[ 0.47981771+0.j , 0.00439453-0.0086263j ,\n", - " 0.00260417-0.00651042j, -0.01416016-0.44482422j],\n", - " [ 0.00439453+0.0086263j , 0.01920573+0.j ,\n", - " -0.00537109+0.00341797j, 0.01432292+0.00130208j],\n", - " [ 0.00260417+0.00651042j, -0.00537109-0.00341797j,\n", - " 0.03450521+0.j , 0.00146484-0.02034505j],\n", - " [-0.01416016+0.44482422j, 0.01432292-0.00130208j,\n", - " 0.00146484+0.02034505j, 0.46647135+0.j ]],\n", - " dims=(2, 2)),\n", - " 'state_fidelity': 0.91796875,\n", - " 'state_metadata': {'eigvals': array([0.91887418, 0.0471276 , 0.01804304, 0.01595518]),\n", - " 'positive': True,\n", - " 'positive_delta': 0.0,\n", - " 'trace': 1.0000000000000002},\n", - " 'success': True}\n" - ] - } - ], - "metadata": {} - }, - { - "cell_type": "markdown", - "source": [ - "### Tomography Results\n", - "\n", - "The main results for tomography are the fitted state, which is stored in the `\"state\"` key as a `DensityMatrix` object:" - ], - "metadata": {} - }, - { - "cell_type": "code", - "execution_count": 3, - "source": [ - "print(qstresult[\"state\"])" - ], - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "DensityMatrix([[ 0.47981771+0.j , 0.00439453-0.0086263j ,\n", - " 0.00260417-0.00651042j, -0.01416016-0.44482422j],\n", - " [ 0.00439453+0.0086263j , 0.01920573+0.j ,\n", - " -0.00537109+0.00341797j, 0.01432292+0.00130208j],\n", - " [ 0.00260417+0.00651042j, -0.00537109-0.00341797j,\n", - " 0.03450521+0.j , 0.00146484-0.02034505j],\n", - " [-0.01416016+0.44482422j, 0.01432292-0.00130208j,\n", - " 0.00146484+0.02034505j, 0.46647135+0.j ]],\n", - " dims=(2, 2))\n" - ] - } - ], - "metadata": {} - }, - { - "cell_type": "markdown", - "source": [ - "The state fidelity of the fitted state with the ideal state prepared by the input circuit is stored in the `\"state_fidelity\"` result field. Note that if the input circuit contained any measurements the ideal state cannot be automatically generated and this field will be set to `None`." - ], - "metadata": {} - }, - { - "cell_type": "code", - "execution_count": 4, - "source": [ - "print(\"State Fidelity = {:.5f}\".format(qstresult[\"state_fidelity\"]))" - ], - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "State Fidelity = 0.91797\n" - ] - } - ], - "metadata": {} - }, - { - "cell_type": "markdown", - "source": [ - "#### Additional state metadata\n", - "\n", - "Additional data is stored in the tomography under the `\"state_metadata\"` field. This includes\n", - "- `eigvals`: the eigenvalues of the fitted state\n", - "- `trace`: the trace of the fitted state\n", - "- `positive`: Whether the eigenvalues are all non-negative\n", - "- `positive_delta`: the deviation from positivity given by 1-norm of negative eigenvalues.\n", - "\n", - "If trace rescaling was performed this dictionary will also contain a `raw_trace` field containing the trace before rescaling.\n", - "Futhermore, if the state was rescaled to be positive or trace 1 an additional field `raw_eigvals` will contain the state eigenvalues before rescaling was performed." - ], - "metadata": {} - }, - { - "cell_type": "code", - "execution_count": 5, - "source": [ - "pprint(qstresult[\"state_metadata\"])" - ], - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "{'eigvals': array([0.91887418, 0.0471276 , 0.01804304, 0.01595518]),\n", - " 'positive': True,\n", - " 'positive_delta': 0.0,\n", - " 'trace': 1.0000000000000002}\n" - ] - } - ], - "metadata": {} - }, - { - "cell_type": "markdown", - "source": [ - "To see the effect of rescaling we can perform a \"bad\" fit with very low counts" - ], - "metadata": {} - }, - { - "cell_type": "code", - "execution_count": 6, - "source": [ - "# QST Experiment\n", - "bad_data = qstexp1.run(backend, shots=10, seed_simulation=100)\n", - "bad_result = bad_data.analysis_result(-1)\n", - "\n", - "print(bad_result[\"state_fidelity\"])\n", - "pprint(bad_result[\"state_metadata\"])" - ], - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "0.8405316844521707\n", - "{'eigvals': array([0.89168942, 0.10831058, 0. , 0. ]),\n", - " 'positive': True,\n", - " 'positive_delta': 0.0,\n", - " 'raw_eigvals': array([ 1.05462832, 0.27124948, -0.06026308, -0.26561472]),\n", - " 'trace': 0.9999999999999993}\n" - ] - } - ], - "metadata": {} - }, - { - "cell_type": "markdown", - "source": [ - "## Tomography Fitters\n", - "\n", - "The default fitters is `linear_inversion`, which reconstructs the state using *dual basis* of the tomography basis. This will typically result in a non-postive reconstructed state. This state is rescaled to be postive-semidfinite (PSD) by computing its eigen-decomposition and rescaling its eigenvalues using the approach from *J Smolin, JM Gambetta, G Smith, Phys. Rev. Lett. 108, 070502 (2012), [open access](https://arxiv.org/abs/arXiv:1106.5458).\n", - "\n", - "There are several other fitters are included (See API documentation for details). For example if `cvxpy` is installed we can use the `cvxpy_gaussian_lstsq` fitter which allows constraining the fit to be PSD without requiring rescaling." - ], - "metadata": {} - }, - { - "cell_type": "code", - "execution_count": 7, - "source": [ - "qstexp1.run_analysis(qstdata1, fitter='cvxpy_linear_lstsq')\n", - "qstresult2 = qstdata1.analysis_result(-1)\n", - "\n", - "print('FIT RESULT')\n", - "pprint(qstresult2)" - ], - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "FIT RESULT\n", - "{'fitter_metadata': {'cvxpy_solver': 'CVXOPT',\n", - " 'cvxpy_status': 'optimal',\n", - " 'fitter': 'cvxpy_linear_lstsq',\n", - " 'fitter_time': 0.057753801345825195},\n", - " 'state': DensityMatrix([[ 0.47981944+0.00000000e+00j, 0.00439546-8.62489044e-03j,\n", - " 0.00260244-6.51111631e-03j, -0.01416025-4.44827007e-01j],\n", - " [ 0.00439546+8.62489044e-03j, 0.01920331+0.00000000e+00j,\n", - " -0.00537229+3.41858268e-03j, 0.01432449+1.30294300e-03j],\n", - " [ 0.00260244+6.51111631e-03j, -0.00537229-3.41858268e-03j,\n", - " 0.03450426-8.67361738e-19j, 0.00146412-2.03467865e-02j],\n", - " [-0.01416025+4.44827007e-01j, 0.01432449-1.30294300e-03j,\n", - " 0.00146412+2.03467865e-02j, 0.46647299+1.73472348e-18j]],\n", - " dims=(2, 2)),\n", - " 'state_fidelity': 0.9179732199819044,\n", - " 'state_metadata': {'eigvals': array([0.91887865, 0.04713024, 0.01804001, 0.0159511 ]),\n", - " 'positive': True,\n", - " 'positive_delta': 0.0,\n", - " 'raw_eigvals': array([0.91887729, 0.04713017, 0.01803999, 0.01595107]),\n", - " 'raw_trace': 0.999998525291621,\n", - " 'trace': 0.9999999999999999},\n", - " 'success': True}\n" - ] - } - ], - "metadata": {} - }, - { - "cell_type": "markdown", - "source": [ - "## Parallel Tomography Experiment\n", - "\n", - "We can also use the `qiskit_experiments.ParallelExperiment` class to run subsystem tomography on multiple qubits in parallel.\n", - "\n", - "For example if we want to perform 1-qubit QST on several qubits at once:" - ], - "metadata": {} - }, - { - "cell_type": "code", - "execution_count": 8, - "source": [ - "from math import pi\n", - "num_qubits = 5\n", - "gates = [qiskit.circuit.library.RXGate(i * pi / (num_qubits - 1))\n", - " for i in range(num_qubits)]\n", - "\n", - "subexps = [\n", - " StateTomography(gate, qubits=[i])\n", - " for i, gate in enumerate(gates)\n", - "]\n", - "parexp = ParallelExperiment(subexps)\n", - "pardata = parexp.run(backend, seed_simulation=100)\n", - "print(pardata.analysis_result(-1))" - ], - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "\n", - "- experiment_types: ['StateTomography', 'StateTomography', 'StateTomography', 'StateTomography', 'StateTomography']\n", - "- experiment_ids: ['e8025a8b-edcb-483d-b1a6-131ca638c7d2', 'f8f971b7-d99d-4d16-bfdf-c8d489b0d0f1', '15b3f86a-b34d-4f8d-9167-e70aa9efdcc9', '9f35847c-d601-41b3-a2e8-57a701023a16', 'cc2c46b9-292b-4017-b353-465271580b5e']\n", - "- experiment_qubits: [(0,), (1,), (2,), (3,), (4,)]\n", - "- success: True\n" - ] - } - ], - "metadata": {} - }, - { - "cell_type": "markdown", - "source": [ - "View component experiment analysis results" - ], - "metadata": {} - }, - { - "cell_type": "code", - "execution_count": 9, - "source": [ - "for i in range(parexp.num_experiments):\n", - " expdata = pardata.component_experiment_data(i)\n", - " result = expdata.analysis_result(-1)\n", - " \n", - " print(f'\\nPARALLEL EXP {i}: FIT RESULT')\n", - " pprint(result)" - ], - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "\n", - "PARALLEL EXP 0: FIT RESULT\n", - "{'fitter_metadata': {'fitter': 'linear_inversion',\n", - " 'fitter_time': 0.00016832351684570312},\n", - " 'state': DensityMatrix([[ 0.98339844+0.j , -0.01953125-0.01757812j],\n", - " [-0.01953125+0.01757812j, 0.01660156+0.j ]],\n", - " dims=(2,)),\n", - " 'state_fidelity': 0.9833984374999999,\n", - " 'state_metadata': {'eigvals': array([0.98411208, 0.01588792]),\n", - " 'positive': True,\n", - " 'positive_delta': 0.0,\n", - " 'trace': 1.0000000000000002},\n", - " 'success': True}\n", - "\n", - "PARALLEL EXP 1: FIT RESULT\n", - "{'fitter_metadata': {'fitter': 'linear_inversion',\n", - " 'fitter_time': 9.083747863769531e-05},\n", - " 'state': DensityMatrix([[0.8515625 +0.j , 0.00878906+0.31933594j],\n", - " [0.00878906-0.31933594j, 0.1484375 +0.j ]],\n", - " dims=(2,)),\n", - " 'state_fidelity': 0.9743968346437093,\n", - " 'state_metadata': {'eigvals': array([0.97502514, 0.02497486]),\n", - " 'positive': True,\n", - " 'positive_delta': 0.0,\n", - " 'trace': 1.0000000000000004},\n", - " 'success': True}\n", - "\n", - "PARALLEL EXP 2: FIT RESULT\n", - "{'fitter_metadata': {'fitter': 'linear_inversion',\n", - " 'fitter_time': 8.916854858398438e-05},\n", - " 'state': DensityMatrix([[0.50976563+0.j , 0.01953125+0.46972656j],\n", - " [0.01953125-0.46972656j, 0.49023438+0.j ]],\n", - " dims=(2,)),\n", - " 'state_fidelity': 0.9697265625000003,\n", - " 'state_metadata': {'eigvals': array([0.97023386, 0.02976614]),\n", - " 'positive': True,\n", - " 'positive_delta': 0.0,\n", - " 'trace': 1.0000000000000004},\n", - " 'success': True}\n", - "\n", - "PARALLEL EXP 3: FIT RESULT\n", - "{'fitter_metadata': {'fitter': 'linear_inversion',\n", - " 'fitter_time': 8.487701416015625e-05},\n", - " 'state': DensityMatrix([[0.171875 +0.j , 0.02734375+0.32128906j],\n", - " [0.02734375-0.32128906j, 0.828125 +0.j ]],\n", - " dims=(2,)),\n", - " 'state_fidelity': 0.9592050873916542,\n", - " 'state_metadata': {'eigvals': array([0.96004387, 0.03995613]),\n", - " 'positive': True,\n", - " 'positive_delta': 0.0,\n", - " 'trace': 0.9999999999999999},\n", - " 'success': True}\n", - "\n", - "PARALLEL EXP 4: FIT RESULT\n", - "{'fitter_metadata': {'fitter': 'linear_inversion',\n", - " 'fitter_time': 8.893013000488281e-05},\n", - " 'state': DensityMatrix([[0.03808594+0.j, 0.00585938+0.j],\n", - " [0.00585938+0.j, 0.96191406+0.j]],\n", - " dims=(2,)),\n", - " 'state_fidelity': 0.9619140625,\n", - " 'state_metadata': {'eigvals': array([0.96195122, 0.03804878]),\n", - " 'positive': True,\n", - " 'positive_delta': 0.0,\n", - " 'trace': 1.0000000000000002},\n", - " 'success': True}\n" - ] - } - ], - "metadata": {} - } - ], - "metadata": { - "interpreter": { - "hash": "c45f46a7fd077198472649b02925a2e599779de14e258f4f9ba8eb1d4e684fd2" - }, - "kernelspec": { - "name": "python3", - "display_name": "Python 3.7.7 64-bit ('qiskit-dev': conda)" - }, - "language_info": { - "name": "python", - "version": "3.7.7" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} \ No newline at end of file diff --git a/docs/tutorials/state_tomography.ipynb b/docs/tutorials/state_tomography.ipynb new file mode 100644 index 0000000000..5cbb6c4dee --- /dev/null +++ b/docs/tutorials/state_tomography.ipynb @@ -0,0 +1,465 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Quantum State Tomography" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import qiskit\n", + "from qiskit_experiments.framework import ParallelExperiment\n", + "from qiskit_experiments.library import StateTomography\n", + "\n", + "# For simulation\n", + "from qiskit.providers.aer import AerSimulator\n", + "from qiskit.test.mock import FakeParis\n", + "\n", + "# Noisy simulator backend\n", + "backend = AerSimulator.from_backend(FakeParis())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## State Tomography Experiment\n", + "\n", + "To run a state tomography experiment we initialize the experiment with a circuit to prepare the state to be measured. We can also pass in an `Operator`, or a `Statevector` to describe the preparation circuit." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "FIT RESULT\n", + "\n", + "Analysis Result: StateTomography\n", + "Analysis Result ID: 95c2123e-8164-4fe2-a7c0-bbc1ccf04328\n", + "Experiment ID: a903a1ad-4535-4c28-b7c8-db5f9aec54ae\n", + "Device Components: [, ]\n", + "Quality: None\n", + "Verified: False\n", + "Result Data:\n", + "- state: DensityMatrix([[ 0.47672008+0.00000000e+00j, 0.01743136+3.38352041e-03j,\n", + " 0.02372273-1.18893984e-02j, 0.00085292-4.48489363e-01j],\n", + " [ 0.01743136-3.38352041e-03j, 0.02290845+0.00000000e+00j,\n", + " 0.00348649+5.07348117e-03j, 0.00482618+1.28395469e-03j],\n", + " [ 0.02372273+1.18893984e-02j, 0.00348649-5.07348117e-03j,\n", + " 0.03314588+0.00000000e+00j, -0.01239848-2.14036205e-02j],\n", + " [ 0.00085292+4.48489363e-01j, 0.00482618-1.28395469e-03j,\n", + " -0.01239848+2.14036205e-02j, 0.46722559-2.71050543e-20j]],\n", + " dims=(2, 2))\n", + "- fitter_metadata: {'fitter': 'linear_inversion', 'fitter_time': 0.002125263214111328}\n", + "- success: True\n", + "- state_metadata: {'eigvals': array([0.92178556, 0.04662193, 0.03159251, 0. ]), 'raw_eigvals': array([ 0.92515401, 0.04999039, 0.03496096, -0.01010536]), 'trace': 0.9999999999999997, 'positive': True, 'positive_delta': 0.0}\n", + "- state_fidelity: 0.9204621973308564\n" + ] + } + ], + "source": [ + "# Run experiments\n", + "\n", + "# GHZ State preparation circuit\n", + "nq = 2\n", + "qc_ghz = qiskit.QuantumCircuit(nq)\n", + "qc_ghz.h(0)\n", + "qc_ghz.s(0)\n", + "for i in range(1, nq):\n", + " qc_ghz.cx(0, i)\n", + "\n", + "# QST Experiment\n", + "qstexp1 = StateTomography(qc_ghz)\n", + "qstdata1 = qstexp1.run(backend, seed_simulation=100).block_for_results()\n", + "qstresult = qstdata1.analysis_results(0)\n", + "\n", + "print('FIT RESULT')\n", + "print(qstresult)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Tomography Results\n", + "\n", + "The main results for tomography are the fitted state, which is stored in the `\"state\"` key as a `DensityMatrix` object:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DensityMatrix([[ 0.47672008+0.00000000e+00j, 0.01743136+3.38352041e-03j,\n", + " 0.02372273-1.18893984e-02j, 0.00085292-4.48489363e-01j],\n", + " [ 0.01743136-3.38352041e-03j, 0.02290845+0.00000000e+00j,\n", + " 0.00348649+5.07348117e-03j, 0.00482618+1.28395469e-03j],\n", + " [ 0.02372273+1.18893984e-02j, 0.00348649-5.07348117e-03j,\n", + " 0.03314588+0.00000000e+00j, -0.01239848-2.14036205e-02j],\n", + " [ 0.00085292+4.48489363e-01j, 0.00482618-1.28395469e-03j,\n", + " -0.01239848+2.14036205e-02j, 0.46722559-2.71050543e-20j]],\n", + " dims=(2, 2))\n" + ] + } + ], + "source": [ + "print(qstresult.data()[\"state\"])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The state fidelity of the fitted state with the ideal state prepared by the input circuit is stored in the `\"state_fidelity\"` result field. Note that if the input circuit contained any measurements the ideal state cannot be automatically generated and this field will be set to `None`." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "State Fidelity = 0.92046\n" + ] + } + ], + "source": [ + "print(\"State Fidelity = {:.5f}\".format(qstresult.data()[\"state_fidelity\"]))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Additional state metadata\n", + "\n", + "Additional data is stored in the tomography under the `\"state_metadata\"` field. This includes\n", + "- `eigvals`: the eigenvalues of the fitted state\n", + "- `trace`: the trace of the fitted state\n", + "- `positive`: Whether the eigenvalues are all non-negative\n", + "- `positive_delta`: the deviation from positivity given by 1-norm of negative eigenvalues.\n", + "\n", + "If trace rescaling was performed this dictionary will also contain a `raw_trace` field containing the trace before rescaling.\n", + "Futhermore, if the state was rescaled to be positive or trace 1 an additional field `raw_eigvals` will contain the state eigenvalues before rescaling was performed." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pretty printing has been turned OFF\n" + ] + } + ], + "source": [ + "pprint(qstresult.data()[\"state_metadata\"])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To see the effect of rescaling we can perform a \"bad\" fit with very low counts" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.8686814149289035\n", + "- eigvals: [0.92074124 0.07925876 0. 0. ]\n", + "- raw_eigvals: [ 1.00806592 0.16658344 0.07029948 -0.24494884]\n", + "- trace: 1.0000000000000049\n", + "- positive: True\n", + "- positive_delta: 0.0\n" + ] + } + ], + "source": [ + "# QST Experiment\n", + "bad_data = qstexp1.run(backend, shots=10, seed_simulation=100).block_for_results()\n", + "bad_result = bad_data.analysis_results(0)\n", + "\n", + "print(bad_result.data()[\"state_fidelity\"])\n", + "for key, val in bad_result.data()[\"state_metadata\"].items():\n", + " print(f'- {key}: {val}')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Tomography Fitters\n", + "\n", + "The default fitters is `linear_inversion`, which reconstructs the state using *dual basis* of the tomography basis. This will typically result in a non-postive reconstructed state. This state is rescaled to be postive-semidfinite (PSD) by computing its eigen-decomposition and rescaling its eigenvalues using the approach from *J Smolin, JM Gambetta, G Smith, Phys. Rev. Lett. 108, 070502 (2012), [open access](https://arxiv.org/abs/arXiv:1106.5458).\n", + "\n", + "There are several other fitters are included (See API documentation for details). For example if `cvxpy` is installed we can use the `cvxpy_gaussian_lstsq` fitter which allows constraining the fit to be PSD without requiring rescaling." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "FIT RESULT\n", + "\n", + "Analysis Result: StateTomography\n", + "Analysis Result ID: ce355bf5-8b51-401f-ac79-786cbb28c266\n", + "Experiment ID: a903a1ad-4535-4c28-b7c8-db5f9aec54ae\n", + "Device Components: [, ]\n", + "Quality: None\n", + "Verified: False\n", + "Result Data:\n", + "- state: DensityMatrix([[ 0.47635077+0.00000000e+00j, 0.01748862+3.89240856e-03j,\n", + " 0.02422926-1.18500323e-02j, 0.0008573 -4.47804563e-01j],\n", + " [ 0.01748862-3.89240856e-03j, 0.02291869+0.00000000e+00j,\n", + " 0.00348893+5.05709989e-03j, 0.00532333+1.37176137e-03j],\n", + " [ 0.02422926+1.18500323e-02j, 0.00348893-5.05709989e-03j,\n", + " 0.03382784-8.67361738e-19j, -0.01236219-2.08270256e-02j],\n", + " [ 0.0008573 +4.47804563e-01j, 0.00532333-1.37176137e-03j,\n", + " -0.01236219+2.08270256e-02j, 0.46690269+2.71050543e-20j]],\n", + " dims=(2, 2))\n", + "- fitter_metadata: {'cvxpy_solver': 'CVXOPT', 'cvxpy_status': 'optimal', 'fitter': 'cvxpy_linear_lstsq', 'fitter_time': 0.04554319381713867}\n", + "- success: True\n", + "- state_metadata: {'eigvals': array([9.20753015e-01, 4.72726011e-02, 3.19743598e-02, 2.41266305e-08]), 'raw_eigvals': array([9.22144103e-01, 4.73440213e-02, 3.20226672e-02, 2.41630814e-08]), 'trace': 1.0000000000000002, 'raw_trace': 1.0015108160829784, 'positive': True, 'positive_delta': 0.0}\n", + "- state_fidelity: 0.9194312965227169\n" + ] + } + ], + "source": [ + "qstexp1.run_analysis(qstdata1, fitter='cvxpy_linear_lstsq')\n", + "qstresult2 = qstdata1.analysis_results(-1)\n", + "\n", + "print('FIT RESULT')\n", + "print(qstresult2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Parallel Tomography Experiment\n", + "\n", + "We can also use the `qiskit_experiments.ParallelExperiment` class to run subsystem tomography on multiple qubits in parallel.\n", + "\n", + "For example if we want to perform 1-qubit QST on several qubits at once:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Analysis Result: ParallelExperiment\n", + "Analysis Result ID: 04a4fb78-fbf5-4705-9032-77b81a85b019\n", + "Experiment ID: b761f6c3-f280-4cbe-bfc5-a9a78270697c\n", + "Device Components: [, , , , ]\n", + "Quality: None\n", + "Verified: False\n", + "Result Data:\n", + "- experiment_types: ['StateTomography', 'StateTomography', 'StateTomography', 'StateTomography', 'StateTomography']\n", + "- experiment_ids: ['d79b01b2-d62a-4eed-ae57-efdab09f46d7', 'e4a8c99b-62bd-45c4-8506-8c28a5a91b2a', '451a1368-15c1-4194-b3b4-c7c0a0e5cc23', '81636e00-bbef-4ca1-802d-c1b55f414110', '80dd68ce-390e-479f-8542-07fe6c21427a']\n", + "- experiment_qubits: [(0,), (1,), (2,), (3,), (4,)]\n", + "- success: True\n" + ] + } + ], + "source": [ + "from math import pi\n", + "num_qubits = 5\n", + "gates = [qiskit.circuit.library.RXGate(i * pi / (num_qubits - 1))\n", + " for i in range(num_qubits)]\n", + "\n", + "subexps = [\n", + " StateTomography(gate, qubits=[i])\n", + " for i, gate in enumerate(gates)\n", + "]\n", + "parexp = ParallelExperiment(subexps)\n", + "pardata = parexp.run(backend, seed_simulation=100).block_for_results()\n", + "print(pardata.analysis_results(-1))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "View component experiment analysis results" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "PARALLEL EXP 0: FIT RESULT\n", + "\n", + "Analysis Result: StateTomography\n", + "Analysis Result ID: 5db46640-4a02-4c78-aa82-d0cb8be8e4dc\n", + "Experiment ID: d79b01b2-d62a-4eed-ae57-efdab09f46d7\n", + "Device Components: []\n", + "Quality: None\n", + "Verified: False\n", + "Result Data:\n", + "- state: DensityMatrix([[0.98144531+0.j , 0.00878906-0.03417969j],\n", + " [0.00878906+0.03417969j, 0.01855469+0.j ]],\n", + " dims=(2,))\n", + "- fitter_metadata: {'fitter': 'linear_inversion', 'fitter_time': 0.00010895729064941406}\n", + "- success: True\n", + "- state_metadata: {'eigvals': array([0.98273708, 0.01726292]), 'trace': 1.0000000000000002, 'positive': True, 'positive_delta': 0.0}\n", + "- state_fidelity: 0.9814453125\n", + "\n", + "PARALLEL EXP 1: FIT RESULT\n", + "\n", + "Analysis Result: StateTomography\n", + "Analysis Result ID: 911eeebb-139e-42d8-b9ba-785cc49fbac0\n", + "Experiment ID: e4a8c99b-62bd-45c4-8506-8c28a5a91b2a\n", + "Device Components: []\n", + "Quality: None\n", + "Verified: False\n", + "Result Data:\n", + "- state: DensityMatrix([[0.85644531+0.j , 0.015625 +0.33496094j],\n", + " [0.015625 -0.33496094j, 0.14355469+0.j ]],\n", + " dims=(2,))\n", + "- fitter_metadata: {'fitter': 'linear_inversion', 'fitter_time': 8.511543273925781e-05}\n", + "- success: True\n", + "- state_metadata: {'eigvals': array([0.98938352, 0.01061648]), 'trace': 0.9999999999999999, 'positive': True, 'positive_delta': 0.0}\n", + "- state_fidelity: 0.9888980479297614\n", + "\n", + "PARALLEL EXP 2: FIT RESULT\n", + "\n", + "Analysis Result: StateTomography\n", + "Analysis Result ID: a1b9436d-e63a-4cb6-b9f5-a38b11875fde\n", + "Experiment ID: 451a1368-15c1-4194-b3b4-c7c0a0e5cc23\n", + "Device Components: []\n", + "Quality: None\n", + "Verified: False\n", + "Result Data:\n", + "- state: DensityMatrix([[ 0.4921875 +0.j , -0.00585938+0.47070313j],\n", + " [-0.00585938-0.47070313j, 0.5078125 +0.j ]],\n", + " dims=(2,))\n", + "- fitter_metadata: {'fitter': 'linear_inversion', 'fitter_time': 0.00010514259338378906}\n", + "- success: True\n", + "- state_metadata: {'eigvals': array([0.97080442, 0.02919558]), 'trace': 1.0, 'positive': True, 'positive_delta': 0.0}\n", + "- state_fidelity: 0.9707031249999997\n", + "\n", + "PARALLEL EXP 3: FIT RESULT\n", + "\n", + "Analysis Result: StateTomography\n", + "Analysis Result ID: 29425f7d-0a50-4a99-a0a0-d45dd9115ba1\n", + "Experiment ID: 81636e00-bbef-4ca1-802d-c1b55f414110\n", + "Device Components: []\n", + "Quality: None\n", + "Verified: False\n", + "Result Data:\n", + "- state: DensityMatrix([[0.17578125+0.j , 0.01269531+0.31542969j],\n", + " [0.01269531-0.31542969j, 0.82421875+0.j ]],\n", + " dims=(2,))\n", + "- fitter_metadata: {'fitter': 'linear_inversion', 'fitter_time': 9.799003601074219e-05}\n", + "- success: True\n", + "- state_metadata: {'eigvals': array([0.95252056, 0.04747944]), 'trace': 1.0, 'positive': True, 'positive_delta': 0.0}\n", + "- state_fidelity: 0.9522997477316296\n", + "\n", + "PARALLEL EXP 4: FIT RESULT\n", + "\n", + "Analysis Result: StateTomography\n", + "Analysis Result ID: 49bdcc86-c1cd-494d-94e3-336ff3f19f2a\n", + "Experiment ID: 80dd68ce-390e-479f-8542-07fe6c21427a\n", + "Device Components: []\n", + "Quality: None\n", + "Verified: False\n", + "Result Data:\n", + "- state: DensityMatrix([[0.01953125+0.j , 0.01074219-0.0234375j],\n", + " [0.01074219+0.0234375j, 0.98046875+0.j ]],\n", + " dims=(2,))\n", + "- fitter_metadata: {'fitter': 'linear_inversion', 'fitter_time': 9.965896606445312e-05}\n", + "- success: True\n", + "- state_metadata: {'eigvals': array([0.98115998, 0.01884002]), 'trace': 0.9999999999999997, 'positive': True, 'positive_delta': 0.0}\n", + "- state_fidelity: 0.9804687499999988\n" + ] + } + ], + "source": [ + "for i in range(parexp.num_experiments):\n", + " expdata = pardata.component_experiment_data(i)\n", + " result = expdata.analysis_results(-1)\n", + " \n", + " print(f'\\nPARALLEL EXP {i}: FIT RESULT')\n", + " print(result)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "interpreter": { + "hash": "c45f46a7fd077198472649b02925a2e599779de14e258f4f9ba8eb1d4e684fd2" + }, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.5" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +}