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, sets, polar=False): from sympy import sin, cos x, y, r, theta = symbols('x, y, r, theta', cls=Dummy) I = S.ImaginaryUnit polar = sympify(polar) # Rectangular Form if polar == False: if all(_a.is_FiniteSet for _a in sets.args) and (len(sets.args) == 2): # ** ProductSet of FiniteSets in the Complex Plane. ** # For Cases like ComplexRegion({2, 4}*{3}), It # would return {2 + 3*I, 4 + 3*I} complex_num = [] for x in sets.args[0]: for y in sets.args[1]: complex_num.append(x + I*y) obj = FiniteSet(*complex_num) else: obj = ImageSet.__new__(cls, Lambda((x, y), x + I*y), sets) obj._variables = (x, y) obj._expr = x + I*y # Polar Form elif polar == True: new_sets = [] # sets is Union of ProductSets if not sets.is_ProductSet: for k in sets.args: new_sets.append(k) # sets is ProductSets else: new_sets.append(sets) # Normalize input theta for k, v in enumerate(new_sets): from sympy.sets import ProductSet new_sets[k] = ProductSet(v.args[0], normalize_theta_set(v.args[1])) sets = Union(*new_sets) obj = ImageSet.__new__(cls, Lambda((r, theta), r*(cos(theta) + I*sin(theta))), sets) obj._variables = (r, theta) obj._expr = r*(cos(theta) + I*sin(theta)) else: raise ValueError("polar should be either True or False") obj._sets = sets obj._polar = polar return obj
def __new__(cls, *partition): """ Generates a new partition object. This method also verifies if the arguments passed are valid and raises a ValueError if they are not. Examples ======== >>> from sympy.combinatorics.partitions import Partition >>> a = Partition([1, 2], [3]) >>> a {{3}, {1, 2}} >>> a.partition [[1, 2], [3]] >>> len(a) 2 >>> a.members (1, 2, 3) """ args = partition if not all(isinstance(part, (list, FiniteSet)) for part in args): raise ValueError( "Each argument to Partition should be a list or a FiniteSet") # sort so we have a canonical reference for RGS partition = sorted(sum(partition, []), key=default_sort_key) if has_dups(partition): raise ValueError("Partition contained duplicated elements.") obj = FiniteSet.__new__(cls, *[FiniteSet(*x) for x in args]) obj.members = tuple(partition) obj.size = len(partition) return obj
def test_ImageSet(): raises(ValueError, lambda: ImageSet(x, S.Integers)) assert ImageSet(Lambda(x, 1), S.Integers) == FiniteSet(1) assert ImageSet(Lambda(x, y), S.Integers) == {y} assert ImageSet(Lambda(x, 1), S.EmptySet) == S.EmptySet empty = Intersection(FiniteSet(log(2) / pi), S.Integers) assert unchanged(ImageSet, Lambda(x, 1), empty) # issue #17471 squares = ImageSet(Lambda(x, x**2), S.Naturals) assert 4 in squares assert 5 not in squares assert FiniteSet(*range(10)).intersect(squares) == FiniteSet(1, 4, 9) assert 16 not in squares.intersect(Interval(0, 10)) si = iter(squares) a, b, c, d = next(si), next(si), next(si), next(si) assert (a, b, c, d) == (1, 4, 9, 16) harmonics = ImageSet(Lambda(x, 1 / x), S.Naturals) assert Rational(1, 5) in harmonics assert Rational(.25) in harmonics assert 0.25 not in harmonics assert Rational(.3) not in harmonics assert (1, 2) not in harmonics assert harmonics.is_iterable assert imageset(x, -x, Interval(0, 1)) == Interval(-1, 0) assert ImageSet(Lambda(x, x**2), Interval(0, 2)).doit() == Interval(0, 4) assert ImageSet(Lambda((x, y), 2 * x), {4}, {3}).doit() == FiniteSet(8) assert (ImageSet(Lambda((x, y), x + y), {1, 2, 3}, {10, 20, 30}).doit() == FiniteSet(11, 12, 13, 21, 22, 23, 31, 32, 33)) c = Interval(1, 3) * Interval(1, 3) assert Tuple(2, 6) in ImageSet(Lambda(((x, y), ), (x, 2 * y)), c) assert Tuple(2, S.Half) in ImageSet(Lambda(((x, y), ), (x, 1 / y)), c) assert Tuple(2, -2) not in ImageSet(Lambda(((x, y), ), (x, y**2)), c) assert Tuple(2, -2) in ImageSet(Lambda(((x, y), ), (x, -2)), c) c3 = ProductSet(Interval(3, 7), Interval(8, 11), Interval(5, 9)) assert Tuple(8, 3, 9) in ImageSet(Lambda(((t, y, x), ), (y, t, x)), c3) assert Tuple(Rational(1, 8), 3, 9) in ImageSet(Lambda(((t, y, x), ), (1 / y, t, x)), c3) assert 2 / pi not in ImageSet(Lambda(((x, y), ), 2 / x), c) assert 2 / S(100) not in ImageSet(Lambda(((x, y), ), 2 / x), c) assert Rational(2, 3) in ImageSet(Lambda(((x, y), ), 2 / x), c) S1 = imageset(lambda x, y: x + y, S.Integers, S.Naturals) assert S1.base_pset == ProductSet(S.Integers, S.Naturals) assert S1.base_sets == (S.Integers, S.Naturals) # Passing a set instead of a FiniteSet shouldn't raise assert unchanged(ImageSet, Lambda(x, x**2), {1, 2, 3}) S2 = ImageSet(Lambda(((x, y), ), x + y), {(1, 2), (3, 4)}) assert 3 in S2.doit() # FIXME: This doesn't yet work: #assert 3 in S2 assert S2._contains(3) is None raises(TypeError, lambda: ImageSet(Lambda(x, x**2), 1))
def elements(self): return FiniteSet(*[frozenset(((self.symbol, elem), )) for elem in self.set])
def _density(self): return dict((FiniteSet((self.symbol, val)), prob) for val, prob in self.distribution.dict.items())
def spaces(self): return FiniteSet(*self.args)
def __new__(cls, symbols, *args): symbols = FiniteSet(*symbols) return Basic.__new__(cls, symbols, *args)
def test_Lambda(): e = Lambda(x, x**2) assert e(4) == 16 assert e(x) == x**2 assert e(y) == y**2 assert Lambda((), 42)() == 42 assert unchanged(Lambda, (), 42) assert Lambda((), 42) != Lambda((), 43) assert Lambda((), f(x))() == f(x) assert Lambda((), 42).nargs == FiniteSet(0) assert unchanged(Lambda, (x,), x**2) assert Lambda(x, x**2) == Lambda((x,), x**2) assert Lambda(x, x**2) != Lambda(x, x**2 + 1) assert Lambda((x, y), x**y) != Lambda((y, x), y**x) assert Lambda((x, y), x**y) != Lambda((x, y), y**x) assert Lambda((x, y), x**y)(x, y) == x**y assert Lambda((x, y), x**y)(3, 3) == 3**3 assert Lambda((x, y), x**y)(x, 3) == x**3 assert Lambda((x, y), x**y)(3, y) == 3**y assert Lambda(x, f(x))(x) == f(x) assert Lambda(x, x**2)(e(x)) == x**4 assert e(e(x)) == x**4 x1, x2 = (Indexed('x', i) for i in (1, 2)) assert Lambda((x1, x2), x1 + x2)(x, y) == x + y assert Lambda((x, y), x + y).nargs == FiniteSet(2) p = x, y, z, t assert Lambda(p, t*(x + y + z))(*p) == t * (x + y + z) eq = Lambda(x, 2*x) + Lambda(y, 2*y) assert eq != 2*Lambda(x, 2*x) assert eq.as_dummy() == 2*Lambda(x, 2*x).as_dummy() assert Lambda(x, 2*x) not in [ Lambda(x, x) ] raises(BadSignatureError, lambda: Lambda(1, x)) assert Lambda(x, 1)(1) is S.One raises(BadSignatureError, lambda: Lambda((x, x), x + 2)) raises(BadSignatureError, lambda: Lambda(((x, x), y), x)) raises(BadSignatureError, lambda: Lambda(((y, x), x), x)) raises(BadSignatureError, lambda: Lambda(((y, 1), 2), x)) with warns_deprecated_sympy(): assert Lambda([x, y], x+y) == Lambda((x, y), x+y) flam = Lambda(((x, y),), x + y) assert flam((2, 3)) == 5 flam = Lambda(((x, y), z), x + y + z) assert flam((2, 3), 1) == 6 flam = Lambda((((x, y), z),), x + y + z) assert flam(((2, 3), 1)) == 6 raises(BadArgumentsError, lambda: flam(1, 2, 3)) flam = Lambda( (x,), (x, x)) assert flam(1,) == (1, 1) assert flam((1,)) == ((1,), (1,)) flam = Lambda( ((x,),), (x, x)) raises(BadArgumentsError, lambda: flam(1)) assert flam((1,)) == (1, 1) # Previously TypeError was raised so this is potentially needed for # backwards compatibility. assert issubclass(BadSignatureError, TypeError) assert issubclass(BadArgumentsError, TypeError) # These are tested to see they don't raise: hash(Lambda(x, 2*x)) hash(Lambda(x, x)) # IdentityFunction subclass
def normalize_theta_set(theta): """ Normalize a Real Set `theta` in the Interval [0, 2*pi). It returns a normalized value of theta in the Set. For Interval, a maximum of one cycle [0, 2*pi], is returned i.e. for theta equal to [0, 10*pi], returned normalized value would be [0, 2*pi). As of now intervals with end points as non-multiples of `pi` is not supported. Raises ====== NotImplementedError The algorithms for Normalizing theta Set are not yet implemented. ValueError The input is not valid, i.e. the input is not a real set. RuntimeError It is a bug, please report to the github issue tracker. Examples ======== >>> from sympy.sets.fancysets import normalize_theta_set >>> from sympy import Interval, FiniteSet, pi >>> normalize_theta_set(Interval(9*pi/2, 5*pi)) Interval(pi/2, pi) >>> normalize_theta_set(Interval(-3*pi/2, pi/2)) Interval.Ropen(0, 2*pi) >>> normalize_theta_set(Interval(-pi/2, pi/2)) Union(Interval(0, pi/2), Interval.Ropen(3*pi/2, 2*pi)) >>> normalize_theta_set(Interval(-4*pi, 3*pi)) Interval.Ropen(0, 2*pi) >>> normalize_theta_set(Interval(-3*pi/2, -pi/2)) Interval(pi/2, 3*pi/2) >>> normalize_theta_set(FiniteSet(0, pi, 3*pi)) {0, pi} """ from sympy.functions.elementary.trigonometric import _pi_coeff as coeff if theta.is_Interval: interval_len = theta.measure # one complete circle if interval_len >= 2 * S.Pi: if interval_len == 2 * S.Pi and theta.left_open and theta.right_open: k = coeff(theta.start) return Union(Interval(0, k * S.Pi, False, True), Interval(k * S.Pi, 2 * S.Pi, True, True)) return Interval(0, 2 * S.Pi, False, True) k_start, k_end = coeff(theta.start), coeff(theta.end) if k_start is None or k_end is None: raise NotImplementedError( "Normalizing theta without pi as coefficient is " "not yet implemented") new_start = k_start * S.Pi new_end = k_end * S.Pi if new_start > new_end: return Union(Interval(S.Zero, new_end, False, theta.right_open), Interval(new_start, 2 * S.Pi, theta.left_open, True)) else: return Interval(new_start, new_end, theta.left_open, theta.right_open) elif theta.is_FiniteSet: new_theta = [] for element in theta: k = coeff(element) if k is None: raise NotImplementedError('Normalizing theta without pi as ' 'coefficient, is not Implemented.') else: new_theta.append(k * S.Pi) return FiniteSet(*new_theta) elif theta.is_Union: return Union( *[normalize_theta_set(interval) for interval in theta.args]) elif theta.is_subset(S.Reals): raise NotImplementedError( "Normalizing theta when, it is of type %s is not " "implemented" % type(theta)) else: raise ValueError(" %s is not a real set" % (theta))
def __new__(cls, *partition): """ Generates a new partition object. This method also verifies if the arguments passed are valid and raises a ValueError if they are not. Examples ======== Creating Partition from Python lists: >>> from sympy.combinatorics.partitions import Partition >>> a = Partition([1, 2], [3]) >>> a Partition(FiniteSet(1, 2), FiniteSet(3)) >>> a.partition [[1, 2], [3]] >>> len(a) 2 >>> a.members (1, 2, 3) Creating Partition from Python sets: >>> Partition({1, 2, 3}, {4, 5}) Partition(FiniteSet(1, 2, 3), FiniteSet(4, 5)) Creating Partition from SymPy finite sets: >>> from sympy.sets.sets import FiniteSet >>> a = FiniteSet(1, 2, 3) >>> b = FiniteSet(4, 5) >>> Partition(a, b) Partition(FiniteSet(1, 2, 3), FiniteSet(4, 5)) """ args = [] dups = False for arg in partition: if isinstance(arg, list): as_set = set(arg) if len(as_set) < len(arg): dups = True break # error below arg = as_set args.append(_sympify(arg)) if not all(isinstance(part, FiniteSet) for part in args): raise ValueError( "Each argument to Partition should be " \ "a list, set, or a FiniteSet") # sort so we have a canonical reference for RGS U = Union(*args) if dups or len(U) < sum(len(arg) for arg in args): raise ValueError("Partition contained duplicate elements.") obj = FiniteSet.__new__(cls, *args) obj.members = tuple(U) obj.size = len(U) return obj
def test_normalize_theta_set(): # Interval assert normalize_theta_set(Interval(pi, 2*pi)) == \ Union(FiniteSet(0), Interval.Ropen(pi, 2*pi)) assert normalize_theta_set(Interval(9 * pi / 2, 5 * pi)) == Interval(pi / 2, pi) assert normalize_theta_set(Interval(-3 * pi / 2, pi / 2)) == Interval.Ropen(0, 2 * pi) assert normalize_theta_set(Interval.open(-3*pi/2, pi/2)) == \ Union(Interval.Ropen(0, pi/2), Interval.open(pi/2, 2*pi)) assert normalize_theta_set(Interval.open(-7*pi/2, -3*pi/2)) == \ Union(Interval.Ropen(0, pi/2), Interval.open(pi/2, 2*pi)) assert normalize_theta_set(Interval(-pi/2, pi/2)) == \ Union(Interval(0, pi/2), Interval.Ropen(3*pi/2, 2*pi)) assert normalize_theta_set(Interval.open(-pi/2, pi/2)) == \ Union(Interval.Ropen(0, pi/2), Interval.open(3*pi/2, 2*pi)) assert normalize_theta_set(Interval(-4 * pi, 3 * pi)) == Interval.Ropen(0, 2 * pi) assert normalize_theta_set(Interval(-3 * pi / 2, -pi / 2)) == Interval( pi / 2, 3 * pi / 2) assert normalize_theta_set(Interval.open(0, 2 * pi)) == Interval.open( 0, 2 * pi) assert normalize_theta_set(Interval.Ropen(-pi/2, pi/2)) == \ Union(Interval.Ropen(0, pi/2), Interval.Ropen(3*pi/2, 2*pi)) assert normalize_theta_set(Interval.Lopen(-pi/2, pi/2)) == \ Union(Interval(0, pi/2), Interval.open(3*pi/2, 2*pi)) assert normalize_theta_set(Interval(-pi/2, pi/2)) == \ Union(Interval(0, pi/2), Interval.Ropen(3*pi/2, 2*pi)) assert normalize_theta_set(Interval.open(4 * pi, 9 * pi / 2)) == Interval.open( 0, pi / 2) assert normalize_theta_set(Interval.Lopen(4 * pi, 9 * pi / 2)) == Interval.Lopen( 0, pi / 2) assert normalize_theta_set(Interval.Ropen(4 * pi, 9 * pi / 2)) == Interval.Ropen( 0, pi / 2) assert normalize_theta_set(Interval.open(3*pi, 5*pi)) == \ Union(Interval.Ropen(0, pi), Interval.open(pi, 2*pi)) # FiniteSet assert normalize_theta_set(FiniteSet(0, pi, 3 * pi)) == FiniteSet(0, pi) assert normalize_theta_set(FiniteSet(0, pi / 2, pi, 2 * pi)) == FiniteSet(0, pi / 2, pi) assert normalize_theta_set(FiniteSet(0, -pi / 2, -pi, -2 * pi)) == FiniteSet( 0, pi, 3 * pi / 2) assert normalize_theta_set(FiniteSet(-3*pi/2, pi/2)) == \ FiniteSet(pi/2) assert normalize_theta_set(FiniteSet(2 * pi)) == FiniteSet(0) # Unions assert normalize_theta_set(Union(Interval(0, pi/3), Interval(pi/2, pi))) == \ Union(Interval(0, pi/3), Interval(pi/2, pi)) assert normalize_theta_set(Union(Interval(0, pi), Interval(2*pi, 7*pi/3))) == \ Interval(0, pi) # ValueError for non-real sets raises(ValueError, lambda: normalize_theta_set(S.Complexes))
def __pow__(self, other): from sympy.functions.elementary.miscellaneous import real_root if isinstance(other, Expr): if other is S.Infinity: if self.min.is_nonnegative: if self.max < 1: return S.Zero if self.min > 1: return S.Infinity return AccumBounds(0, oo) elif self.max.is_negative: if self.min > -1: return S.Zero if self.max < -1: return FiniteSet(-oo, oo) return AccumBounds(-oo, oo) else: if self.min > -1: if self.max < 1: return S.Zero return AccumBounds(0, oo) return AccumBounds(-oo, oo) if other is S.NegativeInfinity: return (1 / self)**oo if other.is_real and other.is_number: if other.is_zero: return S.One if other.is_Integer: if self.min.is_positive: return AccumBounds( Min(self.min**other, self.max**other), Max(self.min**other, self.max**other)) elif self.max.is_negative: return AccumBounds( Min(self.max**other, self.min**other), Max(self.max**other, self.min**other)) if other % 2 == 0: if other.is_negative: if self.min.is_zero: return AccumBounds(self.max**other, oo) if self.max.is_zero: return AccumBounds(self.min**other, oo) return AccumBounds(0, oo) return AccumBounds( S.Zero, Max(self.min**other, self.max**other)) else: if other.is_negative: if self.min.is_zero: return AccumBounds(self.max**other, oo) if self.max.is_zero: return AccumBounds(-oo, self.min**other) return AccumBounds(-oo, oo) return AccumBounds(self.min**other, self.max**other) num, den = other.as_numer_denom() if num == S(1): if den % 2 == 0: if S.Zero in self: if self.min.is_negative: return AccumBounds(0, real_root(self.max, den)) return AccumBounds(real_root(self.min, den), real_root(self.max, den)) num_pow = self**num return num_pow**(1 / den) return Pow(self, other, evaluate=False) return NotImplemented
def function_range(f, symbol, domain): """ Finds the range of a function in a given domain. This method is limited by the ability to determine the singularities and determine limits. Examples ======== >>> from sympy import Symbol, S, exp, log, pi, sqrt, sin, tan >>> from sympy.sets import Interval >>> from sympy.calculus.util import function_range >>> x = Symbol('x') >>> function_range(sin(x), x, Interval(0, 2*pi)) [-1, 1] >>> function_range(tan(x), x, Interval(-pi/2, pi/2)) (-oo, oo) >>> function_range(1/x, x, S.Reals) (-oo, oo) >>> function_range(exp(x), x, S.Reals) (0, oo) >>> function_range(log(x), x, S.Reals) (-oo, oo) >>> function_range(sqrt(x), x , Interval(-5, 9)) [0, 3] """ from sympy.solvers.solveset import solveset vals = S.EmptySet intervals = continuous_domain(f, symbol, domain) range_int = S.EmptySet if isinstance(intervals, Interval): interval_iter = (intervals, ) else: interval_iter = intervals.args for interval in interval_iter: critical_points = S.EmptySet critical_values = S.EmptySet bounds = ((interval.left_open, interval.inf, '+'), (interval.right_open, interval.sup, '-')) for is_open, limit_point, direction in bounds: if is_open: critical_values += FiniteSet( limit(f, symbol, limit_point, direction)) vals += critical_values else: vals += FiniteSet(f.subs(symbol, limit_point)) critical_points += solveset(f.diff(symbol), symbol, domain) for critical_point in critical_points: vals += FiniteSet(f.subs(symbol, critical_point)) left_open, right_open = False, False if critical_values is not S.EmptySet: if critical_values.inf == vals.inf: left_open = True if critical_values.sup == vals.sup: right_open = True range_int += Interval(vals.inf, vals.sup, left_open, right_open) return range_int
def __new__(cls, symbol, set): if not isinstance(set, FiniteSet) and \ not isinstance(set, Intersection): set = FiniteSet(*set) return Basic.__new__(cls, symbol, set)
def dict(self): return FiniteSet(*[Dict(dict(el)) for el in self.elements])
def symbols(self): return FiniteSet(sym for sym, val in self.elements)
def test_ComplexRegion_from_real(): c1 = ComplexRegion(Interval(0, 1) * Interval(0, 2 * S.Pi), polar=True) raises(ValueError, lambda: c1.from_real(c1)) assert c1.from_real(Interval(-1, 1)) == ComplexRegion( Interval(-1, 1) * FiniteSet(0), False)
def test_not_empty_in(): from sympy.abc import x a = Symbol('a', real=True) assert not_empty_in(FiniteSet(x, 2*x).intersect(Interval(1, 2, True, False)), x) == \ Interval(S(1)/2, 2, True, False) assert not_empty_in(FiniteSet(x, x**2).intersect(Interval(1, 2)), x) == \ Union(Interval(-sqrt(2), -1), Interval(1, 2)) assert not_empty_in(FiniteSet(x**2 + x, x).intersect(Interval(2, 4)), x) == \ Union(Interval(-sqrt(17)/2 - S(1)/2, -2), Interval(1, -S(1)/2 + sqrt(17)/2), Interval(2, 4)) assert not_empty_in(FiniteSet(x/(x - 1)).intersect(S.Reals), x) == Complement(S.Reals, FiniteSet(1)) assert not_empty_in(FiniteSet(a/(a - 1)).intersect(S.Reals), a) == Complement(S.Reals, FiniteSet(1)) assert not_empty_in(FiniteSet((x**2 - 3*x + 2)/(x - 1)).intersect(S.Reals), x) == \ Complement(S.Reals, FiniteSet(1)) assert not_empty_in(FiniteSet(3, 4, x/(x - 1)).intersect(Interval(2, 3)), x) == \ Union(Interval(S(3)/2, 2), FiniteSet(3)) assert not_empty_in(FiniteSet(x/(x**2 - 1)).intersect(S.Reals), x) == \ Complement(S.Reals, FiniteSet(-1, 1)) assert not_empty_in(FiniteSet(x, x**2).intersect(Union(Interval(1, 3, True, True), Interval(4, 5))), x) == \ Union(Interval(-sqrt(5), -2), Interval(-sqrt(3), -1, True, True), Interval(1, 3, True, True), Interval(4, 5)) assert not_empty_in(FiniteSet(1).intersect(Interval(3, 4)), x) == S.EmptySet assert not_empty_in(FiniteSet(x**2/(x + 2)).intersect(Interval(1, oo)), x) == \ Union(Interval(-2, -1, True, False), Interval(2, oo))
def test_normalize_theta_set(): # Interval assert normalize_theta_set(Interval(pi, 2*pi)) == \ Union(FiniteSet(0), Interval.Ropen(pi, 2*pi)) assert normalize_theta_set(Interval(pi * Rational(9, 2), 5 * pi)) == Interval(pi / 2, pi) assert normalize_theta_set(Interval(pi * Rational(-3, 2), pi / 2)) == Interval.Ropen(0, 2 * pi) assert normalize_theta_set(Interval.open(pi*Rational(-3, 2), pi/2)) == \ Union(Interval.Ropen(0, pi/2), Interval.open(pi/2, 2*pi)) assert normalize_theta_set(Interval.open(pi*Rational(-7, 2), pi*Rational(-3, 2))) == \ Union(Interval.Ropen(0, pi/2), Interval.open(pi/2, 2*pi)) assert normalize_theta_set(Interval(-pi/2, pi/2)) == \ Union(Interval(0, pi/2), Interval.Ropen(pi*Rational(3, 2), 2*pi)) assert normalize_theta_set(Interval.open(-pi/2, pi/2)) == \ Union(Interval.Ropen(0, pi/2), Interval.open(pi*Rational(3, 2), 2*pi)) assert normalize_theta_set(Interval(-4 * pi, 3 * pi)) == Interval.Ropen(0, 2 * pi) assert normalize_theta_set(Interval(pi * Rational(-3, 2), -pi / 2)) == Interval( pi / 2, pi * Rational(3, 2)) assert normalize_theta_set(Interval.open(0, 2 * pi)) == Interval.open( 0, 2 * pi) assert normalize_theta_set(Interval.Ropen(-pi/2, pi/2)) == \ Union(Interval.Ropen(0, pi/2), Interval.Ropen(pi*Rational(3, 2), 2*pi)) assert normalize_theta_set(Interval.Lopen(-pi/2, pi/2)) == \ Union(Interval(0, pi/2), Interval.open(pi*Rational(3, 2), 2*pi)) assert normalize_theta_set(Interval(-pi/2, pi/2)) == \ Union(Interval(0, pi/2), Interval.Ropen(pi*Rational(3, 2), 2*pi)) assert normalize_theta_set(Interval.open( 4 * pi, pi * Rational(9, 2))) == Interval.open(0, pi / 2) assert normalize_theta_set(Interval.Lopen( 4 * pi, pi * Rational(9, 2))) == Interval.Lopen(0, pi / 2) assert normalize_theta_set(Interval.Ropen( 4 * pi, pi * Rational(9, 2))) == Interval.Ropen(0, pi / 2) assert normalize_theta_set(Interval.open(3*pi, 5*pi)) == \ Union(Interval.Ropen(0, pi), Interval.open(pi, 2*pi)) # FiniteSet assert normalize_theta_set(FiniteSet(0, pi, 3 * pi)) == FiniteSet(0, pi) assert normalize_theta_set(FiniteSet(0, pi / 2, pi, 2 * pi)) == FiniteSet(0, pi / 2, pi) assert normalize_theta_set(FiniteSet(0, -pi / 2, -pi, -2 * pi)) == FiniteSet( 0, pi, pi * Rational(3, 2)) assert normalize_theta_set(FiniteSet(pi*Rational(-3, 2), pi/2)) == \ FiniteSet(pi/2) assert normalize_theta_set(FiniteSet(2 * pi)) == FiniteSet(0) # Unions assert normalize_theta_set(Union(Interval(0, pi/3), Interval(pi/2, pi))) == \ Union(Interval(0, pi/3), Interval(pi/2, pi)) assert normalize_theta_set(Union(Interval(0, pi), Interval(2*pi, pi*Rational(7, 3)))) == \ Interval(0, pi) # ValueError for non-real sets raises(ValueError, lambda: normalize_theta_set(S.Complexes)) # NotImplementedError for subset of reals raises(NotImplementedError, lambda: normalize_theta_set(Interval(0, 1))) # NotImplementedError without pi as coefficient raises(NotImplementedError, lambda: normalize_theta_set(Interval(1, 2 * pi))) raises(NotImplementedError, lambda: normalize_theta_set(Interval(2 * pi, 10))) raises(NotImplementedError, lambda: normalize_theta_set(FiniteSet(0, 3, 3 * pi)))
def test_codomain(): x = Symbol('x', real=True) assert codomain(x, Interval(-1, 1), x) == Interval(-1, 1) assert codomain(x, Interval(0, 1, True, True), x) == \ Interval(0, 1, True, True) assert codomain(x, Interval(1, 2, True, False), x) == Interval(1, 2, True, False) assert codomain(x, Interval(1, 2, False, True), x) == Interval(1, 2, False, True) assert codomain(x**2, Interval(-1, 1), x) == Interval(0, 1) assert codomain(x**3, Interval(0, 1), x) == Interval(0, 1) assert codomain(x/(x**2 - 4), Interval(3, 4), x) == Interval(S(1)/3, S(3)/5) assert codomain(1, Interval(-1, 4), x) == FiniteSet(1) assert codomain(x, Interval(-oo, oo), x) == S.Reals assert codomain(1/x**2, FiniteSet(1, 2, -1, 0), x) == FiniteSet(1, S(1)/4) assert codomain(x, FiniteSet(1, -1, 3, 5), x) == FiniteSet(-1, 1, 3, 5) assert codomain(x**2 - x, FiniteSet(1, -1, 3, 5, -oo), x) == \ FiniteSet(0, 2, 6, 20, oo) assert codomain(x**2/(x - 4), FiniteSet(4), x) == S.EmptySet assert codomain(x**2 - x, FiniteSet(S(1)/2, -oo, oo, 2), x) == \ FiniteSet(S(-1)/4, 2, oo) assert codomain(x**2, Interval(-1, 1, True, True), x) == Interval(0, 1, False, True) assert codomain(x**2, Interval(-1, 1, False, True), x) == Interval(0, 1) assert codomain(x**2, Interval(-1, 1, True, False), x) == Interval(0, 1) assert codomain(1/x, Interval(0, 1), x) == Interval(1, oo) assert codomain(1/x, Interval(-1, 1), x) == Union(Interval(-oo, -1), Interval(1, oo)) assert codomain(1/x**2, Interval(-1, 1), x) == Interval(1, oo) assert codomain(1/x**2, Interval(-1, 1, True, False), x) == Interval(1, oo) assert codomain(1/x**2, Interval(-1, 1, True, True), x) == \ Interval(1, oo, True, True) assert codomain(1/x**2, Interval(-1, 1, False, True), x) == Interval(1, oo) assert codomain(1/x, Interval(1, 2), x) == Interval(S(1)/2, 1) assert codomain(1/x**2, Interval(-2, -1, True, True), x) == \ Interval(S(1)/4, 1, True, True) assert codomain(x**2/(x - 4), Interval(-oo, oo), x) == \ Complement(S.Reals, Interval(0, 16, True, True)) assert codomain(x**2/(x - 4), Interval(3, 4), x) == Interval(-oo, -9) assert codomain(-x**2/(x - 4), Interval(3, 4), x) == Interval(9, oo) assert codomain((x**2 - x)/(x**3 - 1), S.Reals, x) == Interval(-1, S(1)/3, False, True) assert codomain(-x**2 + 1/x, S.Reals, x) == S.Reals assert codomain(x**2 - 1/x, S.Reals, x) == S.Reals assert codomain(x**2, Union(Interval(1, 2), FiniteSet(3)), x) == \ Union(Interval(1, 4), FiniteSet(9)) assert codomain(x/(x**2 - 4), Union(Interval(-oo, 1), Interval(0, oo)), x) == S.Reals assert codomain(x, Union(Interval(-1, 1), FiniteSet(-oo)), x) == \ Union(Interval(-1, 1), FiniteSet(-oo)) assert codomain(x**2 - x, Interval(1, oo), x) == Interval(0, oo) raises(ValueError, lambda: codomain(sqrt(x), Interval(-1, 2), x))
def _set_pow(x, z): # noqa:F811 return FiniteSet(S.One)
def test_issue_16871(): assert ImageSet(Lambda(x, x), FiniteSet(1)) == {1} assert ImageSet(Lambda(x, x - 3), S.Integers).intersection( S.Integers) is S.Integers
def symbols(self): return FiniteSet(*[val.symbol for val in self.rs_space_dict.keys()])
def solve_univariate_inequality(expr, gen, relational=True, domain=S.Reals, continuous=False): """Solves a real univariate inequality. Parameters ========== expr : Relational The target inequality gen : Symbol The variable for which the inequality is solved relational : bool A Relational type output is expected or not domain : Set The domain over which the equation is solved continuous: bool True if expr is known to be continuous over the given domain (and so continuous_domain() doesn't need to be called on it) Raises ====== NotImplementedError The solution of the inequality cannot be determined due to limitation in :func:`sympy.solvers.solveset.solvify`. Notes ===== Currently, we cannot solve all the inequalities due to limitations in :func:`sympy.solvers.solveset.solvify`. Also, the solution returned for trigonometric inequalities are restricted in its periodic interval. See Also ======== sympy.solvers.solveset.solvify: solver returning solveset solutions with solve's output API Examples ======== >>> from sympy.solvers.inequalities import solve_univariate_inequality >>> from sympy import Symbol, sin, Interval, S >>> x = Symbol('x') >>> solve_univariate_inequality(x**2 >= 4, x) ((2 <= x) & (x < oo)) | ((x <= -2) & (-oo < x)) >>> solve_univariate_inequality(x**2 >= 4, x, relational=False) Union(Interval(-oo, -2), Interval(2, oo)) >>> domain = Interval(0, S.Infinity) >>> solve_univariate_inequality(x**2 >= 4, x, False, domain) Interval(2, oo) >>> solve_univariate_inequality(sin(x) > 0, x, relational=False) Interval.open(0, pi) """ from sympy import im from sympy.calculus.util import continuous_domain, periodicity, function_range from sympy.solvers.solvers import denoms from sympy.solvers.solveset import solvify, solveset # This keeps the function independent of the assumptions about `gen`. # `solveset` makes sure this function is called only when the domain is # real. _gen = gen _domain = domain if gen.is_extended_real is False: rv = S.EmptySet return rv if not relational else rv.as_relational(_gen) elif gen.is_extended_real is None: gen = Dummy("gen", extended_real=True) try: expr = expr.xreplace({_gen: gen}) except TypeError: raise TypeError( filldedent(""" When gen is real, the relational has a complex part which leads to an invalid comparison like I < 0. """)) rv = None if expr is S.true: rv = domain elif expr is S.false: rv = S.EmptySet else: e = expr.lhs - expr.rhs period = periodicity(e, gen) if period == S.Zero: e = expand_mul(e) const = expr.func(e, 0) if const is S.true: rv = domain elif const is S.false: rv = S.EmptySet elif period is not None: frange = function_range(e, gen, domain) rel = expr.rel_op if rel == "<" or rel == "<=": if expr.func(frange.sup, 0): rv = domain elif not expr.func(frange.inf, 0): rv = S.EmptySet elif rel == ">" or rel == ">=": if expr.func(frange.inf, 0): rv = domain elif not expr.func(frange.sup, 0): rv = S.EmptySet inf, sup = domain.inf, domain.sup if sup - inf is S.Infinity: domain = Interval(0, period, False, True) if rv is None: n, d = e.as_numer_denom() try: if gen not in n.free_symbols and len(e.free_symbols) > 1: raise ValueError # this might raise ValueError on its own # or it might give None... solns = solvify(e, gen, domain) if solns is None: # in which case we raise ValueError raise ValueError except (ValueError, NotImplementedError): # replace gen with generic x since it's # univariate anyway raise NotImplementedError( filldedent(""" The inequality, %s, cannot be solved using solve_univariate_inequality. """ % expr.subs(gen, Symbol("x")))) expanded_e = expand_mul(e) def valid(x): # this is used to see if gen=x satisfies the # relational by substituting it into the # expanded form and testing against 0, e.g. # if expr = x*(x + 1) < 2 then e = x*(x + 1) - 2 # and expanded_e = x**2 + x - 2; the test is # whether a given value of x satisfies # x**2 + x - 2 < 0 # # expanded_e, expr and gen used from enclosing scope v = expanded_e.subs(gen, expand_mul(x)) try: r = expr.func(v, 0) except TypeError: r = S.false if r in (S.true, S.false): return r if v.is_extended_real is False: return S.false else: v = v.n(2) if v.is_comparable: return expr.func(v, 0) # not comparable or couldn't be evaluated raise NotImplementedError( "relationship did not evaluate: %s" % r) singularities = [] for d in denoms(expr, gen): singularities.extend(solvify(d, gen, domain)) if not continuous: domain = continuous_domain(expanded_e, gen, domain) include_x = "=" in expr.rel_op and expr.rel_op != "!=" try: discontinuities = set(domain.boundary - FiniteSet(domain.inf, domain.sup)) # remove points that are not between inf and sup of domain critical_points = FiniteSet( *(solns + singularities + list(discontinuities))).intersection( Interval( domain.inf, domain.sup, domain.inf not in domain, domain.sup not in domain, )) if all(r.is_number for r in critical_points): reals = _nsort(critical_points, separated=True)[0] else: sifted = sift(critical_points, lambda x: x.is_extended_real) if sifted[None]: # there were some roots that weren't known # to be real raise NotImplementedError try: reals = sifted[True] if len(reals) > 1: reals = list(sorted(reals)) except TypeError: raise NotImplementedError except NotImplementedError: raise NotImplementedError( "sorting of these roots is not supported") # If expr contains imaginary coefficients, only take real # values of x for which the imaginary part is 0 make_real = S.Reals if im(expanded_e) != S.Zero: check = True im_sol = FiniteSet() try: a = solveset(im(expanded_e), gen, domain) if not isinstance(a, Interval): for z in a: if (z not in singularities and valid(z) and z.is_extended_real): im_sol += FiniteSet(z) else: start, end = a.inf, a.sup for z in _nsort(critical_points + FiniteSet(end)): valid_start = valid(start) if start != end: valid_z = valid(z) pt = _pt(start, z) if (pt not in singularities and pt.is_extended_real and valid(pt)): if valid_start and valid_z: im_sol += Interval(start, z) elif valid_start: im_sol += Interval.Ropen(start, z) elif valid_z: im_sol += Interval.Lopen(start, z) else: im_sol += Interval.open(start, z) start = z for s in singularities: im_sol -= FiniteSet(s) except (TypeError): im_sol = S.Reals check = False if isinstance(im_sol, EmptySet): raise ValueError( filldedent(""" %s contains imaginary parts which cannot be made 0 for any value of %s satisfying the inequality, leading to relations like I < 0. """ % (expr.subs(gen, _gen), _gen))) make_real = make_real.intersect(im_sol) sol_sets = [S.EmptySet] start = domain.inf if valid(start) and start.is_finite: sol_sets.append(FiniteSet(start)) for x in reals: end = x if valid(_pt(start, end)): sol_sets.append(Interval(start, end, True, True)) if x in singularities: singularities.remove(x) else: if x in discontinuities: discontinuities.remove(x) _valid = valid(x) else: # it's a solution _valid = include_x if _valid: sol_sets.append(FiniteSet(x)) start = end end = domain.sup if valid(end) and end.is_finite: sol_sets.append(FiniteSet(end)) if valid(_pt(start, end)): sol_sets.append(Interval.open(start, end)) if im(expanded_e) != S.Zero and check: rv = (make_real).intersect(_domain) else: rv = Intersection((Union(*sol_sets)), make_real, _domain).subs(gen, _gen) return rv if not relational else rv.as_relational(_gen)
def symbols(self): return FiniteSet( *[sym for domain in self.domains for sym in domain.symbols])
def _intersect(self, other): from sympy.solvers.diophantine import diophantine if self.base_set is S.Integers: g = None if isinstance(other, ImageSet) and other.base_set is S.Integers: g = other.lamda.expr m = other.lamda.variables[0] elif other is S.Integers: m = g = Dummy('x') if g is not None: f = self.lamda.expr n = self.lamda.variables[0] # Diophantine sorts the solutions according to the alphabetic # order of the variable names, since the result should not depend # on the variable name, they are replaced by the dummy variables # below a, b = Dummy('a'), Dummy('b') f, g = f.subs(n, a), g.subs(m, b) solns_set = diophantine(f - g) if solns_set == set(): return EmptySet() solns = list(diophantine(f - g)) if len(solns) != 1: return # since 'a' < 'b', select soln for n nsol = solns[0][0] t = nsol.free_symbols.pop() return imageset(Lambda(n, f.subs(a, nsol.subs(t, n))), S.Integers) if other == S.Reals: from sympy.solvers.solveset import solveset_real from sympy.core.function import expand_complex if len(self.lamda.variables) > 1: return None f = self.lamda.expr n = self.lamda.variables[0] n_ = Dummy(n.name, real=True) f_ = f.subs(n, n_) re, im = f_.as_real_imag() im = expand_complex(im) return imageset(Lambda(n_, re), self.base_set.intersect(solveset_real(im, n_))) elif isinstance(other, Interval): from sympy.solvers.solveset import (invert_real, invert_complex, solveset) f = self.lamda.expr n = self.lamda.variables[0] base_set = self.base_set new_inf, new_sup = None, None if f.is_real: inverter = invert_real else: inverter = invert_complex g1, h1 = inverter(f, other.inf, n) g2, h2 = inverter(f, other.sup, n) if all(isinstance(i, FiniteSet) for i in (h1, h2)): if g1 == n: if len(h1) == 1: new_inf = h1.args[0] if g2 == n: if len(h2) == 1: new_sup = h2.args[0] # TODO: Design a technique to handle multiple-inverse # functions # Any of the new boundary values cannot be determined if any(i is None for i in (new_sup, new_inf)): return range_set = S.EmptySet if all(i.is_real for i in (new_sup, new_inf)): new_interval = Interval(new_inf, new_sup) range_set = base_set._intersect(new_interval) else: if other.is_subset(S.Reals): solutions = solveset(f, n, S.Reals) if not isinstance(range_set, (ImageSet, ConditionSet)): range_set = solutions._intersect(other) else: return if range_set is S.EmptySet: return S.EmptySet elif isinstance(range_set, Range) and range_set.size is not S.Infinity: range_set = FiniteSet(*list(range_set)) if range_set is not None: return imageset(Lambda(n, f), range_set) return else: return
def symbols(self): return FiniteSet(self.symbol)
def test_fun(): assert (FiniteSet( *ImageSet(Lambda(x, sin(pi * x / 4)), Range(-10, 11))) == FiniteSet( -1, -sqrt(2) / 2, 0, sqrt(2) / 2, 1))
def test_Range_set(): empty = Range(0) assert Range(5) == Range(0, 5) == Range(0, 5, 1) r = Range(10, 20, 2) assert 12 in r assert 8 not in r assert 11 not in r assert 30 not in r assert list(Range(0, 5)) == list(range(5)) assert list(Range(5, 0, -1)) == list(range(5, 0, -1)) assert Range(5, 15).sup == 14 assert Range(5, 15).inf == 5 assert Range(15, 5, -1).sup == 15 assert Range(15, 5, -1).inf == 6 assert Range(10, 67, 10).sup == 60 assert Range(60, 7, -10).inf == 10 assert len(Range(10, 38, 10)) == 3 assert Range(0, 0, 5) == empty assert Range(oo, oo, 1) == empty assert Range(oo, 1, 1) == empty assert Range(-oo, 1, -1) == empty assert Range(1, oo, -1) == empty assert Range(1, -oo, 1) == empty assert Range(1, -4, oo) == empty assert Range(1, -4, -oo) == Range(1, 2) assert Range(1, 4, oo) == Range(1, 2) assert Range(-oo, oo).size == oo assert Range(oo, -oo, -1).size == oo raises(ValueError, lambda: Range(-oo, oo, 2)) raises(ValueError, lambda: Range(x, pi, y)) raises(ValueError, lambda: Range(x, y, 0)) assert 5 in Range(0, oo, 5) assert -5 in Range(-oo, 0, 5) assert oo not in Range(0, oo) ni = symbols('ni', integer=False) assert ni not in Range(oo) u = symbols('u', integer=None) assert Range(oo).contains(u) is not False inf = symbols('inf', infinite=True) assert inf not in Range(-oo, oo) raises(ValueError, lambda: Range(0, oo, 2)[-1]) raises(ValueError, lambda: Range(0, -oo, -2)[-1]) assert Range(-oo, 1, 1)[-1] is S.Zero assert Range(oo, 1, -1)[-1] == 2 assert inf not in Range(oo) inf = symbols('inf', infinite=True) assert inf not in Range(oo) assert Range(-oo, 1, 1)[-1] is S.Zero assert Range(oo, 1, -1)[-1] == 2 assert Range(1, 10, 1)[-1] == 9 assert all(i.is_Integer for i in Range(0, -1, 1)) it = iter(Range(-oo, 0, 2)) raises(TypeError, lambda: next(it)) assert empty.intersect(S.Integers) == empty assert Range(-1, 10, 1).intersect(S.Integers) == Range(-1, 10, 1) assert Range(-1, 10, 1).intersect(S.Naturals) == Range(1, 10, 1) assert Range(-1, 10, 1).intersect(S.Naturals0) == Range(0, 10, 1) # test slicing assert Range(1, 10, 1)[5] == 6 assert Range(1, 12, 2)[5] == 11 assert Range(1, 10, 1)[-1] == 9 assert Range(1, 10, 3)[-1] == 7 raises(ValueError, lambda: Range(oo, 0, -1)[1:3:0]) raises(ValueError, lambda: Range(oo, 0, -1)[:1]) raises(ValueError, lambda: Range(1, oo)[-2]) raises(ValueError, lambda: Range(-oo, 1)[2]) raises(IndexError, lambda: Range(10)[-20]) raises(IndexError, lambda: Range(10)[20]) raises(ValueError, lambda: Range(2, -oo, -2)[2:2:0]) assert Range(2, -oo, -2)[2:2:2] == empty assert Range(2, -oo, -2)[:2:2] == Range(2, -2, -4) raises(ValueError, lambda: Range(-oo, 4, 2)[:2:2]) assert Range(-oo, 4, 2)[::-2] == Range(2, -oo, -4) raises(ValueError, lambda: Range(-oo, 4, 2)[::2]) assert Range(oo, 2, -2)[::] == Range(oo, 2, -2) assert Range(-oo, 4, 2)[:-2:-2] == Range(2, 0, -4) assert Range(-oo, 4, 2)[:-2:2] == Range(-oo, 0, 4) raises(ValueError, lambda: Range(-oo, 4, 2)[:0:-2]) raises(ValueError, lambda: Range(-oo, 4, 2)[:2:-2]) assert Range(-oo, 4, 2)[-2::-2] == Range(0, -oo, -4) raises(ValueError, lambda: Range(-oo, 4, 2)[-2:0:-2]) raises(ValueError, lambda: Range(-oo, 4, 2)[0::2]) assert Range(oo, 2, -2)[0::] == Range(oo, 2, -2) raises(ValueError, lambda: Range(-oo, 4, 2)[0:-2:2]) assert Range(oo, 2, -2)[0:-2:] == Range(oo, 6, -2) raises(ValueError, lambda: Range(oo, 2, -2)[0:2:]) raises(ValueError, lambda: Range(-oo, 4, 2)[2::-1]) assert Range(-oo, 4, 2)[-2::2] == Range(0, 4, 4) assert Range(oo, 0, -2)[-10:0:2] == empty raises(ValueError, lambda: Range(oo, 0, -2)[-10:10:2]) raises(ValueError, lambda: Range(oo, 0, -2)[0::-2]) assert Range(oo, 0, -2)[0:-4:-2] == empty assert Range(oo, 0, -2)[:0:2] == empty raises(ValueError, lambda: Range(oo, 0, -2)[:1:-1]) # test empty Range assert Range(x, x, y) == empty assert empty.reversed == empty assert 0 not in empty assert list(empty) == [] assert len(empty) == 0 assert empty.size is S.Zero assert empty.intersect(FiniteSet(0)) is S.EmptySet assert bool(empty) is False raises(IndexError, lambda: empty[0]) assert empty[:0] == empty raises(NotImplementedError, lambda: empty.inf) raises(NotImplementedError, lambda: empty.sup) AB = [None] + list(range(12)) for R in [ Range(1, 10), Range(1, 10, 2), ]: r = list(R) for a, b, c in cartes(AB, AB, [-3, -1, None, 1, 3]): for reverse in range(2): r = list(reversed(r)) R = R.reversed result = list(R[a:b:c]) ans = r[a:b:c] txt = ('\n%s[%s:%s:%s] = %s -> %s' % (R, a, b, c, result, ans)) check = ans == result assert check, txt assert Range(1, 10, 1).boundary == Range(1, 10, 1) for r in (Range(1, 10, 2), Range(1, oo, 2)): rev = r.reversed assert r.inf == rev.inf and r.sup == rev.sup assert r.step == -rev.step builtin_range = range raises(TypeError, lambda: Range(builtin_range(1))) assert S(builtin_range(10)) == Range(10) assert S(builtin_range(1000000000000)) == Range(1000000000000) # test Range.as_relational assert Range(1, 4).as_relational(x) == (x >= 1) & (x <= 3) & Eq(x, floor(x)) assert Range(oo, 1, -2).as_relational(x) == (x >= 3) & (x < oo) & Eq(x, floor(x))
def elements(self): return FiniteSet(*self)
def test_Range_symbolic(): # symbolic Range sr = Range(x, y, t) i = Symbol('i', integer=True) ip = Symbol('i', integer=True, positive=True) ir = Range(i, i + 20, 2) inf = symbols('inf', infinite=True) # args assert sr.args == (x, y, t) assert ir.args == (i, i + 20, 2) # reversed raises(ValueError, lambda: sr.reversed) assert ir.reversed == Range(i + 18, i - 2, -2) # contains assert inf not in sr assert inf not in ir assert .1 not in sr assert .1 not in ir assert i + 1 not in ir assert i + 2 in ir raises(TypeError, lambda: 1 in sr) # XXX is this what contains is supposed to do? # iter raises(ValueError, lambda: next(iter(sr))) assert next(iter(ir)) == i assert sr.intersect(S.Integers) == sr assert sr.intersect(FiniteSet(x)) == Intersection({x}, sr) raises(ValueError, lambda: sr[:2]) raises(ValueError, lambda: sr[0]) raises(ValueError, lambda: sr.as_relational(x)) # len assert len(ir) == ir.size == 10 raises(ValueError, lambda: len(sr)) raises(ValueError, lambda: sr.size) # bool assert bool(ir) == bool(sr) == True # getitem raises(ValueError, lambda: sr[0]) raises(ValueError, lambda: sr[-1]) raises(ValueError, lambda: sr[:2]) assert ir[:2] == Range(i, i + 4, 2) assert ir[0] == i assert ir[-2] == i + 16 assert ir[-1] == i + 18 raises(ValueError, lambda: Range(i)[-1]) assert Range(ip)[-1] == ip - 1 assert ir.inf == i assert ir.sup == i + 18 assert Range(ip).inf == 0 assert Range(ip).sup == ip - 1 raises(ValueError, lambda: Range(i).inf) # as_relational raises(ValueError, lambda: sr.as_relational(x)) assert ir.as_relational(x) == (x >= i) & Eq(x, floor(x)) & (x <= i + 18) assert Range(i, i + 1).as_relational(x) == Eq(x, i) # contains() for symbolic values (issue #18146) e = Symbol('e', integer=True, even=True) o = Symbol('o', integer=True, odd=True) assert Range(5).contains(i) == And(i >= 0, i <= 4) assert Range(1).contains(i) == Eq(i, 0) assert Range(-oo, 5, 1).contains(i) == (i <= 4) assert Range(-oo, oo).contains(i) == True assert Range(0, 8, 2).contains(i) == Contains(i, Range(0, 8, 2)) assert Range(0, 8, 2).contains(e) == And(e >= 0, e <= 6) assert Range(0, 8, 2).contains(2 * i) == And(2 * i >= 0, 2 * i <= 6) assert Range(0, 8, 2).contains(o) == False assert Range(1, 9, 2).contains(e) == False assert Range(1, 9, 2).contains(o) == And(o >= 1, o <= 7) assert Range(8, 0, -2).contains(o) == False assert Range(9, 1, -2).contains(o) == And(o >= 3, o <= 9) assert Range(-oo, 8, 2).contains(i) == Contains(i, Range(-oo, 8, 2))
def test_DiagramGrid(): # Set up some objects and morphisms. A = Object("A") B = Object("B") C = Object("C") D = Object("D") E = Object("E") f = NamedMorphism(A, B, "f") g = NamedMorphism(B, C, "g") h = NamedMorphism(D, A, "h") k = NamedMorphism(D, B, "k") # A one-morphism diagram. d = Diagram([f]) grid = DiagramGrid(d) assert grid.width == 2 assert grid.height == 1 assert grid[0, 0] == A assert grid[0, 1] == B assert grid.morphisms == {f: FiniteSet()} # A triangle. d = Diagram([f, g], {g * f: "unique"}) grid = DiagramGrid(d) assert grid.width == 2 assert grid.height == 2 assert grid[0, 0] == A assert grid[0, 1] == B assert grid[1, 0] == C assert grid[1, 1] is None assert grid.morphisms == {f: FiniteSet(), g: FiniteSet(), g * f: FiniteSet("unique")} # A triangle with a "loop" morphism. l_A = NamedMorphism(A, A, "l_A") d = Diagram([f, g, l_A]) grid = DiagramGrid(d) assert grid.width == 2 assert grid.height == 2 assert grid[0, 0] == A assert grid[0, 1] == B assert grid[1, 0] is None assert grid[1, 1] == C assert grid.morphisms == {f: FiniteSet(), g: FiniteSet(), l_A: FiniteSet()} # A simple diagram. d = Diagram([f, g, h, k]) grid = DiagramGrid(d) assert grid.width == 3 assert grid.height == 2 assert grid[0, 0] == A assert grid[0, 1] == B assert grid[0, 2] == D assert grid[1, 0] is None assert grid[1, 1] == C assert grid[1, 2] is None assert grid.morphisms == {f: FiniteSet(), g: FiniteSet(), h: FiniteSet(), k: FiniteSet()} assert str(grid) == '[[Object("A"), Object("B"), Object("D")], ' \ '[None, Object("C"), None]]' # A chain of morphisms. f = NamedMorphism(A, B, "f") g = NamedMorphism(B, C, "g") h = NamedMorphism(C, D, "h") k = NamedMorphism(D, E, "k") d = Diagram([f, g, h, k]) grid = DiagramGrid(d) assert grid.width == 3 assert grid.height == 3 assert grid[0, 0] == A assert grid[0, 1] == B assert grid[0, 2] is None assert grid[1, 0] is None assert grid[1, 1] == C assert grid[1, 2] == D assert grid[2, 0] is None assert grid[2, 1] is None assert grid[2, 2] == E assert grid.morphisms == {f: FiniteSet(), g: FiniteSet(), h: FiniteSet(), k: FiniteSet()} # A square. f = NamedMorphism(A, B, "f") g = NamedMorphism(B, D, "g") h = NamedMorphism(A, C, "h") k = NamedMorphism(C, D, "k") d = Diagram([f, g, h, k]) grid = DiagramGrid(d) assert grid.width == 2 assert grid.height == 2 assert grid[0, 0] == A assert grid[0, 1] == B assert grid[1, 0] == C assert grid[1, 1] == D assert grid.morphisms == {f: FiniteSet(), g: FiniteSet(), h: FiniteSet(), k: FiniteSet()} # A strange diagram which resulted from a typo when creating a # test for five lemma, but which allowed to stop one extra problem # in the algorithm. A = Object("A") B = Object("B") C = Object("C") D = Object("D") E = Object("E") A_ = Object("A'") B_ = Object("B'") C_ = Object("C'") D_ = Object("D'") E_ = Object("E'") f = NamedMorphism(A, B, "f") g = NamedMorphism(B, C, "g") h = NamedMorphism(C, D, "h") i = NamedMorphism(D, E, "i") # These 4 morphisms should be between primed objects. j = NamedMorphism(A, B, "j") k = NamedMorphism(B, C, "k") l = NamedMorphism(C, D, "l") m = NamedMorphism(D, E, "m") o = NamedMorphism(A, A_, "o") p = NamedMorphism(B, B_, "p") q = NamedMorphism(C, C_, "q") r = NamedMorphism(D, D_, "r") s = NamedMorphism(E, E_, "s") d = Diagram([f, g, h, i, j, k, l, m, o, p, q, r, s]) grid = DiagramGrid(d) assert grid.width == 3 assert grid.height == 4 assert grid[0, 0] is None assert grid[0, 1] == A assert grid[0, 2] == A_ assert grid[1, 0] == C assert grid[1, 1] == B assert grid[1, 2] == B_ assert grid[2, 0] == C_ assert grid[2, 1] == D assert grid[2, 2] == D_ assert grid[3, 0] is None assert grid[3, 1] == E assert grid[3, 2] == E_ morphisms = {} for m in [f, g, h, i, j, k, l, m, o, p, q, r, s]: morphisms[m] = FiniteSet() assert grid.morphisms == morphisms # A cube. A1 = Object("A1") A2 = Object("A2") A3 = Object("A3") A4 = Object("A4") A5 = Object("A5") A6 = Object("A6") A7 = Object("A7") A8 = Object("A8") # The top face of the cube. f1 = NamedMorphism(A1, A2, "f1") f2 = NamedMorphism(A1, A3, "f2") f3 = NamedMorphism(A2, A4, "f3") f4 = NamedMorphism(A3, A4, "f3") # The bottom face of the cube. f5 = NamedMorphism(A5, A6, "f5") f6 = NamedMorphism(A5, A7, "f6") f7 = NamedMorphism(A6, A8, "f7") f8 = NamedMorphism(A7, A8, "f8") # The remaining morphisms. f9 = NamedMorphism(A1, A5, "f9") f10 = NamedMorphism(A2, A6, "f10") f11 = NamedMorphism(A3, A7, "f11") f12 = NamedMorphism(A4, A8, "f11") d = Diagram([f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12]) grid = DiagramGrid(d) assert grid.width == 4 assert grid.height == 3 assert grid[0, 0] is None assert grid[0, 1] == A5 assert grid[0, 2] == A6 assert grid[0, 3] is None assert grid[1, 0] is None assert grid[1, 1] == A1 assert grid[1, 2] == A2 assert grid[1, 3] is None assert grid[2, 0] == A7 assert grid[2, 1] == A3 assert grid[2, 2] == A4 assert grid[2, 3] == A8 morphisms = {} for m in [f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12]: morphisms[m] = FiniteSet() assert grid.morphisms == morphisms # A line diagram. A = Object("A") B = Object("B") C = Object("C") D = Object("D") E = Object("E") f = NamedMorphism(A, B, "f") g = NamedMorphism(B, C, "g") h = NamedMorphism(C, D, "h") i = NamedMorphism(D, E, "i") d = Diagram([f, g, h, i]) grid = DiagramGrid(d, layout="sequential") assert grid.width == 5 assert grid.height == 1 assert grid[0, 0] == A assert grid[0, 1] == B assert grid[0, 2] == C assert grid[0, 3] == D assert grid[0, 4] == E assert grid.morphisms == {f: FiniteSet(), g: FiniteSet(), h: FiniteSet(), i: FiniteSet()} # Test the transposed version. grid = DiagramGrid(d, layout="sequential", transpose=True) assert grid.width == 1 assert grid.height == 5 assert grid[0, 0] == A assert grid[1, 0] == B assert grid[2, 0] == C assert grid[3, 0] == D assert grid[4, 0] == E assert grid.morphisms == {f: FiniteSet(), g: FiniteSet(), h: FiniteSet(), i: FiniteSet()} # A pullback. m1 = NamedMorphism(A, B, "m1") m2 = NamedMorphism(A, C, "m2") s1 = NamedMorphism(B, D, "s1") s2 = NamedMorphism(C, D, "s2") f1 = NamedMorphism(E, B, "f1") f2 = NamedMorphism(E, C, "f2") g = NamedMorphism(E, A, "g") d = Diagram([m1, m2, s1, s2, f1, f2], {g: "unique"}) grid = DiagramGrid(d) assert grid.width == 3 assert grid.height == 2 assert grid[0, 0] == A assert grid[0, 1] == B assert grid[0, 2] == E assert grid[1, 0] == C assert grid[1, 1] == D assert grid[1, 2] is None morphisms = {g: FiniteSet("unique")} for m in [m1, m2, s1, s2, f1, f2]: morphisms[m] = FiniteSet() assert grid.morphisms == morphisms # Test the pullback with sequential layout, just for stress # testing. grid = DiagramGrid(d, layout="sequential") assert grid.width == 5 assert grid.height == 1 assert grid[0, 0] == D assert grid[0, 1] == B assert grid[0, 2] == A assert grid[0, 3] == C assert grid[0, 4] == E assert grid.morphisms == morphisms # Test a pullback with object grouping. grid = DiagramGrid(d, groups=FiniteSet(E, FiniteSet(A, B, C, D))) assert grid.width == 3 assert grid.height == 2 assert grid[0, 0] == E assert grid[0, 1] == A assert grid[0, 2] == B assert grid[1, 0] is None assert grid[1, 1] == C assert grid[1, 2] == D assert grid.morphisms == morphisms # Five lemma, actually. A = Object("A") B = Object("B") C = Object("C") D = Object("D") E = Object("E") A_ = Object("A'") B_ = Object("B'") C_ = Object("C'") D_ = Object("D'") E_ = Object("E'") f = NamedMorphism(A, B, "f") g = NamedMorphism(B, C, "g") h = NamedMorphism(C, D, "h") i = NamedMorphism(D, E, "i") j = NamedMorphism(A_, B_, "j") k = NamedMorphism(B_, C_, "k") l = NamedMorphism(C_, D_, "l") m = NamedMorphism(D_, E_, "m") o = NamedMorphism(A, A_, "o") p = NamedMorphism(B, B_, "p") q = NamedMorphism(C, C_, "q") r = NamedMorphism(D, D_, "r") s = NamedMorphism(E, E_, "s") d = Diagram([f, g, h, i, j, k, l, m, o, p, q, r, s]) grid = DiagramGrid(d) assert grid.width == 5 assert grid.height == 3 assert grid[0, 0] is None assert grid[0, 1] == A assert grid[0, 2] == A_ assert grid[0, 3] is None assert grid[0, 4] is None assert grid[1, 0] == C assert grid[1, 1] == B assert grid[1, 2] == B_ assert grid[1, 3] == C_ assert grid[1, 4] is None assert grid[2, 0] == D assert grid[2, 1] == E assert grid[2, 2] is None assert grid[2, 3] == D_ assert grid[2, 4] == E_ morphisms = {} for m in [f, g, h, i, j, k, l, m, o, p, q, r, s]: morphisms[m] = FiniteSet() assert grid.morphisms == morphisms # Test the five lemma with object grouping. grid = DiagramGrid(d, FiniteSet( FiniteSet(A, B, C, D, E), FiniteSet(A_, B_, C_, D_, E_))) assert grid.width == 6 assert grid.height == 3 assert grid[0, 0] == A assert grid[0, 1] == B assert grid[0, 2] is None assert grid[0, 3] == A_ assert grid[0, 4] == B_ assert grid[0, 5] is None assert grid[1, 0] is None assert grid[1, 1] == C assert grid[1, 2] == D assert grid[1, 3] is None assert grid[1, 4] == C_ assert grid[1, 5] == D_ assert grid[2, 0] is None assert grid[2, 1] is None assert grid[2, 2] == E assert grid[2, 3] is None assert grid[2, 4] is None assert grid[2, 5] == E_ assert grid.morphisms == morphisms # Test the five lemma with object grouping, but mixing containers # to represent groups. grid = DiagramGrid(d, [(A, B, C, D, E), {A_, B_, C_, D_, E_}]) assert grid.width == 6 assert grid.height == 3 assert grid[0, 0] == A assert grid[0, 1] == B assert grid[0, 2] is None assert grid[0, 3] == A_ assert grid[0, 4] == B_ assert grid[0, 5] is None assert grid[1, 0] is None assert grid[1, 1] == C assert grid[1, 2] == D assert grid[1, 3] is None assert grid[1, 4] == C_ assert grid[1, 5] == D_ assert grid[2, 0] is None assert grid[2, 1] is None assert grid[2, 2] == E assert grid[2, 3] is None assert grid[2, 4] is None assert grid[2, 5] == E_ assert grid.morphisms == morphisms # Test the five lemma with object grouping and hints. grid = DiagramGrid(d, { FiniteSet(A, B, C, D, E): {"layout": "sequential", "transpose": True}, FiniteSet(A_, B_, C_, D_, E_): {"layout": "sequential", "transpose": True}}, transpose=True) assert grid.width == 5 assert grid.height == 2 assert grid[0, 0] == A assert grid[0, 1] == B assert grid[0, 2] == C assert grid[0, 3] == D assert grid[0, 4] == E assert grid[1, 0] == A_ assert grid[1, 1] == B_ assert grid[1, 2] == C_ assert grid[1, 3] == D_ assert grid[1, 4] == E_ assert grid.morphisms == morphisms # A two-triangle disconnected diagram. f = NamedMorphism(A, B, "f") g = NamedMorphism(B, C, "g") f_ = NamedMorphism(A_, B_, "f") g_ = NamedMorphism(B_, C_, "g") d = Diagram([f, g, f_, g_], {g * f: "unique", g_ * f_: "unique"}) grid = DiagramGrid(d) assert grid.width == 4 assert grid.height == 2 assert grid[0, 0] == A assert grid[0, 1] == B assert grid[0, 2] == A_ assert grid[0, 3] == B_ assert grid[1, 0] == C assert grid[1, 1] is None assert grid[1, 2] == C_ assert grid[1, 3] is None assert grid.morphisms == {f: FiniteSet(), g: FiniteSet(), f_: FiniteSet(), g_: FiniteSet(), g * f: FiniteSet("unique"), g_ * f_: FiniteSet("unique")} # A two-morphism disconnected diagram. f = NamedMorphism(A, B, "f") g = NamedMorphism(C, D, "g") d = Diagram([f, g]) grid = DiagramGrid(d) assert grid.width == 4 assert grid.height == 1 assert grid[0, 0] == A assert grid[0, 1] == B assert grid[0, 2] == C assert grid[0, 3] == D assert grid.morphisms == {f: FiniteSet(), g: FiniteSet()} # Test a one-object diagram. f = NamedMorphism(A, A, "f") d = Diagram([f]) grid = DiagramGrid(d) assert grid.width == 1 assert grid.height == 1 assert grid[0, 0] == A # Test a two-object disconnected diagram. g = NamedMorphism(B, B, "g") d = Diagram([f, g]) grid = DiagramGrid(d) assert grid.width == 2 assert grid.height == 1 assert grid[0, 0] == A assert grid[0, 1] == B