{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Quantum state propagation in pyGSTi\n", "The ability prepare, propagate, and measure quantum states in simulations is a core capability of pyGSTi. We call the calculation of circuit outcome probabilities *forward simulation*, and this type of calculation lies at the heart of Gate Set Tomography and other characterization protocols which need to compare a model's predictions with actual data. As you're probably already encountered through other tutorials, `Model` objects have a `.probs(circuit)` method that performs forward simulation (computes the outcome probabilities of `circuit`). \n", "\n", "What is not so apparent is that there can be several different types of computational \"engines\" under the hood of a `Model` that do the heavy lifting within a call to `probs`. **Understanding the different types of forward simulation engines in pyGSTi is the topic of this tutorial.**\n", "\n", "First, let's lay down a bit of background. A `Model` contains a `.evotype` attribute that describes what type of *state* object is being stored and propagated by the model - the *evolution type*. Allowed values are:\n", "- `\"densitymx\"`: a *mixed* state is propagated as a vectorized density matrix (of length $4^n$ for $n$ qubits) in a Hermitian basis (so its elements are *real*). If an operation is represented as a dense (real) matrix, its shape is $4^n \\times 4^n$. This is the default evolution type in pyGSTi.\n", "- `\"statevec\"`: a *pure* state is propagated as a complex state vector (of length $2^n$ for $n$ qubits). Dense operations representations are $2^n \\times 2^n$ unitary matrices in this case. Because of the lower dimensionality, state-vector propagation is faster than density-matrix propagation, and is therefore preferable when all preparations and POVM effects are pure states and projections, and all operations are unitary.\n", "- `\"stabilizer\"`: a *stabilizer* state is propagated by keeping track of its stabilizer (and anti-stabilizer) group generators. This only requires memory that scales with $n$ for $n$ qubits, and so this state representation offers significantly more efficient simulation than the two aforementioned evolution types. The caveat is preparations must prepare a stabilizer state, POVMs must measure in the computational $z$-basis, and *all operations must be Clifford elements*, mapping Pauli group elements to Pauli group elements.\n", "- `\"svterm\"` and `\"cterm\"`: advanced topic to be added at a later time.\n", "\n", "\n", "Every operator (state preparation, POVM, gate/layer operation) within a `Model` also has an evolution type, and it must match the parent `Model`'s `.evotype`. (You usually don't need to worry about this; `Model` objects are created with a given `evotype` and their contained elements are created to match that type.) \n", "\n", "Related to their `evotype`, `Model` objects also have a `simtype` attribute. This attribute determines which forward simulation engine is used when the model is asked to compute circuit probabilities. There are again several different options, but each `simtype` value is only compatible with certain evolution types (`evotype` value):\n", "- `\"map\"`: propagate a `\"densitymx\"`, `\"statevec\"`, `\"stabilizer\"` state by repeatedly acting with circuit layer operators, treated as maps from an input to an output state. When there is a dense layer-operation matrix for each circuit layer, this engine repeatedly performs matrix-vector products (one per layer, between the operation matrix and column-vector state) and finally contracts the result with each row-vector POVM effect to get outcome probabilities. This is the most straightforward and intuitive of the forward simulation engines, so much so that you may be thinking \"what else would you do?\". Keep reading :)\n", "- `\"matrix\"`: propagate a `\"densitymx\"` or `\"statevec\"` state by composing a dense operation matrix for the entire circuit and then applying that \"circuit map\" to the input state. Each circuit layer *must be representable as a dense matrix* to use this forward simulation type, as it multiplies together the matrices of each layer (in reverse order!) to get a single \"circuit matrix* and then contracts this matrix between the (column vector) state preparation and each of the (row vector) POVM effects (and norm-squaring the result when the evolution type is `\"statevec\"`) to get outcome probabilities. At first glance this seems like a very inefficient way to compute probabilities since it performs matrix-matrix instead of matrix-vector multiplications, and it is true that this method should not be used with many-qubit models. However, for lower dimensional Hilbert spaces (1-2 qubits in practice) the ability to cache and reuse intermediate results can make this method faster than the `\"map\"` method when the outcome probabilities of *many* circuits are needed at once (as is the case in Gate Set Tomography, for instance). Indeed, it was specifically for 1- and 2-qubit GST that this method was implemented. Apart from this case, `\"map\"` should be used (thought using `\"matrix\"` instead on 1 or 2 qubit systems often achieves similar run times because of other technical implementation factors).\n", "- `\"termorder\"`: advanced topic to be added at a later time\n", "\n", "\n", "Thus, but setting a model's `evotype` and `simtype` you can specify how circuit-probability-computation is implemented. But how do you set these values? The `evotype` of a `Model` is almost always set for good when the object is created. The `simtype` *can* be changed using the `set_simtype` method of a `Model`, but it's usually set to an appropriate value at object-creation time and doesn't need to be altered. Here's how several of pyGSTi's model-construction routines allow you to set (or set for you) the `evotype` and `simtype` (note that this is often done *indirectly*, as setting the `evotype` is largely done \"under the hood\", and the default behavior is usually what is desired):\n", "- When creating an empty `ExplicitOpModel`, you can specify `evotype` and `sim_type` arguments.\n", "\n", "\n", "- `pygsti.construction.build_explicit_model` currently *always* creates a model with the `\"densitymx\"` evolution type. (It accepts a `parameterization` argument, which may, in the future, be used to construct models with other evolution types.)\n", "\n", "\n", "- `pygsti.construction.build_standard_localnoise_model`, `LocalNoiseModel.build_standard`, and just `LocalNoiseModel` have a `parameterization` argument which is the easiest way to create models with various evolution types. Here is an incomplete list of valid `parameterization` values and the corresponding evolution type of the created `Model`:\n", " - `\"static\"`, `\"full\"`, `\"TP\"`, `\"CPTP\"`, `\"H+S\"` $\\rightarrow$ `\"densitymx\"`\n", " - `\"static unitary\"` $\\rightarrow$ `\"statevec\"`\n", " - `\"clifford\"` $\\rightarrow$ `\"stabilizer\"`\n", " - `\"H+S\"` $\\rightarrow$ `\"densitymx\"`\n", " - `\"H+S terms\"` $\\rightarrow$ `\"svterm\"`\n", " - `\"H+S clifford terms\"` $\\rightarrow$ `\"cterm\"`\n", " \n", " There are also a separate `\"evotype\"` argument, which should usually be left as `\"auto\"` unless you want to override the default behavior of the `parameterization` argument. The `\"sim_type\"` argument can be used to override the default choice of forward simulation type/engine, which is usually unnecessary. The `\"matrix\"` simulator is used only for $\\le 2$ qubits, for instance.\n", "\n", "\n", "- `pygsti.construction.build_standard_cloudnoise_model`, `CloudNoiseModel.build_standard`, and just `CloudNoiseModel` similarly have a `parameterization` argument which determines the evolution type. Here are some allowed examples:\n", " - `\"H+S\"` $\\rightarrow$ `\"densitymx\"`\n", " - `\"H+S terms\"` $\\rightarrow$ `\"svterm\"`\n", " - `\"H+S clifford terms\"` $\\rightarrow$ `\"cterm\"`\n", " \n", " Similar to the local noisie model case, the `\"sim_type\"` argument can be used to override the default choice of forward simulation type/engine, which is usually unnecessary. \n", " \n", " \n", "Below, we'll demonstrate the use of different evolution and forward-simulation types using a local-noise model on 5 and then 10 qubits. \n", "\n", "## 5 qubits\n", "First, let's generate a random circuit using the Randomized Benchmarking (RB) sub-package `pygsti.extras.rb` (just so we don't need to write down a circuit by hand). See the [Randomized Benchmarking tutorial](../RBAnalysis.ipynb) for more information about running RB." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Qubit 0 ---|Gx|-|Gy|-|Gx|-|C1|-|C1|-|C1|-|Gx|-|C1|-|Gy|-|Gy|-|C1|-|C1|-|C1|-|Gx|-|Gy|-|C1|-|C1|-|Gx|-|C1|-|Gy|---\n", "Qubit 1 ---|Gy|-|C2|-|Gx|-|T0|-|T0|-|T0|-|Gy|-|T0|-|Gy|-|Gx|-|T0|-|T0|-|T0|-|C2|-|Gx|-|T0|-|T0|-|C2|-|T0|-|C2|---\n", "Qubit 2 ---|Gy|-|T1|-|Gx|-|Gx|-|Gy|-|C3|-|C3|-|Gx|-|Gx|-|C3|-|C3|-|Gx|-|Gy|-|T1|-|Gy|-|Gy|-|Gx|-|T1|-|Gy|-|T1|---\n", "Qubit 3 ---|Gx|-|Gx|-|Gx|-|C4|-|C4|-|T2|-|T2|-|Gx|-|Gx|-|T2|-|T2|-|Gy|-|Gy|-|Gy|-|C4|-|Gy|-|C4|-|Gx|-|Gx|-|Gx|---\n", "Qubit 4 ---|Gx|-|Gx|-|Gy|-|T3|-|T3|-|Gy|-|Gx|-|Gy|-|Gx|-|Gx|-|Gx|-|Gy|-|Gx|-|Gx|-|T3|-|Gy|-|T3|-|Gy|-|Gy|-|Gy|---\n", "\n" ] } ], "source": [ "import pygsti, time\n", "import numpy as np\n", "from pygsti.extras import rb\n", "\n", "nQubits = 5\n", "ps = pygsti.obj.ProcessorSpec(nQubits=nQubits, gate_names=['Gx','Gy','Gcnot'],\n", " availability={'Gcnot': [(i,i+1) for i in range(nQubits-1)]})\n", "c = rb.sample.random_circuit(ps, length=20)\n", "print(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Propagate a **density matrix** (`\"densitymx\"` evolution type) using the **matrix-matrix multiplying** forward simulator (`\"matrix\"`):" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Gx gate is a \n", "32 probabilities computed in 10.406s\n" ] } ], "source": [ "mdl = pygsti.construction.build_standard_localnoise_model(\n", " nQubits, ['Gx','Gy','Gcnot'], sim_type=\"matrix\")\n", "print(\"Gx gate is a \",type(mdl.operation_blks['gates']['Gx']))\n", "t0 = time.time()\n", "out = mdl.probs(c)\n", "print(\"%d probabilities computed in %.3fs\" % (len(out), time.time()-t0))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also propagate a density matrix using the **matrix-vector multiplying** forward simulator (`\"map\"`). This forward simulator is much faster for even several (5) qubits. This is why pyGSTi automatically selects the `\"map\"` simulator when the number of qubits is $\\ge 2$." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "32 probabilities computed in 0.010s\n" ] } ], "source": [ "mdl = pygsti.construction.build_standard_localnoise_model(\n", " nQubits, ['Gx','Gy','Gcnot'], sim_type=\"map\")\n", "t0 = time.time()\n", "out2 = mdl.probs(c)\n", "print(\"%d probabilities computed in %.3fs\" % (len(out2), time.time()-t0))\n", "assert(all([np.isclose(out[k],out2[k]) for k in out])) # check that the probabilites are the same" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we don't need to consider mixed states, we can represent the quantum state using a **state vector** (`\"statevec\"`, selected by the `\"static unitary\"` parameterization type) and use either the matrix-matrix or matrix-vector product simulation types (the latter is again considerably faster even for just 5 qubits):" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Mat-mat: 32 probabilities in 0.095s\n", "Mat-vec: 32 probabilities in 0.010s\n" ] } ], "source": [ "mdl = pygsti.construction.build_standard_localnoise_model(\n", " nQubits, ['Gx','Gy','Gcnot'], parameterization=\"static unitary\", sim_type=\"matrix\")\n", "t0 = time.time()\n", "out3 = mdl.probs(c)\n", "print(\"Mat-mat: %d probabilities in %.3fs\" % (len(out3), time.time()-t0))\n", "assert(all([np.isclose(out[k],out3[k]) for k in out])) # check that the probabilites are the same\n", "\n", "mdl = pygsti.construction.build_standard_localnoise_model(\n", " nQubits, ['Gx','Gy','Gcnot'], parameterization=\"static unitary\", sim_type=\"map\")\n", "t0 = time.time()\n", "out4 = mdl.probs(c)\n", "print(\"Mat-vec: %d probabilities in %.3fs\" % (len(out4), time.time()-t0))\n", "assert(all([np.isclose(out[k],out4[k]) for k in out])) # check that the probabilites are the same" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, if all the gates are **Clifford** operations (as they are in this case), we can use the `\"clifford\"` parameterization to propagate a `\"stabilizer\"` state. Only the `\"map\"` simulation type is compatible with the `\"stabilizer\"` evolution type (selected automatically)." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Gx gate is a \n", "32 probabilities in 0.015s\n" ] } ], "source": [ "mdl = pygsti.construction.build_standard_localnoise_model(\n", " nQubits, ['Gx','Gy','Gcnot'], parameterization=\"clifford\")\n", "print(\"Gx gate is a \",type(mdl.operation_blks['gates']['Gx']))\n", "t0 = time.time()\n", "out5 = mdl.probs(c)\n", "print(\"%d probabilities in %.3fs\" % (len(out5), time.time()-t0))\n", "assert(all([np.isclose(out[k],out5[k]) for k in out])) # check that the probabilites are the same" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 10 qubits\n", "Let's create a function to compare the above methods for a given number of qubits. We'll automatically exclude the `\"densitymx\"`-`\"matrix\"` case when the number of qubits is greater than 5 as we know this is getting slow at this point. At 10 qubits, the stabilizer and state-vector simulations are of comparable runtime (though this is largely due to the fact that *all* the outcomes are always computed - see below)." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "---- Comparing times for 10 qubits (1024 outcomes) ----\n", "Create processor spec: 2.494s\n", "Random Circuit:\n", "Qubit 0 ---|Gx|-|C1|-|Gy|-|Gx|-|C1|-|C1|-|Gx|-|C1|-|Gy|-|C1|-|C1|-|Gx|-|Gx|-|Gx|-|Gx|-|C1|-|Gy|-|Gx|-|Gy|-|Gx|---\n", "Qubit 1 ---|Gy|-|T0|-|C2|-|Gy|-|T0|-|T0|-|C2|-|T0|-|Gx|-|T0|-|T0|-|Gy|-|C2|-|C2|-|Gy|-|T0|-|Gy|-|C2|-|Gx|-|Gx|---\n", "Qubit 2 ---|Gx|-|Gx|-|T1|-|C3|-|Gx|-|Gx|-|T1|-|Gy|-|Gx|-|Gx|-|Gx|-|C3|-|T1|-|T1|-|Gy|-|C3|-|Gy|-|T1|-|C3|-|C3|---\n", "Qubit 3 ---|C4|-|Gx|-|Gy|-|T2|-|Gy|-|C4|-|C4|-|C4|-|C4|-|C4|-|Gx|-|T2|-|Gy|-|Gx|-|C4|-|T2|-|Gy|-|C4|-|T2|-|T2|---\n", "Qubit 4 ---|T3|-|Gx|-|Gx|-|Gy|-|Gx|-|T3|-|T3|-|T3|-|T3|-|T3|-|Gx|-|Gx|-|C5|-|C5|-|T3|-|C5|-|Gx|-|T3|-|Gy|-|Gy|---\n", "Qubit 5 ---|C6|-|C6|-|Gx|-|Gy|-|C6|-|Gx|-|Gy|-|C6|-|Gy|-|C6|-|Gx|-|Gx|-|T4|-|T4|-|C6|-|T4|-|Gy|-|C6|-|Gx|-|Gx|---\n", "Qubit 6 ---|T5|-|T5|-|Gy|-|Gy|-|T5|-|Gy|-|C7|-|T5|-|Gy|-|T5|-|Gx|-|C7|-|Gx|-|Gy|-|T5|-|C7|-|Gx|-|T5|-|Gy|-|Gx|---\n", "Qubit 7 ---|Gy|-|C8|-|C8|-|C8|-|Gx|-|Gy|-|T6|-|C8|-|Gy|-|C8|-|C8|-|T6|-|Gy|-|C8|-|Gy|-|T6|-|Gy|-|Gy|-|C8|-|C8|---\n", "Qubit 8 ---|C9|-|T7|-|T7|-|T7|-|C9|-|Gy|-|Gy|-|T7|-|Gy|-|T7|-|T7|-|C9|-|C9|-|T7|-|C9|-|C9|-|Gx|-|Gx|-|T7|-|T7|---\n", "Qubit 9 ---|T8|-|Gx|-|Gy|-|Gy|-|T8|-|Gx|-|Gx|-|Gx|-|Gx|-|Gy|-|Gx|-|T8|-|T8|-|Gx|-|T8|-|T8|-|Gy|-|Gy|-|Gx|-|Gy|---\n", "\n", "densitymx, map: 1.957s\n", "statevec, map: 0.053s\n", "stabilizer, map: 0.094s\n" ] } ], "source": [ "import pygsti, time\n", "\n", "def compare_calc_methods(nQubits):\n", " print(\"---- Comparing times for %d qubits (%d outcomes) ----\" % (nQubits,2**nQubits))\n", " t0=time.time()\n", " ps = pygsti.obj.ProcessorSpec(nQubits=nQubits, gate_names=['Gx','Gy','Gcnot'],\n", " availability={'Gcnot': [(i,i+1) for i in range(nQubits-1)]})\n", " print(\"Create processor spec: %.3fs\" % (time.time()-t0))\n", "\n", " from pygsti.extras import rb\n", " c = rb.sample.random_circuit(ps, 20)\n", " print(\"Random Circuit:\")\n", " print(c)\n", "\n", " if nQubits <= 5:\n", " mdl = pygsti.construction.build_standard_localnoise_model(\n", " nQubits, ['Gx','Gy','Gcnot'], sim_type=\"matrix\")\n", " t0 = time.time()\n", " mdl.probs(c)\n", " print(\"densitymx, matrix: %.3fs\" % (time.time()-t0))\n", "\n", " mdl = pygsti.construction.build_standard_localnoise_model(\n", " nQubits, ['Gx','Gy','Gcnot'], parameterization=\"static unitary\", sim_type=\"matrix\")\n", " t0 = time.time()\n", " mdl.probs(c)\n", " print(\"statevec, matrix: %.3fs\" % (time.time()-t0))\n", "\n", " if nQubits <= 12:\n", " mdl = pygsti.construction.build_standard_localnoise_model(\n", " nQubits, ['Gx','Gy','Gcnot'], sim_type=\"map\")\n", " t0 = time.time()\n", " mdl.probs(c)\n", " print(\"densitymx, map: %.3fs\" % (time.time()-t0))\n", "\n", " mdl = pygsti.construction.build_standard_localnoise_model(\n", " nQubits, ['Gx','Gy','Gcnot'], parameterization=\"static unitary\", sim_type=\"map\")\n", " t0 = time.time()\n", " mdl.probs(c)\n", " print(\"statevec, map: %.3fs\" % (time.time()-t0))\n", " \n", " mdl = pygsti.construction.build_standard_localnoise_model(\n", " nQubits, ['Gx','Gy','Gcnot'], parameterization=\"clifford\")\n", " t0 = time.time()\n", " out5 = mdl.probs(c)\n", " print(\"stabilizer, map: %.3fs\" % (time.time()-t0))\n", " \n", "compare_calc_methods(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## More qubits\n", "Going beyond 10 qubits, run times will start to get long even for the stabilizer-simulation case. This is because pyGSTi currently *always* computes *all* the outcomes of a circuit, the number of which scales exponentially with the system size (as $2^n$ for $n$ qubits). Future versions will remedy this technical issue, allowing you to compute *just* the outcome probabilites you want. Once this update is released, the stabilizer state simulation will clearly be faster than either the density-matrix or state-vector approaches; for now, we can see that it get's marginally faster as the number of qubits rises (note: this cell takes several minutes to run!):" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "---- Comparing times for 12 qubits (4096 outcomes) ----\n", "Create processor spec: 3.949s\n", "Random Circuit:\n", "Qubit 0 ---|Gy |-|Gy|-|C1|-|C1|-|Gx |-|Gx |-|C1|-|C1 |-|Gy |-|Gy |-|C1 |-|Gx |-|C1 |-|Gy|-|Gy |-|C1 |-|Gy |-|Gx |-|Gy|-|Gy |---\n", "Qubit 1 ---|Gx |-|C2|-|T0|-|T0|-|Gy |-|C2 |-|T0|-|T0 |-|Gy |-|C2 |-|T0 |-|Gx |-|T0 |-|C2|-|Gx |-|T0 |-|Gy |-|Gy |-|Gy|-|C2 |---\n", "Qubit 2 ---|Gx |-|T1|-|Gy|-|Gy|-|Gy |-|T1 |-|Gy|-|Gy |-|C3 |-|T1 |-|C3 |-|Gy |-|Gy |-|T1|-|C3 |-|Gx |-|Gx |-|C3 |-|Gy|-|T1 |---\n", "Qubit 3 ---|C4 |-|Gy|-|C4|-|C4|-|Gx |-|Gy |-|Gx|-|Gx |-|T2 |-|C4 |-|T2 |-|Gx |-|Gy |-|Gx|-|T2 |-|C4 |-|C4 |-|T2 |-|C4|-|C4 |---\n", "Qubit 4 ---|T3 |-|C5|-|T3|-|T3|-|Gx |-|Gx |-|C5|-|Gx |-|C5 |-|T3 |-|C5 |-|Gx |-|Gy |-|Gx|-|C5 |-|T3 |-|T3 |-|C5 |-|T3|-|T3 |---\n", "Qubit 5 ---|C6 |-|T4|-|Gx|-|C6|-|Gy |-|C6 |-|T4|-|Gy |-|T4 |-|C6 |-|T4 |-|Gx |-|C6 |-|C6|-|T4 |-|Gx |-|C6 |-|T4 |-|C6|-|Gy |---\n", "Qubit 6 ---|T5 |-|Gy|-|C7|-|T5|-|C7 |-|T5 |-|Gx|-|C7 |-|C7 |-|T5 |-|C7 |-|Gx |-|T5 |-|T5|-|Gx |-|Gy |-|T5 |-|Gx |-|T5|-|Gx |---\n", "Qubit 7 ---|Gy |-|Gy|-|T6|-|C8|-|T6 |-|C8 |-|Gy|-|T6 |-|T6 |-|Gy |-|T6 |-|C8 |-|Gy |-|Gx|-|Gy |-|Gy |-|C8 |-|C8 |-|C8|-|C8 |---\n", "Qubit 8 ---|Gx |-|Gy|-|C9|-|T7|-|Gx |-|T7 |-|Gy|-|Gx |-|Gx |-|Gx |-|C9 |-|T7 |-|C9 |-|Gx|-|C9 |-|Gx |-|T7 |-|T7 |-|T7|-|T7 |---\n", "Qubit 9 ---|Gy |-|Gx|-|T8|-|Gy|-|C10|-|Gy |-|Gx|-|Gx |-|Gx |-|C10|-|T8 |-|Gy |-|T8 |-|Gy|-|T8 |-|C10|-|C10|-|C10|-|Gx|-|Gx |---\n", "Qubit 10 ---|C11|-|Gy|-|Gy|-|Gy|-|T9 |-|C11|-|Gx|-|C11|-|C11|-|T9 |-|C11|-|C11|-|C11|-|Gy|-|C11|-|T9 |-|T9 |-|T9 |-|Gx|-|C11|---\n", "Qubit 11 ---|T10|-|Gx|-|Gx|-|Gy|-|Gx |-|T10|-|Gy|-|T10|-|T10|-|Gy |-|T10|-|T10|-|T10|-|Gy|-|T10|-|Gy |-|Gx |-|Gx |-|Gx|-|T10|---\n", "\n", "densitymx, map: 41.990s\n", "statevec, map: 0.188s\n", "stabilizer, map: 0.225s\n" ] } ], "source": [ "compare_calc_methods(12)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "---- Comparing times for 16 qubits (65536 outcomes) ----\n", "Create processor spec: 11.575s\n", "Random Circuit:\n", "Qubit 0 ---|Gy |-|C1 |-|Gy |-|Gy |-|C1|-|C1 |-|Gx |-|Gy |-|C1 |-|C1 |-|C1 |-|Gy |-|C1 |-|C1 |-|Gy |-|Gx |-|Gy |-|C1 |-|C1 |-|C1 |---\n", "Qubit 1 ---|Gx |-|T0 |-|C2 |-|Gy |-|T0|-|T0 |-|C2 |-|C2 |-|T0 |-|T0 |-|T0 |-|Gy |-|T0 |-|T0 |-|Gx |-|C2 |-|Gy |-|T0 |-|T0 |-|T0 |---\n", "Qubit 2 ---|C3 |-|Gy |-|T1 |-|C3 |-|Gx|-|C3 |-|T1 |-|T1 |-|C3 |-|Gy |-|Gy |-|C3 |-|C3 |-|C3 |-|C3 |-|T1 |-|Gx |-|C3 |-|Gy |-|Gy |---\n", "Qubit 3 ---|T2 |-|Gx |-|Gx |-|T2 |-|Gy|-|T2 |-|Gy |-|C4 |-|T2 |-|C4 |-|C4 |-|T2 |-|T2 |-|T2 |-|T2 |-|C4 |-|Gx |-|T2 |-|Gy |-|C4 |---\n", "Qubit 4 ---|C5 |-|C5 |-|C5 |-|Gy |-|C5|-|C5 |-|C5 |-|T3 |-|C5 |-|T3 |-|T3 |-|Gx |-|Gy |-|Gx |-|C5 |-|T3 |-|Gy |-|C5 |-|Gx |-|T3 |---\n", "Qubit 5 ---|T4 |-|T4 |-|T4 |-|C6 |-|T4|-|T4 |-|T4 |-|Gy |-|T4 |-|C6 |-|C6 |-|Gy |-|Gy |-|Gy |-|T4 |-|C6 |-|Gy |-|T4 |-|Gy |-|Gy |---\n", "Qubit 6 ---|Gx |-|C7 |-|C7 |-|T5 |-|Gx|-|C7 |-|Gy |-|Gy |-|Gx |-|T5 |-|T5 |-|C7 |-|Gy |-|Gx |-|Gy |-|T5 |-|C7 |-|C7 |-|Gx |-|Gx |---\n", "Qubit 7 ---|Gy |-|T6 |-|T6 |-|Gy |-|C8|-|T6 |-|Gy |-|C8 |-|C8 |-|Gx |-|Gx |-|T6 |-|C8 |-|Gx |-|C8 |-|C8 |-|T6 |-|T6 |-|C8 |-|C8 |---\n", "Qubit 8 ---|Gx |-|C9 |-|Gy |-|C9 |-|T7|-|C9 |-|C9 |-|T7 |-|T7 |-|Gy |-|Gy |-|Gy |-|T7 |-|C9 |-|T7 |-|T7 |-|C9 |-|Gy |-|T7 |-|T7 |---\n", "Qubit 9 ---|Gy |-|T8 |-|C10|-|T8 |-|Gy|-|T8 |-|T8 |-|Gx |-|Gy |-|Gy |-|Gx |-|Gy |-|C10|-|T8 |-|C10|-|C10|-|T8 |-|Gy |-|Gy |-|C10|---\n", "Qubit 10 ---|Gx |-|Gy |-|T9 |-|Gx |-|Gy|-|C11|-|C11|-|C11|-|Gx |-|Gx |-|C11|-|Gx |-|T9 |-|Gy |-|T9 |-|T9 |-|Gy |-|Gy |-|Gx |-|T9 |---\n", "Qubit 11 ---|Gy |-|Gx |-|Gy |-|Gy |-|Gy|-|T10|-|T10|-|T10|-|C12|-|Gy |-|T10|-|Gy |-|C12|-|C12|-|Gx |-|Gx |-|C12|-|C12|-|Gy |-|C12|---\n", "Qubit 12 ---|Gx |-|Gy |-|C13|-|Gy |-|Gx|-|C13|-|Gy |-|C13|-|T11|-|C13|-|Gy |-|Gx |-|T11|-|T11|-|Gx |-|C13|-|T11|-|T11|-|C13|-|T11|---\n", "Qubit 13 ---|Gx |-|Gy |-|T12|-|Gx |-|Gy|-|T12|-|C14|-|T12|-|Gx |-|T12|-|Gx |-|Gy |-|Gy |-|Gx |-|Gx |-|T12|-|Gy |-|Gx |-|T12|-|Gy |---\n", "Qubit 14 ---|C15|-|C15|-|Gy |-|C15|-|Gx|-|Gy |-|T13|-|Gx |-|C15|-|Gx |-|C15|-|C15|-|Gx |-|Gx |-|Gy |-|C15|-|Gx |-|Gx |-|Gx |-|C15|---\n", "Qubit 15 ---|T14|-|T14|-|Gx |-|T14|-|Gy|-|Gy |-|Gy |-|Gy |-|T14|-|Gy |-|T14|-|T14|-|Gy |-|Gx |-|Gy |-|T14|-|Gx |-|Gy |-|Gx |-|T14|---\n", "\n", "statevec, map: 3.776s\n", "stabilizer, map: 3.407s\n" ] } ], "source": [ "compare_calc_methods(16)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "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.0" } }, "nbformat": 4, "nbformat_minor": 2 }