mutwo.common_generators

Object

Documentation

mutwo.common_generators.random_walk_noise

Generate an instance of Brownian motion (i.e. the Wiener process).

mutwo.common_generators.make_bruns_euclidean_algorithm_generator

Make generator which runs Bruns adaption of the Euclidean algorithm.

mutwo.common_generators.NonTerminal

Can be used as a Mixin to define context-free grammar.

mutwo.common_generators.Terminal

Can be used as a Mixin to define context-free grammar.

mutwo.common_generators.ContextFreeGrammarRule

Describe a context_free_grammar_rule for a ContextFreeGrammar

mutwo.common_generators.ContextFreeGrammar

Describe a context-free grammar and resolve non-terminals

mutwo.common_generators.ActivityLevel

Python implementation of Michael Edwards activity level algorithm.

mutwo.common_generators.DynamicChoice

Weighted random choices with dynamically changing weights.

mutwo.common_generators.reflected_binary_code

Make gray code where each tuple has length items with modulus different numbers.

mutwo.common_generators.Tendency

Tendency offers an interface for dynamically changing minima / maxima areas.

mutwo.common_generators.Backtracking

Abstract base class to implement a backtracking algorithm

mutwo.common_generators.IndexBasedBacktracking

Abstract base class for index based backtracking algorithms

mutwo.common_generators.euclidean

Return euclidean rhythm as described in a 2005 paper by G. T. Toussaint.

mutwo.common_generators.paradiddle

Generates rhythm using the paradiddle method described by G. T. Toussaint.

mutwo.common_generators.alternating_hands

Generates rhythm using the alternating hands method described by G. T. Toussaint.

random_walk_noise(x0, n, dt, delta, out=None, random_state=None)[source]

Generate an instance of Brownian motion (i.e. the Wiener process).

Parameters:
  • x0 (float) – the initial condition(s) (i.e. position(s)) of the Brownian motion.

  • n (int) – the number of steps to take

  • dt (float) – the time step

  • delta (float) – delta determines the “speed” of the Brownian motion. The random variable of the position at time t, X(t), has a normal distribution whose mean is the position at time t=0 and whose variance is delta**2*t.

  • out (Optional[array]) – If out is not None, it specifies the array in which to put the result. If out is None, a new numpy array is created and returned.

  • random_state (Optional[int]) – set the random seed of the pseudo-random generator.

Returns:

A numpy array of floats with shape x0.shape + (n,).

Return type:

array

X(t) = X(0) + N(0, delta**2 * t; 0, t)

where N(a,b; t0, t1) is a normally distributed random variable with mean a and variance b. The parameters t0 and t1 make explicit the statistical independence of N on different time intervals; that is, if [t0, t1) and [t2, t3) are disjoint intervals, then N(a, b; t0, t1) and N(a, b; t2, t3) are independent.

Written as an iteration scheme,

X(t + dt) = X(t) + N(0, delta**2 * dt; t, t+dt)

If x0 is an array (or array-like), each value in x0 is treated as an initial condition, and the value returned is a numpy array with one more dimension than x0.

Note that the initial value x0 is not included in the returned array.

This code has been copied from the scipy cookbook:

https://scipy-cookbook.readthedocs.io/items/BrownianMotion.html

make_bruns_euclidean_algorithm_generator(element_tuple, matrix=array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]), subtraction_index=1)[source]

Make generator which runs Bruns adaption of the Euclidean algorithm.

Parameters:
  • element_tuple (tuple[_BrunEuclideanElement, _BrunEuclideanElement, _BrunEuclideanElement]) – 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__.

  • matrix (np.array) – The initial matrix.

  • subtraction_index (Literal[1, 2]) – This parameter has been added for the adaption of the function in 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.

Return type:

Generator

This algorithm has been described by V. Brun in his paper “EUCLIDEAN ALGORITHMS AND MUSICAL THEORY” (1964).

Example:

>>> import fractions
>>> from mutwo import common_generators
>>> b = common_generators.make_bruns_euclidean_algorithm_generator(
...     (
...         fractions.Fraction(2, 1),
...         fractions.Fraction(3, 2),
...         fractions.Fraction(5, 4),
...     )
... )
>>> next(b)
((Fraction(2, 1), Fraction(3, 2), Fraction(5, 4)), array([[1, 0, 0],
       [0, 1, 0],
       [0, 0, 1]]), Fraction(2, 1))
reflected_binary_code(length, modulus)[source]

Make gray code where each tuple has length items with modulus different numbers.

Parameters:
  • length (int) – how long one code is

  • modulus (int) – how many different numbers are included

Return type:

tuple[tuple[int, …], …]

Example:

>>> from mutwo import common_generators
>>> common_generators.reflected_binary_code(2, 2)
((0, 0), (0, 1), (1, 1), (1, 0))
>>> common_generators.reflected_binary_code(3, 2)
((0, 0, 0), (0, 0, 1), (0, 1, 1), (0, 1, 0), (1, 1, 0), (1, 1, 1), (1, 0, 1), (1, 0, 0))
>>> common_generators.reflected_binary_code(2, 3)
((0, 0), (0, 1), (0, 2), (1, 2), (1, 1), (1, 0), (2, 0), (2, 1), (2, 2))
Basic code has been copied from:

https://yetalengthothermodulusathblog.com/tag/gray-codes/

euclidean(size, distribution)[source]

Return euclidean rhythm as described in a 2005 paper by G. T. Toussaint.

Parameters:
  • size (int) – how many beats the rhythm contains

  • distribution (int) – how many beats are played

Returns:

The rhythm in relative time.

Return type:

tuple[int, …]

Example:

>>> from mutwo import common_generators
>>> common_generators.euclidean(8, 4)
(2, 2, 2, 2)
>>> common_generators.euclidean(7, 5)
(2, 1, 1, 2, 1)

The title of Toussaints paper is “The Euclidean Algorithm Generates Traditional Musical Rhythms”.

paradiddle(size)[source]

Generates rhythm using the paradiddle method described by G. T. Toussaint.

Parameters:

size (int) – how many beats the resulting rhythm shall last. ‘Size’ has to be divisible by 2 because of the symmetrical structure of the generated rhythm.

Returns:

Return nested tuple that contains two tuple where each tuple represents one rhythm (both rhythms are complementary to each other). The rhythms are encoded in absolute time values.

Return type:

tuple[tuple[int, …], …]

Example:

>>> from mutwo import common_generators
>>> common_generators.paradiddle(8)
((0, 2, 3, 5), (1, 4, 6, 7))
>>> common_generators.paradiddle(6)
((0, 4, 5), (1, 2, 3))

The paradiddle algorithm has been described by Godfried T. Toussaint in his paper ‘Generating “Good” Musical Rhythms Algorithmically’.

alternating_hands(seed_rhythm)[source]

Generates rhythm using the alternating hands method described by G. T. Toussaint.

Parameters:

seed_rhythm (tuple[int, ...]) – rhythm that shall be distributed on two hands.

Returns:

Return nested tuple that contains two tuple where each tuple represents one rhythm (both rhythms are complementary to each other). The rhythms are encoded in absolute time values.

Return type:

tuple[tuple[int, …], …]

Example:

>>> from mutwo import common_generators
>>> common_generators.alternating_hands((2, 2))
((0, 6), (2, 4))
>>> common_generators.alternating_hands((3, 2, 2))
((0, 5, 10), (3, 7, 12))

The alternating hands algorithm has been described by Godfried T. Toussaint in his paper ‘Generating “Good” Musical Rhythms Algorithmically’.

class NonTerminal[source]

Bases: object

Can be used as a Mixin to define context-free grammar.


class Terminal[source]

Bases: object

Can be used as a Mixin to define context-free grammar.


class ContextFreeGrammarRule(left_side, right_side)[source]

Bases: object

Describe a context_free_grammar_rule for a ContextFreeGrammar

Public Data Attributes:

left_side

right_side


Parameters:
left_side: NonTerminal
right_side: tuple[Union[mutwo.common_generators.chomksy.NonTerminal, mutwo.common_generators.chomksy.Terminal], ...]
class ContextFreeGrammar(context_free_grammar_rule_sequence)[source]

Bases: object

Describe a context-free grammar and resolve non-terminals

Parameters:

context_free_grammar_rule_sequence (Sequence[ContextFreeGrammarRule]) – A sequence of ContextFreeGrammarRule objects. It is allowed to provide multiple context_free_grammar_rules with the same :attribute:`left_side`.

This is a very reduced implementation of a context-free grammar which only provides the most basic functions. It is not made for the purpose of parsing text but rather as a technique to generate algorithmic data (for the sake of art creation). Therefore it is all about the resolution of start objects to variants of this start.

Public Data Attributes:

non_terminal_tuple

terminal_tuple

context_free_grammar_rule_tuple

Get all defined rules

Public Methods:

get_context_free_grammar_rule_tuple(non_terminal)

Find all defined context_free_grammar_rules for the provided NonTerminal.

resolve_one_layer(tree)

