def forward(
        self, x: np.ndarray, column_pos: int | list | None = None, row_pos: int | list | None = None
    ) -> np.ndarray:
        """
        Performs ablation on the input x. If no column_pos is specified a random location will be selected.

        :param x: input batch.
        :param column_pos: int indicating the start column to retain across all samples in the batch
                           or list of ints of length equal to the number of samples to have a different
                           column retained per sample. If not supplied a random location will be selected.
                           NB, if row_ablation_mode is true then this will be used to act on the rows through
                           transposing the image.
        :param row_pos: Unused.
        :return: Batch ablated according to the locations in column_pos. Data is channel extended to indicate to a
                 model if a position is ablated.
        """
        if not self.channels_first:
            x = np.transpose(x, (0, 3, 1, 2))

        x = np.concatenate([x, 1.0 - x], axis=1)

        if column_pos is None:
            column_pos = random.randint(0, x.shape[3])

        if isinstance(column_pos, list):
            assert len(column_pos) == len(x)
            for i, pos in enumerate(column_pos):
                x[i : i + 1] = self.ablate(x[i : i + 1], pos)
        else:
            x = self.ablate(x, column_pos)

        if not self.channels_first:
            x = np.transpose(x, (0, 2, 3, 1))

        return x

        Performs ablation on the input x. If no column_pos is specified a random location will be selected.

        :param x: input batch.
        :param column_pos: int indicating the start column to retain across all samples in the batch
                           or list of ints of length equal to the number of samples to have a different
                           column retained per sample. If not supplied a random location will be selected.
                           NB, if row_ablation_mode is true then this will be used to act on the rows through
                           transposing the image.
        :param row_pos: Unused.
        :return: Batch ablated according to the locations in column_pos. Data is channel extended to indicate to a
                 model if a position is ablated.
        
art/estimators/certification/derandomized_smoothing/ablators/tensorflow.py