[docs]classSet(Basic):""" Represents any kind of set. Real intervals are represented by the Interval class and unions of sets by the Union class. The empty set is represented by the EmptySet class and available as a singleton as S.EmptySet. """

[docs]defcontains(self,other):""" Returns True if 'other' is contained in 'self' as an element. As a shortcut it is possible to use the 'in' operator: >>> from sympy import Interval >>> Interval(0, 1).contains(0.5) True >>> 0.5 in Interval(0, 1) True """returnself._contains(other)

@propertydef_measure(self):raiseNotImplementedError("(%s)._measure"%self)def__add__(self,other):returnself.union(other)def__or__(self,other):returnself.union(other)def__and__(self,other):returnself.intersect(other)def__mul__(self,other):returnProductSet(self,other)def__pow__(self,exp):ifnotsympify(exp).is_Integerandexp>=0:raiseValueError("%s: Exponent must be a positive Integer"%exp)returnProductSet([self]*exp)def__sub__(self,other):returnself.intersect(other.complement)def__neg__(self):returnself.complementdef__invert__(self):returnself.complementdef__contains__(self,other):result=self.contains(other)ifnotisinstance(result,bool):raiseTypeError('contains did not evaluate to a bool: %r'%result)returnresultdef_eval_subs(self,old,new):ifself==old:returnnewnew_args=[]forarginself.args:ifarg==old:new_args.append(new)elifisinstance(arg,Basic):new_args.append(arg._eval_subs(old,new))else:new_args.append(arg)returnself.__class__(*new_args)@propertydefis_number(self):returnFalse@propertydefis_real(self):returnFalse@propertydefis_iterable(self):returnFalse@propertydefis_interval(self):returnFalse@propertydefis_FiniteSet(self):returnFalse@propertydefis_Interval(self):returnFalse@propertydefis_ProductSet(self):returnFalse@propertydefis_Union(self):returnFalse

classRealSet(Set,EvalfMixin):""" A set of real values """@propertydefis_real(self):returnTrueclassProductSet(Set):""" Represents a Cartesian Product of Sets. Usage: Returns a cartesian product given several sets as either an iterable or individual arguments. Can use '*' operator on any sets for convenient shorthand. Examples: >>> from sympy import Interval, FiniteSet, ProductSet >>> I = Interval(0, 5); S = FiniteSet(1, 2, 3) >>> ProductSet(I, S) [0, 5] x {1, 2, 3} >>> (2, 2) in ProductSet(I, S) True >>> Interval(0, 1) * Interval(0, 1) # The unit square [0, 1] x [0, 1] >>> coin = FiniteSet('H','T') >>> for pair in coin**2: print pair (H, H) (H, T) (T, H) (T, T) Notes: - Passes most operations down to the argument sets - Flattens Products of ProductSets """def__new__(cls,*sets,**assumptions):defflatten(arg):ifisinstance(arg,Set):ifarg.is_ProductSet:returnsum(map(flatten,arg.args),[])else:return[arg]elifis_flattenable(arg):returnsum(map(flatten,arg),[])raiseTypeError("Input must be Sets or iterables of Sets")sets=flatten(list(sets))ifEmptySet()insetsorlen(sets)==0:returnEmptySet()returnBasic.__new__(cls,*sets,**assumptions)def_contains(self,element):""" in operator for ProductSets >>> from sympy import Interval >>> (2, 3) in Interval(0, 5) * Interval(0, 5) True >>> (10, 10) in Interval(0, 5) * Interval(0, 5) False Passes operation on to constitent sets """iflen(element)isnotlen(self.args):returnFalsefromsympy.logic.boolalgimportAndreturnAnd(*[set.contains(item)forset,iteminzip(self.sets,element)])def_intersect(self,other):ifother.is_Union:returnUnion(self.intersect(set)forsetinother.args)ifnotother.is_ProductSet:raiseTypeError("%s is not a Product Set."%str(other))iflen(other.args)!=len(self.args):raiseValueError("Sets not the same size Left: %d, Right: %d"%(len(self.args),len(other.args)))returnProductSet(a.intersect(b)fora,binzip(self.sets,other.sets))@propertydefsets(self):returnself.args@propertydef_complement(self):# For each set consider it or it's complement# We need at least one of the sets to be complemented# Consider all 2^n combinations.# We can conveniently represent these options easily using a ProductSetswitch_sets=ProductSet(FiniteSet(set,set.complement)forsetinself.sets)product_sets=(ProductSet(*set)forsetinswitch_sets)# Union of all combinations but this onereturnUnion(pforpinproduct_setsifp!=self)@propertydefis_real(self):returnall(set.is_realforsetinself.sets)@propertydefis_iterable(self):returnall(set.is_iterableforsetinself.sets)def__iter__(self):ifself.is_iterable:fromsympy.core.compatibilityimportproductreturnproduct(*self.sets)else:raiseTypeError("Not all constituent sets are iterable")@propertydef_measure(self):measure=1forsetinself.sets:measure*=set.measurereturnmeasure@propertydefis_ProductSet(self):returnTrueclassRealSet(Set,EvalfMixin):""" A set of real values """@propertydefis_real(self):returnTrueclassCountableSet(Set):""" Represents a set of countable numbers such as {1, 2, 3, 4} or {1, 2, 3, ...} """@propertydef_measure(self):return0@propertydefis_iterable(self):returnTruedef__iter__(self):raiseNotImplementedError("Iteration not yet implemented")