Resolve all leaves of the tree.

resolve(start[, limit])

Resolve until only Terminal are left or the limit is reached.


get_context_free_grammar_rule_tuple(non_terminal)[source]

Find all defined context_free_grammar_rules for the provided NonTerminal.

Parameters:

non_terminal (NonTerminal) – The left side element of the ContextFreeGrammarRule.

Return type:

tuple[mutwo.common_generators.chomksy.ContextFreeGrammarRule, …]

resolve(start, limit=None)[source]

Resolve until only Terminal are left or the limit is reached.

Parameters:
  • start (NonTerminal) – The start value.

  • limit (Optional[int]) – The maximum node levels until the function returns a tree. If it is set to None it will only stop once all nodes are Terminal.

Return type:

Tree

resolve_one_layer(tree)[source]

Resolve all leaves of the tree.

Parameters:

tree (treelib.Tree) – The tree from which all leaves should be resolved.

Returns:

True if any leaf has been resolved and False if no resolution has happened (e.g. if there are only Terminal left).

Return type:

bool

property context_free_grammar_rule_tuple: tuple[mutwo.common_generators.chomksy.ContextFreeGrammarRule, ...]

Get all defined rules

property non_terminal_tuple: tuple[mutwo.common_generators.chomksy.NonTerminal, ...]
property terminal_tuple: tuple[mutwo.common_generators.chomksy.Terminal, ...]
class ActivityLevel(start_at=0)[source]

Bases: object

Python implementation of Michael Edwards activity level algorithm.

Parameters:

start_at (int) – from which pattern per level shall be started (can be either 0, 1 or 2)

Activity Levels is a concept derived from Michael Edwards. Quoting Michael Edwards, Activity Levels are an “object for determining (deterministically) on a call-by-call basis whether a process is active or not (boolean). This is determined by nine 10-element lists (actually three versions of each) of hand-coded 1s and 0s, each list representing an ‘activity-level’ (how active the process should be). The first three 10-element lists have only one 1 in them, the rest being zeros. The second three have two 1s, etc. Activity-levels of 0 and 10 would return never active and always active respectively.”.

Example:

>>> from mutwo import common_generators
>>> activity_levels = common_generators.ActivityLevel()
>>> activity_levels(0)  # activity level 0 will always return False
False
>>> activity_levels(10)  # activity level 10 will always return True
True
>>> activity_levels(7)  # activity level 7 will mostly return True
True
>>> tuple(activity_levels(7) for _ in range(10))
(True, False, True, True, False, True, True, False, True, True)

class DynamicChoice(value_sequence, curve_sequence, random_seed=100)[source]

Bases: object

Weighted random choices with dynamically changing weights.

Parameters:
  • value_sequence (Sequence[Any]) – The items to choose from.

  • curve_sequence (Sequence[core_events.Envelope]) – The dynamically changing weight for each value.

  • random_seed (int) – The seed which shall be set at class initialisation.

Example:

>>> from mutwo import core_events
>>> from mutwo import common_generators
>>> dynamic_choice = common_generators.DynamicChoice(
...    [0, 1, 2],
...    [
...        core_events.Envelope([(0, 0), (0.5, 1), (1, 0)]),
...        core_events.Envelope([(0, 0.5), (0.5, 0), (1, 0.5)]),
...        core_events.Envelope([(0, 0.5), (1, 1)]),
...    ],
... )
>>> dynamic_choice.gamble_at(0.3)
0
>>> dynamic_choice.gamble_at(0.3)
1
>>> dynamic_choice.gamble_at(0.3)
2

Public Methods:

items()

gamble_at(time)

Return value at requested time.


gamble_at(time)[source]

Return value at requested time.

Parameters:

time (numbers.Real) – At which position on the x-Axis shall be gambled.

Returns:

The chosen value.

Return type:

Any

items()[source]
Return type:

tuple[tuple[Any, mutwo.core_events.envelopes.Envelope]]

class Tendency(minima_curve, maxima_curve, random_seed=100)[source]

Bases: object

Tendency offers an interface for dynamically changing minima / maxima areas.

Parameters:
  • minima_curve (core_events.Envelope) – The curve which describes the smallest allowed value over the time axis.

  • maxima_curve (core_events.Envelope) – The curve which describes the biggest allowed value over the time axis.

  • random_seed (int) – The random seed which shall be set.

The class is based on Gottfried Michael Koenigs algorithm of “Tendenz-Masken” in his program “Projekt 2” where those minima / maxima areas represent probability fields.

Example:

