Exemple #1
0
 def test_change_between_composites(self):
     a = Basis.cast('std', [4, 1])
     b = Basis.cast('gm', [4, 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)
Exemple #2
0
def jamiolkowski_iso_inv(choi_mx, choi_mx_basis='pp', op_mx_basis='pp'):
    """
    Given a choi matrix, return the corresponding operation matrix.

    This function performs the inverse of :function:`jamiolkowski_iso`.

    Parameters
    ----------
    choi_mx : numpy array
        the Choi matrix, normalized to have trace == 1, to compute operation matrix for.

    choi_mx_basis : Basis object
        The source and destination basis, respectively.  Allowed
        values are Matrix-unit (std), Gell-Mann (gm), Pauli-product (pp),
        and Qutrit (qt) (or a custom basis object).

    op_mx_basis : Basis object
        The source and destination basis, respectively.  Allowed
        values are Matrix-unit (std), Gell-Mann (gm), Pauli-product (pp),
        and Qutrit (qt) (or a custom basis object).

    Returns
    -------
    numpy array
        operation matrix in the desired basis.
    """
    choi_mx = _np.asarray(choi_mx)  # will have "expanded" dimension even if bases are for reduced...
    N = choi_mx.shape[0]  # dimension of full-basis (expanded) operation matrix
    if not isinstance(choi_mx_basis, _Basis):  # if we're not given a basis, build
        choi_mx_basis = _Basis.cast(choi_mx_basis, N)  # one with the full dimension

    dmDim = int(round(_np.sqrt(N)))  # density matrix dimension

    #get full list of basis matrices (in std basis)
    BVec = _bt.basis_matrices(choi_mx_basis.create_simple_equivalent(), N)
    assert(len(BVec) == N)  # make sure the number of basis matrices matches the dim of the choi matrix given

    # Invert normalization
    choiMx_unnorm = choi_mx * dmDim

    opMxInStdBasis = _np.zeros((N, N), 'complex')  # in matrix unit basis of entire density matrix
    for i in range(N):
        for j in range(N):
            BiBj = _np.kron(BVec[i], _np.conjugate(BVec[j]))
            opMxInStdBasis += choiMx_unnorm[i, j] * BiBj

    if not isinstance(op_mx_basis, _Basis):
        op_mx_basis = _Basis.cast(op_mx_basis, N)  # make sure op_mx_basis is a Basis; we'd like dimension to be N

    #project operation matrix so it acts only on the space given by the desired state space blocks
    opMxInStdBasis = _bt.resize_std_mx(opMxInStdBasis, 'contract',
                                       op_mx_basis.create_simple_equivalent('std'),
                                       op_mx_basis.create_equivalent('std'))

    #transform operation matrix into appropriate basis
    return _bt.change_basis(opMxInStdBasis, op_mx_basis.create_equivalent('std'), op_mx_basis)
Exemple #3
0
 def test_flexible_change_basis(self):
     comp = Basis.cast([(
         'gm',
         4,
     ), ('gm', 1)])
     std = Basis.cast('std', 9)
     mx = np.identity(5)
     test = bt.flexible_change_basis(mx, comp, std)
     self.assertEqual(test.shape[0], comp.elsize)
     test2 = bt.flexible_change_basis(test, std, comp)
     self.assertArraysAlmostEqual(test2, mx)
Exemple #4
0
    def test_lind_errgens(self):

        bases = [Basis.cast('gm', 4), Basis.cast('pp', 4), Basis.cast('PP', 4)]

        for basis in bases:
            print(basis)
            Hblk = LindbladCoefficientBlock('ham', basis)
            Hblk_superops = Hblk.create_lindblad_term_superoperators(
                mx_basis='std')

            for i, mi in enumerate(basis[1:]):
                Hi = lt.create_elementary_errorgen('H', mi)
                HiB = lt.create_lindbladian_term_errorgen('H', mi)
                self.assertArraysAlmostEqual(Hi, HiB)
                self.assertArraysAlmostEqual(Hi, Hblk_superops[i])

            ODblk = LindbladCoefficientBlock('other_diagonal', basis)
            ODblk_superops = ODblk.create_lindblad_term_superoperators(
                mx_basis='std')

            for i, mi in enumerate(basis[1:]):
                ODi = lt.create_elementary_errorgen('S', mi)
                ODiB = lt.create_lindbladian_term_errorgen('O', mi, mi)
                self.assertArraysAlmostEqual(ODi, ODiB)
                self.assertArraysAlmostEqual(ODi, ODblk_superops[i])

            Oblk = LindbladCoefficientBlock('other', basis)
            Oblk_superops = Oblk.create_lindblad_term_superoperators(
                mx_basis='std')

            for i, mi in enumerate(basis[1:]):
                for j, mj in enumerate(basis[1:]):
                    Oij = lt.create_lindbladian_term_errorgen('O', mi, mj)
                    self.assertArraysAlmostEqual(Oij, Oblk_superops[i][j])

                    # C_PQ = NH_PQ + NH_QP
                    # A_PQ = i(NH_PQ - NH_QP)
                    if i < j:
                        Cij = lt.create_elementary_errorgen('C', mi, mj)
                        Aij = lt.create_elementary_errorgen('A', mi, mj)
                        self.assertArraysAlmostEqual(Oij,
                                                     (Cij + 1j * Aij) / 2.0)
                    elif j < i:
                        Cji = lt.create_elementary_errorgen('C', mj, mi)
                        Aji = lt.create_elementary_errorgen('A', mj, mi)
                        self.assertArraysAlmostEqual(Oij,
                                                     (Cji - 1j * Aji) / 2.0)
                    else:  # i == j
                        Sii = lt.create_elementary_errorgen('S', mi)
                        self.assertArraysAlmostEqual(Oij, Sii)
Exemple #5
0
    def test_auto_expand(self):
        comp = Basis.cast([(
            'std',
            4,
        ), ('std', 1)])
        std = Basis.cast('std', 9)
        mxStd = np.identity(5)
        test = bt.resize_std_mx(mxStd, 'expand', comp, std)
        # Intermediate test
        mxInter = np.identity(9)
        mxInter[2, 2] = mxInter[5, 5] = mxInter[6, 6] = mxInter[7, 7] = 0
        self.assertArraysAlmostEqual(test, mxInter)

        test2 = bt.resize_std_mx(test, 'contract', std, comp)
        self.assertArraysAlmostEqual(test2, mxStd)
Exemple #6
0
    def test_complement_spamvec(self):
        model = pygsti.models.modelconstruction.create_explicit_model_from_expressions(
            [('Q0', )], ['Gi', 'Gx', 'Gy'],
            ["I(Q0)", "X(pi/8,Q0)", "Y(pi/8,Q0)"])

        E0 = model.povms['Mdefault']['0']
        E1 = model.povms['Mdefault']['1']
        Ec = povms.ComplementPOVMEffect(
            modelconstruction.create_identity_vec(Basis.cast("pp", [4])), [E0])
        print(Ec.gpindices)

        #Test TPPOVM which uses a complement evec
        model.povms['Mtest'] = povms.TPPOVM([('+', E0), ('-', E1)])
        E0 = model.povms['Mtest']['+']
        Ec = model.povms['Mtest']['-']

        v = model.to_vector()
        model.from_vector(v)

        #print(Ec.num_params) #not implemented for complement vecs - only for POVM
        identity = np.array([[np.sqrt(2)], [0], [0], [0]], 'd')
        print("TEST1")
        print(E0)
        print(Ec)
        print(E0 + Ec)
        self.assertArraysAlmostEqual(E0 + Ec, identity)
Exemple #7
0
    def __init__(self, mx, basis, evotype, state_space):
        """ Initialize a new LinearOperator """
        mx = _LinearOperator.convert_to_matrix(mx)
        state_space = _statespace.default_space_for_udim(mx.shape[0]) if (state_space is None) \
            else _statespace.StateSpace.cast(state_space)
        basis = _Basis.cast(
            basis,
            state_space.dim)  # basis for Hilbert-Schmidt (superop) space
        evotype = _Evotype.cast(evotype)

        #Try to create a dense unitary rep.  If this fails, see if a dense superop rep
        # can be created, as this type of rep can also hold arbitrary unitary ops.
        try:
            rep = evotype.create_dense_unitary_rep(mx, basis, state_space)
            self._reptype = 'unitary'
            self._unitary = None
        except Exception:
            if mx.shape[0] == basis.dim and _np.linalg.norm(mx.imag) < 1e-10:
                # Special case when a *superop* was provided instead of a unitary mx
                superop_mx = mx.real  # used as a convenience case that really shouldn't be used
            else:
                superop_mx = _ot.unitary_to_superop(mx, basis)
            rep = evotype.create_dense_superop_rep(superop_mx, state_space)
            self._reptype = 'superop'
            self._unitary = mx
        self._basis = basis

        _LinearOperator.__init__(self, rep, evotype)
        DenseOperatorInterface.__init__(self)
Exemple #8
0
    def __init__(self, vec, basis, truncate=False, evotype="default", state_space=None):
        vector = _State._to_vector(vec)
        basis = _Basis.cast(basis, len(vector))

        self.basis = basis
        self.basis_mxs = basis.elements  # shape (len(vec), dmDim, dmDim)
        self.basis_mxs = _np.rollaxis(self.basis_mxs, 0, 3)  # shape (dmDim, dmDim, len(vec))
        assert(self.basis_mxs.shape[-1] == len(vector))

        # set self.params and self.dmDim
        self._set_params_from_vector(vector, truncate)

        #parameter labels (parameter encode the Cholesky Lmx)
        labels = []
        for i, ilbl in enumerate(basis.labels[1:]):
            for j, jlbl in enumerate(basis.labels[1:]):
                if i == j: labels.append("%s diagonal element of density matrix Cholesky decomp" % ilbl)
                elif j < i: labels.append("Re[(%s,%s) element of density matrix Cholesky decomp]" % (ilbl, jlbl))
                else: labels.append("Im[(%s,%s) element of density matrix Cholesky decomp]" % (ilbl, jlbl))

        #scratch space
        self.Lmx = _np.zeros((self.dmDim, self.dmDim), 'complex')

        state_space = _statespace.default_space_for_dim(len(vector)) if (state_space is None) \
            else _statespace.StateSpace.cast(state_space)

        evotype = _Evotype.cast(evotype)
        _DenseState.__init__(self, vector, evotype, state_space)
        self._paramlbls = _np.array(labels, dtype=object)
Exemple #9
0
    def __init__(self, purevec, basis, evotype, state_space):
        purevec = _State._to_vector(purevec)
        purevec = purevec.astype(complex)
        state_space = _statespace.default_space_for_udim(purevec.shape[0]) if (state_space is None) \
            else _statespace.StateSpace.cast(state_space)
        evotype = _Evotype.cast(evotype)
        basis = _Basis.cast(
            basis,
            state_space.dim)  # basis for Hilbert-Schmidt (superop) space

        #Try to create a dense pure rep.  If this fails, see if a dense superkey rep
        # can be created, as this type of rep can also hold arbitrary pure states.
        try:
            rep = evotype.create_pure_state_rep(purevec, basis, state_space)
            self._reptype = 'pure'
            self._purevec = self._basis = None
        except Exception:
            if len(purevec) == basis.dim and _np.linalg.norm(
                    purevec.imag) < 1e-10:
                # Special case when a *superket* was provided instead of a purevec
                superket_vec = purevec.real  # used as a convenience case that really shouldn't be used
            else:
                superket_vec = _bt.change_basis(_ot.state_to_dmvec(purevec),
                                                'std', basis)
            rep = evotype.create_dense_state_rep(superket_vec, state_space)
            self._reptype = 'superket'
            self._purevec = purevec
            self._basis = basis

        _State.__init__(self, rep, evotype)
        DenseStateInterface.__init__(self)
Exemple #10
0
    def __init__(self,
                 state_space,
                 basis="PP",
                 evotype="default",
                 initial_rates=None,
                 seed_or_state=None):
        state_space = _statespace.StateSpace.cast(state_space)
        self.basis = _Basis.cast(basis, state_space.dim, sparse=False)
        assert (
            state_space.dim == self.basis.dim
        ), "Dimension of `basis` must match the dimension (`dim`) of this op."

        evotype = _Evotype.cast(evotype)

        #Setup initial parameters
        self.params = _np.zeros(
            self.basis.size - 1,
            'd')  # note that basis.dim can be < self.dim (OK)
        if initial_rates is not None:
            assert(len(initial_rates) == self.basis.size - 1), \
                "Expected %d initial rates but got %d!" % (self.basis.size - 1, len(initial_rates))
            self.params[:] = self._rates_to_params(initial_rates)
            rates = _np.array(initial_rates)
        else:
            rates = _np.zeros(len(self.params), 'd')

        rep = evotype.create_stochastic_rep(self.basis,
                                            self._get_rate_poly_dicts(), rates,
                                            seed_or_state, state_space)
        _LinearOperator.__init__(self, rep, evotype)
        self._update_rep()  # initialize self._rep
        self._paramlbls = _np.array(
            ['sqrt(%s error rate)' % bl for bl in self.basis.labels[1:]],
            dtype=object)
Exemple #11
0
    def from_basis_coefficients(cls, parameterization, lindblad_basis, state_space, ham_coefficients=None,
                                nonham_coefficients=None):
        """
        Create a :class:`LindbladNoise` object containing a complete basis of elementary terms.

        This method provides a convenient way to create a lindblad noise specification containing the
        complete set of terms in a Lindbladian based on a given "Lindblad basis" (often just a Pauli product
        basis).  This routine by default creates all the terms with zero coefficients, but coefficient vectors
        or matrices (usually obtained by projecting an arbitrary error generator onto the lindblad basis) can
        be specified via the `ham_coefficients` and `nonham_coefficients` arguments.

        Parameters
        ----------
        parameterization : str or LindbladParameterization
            The Lindblad parameterization, specifying what constitutes the "complete" set of
            Lindblad terms.  For example, `"H"` means that just Hamiltonian terms are included
            whereas `"CPTP"` includes all the terms in a standard Lindblad decomposition.

        lindblad_basis : str or Basis
            The basis used to construct the Lindblad terms.

        state_space : StateSpace
            The state space, used only to convert string-valued `lindblad_basis` names into a
            :class:`Basis` object.  If `lindblad_basis` is given as a :class:`Basis`, then this
            can be set to `None`.

        ham_coefficients : numpy.ndarray or None, optional
            A 1-dimensional array of coefficients giving the initial values of the Hamiltonian-term
            coefficients.  The length of this arrays should be one less than the size of `lindblad_basis`
            (since there's no Lindblad term for the identity element).

        nonham_coefficients : numpy.ndarray or None, optional
            A 1- or 2-dimensional array of coefficients for the "other" (non-Hamiltonian) terms.
            The shape of this array should be `(d,)`, `(2,d)`, or `(d,d)` depending on `parameterization`
            (e.g. for S, S+A, and CPTP parameterizations).

        Returns
        -------
        LindbladNoise
        """
        lindblad_basis = _Basis.cast(lindblad_basis, state_space)
        parameterization = _op.LindbladParameterization.cast(parameterization)

        assert(len(parameterization.block_types) <= 2
               and len(parameterization.block_types) == len(set(parameterization.block_types))), \
            "Parameterization must have distinct block types and at most 2!"

        # coeffs + bases => elementary errorgen dict
        elementary_errorgens = {}
        for blk_type, blk_param in zip(parameterization.block_types, parameterization.param_modes):
            initial_data = ham_coefficients if blk_type == 'ham' else nonham_coefficients
            blk = _LindbladCoefficientBlock(blk_type, lindblad_basis, initial_block_data=initial_data)
            elementary_errorgens.update(blk.elementary_errorgens)

        return cls(elementary_errorgens, parameterization)
    def __init__(self, zvals, basis='pp', evotype="default", state_space=None):
        zvals = _np.ascontiguousarray(_np.array(zvals, _np.int64))

        state_space = _statespace.default_space_for_num_qubits(len(zvals)) if (state_space is None) \
            else _statespace.StateSpace.cast(state_space)
        basis = _Basis.cast(
            basis,
            state_space.dim)  # basis for Hilbert-Schmidt (superop) space

        evotype = _Evotype.cast(evotype)
        self._evotype = evotype  # set this before call to _State.__init__ so self.to_dense() can work...
        rep = evotype.create_computational_effect_rep(zvals, basis,
                                                      state_space)
        _POVMEffect.__init__(self, rep, evotype)
Exemple #13
0
    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.cast('std', [1, 1])
        end = Basis.cast('std', 4)

        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)
