def is_assignable_integer(argument): r'''Is true when `argument` is equivalent to an integer that can be written without recourse to ties. Otherwise false. .. container:: example >>> for n in range(0, 16 + 1): ... print('%s\t%s' % (n, abjad.mathtools.is_assignable_integer(n))) ... 0 False 1 True 2 True 3 True 4 True 5 False 6 True 7 True 8 True 9 False 10 False 11 False 12 True 13 False 14 True 15 True 16 True Returns true or false. ''' from abjad.tools import mathtools if isinstance(argument, int): if 0 < argument: if '01' not in mathtools.integer_to_binary_string(argument): return True return False
def inventory_aggregate_subsets(): '''Inventory aggregate subsets: :: >>> U_star = pitchtools.inventory_aggregate_subsets() >>> len(U_star) 4096 >>> for pcset in U_star[:20]: ... pcset PitchClassSet([]) PitchClassSet([0]) PitchClassSet([1]) PitchClassSet([0, 1]) PitchClassSet([2]) PitchClassSet([0, 2]) PitchClassSet([1, 2]) PitchClassSet([0, 1, 2]) PitchClassSet([3]) PitchClassSet([0, 3]) PitchClassSet([1, 3]) PitchClassSet([0, 1, 3]) PitchClassSet([2, 3]) PitchClassSet([0, 2, 3]) PitchClassSet([1, 2, 3]) PitchClassSet([0, 1, 2, 3]) PitchClassSet([4]) PitchClassSet([0, 4]) PitchClassSet([1, 4]) PitchClassSet([0, 1, 4]) There are 4096 subsets of the aggregate. This is ``U*`` in [Morris 1987]. Returns list of numbered pitch-class sets. ''' from abjad.tools import pitchtools def _helper(binary_string): result = zip(binary_string, range(len(binary_string))) result = [x[1] for x in result if x[0] == '1'] return result result = [] for x in range(4096): subset = ''.join( list(reversed(mathtools.integer_to_binary_string(x).zfill(12)))) subset = _helper(subset) subset = pitchtools.PitchClassSet( subset, item_class=pitchtools.NumberedPitchClass, ) result.append(subset) return result
def inventory_aggregate_subsets(): '''Inventory aggregate subsets: :: >>> U_star = pitchtools.inventory_aggregate_subsets() >>> len(U_star) 4096 >>> for pcset in U_star[:20]: ... pcset PitchClassSet([]) PitchClassSet([0]) PitchClassSet([1]) PitchClassSet([0, 1]) PitchClassSet([2]) PitchClassSet([0, 2]) PitchClassSet([1, 2]) PitchClassSet([0, 1, 2]) PitchClassSet([3]) PitchClassSet([0, 3]) PitchClassSet([1, 3]) PitchClassSet([0, 1, 3]) PitchClassSet([2, 3]) PitchClassSet([0, 2, 3]) PitchClassSet([1, 2, 3]) PitchClassSet([0, 1, 2, 3]) PitchClassSet([4]) PitchClassSet([0, 4]) PitchClassSet([1, 4]) PitchClassSet([0, 1, 4]) There are 4096 subsets of the aggregate. This is ``U*`` in [Morris 1987]. Returns list of numbered pitch-class sets. ''' from abjad.tools import pitchtools def _helper(binary_string): result = zip(binary_string, range(len(binary_string))) result = [x[1] for x in result if x[0] == '1'] return result result = [] for x in range(4096): subset = ''.join(list(reversed(mathtools.integer_to_binary_string(x).zfill(12)))) subset = _helper(subset) subset = pitchtools.PitchClassSet( subset, item_class=pitchtools.NumberedPitchClass, ) result.append(subset) return result
def test_mathtools_integer_to_binary_string_01(): r'''Returns base-2 representation of integer n as string. ''' assert mathtools.integer_to_binary_string(1) == '1' assert mathtools.integer_to_binary_string(2) == '10' assert mathtools.integer_to_binary_string(3) == '11' assert mathtools.integer_to_binary_string(4) == '100' assert mathtools.integer_to_binary_string(5) == '101' assert mathtools.integer_to_binary_string(6) == '110' assert mathtools.integer_to_binary_string(7) == '111' assert mathtools.integer_to_binary_string(8) == '1000'
def yield_all_compositions_of_integer(n): r'''Yields all compositions of positive integer `n` in descending lex order: :: >>> for integer_composition in mathtools.yield_all_compositions_of_integer(5): ... integer_composition ... (5,) (4, 1) (3, 2) (3, 1, 1) (2, 3) (2, 2, 1) (2, 1, 2) (2, 1, 1, 1) (1, 4) (1, 3, 1) (1, 2, 2) (1, 2, 1, 1) (1, 1, 3) (1, 1, 2, 1) (1, 1, 1, 2) (1, 1, 1, 1, 1) Integer compositions are ordered integer partitions. Returns generator of positive integer tuples of length at least ``1``. ''' from abjad.tools import mathtools # Finds small values of n easily. # Takes ca. 4 seconds for n = 17. compositions = [] x = 0 string_length = n while x < 2**(n - 1): binary_string = mathtools.integer_to_binary_string(x) binary_string = binary_string.zfill(string_length) l = [int(c) for c in list(binary_string)] partition = [] g = itertools.groupby(l, lambda x: x) for value, group in g: partition.append(list(group)) sublengths = [len(part) for part in partition] composition = tuple(sublengths) compositions.append(composition) x += 1 for composition in reversed(sorted(compositions)): yield composition
def yield_all_compositions_of_integer(n): r'''Yields all compositions of positive integer `n` in descending lex order: :: >>> for integer_composition in mathtools.yield_all_compositions_of_integer(5): ... integer_composition ... (5,) (4, 1) (3, 2) (3, 1, 1) (2, 3) (2, 2, 1) (2, 1, 2) (2, 1, 1, 1) (1, 4) (1, 3, 1) (1, 2, 2) (1, 2, 1, 1) (1, 1, 3) (1, 1, 2, 1) (1, 1, 1, 2) (1, 1, 1, 1, 1) Integer compositions are ordered integer partitions. Returns generator of positive integer tuples of length at least ``1``. ''' from abjad.tools import mathtools # Finds small values of n easily. # Takes ca. 4 seconds for n = 17. compositions = [] x = 0 string_length = n while x < 2 ** (n - 1): binary_string = mathtools.integer_to_binary_string(x) binary_string = binary_string.zfill(string_length) l = [int(c) for c in list(binary_string)] partition = [] g = itertools.groupby(l, lambda x: x) for value, group in g: partition.append(list(group)) sublengths = [len(part) for part in partition] composition = tuple(sublengths) compositions.append(composition) x += 1 for composition in reversed(sorted(compositions)): yield composition
def yield_all_compositions_of_integer(n): r'''Yields all compositions of positive integer `n`. .. container:: example >>> for tuple_ in abjad.mathtools.yield_all_compositions_of_integer(5): ... tuple_ ... (5,) (4, 1) (3, 2) (3, 1, 1) (2, 3) (2, 2, 1) (2, 1, 2) (2, 1, 1, 1) (1, 4) (1, 3, 1) (1, 2, 2) (1, 2, 1, 1) (1, 1, 3) (1, 1, 2, 1) (1, 1, 1, 2) (1, 1, 1, 1, 1) Lists parts in descending lex order. Parts sum to `n`. Finds small values of `n` easily. Takes around 4 seconds for `n` equal to 17. Returns integer tuple generator. ''' from abjad.tools import mathtools compositions = [] integer = 0 string_length = n while integer < 2**(n - 1): binary_string = mathtools.integer_to_binary_string(integer) binary_string = binary_string.zfill(string_length) digits = [int(_) for _ in list(binary_string)] partition = [] generator = itertools.groupby(digits, lambda _: _) for value, group in generator: partition.append(list(group)) sublengths = [len(part) for part in partition] composition = tuple(sublengths) compositions.append(composition) integer += 1 for composition in reversed(sorted(compositions)): yield composition
def dot_count(self): r'''Gets dot count. .. container:: example **Example.** Gets dot count: :: >>> for n in range(1, 16 + 1): ... try: ... duration = Duration(n, 16) ... sixteenths = duration.with_denominator(16) ... dot_count = duration.dot_count ... string = '{!s}\t{}' ... string = string.format(sixteenths, dot_count) ... print(string) ... except AssignabilityError: ... sixteenths = duration.with_denominator(16) ... string = '{!s}\t{}' ... string = string.format(sixteenths, '--') ... print(string) ... 1/16 0 2/16 0 3/16 1 4/16 0 5/16 -- 6/16 1 7/16 2 8/16 0 9/16 -- 10/16 -- 11/16 -- 12/16 1 13/16 -- 14/16 2 15/16 3 16/16 0 Dot count defined equal to number of dots required to notate duration. Raises assignability error when duration is not assignable. Returns positive integer. ''' if not self.is_assignable: raise AssignabilityError binary_string = mathtools.integer_to_binary_string(self.numerator) digit_sum = sum([int(x) for x in list(binary_string)]) dot_count = digit_sum - 1 return dot_count
def yield_all_partitions_of_sequence(sequence): '''Yields all partitions of `sequence`. :: >>> sequence = [0, 1, 2, 3] >>> result = sequencetools.yield_all_partitions_of_sequence(sequence) >>> for partition in result: ... partition ... [[0, 1, 2, 3]] [[0, 1, 2], [3]] [[0, 1], [2, 3]] [[0, 1], [2], [3]] [[0], [1, 2, 3]] [[0], [1, 2], [3]] [[0], [1], [2, 3]] [[0], [1], [2], [3]] Returns new object of `sequence` type. ''' if not isinstance(sequence, collections.Sequence): message = 'must by sequence {!r}.' message = message.format(sequence) raise Exception(message) sequence_type = type(sequence) result = [] len_l_minus_1 = len(sequence) - 1 for i in range(2 ** len_l_minus_1): binary_string = mathtools.integer_to_binary_string(i) binary_string = binary_string.zfill(len_l_minus_1) part = sequence[0:1] partition = [part] for n, token in zip(sequence[1:], binary_string): if int(token) == 0: part.append(n) else: part = [n] partition.append(part) result.append(partition) result = sequence_type(result) return result
def yield_all_partitions_of_sequence(sequence): '''Yields all partitions of `sequence`. :: >>> sequence = [0, 1, 2, 3] >>> result = sequencetools.yield_all_partitions_of_sequence(sequence) >>> for partition in result: ... partition ... [[0, 1, 2, 3]] [[0, 1, 2], [3]] [[0, 1], [2, 3]] [[0, 1], [2], [3]] [[0], [1, 2, 3]] [[0], [1, 2], [3]] [[0], [1], [2, 3]] [[0], [1], [2], [3]] Returns new object of `sequence` type. ''' if not isinstance(sequence, collections.Sequence): message = 'must by sequence {!r}.' message = message.format(sequence) raise Exception(message) sequence_type = type(sequence) result = [] len_l_minus_1 = len(sequence) - 1 for i in range(2**len_l_minus_1): binary_string = mathtools.integer_to_binary_string(i) binary_string = binary_string.zfill(len_l_minus_1) part = sequence[0:1] partition = [part] for n, token in zip(sequence[1:], binary_string): if int(token) == 0: part.append(n) else: part = [n] partition.append(part) result.append(partition) result = sequence_type(result) return result
def yield_all_partitions_of_sequence(sequence): '''Yields all partitions of `sequence`. :: >>> sequence = [0, 1, 2, 3] >>> result = sequencetools.yield_all_partitions_of_sequence(sequence) >>> for partition in result: ... partition ... [[0, 1, 2, 3]] [[0, 1, 2], [3]] [[0, 1], [2, 3]] [[0, 1], [2], [3]] [[0], [1, 2, 3]] [[0], [1, 2], [3]] [[0], [1], [2, 3]] [[0], [1], [2], [3]] Returns generator of newly created lists. ''' # TODO: remove type restriction if not isinstance(sequence, list): message = '{!r} must be list.' message = message.format(sequence) raise TypeError(message) partitions = [] len_l_minus_1 = len(sequence) - 1 for i in range(2 ** len_l_minus_1): binary_string = mathtools.integer_to_binary_string(i) binary_string = binary_string.zfill(len_l_minus_1) part = sequence[0:1] partition = [part] for n, token in zip(sequence[1:], binary_string): if int(token) == 0: part.append(n) else: part = [n] partition.append(part) partitions.append(partition) return partitions
def yield_all_partitions_of_sequence(sequence): '''Yields all partitions of `sequence`. :: >>> sequence = [0, 1, 2, 3] >>> result = sequencetools.yield_all_partitions_of_sequence(sequence) >>> for partition in result: ... partition ... [[0, 1, 2, 3]] [[0, 1, 2], [3]] [[0, 1], [2, 3]] [[0, 1], [2], [3]] [[0], [1, 2, 3]] [[0], [1, 2], [3]] [[0], [1], [2, 3]] [[0], [1], [2], [3]] Returns generator of newly created lists. ''' # TODO: remove type restriction if not isinstance(sequence, list): message = '{!r} must be list.' message = message.format(sequence) raise TypeError(message) partitions = [] len_l_minus_1 = len(sequence) - 1 for i in range(2**len_l_minus_1): binary_string = mathtools.integer_to_binary_string(i) binary_string = binary_string.zfill(len_l_minus_1) part = sequence[0:1] partition = [part] for n, token in zip(sequence[1:], binary_string): if int(token) == 0: part.append(n) else: part = [n] partition.append(part) partitions.append(partition) return partitions
def yield_all_partitions_of_sequence(sequence): '''Yield all partitions of `sequence`: :: >>> for partition in sequencetools.yield_all_partitions_of_sequence([0, 1, 2, 3]): ... partition ... [[0, 1, 2, 3]] [[0, 1, 2], [3]] [[0, 1], [2, 3]] [[0, 1], [2], [3]] [[0], [1, 2, 3]] [[0], [1, 2], [3]] [[0], [1], [2, 3]] [[0], [1], [2], [3]] Returns generator of newly created lists. ''' # TODO: remove type restriction # if not isinstance(sequence, list): raise TypeError('%s must be list.' % sequence) partitions = [] len_l_minus_1 = len(sequence) - 1 for i in range(2 ** len_l_minus_1): binary_string = mathtools.integer_to_binary_string(i) binary_string = binary_string.zfill(len_l_minus_1) part = sequence[0:1] partition = [part] for n, indicator in zip(sequence[1:], binary_string): if int(indicator) == 0: part.append(n) else: part = [n] partition.append(part) partitions.append(partition) return partitions
def dot_count(self): r'''Positive integer number of dots required to notate duration: :: >>> for n in range(1, 16 + 1): ... try: ... duration = Duration(n, 16) ... print '{}\t{}'.format( ... duration.with_denominator(16), duration.dot_count) ... except AssignabilityError: ... print '{}\t{}'.format( ... duration.with_denominator(16), '--') ... 1/16 0 2/16 0 3/16 1 4/16 0 5/16 -- 6/16 1 7/16 2 8/16 0 9/16 -- 10/16 -- 11/16 -- 12/16 1 13/16 -- 14/16 2 15/16 3 16/16 0 Returns positive integer. Raise assignability error when duration is not assignable. ''' if not self.is_assignable: raise AssignabilityError binary_string = mathtools.integer_to_binary_string(self.numerator) digit_sum = sum([int(x) for x in list(binary_string)]) dot_count = digit_sum - 1 return dot_count
def is_assignable_integer(expr): r'''Is true when `expr` is equivalent to an integer and can be written without recourse to ties. :: >>> for n in range(0, 16 + 1): ... print('%s\t%s' % (n, mathtools.is_assignable_integer(n))) ... 0 False 1 True 2 True 3 True 4 True 5 False 6 True 7 True 8 True 9 False 10 False 11 False 12 True 13 False 14 True 15 True 16 True Otherwise false. Returns true or false. ''' from abjad.tools import mathtools if isinstance(expr, int): if 0 < expr: if not '01' in mathtools.integer_to_binary_string(expr): return True return False
def is_assignable_integer(expr): r'''Is true when `expr` is equivalent to an integer and can be written without recourse to ties. :: >>> for n in range(0, 16 + 1): ... print '%s\t%s' % (n, mathtools.is_assignable_integer(n)) ... 0 False 1 True 2 True 3 True 4 True 5 False 6 True 7 True 8 True 9 False 10 False 11 False 12 True 13 False 14 True 15 True 16 True Otherwise false. Returns boolean. ''' from abjad.tools import mathtools if isinstance(expr, int): if 0 < expr: if not '01' in mathtools.integer_to_binary_string(expr): return True return False
def yield_all_pitch_class_sets(): '''Yields all pitch-class sets. .. container:: example :: >>> all_pitch_class_sets = pitchtools.yield_all_pitch_class_sets() >>> len(all_pitch_class_sets) 4096 :: >>> for pitch_class_set in all_pitch_class_sets[:20]: ... pitch_class_set PitchClassSet([]) PitchClassSet([0]) PitchClassSet([1]) PitchClassSet([0, 1]) PitchClassSet([2]) PitchClassSet([0, 2]) PitchClassSet([1, 2]) PitchClassSet([0, 1, 2]) PitchClassSet([3]) PitchClassSet([0, 3]) PitchClassSet([1, 3]) PitchClassSet([0, 1, 3]) PitchClassSet([2, 3]) PitchClassSet([0, 2, 3]) PitchClassSet([1, 2, 3]) PitchClassSet([0, 1, 2, 3]) PitchClassSet([4]) PitchClassSet([0, 4]) PitchClassSet([1, 4]) PitchClassSet([0, 1, 4]) There are 4096 pitch-class sets. This is ``U*`` in [Morris 1987]. Returns list of numbered pitch-class sets. ''' from abjad.tools import pitchtools def _helper(binary_string): result = zip(binary_string, range(len(binary_string))) result = [x[1] for x in result if x[0] == '1'] return result result = [] for x in range(4096): string = mathtools.integer_to_binary_string(x).zfill(12) subset = ''.join(list(reversed(string))) subset = _helper(subset) subset = pitchtools.PitchClassSet( subset, item_class=pitchtools.NumberedPitchClass, ) result.append(subset) return result
def partition_integer_into_canonic_parts(n, decrease_parts_monotonically=True): r'''Partitions integer `n` into canonic parts. Returns all parts positive on positive `n`: :: >>> for n in range(1, 11): ... print(n, mathtools.partition_integer_into_canonic_parts(n)) ... 1 (1,) 2 (2,) 3 (3,) 4 (4,) 5 (4, 1) 6 (6,) 7 (7,) 8 (8,) 9 (8, 1) 10 (8, 2) Returns all parts negative on negative `n`: :: >>> for n in reversed(range(-20, -10)): ... print(n, mathtools.partition_integer_into_canonic_parts(n)) ... -11 (-8, -3) -12 (-12,) -13 (-12, -1) -14 (-14,) -15 (-15,) -16 (-16,) -17 (-16, -1) -18 (-16, -2) -19 (-16, -3) -20 (-16, -4) Returns parts that increase monotonically: :: >>> for n in range(11, 21): ... print(n, mathtools.partition_integer_into_canonic_parts(n, ... decrease_parts_monotonically=False)) ... 11 (3, 8) 12 (12,) 13 (1, 12) 14 (14,) 15 (15,) 16 (16,) 17 (1, 16) 18 (2, 16) 19 (3, 16) 20 (4, 16) Returns tuple with parts that decrease monotonically. Raises type error on noninteger `n`. Returns tuple of one or more integers. ''' from abjad.tools import mathtools if not isinstance(n, int): raise TypeError if not isinstance(decrease_parts_monotonically, bool): raise ValueError if n == 0: return (0, ) result = [] previous_empty = True binary_n = mathtools.integer_to_binary_string(abs(n)) binary_length = len(binary_n) for i, x in enumerate(binary_n): if x == '1': place_value = 2 ** (binary_length - i - 1) if previous_empty: result.append(place_value) else: result[-1] += place_value previous_empty = False else: previous_empty = True sign_n = mathtools.sign(n) if mathtools.sign(n) == -1: result = [sign_n * x for x in result] if decrease_parts_monotonically: return tuple(result) else: return tuple(reversed(result))
def yield_all_pitch_class_sets(): '''Yields all pitch-class sets: .. container:: example :: >>> all_pitch_class_sets = pitchtools.yield_all_pitch_class_sets() >>> len(all_pitch_class_sets) 4096 :: >>> for pitch_class_set in all_pitch_class_sets[:20]: ... pitch_class_set PitchClassSet([]) PitchClassSet([0]) PitchClassSet([1]) PitchClassSet([0, 1]) PitchClassSet([2]) PitchClassSet([0, 2]) PitchClassSet([1, 2]) PitchClassSet([0, 1, 2]) PitchClassSet([3]) PitchClassSet([0, 3]) PitchClassSet([1, 3]) PitchClassSet([0, 1, 3]) PitchClassSet([2, 3]) PitchClassSet([0, 2, 3]) PitchClassSet([1, 2, 3]) PitchClassSet([0, 1, 2, 3]) PitchClassSet([4]) PitchClassSet([0, 4]) PitchClassSet([1, 4]) PitchClassSet([0, 1, 4]) There are 4096 pitch-class sets. This is ``U*`` in [Morris 1987]. Returns list of numbered pitch-class sets. ''' from abjad.tools import pitchtools def _helper(binary_string): result = zip(binary_string, range(len(binary_string))) result = [x[1] for x in result if x[0] == '1'] return result result = [] for x in range(4096): string = mathtools.integer_to_binary_string(x).zfill(12) subset = ''.join(list(reversed(string))) subset = _helper(subset) subset = pitchtools.PitchClassSet( subset, item_class=pitchtools.NumberedPitchClass, ) result.append(subset) return result
def yield_all_combinations_of_elements( sequence, min_length=None, max_length=None, ): '''Yields all combinations of `sequence` in binary string order. :: >>> list(sequencetools.yield_all_combinations_of_elements( ... [1, 2, 3, 4])) [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3], [4], [1, 4], [2, 4], [1, 2, 4], [3, 4], [1, 3, 4], [2, 3, 4], [1, 2, 3, 4]] Yields all combinations of `sequence` greater than or equal to `min_length` in binary string order: :: >>> list(sequencetools.yield_all_combinations_of_elements( ... [1, 2, 3, 4], min_length=3)) [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4], [1, 2, 3, 4]] Yields all combinations of `sequence` less than or equal to `max_length` in binary string order: :: >>> list(sequencetools.yield_all_combinations_of_elements( ... [1, 2, 3, 4], max_length=2)) [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [4], [1, 4], [2, 4], [3, 4]] Yields all combiantions of `sequence` greater than or equal to `min_length` and less than or equal to `max_length` in lex order: :: >>> list(sequencetools.yield_all_combinations_of_elements( ... [1, 2, 3, 4], min_length=2, max_length=2)) [[1, 2], [1, 3], [2, 3], [1, 4], [2, 4], [3, 4]] Yields references to `sequence` elements; does not copy `sequence` elements. Returns generator. ''' if not isinstance(sequence, collections.Sequence): message = 'must by sequence {!r}.' message = message.format(sequence) raise Exception(message) sequence_type = type(sequence) len_l = len(sequence) for i in range(2 ** len_l): binary_string = mathtools.integer_to_binary_string(i) binary_string = binary_string.zfill(len_l) sublist = [] for j, digit in enumerate(reversed(binary_string)): if digit == '1': sublist.append(sequence[j]) yield_sublist = True if min_length is not None: if len(sublist) < min_length: yield_sublist = False if max_length is not None: if max_length < len(sublist): yield_sublist = False if yield_sublist: # type-checking hack ... but is there a better way? if isinstance(sequence, str): yield ''.join(sublist) else: yield type(sequence)(sublist)
def yield_all_combinations_of_elements( sequence, min_length=None, max_length=None, ): '''Yields all combinations of `sequence` in binary string order. :: >>> list(sequencetools.yield_all_combinations_of_elements( ... [1, 2, 3, 4])) [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3], [4], [1, 4], [2, 4], [1, 2, 4], [3, 4], [1, 3, 4], [2, 3, 4], [1, 2, 3, 4]] Yields all combinations of `sequence` greater than or equal to `min_length` in binary string order: :: >>> list(sequencetools.yield_all_combinations_of_elements( ... [1, 2, 3, 4], min_length=3)) [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4], [1, 2, 3, 4]] Yields all combinations of `sequence` less than or equal to `max_length` in binary string order: :: >>> list(sequencetools.yield_all_combinations_of_elements( ... [1, 2, 3, 4], max_length=2)) [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [4], [1, 4], [2, 4], [3, 4]] Yields all combiantions of `sequence` greater than or equal to `min_length` and less than or equal to `max_length` in lex order: :: >>> list(sequencetools.yield_all_combinations_of_elements( ... [1, 2, 3, 4], min_length=2, max_length=2)) [[1, 2], [1, 3], [2, 3], [1, 4], [2, 4], [3, 4]] Returns generator of newly created `sequence` objects. ''' len_l = len(sequence) for i in range(2**len_l): binary_string = mathtools.integer_to_binary_string(i) binary_string = binary_string.zfill(len_l) sublist = [] for j, digit in enumerate(reversed(binary_string)): if digit == '1': # copy makes the function work with score components # copy also makes twice as slow on lists of built-ins #sublist.append(sequence[j]) sublist.append(copy.copy(sequence[j])) yield_sublist = True if min_length is not None: if len(sublist) < min_length: yield_sublist = False if max_length is not None: if max_length < len(sublist): yield_sublist = False if yield_sublist: # type-checking hack ... but is there a better way? if isinstance(sequence, str): yield ''.join(sublist) else: yield type(sequence)(sublist)
def yield_all_combinations_of_elements( sequence, min_length=None, max_length=None, ): '''Yields all combinations of `sequence` in binary string order. :: >>> list(sequencetools.yield_all_combinations_of_elements( ... [1, 2, 3, 4])) [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3], [4], [1, 4], [2, 4], [1, 2, 4], [3, 4], [1, 3, 4], [2, 3, 4], [1, 2, 3, 4]] Yields all combinations of `sequence` greater than or equal to `min_length` in binary string order: :: >>> list(sequencetools.yield_all_combinations_of_elements( ... [1, 2, 3, 4], min_length=3)) [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4], [1, 2, 3, 4]] Yields all combinations of `sequence` less than or equal to `max_length` in binary string order: :: >>> list(sequencetools.yield_all_combinations_of_elements( ... [1, 2, 3, 4], max_length=2)) [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [4], [1, 4], [2, 4], [3, 4]] Yields all combiantions of `sequence` greater than or equal to `min_length` and less than or equal to `max_length` in lex order: :: >>> list(sequencetools.yield_all_combinations_of_elements( ... [1, 2, 3, 4], min_length=2, max_length=2)) [[1, 2], [1, 3], [2, 3], [1, 4], [2, 4], [3, 4]] Yields references to `sequence` elements; does not copy `sequence` elements. Returns generator. ''' if not isinstance(sequence, collections.Sequence): message = 'must by sequence {!r}.' message = message.format(sequence) raise Exception(message) sequence_type = type(sequence) len_l = len(sequence) for i in range(2**len_l): binary_string = mathtools.integer_to_binary_string(i) binary_string = binary_string.zfill(len_l) sublist = [] for j, digit in enumerate(reversed(binary_string)): if digit == '1': sublist.append(sequence[j]) yield_sublist = True if min_length is not None: if len(sublist) < min_length: yield_sublist = False if max_length is not None: if max_length < len(sublist): yield_sublist = False if yield_sublist: # type-checking hack ... but is there a better way? if isinstance(sequence, str): yield ''.join(sublist) else: yield type(sequence)(sublist)
def test_mathtools_integer_to_binary_string_02(): assert mathtools.integer_to_binary_string(0) == '0' assert mathtools.integer_to_binary_string(-1) == '-1' assert mathtools.integer_to_binary_string(-2) == '-10' assert mathtools.integer_to_binary_string(-3) == '-11'
def yield_all_combinations_of_elements( sequence, min_length=None, max_length=None, ): '''Yields all combinations of `sequence` in binary string order. :: >>> list(sequencetools.yield_all_combinations_of_elements( ... [1, 2, 3, 4])) [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3], [4], [1, 4], [2, 4], [1, 2, 4], [3, 4], [1, 3, 4], [2, 3, 4], [1, 2, 3, 4]] Yields all combinations of `sequence` greater than or equal to `min_length` in binary string order: :: >>> list(sequencetools.yield_all_combinations_of_elements( ... [1, 2, 3, 4], min_length=3)) [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4], [1, 2, 3, 4]] Yields all combinations of `sequence` less than or equal to `max_length` in binary string order: :: >>> list(sequencetools.yield_all_combinations_of_elements( ... [1, 2, 3, 4], max_length=2)) [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [4], [1, 4], [2, 4], [3, 4]] Yields all combiantions of `sequence` greater than or equal to `min_length` and less than or equal to `max_length` in lex order: :: >>> list(sequencetools.yield_all_combinations_of_elements( ... [1, 2, 3, 4], min_length=2, max_length=2)) [[1, 2], [1, 3], [2, 3], [1, 4], [2, 4], [3, 4]] Returns generator of newly created `sequence` objects. ''' len_l = len(sequence) for i in range(2 ** len_l): binary_string = mathtools.integer_to_binary_string(i) binary_string = binary_string.zfill(len_l) sublist = [] for j, digit in enumerate(reversed(binary_string)): if digit == '1': # copy makes the function work with score components # copy also makes twice as slow on lists of built-ins #sublist.append(sequence[j]) sublist.append(copy.copy(sequence[j])) yield_sublist = True if min_length is not None: if len(sublist) < min_length: yield_sublist = False if max_length is not None: if max_length < len(sublist): yield_sublist = False if yield_sublist: # type-checking hack ... but is there a better way? if isinstance(sequence, str): yield ''.join(sublist) else: yield type(sequence)(sublist)
def _make_gridded_test_rhythm(grid_length, rhythm_number, denominator=16): r'''Make test rhythm number `rhythm_number` that fits `grid_length`. Returns selection of one or more possibly tied notes. .. container:: example **Example 1.** The eight test rhythms that fit a length-``4`` grid: :: >>> from abjad.tools.metertools import Meter >>> for rhythm_number in range(8): ... notes = Meter._make_gridded_test_rhythm( ... 4, rhythm_number, denominator=4) ... measure = Measure((4, 4), notes) ... print '{}\t{}'.format(rhythm_number, str(measure)) ... 0 |4/4 c'1| 1 |4/4 c'2. c'4| 2 |4/4 c'2 c'4 c'4| 3 |4/4 c'2 c'2| 4 |4/4 c'4 c'4 c'2| 5 |4/4 c'4 c'4 c'4 c'4| 6 |4/4 c'4 c'2 c'4| 7 |4/4 c'4 c'2.| .. container:: example **Example 2.** The sixteenth test rhythms for that a length-``5`` grid: :: >>> for rhythm_number in range(16): ... notes = Meter._make_gridded_test_rhythm( ... 5, rhythm_number, denominator=4) ... measure = Measure((5, 4), notes) ... print '{}\t{}'.format(rhythm_number, str(measure)) ... 0 |5/4 c'1 ~ c'4| 1 |5/4 c'1 c'4| 2 |5/4 c'2. c'4 c'4| 3 |5/4 c'2. c'2| 4 |5/4 c'2 c'4 c'2| 5 |5/4 c'2 c'4 c'4 c'4| 6 |5/4 c'2 c'2 c'4| 7 |5/4 c'2 c'2.| 8 |5/4 c'4 c'4 c'2.| 9 |5/4 c'4 c'4 c'2 c'4| 10 |5/4 c'4 c'4 c'4 c'4 c'4| 11 |5/4 c'4 c'4 c'4 c'2| 12 |5/4 c'4 c'2 c'2| 13 |5/4 c'4 c'2 c'4 c'4| 14 |5/4 c'4 c'2. c'4| 15 |5/4 c'4 c'1| Use for testing meter establishment. ''' from abjad.tools import scoretools # check input assert mathtools.is_positive_integer(grid_length) assert isinstance(rhythm_number, int) assert mathtools.is_positive_integer_power_of_two(denominator) # find count of all rhythms that fit grid length rhythm_count = 2 ** (grid_length - 1) # read rhythm number cyclically to allow large and # negative rhythm numbers rhythm_number = rhythm_number % rhythm_count # find binary representation of rhythm binary_representation = \ mathtools.integer_to_binary_string(rhythm_number) binary_representation = binary_representation.zfill(grid_length) # partition binary representation of rhythm parts = sequencetools.partition_sequence_by_value_of_elements( binary_representation) # find durations durations = [ durationtools.Duration(len(part), denominator) for part in parts ] # make notes notes = scoretools.make_notes([0], durations) # return notes return notes
def _make_gridded_test_rhythm(grid_length, rhythm_number, denominator=16): r'''Make test rhythm number `rhythm_number` that fits `grid_length`. Returns selection of one or more possibly tied notes. .. container:: example **Example 1.** The eight test rhythms that fit a length-``4`` grid: :: >>> from abjad.tools.metertools import Meter >>> for rhythm_number in range(8): ... notes = Meter._make_gridded_test_rhythm( ... 4, rhythm_number, denominator=4) ... measure = Measure((4, 4), notes) ... print('{}\t{}'.format(rhythm_number, str(measure))) ... 0 Measure((4, 4), "c'1") 1 Measure((4, 4), "c'2. c'4") 2 Measure((4, 4), "c'2 c'4 c'4") 3 Measure((4, 4), "c'2 c'2") 4 Measure((4, 4), "c'4 c'4 c'2") 5 Measure((4, 4), "c'4 c'4 c'4 c'4") 6 Measure((4, 4), "c'4 c'2 c'4") 7 Measure((4, 4), "c'4 c'2.") .. container:: example **Example 2.** The sixteenth test rhythms for that a length-``5`` grid: :: >>> for rhythm_number in range(16): ... notes = Meter._make_gridded_test_rhythm( ... 5, rhythm_number, denominator=4) ... measure = Measure((5, 4), notes) ... print('{}\t{}'.format(rhythm_number, str(measure))) ... 0 Measure((5, 4), "c'1 ~ c'4") 1 Measure((5, 4), "c'1 c'4") 2 Measure((5, 4), "c'2. c'4 c'4") 3 Measure((5, 4), "c'2. c'2") 4 Measure((5, 4), "c'2 c'4 c'2") 5 Measure((5, 4), "c'2 c'4 c'4 c'4") 6 Measure((5, 4), "c'2 c'2 c'4") 7 Measure((5, 4), "c'2 c'2.") 8 Measure((5, 4), "c'4 c'4 c'2.") 9 Measure((5, 4), "c'4 c'4 c'2 c'4") 10 Measure((5, 4), "c'4 c'4 c'4 c'4 c'4") 11 Measure((5, 4), "c'4 c'4 c'4 c'2") 12 Measure((5, 4), "c'4 c'2 c'2") 13 Measure((5, 4), "c'4 c'2 c'4 c'4") 14 Measure((5, 4), "c'4 c'2. c'4") 15 Measure((5, 4), "c'4 c'1") Use for testing meter establishment. ''' from abjad.tools import scoretools # check input assert mathtools.is_positive_integer(grid_length) assert isinstance(rhythm_number, int) assert mathtools.is_positive_integer_power_of_two(denominator) # find count of all rhythms that fit grid length rhythm_count = 2**(grid_length - 1) # read rhythm number cyclically to allow large and # negative rhythm numbers rhythm_number = rhythm_number % rhythm_count # find binary representation of rhythm binary_representation = \ mathtools.integer_to_binary_string(rhythm_number) binary_representation = binary_representation.zfill(grid_length) # partition binary representation of rhythm parts = sequencetools.partition_sequence_by_value_of_elements( binary_representation) # find durations durations = [ durationtools.Duration(len(part), denominator) for part in parts ] # make notes notes = scoretools.make_notes([0], durations) # return notes return notes