def abstract_forward(self, x_interval: np.ndarray) -> "torch.Tensor":
        """
        Do the forward pass through the NN with interval arithmetic.

        :param x_interval: data in interval form with shape:
        x_interval[batch_size, 2, feature_1, feature_2, ...] where axis=1 corresponds to the [lower, upper] bounds.
        :return: interval predictions
        """

        x = torch.from_numpy(x_interval.astype("float32")).to(self.device)

        for op_num, op in enumerate(self.ops):
            # as reshapes are not modules we infer when the reshape from convolutional to dense occurs
            if self.reshape_op_num == op_num:
                x = x.reshape((x.shape[0], 2, -1))
            x = op.forward(x)
        return x

        Do the forward pass through the NN with interval arithmetic.

        :param x_interval: data in interval form with shape:
        x_interval[batch_size, 2, feature_1, feature_2, ...] where axis=1 corresponds to the [lower, upper] bounds.
        :return: interval predictions
        
art/estimators/certification/interval/pytorch.py