def get_sequence_period_of_rotation(sequence, n): '''Change `sequence` to period of rotation: :: >>> sequencetools.get_sequence_period_of_rotation([1, 2, 3, 1, 2, 3], 1) 3 :: >>> sequencetools.get_sequence_period_of_rotation([1, 2, 3, 1, 2, 3], 2) 3 :: >>> sequencetools.get_sequence_period_of_rotation([1, 2, 3, 1, 2, 3], 3) 1 Returns positive integer. ''' degree = get_sequence_degree_of_rotational_symmetry(sequence) period = len(sequence) / degree divisors_of_n = set(mathtools.divisors(n)) divisors_of_period = set(mathtools.divisors(period)) max_shared_divisor = max(divisors_of_n & divisors_of_period) return period / max_shared_divisor
def test_mathtools_divisors_01(): r'''Positive divisors of integer n. ''' assert mathtools.divisors(1) == [1] assert mathtools.divisors(2) == [1, 2] assert mathtools.divisors(3) == [1, 3] assert mathtools.divisors(-4) == [1, 2, 4] assert mathtools.divisors(-5) == [1, 5] assert mathtools.divisors(-6) == [1, 2, 3, 6] assert mathtools.divisors(7) == [1, 7] assert mathtools.divisors(8) == [1, 2, 4, 8] assert mathtools.divisors(9) == [1, 3, 9] assert mathtools.divisors(10) == [1, 2, 5, 10]
def is_compound(self): r'''Is true when meter is compound. Otherwise false. .. container:: example **Example 1.** Compound meters written over ``4``: :: >>> for numerator in range(1, 13): ... meter = metertools.Meter((numerator, 4)) ... string = True if meter.is_compound else '' ... print(str(meter), string) ... 1/4 2/4 3/4 4/4 5/4 6/4 True 7/4 8/4 9/4 True 10/4 11/4 12/4 True .. container:: example **Example 2.** Compound meters written over ``8``: :: >>> for numerator in range(1, 13): ... meter = metertools.Meter((numerator, 8)) ... string = True if meter.is_compound else '' ... print(str(meter), string) ... 1/8 2/8 3/8 4/8 5/8 6/8 True 7/8 8/8 9/8 True 10/8 11/8 12/8 True Compound meters defined equal to those meters with a numerator divisible by ``3`` (but not equal to ``3``). Returns true or false. ''' if 3 in mathtools.divisors(self.numerator): if not self.numerator == 3: return True return False
def greatest_common_divisor(*integers): '''Calculates greatest common divisor of `integers`. :: >>> mathtools.greatest_common_divisor(84, -94, -144) 2 Allows nonpositive input. Raises type error on noninteger input. Raises not implemented error when ``0`` is included in input. Returns positive integer. ''' from abjad.tools import mathtools common_divisors = None for positive_integer in integers: all_divisors = set(mathtools.divisors(positive_integer)) if common_divisors is None: common_divisors = all_divisors else: common_divisors &= all_divisors if common_divisors == set([1]): return 1 return max(common_divisors)
def _is_valid_definition(self, definition): if not isinstance(definition, dict): return False elif 'divisors' not in definition: return False elif not len(definition['divisors']): return False elif not all(isinstance(x, int) and \ 1 < x for x in definition['divisors']): return False elif not all(mathtools.divisors(x) == [1, x] for x in definition['divisors']): return False elif 'max_depth' not in definition: return False elif not isinstance(definition['max_depth'], int): return False elif not 0 < definition['max_depth']: return False elif 'max_divisions' not in definition: return False elif not isinstance(definition['max_divisions'], int): return False elif not 1 < definition['max_divisions']: return False return True
def _is_valid_definition(self, definition): if not isinstance(definition, dict): return False elif 'divisors' not in definition: return False elif not len(definition['divisors']): return False elif not all( isinstance(x, int) and 1 < x for x in definition['divisors']): return False elif not all( mathtools.divisors(x) == [1, x] for x in definition['divisors']): return False elif 'max_depth' not in definition: return False elif not isinstance(definition['max_depth'], int): return False elif not 0 < definition['max_depth']: return False elif 'max_divisions' not in definition: return False elif not isinstance(definition['max_divisions'], int): return False elif not 1 < definition['max_divisions']: return False return True
def greatest_common_divisor(*integers): '''Calculates greatest common divisor of `integers`. .. container:: example >>> abjad.mathtools.greatest_common_divisor(84, -94, -144) 2 Allows nonpositive input. Raises not implemented error when zero is included in input. Returns positive integer. ''' from abjad.tools import mathtools common_divisors = None for positive_integer in integers: all_divisors = set(mathtools.divisors(positive_integer)) if common_divisors is None: common_divisors = all_divisors else: common_divisors &= all_divisors if common_divisors == set([1]): return 1 return max(common_divisors)
def recurse(n): results = [] for key in n: if not isinstance(key, int) or \ not 0 < key or \ not mathtools.divisors(key) == [1, key]: results.append(False) elif not isinstance(n[key], (dict, type(None))): results.append(False) elif isinstance(n[key], dict) and not recurse(n[key]): results.append(False) else: results.append(True) return results
def rewrite_integer_tempo(integer_tempo, maximum_numerator=None, maximum_denominator=None): r'''Rewrite `integer_tempo`. Allow no tempo less than half `integer_tempo` or greater than double `integer_tempo`: :: >>> pairs = tempotools.rewrite_integer_tempo( ... 58, maximum_numerator=8, maximum_denominator=8) :: >>> for pair in pairs: ... pair ... (Multiplier(1, 2), 29) (Multiplier(1, 1), 58) (Multiplier(3, 2), 87) (Multiplier(2, 1), 116) Returns list. ''' # find divisors divisors = mathtools.divisors(integer_tempo) if maximum_denominator is not None: divisors = [x for x in divisors if x <= maximum_denominator] # make pairs pairs = [] for divisor in divisors: start = int(math.ceil(divisor / 2.0)) stop = 2 * divisor numerators = range(start, stop + 1) if maximum_numerator is not None: numerators = [x for x in numerators if x <= maximum_numerator] for numerator in numerators: multiplier = durationtools.Multiplier(numerator, divisor) new_tempo = fractions.Fraction(multiplier * integer_tempo) assert mathtools.is_integer_equivalent_number(new_tempo) new_tempo = int(new_tempo) pair = (multiplier, new_tempo) if pair not in pairs: pairs.append(pair) # sort pairs pairs.sort() # return pairs return pairs
def respell_division(self, division): r'''Respells `division` according to partition table. .. container:: example **Example 1.** Respells divisions according to table: :: >>> table = rhythmmakertools.PartitionTable([ ... (2, [1, 1]), ... (3, [2, 1]), ... (5, [3, 2]), ... (7, [4, 3]), ... ]) :: >>> for numerator in range(1, 15): ... division = mathtools.NonreducedFraction(numerator, 4) ... result = table.respell_division(division) ... print((division, result)) (NonreducedFraction(1, 4), [NonreducedFraction(1, 4)]) (NonreducedFraction(2, 4), [NonreducedFraction(1, 4), NonreducedFraction(1, 4)]) (NonreducedFraction(3, 4), [NonreducedFraction(2, 4), NonreducedFraction(1, 4)]) (NonreducedFraction(4, 4), [NonreducedFraction(2, 4), NonreducedFraction(2, 4)]) (NonreducedFraction(5, 4), [NonreducedFraction(3, 4), NonreducedFraction(2, 4)]) (NonreducedFraction(6, 4), [NonreducedFraction(4, 4), NonreducedFraction(2, 4)]) (NonreducedFraction(7, 4), [NonreducedFraction(4, 4), NonreducedFraction(3, 4)]) (NonreducedFraction(8, 4), [NonreducedFraction(4, 4), NonreducedFraction(4, 4)]) (NonreducedFraction(9, 4), [NonreducedFraction(6, 4), NonreducedFraction(3, 4)]) (NonreducedFraction(10, 4), [NonreducedFraction(6, 4), NonreducedFraction(4, 4)]) (NonreducedFraction(11, 4), [NonreducedFraction(11, 4)]) (NonreducedFraction(12, 4), [NonreducedFraction(8, 4), NonreducedFraction(4, 4)]) (NonreducedFraction(13, 4), [NonreducedFraction(13, 4)]) (NonreducedFraction(14, 4), [NonreducedFraction(8, 4), NonreducedFraction(6, 4)]) .. container:: example **Example 2.** Respells divisions according to another table: :: >>> table = rhythmmakertools.PartitionTable([ ... (5, [1, 3, 1]), ... (7, [1, 2, 4]), ... ]) :: >>> for numerator in range(1, 15): ... division = mathtools.NonreducedFraction(numerator, 4) ... result = table.respell_division(division) ... print((division, result)) (NonreducedFraction(1, 4), [NonreducedFraction(1, 4)]) (NonreducedFraction(2, 4), [NonreducedFraction(2, 4)]) (NonreducedFraction(3, 4), [NonreducedFraction(3, 4)]) (NonreducedFraction(4, 4), [NonreducedFraction(4, 4)]) (NonreducedFraction(5, 4), [NonreducedFraction(1, 4), NonreducedFraction(3, 4), NonreducedFraction(1, 4)]) (NonreducedFraction(6, 4), [NonreducedFraction(6, 4)]) (NonreducedFraction(7, 4), [NonreducedFraction(1, 4), NonreducedFraction(2, 4), NonreducedFraction(4, 4)]) (NonreducedFraction(8, 4), [NonreducedFraction(8, 4)]) (NonreducedFraction(9, 4), [NonreducedFraction(9, 4)]) (NonreducedFraction(10, 4), [NonreducedFraction(2, 4), NonreducedFraction(6, 4), NonreducedFraction(2, 4)]) (NonreducedFraction(11, 4), [NonreducedFraction(11, 4)]) (NonreducedFraction(12, 4), [NonreducedFraction(12, 4)]) (NonreducedFraction(13, 4), [NonreducedFraction(13, 4)]) (NonreducedFraction(14, 4), [NonreducedFraction(2, 4), NonreducedFraction(4, 4), NonreducedFraction(8, 4)]) Returns list of new divisions. ''' division = mathtools.NonreducedFraction(division) result = [division] divisors = mathtools.divisors(division.numerator) for numerator, ratio in reversed(list(self.items())): if numerator in divisors: result = [division * _ for _ in ratio.multipliers] break result = [mathtools.NonreducedFraction(_) for _ in result] return result
def list_related_tempos( self, maximum_numerator=None, maximum_denominator=None, ): r'''Lists tempos related to this tempo. Returns list of tempo / ratio pairs. Each new tempo equals not less than half of this tempo and not more than twice this tempo. .. container:: example Rewrites tempo ``58`` MM by ratios of the form ``n:d`` such that ``1 <= n <= 8`` and ``1 <= d <= 8``: ... :: >>> tempo = Tempo(Duration(1, 4), 58) >>> pairs = tempo.list_related_tempos( ... maximum_numerator=8, ... maximum_denominator=8, ... ) :: >>> for tempo, ratio in pairs: ... string = '{!s}\t{!s}'.format(tempo, ratio) ... print string 4=29 1:2 4=58 1:1 4=87 3:2 4=116 2:1 .. container:: example Rewrites tempo ``58`` MM by ratios of the form ``n:d`` such that ``1 <= n <= 30`` and ``1 <= d <= 30``: :: >>> tempo = Tempo(Duration(1, 4), 58) >>> pairs = tempo.list_related_tempos( ... maximum_numerator=30, ... maximum_denominator=30, ... ) :: >>> for tempo, ratio in pairs: ... string = '{!s}\t{!s}'.format(tempo, ratio) ... print string ... 4=30 15:29 4=32 16:29 4=34 17:29 4=36 18:29 4=38 19:29 4=40 20:29 4=42 21:29 4=44 22:29 4=46 23:29 4=48 24:29 4=50 25:29 4=52 26:29 4=54 27:29 4=56 28:29 4=58 1:1 4=60 30:29 Returns list. ''' # assert integer tempo assert isinstance(self.units_per_minute, int), repr(self) # find divisors divisors = mathtools.divisors(self.units_per_minute) if maximum_denominator is not None: divisors = [x for x in divisors if x <= maximum_denominator] # make pairs pairs = [] for divisor in divisors: start = int(math.ceil(divisor / 2.0)) stop = 2 * divisor numerators = range(start, stop + 1) if maximum_numerator is not None: numerators = [ x for x in numerators if x <= maximum_numerator ] for numerator in numerators: ratio = mathtools.Ratio(numerator, divisor) multiplier = durationtools.Multiplier(*ratio) new_units_per_minute = multiplier * self.units_per_minute assert mathtools.is_integer_equivalent_expr( new_units_per_minute) new_units_per_minute = int(new_units_per_minute) new_tempo = type(self)(self.duration, new_units_per_minute) pair = (new_tempo, ratio) if pair not in pairs: pairs.append(pair) # sort pairs pairs.sort() # return pairs return pairs
def list_related_tempos( self, maximum_numerator=None, maximum_denominator=None, ): r'''Lists tempos related to this tempo. Returns list of tempo / ratio pairs. Each new tempo equals not less than half of this tempo and not more than twice this tempo. .. container:: example Rewrites tempo ``58`` MM by ratios of the form ``n:d`` such that ``1 <= n <= 8`` and ``1 <= d <= 8``: ... :: >>> tempo = Tempo(Duration(1, 4), 58) >>> pairs = tempo.list_related_tempos( ... maximum_numerator=8, ... maximum_denominator=8, ... ) :: >>> for tempo, ratio in pairs: ... string = '{!s}\t{!s}'.format(tempo, ratio) ... print(string) 4=29 1:2 4=58 1:1 4=87 3:2 4=116 2:1 .. container:: example Rewrites tempo ``58`` MM by ratios of the form ``n:d`` such that ``1 <= n <= 30`` and ``1 <= d <= 30``: :: >>> tempo = Tempo(Duration(1, 4), 58) >>> pairs = tempo.list_related_tempos( ... maximum_numerator=30, ... maximum_denominator=30, ... ) :: >>> for tempo, ratio in pairs: ... string = '{!s}\t{!s}'.format(tempo, ratio) ... print(string) ... 4=30 15:29 4=32 16:29 4=34 17:29 4=36 18:29 4=38 19:29 4=40 20:29 4=42 21:29 4=44 22:29 4=46 23:29 4=48 24:29 4=50 25:29 4=52 26:29 4=54 27:29 4=56 28:29 4=58 1:1 4=60 30:29 Returns list. ''' # assert integer tempo assert isinstance(self.units_per_minute, int), repr(self) # find divisors divisors = mathtools.divisors(self.units_per_minute) if maximum_denominator is not None: divisors = [x for x in divisors if x <= maximum_denominator] # make pairs pairs = [] for divisor in divisors: start = int(math.ceil(divisor / 2.0)) stop = 2 * divisor numerators = range(start, stop + 1) if maximum_numerator is not None: numerators = [ x for x in numerators if x <= maximum_numerator ] for numerator in numerators: ratio = mathtools.Ratio(numerator, divisor) multiplier = durationtools.Multiplier(*ratio) new_units_per_minute = multiplier * self.units_per_minute assert mathtools.is_integer_equivalent_expr( new_units_per_minute) new_units_per_minute = int(new_units_per_minute) new_tempo = type(self)( duration=self.duration, units_per_minute=new_units_per_minute, ) pair = (new_tempo, ratio) if pair not in pairs: pairs.append(pair) # sort pairs pairs.sort() # return pairs return pairs