'Return a simplified intersection by applying rules.
We first start with global rules like
\'if any empty sets, return empty set\' and \'distribute unions\'.
Then we iterate through all pairs and ask the constituent sets if they
can simplify themselves with any other constituent'

@staticmethod
def reduce(args):

    from sympy.simplify.simplify import clear_coefficients
    if any((s.is_EmptySet for s in args)):
        return S.EmptySet
    rv = Intersection._handle_finite_sets(args)
    if (rv is not None):
        return rv
    for s in args:
        if s.is_Union:
            other_sets = (set(args) - set((s,)))
            if (len(other_sets) > 0):
                other = Intersection(other_sets)
                return Union((Intersection(arg, other) for arg in s.args))
            else:
                return Union((arg for arg in s.args))
    for s in args:
        if s.is_Complement:
            args.remove(s)
            other_sets = (args + [s.args[0]])
            return Complement(Intersection(*other_sets), s.args[1])
    args = set(args)
    new_args = True
    while new_args:
        for s in args:
            new_args = False
            for t in (args - set((s,))):
                new_set = s._intersect(t)
                if (new_set is not None):
                    new_args = (args - set((s, t))).union(set((new_set,)))
                    break
            if new_args:
                args = new_args
                break
    if (len(args) == 1):
        return args.pop()
    else:
        return Intersection(args, evaluate=False)
