From 8dd0443cf43a0bc2d2226a0f76af041563134c3c Mon Sep 17 00:00:00 2001 From: "Stefan K. Seritan" Date: Mon, 15 Apr 2024 16:49:56 -0700 Subject: [PATCH] Partial leakage notebook fix after PR #418 --- jupyter_notebooks/Examples/Leakage.ipynb | 145 +++++++++++++++-------- pygsti/algorithms/fiducialselection.py | 18 ++- 2 files changed, 113 insertions(+), 50 deletions(-) diff --git a/jupyter_notebooks/Examples/Leakage.ipynb b/jupyter_notebooks/Examples/Leakage.ipynb index 051e6dd9b..346e837ff 100644 --- a/jupyter_notebooks/Examples/Leakage.ipynb +++ b/jupyter_notebooks/Examples/Leakage.ipynb @@ -15,7 +15,9 @@ "outputs": [], "source": [ "import pygsti\n", - "import pygsti.modelpacks.legacy.std1Q_XYI as std1Q\n", + "import pygsti.modelpacks.smq1Q_XYI as smq1Q\n", + "from pygsti.baseobjs import Label\n", + "from pygsti.circuits import Circuit\n", "import numpy as np\n", "import scipy.linalg as sla\n", "#import pickle" @@ -49,8 +51,7 @@ "metadata": {}, "outputs": [], "source": [ - "mdl_2level_ideal = std1Q.target_model()\n", - "mdl_2level_ideal.sim = \"matrix\" # so we can create reports later on" + "mdl_2level_ideal = smq1Q.target_model(qubit_labels=[\"Qubit\"])" ] }, { @@ -67,17 +68,16 @@ " [0,1,0],\n", " [0,0,1]], complex)\n", "\n", - "sslbls = pygsti.baseobjs.ExplicitStateSpace(['Qubit+Leakage'],[3])\n", - "mdl_3level_ideal = pygsti.models.ExplicitOpModel(sslbls, 'gm')\n", + "sslbls = pygsti.baseobjs.ExplicitStateSpace(['Qubit_leakage'],[3])\n", + "mdl_3level_ideal = pygsti.models.ExplicitOpModel(sslbls, 'gm', simulator='matrix')\n", "mdl_3level_ideal['rho0'] = pygsti.tools.stdmx_to_gmvec(rho0)\n", "mdl_3level_ideal['Mdefault'] = pygsti.modelmembers.povms.TPPOVM([('0',pygsti.tools.stdmx_to_gmvec(E0)),\n", " ('1',pygsti.tools.stdmx_to_gmvec(E1))],\n", " evotype='default')\n", "\n", - "mdl_3level_ideal['Gi'] = unitary_to_gmgate( to_3level_unitary(Us['Gi']))\n", - "mdl_3level_ideal['Gx'] = unitary_to_gmgate( to_3level_unitary(Us['Gxpi2']))\n", - "mdl_3level_ideal['Gy'] = unitary_to_gmgate( to_3level_unitary(Us['Gypi2']))\n", - "mdl_3level_ideal.sim = \"matrix\" # so we can create reports later on" + "mdl_3level_ideal[tuple()] = unitary_to_gmgate( to_3level_unitary(Us['Gi']))\n", + "mdl_3level_ideal['Gxpi2', 'Qubit_leakage'] = unitary_to_gmgate( to_3level_unitary(Us['Gxpi2']))\n", + "mdl_3level_ideal['Gypi2', 'Qubit_leakage'] = unitary_to_gmgate( to_3level_unitary(Us['Gypi2']))" ] }, { @@ -95,15 +95,15 @@ "\n", "#Guess of a model w/just unitary leakage\n", "mdl_3level_guess = mdl_3level_ideal.copy()\n", - "mdl_3level_guess['Gi'] = np.dot(leakageOp, mdl_3level_guess['Gi'])\n", - "#mdl_3level_guess['Gx'] = np.dot(leakageOp, mdl_3level_guess['Gx'])\n", - "#mdl_3level_guess['Gy'] = np.dot(leakageOp, mdl_3level_guess['Gy'])\n", + "mdl_3level_guess[tuple()] = np.dot(leakageOp, mdl_3level_guess[tuple()])\n", + "#mdl_3level_guess['Gxpi2', 'Qubit_leakage'] = np.dot(leakageOp, mdl_3level_guess['Gxpi2', 'Qubit_leakage'])\n", + "#mdl_3level_guess['Gypi2', 'Qubit_leakage'] = np.dot(leakageOp, mdl_3level_guess['Gypi2', 'Qubit_leakage'])\n", "\n", "#Actual model used for data generation (some depolarization too)\n", "mdl_3level_noisy = mdl_3level_ideal.depolarize(op_noise=0.005, spam_noise=0.01)\n", - "mdl_3level_noisy['Gi'] = np.dot(leakageOp, mdl_3level_noisy['Gi'])\n", - "#mdl_3level_noisy['Gx'] = np.dot(leakageOp, mdl_3level_noisy['Gx'])\n", - "#mdl_3level_noisy['Gy'] = np.dot(leakageOp, mdl_3level_noisy['Gy'])" + "mdl_3level_noisy[tuple()] = np.dot(leakageOp, mdl_3level_noisy[tuple()])\n", + "#mdl_3level_noisy['Gxpi2', 'Qubit_leakage'] = np.dot(leakageOp, mdl_3level_noisy['Gxpi2', 'Qubit_leakage'])\n", + "#mdl_3level_noisy['Gypi2', 'Qubit_leakage'] = np.dot(leakageOp, mdl_3level_noisy['Gypi2', 'Qubit_leakage'])" ] }, { @@ -126,7 +126,7 @@ "\n", "if find_fiducials:\n", " prepfids, measfids = pygsti.algorithms.find_fiducials(\n", - " mdl_3level_guess, omit_identity=False, max_fid_length=4, verbosity=4)\n", + " mdl_3level_guess, omit_identity=False, candidate_fid_counts={4: \"all upto\"}, verbosity=4)\n", " pygsti.io.write_circuit_list(\"example_files/leakage_prepfids.txt\", prepfids)\n", " pygsti.io.write_circuit_list(\"example_files/leakage_measfids.txt\", measfids)" ] @@ -140,11 +140,8 @@ "# If files missing, run previous cell at least once with find_fiducials = True\n", "prepfids = pygsti.io.read_circuit_list(\"example_files/leakage_prepfids.txt\")\n", "measfids = pygsti.io.read_circuit_list(\"example_files/leakage_measfids.txt\")\n", - "# HACK: Fix broken force empty labels\n", - "prepfids[-1] = pygsti.circuits.Circuit([])\n", - "measfids[-1] = pygsti.circuits.Circuit([])\n", - "germs = std1Q.germs\n", - "maxLengths = [1,]\n", + "germs = smq1Q.germs(qubit_labels=[\"Qubit_leakage\"])\n", + "maxLengths = [1,2]\n", "expList = pygsti.circuits.create_lsgst_circuits(mdl_3level_noisy, prepfids, measfids, germs, maxLengths)\n", "ds = pygsti.data.simulate_data(mdl_3level_noisy, expList, 1000, 'binomial', seed=1234)" ] @@ -155,8 +152,37 @@ "metadata": {}, "outputs": [], "source": [ - "results_2level = pygsti.run_stdpractice_gst(ds, mdl_2level_ideal, prepfids, measfids,\n", - " germs, maxLengths, modes=\"CPTPLND\", verbosity=3)" + "\n", + "# We have found out prep fids, meas fids, and germs, as well as simulated noisy data, for the 3 level model\n", + "# If we want to run GST on another model, we need to get versions of the circuits will the correct state space labels\n", + "\n", + "def map_2level_sslbls(circuit):\n", + " sslbl_map = {'Qubit_leakage': 'Qubit'}\n", + " return circuit.map_state_space_labels(sslbl_map)\n", + "\n", + "prepfids_2level = [map_2level_sslbls(c) for c in prepfids]\n", + "measfids_2level = [map_2level_sslbls(c) for c in measfids]\n", + "germs_2level = [map_2level_sslbls(c) for c in germs]\n", + "ds_2level = ds.process_circuits(map_2level_sslbls)\n", + "\n", + "results_2level = pygsti.run_stdpractice_gst(ds_2level, mdl_2level_ideal, prepfids_2level, measfids_2level,\n", + " germs_2level, maxLengths, modes=\"CPTPLND\", verbosity=3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pygsti.report.construct_standard_report(results_2level, \"2-level Leakage Example Report\").write_html('example_files/leakage_report_2level')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Open the report [here](example_files/leakage_report_2level/main.html)" ] }, { @@ -168,7 +194,7 @@ "outputs": [], "source": [ "results_3level = pygsti.run_stdpractice_gst(ds, mdl_3level_ideal, prepfids, measfids,\n", - " germs, maxLengths, modes=[\"CPTP\",\"True\"],\n", + " germs, maxLengths, modes=[\"CPTPLND\",\"True\"],\n", " models_to_test={'True': mdl_3level_noisy}, \n", " verbosity=4, advanced_options={'all': {'tolerance': 1e-2}})" ] @@ -179,10 +205,14 @@ "metadata": {}, "outputs": [], "source": [ - "pygsti.report.construct_standard_report(\n", - " {'two-level': results_2level, 'three-level': results_3level},\n", - " \"Leakage Example Report\"\n", - ").write_html('example_files/leakage_report')" + "pygsti.report.construct_standard_report(results_3level, \"3-level Leakage Example Report\").write_html('example_files/leakage_report')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Open the report [here](example_files/leakage_report/main.html)" ] }, { @@ -254,17 +284,15 @@ "metadata": {}, "outputs": [], "source": [ - "pygsti.report.construct_standard_report(\n", - " {'two-level': results_2level, 'three-level': results_3level_leakage_basis},\n", - " \"Leakage Example Report\"\n", - ").write_html('example_files/leakage_report')" + "pygsti.report.construct_standard_report(results_3level_leakage_basis, \"3-level with Basis Change Leakage Example Report\"\n", + " ).write_html('example_files/leakage_report_basis')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Open the report [here](example_files/leakage_report/main.html)" + "Open the report [here](example_files/leakage_report_basis/main.html)" ] }, { @@ -288,15 +316,15 @@ "E1 = np.concatenate( (mdl_2level_ideal.povms['Mdefault']['1'].to_dense(),[eps]), axis=0)\n", "\n", "\n", - "statespace = pygsti.baseobjs.ExplicitStateSpace([('Qubit',),('Leakage',)],[(2,),(1,)])\n", - "mdl_2plus1_ideal = pygsti.models.ExplicitOpModel(statespace, 'gm')\n", + "statespace = pygsti.baseobjs.ExplicitStateSpace([('Qubit',),('Leakage',)], [(2,), (1,)])\n", + "mdl_2plus1_ideal = pygsti.models.ExplicitOpModel(statespace, 'gm', simulator='matrix')\n", "mdl_2plus1_ideal['rho0'] = rho0\n", "mdl_2plus1_ideal['Mdefault'] = pygsti.modelmembers.povms.UnconstrainedPOVM([('0',E0),('1',E1)],\n", " evotype='default', state_space=statespace)\n", "\n", - "mdl_2plus1_ideal['Gi'] = to_2plus1_superop(mdl_2level_ideal['Gi'])\n", - "mdl_2plus1_ideal['Gx'] = to_2plus1_superop(mdl_2level_ideal['Gx'])\n", - "mdl_2plus1_ideal['Gy'] = to_2plus1_superop(mdl_2level_ideal['Gy'])" + "mdl_2plus1_ideal[tuple()] = to_2plus1_superop(mdl_2level_ideal[tuple()])\n", + "mdl_2plus1_ideal['Gxpi2'] = to_2plus1_superop(mdl_2level_ideal['Gxpi2', 'Qubit'])\n", + "mdl_2plus1_ideal['Gypi2'] = to_2plus1_superop(mdl_2level_ideal['Gypi2', 'Qubit'])" ] }, { @@ -305,14 +333,36 @@ "metadata": {}, "outputs": [], "source": [ - "mdl_2plus1_ideal.sim = \"matrix\" # so we can construct report below\n", - "results_2plus1 = pygsti.run_long_sequence_gst(ds, mdl_2plus1_ideal, prepfids, measfids,\n", - " germs, maxLengths, verbosity=2,\n", + "# We have found out prep fids, meas fids, and germs, as well as simulated noisy data, for the 3 level model\n", + "# If we want to run GST on another model, we need to get versions of the circuits will the correct state space labels\n", + "\n", + "# We do this in a slightly different/awkward way here for this case since our state space labels are not a single entry\n", + "# This would not be necessary if we were rebuilding the circuits/dataset from scratch, only hacky since we are reusing the 3-level information\n", + "def map_2plus1_circuit_linelabels(circuit):\n", + " return Circuit([Label(l.name) if l.name != \"COMPOUND\" else tuple() for l in circuit.layertup],\n", + " ['Qubit', 'Leakage'], None, not circuit._static)\n", + "\n", + "prepfids_2plus1 = [map_2plus1_circuit_linelabels(c) for c in prepfids]\n", + "measfids_2plus1 = [map_2plus1_circuit_linelabels(c) for c in measfids]\n", + "germs_2plus1 = [map_2plus1_circuit_linelabels(c) for c in germs]\n", + "ds_2plus1 = ds.process_circuits(map_2plus1_circuit_linelabels)\n", + "\n", + "results_2plus1 = pygsti.run_long_sequence_gst(ds_2plus1, mdl_2plus1_ideal, prepfids_2plus1, measfids_2plus1,\n", + " germs_2plus1, maxLengths, verbosity=2,\n", " advanced_options={\"starting_point\": \"target\",\n", " \"tolerance\": 1e-8, # (lowering tolerance from 1e-6 gave a better fit)\n", " \"estimate_label\": \"kite\"})" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mdl_2plus1_ideal._default_primitive_povm_layer_lbl()" + ] + }, { "cell_type": "code", "execution_count": null, @@ -324,11 +374,8 @@ "outputs": [], "source": [ "# TODO: This is currently broken\n", - "pygsti.report.construct_standard_report(\n", - " {'two-level': results_2level, 'three-level': results_3level_leakage_basis,\n", - " 'two+one level': results_2plus1},\n", - " \"Leakage Example Report\"\n", - ").write_html('example_files/leakage_report', autosize='none')" + "pygsti.report.construct_standard_report(results_2plus1,\"2+1 Leakage Example Report\"\n", + ").write_html('example_files/leakage_report_2plus1', autosize='none')" ] }, { @@ -341,9 +388,9 @@ ], "metadata": { "kernelspec": { - "display_name": "leakage_models", + "display_name": "pygsti", "language": "python", - "name": "leakage_models" + "name": "python3" }, "language_info": { "codemirror_mode": { @@ -355,7 +402,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.13" + "version": "3.11.5" } }, "nbformat": 4, diff --git a/pygsti/algorithms/fiducialselection.py b/pygsti/algorithms/fiducialselection.py index 39ff8d6de..536db2847 100644 --- a/pygsti/algorithms/fiducialselection.py +++ b/pygsti/algorithms/fiducialselection.py @@ -2013,7 +2013,23 @@ def create_candidate_fiducial_list(target_model, omit_identity= True, ops_to_omi else: availableFidList.extend(_circuits.list_random_circuits_onelen( fidOps, fidLength, count, seed=candidate_seed)) - return availableFidList + + #force the line labels on each circuit to match the state space labels for the target model. + #this is suboptimal for many-qubit models, so will probably want to revisit this. #TODO + finalFidList = [] + for ckt in availableFidList: + if ckt._static: + new_ckt = ckt.copy(editable=True) + new_ckt.line_labels = target_model.state_space.state_space_labels + new_ckt.done_editing() + + finalFidList.append(new_ckt) + else: + ckt.line_labels = target_model.state_space.state_space_labels + + finalFidList.append(ckt) + + return finalFidList