def test_composite_basis(self): comp = Basis([('std', 2,), ('std', 1)]) a = Basis([('std', 2), ('std', 2)]) b = Basis('std', [2,2]) self.assertEqual(len(a), len(b)) self.assertArraysAlmostEqual(np.array(a._matrices), np.array(b._matrices))
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 test_expand_contract(self): # matrix that operates on 2x2 density matrices, but only on the 0-th and 3-rd # elements which correspond to the diagonals of the 2x2 density matrix. mxInStdBasis = np.array([[1,0,0,2], [0,0,0,0], [0,0,0,0], [3,0,0,4]],'d') # Reduce to a matrix operating on a density matrix space with 2 1x1 blocks (hence [1,1]) begin = Basis('std', [1,1]) end = Basis('std', 2) mxInReducedBasis = bt.resize_std_mx(mxInStdBasis, 'contract', end, begin) #mxInReducedBasis = bt.change_basis(mxInStdBasis, begin, end) notReallyContracted = bt.change_basis(mxInStdBasis, 'std', 'std', 4) correctAnswer = np.array([[ 1.0, 2.0], [ 3.0, 4.0]]) #self.assertArraysAlmostEqual( mxInReducedBasis, correctAnswer ) self.assertArraysAlmostEqual( notReallyContracted, mxInStdBasis ) expandedMx = bt.resize_std_mx(mxInReducedBasis, 'expand', begin, end) #expandedMx = bt.change_basis(mxInReducedBasis, end, begin) expandedMxAgain = bt.change_basis(expandedMx, 'std', 'std', 4) self.assertArraysAlmostEqual( expandedMx, mxInStdBasis ) self.assertArraysAlmostEqual( expandedMxAgain, mxInStdBasis )
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_auto_expand(self): comp = Basis(matrices=[('std', 2,), ('std', 1)]) std = Basis('std', 3) mxStd = np.identity(5) test = bt.resize_std_mx(mxStd, 'expand', comp, std) test2 = bt.resize_std_mx(test, 'contract', std, comp) self.assertArraysAlmostEqual(test2, mxStd)
def test_change_between_composites(self): a = Basis('std', [2, 1]) b = Basis('gm', [2, 1]) mxStd = np.identity(5) test = bt.change_basis(mxStd, a, b) self.assertEqual(test.shape, mxStd.shape) test2 = bt.change_basis(test, b, a) self.assertArraysAlmostEqual(test2, mxStd)
def test_flexible_change_basis(self): comp = Basis(matrices=[('gm', 2,), ('gm', 1)]) std = Basis('std', 3) mx = np.identity(5) test = bt.flexible_change_basis(mx, comp, std) self.assertEqual(test.shape[0], sum(comp.dim.blockDims) ** 2) test2 = bt.flexible_change_basis(test, std, comp) self.assertArraysAlmostEqual(test2, mx)
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_basis_object(self): #test a few aspects of a Basis object that other tests miss... b = Basis("pp",2) beq = b.expanded_equivalent() longnm = bt.basis_longname(b) lbls = bt.basis_element_labels(b) raw_mxs = bt.basis_matrices("pp",2) with self.assertRaises(NotImplementedError): bt.basis_matrices("foobar",2) #invalid basis name print("Dim = ", repr(b.dim) ) # calls Dim.__repr__
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_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 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_jamiolkowski_ops(self): gm = Basis('gm', 2) pp = Basis('pp', 2) std = Basis('std', 2) 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.gs_target) sumOfNegWt = pygsti.sum_of_negative_choi_evals(std1Q.gs_target, { 'Gx': 1.0, 'Gy': 0.5 }) sumsOfNeg = pygsti.sums_of_negative_choi_evals(std1Q.gs_target) magsOfNeg = pygsti.mags_of_negative_choi_evals(std1Q.gs_target) self.assertAlmostEqual(sumOfNeg, 0.0) self.assertArraysAlmostEqual(sumsOfNeg, np.zeros(3, 'd')) # 3 gates in std.gs_target self.assertArraysAlmostEqual(magsOfNeg, np.zeros( 12, 'd')) # 3 gates * 4 evals each = 12
def test_gm_basis(self): cmb = Basis('gm', sum(self.stateSpaceDims)) self.checkBasis(cmb)
def test_std_basis(self): cmb = Basis('std', sum(self.stateSpaceDims)) self.checkBasis(cmb)
def test_raises_on_invalid_conversion_type(self): basis = Basis.cast("pp", 4) with self.assertRaises(ValueError): states.convert(self.vec, "foobar", basis)
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 test_convert(self): basis = Basis.cast("pp", 4) conv = states.convert(self.vec, "static", basis)
def _from_memoized_dict(cls, mm_dict, serial_memo): errormap = serial_memo[mm_dict['submembers'][0]] base_povm = serial_memo[mm_dict['submembers'][1]] if len( mm_dict['submembers']) > 1 else None mx_basis = _Basis.from_nice_serialization(mm_dict['matrix_basis']) return cls(errormap, base_povm, mx_basis)
def test_sparse_basis(self): sparsePP = Basis("pp",2,sparse=True) sparsePP2 = Basis("pp",2,sparse=True) sparseBlockPP = Basis("pp",[2,2],sparse=True) sparsePP_2Q = Basis("pp",4,sparse=True) sparseGM_2Q = Basis("gm",2,sparse=True) #different sparsity structure than PP 2Q denseGM = Basis("gm",2,sparse=False) mxs = sparsePP.get_composite_matrices() block_mxs = sparseBlockPP.get_composite_matrices() expeq = sparsePP.expanded_equivalent() block_expeq = sparseBlockPP.expanded_equivalent() raw_mxs = bt.basis_matrices("pp",2,sparse=True) #test equality of bases with other bases and matrices self.assertEqual(sparsePP, sparsePP2) self.assertEqual(sparsePP, raw_mxs) self.assertNotEqual(sparsePP, sparsePP_2Q) self.assertNotEqual(sparsePP_2Q, sparseGM_2Q) #sparse transform matrix trans = sparsePP.transform_matrix(sparsePP2) self.assertArraysAlmostEqual(trans, np.identity(4,'d')) trans2 = sparsePP.transform_matrix(denseGM) #test equality for large bases, which is too expensive so it always returns false large_sparsePP = Basis("pp",16,sparse=True) large_sparsePP2 = Basis("pp",16,sparse=True) self.assertNotEqual(large_sparsePP, large_sparsePP2)
def test_general(self): Basis('pp', 2) Basis('std', [2, 1]) Basis([('std', 2), ('gm', 2)]) std = Basis('std', 2) std4 = Basis('std', 4) std2x2 = Basis([('std', 2), ('std', 2)]) gm = Basis('gm', 2) ungm = Basis('gm_unnormalized', 2) empty = Basis([]) #special "empty" basis self.assertEqual(empty.name, "*Empty*") from_basis,to_basis = pygsti.tools.build_basis_pair(np.identity(4,'d'),"std","gm") from_basis,to_basis = pygsti.tools.build_basis_pair(np.identity(4,'d'),std,"gm") from_basis,to_basis = pygsti.tools.build_basis_pair(np.identity(4,'d'),"std",gm) gm_mxs = gm.get_composite_matrices() unnorm = Basis(matrices=[ gm_mxs[0], 2*gm_mxs[1] ]) std[0] std.get_sub_basis_matrices(0) print(gm.get_composite_matrices()) self.assertTrue(gm.is_normalized()) self.assertFalse(ungm.is_normalized()) self.assertFalse(unnorm.is_normalized()) transMx = bt.transform_matrix(std, gm) composite = Basis([std, gm]) comp = Basis(matrices=[std, gm], name='comp', longname='CustomComposite') comp.labels = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'] comp = Basis(matrices=[std, gm], name='comp', longname='CustomComposite', labels=[ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' ]) std2x2Matrices = np.array([ [[1, 0], [0, 0]], [[0, 1], [0, 0]], [[0, 0], [1, 0]], [[0, 0], [0, 1]] ],'complex') empty = Basis(matrices=[]) alt_standard = Basis(matrices=std2x2Matrices) print("MXS = \n",alt_standard._matrices) alt_standard = Basis(matrices=std2x2Matrices, name='std', longname='Standard' ) self.assertEqual(alt_standard, std2x2Matrices) mx = np.array([ [1, 0, 0, 1], [0, 1, 2, 0], [0, 2, 1, 0], [1, 0, 0, 1] ]) bt.change_basis(mx, 'std', 'gm') # shortname lookup bt.change_basis(mx, std, gm) # object bt.change_basis(mx, std, 'gm') # combination bt.flexible_change_basis(mx, std, gm) #same dimension I2x2 = np.identity(8,'d') I4 = bt.flexible_change_basis(I2x2, std2x2, std4) self.assertArraysAlmostEqual(bt.flexible_change_basis(I4, std4, std2x2), I2x2) with self.assertRaises(ValueError): bt.change_basis(mx, std, std4) # basis size mismatch mxInStdBasis = np.array([[1,0,0,2], [0,0,0,0], [0,0,0,0], [3,0,0,4]],'d') begin = Basis('std', [1,1]) end = Basis('std', 2) mxInReducedBasis = bt.resize_std_mx(mxInStdBasis, 'contract', end, begin) original = bt.resize_std_mx(mxInReducedBasis, 'expand', begin, end)
def test_qt(self): qt = Basis('qt', 3) qt = Basis('qt', [3])
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