""" Defines a class that represents a partition of a list of integers:author: Michel Bierlaire:date: Thu Oct 26 17:30:36 2023"""importloggingfromtypingimportIterator,SequenceSegment=set[int]logger=logging.getLogger(__name__)
[docs]classPartition:"""Class defining a partition of a set"""def__init__(self,segments:Sequence[Segment],full_set:Segment|None=None):self.segments=segmentsiffull_set:self.full_set=full_setelse:logger.warning('The full set of the partition has not been specified. It is defined ''by default as the union of the provided segment.')self.full_set=set().union(*self.segments)self.validate_segments()self.validate_partition()
[docs]defvalidate_segments(self)->None:"""Check the types"""forsegmentinself.segments:ifnotisinstance(segment,set):raiseValueError('Each segment must be of type "set".')ifnotsegment:raiseValueError('Partition contains empty segment')foriteminsegment:ifnotisinstance(item,int):raiseValueError('Each item in the segment must be an integer.')
[docs]defvalidate_partition(self)->None:"""Check that there is no intersection between segments"""fors1,segment1inenumerate(self.segments):fors2,segment2inenumerate(self.segments):ifs1!=s2:intersection=segment1.intersection(segment2)ifintersection:raiseValueError(f'Elements in two different segments: {intersection}.')# Check that the union of all segments is the given setunion_of_segments=set().union(*self.segments)ifunion_of_segments!=self.full_set:missing_elements=self.full_set-union_of_segmentsraiseValueError(f'The union of segments does not match the given set. 'f'Missing elements: {missing_elements}.')