def generate(self, x: np.ndarray, y: np.ndarray | None = None, **kwargs) -> np.ndarray:
        """
        Generate adversarial samples and return them in an array.

        :param x: An array with the original inputs.
        :param y: Target values (class labels) one-hot-encoded of shape `(nb_samples, nb_classes)` or indices of shape
                  (nb_samples,). Only provide this parameter if you'd like to use true labels when crafting adversarial
                  samples. Otherwise, model predictions are used as labels to avoid the "label leaking" effect
                  (explained in this paper: https://arxiv.org/abs/1611.01236). Default is `None`.
        :param mask: An array with a mask broadcastable to input `x` defining where to apply adversarial perturbations.
                     Shape needs to be broadcastable to the shape of x and can also be of the same shape as `x`. Any
                     features for which the mask is zero will not be adversarially perturbed.
        :type mask: `np.ndarray`
        :return: An array holding the adversarial examples.
        """
        import multiprocess

        x_adv = x.astype(ART_NUMPY_DTYPE)
        if y is not None:
            y = check_and_transform_label_format(y, nb_classes=self.estimator.nb_classes)

        if y is None:
            y = get_labels_np_array(self.estimator.predict(x, batch_size=self.batch_size))

        # Determine correctly predicted samples
        y_pred = self.estimator_orig.predict(x.astype(ART_NUMPY_DTYPE))
        sample_is_robust = np.argmax(y_pred, axis=1) == np.argmax(y, axis=1)

        # Set slots for images which have yet to be filled as SAMPLE_DEFAULT
        self.best_attacks = np.array([self.SAMPLE_DEFAULT] * len(x))
        # Set samples that are misclassified and do not need to be filled as SAMPLE_MISCLASSIFIED
        self.best_attacks[np.logical_not(sample_is_robust)] = self.SAMPLE_MISCLASSIFIED

        args = []
        # Untargeted attacks
        for attack in self.attacks:

            # Stop if all samples are misclassified
            if np.sum(sample_is_robust) == 0:
                break

            if attack.targeted:
                attack.set_params(targeted=False)

            if self.parallel_pool_size > 0:
                attack.estimator._optimizer = None
                self.estimator._optimizer = None

                args.append(
                    (
                        deepcopy(x_adv),
                        deepcopy(y),
                        deepcopy(sample_is_robust),
                        deepcopy(attack),
                        deepcopy(self.estimator),
                        deepcopy(self.norm),
                        deepcopy(self.eps),
                    )
                )
            else:
                x_adv, sample_is_robust = run_attack(
                    x=x_adv,
                    y=y,
                    sample_is_robust=sample_is_robust,
                    attack=attack,
                    estimator_orig=self.estimator,
                    norm=self.norm,
                    eps=self.eps,
                    **kwargs,
                )
                # create a mask which identifies images which this attack was effective on
                # not including originally misclassified images
                atk_mask = np.logical_and(
                    np.array([i == self.SAMPLE_DEFAULT for i in self.best_attacks]), np.logical_not(sample_is_robust)
                )
                # update attack at image index with index of attack that was successful
                self.best_attacks[atk_mask] = self.attacks.index(attack)

        # Targeted attacks
        if self.targeted:
            # Labels for targeted attacks
            y_t = np.array([range(y.shape[1])] * y.shape[0])
            y_idx = np.argmax(y, axis=1)
            y_idx = np.expand_dims(y_idx, 1)
            y_t = y_t[y_t != y_idx]
            targeted_labels = np.reshape(y_t, (y.shape[0], self.SAMPLE_DEFAULT))

            for attack in self.attacks:

                try:
                    attack.set_params(targeted=True)

                    for i in range(self.estimator.nb_classes - 1):
                        # Stop if all samples are misclassified
                        if np.sum(sample_is_robust) == 0:
                            break

                        target = check_and_transform_label_format(
                            targeted_labels[:, i], nb_classes=self.estimator.nb_classes
                        )

                        if self.parallel_pool_size > 0:
                            attack.estimator._optimizer = None
                            self.estimator._optimizer = None

                            args.append(
                                (
                                    deepcopy(x_adv),
                                    deepcopy(target),
                                    deepcopy(sample_is_robust),
                                    deepcopy(attack),
                                    deepcopy(self.estimator),
                                    deepcopy(self.norm),
                                    deepcopy(self.eps),
                                )
                            )
                        else:
                            x_adv, sample_is_robust = run_attack(
                                x=x_adv,
                                y=target,
                                sample_is_robust=sample_is_robust,
                                attack=attack,
                                estimator_orig=self.estimator,
                                norm=self.norm,
                                eps=self.eps,
                                **kwargs,
                            )
                            # create a mask which identifies images which this attack was effective on
                            # not including originally misclassified images
                            atk_mask = np.logical_and(
                                np.array([i == self.SAMPLE_DEFAULT for i in self.best_attacks]),
                                np.logical_not(sample_is_robust),
                            )
                            # update attack at image index with index of attack that was successful
                            self.best_attacks[atk_mask] = self.attacks.index(attack)
                except ValueError as error:
                    logger.warning("Error completing attack: %s}", str(error))

        if self.parallel_pool_size > 0:
            with multiprocess.get_context("spawn").Pool(processes=self.parallel_pool_size) as pool:
                # Results come back in the order that they were issued
                results = pool.starmap(run_attack, args)
            perturbations = []
            is_robust = []
            for img_idx in range(len(x)):
                perturbations.append(np.array([np.linalg.norm(x[img_idx] - i[0][img_idx]) for i in results]))
                is_robust.append([i[1][img_idx] for i in results])
            best_attacks = np.argmin(np.where(np.invert(np.array(is_robust)), np.array(perturbations), np.inf), axis=1)
            x_adv = np.concatenate([results[best_attacks[img]][0][[img]] for img in range(len(x))])
            self.best_attacks = best_attacks
            self.args = args
        return x_adv

        Generate adversarial samples and return them in an array.

        :param x: An array with the original inputs.
        :param y: Target values (class labels) one-hot-encoded of shape `(nb_samples, nb_classes)` or indices of shape
                  (nb_samples,). Only provide this parameter if you'd like to use true labels when crafting adversarial
                  samples. Otherwise, model predictions are used as labels to avoid the "label leaking" effect
                  (explained in this paper: https://arxiv.org/abs/1611.01236). Default is `None`.
        :param mask: An array with a mask broadcastable to input `x` defining where to apply adversarial perturbations.
                     Shape needs to be broadcastable to the shape of x and can also be of the same shape as `x`. Any
                     features for which the mask is zero will not be adversarially perturbed.
        :type mask: `np.ndarray`
        :return: An array holding the adversarial examples.
        
art/attacks/evasion/auto_attack.py