Hello.
That's a good idea but you will have to explain what you mean by infinite
sets.
An easy task is to produce something for the reunions of intervals which can
contain {a} = [a, a].
I've made an incomplete code so as to work with intervals (I'm not sure that
all the classes work well). Feel free to correct it, and adapt and port it
to sympy.
Christophe BAL
=== My code - START ===
#!/usr/bin/env python
#coding=utf-8
# Code writing by BAL Christophe
# Mail : [email protected]
def endPointsToUser(europeanEndpoints, notation):
# Lines automatically built by tool_simpleSets.py. ===== START
epEuropean_2_User = {}
# AM-erican notations.
epEuropean_2_User['am'] = {']]': '(]', '[[': '[)', '[]': '[]', '][':
'()'}
# CZ-ech notations.
epEuropean_2_User['cz'] = {']]': '(>', '[[': '<)', '[]': '<>', '][':
'()'}
# EU-ropean notations.
epEuropean_2_User['eu'] = {'[[': '[[', ']]': ']]', '][': '][', '[]':
'[]'}
# Lines automatically built by tool_simpleSets.py. ===== END
return epEuropean_2_User[notation][europeanEndpoints]
class Interval():
"""
"""
def __init__(self, minPoint=0, maxPoint=0, endpoints='', notation =
'am'):
# Lines automatically built by tool_simpleSets.py. ===== START
epNotationIsValid = {}
epUser_2_European = {}
# AM-erican notations.
epNotationIsValid['am'] = ['[]', '(]', '[)', '()']
epUser_2_European['am'] = [{'(': ']', '[': '['}, {')': '[', ']':
']'}]
# CZ-ech notations.
epNotationIsValid['cz'] = ['<>', '(>', '<)', '()']
epUser_2_European['cz'] = [{'(': ']', '<': '['}, {')': '[', '>':
']'}]
# EU-ropean notations.
epNotationIsValid['eu'] = ['[]', ']]', '[[', '][']
epUser_2_European['eu'] = [{'[': '[', ']': ']'}, {'[': '[', ']':
']'}]
# Lines automatically built by tool_simpleSets.py. ===== END
self.notation = notation
# An empty set ?
if endpoints == '':
minPoint = 0
minPoint = 0
endpoints = endPointsToUser('][', self.notation)
if minPoint=='+inf':
raise TypeError('The first value ' + str(minPoint) + ' is not
lower or equal to the second one ' + str(maxPoint) + '.')
elif maxPoint=='-inf':
raise TypeError('The first value ' + str(minPoint) + ' is not
lower or equal to the second one ' + str(maxPoint) + '.')
elif minPoint != '-inf' and maxPoint != '+inf':
if minPoint > maxPoint:
raise TypeError('The first value ' + str(minPoint) + ' is
not lower or equal to the second one ' + str(maxPoint) + '.')
self.minPoint = minPoint
self.maxPoint = maxPoint
self.endpoints = endpoints
if self.endpoints not in epNotationIsValid[self.notation]:
raise TypeError('Unknown endpoints of interval : "' +
str(endpoints) + '"')
# In the code we are gonning to work with the european notations.
if self.notation == 'eu':
self.europeanEndpoints = self.endpoints
else:
self.europeanEndpoints =
epUser_2_European[self.notation][0][self.endpoints[0]] +
epUser_2_European[self.notation][1][self.endpoints[1]]
# print 'self.notation = ' + self.notation
# print 'self.endpoints = ' + self.endpoints
# print 'self.europeanEndpoints = ' + self.europeanEndpoints
def __str__(self):
if self.minPoint == self.maxPoint:
if self.europeanEndpoints == '[]':
return '{' + str(self.minPoint) + '}'
else:
return 'Empty Set'
return self.endpoints[0] + str(self.minPoint) + ';' +
str(self.maxPoint) + self.endpoints[1]
# Thanks to Nicolas we explain me this trick.
@property
def isEmpty(self):
return str(self) == 'Empty Set'
def __and__(self, otherInterval):
# We reimplement the use of & .
# The intersection is empty.
if self.isEmpty or otherInterval.isEmpty:
return Interval()
maxOfminPoints = max(self.minPoint, otherInterval.minPoint)
minOfmaxPoints = min(self.maxPoint, otherInterval.maxPoint)
if maxOfminPoints > minOfmaxPoints:
return Interval()
# The intersection could be a set with a single element.
if minOfmaxPoints == maxOfminPoints:
if self.maxPoint == minOfmaxPoints:
if self.europeanEndpoints[1] == '[' or
otherInterval.europeanEndpoints[0] ==']':
return Interval()
else:
return Interval(minOfmaxPoints, minOfmaxPoints,
endPointsToUser('[]', self.notation), self.notation)
else:
if self.europeanEndpoints[0] == ']' or
otherInterval.europeanEndpoints[1] =='[':
return Interval()
else:
return Interval(minOfmaxPoints, minOfmaxPoints,
endPointsToUser('[]', self.notation), self.notation)
# What is the endpoints of the intersection ?
interEndPtMin = '['
if self.minPoint == maxOfminPoints :
interEndPtMin = self.europeanEndpoints[0]
if otherInterval.minPoint == maxOfminPoints and interEndPtMin ==
'[':
interEndPtMin = otherInterval.europeanEndpoints[0]
interEndPtMax = ']'
if self.maxPoint == minOfmaxPoints :
interEndPtMax = self.europeanEndpoints[1]
if otherInterval.maxPoint == minOfmaxPoints and interEndPtMax ==
']':
interEndPtMax = otherInterval.europeanEndpoints[1]
# print 'interEndPtMin + interEndPtMax'
# print interEndPtMin + interEndPtMax
# print endPointsToUser(interEndPtMin + interEndPtMax, self.notation)
return Interval(maxOfminPoints, minOfmaxPoints,
endPointsToUser(interEndPtMin + interEndPtMax, self.notation),
self.notation)
def __or__(self, otherSet):
# We reimplement the use of or.
if self.isEmpty :
return otherSet
if isinstance(otherSet, Interval):
# print UnionIntervals([self, otherSet]).simplify()
return UnionIntervals([self, otherSet]).simplify()
else:
# print otherSet
# print isinstance(otherSet[0], UnionIntervals)
return UnionIntervals([self] +
otherSet.shorListIntervals).simplify()
def __mul__(self, realNumber):
"""
I*k ok mais pas k*I : il faudrait réimplémenter les multiplications
des réels,...
"""
# We reimplement the use of or.
if isinstance(realNumber, int):
if realNumber < 0:
if self.europeanEndpoints[1]=='[':
newEndpoints = ']'
else:
newEndpoints = '['
if self.europeanEndpoints[0]==']':
newEndpoints += '['
else:
newEndpoints += ']'
return Interval(realNumber*self.maxPoint,
realNumber*self.minPoint, endPointsToUser(newEndpoints, self.notation),
self.notation)
else:
return Interval(realNumber*self.minPoint,
realNumber*self.maxPoint, self.endpoints, self.notation)
else:
raise Exception('You can multiply an interval only by an
interger')
def __rmul__(self, realNumber):
""" I*k ok mais pas k*I : il faudrait réimplémenter les
multiplications des réels,...
"""
# We reimplement the use of or.
return self*realNumber
def __add__(self, otherSet):
# We reimplement the use of or.
if isinstance(otherSet, Interval):
if self.isEmpty or otherSet.isEmpty:
return Interval()
if self.minPoint == '-inf' or otherSet.minPoint == '-inf' :
minAddIntervals = '-inf'
endpointsAddIntervals = ']'
else:
minAddIntervals = self.minPoint + otherSet.minPoint
if self.europeanEndpoints[0] == ']' or
otherSet.europeanEndpoints[0] == ']':
endpointsAddIntervals = ']'
else:
endpointsAddIntervals = '['
if self.maxPoint == '+inf' or otherSet.maxPoint == '+inf' :
maxAddIntervals = '+inf'
endpointsAddIntervals += '['
else:
maxAddIntervals = self.maxPoint + otherSet.maxPoint
if self.europeanEndpoints[1] == '[' or
otherSet.europeanEndpoints[1] == '[':
endpointsAddIntervals += '['
else:
endpointsAddIntervals += ']'
return Interval(minAddIntervals, maxAddIntervals,
endPointsToUser(endpointsAddIntervals, self.notation), self.notation)
else:
disjointUnion = otherSet.simplify()
listAdditionOneByOne = []
for i in range(len(disjointUnion.listIntervals)):
listAdditionOneByOne.append(self +
disjointUnion.listIntervals[i])
return UnionIntervals(listAdditionOneByOne).simplify()
def __contains__(self, x):
if self.isEmpty:
return False
if x == self.minPoint:
return self.europeanEndpoints[0] =='['
if x == self.maxPoint:
return self.europeanEndpoints[1] ==']'
if str(self.minPoint) == '-inf':
return x < self.maxPoint
elif str(self.maxPoint) == 'inf':
return x > self.minPoint
else:
return self.minPoint < x < self.maxPoint
class UnionIntervals():
def __init__(self, listIntervals):
if listIntervals == []:
self.listIntervals = [Interval(0, 0, '')]
else:
self.listIntervals = listIntervals
self.shortListIntervals = None
# The first notation will be used for the simplified union.
self.notation = self.listIntervals[0].notation
# Thanks to Nicolas we explain me this trick.
@property
def isEmpty(self):
if self.shortListIntervals == None:
self.simplify()
return (len(self.shortListIntervals) == 1) and
(str(self.shortListIntervals[0])=='Empty Set')
def __str__(self):
if len(self.listIntervals)==1:
return str(self.listIntervals[0])
t = str(self.listIntervals[0])
for i in range(1, len(self.listIntervals)):
t += ' u ' + str(self.listIntervals[i])
return t
def __add__(self, otherSet):
# We reimplement the use of or.
if isinstance(otherSet, Interval):
return otherSet + self
else:
if self.shortListIntervals==None:
listCurrentSet= self.simplify().listIntervals
else:
listCurrentSet= self.shortListIntervals
listOtherSet = otherSet.simplify().listIntervals
listAdditionOneByOne = []
for i in range(len(listCurrentSet)):
for j in range(len(listOtherSet)):
listAdditionOneByOne.append(listCurrentSet[i] +
listOtherSet[j])
return UnionIntervals(listAdditionOneByOne).simplify()
def __mul__(self, realNumber):
""" Union*k ok mais pas k*Union : il faudrait réimplémenter les
multiplications des réels,...
"""
# We reimplement the use of or.
listProductOneByOne = []
for i in range(len(self.listIntervals)):
listProductOneByOne.append(self.listIntervals[i] * realNumber)
return UnionIntervals(listProductOneByOne).simplify()
def __or__(self, otherSet):
# We reimplement the use of +.
if self.isEmpty :
return otherSet
if isinstance(otherSet, Interval):
newUnion = UnionIntervals(self.listIntervals + [otherSet])
else:
newUnion = UnionIntervals(self.listIntervals +
otherSet.listIntervals)
return newUnion.simplify()
def __unionOfTwo(self, interval_1, interval_2):
"""
intervalle ranbgés
"""
if not (interval_1 & interval_2).isEmpty :
minPoint = min(interval_1.minPoint, interval_2.minPoint)
maxPoint = max(interval_1.maxPoint, interval_2.maxPoint)
if minPoint == interval_1.minPoint:
if minPoint == interval_2.minPoint:
if interval_1.europeanEndpoints[0]==']' and
interval_2.europeanEndpoints[0]==']':
europeanEndpoints = ']'
else:
europeanEndpoints = '['
else:
europeanEndpoints = interval_1.europeanEndpoints[0]
else:
europeanEndpoints = interval_2.europeanEndpoints[0]
if maxPoint == interval_1.maxPoint:
if maxPoint == interval_2.maxPoint:
if interval_1.europeanEndpoints[1]=='[' and
interval_2.europeanEndpoints[1]=='[':
europeanEndpoints += '['
else:
europeanEndpoints += ']'
else:
europeanEndpoints += interval_1.europeanEndpoints[1]
else:
europeanEndpoints += interval_2.europeanEndpoints[1]
return Interval(minPoint, maxPoint,
endPointsToUser(europeanEndpoints, self.notation), self.notation)
if interval_1.maxPoint == interval_2.minPoint and
(interval_1.europeanEndpoints[1]==']' or
interval_2.europeanEndpoints[0]=='['):
return Interval(interval_1.minPoint, interval_2.maxPoint,
endPointsToUser(interval_1.europeanEndpoints[0] +
interval_2.europeanEndpoints[1], self.notation), self.notation)
return None
def simplify(self):
if self.shortListIntervals != None :
return self.shortListIntervals
# We only keep non-empty intervals.
self.shortListIntervals = []
for i in range(len(self.listIntervals)):
if self.listIntervals[i].isEmpty == False:
self.shortListIntervals.append(self.listIntervals[i])
if self.shortListIntervals == []:
return UnionIntervals([Interval()])
if len(self.shortListIntervals) == 1:
return UnionIntervals(self.shortListIntervals)
# We start by sorting the intervals regarding to their minPoint value.
self.shortListIntervals.sort(key=lambda x: x.minPoint)
# We can start the simplification.
i = 0
while (i < len(self.shortListIntervals)-1):
newUnion = self.__unionOfTwo(self.shortListIntervals[i],
self.shortListIntervals[i+1])
if newUnion==None:
i+=1
else:
self.shortListIntervals.pop(i)
self.shortListIntervals[i] = newUnion
return UnionIntervals(self.shortListIntervals)
class IntersectionIntervals():
def __init__(self, listIntervals):
if listIntervals == []:
self.listIntervals = [Interval(0, 0, '')]
else:
self.listIntervals = listIntervals
self.finalIntersection = None
# The first notation will be used for the simplified union.
self.notation = self.listIntervals[0].notation
def __str__(self):
if len(self.listIntervals)==1:
return str(self.listIntervals[0])
t = str(self.listIntervals[0])
for i in range(1, len(self.listIntervals)):
t += ' n ' + str(self.listIntervals[i])
return t
def simplify(self):
if self.finalIntersection!=None:
return self.finalIntersection
if len(self.listIntervals) == 1:
self.finalIntersection = self.listIntervals[0]
return self.finalIntersection
self.finalIntersection = self.listIntervals[0]
for i in range(1, len(self.listIntervals)):
if self.finalIntersection.isEmpty:
break
self.finalIntersection = self.finalIntersection &
self.listIntervals[i]
return self.finalIntersection
class MixingIntervals():
"""
"""
def __init__(self, strIntervalsMixed, notation = 'am'):
self.strIntervalsMixed = strIntervalsMixed
self.notation = notation
self.minimalUnion = None
def __str__(self):
return self.strIntervalsMixed
def simplify(self):
"""
(-5;3) n ([-4;3] u (-2;7]) n ([-3;13] u {24})
"""
if self.minimalUnion != None:
return self.minimalUnion
piecesOfUnions = self.strIntervalsMixed.split('u')
listIntervalsUnion = []
for i in range(len(piecesOfUnions)):
# print
# print 'piecesOfIntersections'
piecesOfIntersections = piecesOfUnions[i].split('n')
listIntervalsIntersection = []
for j in range(len(piecesOfIntersections)):
oneInterval = piecesOfIntersections[j].strip()
endpoints = oneInterval[0] + oneInterval[-1]
if endpoints=='{}':
endpoints='[]'
minMax = [oneInterval[1:-1], oneInterval[1:-1]]
else:
minMax = oneInterval[1:-1].split(';')
# print 'Interval(minMax[0], minMax[1], endpoints,
self.notation)'
# print Interval(minMax[0], minMax[1], endpoints,
self.notation)
listIntervalsIntersection.append(Interval(int(minMax[0]),
int(minMax[1]), endpoints, self.notation))
# print
'IntersectionIntervals(listIntervalsIntersection).simplify()'
# print
IntersectionIntervals(listIntervalsIntersection).simplify()
listIntervalsUnion.append(IntersectionIntervals(listIntervalsIntersection).simplify())
# print 'listIntervalsUnion'
for i in range(len(listIntervalsUnion)):
print(listIntervalsUnion[i])
return UnionIntervals(listIntervalsUnion).simplify()
# Some special intervals.
empty = Interval()
R = Interval('-inf','+inf','()')
Rpos = Interval('0','+inf','[)')
RposStrict = Interval('0','+inf','()')
Rneg = Interval('-inf','0','(]')
RnegStrict = Interval('-inf','0','()')
Rstar = RnegStrict or RposStrict
==== My code - END ====
2011/3/18 SherjilOzair <[email protected]>
> The Set class of sympy is not complete.
> I plan to add a full FiniteSet class functionality which will inherit
> the Set class, we can also have an InfiniteSet abstract class later
> which Interval and Union can inherit.
>
> A FiniteSet would behave something like this,
>
> a=Set([1,2,3,4,5])
> b=Set([4,5,6,7])
> c=a+b // or c=a.union(b)
> print c
> [1,2,3,4,5,6]
>
> and similar behavior for intersection, complement, contains
> functions.
> Feel free to suggest me more features.
>
> With a good polys class, we can also add conversion from set-builder
> notation to list notation.
>
> I ask more experienced developers to tell me if there is any design
> flaw in this.
> I need the go-ahead to start coding this class.
>
> Thanks,
> Sherjil
>
> --
> You received this message because you are subscribed to the Google Groups
> "sympy" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
> [email protected].
> For more options, visit this group at
> http://groups.google.com/group/sympy?hl=en.
>
>
--
You received this message because you are subscribed to the Google Groups
"sympy" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/sympy?hl=en.