Exemple #14
0
    def test_sparse_lindblad_bases(self):
        sparsePP = Basis.cast("pp", 16, sparse=True)
        mxs = sparsePP.elements
        #for lbl, mx in zip(sparsePP.labels, mxs):
        #    print("{}: {} matrix with {} nonzero entries (of {} total)".format(
        #        lbl, mx.shape, mx.nnz, mx.shape[0] * mx.shape[1]
        #    ))
        #    print(mx.toarray())
        #print("{} basis elements".format(len(sparsePP)))
        self.assertEqual(len(sparsePP), 16)

        densePP = Basis.cast("pp", 16, sparse=False)
        for smx, dmx in zip(sparsePP.elements, densePP.elements):
            self.assertArraysAlmostEqual(smx.toarray(), dmx)

        M = np.ones((16, 16), 'd')
        v = np.ones(16, 'd')
        S = scipy.sparse.identity(16, 'd', 'csr')

        #print("Test types after basis change by sparse basis:")
        Mout = bt.change_basis(M, sparsePP, 'std')
        vout = bt.change_basis(v, sparsePP, 'std')
        Sout = bt.change_basis(S, sparsePP, 'std')
        #print("{} -> {}".format(type(M), type(Mout)))
        #print("{} -> {}".format(type(v), type(vout)))
        #print("{} -> {}".format(type(S), type(Sout)))
        self.assertIsInstance(Mout, np.ndarray)
        self.assertIsInstance(vout, np.ndarray)
        self.assertIsInstance(Sout, scipy.sparse.csr_matrix)

        Mdout = bt.change_basis(M, densePP, 'std')
        vdout = bt.change_basis(v, densePP, 'std')
        Sdout = bt.change_basis(S, densePP, 'std')
        self.assertIsInstance(Sdout, np.ndarray)
        self.assertArraysAlmostEqual(Mout, Mdout)
        self.assertArraysAlmostEqual(vout, vdout)
        self.assertArraysAlmostEqual(Sout, Sdout)