>>> from mutwo import core_events
>>> from mutwo import common_generators
>>> minima_curve = core_events.Envelope([(0, 0), (1, 1), (2, 0)])
>>> maxima_curve = core_events.Envelope([(0, 1), (1, 2), (2, 3)])
>>> my_tendency = common_generators.Tendency(minima_curve, maxima_curve)
>>> my_tendency.value_at(0.5)
1.3349816305020088
>>> my_tendency.value_at(0.5)
1.0965540269678873

Public Data Attributes:

minima_curve

maxima_curve

Public Methods:

range_at(time)

Get minima / maxima range at requested time.

value_at(time)

Get value at requested time.


range_at(time)[source]

Get minima / maxima range at requested time.

Parameters:

time (float) –

Return type:

Range

value_at(time)[source]

Get value at requested time.

Parameters:

time (float) –

Return type:

float

property maxima_curve: Envelope
property minima_curve: Envelope
class Backtracking[source]

Bases: ABC

Abstract base class to implement a backtracking algorithm

By inheriting from this class, various backtracking algorithms can be implemented. In order to do so the user has to override a set of abstract methods. The abstract methods include:

Furthermore it may be helpful to override the following method (even though there is a valid working implementation):

Please see the methods documentation for more details.

The implementation of this backtracking algorithm makes a distinction between an element list and a solution. A solution is created by an element list. A solution is the output a user wants to get, but an element list is an object which is used internally in order to solve the problem. When implementing a backtracking algorithm by using this interface the user doesn’t have to make the distinction between both (and in this case treat both in the same way).

The most common use case for this distinction is by having a set of items which can appear in the solution and a list of indices which item of set shall be used. In this case the element_list is actually a list of indices. This use case is implemented in the IndexBasedBacktracking class.

Bitner and Reingold [2] credit Derrick H. Lehmer with first using the term ‘backtrack’ in the 1950s..

Public Data Attributes:

solution_count

Return expected solution size

Public Methods:

is_valid(element_list)

Checks if an element list provides an acceptable solution.

append_new_element(element_list)

Append new element to element list.

update_last_element(element_list)

Increments value of the last element in an element_list.

can_last_element_be_updated(element_list)

Checks if the last element of the list can be incremented.

element_list_to_solution(element_list)

Converts an element list to the final solution

solve([return_element_list])

Apply backtracking algorithm.


abstract append_new_element(element_list)[source]

Append new element to element list.

Parameters:

element_list (list[Any]) – The element list to which a new element shall be appended.

abstract can_last_element_be_updated(element_list)[source]

Checks if the last element of the list can be incremented.

Parameters:

element_list (list[Any]) – The element list which last value shall be checked.

Return type:

bool

element_list_to_solution(element_list)[source]

Converts an element list to the final solution

Parameters:

element_list (list[Any]) – The element list to be converted.

Return type:

tuple[Any, …]

abstract is_valid(element_list)[source]

Checks if an element list provides an acceptable solution.

Returns:

True if the solution is acceptable and False if the solution is rejected.

Parameters:

element_list (list[Any]) –

Return type:

bool

solve(return_element_list=False)[source]

Apply backtracking algorithm.

Parameters:

return_element_list (bool) – If set to True the function will not only return the solution, but also the element list.

Return type:

Union[tuple[Any, …], tuple[tuple[Any, …], list[Any]]]

abstract update_last_element(element_list)[source]

Increments value of the last element in an element_list.

Parameters:

element_list (list[Any]) – The element list which last value shall be updated.

This function should raise an Exception in case the last element can’t be updated.

abstract property solution_count: int

Return expected solution size

class IndexBasedBacktracking[source]

Bases: Backtracking

Abstract base class for index based backtracking algorithms

This class implements concrete solutions for the following methods which are inherited from the parent class Backtracking:

The following methods still have to be implemented:

(Please consult for more information the documentation of Backtracking).

Furthermore the class adds new abstract methods to be implemented by child classes:

Example:

>>> import itertools
>>> from mutwo import common_generators
>>> class QueenProblem8(common_generators.IndexBasedBacktracking):
...     queen_count = 8
...     point_list = list(itertools.combinations_with_replacement(range(queen_count), 2))
...     point_list.extend(
...         [tuple(reversed(point)) for point in point_list if len(set(point)) == 2]
...     )
...     def element_index_to_item_sequence(self, element_index, element_list):
...         return self.point_list
...     @property
...     def solution_count(self):
...         # 8 queens problem!
...         return 8
...     def is_valid(self, element_list):
...         solution = self.element_list_to_solution(element_list)
...         for q0, q1 in itertools.combinations(solution, 2):
...             # x != x, y != y
...             is_valid = all(v0 != v1 for v0, v1 in zip(q0, q1))
...             diff_x, diff_y = (v0 - v1 for v0, v1 in zip(q0, q1))
...             is_valid = is_valid and (diff_x != diff_y)
...             if not is_valid: return False
...         return True
>>> queen_problem_8 = QueenProblem8()
>>> queen_problem_8.solve()
((0, 0), (1, 2), (2, 5), (3, 7), (4, 6), (6, 1), (5, 3), (7, 4))

