def test_deprecated_imports(): x = symbols('x') with warns_deprecated_sympy(): from sympy.core.basic import preorder_traversal preorder_traversal(x) with warns_deprecated_sympy(): from sympy.simplify.simplify import bottom_up bottom_up(x, lambda x: x) with warns_deprecated_sympy(): from sympy.simplify.simplify import walk walk(x, lambda x: x) with warns_deprecated_sympy(): from sympy.simplify.traversaltools import use use(x, lambda x: x) with warns_deprecated_sympy(): from sympy.utilities.iterables import postorder_traversal postorder_traversal(x) with warns_deprecated_sympy(): from sympy.utilities.iterables import interactive_traversal capture(lambda: interactive_traversal(x))
def _collapse_arguments(cls, args, **assumptions): """Remove redundant args. Examples ======== >>> from sympy import Min, Max >>> from sympy.abc import a, b, c, d, e Any arg in parent that appears in any parent-like function in any of the flat args of parent can be removed from that sub-arg: >>> Min(a, Max(b, Min(a, c, d))) Min(a, Max(b, Min(c, d))) If the arg of parent appears in an opposite-than parent function in any of the flat args of parent that function can be replaced with the arg: >>> Min(a, Max(b, Min(c, d, Max(a, e)))) Min(a, Max(b, Min(a, c, d))) """ from sympy.utilities.iterables import ordered from sympy.simplify.simplify import walk if not args: return args args = list(ordered(args)) if cls == Min: other = Max else: other = Min # find global comparable max of Max and min of Min if a new # value is being introduced in these args at position 0 of # the ordered args if args[0].is_number: sifted = mins, maxs = [], [] for i in args: for v in walk(i, Min, Max): if v.args[0].is_comparable: sifted[isinstance(v, Max)].append(v) small = Min.identity for i in mins: v = i.args[0] if v.is_number and (v < small) == True: small = v big = Max.identity for i in maxs: v = i.args[0] if v.is_number and (v > big) == True: big = v # at the point when this function is called from __new__, # there may be more than one numeric arg present since # local zeros have not been handled yet, so look through # more than the first arg if cls == Min: for i in range(len(args)): if not args[i].is_number: break if (args[i] < small) == True: small = args[i] elif cls == Max: for i in range(len(args)): if not args[i].is_number: break if (args[i] > big) == True: big = args[i] T = None if cls == Min: if small != Min.identity: other = Max T = small elif big != Max.identity: other = Min T = big if T is not None: # remove numerical redundancy for i in range(len(args)): a = args[i] if isinstance(a, other): a0 = a.args[0] if ((a0 > T) if other == Max else (a0 < T)) == True: args[i] = cls.identity # remove redundant symbolic args def do(ai, a): if not isinstance(ai, (Min, Max)): return ai cond = a in ai.args if not cond: return ai.func(*[do(i, a) for i in ai.args], evaluate=False) if isinstance(ai, cls): return ai.func(*[do(i, a) for i in ai.args if i != a], evaluate=False) return a for i, a in enumerate(args): args[i + 1:] = [do(ai, a) for ai in args[i + 1:]] # factor out common elements as for # Min(Max(x, y), Max(x, z)) -> Max(x, Min(y, z)) # and vice versa when swapping Min/Max -- do this only for the # easy case where all functions contain something in common; # trying to find some optimal subset of args to modify takes # too long if len(args) > 1: common = None remove = [] sets = [] for i in range(len(args)): a = args[i] if not isinstance(a, other): continue s = set(a.args) common = s if common is None else (common & s) if not common: break sets.append(s) remove.append(i) if common: sets = filter(None, [s - common for s in sets]) sets = [other(*s, evaluate=False) for s in sets] for i in reversed(remove): args.pop(i) oargs = [cls(*sets)] if sets else [] oargs.extend(common) args.append(other(*oargs, evaluate=False)) return args
def _collapse_arguments(cls, args, **assumptions): """Remove redundant args. Examples ======== >>> from sympy import Min, Max >>> from sympy.abc import a, b, c, d, e Any arg in parent that appears in any parent-like function in any of the flat args of parent can be removed from that sub-arg: >>> Min(a, Max(b, Min(a, c, d))) Min(a, Max(b, Min(c, d))) If the arg of parent appears in an opposite-than parent function in any of the flat args of parent that function can be replaced with the arg: >>> Min(a, Max(b, Min(c, d, Max(a, e)))) Min(a, Max(b, Min(a, c, d))) """ from sympy.simplify.simplify import walk if not args: return args args = list(ordered(args)) if cls == Min: other = Max else: other = Min # find global comparable max of Max and min of Min if a new # value is being introduced in these args at position 0 of # the ordered args if args[0].is_number: sifted = mins, maxs = [], [] for i in args: for v in walk(i, Min, Max): if v.args[0].is_comparable: sifted[isinstance(v, Max)].append(v) small = Min.identity for i in mins: v = i.args[0] if v.is_number and (v < small) == True: small = v big = Max.identity for i in maxs: v = i.args[0] if v.is_number and (v > big) == True: big = v # at the point when this function is called from __new__, # there may be more than one numeric arg present since # local zeros have not been handled yet, so look through # more than the first arg if cls == Min: for i in range(len(args)): if not args[i].is_number: break if (args[i] < small) == True: small = args[i] elif cls == Max: for i in range(len(args)): if not args[i].is_number: break if (args[i] > big) == True: big = args[i] T = None if cls == Min: if small != Min.identity: other = Max T = small elif big != Max.identity: other = Min T = big if T is not None: # remove numerical redundancy for i in range(len(args)): a = args[i] if isinstance(a, other): a0 = a.args[0] if ((a0 > T) if other == Max else (a0 < T)) == True: args[i] = cls.identity # remove redundant symbolic args def do(ai, a): if not isinstance(ai, (Min, Max)): return ai cond = a in ai.args if not cond: return ai.func(*[do(i, a) for i in ai.args], evaluate=False) if isinstance(ai, cls): return ai.func(*[do(i, a) for i in ai.args if i != a], evaluate=False) return a for i, a in enumerate(args): args[i + 1:] = [do(ai, a) for ai in args[i + 1:]] # factor out common elements as for # Min(Max(x, y), Max(x, z)) -> Max(x, Min(y, z)) # and vice versa when swapping Min/Max -- do this only for the # easy case where all functions contain something in common; # trying to find some optimal subset of args to modify takes # too long def factor_minmax(args): is_other = lambda arg: isinstance(arg, other) other_args, remaining_args = sift(args, is_other, binary=True) if not other_args: return args # Min(Max(x, y, z), Max(x, y, u, v)) -> {x,y}, ({z}, {u,v}) arg_sets = [set(arg.args) for arg in other_args] common = set.intersection(*arg_sets) if not common: return args new_other_args = list(common) arg_sets_diff = [arg_set - common for arg_set in arg_sets] # If any set is empty after removing common then all can be # discarded e.g. Min(Max(a, b, c), Max(a, b)) -> Max(a, b) if all(arg_sets_diff): other_args_diff = [ other(*s, evaluate=False) for s in arg_sets_diff ] new_other_args.append(cls(*other_args_diff, evaluate=False)) other_args_factored = other(*new_other_args, evaluate=False) return remaining_args + [other_args_factored] if len(args) > 1: args = factor_minmax(args) return args
def _collapse_arguments(cls, args, **assumptions): """Remove redundant args. Examples ======== >>> from sympy import Min, Max >>> from sympy.abc import a, b, c, d, e Any arg in parent that appears in any parent-like function in any of the flat args of parent can be removed from that sub-arg: >>> Min(a, Max(b, Min(a, c, d))) Min(a, Max(b, Min(c, d))) If the arg of parent appears in an opposite-than parent function in any of the flat args of parent that function can be replaced with the arg: >>> Min(a, Max(b, Min(c, d, Max(a, e)))) Min(a, Max(b, Min(a, c, d))) """ from sympy.utilities.iterables import ordered from sympy.simplify.simplify import walk if not args: return args args = list(ordered(args)) if cls == Min: other = Max else: other = Min # find global comparable max of Max and min of Min if a new # value is being introduced in these args at position 0 of # the ordered args if args[0].is_number: sifted = mins, maxs = [], [] for i in args: for v in walk(i, Min, Max): if v.args[0].is_comparable: sifted[isinstance(v, Max)].append(v) small = Min.identity for i in mins: v = i.args[0] if v.is_number and (v < small) == True: small = v big = Max.identity for i in maxs: v = i.args[0] if v.is_number and (v > big) == True: big = v # at the point when this function is called from __new__, # there may be more than one numeric arg present since # local zeros have not been handled yet, so look through # more than the first arg if cls == Min: for i in range(len(args)): if not args[i].is_number: break if (args[i] < small) == True: small = args[i] elif cls == Max: for i in range(len(args)): if not args[i].is_number: break if (args[i] > big) == True: big = args[i] T = None if cls == Min: if small != Min.identity: other = Max T = small elif big != Max.identity: other = Min T = big if T is not None: # remove numerical redundancy for i in range(len(args)): a = args[i] if isinstance(a, other): a0 = a.args[0] if ((a0 > T) if other == Max else (a0 < T)) == True: args[i] = cls.identity # remove redundant symbolic args def do(ai, a): if not isinstance(ai, (Min, Max)): return ai cond = a in ai.args if not cond: return ai.func(*[do(i, a) for i in ai.args], evaluate=False) if isinstance(ai, cls): return ai.func(*[do(i, a) for i in ai.args if i != a], evaluate=False) return a for i, a in enumerate(args): args[i + 1:] = [do(ai, a) for ai in args[i + 1:]] # factor out common elements as for # Min(Max(x, y), Max(x, z)) -> Max(x, Min(y, z)) # and vice versa when swapping Min/Max -- do this only for the # easy case where all functions contain something in common; # trying to find some optimal subset of args to modify takes # too long if len(args) > 1: common = None remove = [] sets = [] for i in range(len(args)): a = args[i] if not isinstance(a, other): continue s = set(a.args) common = s if common is None else (common & s) if not common: break sets.append(s) remove.append(i) if common: sets = filter(None, [s - common for s in sets]) sets = [other(*s, evaluate=False) for s in sets] for i in reversed(remove): args.pop(i) oargs = [cls(*sets)] if sets else [] oargs.extend(common) args.append(other(*oargs, evaluate=False)) return args