Exemple #15
0
    def __init__(self, state_space, target_labels, errgen_to_embed):
        _EmbeddedOp.__init__(self, state_space, target_labels, errgen_to_embed)

        # set "API" error-generator members (to interface properly w/other objects)
        # FUTURE: create a base class that defines this interface (maybe w/properties?)
        #self.sparse = True # Embedded error generators are *always* sparse (pointless to
        #                   # have dense versions of these)

        embedded_matrix_basis = errgen_to_embed.matrix_basis
        if isinstance(embedded_matrix_basis, str):
            self.matrix_basis = embedded_matrix_basis
        else:  # assume a Basis object
            my_basis_dim = self.state_space.dim
            self.matrix_basis = _Basis.cast(embedded_matrix_basis.name,
                                            my_basis_dim,
                                            sparse=True)
Exemple #16
0
    def __init__(self, state_space, basis="PP", evotype="default", initial_rate=0, seed_or_state=None):
        #TODO - need to fix CHP basis dimension issue (dim ~= statevec but acts as density mx)
        #if evotype == 'chp':
        #    assert (basis == 'pp'), "Only Pauli basis is allowed for 'chp' evotype"
        #    # For chp (and statevec, etc), want full superoperator basis
        #    basis = _Basis.cast(basis, 2**dim, sparse=False)
        #else:
        state_space = _statespace.StateSpace.cast(state_space)
        self.basis = _Basis.cast(basis, state_space.dim, sparse=False)

        num_rates = self.basis.size - 1
        initial_sto_rates = [initial_rate / num_rates] * num_rates
        _StochasticNoiseOp.__init__(self, state_space, self.basis, evotype, initial_sto_rates, seed_or_state)

        # For DepolarizeOp, set params to only first element
        self.params = _np.array([self.params[0]])
        self._paramlbls = _np.array(["common stochastic error rate for depolarization"], dtype=object)
