def __new__(cls, label, shape=None, **kw_args): from sympy import MatrixBase, NDimArray if isinstance(label, string_types): label = Symbol(label) elif isinstance(label, Symbol): pass elif isinstance(label, (MatrixBase, NDimArray)): return label elif isinstance(label, Iterable): return _sympify(label) else: label = _sympify(label) if is_sequence(shape): shape = Tuple(*shape) elif shape is not None: shape = Tuple(shape) offset = kw_args.pop('offset', S.Zero) strides = kw_args.pop('strides', None) if shape is not None: obj = Expr.__new__(cls, label, shape) else: obj = Expr.__new__(cls, label) obj._shape = shape obj._offset = offset obj._strides = strides obj._name = str(label) return obj
def __new__(cls, base, *args, **kw_args): if not args: raise IndexException("Indexed needs at least one index") if isinstance(base, (basestring, Symbol)): base = IndexedBase(base) elif not isinstance(base, IndexedBase): raise TypeError("Indexed expects string, Symbol or IndexedBase as base") return Expr.__new__(cls, base, *args, **kw_args)
def __new__(cls, name, abbrev, **assumptions): obj = Expr.__new__(cls, **assumptions) assert isinstance(name, str),`type(name)` assert isinstance(abbrev, str),`type(abbrev)` obj.name = name obj.abbrev = abbrev return obj
def __new__(cls, e, z, z0, dir="+"): e = sympify(e) z = sympify(z) z0 = sympify(z0) obj = Expr.__new__(cls) obj._args = (e, z, z0, dir) return obj
def __new__(cls, function, *symbols, **assumptions): # Any embedded piecewise functions need to be brought out to the # top level so that integration can go into piecewise mode at the # earliest possible moment. function = piecewise_fold(sympify(function)) if function.is_Number: if function is S.NaN: return S.NaN elif function is S.Infinity: return S.Infinity elif function is S.NegativeInfinity: return S.NegativeInfinity if symbols: limits = [] for V in symbols: if isinstance(V, Symbol): limits.append(Tuple(V)) continue elif isinstance(V, (tuple, list, Tuple)): V = flatten(V) newsymbol = sympify(V[0]) if len(V) == 3: if isinstance(newsymbol, Symbol): nlim = map(sympify, V[1:]) if V[1] is None and V[2] is not None: nlim = [V[2]] if V[2] is None and V[1] is not None: function = -function nlim = [V[1]] if V[1] is None and V[2] is None: nlim = [] limits.append( Tuple(newsymbol, *nlim )) continue elif len(V) == 1 or (len(V) == 2 and V[1] is None): if isinstance(newsymbol, Symbol): limits.append(Tuple(newsymbol)) continue elif len(V) == 2: if isinstance(newsymbol, Symbol): limits.append(Tuple(newsymbol,V[1])) continue raise ValueError("Invalid integration variable or limits: %s" % str(symbols)) else: # no symbols provided -- let's compute full anti-derivative limits = [Tuple(symb) for symb in function.atoms(Symbol)] if not limits: return function obj = Expr.__new__(cls, **assumptions) arglist = [function] arglist.extend(limits) obj._args = tuple(arglist) return obj
def __new__(cls, function, *symbols, **assumptions): from sympy.integrals.integrals import _process_limits # Any embedded piecewise functions need to be brought out to the # top level so that integration can go into piecewise mode at the # earliest possible moment. function = piecewise_fold(sympify(function)) if function is S.NaN: return S.NaN if not symbols: raise ValueError("Summation variables must be given") limits, sign = _process_limits(*symbols) # Only limits with lower and upper bounds are supported; the indefinite Sum # is not supported if any(len(l) != 3 or None in l for l in limits): raise ValueError('Sum requires values for lower and upper bounds.') obj = Expr.__new__(cls, **assumptions) arglist = [sign*function] arglist.extend(limits) obj._args = tuple(arglist) return obj
def __new__(cls, label, range=None, **kw_args): from sympy.utilities.misc import filldedent if isinstance(label, basestring): label = Symbol(label, integer=True) label, range = map(sympify, (label, range)) if not label.is_integer: raise TypeError("Idx object requires an integer label.") elif is_sequence(range): if len(range) != 2: raise ValueError(filldedent(""" Idx range tuple must have length 2, but got %s""" % len(range))) for bound in range: if not (bound.is_integer or abs(bound) is S.Infinity): raise TypeError("Idx object requires integer bounds.") args = label, Tuple(*range) elif isinstance(range, Expr): if not (range.is_integer or range is S.Infinity): raise TypeError("Idx object requires an integer dimension.") args = label, Tuple(0, range - 1) elif range: raise TypeError(filldedent(""" The range must be an ordered iterable or integer SymPy expression.""")) else: args = label, obj = Expr.__new__(cls, *args, **kw_args) return obj
def __new__(cls, function, *symbols, **assumptions): # Any embedded piecewise functions need to be brought out to the # top level so that integration can go into piecewise mode at the # earliest possible moment. function = piecewise_fold(sympify(function)) if function is S.NaN: return S.NaN if symbols: limits, sign = _process_limits(*symbols) else: # no symbols provided -- let's compute full anti-derivative limits, sign = [Tuple(s) for s in function.free_symbols], 1 if len(limits) != 1: raise ValueError("specify integration variables to integrate %s" % function) while isinstance(function, Integral): # denest the integrand limits = list(function.limits) + limits function = function.function obj = Expr.__new__(cls, **assumptions) arglist = [sign*function] arglist.extend(limits) obj._args = tuple(arglist) obj.is_commutative = all(s.is_commutative for s in obj.free_symbols) return obj
def __new__(cls, term, *symbols, **assumptions): term = sympify(term) if term is S.NaN: return S.NaN if len(symbols) == 1: symbol = symbols[0] if isinstance(symbol, C.Equality): k = symbol.lhs a = symbol.rhs.start n = symbol.rhs.end elif is_sequence(symbol): k, a, n = symbol else: raise ValueError("Invalid arguments") k, a, n = map(sympify, (k, a, n)) else: raise NotImplementedError obj = Expr.__new__(cls, **assumptions) obj._args = (term, Tuple(k, a, n)) return obj
def __new__(cls, label, range=None, **kw_args): if isinstance(label, basestring): label = Symbol(label, integer=True) label, range = map(sympify, (label, range)) if not label.is_integer: raise TypeError("Idx object requires an integer label") elif is_sequence(range): assert len(range) == 2, "Idx got range tuple with wrong length" for bound in range: if not (bound.is_integer or abs(bound) is S.Infinity): raise TypeError("Idx object requires integer bounds") args = label, Tuple(*range) elif isinstance(range, Expr): if not (range.is_integer or range is S.Infinity): raise TypeError("Idx object requires an integer dimension") args = label, Tuple(S.Zero, range-S.One) elif range: raise TypeError("range must be ordered iterable or integer sympy expression") else: args = label, obj = Expr.__new__(cls, *args, **kw_args) return obj
def __new__(cls, arg): if hasattr(arg, 'adjoint'): obj = arg.adjoint() elif hasattr(arg, 'conjugate') and hasattr(arg, 'transpose'): obj = arg.conjugate().transpose() if obj is not None: return obj return Expr.__new__(cls, arg)
def __new__(cls, arg): if hasattr(arg, "adjoint"): obj = arg.adjoint() elif hasattr(arg, "conjugate") and hasattr(arg, "transpose"): obj = arg.conjugate().transpose() if obj is not None: return obj return Expr.__new__(cls, arg)
def _new(cls, poly, index): """Construct new ``RootOf`` object from raw data. """ obj = Expr.__new__(cls) obj.poly = poly obj.index = index return obj
def __new__(cls, label, shape=None, **kw_args): if isinstance(label, string_types): label = Symbol(label) elif isinstance(label, Symbol): pass else: raise TypeError("Base label should be a string or Symbol.") if is_sequence(shape): shape = Tuple(*shape) else: shape = sympify(shape) if shape is not None: obj = Expr.__new__(cls, label, shape, **kw_args) else: obj = Expr.__new__(cls, label, **kw_args) obj._shape = shape return obj
def __new__(cls, name, n, m): n, m = map(sympify, (n, m)) from sympy import MatrixBase if isinstance(name, (MatrixBase,)): if n.is_Integer and m.is_Integer: return name[n, m] name = sympify(name) obj = Expr.__new__(cls, name, n, m) return obj
def _new(cls, poly, func, auto=True): """Construct new raw ``RootSum`` instance. """ obj = Expr.__new__(cls) obj.poly = poly obj.fun = func obj.auto = auto return obj
def __new__(cls, label, shape=None, **kw_args): if isinstance(label, basestring): label = Symbol(label) obj = Expr.__new__(cls, label, **kw_args) if is_sequence(shape): obj._shape = Tuple(*shape) else: obj._shape = shape return obj
def __new__(cls, f, x=None): if not isinstance(f, Poly): f = Poly(f, x) elif x is not None: raise SymbolsError("Redundant symbols were given") if f.is_multivariate: raise ValueError('multivariate polynomial') return Expr.__new__(cls, f)
def __new__(cls, base, *args, **kw_args): if not args: raise IndexException("Indexed needs at least one index") if isinstance(base, (basestring, Symbol)): base = IndexedBase(base) elif not isinstance(base, IndexedBase): raise TypeError("Indexed expects string, Symbol or IndexedBase as base") # FIXME: 2.4 compatibility args = map(_ensure_Idx, args) # args = tuple([ a if isinstance(a, Idx) else Idx(a) for a in args ]) return Expr.__new__(cls, base, *args, **kw_args)
def __new__(cls, label, shape=None, **kw_args): if isinstance(label, string_types): label = Symbol(label) elif isinstance(label, Symbol): pass else: label = _sympify(label) if is_sequence(shape): shape = Tuple(*shape) elif shape is not None: shape = Tuple(shape) if shape is not None: obj = Expr.__new__(cls, label, shape, **kw_args) else: obj = Expr.__new__(cls, label, **kw_args) obj._shape = shape return obj
def __new__(cls, function, *symbols, **assumptions): # Any embedded piecewise functions need to be brought out to the # top level so that integration can go into piecewise mode at the # earliest possible moment. function = piecewise_fold(sympify(function)) if function is S.NaN: return S.NaN symbols = list(symbols) if not symbols: # no symbols provided -- let's compute full anti-derivative symbols = sorted(function.free_symbols, Basic.compare) if not symbols: raise ValueError('An integration variable is required.') while isinstance(function, Integral): # denest the integrand symbols = list(function.limits) + symbols function = function.function limits = [] for V in symbols: if isinstance(V, Symbol): limits.append(Tuple(V)) continue elif isinstance(V, (tuple, list, Tuple)): V = sympify(flatten(V)) if V[0].is_Symbol: newsymbol = V[0] if len(V) == 3: if V[1] is None and V[2] is not None: nlim = [V[2]] elif V[1] is not None and V[2] is None: function = -function nlim = [V[1]] elif V[1] is None and V[2] is None: nlim = [] else: nlim = V[1:] limits.append(Tuple(newsymbol, *nlim )) continue elif len(V) == 1 or (len(V) == 2 and V[1] is None): limits.append(Tuple(newsymbol)) continue elif len(V) == 2: limits.append(Tuple(newsymbol, V[1])) continue raise ValueError("Invalid integration variable or limits: %s" % str(symbols)) obj = Expr.__new__(cls, **assumptions) obj._args = tuple([function] + limits) obj.is_commutative = all(s.is_commutative for s in obj.free_symbols) return obj
def __new__(cls, name, n, m): n, m = map(_sympify, (n, m)) from sympy import MatrixBase if isinstance(name, (MatrixBase,)): if n.is_Integer and m.is_Integer: return name[n, m] if isinstance(name, string_types): name = Symbol(name) name = _sympify(name) obj = Expr.__new__(cls, name, n, m) return obj
def __new__(cls, base, *args, **kw_args): from sympy.utilities.misc import filldedent if not args: raise IndexException("Indexed needs at least one index.") if isinstance(base, (basestring, Symbol)): base = IndexedBase(base) elif not isinstance(base, IndexedBase): raise TypeError(filldedent(""" Indexed expects string, Symbol or IndexedBase as base.""")) return Expr.__new__(cls, base, *args, **kw_args)
def __new__(cls, label, shape=None, **kw_args): if not isinstance(label, (basestring, Symbol)): raise TypeError("Base label should be a string or Symbol.") label = sympify(label) obj = Expr.__new__(cls, label, **kw_args) if is_sequence(shape): obj._shape = Tuple(*shape) else: obj._shape = sympify(shape) return obj
def __new__(cls, f, *args, **flags): if not hasattr(f, '__call__'): raise TypeError("%s is not a callable object" % f) roots = RootsOf(*args) if not flags.get('evaluate', True): return Expr.__new__(cls, f, roots) else: if roots.count == 0: return S.Zero else: result = [] for root in roots.exact_roots(): result.append(f(root)) if len(result) < roots.count: result.append(Expr.__new__(cls, f, roots)) return Add(*result)
def __new__(cls, base, *args, **kw_args): from sympy.utilities.misc import filldedent if not args: raise IndexException("Indexed needs at least one index.") if isinstance(base, (string_types, Symbol)): base = IndexedBase(base) elif not hasattr(base, '__getitem__') and not isinstance(base, IndexedBase): raise TypeError(filldedent(""" Indexed expects string, Symbol, or IndexedBase as base.""")) args = list(map(sympify, args)) return Expr.__new__(cls, base, *args, **kw_args)
def __new__(cls, e, z, z0, dir="+"): e = sympify(e) z = sympify(z) z0 = sympify(z0) if isinstance(dir, basestring): dir = Symbol(dir) elif not isinstance(dir, Symbol): raise TypeError("direction must be of type basestring or Symbol, not %s" % type(dir)) if str(dir) not in ("+", "-"): raise ValueError("direction must be either '+' or '-', not %s" % dir) obj = Expr.__new__(cls) obj._args = (e, z, z0, dir) return obj
def __new__(cls, expr, *symbols, **assumptions): expr = sympify(expr).expand() if expr is S.NaN: return S.NaN if symbols: symbols = map(sympify, symbols) if not all(isinstance(s, Symbol) for s in symbols): raise NotImplementedError( 'Order at points other than 0 not supported.') else: symbols = list(expr.free_symbols) if expr.is_Order: new_symbols = list(expr.variables) for s in symbols: if s not in new_symbols: new_symbols.append(s) if len(new_symbols) == len(expr.variables): return expr symbols = new_symbols elif symbols: if expr.is_Add: lst = expr.extract_leading_order(*symbols) expr = Add(*[f.expr for (e, f) in lst]) elif expr: if len(symbols) > 1 or expr.is_commutative is False: # TODO # We cannot use compute_leading_term because that only # works in one symbol. expr = expr.as_leading_term(*symbols) else: expr = expr.compute_leading_term(symbols[0]) terms = expr.as_coeff_mul(*symbols)[1] s = set(symbols) expr = Mul(*[t for t in terms if s & t.free_symbols]) if expr is S.Zero: return expr elif not expr.has(*symbols): expr = S.One # create Order instance: symbols.sort(key=cmp_to_key(Basic.compare)) obj = Expr.__new__(cls, expr, *symbols, **assumptions) return obj
def _new(cls, poly, index): """Construct new ``CRootOf`` object from raw data. """ obj = Expr.__new__(cls) obj.poly = PurePoly(poly) obj.index = index try: _reals_cache[obj.poly] = _reals_cache[poly] _complexes_cache[obj.poly] = _complexes_cache[poly] except KeyError: pass return obj
def __new__(cls, function, argument, **kwargs): evaluate = kwargs.pop('evaluate', global_evaluate[0]) argument = repack_if_can(sympify(unpack_if_can(argument))) if not is_Function(function): raise TypeError('function is not a FunctionClass, Functor or Lambda: %s'%function) if evaluate: function, argument = Apply.reduce(function, argument) if function == Id: return argument else: return Expr.__new__(cls, function, argument, **kwargs)
def __new__(cls, expr, *symbols, **assumptions): expr = sympify(expr) if expr is S.NaN: return S.NaN if symbols: symbols = map(sympify, symbols) if not all(isinstance(s, Symbol) for s in symbols): raise NotImplementedError( 'Order at points other than 0 not supported.') else: symbols = list(expr.free_symbols) if expr.is_Order: v = set(expr.variables) symbols = v | set(symbols) if symbols == v: return expr symbols = list(symbols) elif symbols: symbols = list(set(symbols)) if len(symbols) > 1: # XXX: better way? We need this expand() to # workaround e.g: expr = x*(x + y). # (x*(x + y)).as_leading_term(x, y) currently returns # x*y (wrong order term!). That's why we want to deal with # expand()'ed expr (handled in "if expr.is_Add" branch below). expr = expr.expand() if expr.is_Add: lst = expr.extract_leading_order(*symbols) expr = Add(*[f.expr for (e, f) in lst]) elif expr: expr = expr.as_leading_term(*symbols) expr = expr.as_independent(*symbols, as_Add=False)[1] expr = expand_power_base(expr) expr = expand_log(expr) if len(symbols) == 1: # The definition of O(f(x)) symbol explicitly stated that # the argument of f(x) is irrelevant. That's why we can # combine some power exponents (only "on top" of the # expression tree for f(x)), e.g.: # x**p * (-x)**q -> x**(p+q) for real p, q. x = symbols[0] margs = list( Mul.make_args(expr.as_independent(x, as_Add=False)[1])) for i, t in enumerate(margs): if t.is_Pow: b, q = t.args if b in (x, -x) and q.is_real and not q.has(x): margs[i] = x**q elif b.is_Pow and not b.exp.has(x): b, r = b.args if b in (x, -x) and r.is_real: margs[i] = x**(r * q) elif b.is_Mul and b.args[0] is S.NegativeOne: b = -b if b.is_Pow and not b.exp.has(x): b, r = b.args if b in (x, -x) and r.is_real: margs[i] = x**(r * q) expr = Mul(*margs) if expr is S.Zero: return expr if not expr.has(*symbols): expr = S.One # create Order instance: symbols.sort(key=cmp_to_key(Basic.compare)) obj = Expr.__new__(cls, expr, *symbols, **assumptions) return obj
def __new__(cls, expr, *args, **kwargs): expr = sympify(expr) if not args: if expr.is_Order: variables = expr.variables point = expr.point else: variables = list(expr.free_symbols) point = [S.Zero] * len(variables) else: args = list(args if is_sequence(args) else [args]) variables, point = [], [] if is_sequence(args[0]): for a in args: v, p = list(map(sympify, a)) variables.append(v) point.append(p) else: variables = list(map(sympify, args)) point = [S.Zero] * len(variables) if not all(v.is_symbol for v in variables): raise TypeError('Variables are not symbols, got %s' % variables) if len(list(uniq(variables))) != len(variables): raise ValueError( 'Variables are supposed to be unique symbols, got %s' % variables) if expr.is_Order: expr_vp = dict(expr.args[1:]) new_vp = dict(expr_vp) vp = dict(zip(variables, point)) for v, p in vp.items(): if v in new_vp.keys(): if p != new_vp[v]: raise NotImplementedError( "Mixing Order at different points is not supported." ) else: new_vp[v] = p if set(expr_vp.keys()) == set(new_vp.keys()): return expr else: variables = list(new_vp.keys()) point = [new_vp[v] for v in variables] if expr is S.NaN: return S.NaN if any(x in p.free_symbols for x in variables for p in point): raise ValueError('Got %s as a point.' % point) if variables: if any(p != point[0] for p in point): raise NotImplementedError( "Multivariable orders at different points are not supported." ) if point[0] is S.Infinity: s = {k: 1 / Dummy() for k in variables} rs = {1 / v: 1 / k for k, v in s.items()} ps = [S.Zero for p in point] elif point[0] is S.NegativeInfinity: s = {k: -1 / Dummy() for k in variables} rs = {-1 / v: -1 / k for k, v in s.items()} ps = [S.Zero for p in point] elif point[0] is not S.Zero: s = {k: Dummy() + point[0] for k in variables} rs = {(v - point[0]).together(): k - point[0] for k, v in s.items()} ps = [S.Zero for p in point] else: s = () rs = () ps = list(point) expr = expr.subs(s) if expr.is_Add: expr = expr.factor() if s: args = tuple([r[0] for r in rs.items()]) else: args = tuple(variables) if len(variables) > 1: # XXX: better way? We need this expand() to # workaround e.g: expr = x*(x + y). # (x*(x + y)).as_leading_term(x, y) currently returns # x*y (wrong order term!). That's why we want to deal with # expand()'ed expr (handled in "if expr.is_Add" branch below). expr = expr.expand() old_expr = None while old_expr != expr: old_expr = expr if expr.is_Add: lst = expr.extract_leading_order(args) expr = Add(*[f.expr for (e, f) in lst]) elif expr: try: expr = expr.as_leading_term(*args) except PoleError: if isinstance(expr, Function) or\ all(isinstance(arg, Function) for arg in expr.args): # It is not possible to simplify an expression # containing only functions (which raise error on # call to leading term) further pass else: orders = [] pts = tuple(zip(args, ps)) for arg in expr.args: try: lt = arg.as_leading_term(*args) except PoleError: lt = arg if lt not in args: order = Order(lt) else: order = Order(lt, *pts) orders.append(order) if expr.is_Add: new_expr = Order(Add(*orders), *pts) if new_expr.is_Add: new_expr = Order( Add(*[a.expr for a in new_expr.args]), *pts) expr = new_expr.expr elif expr.is_Mul: expr = Mul(*[a.expr for a in orders]) elif expr.is_Pow: expr = orders[0].expr**orders[1].expr expr = expr.as_independent(*args, as_Add=False)[1] expr = expand_power_base(expr) expr = expand_log(expr) if len(args) == 1: # The definition of O(f(x)) symbol explicitly stated that # the argument of f(x) is irrelevant. That's why we can # combine some power exponents (only "on top" of the # expression tree for f(x)), e.g.: # x**p * (-x)**q -> x**(p+q) for real p, q. x = args[0] margs = list( Mul.make_args( expr.as_independent(x, as_Add=False)[1])) for i, t in enumerate(margs): if t.is_Pow: b, q = t.args if b in (x, -x) and q.is_real and not q.has(x): margs[i] = x**q elif b.is_Pow and not b.exp.has(x): b, r = b.args if b in (x, -x) and r.is_real: margs[i] = x**(r * q) elif b.is_Mul and b.args[0] is S.NegativeOne: b = -b if b.is_Pow and not b.exp.has(x): b, r = b.args if b in (x, -x) and r.is_real: margs[i] = x**(r * q) expr = Mul(*margs) expr = expr.subs(rs) if expr.is_Order: expr = expr.expr if not expr.has(*variables) and not expr.is_zero: expr = S.One # create Order instance: vp = dict(zip(variables, point)) variables.sort(key=default_sort_key) point = [vp[v] for v in variables] args = (expr, ) + Tuple(*zip(variables, point)) obj = Expr.__new__(cls, *args) return obj
def __new__(cls, function, *symbols, **assumptions): """Create an unevaluated integral. Arguments are an integrand followed by one or more limits. If no limits are given and there is only one free symbol in the expression, that symbol will be used, otherwise an error will be raised. >>> from sympy import Integral >>> from sympy.abc import x, y >>> Integral(x) Integral(x, x) >>> Integral(y) Integral(y, y) When limits are provided, they are interpreted as follows (using ``x`` as though it were the variable of integration): (x,) or x - indefinite integral (x, a) - "evaluate at" integral (x, a, b) - definite integral Although the same integral will be obtained from an indefinite integral and an "evaluate at" integral when ``a == x``, they respond differently to substitution: >>> i = Integral(x, x) >>> at = Integral(x, (x, x)) >>> i.doit() == at.doit() True >>> i.subs(x, 1) Integral(1, x) >>> at.subs(x, 1) Integral(x, (x, 1)) The ``as_dummy`` method can be used to see which symbols cannot be targeted by subs: those with a preppended underscore cannot be changed with ``subs``. (Also, the integration variables themselves -- the first element of a limit -- can never be changed by subs.) >>> i.as_dummy() Integral(x, x) >>> at.as_dummy() Integral(_x, (_x, x)) """ # Any embedded piecewise functions need to be brought out to the # top level so that integration can go into piecewise mode at the # earliest possible moment. function = piecewise_fold(sympify(function)) if function is S.NaN: return S.NaN if symbols: limits, sign = _process_limits(*symbols) else: # no symbols provided -- let's compute full anti-derivative free = function.free_symbols if len(free) != 1: raise ValueError("specify variables of integration for %s" % function) limits, sign = [Tuple(s) for s in free], 1 while isinstance(function, Integral): # denest the integrand limits = list(function.limits) + limits function = function.function obj = Expr.__new__(cls, **assumptions) arglist = [sign * function] arglist.extend(limits) obj._args = tuple(arglist) obj.is_commutative = all(s.is_commutative for s in obj.free_symbols) return obj
def __new__(cls, setarg): return Expr.__new__(cls, setarg)
def __new__(cls, expr, *args, **kwargs): expr = sympify(expr) if not args: if expr.is_Order: variables = expr.variables point = expr.point else: variables = list(expr.free_symbols) point = [S.Zero] * len(variables) else: args = list(args if is_sequence(args) else [args]) variables, point = [], [] if is_sequence(args[0]): for a in args: v, p = list(map(sympify, a)) variables.append(v) point.append(p) else: variables = list(map(sympify, args)) point = [S.Zero] * len(variables) if not all(isinstance(v, Symbol) for v in variables): raise TypeError('Variables are not symbols, got %s' % variables) if len(list(uniq(variables))) != len(variables): raise ValueError( 'Variables are supposed to be unique symbols, got %s' % variables) if expr.is_Order: expr_vp = dict(expr.args[1:]) new_vp = dict(expr_vp) vp = dict(zip(variables, point)) for v, p in vp.items(): if v in new_vp.keys(): if p != new_vp[v]: raise NotImplementedError( "Mixing Order at different points is not supported." ) else: new_vp[v] = p if set(expr_vp.keys()) == set(new_vp.keys()): return expr else: variables = list(new_vp.keys()) point = [new_vp[v] for v in variables] if expr is S.NaN: return S.NaN if any(x in p.free_symbols for x in variables for p in point): raise ValueError('Got %s as a point.' % point) if variables: if any(p != point[0] for p in point): raise NotImplementedError if point[0] is S.Infinity: s = dict([(k, 1 / Dummy()) for k in variables]) rs = dict([(1 / v, 1 / k) for k, v in s.items()]) elif point[0] is not S.Zero: s = dict((k, Dummy() + point[0]) for k in variables) rs = dict((v - point[0], k - point[0]) for k, v in s.items()) else: s = () rs = () expr = expr.subs(s) if expr.is_Add: from sympy import expand_multinomial expr = expand_multinomial(expr) if s: args = tuple([r[0] for r in rs.items()]) else: args = tuple(variables) if len(variables) > 1: # XXX: better way? We need this expand() to # workaround e.g: expr = x*(x + y). # (x*(x + y)).as_leading_term(x, y) currently returns # x*y (wrong order term!). That's why we want to deal with # expand()'ed expr (handled in "if expr.is_Add" branch below). expr = expr.expand() if expr.is_Add: lst = expr.extract_leading_order(args) expr = Add(*[f.expr for (e, f) in lst]) elif expr: expr = expr.as_leading_term(*args) expr = expr.as_independent(*args, as_Add=False)[1] expr = expand_power_base(expr) expr = expand_log(expr) if len(args) == 1: # The definition of O(f(x)) symbol explicitly stated that # the argument of f(x) is irrelevant. That's why we can # combine some power exponents (only "on top" of the # expression tree for f(x)), e.g.: # x**p * (-x)**q -> x**(p+q) for real p, q. x = args[0] margs = list( Mul.make_args(expr.as_independent(x, as_Add=False)[1])) for i, t in enumerate(margs): if t.is_Pow: b, q = t.args if b in (x, -x) and q.is_real and not q.has(x): margs[i] = x**q elif b.is_Pow and not b.exp.has(x): b, r = b.args if b in (x, -x) and r.is_real: margs[i] = x**(r * q) elif b.is_Mul and b.args[0] is S.NegativeOne: b = -b if b.is_Pow and not b.exp.has(x): b, r = b.args if b in (x, -x) and r.is_real: margs[i] = x**(r * q) expr = Mul(*margs) expr = expr.subs(rs) if expr is S.Zero: return expr if expr.is_Order: expr = expr.expr if not expr.has(*variables): expr = S.One # create Order instance: vp = dict(zip(variables, point)) variables.sort(key=default_sort_key) point = [vp[v] for v in variables] args = (expr, ) + Tuple(*zip(variables, point)) obj = Expr.__new__(cls, *args) return obj
def __new__(cls, expr, *symbols, **assumptions): expr = sympify(expr).expand() if expr is S.NaN: return S.NaN if symbols: symbols = map(sympify, symbols) else: symbols = list(expr.atoms(C.Symbol)) symbols.sort(Basic.compare) if expr.is_Order: new_symbols = list(expr.symbols) for s in symbols: if s not in new_symbols: new_symbols.append(s) if len(new_symbols)==len(expr.symbols): return expr symbols = new_symbols elif symbols: symbol_map = {} new_symbols = [] for s in symbols: if isinstance(s, C.Symbol): new_symbols.append(s) continue z = C.Symbol('z',dummy=True) x1,s1 = solve4linearsymbol(s, z) expr = expr.subs(x1,s1) symbol_map[z] = s new_symbols.append(z) if symbol_map: r = Order(expr, *new_symbols, **assumptions) expr = r.expr.subs(symbol_map) symbols = [] for s in r.symbols: if symbol_map.has_key(s): symbols.append(symbol_map[s]) else: symbols.append(s) else: if expr.is_Add: lst = expr.extract_leading_order(*symbols) expr = C.Add(*[f.expr for (e,f) in lst]) else: expr = expr.as_leading_term(*symbols) coeff, terms = expr.as_coeff_terms() if coeff is S.Zero: return coeff expr = C.Mul(*[t for t in terms if t.has(*symbols)]) elif expr is not S.Zero: expr = S.One if expr is S.Zero: return expr # create Order instance: obj = Expr.__new__(cls, expr, *symbols, **assumptions) return obj