def _optimizer_adam_coordinate(
        self,
        losses: np.ndarray,
        index: np.ndarray,
        mean: np.ndarray,
        var: np.ndarray,
        current_noise: np.ndarray,
        learning_rate: float,
        adam_epochs: np.ndarray,
        proj: bool,
    ) -> np.ndarray:
        """
        Implementation of the ADAM optimizer for coordinate descent.

        :param losses: Overall loss.
        :param index: Indices of the coordinates to update.
        :param mean: The mean of the gradient (first moment).
        :param var: The uncentered variance of the gradient (second moment).
        :param current_noise: Current noise.
        :param learning_rate: Learning rate for Adam optimizer.
        :param adam_epochs: Epochs to run the Adam optimizer.
        :param proj: Whether to project the noise to the L_p ball.
        :return: Updated noise for coordinate descent.
        """
        beta1, beta2 = 0.9, 0.999

        # Estimate grads from loss variation (constant `h` from the paper is fixed to .0001)
        grads = np.array([(losses[i] - losses[i + 1]) / (2 * self.variable_h) for i in range(0, len(losses), 2)])

        # ADAM update
        mean[index] = beta1 * mean[index] + (1 - beta1) * grads
        var[index] = beta2 * var[index] + (1 - beta2) * grads**2

        corr = (np.sqrt(1 - np.power(beta2, adam_epochs[index]))) / (1 - np.power(beta1, adam_epochs[index]))
        orig_shape = current_noise.shape
        current_noise = current_noise.reshape(-1)
        current_noise[index] -= learning_rate * corr * mean[index] / (np.sqrt(var[index]) + 1e-8)
        adam_epochs[index] += 1

        if proj and hasattr(self.estimator, "clip_values") and self.estimator.clip_values is not None:
            clip_min, clip_max = self.estimator.clip_values
            current_noise[index] = np.clip(current_noise[index], clip_min, clip_max)

        return current_noise.reshape(orig_shape)

        Implementation of the ADAM optimizer for coordinate descent.

        :param losses: Overall loss.
        :param index: Indices of the coordinates to update.
        :param mean: The mean of the gradient (first moment).
        :param var: The uncentered variance of the gradient (second moment).
        :param current_noise: Current noise.
        :param learning_rate: Learning rate for Adam optimizer.
        :param adam_epochs: Epochs to run the Adam optimizer.
        :param proj: Whether to project the noise to the L_p ball.
        :return: Updated noise for coordinate descent.
        
art/attacks/evasion/zoo.py