Beispiel #1
0
    def test_decompose_gpindices(self):
        parent_gpindices = slice(10, 20)
        sibling_gpindices = slice(12, 14)
        x = mm._decompose_gpindices(parent_gpindices, sibling_gpindices)
        self.assertEqual(x, slice(2, 4))

        parent_gpindices = slice(10, 20)
        sibling_gpindices = np.array([10, 12, 14], 'i')
        x = mm._decompose_gpindices(parent_gpindices, sibling_gpindices)
        self.assertEqual(list(x), list(np.array([0, 2, 4], 'i')))

        parent_gpindices = np.array([2, 4, 6, 8, 10], 'i')
        sibling_gpindices = np.array([2, 6, 10], 'i')
        x = mm._decompose_gpindices(parent_gpindices, sibling_gpindices)
        self.assertEqual(list(x), list(np.array([0, 2, 4], 'i')))
Beispiel #2
0
    def from_vector(self, v, close=False, dirty_value=True):
        """
        Initialize this factory using a vector of parameters.

        Parameters
        ----------
        v : numpy array
            The 1D vector of gate parameters.  Length
            must == num_params()

        close : bool, optional
            Whether `v` is close to this factory's current
            set of parameters.  Under some circumstances, when this
            is true this call can be completed more quickly.

        dirty_value : bool, optional
            The value to set this object's "dirty flag" to before exiting this
            call.  This is passed as an argument so it can be updated *recursively*.
            Leave this set to `True` unless you know what you're doing.

        Returns
        -------
        None
        """
        assert (
            self.gpindices is not None
        ), "Must set a ComposedOp's .gpindices before calling from_vector"
        for gate in self.factors:
            factor_local_inds = _gm._decompose_gpindices(
                self.gpindices, gate.gpindices)
            gate.from_vector(v[factor_local_inds], close, dirty_value)
        self.dirty = dirty_value
Beispiel #3
0
    def hessian_wrt_params(self, wrt_filter1=None, wrt_filter2=None):
        """
        Construct the Hessian of this error generator with respect to its parameters.

        This function returns a tensor whose first axis corresponds to the
        flattened operation matrix and whose 2nd and 3rd axes correspond to the
        parameters that are differentiated with respect to.

        Parameters
        ----------
        wrt_filter1 : list or numpy.ndarray
            List of parameter indices to take 1st derivatives with respect to.
            (None means to use all the this operation's parameters.)

        wrt_filter2 : list or numpy.ndarray
            List of parameter indices to take 2nd derivatives with respect to.
            (None means to use all the this operation's parameters.)

        Returns
        -------
        numpy array
            Hessian with shape (dimension^2, num_params1, num_params2)
        """
        #TODO: in the furture could do this more cleverly so
        # each factor gets an appropriate wrt_filter instead of
        # doing all filtering at the end

        d2 = self.state_space.dim
        nP = self.num_params
        hessianMx = _np.zeros((d2**2, nP, nP), 'd')
        for eg in self.factors:
            factor_hessian = eg.hessian_wrt_params(None,
                                                   None)  # do filtering at end
            rel_gpindices = _modelmember._decompose_gpindices(
                self.gpindices, eg.gpindices)
            hessianMx[:, rel_gpindices,
                      rel_gpindices] += factor_hessian[:, :, :]

        if wrt_filter1 is None:
            if wrt_filter2 is None:
                return hessianMx
            else:
                return _np.take(hessianMx, wrt_filter2, axis=2)
        else:
            if wrt_filter2 is None:
                return _np.take(hessianMx, wrt_filter1, axis=1)
            else:
                return _np.take(_np.take(hessianMx, wrt_filter1, axis=1),
                                wrt_filter2,
                                axis=2)
Beispiel #4
0
    def to_vector(self):
        """
        Get the parameters as an array of values.

        Returns
        -------
        numpy array
            The parameters as a 1D array with length num_params().
        """
        assert (
            self.gpindices is not None
        ), "Must set a ComposedOpFactory's .gpindices before calling to_vector"
        v = _np.empty(self.num_params, 'd')
        for gate in self.factors:
            factor_local_inds = _gm._decompose_gpindices(
                self.gpindices, gate.gpindices)
            v[factor_local_inds] = gate.to_vector()
        return v
