Return a normalized expression transformed to its normal form in the
        given AND or OR operation.

        The new expression arguments will satisfy these conditions:
        - operation(*args) == expr (here mathematical equality is meant)
        - the operation does not occur in any of its arg.
        - NOT is only appearing in literals (aka. Negation normal form).

        The operation must be an AND or OR operation or a subclass.

def normalize(self, expr, operation):
        """
        Return a normalized expression transformed to its normal form in the
        given AND or OR operation.

        The new expression arguments will satisfy these conditions:
        - operation(*args) == expr (here mathematical equality is meant)
        - the operation does not occur in any of its arg.
        - NOT is only appearing in literals (aka. Negation normal form).

        The operation must be an AND or OR operation or a subclass.
        """
        # ensure that the operation is not NOT
        assert operation in (self.AND, self.OR,)
        # Move NOT inwards.
        expr = expr.literalize()
        # Simplify first otherwise _rdistributive() may take forever.
        expr = expr.simplify()
        operation_example = operation(self.TRUE, self.FALSE)
        expr = self._rdistributive(expr, operation_example)
        # Canonicalize
        expr = expr.simplify()
        return expr