def generate(self, x: np.ndarray, y: np.ndarray | None = None, **kwargs) -> np.ndarray:
        """
        Generate adversarial samples.

        :param x: An array with the original inputs to be attacked.
        :param y: Target values (class labels) one-hot-encoded of shape (nb_samples, nb_classes) or indices of shape
                  (nb_samples,). If `self.targeted` is true, then `y` represents the target labels.
        :return: The adversarial examples.
        """
        if y is not None:
            y = check_and_transform_label_format(y, nb_classes=self.estimator.nb_classes, return_one_hot=True)

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

        x_adv = x.copy()

        if y is None:
            # Throw error if attack is targeted, but no targets are provided
            if self.targeted:  # pragma: no cover
                raise ValueError("Target labels `y` need to be provided for a targeted attack.")

            # Use model predictions as correct outputs
            y = get_labels_np_array(self.estimator.predict(x, batch_size=self.batch_size))  # type: ignore

        # Get clip_min and clip_max from the classifier or infer them from data
        if self.estimator.clip_values is not None:
            self.clip_min, self.clip_max = self.estimator.clip_values
        else:
            self.clip_min, self.clip_max = np.min(x), np.max(x)

        # Check for square input images
        if (self.estimator.channels_first and x.shape[2] != x.shape[3]) or (  # pragma: no cover
            not self.estimator.channels_first and x.shape[1] != x.shape[2]
        ):
            raise ValueError("Input images `x` have to be square.")

        # Create or load DCT basis
        image_size = x.shape[2]
        logger.info("Create or load DCT basis.")
        path = f"2d_dct_basis_{self.sub_dim}_{image_size}.npy"
        if os.path.exists(path):
            self.sub_basis = np.load(path).astype(ART_NUMPY_DTYPE)
        else:
            self.sub_basis = self._generate_2d_dct_basis(sub_dim=self.sub_dim, res=image_size).astype(ART_NUMPY_DTYPE)
            np.save(path, self.sub_basis)

        for i in trange(x.shape[0], desc="GeoDA - samples", disable=not self.verbose, position=0):
            x_i = x[[i]]
            y_i = y[[i]]

            # Reset number of calls
            self.nb_calls = 0

            # Random search
            x_random = self._find_random_adversarial(x=x_i, y=y_i)
            logger.info("Random search adversarial example is adversarial: %r", self._is_adversarial(x_random, y_i))

            # Binary search
            x_boundary = self._binary_search(x_i, y_i, x_random, tol=self.bin_search_tol)
            logger.info("Binary search example at boundary is adversarial: %r", self._is_adversarial(x_boundary, y_i))

            grad = np.zeros_like(x_i)
            x_adv_i = x_i

            for k in trange(self.iterate, desc="GeoDA - steps", disable=not self.verbose, position=1):
                grad_oi, _ = self._black_grad_batch(x_boundary, self.q_opt_iter[k], self.batch_size, y_i)
                grad = grad_oi + grad
                x_adv_i = self._go_to_boundary(x_i, y_i, grad)
                x_adv_i = self._binary_search(x_i, y_i, x_adv_i, tol=self.bin_search_tol)
                x_boundary = x_adv_i

            x_adv_i = np.clip(x_adv_i, a_min=self.clip_min, a_max=self.clip_max)

            x_adv[i] = x_adv_i

        return x_adv

        Generate adversarial samples.

        :param x: An array with the original inputs to be attacked.
        :param y: Target values (class labels) one-hot-encoded of shape (nb_samples, nb_classes) or indices of shape
                  (nb_samples,). If `self.targeted` is true, then `y` represents the target labels.
        :return: The adversarial examples.
        
art/attacks/evasion/geometric_decision_based_attack.py