Beispiel #5
0
    def deriv_wrt_params(self, wrt_filter=None):
        """
        The element-wise derivative this POVM effect vector.

        Construct a matrix whose columns are the derivatives of the POVM effect vector
        with respect to a single param.  Thus, each column is of length
        dimension and there is one column per POVM effect vector parameter.

        Parameters
        ----------
        wrt_filter : list or numpy.ndarray
            List of parameter indices to take derivative with respect to.
            (None means to use all the this operation's parameters.)

        Returns
        -------
        numpy array
            Array of derivatives, shape == (dimension, num_params)
        """
        if len(self.other_effects) == 0:
            return _np.zeros((self.dim, 0),
                             'd')  # Complement vecs assumed real
        Np = len(self.gpindices_as_array())
        neg_deriv = _np.zeros((self.dim, Np), 'd')
        for ovec in self.other_effects:
            local_inds = _modelmember._decompose_gpindices(
                self.gpindices, ovec.gpindices)
            #Note: other_vecs are not copies but other *sibling* effect vecs
            # so their gpindices index the same space as this complement vec's
            # does - so we need to "_decompose_gpindices"
            neg_deriv[:, local_inds] += ovec.deriv_wrt_params()
        derivMx = -neg_deriv

        if wrt_filter is None:
            return derivMx
        else:
            return _np.take(derivMx, wrt_filter, axis=1)
Beispiel #6
0
 def _decompose_indices(x):
     return tuple(
         _modelmember._decompose_gpindices(self.gpindices,
                                           _np.array(x, _np.int64)))
Beispiel #7
0
    def taylor_order_terms(self,
                           order,
                           max_polynomial_vars=100,
                           return_coeff_polys=False):
        """
        Get the `order`-th order Taylor-expansion terms of this error generator..

        This function either constructs or returns a cached list of the terms at
        the given order.  Each term is "rank-1", meaning that its action on a
        density matrix `rho` can be written:

        `rho -> A rho B`

        The coefficients of these terms are typically polynomials of the operation's
        parameters, where the polynomial's variable indices index the *global*
        parameters of the operation's parent (usually a :class:`Model`), not the
        operation's local parameter array (i.e. that returned from `to_vector`).

        Parameters
        ----------
        order : int
            The order of terms to get.

        max_polynomial_vars : int, optional
            maximum number of variables the created polynomials can have.

        return_coeff_polys : bool
            Whether a parallel list of locally-indexed (using variable indices
            corresponding to *this* object's parameters rather than its parent's)
            polynomial coefficients should be returned as well.

        Returns
        -------
        terms : list
            A list of :class:`RankOneTerm` objects.
        coefficients : list
            Only present when `return_coeff_polys == True`.
            A list of *compact* polynomial objects, meaning that each element
            is a `(vtape,ctape)` 2-tuple formed by concatenating together the
            output of :method:`Polynomial.compact`.
        """
        assert(order == 0), \
            "Error generators currently treat all terms as 0-th order; nothing else should be requested!"
        assert (return_coeff_polys is False)

        #Need to adjust indices b/c in error generators we (currently) expect terms to have local indices
        ret = []
        for eg in self.factors:
            eg_terms = [
                t.copy() for t in eg.taylor_order_terms(
                    order, max_polynomial_vars, return_coeff_polys)
            ]
            mapvec = _np.ascontiguousarray(
                _modelmember._decompose_gpindices(
                    self.gpindices,
                    _modelmember._compose_gpindices(
                        eg.gpindices, _np.arange(eg.num_params))), _np.int64)
            for t in eg_terms:
                # t.map_indices_inplace(lambda x: tuple(_modelmember._decompose_gpindices(
                #     # map global to *local* indices
                #     self.gpindices, _modelmember._compose_gpindices(eg.gpindices, _np.array(x, _np.int64)))))
                t.mapvec_indices_inplace(mapvec)
            ret.extend(eg_terms)
        return ret