Exemple #17
0
    def test_general(self):
        std = Basis.cast('std', 4)
        std4 = Basis.cast('std', 16)
        std2x2 = Basis.cast([('std', 4), ('std', 4)])
        gm = Basis.cast('gm', 4)

        from_basis, to_basis = bt.create_basis_pair(np.identity(4, 'd'), "std",
                                                    "gm")
        from_basis, to_basis = bt.create_basis_pair(np.identity(4, 'd'), std,
                                                    "gm")
        from_basis, to_basis = bt.create_basis_pair(np.identity(4, 'd'), "std",
                                                    gm)

        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(AssertionError):
            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.cast('std', [1, 1])
        end = Basis.cast('std', 4)
        mxInReducedBasis = bt.resize_std_mx(mxInStdBasis, 'contract', end,
                                            begin)
        original = bt.resize_std_mx(mxInReducedBasis, 'expand', begin, end)
        self.assertArraysAlmostEqual(mxInStdBasis, original)
Exemple #18
0
    def test_gaugeopt_and_contract(self):
        ds = self.ds_lgst

        #pygsti.construction.generate_fake_data(self.datagen_gateset, self.lgstStrings,
        #                                            nSamples=10000,sampleError='binomial', seed=100)

        mdl_lgst = pygsti.do_lgst(ds, self.fiducials, self.fiducials, self.model, svdTruncateTo=4, verbosity=0)


        #Gauge Opt to Target
        mdl_lgst_target     = self.runSilent(pygsti.gaugeopt_to_target, mdl_lgst, self.model, verbosity=10, checkJac=True)

        #
        mdl_lgst.basis = self.model.basis.copy()
        mdl_clgst_cp    = self.runSilent(pygsti.contract, mdl_lgst, "CP",verbosity=10, tol=10.0, useDirectCP=False) #non-direct CP contraction

        #Gauge Opt to Target using non-frobenius metrics
        mdl_lgst_targetAlt  = self.runSilent(pygsti.gaugeopt_to_target, mdl_lgst_target, self.model,
                                            gatesMetric='fidelity', verbosity=10, checkJac=True)

        mdl_lgst_targetAlt  = self.runSilent(pygsti.gaugeopt_to_target, mdl_lgst_target, self.model,
                                            gatesMetric='tracedist', verbosity=10, checkJac=True)

        mdl_lgst_targetAlt  = self.runSilent(pygsti.gaugeopt_to_target, mdl_lgst_target, self.model,
                                            spamMetric='fidelity', verbosity=10, checkJac=True)

        mdl_lgst_targetAlt  = self.runSilent(pygsti.gaugeopt_to_target, mdl_lgst_target, self.model,
                                            spamMetric='tracedist', verbosity=10, checkJac=True)

        #Using other methods
        mdl_BFGS = self.runSilent(pygsti.gaugeopt_to_target, mdl_lgst, self.model, method='BFGS', verbosity=10)
        with self.assertRaises(ValueError): #Invalid metric
            self.runSilent(pygsti.gaugeopt_to_target, mdl_lgst, self.model, method='BFGS', spamMetric='foobar', verbosity=10)
        with self.assertRaises(ValueError): #Invalid metric
            self.runSilent(pygsti.gaugeopt_to_target, mdl_lgst, self.model, method='BFGS', gatesMetric='foobar', verbosity=10)
            
        with self.assertRaises(ValueError): #can't use least-squares for anything but frobenius metric
            self.runSilent(pygsti.gaugeopt_to_target, mdl_lgst_target, self.model,
                           spamMetric='tracedist', method='ls', verbosity=10, checkJac=True)


        #with self.assertRaises(ValueError):
        #    self.runSilent(pygsti.gaugeopt_to_target, mdl_lgst_target, self.model,
        #                   gatesMetric='foobar', verbosity=10) #bad gatesMetric
        #
        #with self.assertRaises(ValueError):
        #    self.runSilent(pygsti.gaugeopt_to_target, mdl_lgst_target, self.model,
        #                   spamMetric='foobar', verbosity=10) #bad spamMetric
                

        #Contractions
        mdl_clgst_tp    = self.runSilent(pygsti.contract, mdl_lgst_target, "TP",verbosity=10, tol=10.0)
        mdl_clgst_cp    = self.runSilent(pygsti.contract, mdl_lgst_target, "CP",verbosity=10, tol=10.0)
        mdl_clgst_cp2    = self.runSilent(pygsti.contract, mdl_lgst_target, "CP",verbosity=10, tol=10.0)
        mdl_clgst_cptp  = self.runSilent(pygsti.contract, mdl_lgst_target, "CPTP",verbosity=10, tol=10.0)
        mdl_clgst_cptp2 = self.runSilent(pygsti.contract, mdl_lgst_target, "CPTP",verbosity=10, useDirectCP=False)
        mdl_clgst_cptp3 = self.runSilent(pygsti.contract, mdl_lgst_target, "CPTP",verbosity=10, tol=10.0, maxiter=0)
        mdl_clgst_xp    = self.runSilent(pygsti.contract, mdl_lgst_target, "XP", ds,verbosity=10, tol=10.0)
        mdl_clgst_xptp  = self.runSilent(pygsti.contract, mdl_lgst_target, "XPTP", ds,verbosity=10, tol=10.0)
        mdl_clgst_vsp   = self.runSilent(pygsti.contract, mdl_lgst_target, "vSPAM",verbosity=10, tol=10.0)
        mdl_clgst_none  = self.runSilent(pygsti.contract, mdl_lgst_target, "nothing",verbosity=10, tol=10.0)

          #test bad effect vector cases
        mdl_bad_effect = mdl_lgst_target.copy()
        mdl_bad_effect.povms['Mdefault'] = pygsti.obj.UnconstrainedPOVM( [('0',[100.0,0,0,0])] ) # E eigvals all > 1.0
        self.runSilent(pygsti.contract, mdl_bad_effect, "vSPAM",verbosity=10, tol=10.0)
        mdl_bad_effect.povms['Mdefault'] = pygsti.obj.UnconstrainedPOVM( [('0',[-100.0,0,0,0])] ) # E eigvals all < 0
        self.runSilent(pygsti.contract, mdl_bad_effect, "vSPAM",verbosity=10, tol=10.0)

        #with self.assertRaises(ValueError):
        #    self.runSilent(pygsti.contract, mdl_lgst_target, "foobar",verbosity=10, tol=10.0) #bad toWhat

            
        #More gauge optimizations
        TP_gauge_group = pygsti.obj.TPGaugeGroup(mdl_lgst.dim)
        mdl_lgst_target_cp  = self.runSilent(pygsti.gaugeopt_to_target, mdl_clgst_cptp, self.model, 
                                            cptp_penalty_factor=1.0, gauge_group=TP_gauge_group, verbosity=10, checkJac=True)

        mdl_lgst_tp         = self.runSilent(pygsti.gaugeopt_to_target, mdl_lgst, None,
                                            spam_penalty_factor=1.0, verbosity=10, checkJac=True)

        mdl_lgst.basis = Basis.cast("gm",4) #so CPTP optimizations can work on mdl_lgst
        mdl_lgst_cptp       = self.runSilent(pygsti.gaugeopt_to_target, mdl_lgst, None,
                                            cptp_penalty_factor=1.0, spam_penalty_factor=1.0, verbosity=10, checkJac=True)

        mdl_lgst_cptp_tp    = self.runSilent(pygsti.gaugeopt_to_target, mdl_lgst, None,
                                            cptp_penalty_factor=1.0, spam_penalty_factor=1.0, gauge_group=TP_gauge_group, verbosity=10, checkJac=True) #no point? (remove?)

        #I'm not sure why moving this test upward fixes a singlar matrix error (TODO LATER? - could one of above tests modify mdl_lgst??)
        #mdl_lgst_tp         = self.runSilent(pygsti.gaugeopt_to_target( mdl_lgst, None,
        #                                    spam_penalty_factor=1.0, verbosity=10, checkJac=True)

        mdl_lgst_tptarget   = self.runSilent(pygsti.gaugeopt_to_target, mdl_lgst, self.model,
                                            spam_penalty_factor=1.0, verbosity=10, checkJac=True)

        mdl_lgst_cptptarget = self.runSilent(pygsti.gaugeopt_to_target, mdl_lgst, self.model,
                                            cptp_penalty_factor=1.0, spam_penalty_factor=1.0, verbosity=10, checkJac=True)

        mdl_lgst_cptptarget2= self.runSilent(pygsti.gaugeopt_to_target, mdl_lgst, self.model,
                                            cptp_penalty_factor=1.0, spam_penalty_factor=1.0, gauge_group=TP_gauge_group, verbosity=10, checkJac=True) #no point? (remove?)

        #Use "None" gauge group
        mdl_none = self.runSilent(pygsti.gaugeopt_to_target, mdl_lgst, self.model, gauge_group=None, verbosity=10)
        soln, trivialEl, mdl_none = self.runSilent(pygsti.gaugeopt_to_target, mdl_lgst, self.model, gauge_group=None, verbosity=10, returnAll=True)

        #Use "None" default gauge group
        mdl_none = self.model.copy()
        mdl_none.default_gauge_group = None
        self.runSilent(pygsti.gaugeopt_to_target, mdl_none, self.model, verbosity=10)
        soln, trivialEl, mdl_none = self.runSilent(pygsti.gaugeopt_to_target, mdl_none, self.model, verbosity=10, returnAll=True)


        #TODO: check output lies in space desired

        # big kick that should land it outside XP, TP, etc, so contraction
        # routines are more tested
        mdl_bigkick = mdl_lgst_target.kick(absmag=1.0)
        mdl_badspam = mdl_bigkick.copy()
        mdl_badspam.povms['Mdefault'] = pygsti.obj.UnconstrainedPOVM( [('0',np.array( [[2],[0],[0],[4]], 'd'))] )
          #set a bad evec so vSPAM has to work...
        

        mdl_clgst_tp    = self.runSilent(pygsti.contract,mdl_bigkick, "TP", verbosity=10, tol=10.0)
        mdl_clgst_cp    = self.runSilent(pygsti.contract,mdl_bigkick, "CP", verbosity=10, tol=10.0)
        mdl_clgst_cptp  = self.runSilent(pygsti.contract,mdl_bigkick, "CPTP", verbosity=10, tol=10.0)
        mdl_clgst_xp    = self.runSilent(pygsti.contract,mdl_bigkick, "XP", ds, verbosity=10, tol=10.0)
        mdl_clgst_xptp  = self.runSilent(pygsti.contract,mdl_bigkick, "XPTP", ds, verbosity=10, tol=10.0)
        mdl_clgst_vsp   = self.runSilent(pygsti.contract,mdl_badspam, "vSPAM", verbosity=10, tol=10.0)
        mdl_clgst_none  = self.runSilent(pygsti.contract,mdl_bigkick, "nothing", verbosity=10, tol=10.0)

        #TODO: check output lies in space desired

        #Check Errors
        with self.assertRaises(ValueError):
            pygsti.contract(mdl_lgst_target, "FooBar",verbosity=0) # bad toWhat argument
Exemple #19
0
def jamiolkowski_iso(operation_mx, op_mx_basis='pp', choi_mx_basis='pp'):
    """
    Given a operation matrix, return the corresponding Choi matrix that is normalized to have trace == 1.

    Parameters
    ----------
    operation_mx : numpy array
        the operation matrix to compute Choi matrix of.

    op_mx_basis : Basis object
        The source and destination basis, respectively.  Allowed
        values are Matrix-unit (std), Gell-Mann (gm), Pauli-product (pp),
        and Qutrit (qt) (or a custom basis object).

    choi_mx_basis : Basis object
        The source and destination basis, respectively.  Allowed
        values are Matrix-unit (std), Gell-Mann (gm), Pauli-product (pp),
        and Qutrit (qt) (or a custom basis object).

    Returns
    -------
    numpy array
        the Choi matrix, normalized to have trace == 1, in the desired basis.
    """
    operation_mx = _np.asarray(operation_mx)
    op_mx_basis = _bt.create_basis_for_matrix(operation_mx, op_mx_basis)
    opMxInStdBasis = _bt.change_basis(operation_mx, op_mx_basis, op_mx_basis.create_equivalent('std'))

    #expand operation matrix so it acts on entire space of dmDim x dmDim density matrices
    #  so that we can take dot products with the BVec matrices below
    opMxInStdBasis = _bt.resize_std_mx(opMxInStdBasis, 'expand', op_mx_basis.create_equivalent(
        'std'), op_mx_basis.create_simple_equivalent('std'))

    N = opMxInStdBasis.shape[0]  # dimension of the full-basis (expanded) gate
    dmDim = int(round(_np.sqrt(N)))  # density matrix dimension

    #Note: we need to use the *full* basis of Matrix Unit, Gell-Mann, or Pauli-product matrices when
    # generating the Choi matrix, even when the original operation matrix doesn't include the entire basis.
    # This is because even when the original operation matrix doesn't include a certain basis element (B0 say),
    # conjugating with this basis element and tracing, i.e. trace(B0^dag * Operation * B0), is not necessarily zero.

    #get full list of basis matrices (in std basis) -- i.e. we use dmDim
    if not isinstance(choi_mx_basis, _Basis):
        choi_mx_basis = _Basis.cast(choi_mx_basis, N)  # we'd like a basis of dimension N

    BVec = choi_mx_basis.create_simple_equivalent().elements
    M = len(BVec)  # can be < N if basis has multiple block dims
    assert(M == N), 'Expected {}, got {}'.format(M, N)

    choiMx = _np.empty((N, N), 'complex')
    for i in range(M):
        for j in range(M):
            BiBj = _np.kron(BVec[i], _np.conjugate(BVec[j]))
            BiBj_dag = _np.transpose(_np.conjugate(BiBj))
            choiMx[i, j] = _mt.trace(_np.dot(opMxInStdBasis, BiBj_dag)) \
                / _mt.trace(_np.dot(BiBj, BiBj_dag))

    # This construction results in a Jmx with trace == dim(H) = sqrt(operation_mx.shape[0])
    #  (dimension of density matrix) but we'd like a Jmx with trace == 1, so normalize:
    choiMx_normalized = choiMx / dmDim
    return choiMx_normalized
