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 to be attacked.
        :param y: An array with the true or target labels.
        :return: An array holding the adversarial examples.
        """
        x = x.astype(ART_NUMPY_DTYPE)
        x_adv = x.copy()

        y_prob_pred = self.estimator.predict(x, batch_size=self.batch_size)

        if not is_probability(y_prob_pred[0]):
            raise ValueError(
                "This attack requires an estimator predicting probabilities. It looks like the current "
                "estimator is not predicting probabilities"
            )

        if self.estimator.nb_classes == 2 and y_prob_pred.shape[1] == 1:
            raise ValueError(
                "This attack has not yet been tested for binary classification with a single output classifier."
            )

        if divmod(x.shape[2] - self.freq_dim, self.stride)[1] != 0:
            raise ValueError(
                "Incompatible value combination in image height/width, freq_dim and stride detected. "
                "Adapt these parameters to fulfill the following conditions: "
                "divmod(image_height - freq_dim, stride)[1] == 0 "
                "and "
                "divmod(image_width - freq_dim, stride)[1] == 0"
            )

        if y is None:
            if self.targeted:
                raise ValueError("Target labels `y` need to be provided for a targeted attack.")

            # Use model predictions as correct outputs
            logger.info("Using the model prediction as the correct label for SimBA.")
            y_i = np.argmax(y_prob_pred, axis=1)
        else:
            y_i = np.argmax(y, axis=1)

        for i_sample in trange(x.shape[0], desc="SimBA - sample", disable=not self.verbose):

            desired_label = y_i[i_sample]

            current_label = np.argmax(y_prob_pred, axis=1)[i_sample]
            last_prob = y_prob_pred[i_sample].reshape(-1)[desired_label]

            if self.estimator.channels_first:
                nb_channels = x.shape[1]
            else:
                nb_channels = x.shape[3]

            n_dims = np.prod(x[[0]].shape)

            if self.attack == "px":
                if self.order == "diag":
                    indices = self.diagonal_order(x.shape[2], nb_channels)[: self.max_iter]
                elif self.order == "random":
                    indices = np.random.permutation(n_dims)[: self.max_iter]
                indices_size = len(indices)
                while indices_size < self.max_iter:
                    if self.order == "diag":
                        tmp_indices = self.diagonal_order(x.shape[2], nb_channels)
                    elif self.order == "random":
                        tmp_indices = np.random.permutation(n_dims)
                    indices = np.hstack((indices, tmp_indices))[: self.max_iter]
                    indices_size = len(indices)
            elif self.attack == "dct":
                indices = self._block_order(x.shape[2], nb_channels, initial_size=self.freq_dim, stride=self.stride)[
                    : self.max_iter
                ]
                indices_size = len(indices)
                while indices_size < self.max_iter:
                    tmp_indices = self._block_order(
                        x.shape[2], nb_channels, initial_size=self.freq_dim, stride=self.stride
                    )
                    indices = np.hstack((indices, tmp_indices))[: self.max_iter]
                    indices_size = len(indices)

                def trans(var_z):
                    return self._block_idct(var_z, block_size=x.shape[2])

            clip_min = -np.inf
            clip_max = np.inf
            if self.estimator.clip_values is not None:
                clip_min, clip_max = self.estimator.clip_values

            term_flag = 1
            if self.targeted:
                if desired_label != current_label:
                    term_flag = 0
            else:
                if desired_label == current_label:
                    term_flag = 0

            nb_iter = 0
            while term_flag == 0 and nb_iter < self.max_iter:
                diff = np.zeros(n_dims).astype(ART_NUMPY_DTYPE)
                diff[indices[nb_iter]] = self.epsilon

                if self.attack == "dct":
                    left_preds = self.estimator.predict(
                        np.clip(x[[i_sample]] - trans(diff.reshape(x[[i_sample]].shape)), clip_min, clip_max),
                        batch_size=self.batch_size,
                    )
                elif self.attack == "px":
                    left_preds = self.estimator.predict(
                        np.clip(x[[i_sample]] - diff.reshape(x[[i_sample]].shape), clip_min, clip_max),
                        batch_size=self.batch_size,
                    )
                left_prob = left_preds.reshape(-1)[desired_label]

                if self.attack == "dct":
                    right_preds = self.estimator.predict(
                        np.clip(x[[i_sample]] + trans(diff.reshape(x[[i_sample]].shape)), clip_min, clip_max),
                        batch_size=self.batch_size,
                    )
                elif self.attack == "px":
                    right_preds = self.estimator.predict(
                        np.clip(x[[i_sample]] + diff.reshape(x[[i_sample]].shape), clip_min, clip_max),
                        batch_size=self.batch_size,
                    )
                right_prob = right_preds.reshape(-1)[desired_label]

                # Use (2 * int(self.targeted) - 1) to shorten code?
                if self.targeted:
                    if left_prob > last_prob:
                        if left_prob > right_prob:
                            if self.attack == "dct":
                                x[[i_sample]] = np.clip(
                                    x[[i_sample]] - trans(diff.reshape(x[[i_sample]].shape)), clip_min, clip_max
                                )
                            elif self.attack == "px":
                                x[[i_sample]] = np.clip(
                                    x[[i_sample]] - diff.reshape(x[[i_sample]].shape), clip_min, clip_max
                                )
                            last_prob = left_prob
                            current_label = np.argmax(left_preds, axis=1)[0]
                        else:
                            if self.attack == "dct":
                                x[[i_sample]] = np.clip(
                                    x[[i_sample]] + trans(diff.reshape(x[[i_sample]].shape)), clip_min, clip_max
                                )
                            elif self.attack == "px":
                                x[[i_sample]] = np.clip(
                                    x[[i_sample]] + diff.reshape(x[[i_sample]].shape), clip_min, clip_max
                                )
                            last_prob = right_prob
                            current_label = np.argmax(right_preds, axis=1)[0]
                    else:
                        if right_prob > last_prob:
                            if self.attack == "dct":
                                x[[i_sample]] = np.clip(
                                    x[[i_sample]] + trans(diff.reshape(x[[i_sample]].shape)), clip_min, clip_max
                                )
                            elif self.attack == "px":
                                x[[i_sample]] = np.clip(
                                    x[[i_sample]] + diff.reshape(x[[i_sample]].shape), clip_min, clip_max
                                )
                            last_prob = right_prob
                            current_label = np.argmax(right_preds, axis=1)[0]
                else:
                    if left_prob < last_prob:
                        if left_prob < right_prob:
                            if self.attack == "dct":
                                x[[i_sample]] = np.clip(
                                    x[[i_sample]] - trans(diff.reshape(x[[i_sample]].shape)), clip_min, clip_max
                                )
                            elif self.attack == "px":
                                x[[i_sample]] = np.clip(
                                    x[[i_sample]] - diff.reshape(x[[i_sample]].shape), clip_min, clip_max
                                )
                            last_prob = left_prob
                            current_label = np.argmax(left_preds, axis=1)[0]
                        else:
                            if self.attack == "dct":
                                x[[i_sample]] = np.clip(
                                    x[[i_sample]] + trans(diff.reshape(x[[i_sample]].shape)), clip_min, clip_max
                                )
                            elif self.attack == "px":
                                x[[i_sample]] = np.clip(
                                    x[[i_sample]] + diff.reshape(x[[i_sample]].shape), clip_min, clip_max
                                )
                            last_prob = right_prob
                            current_label = np.argmax(right_preds, axis=1)[0]
                    else:
                        if right_prob < last_prob:
                            if self.attack == "dct":
                                x[[i_sample]] = np.clip(
                                    x[[i_sample]] + trans(diff.reshape(x[[i_sample]].shape)), clip_min, clip_max
                                )
                            elif self.attack == "px":
                                x[[i_sample]] = np.clip(
                                    x[[i_sample]] + diff.reshape(x[[i_sample]].shape), clip_min, clip_max
                                )
                            last_prob = right_prob
                            current_label = np.argmax(right_preds, axis=1)[0]

                if self.targeted:
                    if desired_label == current_label:
                        term_flag = 1
                else:
                    if desired_label != current_label:
                        term_flag = 1

                nb_iter = nb_iter + 1

            if nb_iter < self.max_iter:
                logger.info(
                    "SimBA (%s) %s attack succeed", self.attack, ["non-targeted", "targeted"][int(self.targeted)]
                )
            else:
                logger.info(
                    "SimBA (%s) %s attack failed", self.attack, ["non-targeted", "targeted"][int(self.targeted)]
                )

            x_adv[i_sample] = x[i_sample]

        return x_adv

        Generate adversarial samples and return them in an array.

        :param x: An array with the original inputs to be attacked.
        :param y: An array with the true or target labels.
        :return: An array holding the adversarial examples.
        
art/attacks/evasion/simba.py