<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def grad(self, x):
 r"""Compute the gradient of a signal defined on the vertices. The gradient :math:`y` of a signal :math:`x` is defined as .. math:: y = \nabla_\mathcal{G} x = D^\top x, where :math:`D` is the differential operator :attr:`D`. The value of the gradient on the edge :math:`e_k = (v_i, v_j)` from :math:`v_i` to :math:`v_j` with weight :math:`W[i, j]` is .. math:: y[k] = D[i, k] x[i] + D[j, k] x[j] = \sqrt{\frac{W[i, j]}{2}} (x[j] - x[i]) for the combinatorial Laplacian, and .. math:: y[k] = \sqrt{\frac{W[i, j]}{2}} \left( \frac{x[j]}{\sqrt{d[j]}} - \frac{x[i]}{\sqrt{d[i]}} \right) for the normalized Laplacian. For undirected graphs, only half the edges are kept and the :math:`1/\sqrt{2}` factor disappears from the above equations. See :meth:`compute_differential_operator` for details. Parameters x : array_like Signal of length :attr:`n_vertices` living on the vertices. Returns ------- y : ndarray Gradient signal of length :attr:`n_edges` living on the edges. See Also -------- compute_differential_operator div : compute the divergence of an edge signal dirichlet_energy : compute the norm of the gradient Examples -------- Non-directed graph and combinatorial Laplacian: array([ 2., 2., -2.]) Directed graph and combinatorial Laplacian: array([ 1.41421356, 1.41421356, -1.41421356]) Non-directed graph and normalized Laplacian: array([ 1.41421356, 1.41421356, -0.82842712]) Directed graph and normalized Laplacian: array([ 1.41421356, 1.41421356, -0.82842712]) """

        x = self._check_signal(x)
        return self.D.T.dot(x)