Exemple #20
0
 def test_raises_on_basis_mismatch(self):
     with self.assertRaises(ValueError):
         mdl_target_gm = std2Q_XXYYII.target_model()
         mdl_target_gm.basis = Basis.cast("gm", 16)
         ot.project_model(self.model, mdl_target_gm, self.projectionTypes,
                          'logGti')  # basis mismatch
Exemple #21
0
    def test_lind_errgen_projects(self):
        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)

        Hblk = LindbladCoefficientBlock('ham', basis)
        ODblk = LindbladCoefficientBlock('other_diagonal', basis)
        Oblk = LindbladCoefficientBlock('other', basis)

        Hblk.set_from_errorgen_projections(errgen, errorgen_basis=mx_basis)
        ODblk.set_from_errorgen_projections(errgen, errorgen_basis=mx_basis)
        Oblk.set_from_errorgen_projections(errgen, errorgen_basis=mx_basis)

        self.assertArraysAlmostEqual(Hblk.block_data, [-0.01, 0, 0.1])
        self.assertArraysAlmostEqual(ODblk.block_data, [0.2, 0.25, 0])
        self.assertArraysAlmostEqual(
            Oblk.block_data,
            np.array([[0.2, 0.05 + 0.01j, 0], [0.05 - 0.01j, 0.25, 0],
                      [0, 0, 0]]))

        def dicts_equal(d, f):
            f = {LEEL.cast(k): v for k, v in f.items()}
            if set(d.keys()) != set(f.keys()): return False
            for k in d:
                if abs(d[k] - f[k]) > 1e-12: return False
            return True

        self.assertTrue(
            dicts_equal(Hblk.elementary_errorgens, {
                ('H', 'Z'): 0.1,
                ('H', 'X'): -0.01,
                ('H', 'Y'): 0
            }))
        self.assertTrue(
            dicts_equal(ODblk.elementary_errorgens, {
                ('S', 'X'): 0.2,
                ('S', 'Y'): 0.25,
                ('S', 'Z'): 0
            }))
        self.assertTrue(
            dicts_equal(
                Oblk.elementary_errorgens, {
                    ('S', 'X'): 0.2,
                    ('S', 'Y'): 0.25,
                    ('S', 'Z'): 0.0,
                    ('C', 'X', 'Y'): 0.05,
                    ('A', 'X', 'Y'): -0.01,
                    ('C', 'X', 'Z'): 0,
                    ('A', 'X', 'Z'): 0,
                    ('C', 'Y', 'Z'): 0,
                    ('A', 'Y', 'Z'): 0,
                }))