r"""Update the proposal using the points
        stored in ``self.samples[-1]`` and the parameters which can be set via
        :py:meth:`.set_adapt_params`.
        In the above referenced function's docstring, the algorithm is
        described in detail. If the resulting matrix is not a valid covariance,
        its offdiagonal elements are set to zero and a warning is printed. If
        that also fails, the proposal's covariance matrix is divided by the
        ``covar_scale_multiplier`` :math:`\beta`.

        .. note::
            This function only uses the points obtained during the last run.

def adapt(self):
        r"""Update the proposal using the points
        stored in ``self.samples[-1]`` and the parameters which can be set via
        :py:meth:`.set_adapt_params`.
        In the above referenced function's docstring, the algorithm is
        described in detail. If the resulting matrix is not a valid covariance,
        its offdiagonal elements are set to zero and a warning is printed. If
        that also fails, the proposal's covariance matrix is divided by the
        ``covar_scale_multiplier`` :math:`\beta`.

        .. note::
            This function only uses the points obtained during the last run.

        """
        last_run = self.samples[-1]
        accept_rate = float(self._last_accept_count) / len(last_run)

        # careful with rowvar!
        # in this form it is expected that each column  of ``points``
        # represents sampling values of a variable
        # this is the case if points is a list of sampled points
        covar_estimator = _np.cov(last_run, rowvar=0)

        # update sigma
        time_dependent_damping_factor = 1./self.adapt_count**self.damping
        self.unscaled_sigma = (1-time_dependent_damping_factor) * self.unscaled_sigma\
                               + time_dependent_damping_factor  * covar_estimator
        self._update_scale_factor(accept_rate)
        scaled_sigma = self.covar_scale_factor * self.unscaled_sigma

        # increase count now before proposal update. It may fail and raise an exception.
        self.adapt_count += 1

        try:
            self.proposal.update(scaled_sigma)
        except _np.linalg.LinAlgError:
            print("WARNING: Markov chain self adaptation failed; trying diagonalization ... ", end='')
            # try to insert offdiagonal elements only
            diagonal_matrix = _np.zeros_like(scaled_sigma)
            _np.fill_diagonal(diagonal_matrix, _np.diag(scaled_sigma))
            try:
                self.proposal.update(diagonal_matrix)
                print('success')
            except _np.linalg.LinAlgError:
                print('fail')
                # just scale the old covariance matrix if everything else fails
                self.proposal.update(self.proposal.sigma / self.covar_scale_multiplier)