[docs]classInterval(RealSet):""" Represents a real interval as a Set. Usage: Returns an interval with end points "start" and "end". For left_open=True (default left_open is False) the interval will be open on the left. Similarly, for right_open=True the interval will be open on the right. Examples: >>> from sympy import Symbol, Interval, sets >>> Interval(0, 1) [0, 1] >>> Interval(0, 1, False, True) [0, 1) >>> a = Symbol('a', real=True) >>> Interval(0, a) [0, a] Notes: - Only real end points are supported - Interval(a, b) with a > b will return the empty set - Use the evalf() method to turn an Interval into an mpmath 'mpi' interval instance """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').ifnotstart.is_realornotend.is_real:raiseValueError("Only real intervals are supported")# Make sure that the created interval will be valid.ifend.is_comparableandstart.is_comparable:ifend<start:returnS.EmptySetifend==startand(left_openorright_open):returnS.EmptySetifend==startandnot(left_openorright_open):returnFiniteSet(end)# Make sure infinite interval end points are open.ifstart==S.NegativeInfinity:left_open=Trueifend==S.Infinity:right_open=TruereturnBasic.__new__(cls,start,end,left_open,right_open)@property

[docs]defstart(self):""" The left end point of 'self'. This property takes the same value as the 'inf' property. >>> from sympy import Interval >>> Interval(0, 1).start 0 """returnself._args[0]

_inf=left=start@property

[docs]defend(self):""" The right end point of 'self'. This property takes the same value as the 'sup' property. >>> from sympy import Interval >>> Interval(0, 1).end 1 """returnself._args[1]

def_intersect(self,other):ifnotisinstance(other,Interval):returnother.intersect(self)ifnotself._is_comparable(other):raiseNotImplementedError("Intersection of intervals with symbolic ""end points is not yet implemented")empty=Falseifself.start<=other.endandother.start<=self.end:# Get topology right.ifself.start<other.start:start=other.startleft_open=other.left_openelifself.start>other.start:start=self.startleft_open=self.left_openelse:start=self.startleft_open=self.left_openorother.left_openifself.end<other.end:end=self.endright_open=self.right_openelifself.end>other.end:end=other.endright_open=other.right_openelse:end=self.endright_open=self.right_openorother.right_openifend-start==0and(left_openorright_open):empty=Trueelse:empty=Trueifempty:returnS.EmptySetreturnself.__class__(start,end,left_open,right_open)@propertydef_complement(self):a=Interval(S.NegativeInfinity,self.start,True,notself.left_open)b=Interval(self.end,S.Infinity,notself.right_open,True)returnUnion(a,b)def_contains(self,other):# We use the logic module here so that this method is meaningful# when used with symbolic end points.fromsympy.logic.boolalgimportAndtry:other=_sympify(other)exceptSympifyError:returnFalseifself.left_open:expr=other>self.startelse:expr=other>=self.startifself.right_open:expr=And(expr,other<self.end)else:expr=And(expr,other<=self.end)returnexpr@propertydef_measure(self):returnself.end-self.startdefto_mpi(self,prec=53):returnmpi(mpf(self.start.evalf(prec)),mpf(self.end.evalf(prec)))def_eval_evalf(self,prec):returnInterval(self.left.evalf(),self.right.evalf(),left_open=self.left_open,right_open=self.right_open)def_is_comparable(self,other):is_comparable=self.start.is_comparableis_comparable&=self.end.is_comparableis_comparable&=other.start.is_comparableis_comparable&=other.end.is_comparablereturnis_comparable@propertydefis_Interval(self):returnTrue@property

