Source code for mutwo.common_generators.brun
"""Algorithms which are related to Norwegian mathematician V. Brun."""
import abc
import typing
import numpy as np
__all__ = ("make_bruns_euclidean_algorithm_generator",)
@typing.runtime_checkable
class _BrunEuclideanElement(typing.Protocol):
"""An ABC with abstract methods __sub__, __lt__ and __gt__."""
__slots__ = ()
@abc.abstractmethod
def __sub__(self) -> typing.Any:
pass
@abc.abstractmethod
def __lt__(self, other) -> bool:
pass
@abc.abstractmethod
def __gt__(self, other) -> bool:
pass
[docs]def make_bruns_euclidean_algorithm_generator(
element_tuple: tuple[
_BrunEuclideanElement, _BrunEuclideanElement, _BrunEuclideanElement
],
matrix: np.array = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]], dtype=int),
subtraction_index: typing.Literal[1, 2] = 1,
) -> typing.Generator:
"""Make generator which runs Bruns adaption of the Euclidean algorithm.
:param element_tuple: The initial elements which gets re-calculated
after each step. Type doesn't matter; objects only need to have
the following magic methods: __sub__, __lt__ and __gt__.
:type element_tuple: tuple[_BrunEuclideanElement, _BrunEuclideanElement, _BrunEuclideanElement]
:param matrix: The initial matrix.
:type matrix: np.array
:param subtraction_index: This parameter has been added for the adaption of the
function in
:func:`~mutwo.generators.wilson.make_wilsons_brun_euclidean_algorithm_generator`
and is not part of Bruns original algorithm. It describes whether in each step
the first element gets subtracted by the second (original) or by the third
(Wilson adaption) element.
:type subtraction_index: typing.Literal[1, 2]
This algorithm has been described by V. Brun in his paper "EUCLIDEAN ALGORITHMS
AND MUSICAL THEORY" (1964).
**Example:**
>>> import fractions
>>> from mutwo.generators import brun
>>> bruns_euclidean_algorithm_generator = brun.make_bruns_euclidean_algorithm_generator(
>>> (
>>> fractions.Fraction(2, 1),
>>> fractions.Fraction(3, 2),
>>> fractions.Fraction(5, 4),
>>> )
>>> )
>>> next(bruns_euclidean_algorithm_generator)
"""
while True:
sorted_element_tuple = tuple(sorted(element_tuple, reverse=True))
indices = [element_tuple.index(element) for element in sorted_element_tuple]
matrix = matrix[indices]
yield sorted_element_tuple, matrix.copy(), element_tuple[0]
element_tuple = (
sorted_element_tuple[0] - sorted_element_tuple[subtraction_index],
) + sorted_element_tuple[1:]
matrix[1] += matrix[0]