<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def elevate(self):
 r"""Return a degree-elevated version of the current surface. Does this by converting the current nodes :math:`\left\{v_{i, j, k}\right\}_{i + j + k = d}` to new nodes :math:`\left\{w_{i, j, k}\right\}_{i + j + k = d + 1}`. Does so by re-writing .. math:: E\left(\lambda_1, \lambda_2, \lambda_3\right) = \left(\lambda_1 + \lambda_2 + \lambda_3\right) B\left(\lambda_1, \lambda_2, \lambda_3\right) = \sum_{i + j + k = d + 1} \binom{d + 1}{i \, j \, k} \lambda_1^i \lambda_2^j \lambda_3^k \cdot w_{i, j, k} In this form, we must have .. math:: \begin{align*} \binom{d + 1}{i \, j \, k} \cdot w_{i, j, k} &= \binom{d}{i - 1 \, j \, k} \cdot v_{i - 1, j, k} + \binom{d}{i \, j - 1 \, k} \cdot v_{i, j - 1, k} + \binom{d}{i \, j \, k - 1} \cdot v_{i, j, k - 1} \\ \Longleftrightarrow (d + 1) \cdot w_{i, j, k} &= i \cdot v_{i - 1, j, k} + j \cdot v_{i, j - 1, k} + k \cdot v_{i, j, k - 1} \end{align*} where we define, for example, :math:`v_{i, j, k - 1} = 0` if :math:`k = 0`. .. image:: ../../images/surface_elevate.png :align: center .. doctest:: surface-elevate :options: +NORMALIZE_WHITESPACE <Surface (degree=3, dimension=2)> array([[0. , 1. , 2. , 3. , 0.5 , 1.5 , 2.5 , 0.5 , 1.5 , 0. ], [0. , 0. , 0. , 0. , 1. , 1.25, 1.5 , 2. , 2.5 , 3. ]]) .. testcleanup:: surface-elevate import make_images make_images.surface_elevate(surface, elevated) Returns: Surface: The degree-elevated surface. """

        _, num_nodes = self._nodes.shape
        # (d + 1)(d + 2)/2 --> (d + 2)(d + 3)/2
        num_new = num_nodes + self._degree + 2
        new_nodes = np.zeros((self._dimension, num_new), order="F")
        # NOTE: We start from the index triples (i, j, k) for the current
        #       nodes and map them onto (i + 1, j, k), etc. This index
        #       tracking is also done in :func:`.de_casteljau_one_round`.
        index = 0
        # parent_i1 = index + k
        # parent_i2 = index + k + 1
        # parent_i3 = index + degree + 2
        parent_i1 = 0
        parent_i2 = 1
        parent_i3 = self._degree + 2
        for k in six.moves.xrange(self._degree + 1):
            for j in six.moves.xrange(self._degree + 1 - k):
                i = self._degree - j - k
                new_nodes[:, parent_i1] += (i + 1) * self._nodes[:, index]
                new_nodes[:, parent_i2] += (j + 1) * self._nodes[:, index]
                new_nodes[:, parent_i3] += (k + 1) * self._nodes[:, index]
                # Update all the indices.
                parent_i1 += 1
                parent_i2 += 1
                parent_i3 += 1
                index += 1
            # Update the indices that depend on k.
            parent_i1 += 1
            parent_i2 += 1
        # Hold off on division until the end, to (attempt to) avoid round-off.
        denominator = self._degree + 1.0
        new_nodes /= denominator
        return Surface(new_nodes, self._degree + 1, _copy=False)