[docs]defis_left_unbounded(self):"""Return ``True`` if the left endpoint is negative infinity. """returnself.leftisS.NegativeInfinityorself.left==Float("-inf")

@property

[docs]defis_right_unbounded(self):"""Return ``True`` if the right endpoint is positive infinity. """returnself.rightisS.Infinityorself.right==Float("+inf")

[docs]classUnion(Set):""" Represents a union of sets as a Set. Examples: >>> from sympy import Union, Interval >>> Union(Interval(1, 2), Interval(3, 4)) [1, 2] U [3, 4] The Union constructor will always try to merge overlapping intervals, if possible. For example: >>> Union(Interval(1, 2), Interval(2, 3)) [1, 3] """def__new__(cls,*args):# Flatten out Iterators and Unions to form one list of setsargs=list(args)defflatten(arg):ifarg==S.EmptySet:return[]ifisinstance(arg,Set):ifarg.is_Union:returnsum(map(flatten,arg.args),[])else:return[arg]ifis_flattenable(arg):# and not isinstance(arg, Set) (implicit)returnsum(map(flatten,arg),[])raiseTypeError("Input must be Sets or iterables of Sets")args=flatten(args)iflen(args)==0:returnS.EmptySet# Only real parts? Return a RealUnionifall(arg.is_realforarginargs):returnRealUnion(args)# Lets find and merge real elements if we have them# Separate into finite, real and other setsfinite_set=sum([sforsinargsifs.is_FiniteSet],S.EmptySet)real_sets=[sforsinargsifs.is_real]other_sets=[sforsinargsifnots.is_FiniteSetandnots.is_real]# Separate finite_set into real and other partreal_finite=RealFiniteSet(iforiinfinite_setifi.is_real)other_finite=FiniteSet(iforiinfinite_setifnoti.is_real)# Merge real part of setreal_union=RealUnion(real_sets+[real_finite])ifnotreal_union:# Real part was emptysets=other_sets+[other_finite]elifreal_union.is_FiniteSet:# Real part was just a FiniteSetsets=other_sets+[real_union+other_finite]elifreal_union.is_Interval:# Real part was just an Intervalsets=[real_union]+other_sets+[other_finite]# If is_RealUnion then separateelifreal_union.is_Unionandreal_union.is_real:intervals=[sforsinreal_union.argsifs.is_Interval]finite_set=sum([sforsinreal_union.argsifs.is_FiniteSet]+[other_finite],S.EmptySet)# Join FiniteSet back togethersets=intervals+[finite_set]+other_sets# Clear out Empty Setssets=[setforsetinsetsifset!=S.EmptySet]# If a single set is left over, don't create a new Union object but# rather return the single set.iflen(sets)==1:returnsets[0]returnBasic.__new__(cls,*sets)@propertydef_inf(self):# We use Min so that sup is meaningful in combination with symbolic# interval end points.fromsympy.functions.elementary.miscellaneousimportMinreturnMin(*[set.infforsetinself.args])@propertydef_sup(self):# We use Max so that sup is meaningful in combination with symbolic# end points.fromsympy.functions.elementary.miscellaneousimportMaxreturnMax(*[set.supforsetinself.args])def_intersect(self,other):# Distributivity.ifother.is_Interval:intersections=[]forintervalinself.args:intersections.append(interval.intersect(other))returnself.__class__(*intersections)ifother.is_FiniteSet:returnother._intersect(self)elifother.is_Union:intersections=[]forsinother.args:intersections.append(self.intersect(s))returnself.__class__(*intersections)else:returnother.intersect(self)@propertydef_complement(self):# De Morgan's formula.complement=self.args[0].complementforsetinself.args[1:]:complement=complement.intersect(set.complement)returncomplementdef_contains(self,other):fromsympy.logic.boolalgimportOror_args=[the_set.contains(other)forthe_setinself.args]returnOr(*or_args)@propertydef_measure(self):# Measure of a union is the sum of the measures of the sets minus# the sum of their pairwise intersections plus the sum of their# triple-wise intersections minus ... etc...# Sets is a collection of intersections and a set of elementary# sets which made up those interections (called "sos" for set of sets)# An example element might of this list might be:# ( {A,B,C}, A.intersect(B).intersect(C) )# Start with just elementary sets ( ({A}, A), ({B}, B), ... )# Then get and subtract ( ({A,B}, (A int B), ... ) while non-zerosets=[(FiniteSet(s),s)forsinself.args]measure=0parity=1whilesets:# Add up the measure of these sets and add or subtract it to totalmeasure+=parity*sum(inter.measureforsos,interinsets)# For each intersection in sets, compute the intersection with every# other set not already part of the intersection.sets=((sos+FiniteSet(newset),newset.intersect(intersection))forsos,intersectioninsetsfornewsetinself.argsifnewsetnotinsos)# Clear out sets with no measuresets=[(sos,inter)forsos,interinsetsifinter.measure!=0]# Clear out duplicatessos_list=[]sets_list=[]forsetinsets:ifset[0]insos_list:continueelse:sos_list.append(set[0])sets_list.append(set)sets=sets_list# Flip Parity - next time subtract/add if we added/subtracted hereparity*=-1returnmeasure

