def setUp(self): #Set Model objects to "strict" mode for testing ExplicitOpModel._strict = True # density matrix == 3x3 block diagonal matrix: a 2x2 block followed by a 1x1 block self.stateSpaceDims = [(4, ), (1, )] self.stateSpaceUDims = [(2, ), (1, )] self.std = Basis.cast('std', 9) self.gm = Basis.cast('gm', 9) self.stdSmall = Basis.cast('std', [4, 1]) self.gmSmall = Basis.cast('gm', [4, 1]) #labels which give a tensor product interp. for the states within each density matrix block self.stateSpaceLabels = [('Qhappy', ), ('Lsad', )] # Adjust for deprecation of _create_operation self.sslbls = statespace.ExplicitStateSpace(self.stateSpaceLabels, self.stateSpaceUDims) #Build a test gate -- old # X(pi,Qhappy)*LX(pi,0,2) self.testGate = create_operation("LX(pi,0,2)", self.sslbls, self.stdSmall) self.testGateGM_mx = bt.change_basis(self.testGate, self.stdSmall, self.gmSmall) self.expTestGate_mx = bt.flexible_change_basis(self.testGate, self.stdSmall, self.std) self.expTestGateGM_mx = bt.change_basis(self.expTestGate_mx, self.std, self.gm)
def test_errgen_construction(self): from pygsti.models.gaugegroup import UnitaryGaugeGroupElement mx_basis = Basis.cast('pp', 4) basis = Basis.cast('pp', 4) X = basis['X'] Y = basis['Y'] Z = basis['Z'] # Build known combination to project back to errgen = (0.1 * lt.create_elementary_errorgen('H', Z) - 0.01 * lt.create_elementary_errorgen('H', X) + 0.2 * lt.create_elementary_errorgen('S', X) + 0.25 * lt.create_elementary_errorgen('S', Y) + 0.05 * lt.create_elementary_errorgen('C', X, Y) - 0.01 * lt.create_elementary_errorgen('A', X, Y)) errgen = bt.change_basis(errgen, 'std', mx_basis) eg = op.LindbladErrorgen.from_error_generator(errgen, "CPTP", 'pp', truncate=False, mx_basis="pp", evotype='default') self.assertTrue(np.allclose(eg.to_dense(), errgen)) errgen_copy = eg.copy() T = UnitaryGaugeGroupElement(np.identity(4, 'd')) errgen_copy.transform_inplace(T) self.assertTrue(np.allclose(errgen_copy.to_dense(), eg.to_dense()))
def setUp(self): self.gm = Basis.cast('gm', 4) self.pp = Basis.cast('pp', 4) self.std = Basis.cast('std', 4) self.mxGM = np.array( [[1, 0, 0, 0], [0, 0, 1, 0], [0, -1, 0, 0], [0, 0, 0, 1]], 'complex') self.mxStd = bt.change_basis(self.mxGM, self.gm, self.std) self.mxPP = bt.change_basis(self.mxGM, self.gm, self.pp)
def test_build_gatesets(self): SQ2 = 1 / np.sqrt(2) for defParamType in ("full", "full TP", "static"): gateset_simple = pygsti.models.ExplicitOpModel(['Q0'], 'pp', defParamType) gateset_simple['rho0'] = [SQ2, 0, 0, SQ2] gateset_simple[ 'Mdefault'] = pygsti.modelmembers.povms.UnconstrainedPOVM( [('0', [SQ2, 0, 0, -SQ2])], evotype='default') gateset_simple['Gi'] = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]] with self.assertRaises(TypeError): gateset_simple['rho0'] = 3.0 with self.assertRaises(ValueError): gateset_simple['rho0'] = [3.0] with self.assertRaises(ValueError): gateset_simple['Gx'] = [1, 2, 3, 4] with self.assertRaises(ValueError): gateset_simple['Gx'] = [[1, 2, 3, 4], [5, 6, 7]] gateset_badDefParam = pygsti.models.ExplicitOpModel(['Q0'], "pp", "full") gateset_badDefParam.preps.default_param = "foobar" gateset_badDefParam.operations.default_param = "foobar" with self.assertRaises(ValueError): gateset_badDefParam['rho0'] = [1, 0, 0, 0] with self.assertRaises(ValueError): gateset_badDefParam['Gi'] = np.identity(4, 'd') stateSpace = [(4, )] # density matrix is a 2x2 matrix spaceLabels = [ ('Q0', ) ] # interpret the 2x2 density matrix as a single qubit named 'Q0' with self.assertRaises(AssertionError): modelconstruction.create_identity_vec( Basis.cast("foobar", stateSpace)) gateset_povm_first = pygsti.models.ExplicitOpModel( ['Q0']) #set effect vector first gateset_povm_first['Mdefault'] = pygsti.modelmembers.povms.TPPOVM( [('0', modelconstruction.create_spam_vector("0", stateSpace, "gm")), ('1', modelconstruction.create_spam_vector("1", stateSpace, "gm")) ], evotype='default') with self.assertRaises(ValueError): gateset_povm_first['rhoBad'] = np.array([1, 2, 3], 'd') #wrong dimension with self.assertRaises(ValueError): gateset_povm_first[ 'Mdefault'] = pygsti.modelmembers.povms.UnconstrainedPOVM( [('0', np.array([1, 2, 3], 'd'))], evotype='default', state_space=pygsti.baseobjs.StateSpace.cast([ ('L0', ), ('L1', ), ('L2', ) ])) #wrong dimension
def __init__(self, errormap, povm=None, mx_basis=None): """ Creates a new LindbladPOVM object. Parameters ---------- errormap : MapOperator The error generator action and parameterization, encapsulated in a gate object. Usually a :class:`LindbladOp` or :class:`ComposedOp` object. (This argument is *not* copied, to allow ComposedPOVMEffects to share error generator parameters with other gates and spam vectors.) povm : POVM, optional A sub-POVM which supplies the set of "reference" effect vectors that `errormap` acts on to produce the final effect vectors of this LindbladPOVM. This POVM must be *static* (have zero parameters) and its evolution type must match that of `errormap`. If None, then a :class:`ComputationalBasisPOVM` is used on the number of qubits appropriate to `errormap`'s dimension. mx_basis : {'std', 'gm', 'pp', 'qt'} or Basis object The basis for this spam vector. Allowed values are Matrix-unit (std), Gell-Mann (gm), Pauli-product (pp), and Qutrit (qt) (or a custom basis object). If None, then this is extracted (if possible) from `errormap`. """ self.error_map = errormap state_space = self.error_map.state_space if mx_basis is None: if isinstance(errormap, _op.ExpErrorgenOp) and isinstance( errormap.errorgen, _op.LindbladErrorgen): mx_basis = errormap.errorgen.matrix_basis else: raise ValueError( "Cannot extract a matrix-basis from `errormap` (type %s)" % str(type(errormap))) self.matrix_basis = _Basis.cast(mx_basis, state_space) evotype = self.error_map._evotype if povm is None: assert(state_space.num_qubits >= 0), \ ("A default computational-basis POVM can only be used with an" " integral number of qubits!") povm = _ComputationalBasisPOVM(state_space.num_qubits, evotype) else: assert(povm.evotype == evotype), \ ("Evolution type of `povm` (%s) must match that of " "`errormap` (%s)!") % (povm.evotype, evotype) assert(povm.num_params == 0), \ "Given `povm` must be static (have 0 parameters)!" self.base_povm = povm items = [] # init as empty (lazy creation of members) _POVM.__init__(self, state_space, evotype, items) self.init_gpindices( ) # initialize gpindices and subm_rpindices from sub-members
def test_elementary_errorgen_bases(self): bases = [Basis.cast('gm', 4), Basis.cast('pp', 4), Basis.cast('PP', 4)] for basis in bases: print(basis) primals = [] duals = [] lbls = [] for lbl, bel in zip(basis.labels[1:], basis.elements[1:]): lbls.append("H_%s" % lbl) primals.append(lt.create_elementary_errorgen('H', bel)) duals.append(lt.create_elementary_errorgen_dual('H', bel)) for lbl, bel in zip(basis.labels[1:], basis.elements[1:]): lbls.append("S_%s" % lbl) primals.append(lt.create_elementary_errorgen('S', bel)) duals.append(lt.create_elementary_errorgen_dual('S', bel)) for i, (lbl, bel) in enumerate(zip(basis.labels[1:], basis.elements[1:])): for lbl2, bel2 in zip(basis.labels[1 + i + 1:], basis.elements[1 + i + 1:]): lbls.append("C_%s_%s" % (lbl, lbl2)) primals.append( lt.create_elementary_errorgen('C', bel, bel2)) duals.append( lt.create_elementary_errorgen_dual('C', bel, bel2)) for i, (lbl, bel) in enumerate(zip(basis.labels[1:], basis.elements[1:])): for lbl2, bel2 in zip(basis.labels[1 + i + 1:], basis.elements[1 + i + 1:]): lbls.append("A_%s_%s" % (lbl, lbl2)) primals.append( lt.create_elementary_errorgen('A', bel, bel2)) duals.append( lt.create_elementary_errorgen_dual('A', bel, bel2)) dot_mx = np.empty((len(duals), len(primals)), complex) for i, dual in enumerate(duals): for j, primal in enumerate(primals): dot_mx[i, j] = np.vdot(dual.flatten(), primal.flatten()) self.assertTrue(np.allclose(dot_mx, np.identity(len(lbls), 'd')))
def build_gate(): mx = np.identity(4, 'd') ppBasis = Basis.cast("pp", 4) return op.LindbladErrorgen.from_operation_matrix(mx, "GLND", ppBasis, truncate=False, mx_basis="pp", evotype='default')
def test_instance(self): state_space = statespace.default_space_for_dim(4) sop = op.StochasticNoiseOp(state_space) sop.from_vector(np.array([0.1, 0.0, 0.0])) self.assertArraysAlmostEqual(sop.to_vector(), np.array([0.1, 0., 0.])) expected_mx = np.identity(4) expected_mx[2, 2] = expected_mx[3, 3] = 0.98 # = 2*(0.1^2) self.assertArraysAlmostEqual(sop.to_dense(), expected_mx) rho = create_spam_vector("0", "Q0", Basis.cast("pp", [4])) self.assertAlmostEqual( float(np.dot(rho.T, np.dot(sop.to_dense(), rho))), 0.99) # b/c X dephasing w/rate is 0.1^2 = 0.01
def __init__(self, state_space, labels, basis1q=None): # TODO: docstring - labels must be of form (sslbls, elementary_errorgen_lbl) self._labels = tuple(labels) if not isinstance(labels, tuple) else labels self._label_indices = _collections.OrderedDict([ (lbl, i) for i, lbl in enumerate(self._labels) ]) self.basis_1q = basis1q if (basis1q is not None) else _Basis.cast( 'pp', 4) self.state_space = state_space assert (self.state_space.is_entirely_qubits ), "FOGI only works for models containing just qubits (so far)" sslbls = self.state_space.tensor_product_block_labels( 0) # all the model's state space labels self.sslbls = sslbls # the "support" of this space - the qubit labels self._cached_elements = None
def __init__(self, vec, basis="pp", evotype="default", state_space=None): vector = _State._to_vector(vec) if basis is not None: if not isinstance(basis, _Basis): basis = _Basis.cast(basis, len( vector)) # don't perform this cast if we're given a basis firstEl = basis.elsize**-0.25 # not dim, as the dimension of the vector space may be less if not _np.isclose(vector[0], firstEl): raise ValueError( "Cannot create TPState: first element must equal %g!" % firstEl) # if basis is None, don't check first element (hackfor de-serialization, so we don't need to store basis) _DenseState.__init__(self, vector, evotype, state_space) assert (isinstance(self.columnvec, _ProtectedArray)) self._paramlbls = _np.array( ["VecElement %d" % i for i in range(1, self.dim)], dtype=object)
def test_depol_noise_op(self): state_space = statespace.default_space_for_dim(4) dop = op.DepolarizeOp(state_space) dop.from_vector(np.array([0.1])) self.assertArraysAlmostEqual(dop.to_vector(), np.array([0.1])) expected_mx = np.identity(4) expected_mx[1, 1] = expected_mx[2, 2] = expected_mx[3, 3] = 0.96 # = 4*(0.1^2) self.assertArraysAlmostEqual(dop.to_dense(), expected_mx) rho = create_spam_vector("0", "Q0", Basis.cast("pp", [4])) # b/c both X and Y dephasing rates => 0.01 reduction self.assertAlmostEqual( float(np.dot(rho.T, np.dot(dop.to_dense(), rho))), 0.98)
def test_gm_basis(self): #mx_dim = sum([ int(np.sqrt(d)) for d in self.stateSpaceDims]) cmb = Basis.cast('gm', self.stateSpaceDims) self.checkBasis(cmb)
def create_qutrit_model(error_scale, x_angle=_np.pi / 2, y_angle=_np.pi / 2, ms_global=_np.pi / 2, ms_local=0, similarity=False, seed=None, basis='qt', evotype='default'): """ Constructs a standard qutrit :class:`Model`. This model contains the identity, XX, YY, and Molmer-Sorenson gates. Parameters ---------- error_scale : float Magnitude of random rotations to apply to the returned model. If zero, then perfect "ideal" gates are constructed. x_angle : float, optional The rotation angle of each X in the XX gate. y_angle : float, optional The rotation angle of each Y in the YY gate. ms_global : float, optional The global Molmer-Sorenson angle (theta) ms_local : float, optional The local Molmer-Sorenson angle (theta) similarity : bool, optional If true, then apply the random rotations (whose strengths are given by `error_scale`) as similarity transformations rather than just as post-multiplications to the ideal operation matrices. seed : int, optional The seed used to generate random rotations. basis : str, optional The string abbreviation of the basis of the returned vector. Allowed values are Matrix-unit (std), Gell-Mann (gm) and Qutrit (qt). A `Basis` object may also be used. evotype : Evotype or str, optional The evolution type. The special value `"default"` is equivalent to specifying the value of `pygsti.evotypes.Evotype.default_evotype`. Returns ------- Model """ arrType = _np.array # Are we casting gates as matrices or arrays? rho0 = arrType(([[1, 0, 0], [0, 0, 0], [0, 0, 0]])) identity3 = arrType(_np.identity(3)) E0 = arrType(_np.diag([1, 0, 0])) E1 = arrType(_np.diag([0, 1, 0])) E2 = arrType(_np.diag([0, 0, 1])) #Define gates as unitary ops on Hilbert space gateImx = arrType(identity3) gateXmx = arrType(_xx_qutrit(x_angle)) gateYmx = arrType(_yy_qutrit(y_angle)) gateMmx = arrType(_ms_qutrit(ms_global, ms_local)) #Now introduce unitary noise. scale = error_scale rndm = _np.random.RandomState(seed) Xrand = _random_rot(scale, rndm) Yrand = _random_rot(scale, rndm) Mrand = _random_rot(scale, rndm) Irand = _random_rot(scale, rndm) if similarity: # Change basis for each gate; this preserves rotation angles, and should map identity to identity gateXmx = _np.dot(_np.dot(_np.conj(Xrand).T, gateXmx), Xrand) gateYmx = _np.dot(_np.dot(_np.conj(Yrand).T, gateYmx), Yrand) gateMmx = _np.dot(_np.dot(_np.conj(Mrand).T, gateMmx), Mrand) gateImx = _np.dot(_np.dot(_np.conj(Irand).T, gateImx), Irand) else: gateXmx = _np.dot(gateXmx, Xrand) gateYmx = _np.dot(gateYmx, Yrand) gateMmx = _np.dot(gateMmx, Mrand) gateImx = _np.dot(gateImx, Irand) #Change gate representation to superoperator in Gell-Mann basis gateISOfinal = unitary_to_superop(gateImx, basis) gateXSOfinal = unitary_to_superop(gateXmx, basis) gateYSOfinal = unitary_to_superop(gateYmx, basis) gateMSOfinal = unitary_to_superop(gateMmx, basis) rho0final = change_basis(_np.reshape(rho0, (9, 1)), "std", basis) E0final = change_basis(_np.reshape(E0, (9, 1)), "std", basis) E1final = change_basis(_np.reshape(E1, (9, 1)), "std", basis) E2final = change_basis(_np.reshape(E2, (9, 1)), "std", basis) state_space = _statespace.ExplicitStateSpace(['QT'], [3]) qutritMDL = _ExplicitOpModel(state_space, _Basis.cast(basis, 9), evotype=evotype) qutritMDL.preps['rho0'] = rho0final qutritMDL.povms['Mdefault'] = _UnconstrainedPOVM([('0bright', E0final), ('1bright', E1final), ('2bright', E2final)], evotype=evotype) qutritMDL.operations['Gi'] = _FullArbitraryOp(arrType(gateISOfinal), evotype, state_space) qutritMDL.operations['Gx'] = _FullArbitraryOp(arrType(gateXSOfinal), evotype, state_space) qutritMDL.operations['Gy'] = _FullArbitraryOp(arrType(gateYSOfinal), evotype, state_space) qutritMDL.operations['Gm'] = _FullArbitraryOp(arrType(gateMSOfinal), evotype, state_space) qutritMDL.default_gauge_group = _FullGaugeGroup(state_space, evotype) return qutritMDL
def test_jamiolkowski_ops(self): gm = Basis.cast('gm', 4) pp = Basis.cast('pp', 4) std = Basis.cast('std', 4) mxGM = np.array( [[1, 0, 0, 0], [0, 0, 1, 0], [0, -1, 0, 0], [0, 0, 0, 1]], 'complex') mxStd = bt.change_basis(mxGM, gm, std) mxPP = bt.change_basis(mxGM, gm, pp) choiStd = pygsti.jamiolkowski_iso(mxStd, std, std) choiStd2 = pygsti.jamiolkowski_iso(mxGM, gm, std) choiStd3 = pygsti.jamiolkowski_iso(mxPP, pp, std) fastChoiStd = pygsti.fast_jamiolkowski_iso_std(mxStd, std) fastChoiStd2 = pygsti.fast_jamiolkowski_iso_std(mxGM, gm) fastChoiStd3 = pygsti.fast_jamiolkowski_iso_std(mxPP, pp) choiGM = pygsti.jamiolkowski_iso(mxStd, std, gm) choiGM2 = pygsti.jamiolkowski_iso(mxGM, gm, gm) choiGM3 = pygsti.jamiolkowski_iso(mxPP, pp, gm) choiPP = pygsti.jamiolkowski_iso(mxStd, std, pp) choiPP2 = pygsti.jamiolkowski_iso(mxGM, gm, pp) choiPP3 = pygsti.jamiolkowski_iso(mxPP, pp, pp) self.assertArraysAlmostEqual(choiStd, choiStd2) self.assertArraysAlmostEqual(choiStd, choiStd3) self.assertArraysAlmostEqual(choiStd, fastChoiStd) self.assertArraysAlmostEqual(choiStd, fastChoiStd2) self.assertArraysAlmostEqual(choiStd, fastChoiStd3) self.assertArraysAlmostEqual(choiGM, choiGM2) self.assertArraysAlmostEqual(choiGM, choiGM3) self.assertArraysAlmostEqual(choiPP, choiPP2) self.assertArraysAlmostEqual(choiPP, choiPP3) gateStd = pygsti.jamiolkowski_iso_inv(choiStd, std, std) gateStd2 = pygsti.jamiolkowski_iso_inv(choiGM, gm, std) gateStd3 = pygsti.jamiolkowski_iso_inv(choiPP, pp, std) gateGM = pygsti.jamiolkowski_iso_inv(choiStd, std, gm) gateGM2 = pygsti.jamiolkowski_iso_inv(choiGM, gm, gm) gateGM3 = pygsti.jamiolkowski_iso_inv(choiPP, pp, gm) gatePP = pygsti.jamiolkowski_iso_inv(choiStd, std, pp) gatePP2 = pygsti.jamiolkowski_iso_inv(choiGM, gm, pp) gatePP3 = pygsti.jamiolkowski_iso_inv(choiPP, pp, pp) fastGateStd = pygsti.fast_jamiolkowski_iso_std_inv(choiStd, std) fastGateGM = pygsti.fast_jamiolkowski_iso_std_inv(choiStd, gm) fastGatePP = pygsti.fast_jamiolkowski_iso_std_inv(choiStd, pp) self.assertArraysAlmostEqual(gateStd, mxStd) self.assertArraysAlmostEqual(gateStd2, mxStd) self.assertArraysAlmostEqual(gateStd3, mxStd) self.assertArraysAlmostEqual(fastGateStd, mxStd) self.assertArraysAlmostEqual(gateGM, mxGM) self.assertArraysAlmostEqual(gateGM2, mxGM) self.assertArraysAlmostEqual(gateGM3, mxGM) self.assertArraysAlmostEqual(fastGateGM, mxGM) self.assertArraysAlmostEqual(gatePP, mxPP) self.assertArraysAlmostEqual(gatePP2, mxPP) self.assertArraysAlmostEqual(gatePP3, mxPP) self.assertArraysAlmostEqual(fastGatePP, mxPP) ''' with self.assertRaises(NotImplementedError): pygsti.jamiolkowski_iso(mxStd, "foobar", gm) #invalid gate basis with self.assertRaises(NotImplementedError): pygsti.jamiolkowski_iso(mxStd, std, "foobar") #invalid choi basis with self.assertRaises(NotImplementedError): pygsti.jamiolkowski_iso_inv(choiStd, "foobar", gm) #invalid choi basis with self.assertRaises(NotImplementedError): pygsti.jamiolkowski_iso_inv(choiStd, std, "foobar") #invalid gate basis ''' sumOfNeg = pygsti.sum_of_negative_choi_evals(std1Q.target_model()) sumOfNegWt = pygsti.sum_of_negative_choi_evals(std1Q.target_model(), { 'Gx': 1.0, 'Gy': 0.5 }) sumsOfNeg = pygsti.sums_of_negative_choi_evals(std1Q.target_model()) magsOfNeg = pygsti.mags_of_negative_choi_evals(std1Q.target_model()) self.assertAlmostEqual(sumOfNeg, 0.0) self.assertArraysAlmostEqual(sumsOfNeg, np.zeros( 3, 'd')) # 3 gates in std.target_model() self.assertArraysAlmostEqual(magsOfNeg, np.zeros( 12, 'd')) # 3 gates * 4 evals each = 12
def test_convert(self): basis = Basis.cast("pp", 4) conv = states.convert(self.vec, "static", basis)
def test_raises_on_invalid_conversion_type(self): basis = Basis.cast("pp", 4) with self.assertRaises(ValueError): states.convert(self.vec, "foobar", basis)