def _eval_apply(cls, n): n = Basic.sympify(n) if isinstance(n, Basic.Number): if isinstance(n, Basic.Zero): return S.One elif isinstance(n, Basic.Integer): if n.is_negative: return S.Zero else: n, result = n.p, 1 if n < 20: for i in range(2, n+1): result *= i else: N, bits = n, 0 while N != 0: if N & 1 == 1: bits += 1 N = N >> 1 result = cls._recursive(n)*2**(n-bits) return Basic.Integer(result) if n.is_integer: if n.is_negative: return S.Zero else: return Basic.gamma(n+1)
def _eval_apply(self, arg): #XXX this doesn't work, but it should (see #390): #return arg**S.Half arg = Basic.sympify(arg) if isinstance(arg, Basic.Number): if isinstance(arg, Basic.NaN): return S.NaN if isinstance(arg, Basic.Infinity): return S.Infinity if isinstance(arg, Basic.NegativeInfinity): return S.ImaginaryUnit * S.Infinity if isinstance(arg, Basic.Rational): factors = arg.factors() sqrt_factors = {} eval_factors = {} n = Basic.Integer(1) for k,v in factors.items(): n *= Basic.Integer(k) ** (v//2) if v % 2: n *= Basic.Integer(k) ** S.Half return n return arg ** S.Half if arg.is_nonnegative: coeff, terms = arg.as_coeff_terms() if not isinstance(coeff, Basic.One): return self(coeff) * self(Basic.Mul(*terms)) base, exp = arg.as_base_exp() if isinstance(exp, Basic.Number): if exp == 2: return Basic.abs(base) return base ** (exp/2)
def intersection(self, o): if isinstance(o, Circle): dx,dy = o._c - self.center d = Basic.sqrt( simplify(dy**2 + dx**2) ) a = simplify((self.radius**2 - o.radius**2 + d**2) / (2*d)) x2 = self.center[0] + (dx * a/d) y2 = self.center[1] + (dy * a/d) h = Basic.sqrt( simplify(self.radius**2 - a**2) ) rx = -dy * (h/d) ry = dx * (h/d) xi_1 = simplify(x2 + rx) xi_2 = simplify(x2 - rx) yi_1 = simplify(y2 + ry) yi_2 = simplify(y2 - ry) ret = [Point(xi_1, yi_1)] if xi_1 != xi_2 or yi_1 != yi_2: ret.append(Point(xi_2, yi_2)) return ret elif isinstance(o, Ellipse): a, b, r = o.hradius, o.vradius, self.radius x = a*Basic.sqrt(simplify((r**2 - b**2)/(a**2 - b**2))) y = b*Basic.sqrt(simplify((a**2 - r**2)/(a**2 - b**2))) return list(set([Point(x,y), Point(x,-y), Point(-x,y), Point(-x,-y)])) return Ellipse.intersection(self, o)
def _eval_apply(cls, x, k): x = Basic.sympify(x) k = Basic.sympify(k) if isinstance(x, Basic.NaN): return S.NaN elif isinstance(k, Basic.Integer): if isinstance(k, Basic.NaN): return S.NaN elif isinstance(k, Basic.Zero): return S.One else: result = S.One if k.is_positive: if isinstance(x, Basic.Infinity): return S.Infinity elif isinstance(x, Basic.NegativeInfinity): if k.is_odd: return S.NegativeInfinity else: return S.Infinity else: return reduce(lambda r, i: r*(x-i), xrange(0, int(k)), 1) else: if isinstance(x, Basic.Infinity): return S.Infinity elif isinstance(x, Basic.NegativeInfinity): return S.Infinity else: return 1/reduce(lambda r, i: r*(x+i), xrange(1, abs(int(k))+1), 1)
def mrv_inflimit(expr, x, _cache = {}): if _cache.has_key((expr, x)): raise RuntimeError('Detected recursion while computing mrv_inflimit(%s, %s)' % (expr, x)) _cache[(expr, x)] = 1 expr_map = {} mrv_map = {} newexpr = mrv2(expr, x, expr_map, mrv_map) if mrv_map.has_key(x): t = Basic.Temporary(unbounded=True, positive=True) r = mrv_inflimit(expr.subs(Basic.log(x), t).subs(x, Basic.exp(t)).subs(t, x), x) del _cache[(expr, x)] return r w = Basic.Symbol('w_0',dummy=True, positive=True, infinitesimal=True) germ, new_mrv_map = rewrite_mrv_map(mrv_map, x, w) new_expr = rewrite_expr(newexpr, germ, new_mrv_map, w) lt = new_expr.as_leading_term(w) if germ is not None: lt = lt.subs(Basic.log(w), -germ[0]) c,e = lt.as_coeff_exponent(w) assert not c.has(w),`c` if e==0: r = c.inflimit(x) del _cache[(expr, x)] return r if e.is_positive: del _cache[(expr, x)] return S.Zero if e.is_negative: del _cache[(expr, x)] return Basic.sign(c) * S.Infinity raise RuntimeError('Failed to compute mrv_inflimit(%s, %s), got lt=%s' % (self, x, lt))
def __new__(cls, expr, x, xlim, direction='<', **assumptions): expr = Basic.sympify(expr) x = Basic.sympify(x) xlim = Basic.sympify(xlim) if not isinstance(x, Basic.Symbol): raise ValueError("Limit 2nd argument must be Symbol instance (got %s)" % (x)) assert isinstance(x, Basic.Symbol),`x` if not expr.has(x): return expr if isinstance(xlim, Basic.NegativeInfinity): xoo = InfLimit.limit_process_symbol() if expr.has(xoo): xoo = Basic.Symbol(x.name + '_oo',dummy=True,positive=True,unbounded=True) return InfLimit(expr.subs(x,-xoo), xoo) if isinstance(xlim, Basic.Infinity): return InfLimit(expr, x) else: xoo = InfLimit.limit_process_symbol() if expr.has(xoo): xoo = Basic.Symbol(x.name + '_oo',dummy=True,positive=True,unbounded=True) if direction=='<': return InfLimit(expr.subs(x, xlim+1/xoo), xoo) elif direction=='>': return InfLimit(expr.subs(x, xlim-1/xoo), xoo) else: raise ValueError("Limit direction must be < or > (got %s)" % (direction)) # XXX This code is currently unreachable obj = Basic.__new__(cls, expr, x, xlim, **assumptions) obj.direction = direction return obj
def subs(self, old, new): old = Basic.sympify(old) if old==self.func: arg = self[0] new = Basic.sympify(new) return new(arg.subs(old, new)) return self
def _eval_expand_complex(self, *args): if self[0].is_real: return self re, im = self[0].as_real_imag() denom = sinh(re)**2 + Basic.sin(im)**2 return (sinh(re)*cosh(re) - \ S.ImaginaryUnit*Basic.sin(im)*Basic.cos(im))/denom
def __new__(cls, *args): if len(args) == 2: low, high = args return Basic.__new__(cls, sympify(low), sympify(high)) elif len(args) == 0 or (len(args) == 1 and args[0] in (':', None)): return Basic.__new__(cls) # assumed shape else: raise ValueError("Expected 0 or 2 args (or one argument == None or ':')")
def vertices(self): Polygon.vertices.__doc__ points = [] c, r, n = self[:] v = 2*S.Pi/n for k in xrange(0, n): points.append( Point(c[0] + r*Basic.cos(k*v), c[1] + r*Basic.sin(k*v)) ) return points
def __new__(cls, center, hradius, vradius, **kwargs): hradius = Basic.sympify(hradius) vradius = Basic.sympify(vradius) if not isinstance(center, Point): raise TypeError("center must be be a Point") if hradius == vradius: return Circle(center, hradius, **kwargs) return GeometryEntity.__new__(cls, center, hradius, vradius, **kwargs)
def __new__(cls, *args, **kwargs): if isinstance(args[0], (tuple, list, set)): coords = tuple([Basic.sympify(x) for x in args[0]]) else: coords = tuple([Basic.sympify(x) for x in args]) if len(coords) != 2: raise NotImplementedError("Only two dimensional points currently supported") return GeometryEntity.__new__(cls, *coords)
def _eval_apply(cls, r, k): r, k = map(Basic.sympify, (r, k)) if isinstance(k, Basic.Number): if isinstance(k, Basic.Zero): return S.One elif isinstance(k, Basic.Integer): if k.is_negative: return S.Zero else: if isinstance(r, Basic.Integer) and r.is_nonnegative: r, k = int(r), int(k) if k > r: return S.Zero elif k > r / 2: k = r - k M, result = int(sqrt(r)), 1 for prime in sieve.primerange(2, r+1): if prime > r - k: result *= prime elif prime > r / 2: continue elif prime > M: if r % prime < k % prime: result *= prime else: R, K = r, k exp = a = 0 while R > 0: a = int((R % prime) < (K % prime + a)) R, K = R / prime, K / prime exp = a + exp if exp > 0: result *= prime**exp return Basic.Integer(result) else: result = r - k + 1 for i in xrange(2, k+1): result *= r-k+i result /= i return result if k.is_integer: if k.is_negative: return S.Zero else: return Basic.gamma(r+1)/(Basic.gamma(r-k+1)*Basic.gamma(k+1))
def __new__(cls, sym, condition, base_set=S.UniversalSet): # nonlinsolve uses ConditionSet to return an unsolved system # of equations (see _return_conditionset in solveset) so until # that is changed we do minimal checking of the args if isinstance(sym, (Tuple, tuple)): # unsolved eqns syntax sym = Tuple(*sym) condition = FiniteSet(*condition) return Basic.__new__(cls, sym, condition, base_set) condition = as_Boolean(condition) if isinstance(base_set, set): base_set = FiniteSet(*base_set) elif not isinstance(base_set, Set): raise TypeError('expecting set for base_set') if condition is S.false: return S.EmptySet if condition is S.true: return base_set if isinstance(base_set, EmptySet): return base_set know = None if isinstance(base_set, FiniteSet): sifted = sift( base_set, lambda _: fuzzy_bool( condition.subs(sym, _))) if sifted[None]: know = FiniteSet(*sifted[True]) base_set = FiniteSet(*sifted[None]) else: return FiniteSet(*sifted[True]) if isinstance(base_set, cls): s, c, base_set = base_set.args if sym == s: condition = And(condition, c) elif sym not in c.free_symbols: condition = And(condition, c.xreplace({s: sym})) elif s not in condition.free_symbols: condition = And(condition.xreplace({sym: s}), c) sym = s else: # user will have to use cls.sym to get symbol dum = Symbol('lambda') if dum in condition.free_symbols or \ dum in c.free_symbols: dum = Dummy(str(dum)) condition = And( condition.xreplace({sym: dum}), c.xreplace({s: dum})) sym = dum if not isinstance(sym, Symbol): s = Dummy('lambda') if s not in condition.xreplace({sym: s}).free_symbols: raise ValueError( 'non-symbol dummy not recognized in condition') rv = Basic.__new__(cls, sym, condition, base_set) return rv if know is None else Union(know, rv)
def __new__(cls, expr, x): expr = orig_expr = Basic.sympify(expr) orig_x = Basic.sympify(x) assert isinstance(orig_x,Basic.Symbol),`orig_x` # handle trivial results if orig_expr==orig_x: return S.Infinity elif not orig_expr.has(orig_x): return orig_expr x = InfLimit.limit_process_symbol() if not orig_expr.has(x): expr = orig_expr.subs(orig_x, x) elif orig_x==x: expr = orig_expr else: x = Basic.Symbol(orig_x.name + '_oo', dummy=True, unbounded=True, positive=True) expr = orig_expr.subs(orig_x, x) result = None if hasattr(expr,'_eval_inflimit'): # support for callbacks result = getattr(expr,'_eval_inflimit')(x) elif isinstance(expr, Basic.Add): result, factors = expr.as_coeff_factors(x) for f in factors: result += f.inflimit(x) if isinstance(result, Basic.NaN): result = None break elif isinstance(expr, Basic.Mul): result, terms = expr.as_coeff_terms(x) for t in terms: result *= t.inflimit(x) if isinstance(result, Basic.NaN): result = None break elif isinstance(expr, Basic.Pow): if not expr.exp.has(x): result = expr.base.inflimit(x) ** expr.exp elif not expr.base.has(x): result = expr.base ** expr.exp.inflimit(x) else: result = Basic.exp(expr.exp * Basic.log(expr.base)).inflimit(x) elif isinstance(expr, Basic.Function): # warning: assume that # lim_x f(g1(x),g2(x),..) = f(lim_x g1(x), lim_x g2(x)) # if this is incorrect, one must define f._eval_inflimit(x) method result = expr.func(*[a.inflimit(x) for a in expr]) if result is None: result = mrv_inflimit(expr, x) return result
def taylor_term(self, n, x, *previous_terms): if n < 0 or n % 2 == 0: return S.Zero else: x = Basic.sympify(x) a, b = ((n-1)//2), 2**(n+1) B = Basic.bernoulli(n+1) F = Basic.Factorial(n+1) return (-1)**a * b*(b-1) * B/F * x**n
def taylor_term(self, n, x, *previous_terms): if n == 0: return 1 / Basic.sympify(x) elif n < 0 or n % 2 == 0: return S.Zero else: x = Basic.sympify(x) B = S.Bernoulli(n+1) F = Basic.Factorial(n+1) return 2**(n+1) * B/F * x**n
def taylor_term(self, n, x, *previous_terms): if n < 0 or n % 2 == 0: return S.Zero else: x = Basic.sympify(x) k = (n - 1)/2 if len(previous_terms) > 2: return -previous_terms[-2] * x**2 * (n-2)/(n*k) else: return 2*(-1)**k * x**n/(n*Basic.Factorial(k)*Basic.sqrt(S.Pi))
def _eval_apply(self, arg, base=None, **fixme): if base is not None: base = Basic.sympify(base) if not isinstance(base, Basic.Exp1): return self(arg)/self(base) arg = Basic.sympify(arg) if isinstance(arg, Basic.Number): if isinstance(arg, Basic.Zero): return S.NegativeInfinity elif isinstance(arg, Basic.One): return S.Zero elif isinstance(arg, Basic.Infinity): return S.Infinity elif isinstance(arg, Basic.NegativeInfinity): return S.Infinity elif isinstance(arg, Basic.NaN): return S.NaN elif arg.is_negative: return S.Pi * S.ImaginaryUnit + self(-arg) elif isinstance(arg, Basic.Exp1): return S.One #this doesn't work due to caching: :( #elif isinstance(arg, exp) and arg[0].is_real: #using this one instead: elif isinstance(arg, exp): return arg[0] #this shouldn't happen automatically (see the issue 252): #elif isinstance(arg, Basic.Pow): # if isinstance(arg.exp, Basic.Number) or \ # isinstance(arg.exp, Basic.NumberSymbol) or arg.exp.is_number: # return arg.exp * self(arg.base) #elif isinstance(arg, Basic.Mul) and arg.is_real: # return Basic.Add(*[self(a) for a in arg]) elif not isinstance(arg, Basic.Add): coeff = arg.as_coefficient(S.ImaginaryUnit) if coeff is not None: if isinstance(coeff, Basic.Infinity): return S.Infinity elif isinstance(coeff, Basic.NegativeInfinity): return S.Infinity elif isinstance(coeff, Basic.Rational): if coeff.is_nonnegative: return S.Pi * S.ImaginaryUnit * S.Half + self(coeff) else: return -S.Pi * S.ImaginaryUnit * S.Half + self(-coeff)
def __new__(cls, sym, condition, base_set): if condition == S.false: return S.EmptySet if condition == S.true: return base_set if isinstance(base_set, EmptySet): return base_set if isinstance(base_set, FiniteSet): sifted = sift(base_set, lambda _: fuzzy_bool(condition.subs(sym, _))) if sifted[None]: return Union(FiniteSet(*sifted[True]), Basic.__new__(cls, sym, condition, FiniteSet(*sifted[None]))) else: return FiniteSet(*sifted[True]) return Basic.__new__(cls, sym, condition, base_set)
def __new__(cls, *args, **kwargs): evaluate = kwargs.get("evaluate", True) # flatten inputs to merge intersections and iterables args = list(args) def flatten(arg): if isinstance(arg, Set): if arg.is_Intersection: return sum(map(flatten, arg.args), []) else: return [arg] if iterable(arg): # and not isinstance(arg, Set) (implicit) return sum(map(flatten, arg), []) raise TypeError("Input must be Sets or iterables of Sets") args = flatten(args) # Intersection of no sets is everything if len(args) == 0: return S.UniversalSet args = sorted(args, key=set_sort_fn) # Reduce sets using known rules if evaluate: return Intersection.reduce(args) return Basic.__new__(cls, *args)
def __new__(cls, *args, **kwargs): evaluate = kwargs.get('evaluate', global_evaluate[0]) # flatten inputs to merge intersections and iterables args = list(args) def flatten(arg): if isinstance(arg, Set): if arg.is_Intersection: return sum(map(flatten, arg.args), []) else: return [arg] if iterable(arg): # and not isinstance(arg, Set) (implicit) return sum(map(flatten, arg), []) raise TypeError("Input must be Sets or iterables of Sets") args = flatten(args) if len(args) == 0: raise TypeError("Intersection expected at least one argument") # Reduce sets using known rules if evaluate: return Intersection.reduce(args) args = list(ordered(args, Set._infimum_key)) return Basic.__new__(cls, *args)
def __new__(cls, start, end, left_open=False, right_open=False): start = _sympify(start) end = _sympify(end) # Only allow real intervals (use symbols with 'is_real=True'). if not start.is_real or not end.is_real: raise ValueError("Only real intervals are supported") # Make sure that the created interval will be valid. if end.is_comparable and start.is_comparable: if end < start: return S.EmptySet if end == start and (left_open or right_open): return S.EmptySet if end == start and not (left_open or right_open): return FiniteSet(end) # Make sure infinite interval end points are open. if start == S.NegativeInfinity: left_open = True if end == S.Infinity: right_open = True return Basic.__new__(cls, start, end, left_open, right_open)
def __new__(cls, *args, **kwargs): evaluate = kwargs.get("evaluate", global_evaluate[0]) # flatten inputs args = list(args) # adapted from sympy.sets.sets.Union def _flatten(arg): if isinstance(arg, SeqBase): if isinstance(arg, SeqMul): return sum(map(_flatten, arg.args), []) else: return [arg] elif iterable(arg): return sum(map(_flatten, arg), []) raise TypeError("Input must be Sequences or " " iterables of Sequences") args = _flatten(args) # Multiplication of no sequences is EmptySequence if not args: return S.EmptySequence if Intersection(a.interval for a in args) is S.EmptySet: return S.EmptySequence # reduce using known rules if evaluate: return SeqMul.reduce(args) args = list(ordered(args, SeqBase._start_key)) return Basic.__new__(cls, *args)
def __new__(cls, start, end, left_open=False, right_open=False): start = _sympify(start) end = _sympify(end) left_open = _sympify(left_open) right_open = _sympify(right_open) if not all(isinstance(a, (type(true), type(false))) for a in [left_open, right_open]): raise NotImplementedError( "left_open and right_open can have only true/false values, " "got %s and %s" % (left_open, right_open)) inftys = [S.Infinity, S.NegativeInfinity] # Only allow real intervals (use symbols with 'is_real=True'). if not (start.is_real or start in inftys) or not (end.is_real or end in inftys): raise ValueError("Only real intervals are supported") # Make sure that the created interval will be valid. if end.is_comparable and start.is_comparable: if end < start: return S.EmptySet if end == start and (left_open or right_open): return S.EmptySet if end == start and not (left_open or right_open): return FiniteSet(end) # Make sure infinite interval end points are open. if start == S.NegativeInfinity: left_open = true if end == S.Infinity: right_open = true return Basic.__new__(cls, start, end, left_open, right_open)
def matrixify(expr): """ Recursively walks down an expression tree changing Expr's to MatExpr's i.e. Add -> MatAdd Mul -> MatMul Only changes those Exprs which contain MatrixSymbols This function is useful when traditional SymPy functions which use Mul and Add are called on MatrixExpressions. Examples flatten, expand, simplify... Calling matrixify after calling these functions will reset classes back to their matrix equivalents """ class_dict = {Mul:MatMul, Add:MatAdd, MatMul:MatMul, MatAdd:MatAdd, Pow:MatPow, MatPow:MatPow} if expr.__class__ not in class_dict: return expr args = map(matrixify, expr.args) # Recursively call down the tree if not any(arg.is_Matrix for arg in args): return expr else: return Basic.__new__(class_dict[expr.__class__], *args)
def __new__(cls, periodical, limits=None): x, start, stop = None, None, None if limits is None: x, start, stop = Dummy("k"), 0, S.Infinity if is_sequence(limits, Tuple): if len(limits) == 3: x, start, stop = limits elif len(limits) == 2: x = Dummy("k") start, stop = limits if not isinstance(x, Symbol) or start is None or stop is None: raise ValueError("Invalid limits given: %s" % str(limits)) if start is S.NegativeInfinity and stop is S.Infinity: raise ValueError("Both the start and end value" " cannot be unbounded") limits = sympify((x, start, stop)) if is_sequence(periodical, Tuple): periodical = sympify(tuple(flatten(periodical))) else: raise ValueError("invalid period %s should be something " "like e.g (1, 2) " % periodical) if Interval(limits[1], limits[2]) is S.EmptySet: return S.EmptySequence return Basic.__new__(cls, periodical, limits)
def eval(cls, *args): """ Logical implication. Accepts two Boolean arguments; A and B. Returns False if A is True and B is False Returns True otherwise. Examples ======== >>> from sympy.logic.boolalg import Implies >>> Implies(True, False) False >>> Implies(False, False) True >>> Implies(True, True) True >>> Implies(False, True) True """ try: A, B = args except ValueError: raise ValueError( "%d operand(s) used for an Implies " "(pairs are required): %s" % (len(args), str(args))) if A is True or A is False or B is True or B is False: return Or(Not(A), B) else: return Basic.__new__(cls, *args)
def eval(cls, *args): """ Equivalence relation. Returns True if all of the arguments are logically equivalent. Returns False otherwise. Examples ======== >>> from sympy.logic.boolalg import Equivalent, And >>> from sympy.abc import x >>> Equivalent(False, False, False) True >>> Equivalent(True, False, False) False >>> Equivalent(x, And(x, True)) True """ argset = set(args) if len(argset) <= 1: return True if True in argset: argset.discard(True) return And(*argset) if False in argset: argset.discard(False) return Nor(*argset) return Basic.__new__(cls, *set(args))
def __new__(cls, *args): from sympy.functions.elementary.integers import ceiling # expand range slc = slice(*args) start, stop, step = slc.start or 0, slc.stop, slc.step or 1 try: start, stop, step = [w if w in [S.NegativeInfinity, S.Infinity] else S(as_int(w)) for w in (start, stop, step)] except ValueError: raise ValueError("Inputs to Range must be Integer Valued\n" + "Use ImageSets of Ranges for other cases") if not step.is_finite: raise ValueError("Infinite step is not allowed") if start == stop: return S.EmptySet n = ceiling((stop - start)/step) if n <= 0: return S.EmptySet # normalize args: regardless of how they are entered they will show # canonically as Range(inf, sup, step) with step > 0 if n.is_finite: start, stop = sorted((start, start + (n - 1)*step)) else: start, stop = sorted((start, stop - step)) step = abs(step) if (start, stop) == (S.NegativeInfinity, S.Infinity): raise ValueError("Both the start and end value of " "Range cannot be unbounded") else: return Basic.__new__(cls, start, stop + step, step)
def test_subs(): assert b21.subs(b2, b1) == Basic(b1, b1) assert b21.subs(b2, b21) == Basic(b21, b1) assert b3.subs(b2, b1) == b2 assert b21.subs([(b2, b1), (b1, b2)]) == Basic(b2, b2) assert b21.subs({b1: b2, b2: b1}) == Basic(b2, b2) if sys.version_info >= (3, 4): assert b21.subs(collections.ChainMap({b1: b2}, {b2: b1})) == Basic(b2, b2) assert b21.subs(collections.OrderedDict([(b2, b1), (b1, b2)])) == Basic(b2, b2) raises(ValueError, lambda: b21.subs('bad arg')) raises(ValueError, lambda: b21.subs(b1, b2, b3))
def __new__(cls, *args): from sympy.functions.elementary.integers import ceiling if len(args) == 1: if isinstance(args[0], range if PY3 else xrange): args = args[0].__reduce__()[1] # use pickle method # expand range slc = slice(*args) start, stop, step = slc.start or 0, slc.stop, slc.step or 1 try: start, stop, step = [ w if w in [S.NegativeInfinity, S.Infinity] else sympify( as_int(w)) for w in (start, stop, step) ] except ValueError: raise ValueError("Inputs to Range must be Integer Valued\n" + "Use ImageSets of Ranges for other cases") if not step.is_finite: raise ValueError("Infinite step is not allowed") if start == stop: return S.EmptySet n = ceiling((stop - start) / step) if n <= 0: return S.EmptySet # normalize args: regardless of how they are entered they will show # canonically as Range(inf, sup, step) with step > 0 if n.is_finite: start, stop = sorted((start, start + (n - 1) * step)) else: start, stop = sorted((start, stop - step)) step = abs(step) if (start, stop) == (S.NegativeInfinity, S.Infinity): raise ValueError("Both the start and end value of " "Range cannot be unbounded") else: return Basic.__new__(cls, start, stop + step, step)
def test_preorder_traversal(): expr = Basic(b21, b3) assert list( preorder_traversal(expr)) == [expr, b21, b2, b1, b1, b3, b2, b1] assert list(preorder_traversal( ('abc', ('d', 'ef')))) == [('abc', ('d', 'ef')), 'abc', ('d', 'ef'), 'd', 'ef'] result = [] pt = preorder_traversal(expr) for i in pt: result.append(i) if i == b2: pt.skip() assert result == [expr, b21, b2, b1, b3, b2] w, x, y, z = symbols('w:z') expr = z + w * (x + y) assert list(preorder_traversal([expr], keys=default_sort_key)) == \ [[w*(x + y) + z], w*(x + y) + z, z, w*(x + y), w, x + y, x, y] assert list(preorder_traversal((x + y)*z, keys=True)) == \ [z*(x + y), z, x + y, x, y]
def __new__(cls, periodical, limits=None): periodical = sympify(periodical) def _find_x(periodical): free = periodical.free_symbols if len(periodical.free_symbols) == 1: return free.pop() else: return Dummy('k') x, start, stop = None, None, None if limits is None: x, start, stop = _find_x(periodical), 0, S.Infinity if is_sequence(limits, Tuple): if len(limits) == 3: x, start, stop = limits elif len(limits) == 2: x = _find_x(periodical) start, stop = limits if not isinstance(x, (Symbol, Idx)) or start is None or stop is None: raise ValueError('Invalid limits given: %s' % str(limits)) if start is S.NegativeInfinity and stop is S.Infinity: raise ValueError("Both the start and end value" "cannot be unbounded") limits = sympify((x, start, stop)) if is_sequence(periodical, Tuple): periodical = sympify(tuple(flatten(periodical))) else: raise ValueError("invalid period %s should be something " "like e.g (1, 2) " % periodical) if Interval(limits[1], limits[2]) is S.EmptySet: return S.EmptySequence return Basic.__new__(cls, periodical, limits)
def test_Singleton(): global instantiated instantiated = 0 class MySingleton(with_metaclass(Singleton, Basic)): def __new__(cls): global instantiated instantiated += 1 return Basic.__new__(cls) assert instantiated == 1 assert MySingleton() is not Basic() assert MySingleton() is MySingleton() assert S.MySingleton is MySingleton() assert instantiated == 1 class MySingleton_sub(MySingleton): pass assert instantiated == 2 assert MySingleton_sub() is not MySingleton() assert MySingleton_sub() is MySingleton_sub()
def test_preorder_traversal(): expr = Basic(b21, b3) assert list( preorder_traversal(expr)) == [expr, b21, b2, b1, b1, b3, b2, b1] assert list(preorder_traversal(("abc", ("d", "ef")))) == [ ("abc", ("d", "ef")), "abc", ("d", "ef"), "d", "ef", ] result = [] pt = preorder_traversal(expr) for i in pt: result.append(i) if i == b2: pt.skip() assert result == [expr, b21, b2, b1, b3, b2] w, x, y, z = symbols("w:z") expr = z + w * (x + y) assert list(preorder_traversal([expr], keys=default_sort_key)) == [ [w * (x + y) + z], w * (x + y) + z, z, w * (x + y), w, x + y, x, y, ] assert list(preorder_traversal((x + y) * z, keys=True)) == [ z * (x + y), z, x + y, x, y, ]
def test_Singleton(): global instanciated instanciated = 0 class MySingleton(Basic): __metaclass__ = Singleton def __new__(cls): global instanciated instanciated += 1 return Basic.__new__(cls) assert instanciated == 1 assert MySingleton() is not Basic() assert MySingleton() is MySingleton() assert S.MySingleton is MySingleton() assert instanciated == 1 class MySingleton_sub(MySingleton): pass assert instanciated == 2 assert MySingleton_sub() is not MySingleton() assert MySingleton_sub() is MySingleton_sub()
def _eval_expand_mul(self, **hints): from sympy import fraction, expand_mul # Handle things like 1/(x*(x + 1)), which are automatically converted # to 1/x*1/(x + 1) expr = self n, d = fraction(expr) if d.is_Mul: expr = n/d._eval_expand_mul(**hints) if not expr.is_Mul: return expand_mul(expr, deep=False) plain, sums, rewrite = [], [], False for factor in expr.args: if factor.is_Add: sums.append(factor) rewrite = True else: if factor.is_commutative: plain.append(factor) else: sums.append(Basic(factor)) # Wrapper if not rewrite: return expr else: plain = Mul(*plain) if sums: terms = Mul._expandsums(sums) args = [] for term in terms: t = Mul(plain, term) if t.is_Mul and any(a.is_Add for a in t.args): t = t._eval_expand_mul() args.append(t) return Add(*args) else: return plain
def __new__(cls, formula, limits=None): formula = sympify(formula) def _find_x(formula): free = formula.free_symbols if len(free) == 1: return free.pop() elif not free: return Dummy('k') else: raise ValueError( " specify dummy variables for %s. If the formula contains" " more than one free symbol, a dummy variable should be" " supplied explicitly e.g., SeqFormula(m*n**2, (n, 0, 5))" % formula) x, start, stop = None, None, None if limits is None: x, start, stop = _find_x(formula), 0, S.Infinity if is_sequence(limits, Tuple): if len(limits) == 3: x, start, stop = limits elif len(limits) == 2: x = _find_x(formula) start, stop = limits if not isinstance(x, (Symbol, Idx)) or start is None or stop is None: raise ValueError('Invalid limits given: %s' % str(limits)) if start is S.NegativeInfinity and stop is S.Infinity: raise ValueError("Both the start and end value " "cannot be unbounded") limits = sympify((x, start, stop)) if Interval(limits[1], limits[2]) is S.EmptySet: return S.EmptySequence return Basic.__new__(cls, formula, limits)
def __new__(cls, name, args, body, results): # name if isinstance(name, str): name = Symbol(name) elif not isinstance(name, Symbol): raise TypeError("Function name must be Symbol or string") # args if not iterable(args): raise TypeError("args must be an iterable") if not all(isinstance(a, Argument) for a in args): raise TypeError("All args must be of type Argument") args = Tuple(*args) # body if not iterable(body): raise TypeError("body must be an iterable") body = Tuple(*(_sympify(i) for i in body)) # results if not iterable(results): raise TypeError("results must be an iterable") if not all(isinstance(i, Result) for i in results): raise TypeError("All results must be of type Result") results = Tuple(*results) return Basic.__new__(cls, name, args, body, results)
def multiplies_var(main_var: basic.Basic, arb_var: basic.Basic, expr: basic.Basic) -> bool: """ This function takes in the following parameters: main_var [sympy.core.basic.Basic]: the main variable arb_var [sympy.core.basic.Basic]: an arbitrary variable expr [sympy.core.basic.Basic]: an algebraic expression Check to see if an arbitrary variable multiplies a sub expression that contains the main variable. If it does, return True else False. """ arg_list = [] for arg1 in expr.args: if arg1.has(main_var): arg_list.append(arg1) for arg2 in expr.args: if ((arg2 is arb_var or (arg2.is_Pow and arg2.has(arb_var))) and expr.has(arg1 * arg2)): return True return any([ multiplies_var(main_var, arb_var, arg) for arg in arg_list if (arg is not main_var) ])
def __new__(cls, expr, *diagonal_indices): expr = _sympify(expr) diagonal_indices = [Tuple(*sorted(i)) for i in diagonal_indices] if isinstance(expr, CodegenArrayDiagonal): return cls._flatten(expr, *diagonal_indices) obj = Basic.__new__(cls, expr, *diagonal_indices) obj._subranks = _get_subranks(expr) shape = expr.shape if shape is None: obj._shape = None else: # Check that no diagonalization happens on indices with mismatched # dimensions: for i in diagonal_indices: if len(set(shape[j] for j in i)) != 1: raise ValueError( "contracting indices of different dimensions") # Get new shape: shp1 = tuple(shp for i, shp in enumerate(shape) if not any(i in j for j in diagonal_indices)) shp2 = tuple(shape[i[0]] for i in diagonal_indices) obj._shape = shp1 + shp2 return obj
def __new__(cls, expr, *contraction_indices, **kwargs): contraction_indices = _sort_contraction_indices(contraction_indices) expr = _sympify(expr) if isinstance(expr, CodegenArrayContraction): return cls._flatten(expr, *contraction_indices) obj = Basic.__new__(cls, expr, *contraction_indices) obj._subranks = _get_subranks(expr) obj._mapping = _get_mapping_from_subranks(obj._subranks) free_indices_to_position = {i: i for i in range(sum(obj._subranks)) if all([i not in cind for cind in contraction_indices])} obj._free_indices_to_position = free_indices_to_position shape = expr.shape if shape: # Check that no contraction happens when the shape is mismatched: for i in contraction_indices: if len(set(shape[j] for j in i)) != 1: raise ValueError("contracting indices of different dimensions") shape = tuple(shp for i, shp in enumerate(shape) if not any(i in j for j in contraction_indices)) obj._shape = shape return obj
def __new__(cls, *args): def flatten(arg): if is_flattenable(arg): return sum(map(flatten, arg), []) return [arg] args = flatten(list(args)) args = map(sympify, args) if len(args) == 0: return EmptySet() try: if all([arg.is_real and arg.is_number for arg in args]): cls = RealFiniteSet except AttributeError: pass elements = frozenset(args) obj = Basic.__new__(cls, elements) obj.elements = elements return obj
def eval(cls, *args): """ Equivalence relation. Returns True if all of the arguments are logically equivalent. Returns False otherwise. Examples ======== >>> from sympy.logic.boolalg import Equivalent, And >>> from sympy.abc import x >>> Equivalent(False, False, False) True >>> Equivalent(True, False, False) False >>> Equivalent(x, And(x, True)) True """ newargs = [] for x in args: if isinstance(x, Number) or x in (0, 1): newargs.append(True if x else False) else: newargs.append(x) argset = set(newargs) if len(argset) <= 1: return True if True in argset: argset.discard(True) return And(*argset) if False in argset: argset.discard(False) return Nor(*argset) return Basic.__new__(cls, *set(args))
def eval(cls, *args): """ Logical implication. Accepts two Boolean arguments; A and B. Returns False if A is True and B is False Returns True otherwise. Examples ======== >>> from sympy.logic.boolalg import Implies >>> Implies(True, False) False >>> Implies(False, False) True >>> Implies(True, True) True >>> Implies(False, True) True """ try: newargs = [] for x in args: if isinstance(x, Number) or x in (0, 1): newargs.append(True if x else False) else: newargs.append(x) A, B = newargs except ValueError: raise ValueError("%d operand(s) used for an Implies " "(pairs are required): %s" % (len(args), str(args))) if A is True or A is False or B is True or B is False: return Or(Not(A), B) else: return Basic.__new__(cls, *args)
def __new__(cls, start, end, left_open=False, right_open=False): start = _sympify(start) end = _sympify(end) left_open = _sympify(left_open) right_open = _sympify(right_open) if not all( isinstance(a, (type(true), type(false))) for a in [left_open, right_open]): raise NotImplementedError( "left_open and right_open can have only true/false values, " "got %s and %s" % (left_open, right_open)) inftys = [S.Infinity, S.NegativeInfinity] # Only allow real intervals (use symbols with 'is_real=True'). if not (start.is_real or start in inftys) or not (end.is_real or end in inftys): raise ValueError("Only real intervals are supported") # Make sure that the created interval will be valid. if end.is_comparable and start.is_comparable: if end < start: return S.EmptySet if end == start and (left_open or right_open): return S.EmptySet if end == start and not (left_open or right_open): return FiniteSet(end) # Make sure infinite interval end points are open. if start == S.NegativeInfinity: left_open = true if end == S.Infinity: right_open = true return Basic.__new__(cls, start, end, left_open, right_open)
def eval(cls, *args): try: newargs = [] for x in args: if isinstance(x, Number) or x in (0, 1): newargs.append(True if x else False) else: newargs.append(x) A, B = newargs except ValueError: raise ValueError("%d operand(s) used for an Implies " "(pairs are required): %s" % (len(args), str(args))) if A == True or A == False or B == True or B == False: return Or(Not(A), B) elif A == B: return S.true elif A.is_Relational and B.is_Relational: if A.canonical == B.canonical: return S.true if (~A).canonical == B.canonical: return B else: return Basic.__new__(cls, *args)
def __new__(cls, flambda, *sets): if not isinstance(flambda, Lambda): raise ValueError('First argument must be a Lambda') sets = [_sympify(s) for s in sets] if flambda is S.IdentityFunction: if len(sets) != 1: raise ValueError('Identity function requires a single set') return sets[0] if not all(isinstance(s, Set) for s in sets): raise TypeError("Set arguments to ImageSet should of type Set") sets = [s.flatten() if s.is_ProductSet else s for s in sets] if not set(flambda.variables) & flambda.expr.free_symbols: emptyprod = fuzzy_or(s.is_empty for s in sets) if emptyprod == True: return S.EmptySet elif emptyprod == False: return FiniteSet(flambda.expr) return Basic.__new__(cls, flambda, *sets)
def __new__(cls, *args): args = [_sympify(arg) for arg in args] args = cls._flatten(args) ranks = [get_rank(arg) for arg in args] if len(args) == 1: return args[0] # If there are contraction objects inside, transform the whole # expression into `CodegenArrayContraction`: contractions = { i: arg for i, arg in enumerate(args) if isinstance(arg, CodegenArrayContraction) } if contractions: cumulative_ranks = list(accumulate([0] + ranks))[:-1] tp = cls(*[ arg.expr if isinstance(arg, CodegenArrayContraction) else arg for arg in args ]) contraction_indices = [ tuple(cumulative_ranks[i] + k for k in j) for i, arg in contractions.items() for j in arg.contraction_indices ] return CodegenArrayContraction(tp, *contraction_indices) obj = Basic.__new__(cls, *args) obj._subranks = ranks shapes = [i.shape for i in args] if any(i is None for i in shapes): obj._shape = None else: obj._shape = tuple(j for i in shapes for j in i) return obj
def __new__(cls, iterable=None, shape=None, **kwargs): shape, flat_list = cls._handle_ndarray_creation_inputs(iterable, shape, **kwargs) shape = Tuple(*map(_sympify, shape)) cls._check_special_bounds(flat_list, shape) loop_size = functools.reduce(lambda x,y: x*y, shape) if shape else len(flat_list) # Sparse array: if isinstance(flat_list, (dict, Dict)): sparse_array = Dict(flat_list) else: sparse_array = {} for i, el in enumerate(flatten(flat_list)): if el != 0: sparse_array[i] = _sympify(el) sparse_array = Dict(sparse_array) self = Basic.__new__(cls, sparse_array, shape, **kwargs) self._shape = shape self._rank = len(shape) self._loop_size = loop_size self._sparse_array = sparse_array return self
def __new__(cls, *args, **kwargs): evaluate = kwargs.get('evaluate', global_parameters.evaluate) # flatten inputs args = list(args) # adapted from sympy.sets.sets.Union def _flatten(arg): if isinstance(arg, SeqBase): if isinstance(arg, SeqAdd): return sum(map(_flatten, arg.args), []) else: return [arg] if iterable(arg): return sum(map(_flatten, arg), []) raise TypeError("Input must be Sequences or " " iterables of Sequences") args = _flatten(args) args = [a for a in args if a is not S.EmptySequence] # Addition of no sequences is EmptySequence if not args: return S.EmptySequence if Intersection(*(a.interval for a in args)) is S.EmptySet: return S.EmptySequence # reduce using known rules if evaluate: return SeqAdd.reduce(args) args = list(ordered(args, SeqBase._start_key)) return Basic.__new__(cls, *args)
def test_subs(): assert b21.subs(b2, b1) == Basic(b1, b1) assert b21.subs(b2, b21) == Basic(b21, b1) assert b3.subs(b2, b1) == b2 assert b21.subs([(b2, b1), (b1, b2)]) == Basic(b2, b2) assert b21.subs({b1: b2, b2: b1}) == Basic(b2, b2) if sys.version_info >= (3, 4): assert b21.subs(collections.ChainMap({b1: b2}, {b2: b1})) == Basic(b2, b2) assert b21.subs(collections.OrderedDict([(b2, b1), (b1, b2)])) == Basic(b2, b2) raises(ValueError, lambda: b21.subs('bad arg')) raises(ValueError, lambda: b21.subs(b1, b2, b3)) # dict(b1=foo) creates a string 'b1' but leaves foo unchanged; subs # will convert the first to a symbol but will raise an error if foo # cannot be sympified; sympification is strict if foo is not string raises(ValueError, lambda: b21.subs(b1='bad arg'))
def __new__(cls, expr): return Basic.__new__(cls, expr)
def __new__(cls, lamda, base_set): return Basic.__new__(cls, lamda, base_set)
def __new__(cls, *args, **kwargs): if kwargs.get('sympify', True): args = ( sympify(arg) for arg in args ) obj = Basic.__new__(cls, *args) return obj
def __new__(cls, *args, **assumptions): args = [sympify(arg) for arg in args] obj = Basic.__new__(cls, *args, **assumptions) return obj
def __new__(cls, base, exp): return Basic.__new__(cls, _sympify(base), _sympify(exp))
def test_18778(): raises(TypeError, lambda: is_le(Basic(), Basic())) raises(TypeError, lambda: is_gt(Basic(), Basic())) raises(TypeError, lambda: is_ge(Basic(), Basic())) raises(TypeError, lambda: is_lt(Basic(), Basic()))
def __new__(cls, sym, condition, base_set=S.UniversalSet): # nonlinsolve uses ConditionSet to return an unsolved system # of equations (see _return_conditionset in solveset) so until # that is changed we do minimal checking of the args sym = _sympify(sym) base_set = _sympify(base_set) condition = _sympify(condition) if isinstance(condition, FiniteSet): condition_orig = condition temp = (Eq(lhs, 0) for lhs in condition) condition = And(*temp) SymPyDeprecationWarning( feature="Using {} for condition".format(condition_orig), issue=17651, deprecated_since_version="1.5", useinstead="{} for condition".format(condition), ).warn() condition = as_Boolean(condition) if isinstance(sym, Tuple): # unsolved eqns syntax return Basic.__new__(cls, sym, condition, base_set) if not isinstance(base_set, Set): raise TypeError("expecting set for base_set") if condition is S.false: return S.EmptySet elif condition is S.true: return base_set if isinstance(base_set, EmptySet): return base_set know = None if isinstance(base_set, FiniteSet): sifted = sift(base_set, lambda _: fuzzy_bool(condition.subs(sym, _))) if sifted[None]: know = FiniteSet(*sifted[True]) base_set = FiniteSet(*sifted[None]) else: return FiniteSet(*sifted[True]) if isinstance(base_set, cls): s, c, base_set = base_set.args if sym == s: condition = And(condition, c) elif sym not in c.free_symbols: condition = And(condition, c.xreplace({s: sym})) elif s not in condition.free_symbols: condition = And(condition.xreplace({sym: s}), c) sym = s else: # user will have to use cls.sym to get symbol dum = Symbol("lambda") if dum in condition.free_symbols or dum in c.free_symbols: dum = Dummy(str(dum)) condition = And(condition.xreplace({sym: dum}), c.xreplace({s: dum})) sym = dum if not isinstance(sym, Symbol): s = Dummy("lambda") if s not in condition.xreplace({sym: s}).free_symbols: raise ValueError( "non-symbol dummy not recognized in condition") rv = Basic.__new__(cls, sym, condition, base_set) return rv if know is None else Union(know, rv)