Add cardinality set methods, conformance tests
This commit is contained in:
parent
5e924992d4
commit
066477755d
2 changed files with 80 additions and 0 deletions
|
|
@ -168,3 +168,35 @@ class SetClass(list):
|
||||||
pitches += f"{pitch}{sub}"
|
pitches += f"{pitch}{sub}"
|
||||||
sup = superscript(self.brightness)
|
sup = superscript(self.brightness)
|
||||||
return f"[{pitches}]{sup}"
|
return f"[{pitches}]{sup}"
|
||||||
|
|
||||||
|
# Class methods -----------------------------------------------------------
|
||||||
|
|
||||||
|
def all_of_cardinality(cardinality: int, tonality: int = 12) -> set:
|
||||||
|
"""
|
||||||
|
Returns all set classes of a given cardinality. Tonality can be specified, default is 12.
|
||||||
|
Warning: high values of tonality can take a long time to calculate (T=24 takes about a
|
||||||
|
minute on an Intel i7-13700H CPU).
|
||||||
|
"""
|
||||||
|
def _powerset(seq):
|
||||||
|
"""Set of all possible unique subsets."""
|
||||||
|
from itertools import chain, combinations
|
||||||
|
return chain.from_iterable(combinations(seq, r) for r in range(len(seq) + 1))
|
||||||
|
|
||||||
|
if tonality < cardinality:
|
||||||
|
return ValueError("Set classes of cardinality {cardinality} are not possible in a {tonality}-tone octave.")
|
||||||
|
|
||||||
|
a = set(SetClass(*i) for i in _powerset(range(tonality)) if len(i) == cardinality and 0 in i)
|
||||||
|
return a
|
||||||
|
|
||||||
|
def darkest_of_cardinality(cardinality: int, tonality: int = 12, prime: bool = False) -> set:
|
||||||
|
"""
|
||||||
|
Returns all set classes of a given cardinality, in their darkest forms (ignore rotations).
|
||||||
|
Tonality can be specified, default is 12.
|
||||||
|
Warning: high values of tonality can take a long time to calculate (T=24 takes about a
|
||||||
|
minute on an Intel i7-13700H CPU).
|
||||||
|
"""
|
||||||
|
if tonality < cardinality:
|
||||||
|
return ValueError("Set classes of cardinality {cardinality} are not possible in a {tonality}-tone octave.")
|
||||||
|
|
||||||
|
a = set(i.darkest_form for i in SetClass.all_of_cardinality(cardinality, tonality))
|
||||||
|
return a
|
||||||
|
|
|
||||||
|
|
@ -248,3 +248,51 @@ def test_empty_complement_dozenal_notation():
|
||||||
|
|
||||||
def test_empty_complement_leonard_notation():
|
def test_empty_complement_leonard_notation():
|
||||||
assert f121.leonard_notation == '[0₁1₁2₁3₁4₁5₁6₁7₁8₁9₁10₁11₁]⁶⁶'
|
assert f121.leonard_notation == '[0₁1₁2₁3₁4₁5₁6₁7₁8₁9₁10₁11₁]⁶⁶'
|
||||||
|
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def test_all_of_cardinality_set_lengths():
|
||||||
|
"Confirm expected lengths of the sets of set classes, for cardinality 1 through 12"
|
||||||
|
sets = [SetClass.all_of_cardinality(i + 1) for i in range(12)]
|
||||||
|
assert [len(s) for s in sets] == [1, 11, 55, 165, 330, 462, 462, 330, 165, 55, 11, 1]
|
||||||
|
|
||||||
|
|
||||||
|
def test_darkest_of_cardinality_set_lengths():
|
||||||
|
"Confirm expected lengths of the sets of set classes, for cardinality 1 through 12"
|
||||||
|
sets = [SetClass.darkest_of_cardinality(i + 1) for i in range(12)]
|
||||||
|
assert [len(s) for s in sets] == [1, 6, 22, 55, 66, 127, 66, 55, 22, 6, 1, 1]
|
||||||
|
|
||||||
|
|
||||||
|
def test_all_of_cardinality():
|
||||||
|
s3 = SetClass.all_of_cardinality(3)
|
||||||
|
s6 = SetClass.all_of_cardinality(6)
|
||||||
|
assert len(s3) == 55
|
||||||
|
assert len(s6) == 462
|
||||||
|
|
||||||
|
# all versions (rotations) of each set class are present
|
||||||
|
assert SetClass(0, 1, 2) in s3
|
||||||
|
assert SetClass(0, 10, 11) in s3
|
||||||
|
|
||||||
|
assert SetClass(0, 4, 6) in s3
|
||||||
|
assert SetClass(0, 6, 10) in s3
|
||||||
|
|
||||||
|
assert SetClass(0, 1, 3, 4, 8, 10) in s6
|
||||||
|
assert SetClass(0, 4, 6, 8, 9, 11) in s6
|
||||||
|
|
||||||
|
|
||||||
|
def test_darkest_of_cardinality():
|
||||||
|
s3 = SetClass.darkest_of_cardinality(3)
|
||||||
|
s6 = SetClass.darkest_of_cardinality(6)
|
||||||
|
assert len(s3) == 22
|
||||||
|
assert len(s6) == 127
|
||||||
|
|
||||||
|
# only one version (rotation) of each set class is present
|
||||||
|
assert SetClass(0, 1, 2) in s3
|
||||||
|
assert SetClass(0, 10, 11) not in s3
|
||||||
|
|
||||||
|
assert SetClass(0, 4, 6) in s3
|
||||||
|
assert SetClass(0, 6, 10) not in s3
|
||||||
|
|
||||||
|
assert SetClass(0, 1, 3, 4, 8, 10) in s6
|
||||||
|
assert SetClass(0, 4, 6, 8, 9, 11) not in s6
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue