# Buggy code
def inv_quad_logdet(self, inv_quad_rhs=None, logdet=False, reduce_inv_quad=True):
    """
    Computes an inverse quadratic form (w.r.t self) with several right hand sides.
    I.e. computes tr( tensor^T self^{-1} tensor )
    In addition, computes an (approximate) log determinant of the the matrix

    Args:
        - tensor (tensor nxk) - Vector (or matrix) for inverse quad

    Returns:
        - scalar - tr( tensor^T (self)^{-1} tensor )
        - scalar - log determinant
    """
    if not self.is_square:
        raise RuntimeError(
            "inv_quad_logdet only operates on (batches of) square (positive semi-definite) LazyTensors. "
            "Got a {} of size {}.".format(self.__class__.__name__, self.size())
        )

    if inv_quad_rhs is not None:
        if self.dim() == 2 and inv_quad_rhs.dim() == 1:
            if self.shape[-1] != inv_quad_rhs.numel():
                raise RuntimeError(
                    "LazyTensor (size={}) cannot be multiplied with right-hand-side Tensor (size={}).".format(
                        self.shape, inv_quad_rhs.shape
                    )
                )
        elif self.dim() != inv_quad_rhs.dim():
            raise RuntimeError(
                "LazyTensor (size={}) and right-hand-side Tensor (size={}) should have the same number "
                "of dimensions.".format(self.shape, inv_quad_rhs.shape)
            )
        elif (
            self.batch_shape != inv_quad_rhs.shape[:-2]
            or self.shape[-1] != inv_quad_rhs.shape[-2]
        ):
            raise RuntimeError(
                "LazyTensor (size={}) cannot be multiplied with right-hand-side Tensor (size={}).".format(
                    self.shape, inv_quad_rhs.shape
                )
            )

    args = self.representation()
    if inv_quad_rhs is not None:
        args = [inv_quad_rhs] + list(args)

    probe_vectors, probe_vector_norms = self._probe_vectors_and_norms()
    inv_quad_term, logdet_term = InvQuadLogDet(
        representation_tree=self.representation_tree(),
        matrix_shape=self.matrix_shape,
        batch_shape=self.batch_shape,
        dtype=self.dtype,
        device=self.device,
        inv_quad=(inv_quad_rhs is not None),
        logdet=logdet,
        preconditioner=self._preconditioner()[0],
        logdet_correction=self._preconditioner()[1],
        probe_vectors=probe_vectors,
        probe_vector_norms=probe_vector_norms,
    )(*args)

    if inv_quad_term.numel() and reduce_inv_quad:
        inv_quad_term = inv_quad_term.sum(-1)
    return inv_quad_term, logdet_term


# Traceback (RuntimeError)
$ python test_1D_grid_gp_regression.py
E.
======================================================================
ERROR: test_grid_gp_mean_abs_error (__main__.TestGridGPRegression)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test_1D_grid_gp_regression.py", line 87, in test_grid_gp_mean_abs_error
loss.backward()
File "/usr/local/lib/python3.6/dist-packages/torch/tensor.py", line 102, in backward
torch.autograd.backward(self, gradient, retain_graph, create_graph)
File "/usr/local/lib/python3.6/dist-packages/torch/autograd/__init__.py", line 90, in backward
allow_unreachable=True)  # allow_unreachable flag
File "/home/gpytorch/gpytorch/functions/_matmul.py", line 34, in backward
rhs = self.saved_tensors[0]
RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation

----------------------------------------------------------------------
Ran 2 tests in 0.088s

FAILED (errors=1)

# Fixed code
def inv_quad_logdet(self, inv_quad_rhs=None, logdet=False, reduce_inv_quad=True):
    """
    Computes an inverse quadratic form (w.r.t self) with several right hand sides.
    I.e. computes tr( tensor^T self^{-1} tensor )
    In addition, computes an (approximate) log determinant of the the matrix

    Args:
        - tensor (tensor nxk) - Vector (or matrix) for inverse quad

    Returns:
        - scalar - tr( tensor^T (self)^{-1} tensor )
        - scalar - log determinant
    """
    if not self.is_square:
        raise RuntimeError(
            "inv_quad_logdet only operates on (batches of) square (positive semi-definite) LazyTensors. "
            "Got a {} of size {}.".format(self.__class__.__name__, self.size())
        )

    if inv_quad_rhs is not None:
        if self.dim() == 2 and inv_quad_rhs.dim() == 1:
            if self.shape[-1] != inv_quad_rhs.numel():
                raise RuntimeError(
                    "LazyTensor (size={}) cannot be multiplied with right-hand-side Tensor (size={}).".format(
                        self.shape, inv_quad_rhs.shape
                    )
                )
        elif self.dim() != inv_quad_rhs.dim():
            raise RuntimeError(
                "LazyTensor (size={}) and right-hand-side Tensor (size={}) should have the same number "
                "of dimensions.".format(self.shape, inv_quad_rhs.shape)
            )
        elif (
            self.batch_shape != inv_quad_rhs.shape[:-2]
            or self.shape[-1] != inv_quad_rhs.shape[-2]
        ):
            raise RuntimeError(
                "LazyTensor (size={}) cannot be multiplied with right-hand-side Tensor (size={}).".format(
                    self.shape, inv_quad_rhs.shape
                )
            )

    args = self.representation()
    if inv_quad_rhs is not None:
        args = [inv_quad_rhs] + list(args)

    probe_vectors, probe_vector_norms = self._probe_vectors_and_norms()
    inv_quad_term, logdet_term = InvQuadLogDet(
        representation_tree=self.representation_tree(),
        matrix_shape=self.matrix_shape,
        batch_shape=self.batch_shape,
        dtype=self.dtype,
        device=self.device,
        inv_quad=(inv_quad_rhs is not None),
        logdet=logdet,
        probe_vectors=probe_vectors,
        probe_vector_norms=probe_vector_norms,
    )(*args)

    if inv_quad_term.numel() and reduce_inv_quad:
        inv_quad_term = inv_quad_term.sum(-1)
    return inv_quad_term, logdet_term