Public Data Attributes:

Inherited from Backtracking

solution_count

Return expected solution size

Public Methods:

element_index_to_item_sequence(...)

Get a sequence of items to choose from for a specific element

append_new_element(element_list)

Append new element to element list.

update_last_element(element_list)

Increments value of the last element in an element_list.

can_last_element_be_updated(element_list)

Checks if the last element of the list can be incremented.

element_list_to_solution(element_list)

Converts an element list to the final solution

Inherited from Backtracking

is_valid(element_list)

Checks if an element list provides an acceptable solution.

append_new_element(element_list)

Append new element to element list.

update_last_element(element_list)

Increments value of the last element in an element_list.

can_last_element_be_updated(element_list)

Checks if the last element of the list can be incremented.

element_list_to_solution(element_list)

Converts an element list to the final solution

solve([return_element_list])

Apply backtracking algorithm.


append_new_element(element_list)[source]

Append new element to element list.

Parameters:

element_list (list[Any]) – The element list to which a new element shall be appended.

can_last_element_be_updated(element_list)[source]

Checks if the last element of the list can be incremented.

Parameters:

element_list (list[Any]) – The element list which last value shall be checked.

Return type:

bool

abstract element_index_to_item_sequence(element_index, element_list)[source]

Get a sequence of items to choose from for a specific element

Parameters:
  • element_index (int) – The index of the element for which a sequence of solutions shall be returned.

  • element_list (list[Any]) – The current element list

Return type:

Sequence[Any]

element_list_to_solution(element_list)[source]

Converts an element list to the final solution

Parameters:

element_list (list[Any]) – The element list to be converted.

Return type:

tuple[Any, …]

update_last_element(element_list)[source]

Increments value of the last element in an element_list.

Parameters:

element_list (list[Any]) – The element list which last value shall be updated.

This function should raise an Exception in case the last element can’t be updated.

mutwo.common_generators.constants

Constants which are used in mutwo.common_generators.

ACTIVITY_LEVEL_TUPLE = (((0,), (0,), (0,)), ((1, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 1, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 1, 0, 0, 0)), ((1, 0, 0, 0, 0, 0, 1, 0, 0, 0), (0, 0, 0, 1, 0, 1, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 1, 1, 0, 0)), ((1, 0, 0, 0, 1, 0, 1, 0, 0, 0), (0, 0, 0, 1, 0, 1, 1, 0, 0, 0), (0, 0, 1, 0, 0, 0, 1, 1, 0, 0)), ((1, 0, 0, 0, 1, 0, 1, 1, 0, 0), (0, 1, 0, 1, 0, 1, 1, 0, 0, 0), (0, 0, 1, 0, 0, 0, 1, 1, 0, 1)), ((1, 1, 0, 0, 1, 0, 1, 1, 0, 0), (0, 1, 0, 1, 0, 1, 1, 0, 0, 1), (0, 0, 1, 0, 1, 0, 1, 1, 0, 1)), ((1, 1, 0, 1, 1, 0, 1, 1, 0, 0), (0, 1, 0, 1, 0, 1, 1, 0, 1, 1), (0, 1, 1, 0, 1, 0, 1, 1, 0, 1)), ((1, 1, 0, 1, 1, 0, 1, 1, 0, 1), (1, 1, 0, 1, 0, 1, 1, 0, 1, 1), (1, 1, 1, 0, 1, 0, 1, 1, 0, 1)), ((1, 1, 0, 1, 1, 1, 1, 1, 0, 1), (1, 1, 1, 1, 0, 1, 1, 0, 1, 1), (1, 1, 1, 0, 1, 1, 1, 1, 0, 1)), ((1, 1, 0, 1, 1, 1, 1, 1, 1, 1), (1, 1, 1, 1, 0, 1, 1, 1, 1, 1), (1, 1, 1, 1, 1, 1, 1, 1, 0, 1)), ((1,), (1,), (1,)))

Definition of activity level pattern. Pattern are copied from Michael Edwards Common Lisp composition software ‘slippery-chicken’.