[docs]defas_relational(self,symbol):"""Rewrite a Union in terms of equalities and logic operators. """fromsympy.logic.boolalgimportOrreturnOr(*[set.as_relational(symbol)forsetinself.args])

classRealUnion(Union,RealSet):""" Represents a union of Real Sets (Intervals, RealFiniteSets) This class should only be used internally. Please make unions with Union class. See Union for details """def__new__(cls,*args):intervals,finite_sets,other_sets=[],[],[]args=list(args)forarginargs:ifisinstance(arg,Set):ifarg==S.EmptySet:continueelifarg.is_Union:args+=arg.argselifarg.is_FiniteSet:finite_sets.append(arg)elifarg.is_Interval:intervals.append(arg)else:other_sets.append(arg)elifis_flattenable(arg):args+=argelse:raiseTypeError("%s: Not a set or iterable of sets"%arg)# Sort intervals according to their infimumintervals.sort(key=lambdai:i.start)# Merge comparable overlapping intervalsi=0whilei<len(intervals)-1:cur=intervals[i]next=intervals[i+1]merge=Falseifcur._is_comparable(next):ifnext.start<cur.end:merge=Trueelifnext.start==cur.end:# Must be careful with boundaries.merge=not(next.left_openandcur.right_open)ifmerge:ifcur.start==next.start:left_open=cur.left_openandnext.left_openelse:left_open=cur.left_openifcur.end<next.end:right_open=next.right_openend=next.endelifcur.end>next.end:right_open=cur.right_openend=cur.endelse:right_open=cur.right_openandnext.right_openend=cur.endintervals[i]=Interval(cur.start,end,left_open,right_open)delintervals[i+1]else:i+=1# Collect all elements in the finite sets not in any intervaliffinite_sets:# Merge Finite Setsfinite_set=sum(finite_sets,S.EmptySet)# Close open intervals if boundary is in finite_setfornum,iinenumerate(intervals):closeLeft=i.startinfinite_setifi.left_openelseFalsecloseRight=i.endinfinite_setifi.right_openelseFalseif((closeLeftandi.left_open)or(closeRightandi.right_open)):intervals[num]=Interval(i.start,i.end,notcloseLeft,notcloseRight)# All elements in finite_set not in any intervalfinite_complement=FiniteSet(elforelinfinite_setifnotel.is_numberornotany(eliniforiinintervals))iflen(finite_complement)>0:# Anything left?other_sets.append(finite_complement)# Clear out empty setssets=[setforsetin(intervals+other_sets)ifset]# If nothing is there then return the empty setifnotsets:returnS.EmptySet# If a single set is left over, don't create a new Union object but# rather return the single set.iflen(sets)==1:returnsets[0]returnBasic.__new__(cls,*sets)def_eval_evalf(self,prec):returnRealUnion(set.evalf()forsetinself.args)def__iter__(self):importitertoolsifall(set.is_iterableforsetinself.args):returnitertools.chain(*(iter(arg)forarginself.args))else:raiseTypeError("Not all constituent sets are iterable")

[docs]classEmptySet(Set):""" Represents the empty set. The empty set is available as a singleton as S.EmptySet. Examples: >>> from sympy import S, Interval >>> S.EmptySet EmptySet() >>> Interval(1, 2).intersect(S.EmptySet) EmptySet() """__metaclass__=Singletondef_intersect(self,other):returnS.EmptySet@propertydef_complement(self):returnInterval(S.NegativeInfinity,S.Infinity)@propertydef_measure(self):return0def_contains(self,other):returnFalsedefas_relational(self,symbol):returnFalsedef__len__(self):return0defunion(self,other):returnotherdef__iter__(self):returniter([])

classFiniteSet(CountableSet):""" Represents a finite set of discrete numbers Examples: >>> from sympy import Symbol, FiniteSet, sets >>> FiniteSet(1, 2, 3, 4) {1, 2, 3, 4} >>> 3 in FiniteSet(1, 2, 3, 4) True """def__new__(cls,*args):defflatten(arg):ifis_flattenable(arg):returnsum(map(flatten,arg),[])return[arg]args=flatten(list(args))# Sympify Argumentsargs=map(sympify,args)# Turn tuples into Tuplesargs=[Tuple(*arg)ifarg.__class__istupleelseargforarginargs]iflen(args)==0:returnEmptySet()ifall([arg.is_realandarg.is_numberforarginargs]):cls=RealFiniteSetelements=frozenset(map(sympify,args))obj=Basic.__new__(cls,*elements)obj.elements=elementsreturnobjdef__iter__(self):returnself.elements.__iter__()def_intersect(self,other):ifisinstance(other,self.__class__):returnself.__class__(*(self.elements&other.elements))returnself.__class__(elforelinselfifelinother)defunion(self,other):""" Returns the union of 'self' and 'other'. As a shortcut it is possible to use the '+' operator: >>> from sympy import FiniteSet, Interval, Symbol >>> FiniteSet(0, 1).union(FiniteSet(2, 3)) {0, 1, 2, 3} >>> FiniteSet(Symbol('x'), 1, 2) + FiniteSet(2, 3) {1, 2, 3, x} >>> Interval(1, 2, True, True) + FiniteSet(2, 3) (1, 2] U {3} Similarly it is possible to use the '-' operator for set differences: >>> FiniteSet(Symbol('x'), 1, 2) - FiniteSet(2, 3) {1, x} >>> Interval(1, 2) - FiniteSet(2, 3) [1, 2) """ifother==S.EmptySet:returnselfifother.is_FiniteSet:returnFiniteSet(*(self.elements|other.elements))returnUnion(self,other)# Resort to defaultdef_contains(self,other):""" Tests whether an element, other, is in the set. Relies on Python's set class. This tests for object equality All inputs are sympified >>> from sympy import FiniteSet >>> 1 in FiniteSet(1, 2) True >>> 5 in FiniteSet(1, 2) False """returnsympify(other)inself.elements@propertydef_inf(self):fromsympy.functions.elementary.miscellaneousimportMinreturnMin(*self)@propertydef_sup(self):fromsympy.functions.elementary.miscellaneousimportMaxreturnMax(*self)def__len__(self):returnlen(self.elements)def__sub__(self,other):returnFiniteSet(elforelinselfifelnotinother)defas_relational(self,symbol):"""Rewrite a FiniteSet in terms of equalities and logic operators. """fromsympy.core.relationalimportEqfromsympy.logic.boolalgimportOrreturnOr(*[Eq(symbol,elem)foreleminself])@propertydefis_FiniteSet(self):returnTrue@propertydefis_real(self):returnall(el.is_realforelinself)classRealFiniteSet(FiniteSet,RealSet):""" A FiniteSet with all elements Real Numbers. Allows for good integration with Intervals This class for internal use only. Use FiniteSet to create a RealFiniteSet See FiniteSet for more details """def_eval_evalf(self,prec):returnRealFiniteSet(elem.evalf(prec)foreleminself)@propertydef_complement(self):""" The complement of a real finite set is the Union of open Intervals between the elements of the set. >>> from sympy import FiniteSet >>> FiniteSet(1, 2, 3).complement (-oo, 1) U (1, 2) U (2, 3) U (3, oo) """ifnotall(elem.is_numberforeleminself.elements):raiseValueError("%s: Complement not defined for symbolic inputs"%self)sorted_elements=sorted(list(self.elements))intervals=[]# Build up a list of intervals between the elementsintervals+=[Interval(S.NegativeInfinity,sorted_elements[0],True,True)]fora,binzip(sorted_elements[0:-1],sorted_elements[1:]):intervals.append(Interval(a,b,True,True))# open intervalsintervals.append(Interval(sorted_elements[-1],S.Infinity,True,True))returnUnion(*intervals)defas_relational(self,symbol):"""Rewrite a FiniteSet in terms of equalities and logic operators. """fromsympy.core.relationalimportEqfromsympy.logic.boolalgimportOrreturnOr(*[Eq(symbol,elem)foreleminself])def_eval_evalf(self,prec):returnFiniteSet(elem.evalf(prec)foreleminself)genclass=(1foriinxrange(2)).__class__defis_flattenable(obj):""" Checks that an argument to a Set constructor should be flattened """returnobj.__class__in[list,set,genclass]