{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 2-qubit GST with a custom 2-qubit gate\n",
"While pyGSTi is able to support several common types of 2-qubit gates, the space of all possible 2-qubit gates is so large that some users will need to construct their own particular 2-qubit gate \"from scratch\". In this tutorial, we look at how to construct a 2-qubit gateset with a \"non-standard\" 2-qubit gate.\n",
"\n",
"The previous tutorial gave an overview of the steps to run GST on a \"standard\" 2-qubit system. In that case, the gate set, fiducials, germs, etc., are already contained in pyGSTi within a `pygsti.construction.stdXXX` module. The previous tutorial also showed how to use `build_gateset` to construct a gate set single-qubit rotations and a CNOT gate. The only difference when working with a \"non-standard\" gate set is in the creation of the \"target gate set\" object. Thus, **in this tutorial we focus only on creating a custom 2-qubit gate** - the rest of the procedure for doing 2-qubit GST is identical to that in the previous tutorial."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import pygsti"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Create a gateset with only single-qubit gates\n",
"Since the space of single-qubit gates is relatively small, let's assume that the single-qubit gates in our gateset are able to be specified using the `build_gateset`. Then we can construct a `GateSet` object containing all but the two-qubit gate(s) using `build_gateset` just as in other tutorials.\n",
"\n",
"If our 2-qubit gate happened to be one that *could* be specified using `build_gateset` then we would just use it to construct the entire `GateSet` and we would be done. Currently, `build_gateset` can create any controlled $X$, $Y$, or $Z$ rotation using `CX`, `CY` and `CZ` (for details, see how `CX` was used to construct a CNOT gate in the previous tutorial)."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# Notes on build_gateset arguments:\n",
"# [4] = a 4-dimensional Hilbert (state) space\n",
"# [('Q0','Q1')] = interpret this 4-d space as that of two qubits 'Q0', and 'Q1' (note these labels *must* begin with 'Q'!)\n",
"# \"Gix\" = gate label; can be anything that begins with 'G' and is followed by lowercase letters\n",
"# \"X(pi/2,Q1)\" = pi/2 single-qubit x-rotation gate on the qubit labeled Q1\n",
"# \"rho0\" = prep label; can be anything that begins with \"rho\"\n",
"# \"E1\" = effect label; can be anything that begins with \"E\"\n",
"# \"2\" = a prep or effect expression indicating a projection/preparation of the 3rd (b/c 0-based) computational basis element\n",
"# 'dnup': ('rho0','E2') = designate the SPAM label \"dnup\" to mean preparation using \"rho0\" (a prep label) and measuring the outcome \"E2\" (an effect label)\n",
"# \"pp\" = create all of these gate & SPAM operators in the Pauli-product basis.\n",
"gs_target = pygsti.construction.build_gateset( \n",
" [4], [('Q0','Q1')],['Gix','Gix','Gxi','Gyi'], \n",
" [ \"X(pi/2,Q1)\", \"Y(pi/2,Q1)\", \"X(pi/2,Q0)\", \"Y(pi/2,Q0)\"],\n",
" prepLabels=['rho0'], prepExpressions=[\"0\"],\n",
" effectLabels=['E0','E1','E2'], effectExpressions=[\"0\",\"1\",\"2\"], \n",
" spamdefs={'upup': ('rho0','E0'), 'updn': ('rho0','E1'),\n",
" 'dnup': ('rho0','E2'), 'dndn': ('rho0','remainder') }, basis=\"pp\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Create a 2-qubit gate\n",
"This is how you create a 2-qubit gate from a given unitary which acts on the state space."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import numpy as np\n",
"\n",
"#Unitary in acting on the state-space { |A>, |B>, |C>, |D> } == { |00>, |01>, |10>, |11> }.\n",
"# This unitary rotates the second qubit by pi/2 in either the (+) or (-) direction based on \n",
"# the state of the first qubit.\n",
"myUnitary = 1./np.sqrt(2) * np.array([[1,-1j,0,0],\n",
" [-1j,1,0,0],\n",
" [0,0,1,1j],\n",
" [0,0,1j,1]])\n",
"\n",
"#Convert this unitary into a \"superoperator\", which acts on the \n",
"# space of vectorized density matrices instead of just the state space.\n",
"# These superoperators are what GST calls \"gates\". \n",
"mySuperOp_stdbasis = pygsti.unitary_to_process_mx(myUnitary)\n",
"\n",
"#After the call to unitary_to_process_mx, the superoperator is a complex matrix\n",
"# in the \"standard\" or \"matrix unit\" basis given by { |A>