Skip to content

Commit

Permalink
Add HSCA block example to ModelNoise
Browse files Browse the repository at this point in the history
  • Loading branch information
sserita committed Aug 12, 2023
1 parent bb0529a commit c28547a
Showing 1 changed file with 101 additions and 153 deletions.
254 changes: 101 additions & 153 deletions jupyter_notebooks/Tutorials/objects/ModelNoise.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -24,11 +24,12 @@
"metadata": {},
"source": [
"## Standard noise types\n",
"There are three standard types of noise that can be added to operations in pyGSTi: depolarization, stochastic, and Lindbladian. The first two types are common in the literature, while the third, \"Lindbladian\", needs a bit more explanation. Many types of gate errors can be represented in terms of an *error generator*. If $G$ is a noisy gate (a CPTP map) and $G_0$ is it's ideal counterpart, then if we write $G = e^{\\Lambda}G_0$ then $\\Lambda$ is called the gate's *error generator*. A `LindbladErrorgen` object, exponentiated using a `ExpErrorgenOp` object represent this $e^{\\Lambda}$ in pyGSTi. If we write $\\Lambda$ as a sum of terms, $\\Lambda = \\sum_i \\alpha_i F_i$ then, when the $F_i$ are specific generators for well-known errors (e.g. rotations or stochastic errors), the $\\alpha_i$ can roughly be interpreted as the error *rates* corresponding to the well-known error types. PyGSTi has three specific generator types (where $P_i$ is a Pauli operator or tensor product of Pauli operators):\n",
"There are three standard types of noise that can be added to operations in pyGSTi: depolarization, stochastic, and Lindbladian. The first two types are common in the literature, while the third, \"Lindbladian\", needs a bit more explanation. Many types of gate errors can be represented in terms of an *error generator*. If $G$ is a noisy gate (a CPTP map) and $G_0$ is it's ideal counterpart, then if we write $G = e^{\\Lambda}G_0$ then $\\Lambda$ is called the gate's *error generator*. A `LindbladErrorgen` object, exponentiated using a `ExpErrorgenOp` object represent this $e^{\\Lambda}$ in pyGSTi. If we write $\\Lambda$ as a sum of terms, $\\Lambda = \\sum_i \\alpha_i F_i + \\sum_{i\\neq j} \\alpha_{ij} F_{ij}$ then, when the $F_i/F_{ij}$ are specific generators for well-known errors (e.g. rotations or stochastic errors), the $\\alpha_i/\\alpha_{ij}$ can roughly be interpreted as the error *rates* corresponding to the well-known error types. PyGSTi has three specific generator types (where $P_i$ is a Pauli operator or tensor product of Pauli operators):\n",
"\n",
"- **Hamiltonian**: $F_i = H_i$ where $H_i : \\rho \\rightarrow -i[P_i,\\rho]$\n",
"- **Stochastic**: $F_i = S_i$ where $S_i : \\rho \\rightarrow P_i \\rho P_i - \\rho$\n",
"- **Affine**: $F_i = A_i$ where $A_i : \\rho \\rightarrow \\mathrm{Tr}(\\rho_{target})P_i \\otimes \\rho_{non-target}$\n",
"- **Hamiltonian**: $H_i : \\rho \\rightarrow -i[P_i,\\rho]$\n",
"- **Stochastic**: $S_i : \\rho \\rightarrow P_i \\rho P_i - \\rho$\n",
"- **Correlated**: $C_{ij} : \\rho \\rightarrow P_i \\rho P_j + P_j \\rho P_i - \\frac{1}{2}\\{\\{P_i,P_j\\}, \\rho\\}$\n",
"- **Affine/Active**: $A_{ij} : \\rho \\rightarrow i\\left(P_i \\rho P_j + P_j \\rho P_i + \\frac{1}{2}\\{[P_i,P_j], \\rho\\}\\right)$\n",
"\n",
"See our recent paper on [the taxonomy of small errors](https://arxiv.org/abs/2103.01928v1) for a more theoretical foundation of error generators.\n",
"\n",
Expand All @@ -38,8 +39,9 @@
"- `stochastic_error_probs`: Values are lists of length $4^{N_{qubits} - 1}$, which correspond to coefficients of a stochastic Pauli channel in a `StochasticNoiseOp`. Order of the rates is lexographical, and can be checked by looking at the elements of a `\"pp\"` Basis object.\n",
"- `lindblad_error_coeffs`: Values are a dict where the key has the form `(<type>, <basis_elements>)` and the values are the $\\alpha_i$ coefficients in the sum of Lindblad terms, which are then exponentiated to give the final noise. The type includes:\n",
" - `'H'` for Hamiltonian errors\n",
" - `'S'` for Pauli-stochastic and Pauli-correlation errors (S and C in the error generator taxonomy)\n",
" - `'A'` for affine errors\n",
" - `'S'` for Pauli-stochastic errors\n",
" - `'C'` for correlated Pauli-stochastic errors\n",
" - `'A'` for affine/active errors\n",
" \n",
" and strings of `I`, `X`, `Y`, and `Z` can be used to label a Pauli basis element. \n",
"\n",
Expand All @@ -49,7 +51,7 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -75,39 +77,9 @@
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Gxpi2\n",
"Composed operation of 2 factors:\n",
"Factor 0:\n",
"StaticStandardOp with name Gxpi2 and evotype densitymx\n",
"Factor 1:\n",
"Depolarize noise operation map with dim = 4, num params = 1\n",
"Strength: [0.1]\n",
"\n",
"Gypi2\n",
"Composed operation of 2 factors:\n",
"Factor 0:\n",
"StaticStandardOp with name Gypi2 and evotype densitymx\n",
"Factor 1:\n",
"Stochastic noise operation map with state space = QubitSpace((0,)), num params = 3\n",
"Rates: [0.04 0.05 0.02]\n",
"\n",
"Gcnot\n",
"Composed operation of 2 factors:\n",
"Factor 0:\n",
"StaticStandardOp with name Gcnot and evotype densitymx\n",
"Factor 1:\n",
"Exponentiated operation map with dim = 16, num params = 1\n",
"\n"
]
}
],
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for gate_name, gate in mdl_locnoise.operation_blks['gates'].items():\n",
" print(gate_name)\n",
Expand All @@ -123,67 +95,9 @@
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Modelmember category: prep_blks|layers\n",
" rho0: ComputationalBasisState (0) : (contents not available)\n",
"\n",
"Modelmember category: povm_blks|layers\n",
" Mdefault: ComputationalBasisPOVM (1) : (contents not available)\n",
"\n",
"Modelmember category: operation_blks|gates\n",
" Gxpi2: ComposedOp (4) : composed of 2 factors\n",
" StaticStandardOp (2) : Gxpi2 gate\n",
" DepolarizeOp (3) : strength: [0.1]\n",
" Gypi2: ComposedOp (7) : composed of 2 factors\n",
" StaticStandardOp (5) : Gypi2 gate\n",
" StochasticNoiseOp (6) : rates: [0.04 0.05 0.02]\n",
" Gcnot: ComposedOp (11) : composed of 2 factors\n",
" StaticStandardOp (8) : Gcnot gate\n",
" ExpErrorgenOp (10) : exponentiates\n",
" LindbladErrorgen (9) : H(ZZ:0,1): 0.15\n",
"\n",
"Modelmember category: operation_blks|layers\n",
" Gxpi2:0: EmbeddedOp (12) : embeds (0,) into QubitSpace((0, 1))\n",
" ComposedOp (4) : --link--^\n",
" StaticStandardOp (2) : --link--^\n",
" DepolarizeOp (3) : --link--^\n",
" Gxpi2:1: EmbeddedOp (13) : embeds (1,) into QubitSpace((0, 1))\n",
" ComposedOp (4) : --link--^\n",
" StaticStandardOp (2) : --link--^\n",
" DepolarizeOp (3) : --link--^\n",
" Gypi2:0: EmbeddedOp (14) : embeds (0,) into QubitSpace((0, 1))\n",
" ComposedOp (7) : --link--^\n",
" StaticStandardOp (5) : --link--^\n",
" StochasticNoiseOp (6) : --link--^\n",
" Gypi2:1: EmbeddedOp (15) : embeds (1,) into QubitSpace((0, 1))\n",
" ComposedOp (7) : --link--^\n",
" StaticStandardOp (5) : --link--^\n",
" StochasticNoiseOp (6) : --link--^\n",
" Gcnot:0:1: ComposedOp (11) : --link--^\n",
" StaticStandardOp (8) : --link--^\n",
" ExpErrorgenOp (10) : --link--^\n",
" LindbladErrorgen (9) : --link--^\n",
" Gcnot:1:0: EmbeddedOp (16) : embeds (1, 0) into QubitSpace((0, 1))\n",
" ComposedOp (11) : --link--^\n",
" StaticStandardOp (8) : --link--^\n",
" ExpErrorgenOp (10) : --link--^\n",
" LindbladErrorgen (9) : --link--^\n",
"\n",
"Modelmember category: instrument_blks|layers\n",
"\n",
"Modelmember category: factories|gates\n",
"\n",
"Modelmember category: factories|layers\n",
"\n"
]
}
],
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"mdl_locnoise.print_modelmembers()"
]
Expand All @@ -200,55 +114,9 @@
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Modelmember category: prep_blks|layers\n",
" rho0: ComputationalBasisState (0) : (contents not available)\n",
"\n",
"Modelmember category: povm_blks|layers\n",
" Mdefault: ComputationalBasisPOVM (1) : (contents not available)\n",
"\n",
"Modelmember category: operation_blks|gates\n",
" Gxpi2: ComposedOp (4) : composed of 2 factors\n",
" StaticStandardOp (2) : Gxpi2 gate\n",
" StochasticNoiseOp (3) : rates: [0.04 0.05 0.02]\n",
" Gxpi2:0: ComposedOp (6) : composed of 2 factors\n",
" StaticStandardOp (2) : --link--^\n",
" StochasticNoiseOp (5) : rates: [0.08 0.1 0.06]\n",
" Gypi2: StaticStandardOp (7) : Gypi2 gate\n",
" Gcnot: StaticStandardOp (8) : Gcnot gate\n",
"\n",
"Modelmember category: operation_blks|layers\n",
" Gxpi2:0: EmbeddedOp (9) : embeds (0,) into QubitSpace((0, 1))\n",
" ComposedOp (6) : --link--^\n",
" StaticStandardOp (2) : --link--^\n",
" StochasticNoiseOp (5) : --link--^\n",
" Gxpi2:1: EmbeddedOp (10) : embeds (1,) into QubitSpace((0, 1))\n",
" ComposedOp (4) : --link--^\n",
" StaticStandardOp (2) : --link--^\n",
" StochasticNoiseOp (3) : --link--^\n",
" Gypi2:0: EmbeddedOp (11) : embeds (0,) into QubitSpace((0, 1))\n",
" StaticStandardOp (7) : --link--^\n",
" Gypi2:1: EmbeddedOp (12) : embeds (1,) into QubitSpace((0, 1))\n",
" StaticStandardOp (7) : --link--^\n",
" Gcnot:0:1: StaticStandardOp (8) : --link--^\n",
" Gcnot:1:0: EmbeddedOp (13) : embeds (1, 0) into QubitSpace((0, 1))\n",
" StaticStandardOp (8) : --link--^\n",
"\n",
"Modelmember category: instrument_blks|layers\n",
"\n",
"Modelmember category: factories|gates\n",
"\n",
"Modelmember category: factories|layers\n",
"\n"
]
}
],
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"mdl_locnoise = pygsti.models.create_crosstalk_free_model(pspec,\n",
" stochastic_error_probs={\n",
Expand All @@ -271,7 +139,7 @@
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
Expand Down Expand Up @@ -387,6 +255,86 @@
"explicit_model.print_modelmembers()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Reduced error generator models\n",
"\n",
"One potentially powerful way to include nonlocal noise with a few lines of code is to include entire sectors of the elementary error generators. For example, one can extend past a crosstalk-free model with only a few parameters by including the H and S sectors on neighboring qubits.\n",
"\n",
"First, let us create an ideal model similar to those above:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"ideal_model = mc.create_explicit_model(pspec) # No noise, we will add that manually!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next, we will make lists of all the weight-1 and weight-2 Pauli strings. We will use these to restrict the CA blocks to only weight-1 later."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"w1_labels = [lbl for lbl in ideal_model.basis.labels if sum([c != 'I' for c in lbl]) == 1]\n",
"w2_labels = [lbl for lbl in ideal_model.basis.labels if sum([c != 'I' for c in lbl]) == 2]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we can go through each operation and create three \"coefficient blocks\". Naively, what we want are weight-1 and weight-2 H and S errors (HS2) and only weight-1 C and A (CA1) errors, but we have to organize our blocks slightly differently due to how they are stored internally. The blocks we can make are:\n",
"\n",
"- H only blocks\n",
"- S only blocks\n",
"- SCA blocks\n",
"\n",
"So we instead build our blocks as: H12, S2, SCA1.\n",
"\n",
"Finally, once we have our blocks, we create the actual Lindbladian error generator and append the exponentiated Lindbladian to the ideal operation."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import pygsti.modelmembers.operations as ops\n",
"from pygsti.modelmembers.operations.lindbladcoefficients import LindbladCoefficientBlock as LindbladCBlock\n",
"\n",
"HS2_CA1_model = ideal_model.copy()\n",
"HS2_CA1_model.operations.flags['auto_embed'] = False\n",
"\n",
"for lbl, op in HS2_CA1_model.operations.items():\n",
" # Lindblad coefficient blocks\n",
" H12_block = LindbladCBlock('ham', ideal_model.basis, w1_labels + w2_labels, param_mode='elements')\n",
" \n",
" S2_block = LindbladCBlock('other_diagonal', ideal_model.basis, w2_labels, param_mode='cholesky')\n",
" \n",
" SCA1_block = LindbladCBlock('other', ideal_model.basis, w1_labels, param_mode='cholesky')\n",
" \n",
" # Build op\n",
" errgen = ops.LindbladErrorgen([H12_block, S2_block, SCA1_block], state_space=ideal_model.state_space)\n",
" HS2_CA1_model.operations[lbl] = ops.ComposedOp([\n",
" op.copy(),\n",
" ops.ExpErrorgenOp(errgen)\n",
" ])"
]
},
{
"cell_type": "markdown",
"metadata": {},
Expand Down Expand Up @@ -767,7 +715,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.13"
"version": "3.10.10"
}
},
"nbformat": 4,
Expand Down

0 comments on commit c28547a

Please sign in to comment.