Wedgie: Difference between revisions

→How to read a wedgie: make it explicit that readers are expected to learn another system first
→Conversion: complete
 
Line 75: Line 75:
== Conversion ==
== Conversion ==
=== Mapping matrix to wedgie ===
=== Mapping matrix to wedgie ===
The wedgie may be found from the mapping by taking the {{w|determinant}}s of the mapping's column slices that correspond to all the combinations of formal primes.  
The wedgie may be found from the mapping by taking the {{w|determinant}}s of the mapping's column slices that correspond to all the combinations of formal primes. Below is a minimalistic [https://www.python.org/ Python] script that finds the wedgie from a mapping matrix, using [https://scipy.org/ SciPy].  
 
Below is a [https://www.python.org/ Python] script that finds the wedgie from a mapping matrix, using [https://scipy.org/ Scipy].  


<syntaxhighlight lang="python">
<syntaxhighlight lang="python">
Line 84: Line 82:
from scipy import linalg
from scipy import linalg


def wedgie (breeds):
def breeds2wedgie (breeds):
    """Takes a mapping, returns the corresponding wedgie. """
 
     r, d = breeds.shape # rank and dimensionality
     r, d = breeds.shape # rank and dimensionality
     combinations = itertools.combinations (range (d), r)
     combinations = itertools.combinations (range (d), r)
Line 103: Line 103:


=== Wedgie to mapping matrix ===
=== Wedgie to mapping matrix ===
{{Todo|inline=1| expand }}
Converting, or ''decomposing'', a wedgie to a mapping matrix is much more complicated. [[Gene Ward Smith]]'s provided an algorithm, explained in [[Dave Keenan & Douglas Blumeyer's guide to EA for RTT #Gene's algorithm]], and implemented in Python by [[Flora Canou]] as part of the [https://github.com/FloraCanou/temperament_evaluator Temperament Evaluator] since v1.21.0. Below is an adaptation. It requires [https://numpy.org/ NumPy] and [https://www.sympy.org/en/index.html SymPy].
 
<syntaxhighlight lang="python">
import itertools, math
import numpy as np
from sympy.matrices import Matrix, normalforms
 
def wedgie2breeds (wedgie):
    """
    Takes a wedgie, returns the corresponding mapping if decomposable,
    or None otherwise. Gene Ward Smith's algorithm.
    """
   
    def inversion_count (a):
        """
        Returns the number of inversions in an array,
        which equals the number of swaps required to sort it.
        https://stackoverflow.com/a/20990301
        """
        length = len (a)
        count = 0 
        for i in range (length - 1):
            for j in range (i + 1, length):
                if a[i] > a[j]:
                    count += 1
        return count
   
    def hnf (a):
        """Normalizes a matrix row-style to the Hermite normal form. """
        return np.flip (np.array (
            normalforms.hermite_normal_form (Matrix (np.flip (a).T)).T, dtype = int))
 
    # check contorsion
    if np.gcd.reduce (wedgie.flat) != 1:
        return None
 
    # find the rank r and dimensionality d
    r = wedgie.ndim
    length = len (wedgie.flat)
    for d in itertools.count (start = r):
        length_current = math.comb (d, r)
        if length_current == length:
            break
        elif length_current > length:
            raise ValueError ("invalid length for the rank. ")
   
    # gene's b and c, converted to tuples
    # so that they will reset themselves on the beginning of each loop
    combinations = tuple (itertools.combinations (range (d), r))
    subcombinations = tuple (itertools.combinations (range (d), r - 1))
 
    # main algorithm
    breeds = np.zeros ((len (subcombinations), d), dtype = int)
    for i, si in enumerate (subcombinations):
        for j in range (d):
            if j in si:
                continue
           
            appended_index = (*si, j)
            sign = 1 if inversion_count (appended_index) % 2 == 0 else -1
            k = combinations.index (tuple (sorted (appended_index)))
            breeds[i][j] = sign*wedgie.flat[k]
   
    breeds = hnf (breeds)
    return breeds if breeds.shape == (r, d) else None
</syntaxhighlight>


== Derivation from edo joins ==
== Derivation from edo joins ==