Add inversions, is_symmetrical, z_relations, split test files
This commit is contained in:
parent
0b968d8e48
commit
6f9cfb62b5
5 changed files with 221 additions and 185 deletions
|
|
@ -48,7 +48,8 @@ class SetClass(list):
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
"""Return the Python instance string representation."""
|
"""Return the Python instance string representation."""
|
||||||
return f"SetClass{set(self.pitch_classes) or '{}'}".replace(' ', '')
|
s = f"SetClass{{{','.join(str(i) for i in self.pitch_classes)}}}"
|
||||||
|
return s if self.tonality == 12 else f"{s} (T={self.tonality})"
|
||||||
|
|
||||||
def __hash__(self) -> int:
|
def __hash__(self) -> int:
|
||||||
return sum([hash(i) for i in self.pitch_classes])
|
return sum([hash(i) for i in self.pitch_classes])
|
||||||
|
|
@ -90,7 +91,16 @@ class SetClass(list):
|
||||||
return intervals
|
return intervals
|
||||||
|
|
||||||
@cache_property
|
@cache_property
|
||||||
def interval_vector(self):
|
def z_relations(self):
|
||||||
|
"""
|
||||||
|
Return all distinct set classes with the same interval vector (Allan Forte: "Z-related").
|
||||||
|
For example, Forte 4-Z15 {0,1,4,6} and Forte 4-Z29 {0,1,3,7} both have iv⟨1,1,1,1,1,1⟩ but
|
||||||
|
are not inversions, complements, or transpositions (rotations) of each other.
|
||||||
|
"""
|
||||||
|
return [i for i in SetClass.darkest_of_cardinality(self.cardinality) if i.interval_vector == self.interval_vector]
|
||||||
|
|
||||||
|
@cache_property
|
||||||
|
def interval_vector(self) -> list:
|
||||||
"""
|
"""
|
||||||
An ordered tuple containing the multiplicities of each interval class in the set class.
|
An ordered tuple containing the multiplicities of each interval class in the set class.
|
||||||
Denoted in angle-brackets, e.g.
|
Denoted in angle-brackets, e.g.
|
||||||
|
|
@ -125,7 +135,7 @@ class SetClass(list):
|
||||||
def versions(self):
|
def versions(self):
|
||||||
"""
|
"""
|
||||||
Returns all possible zero-normalised versions (clock rotations) of this set class,
|
Returns all possible zero-normalised versions (clock rotations) of this set class,
|
||||||
sorted by brightness.
|
sorted by brightness. See Rahn (1987) Set types, Tₙ
|
||||||
"""
|
"""
|
||||||
# The empty set class has one version, itself
|
# The empty set class has one version, itself
|
||||||
if not self.pitch_classes:
|
if not self.pitch_classes:
|
||||||
|
|
@ -133,8 +143,8 @@ class SetClass(list):
|
||||||
|
|
||||||
versions = set()
|
versions = set()
|
||||||
for i in self.pitch_classes:
|
for i in self.pitch_classes:
|
||||||
translate = self.tonality - i
|
transpose = self.tonality - i
|
||||||
versions.add(SetClass(*[j + translate for j in self.pitch_classes], tonality=self.tonality))
|
versions.add(SetClass(*[j + transpose for j in self.pitch_classes], tonality=self.tonality))
|
||||||
versions = list(versions)
|
versions = list(versions)
|
||||||
versions.sort(key=lambda x: x.brightness)
|
versions.sort(key=lambda x: x.brightness)
|
||||||
return versions
|
return versions
|
||||||
|
|
@ -155,6 +165,22 @@ class SetClass(list):
|
||||||
"""
|
"""
|
||||||
return self.versions[-1] if self.versions else self
|
return self.versions[-1] if self.versions else self
|
||||||
|
|
||||||
|
@cache_property
|
||||||
|
def inversion(self):
|
||||||
|
"""
|
||||||
|
Returns the inversion of this set class, equivalent of reflection through the 0 axis on a
|
||||||
|
clock diagram.
|
||||||
|
"""
|
||||||
|
return SetClass(*[self.tonality - i for i in self.pitch_classes], tonality=self.tonality)
|
||||||
|
|
||||||
|
@cache_property
|
||||||
|
def is_symmetrical(self):
|
||||||
|
"""
|
||||||
|
Returns whether this set class is symmetrical upon inversion, for example Forte 5-Z17:
|
||||||
|
{0,1,2,5,9} → {0,4,8,9,11}
|
||||||
|
"""
|
||||||
|
return self.darkest_form == self.inversion.darkest_form
|
||||||
|
|
||||||
@cache_property
|
@cache_property
|
||||||
def complement(self):
|
def complement(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -217,7 +243,7 @@ class SetClass(list):
|
||||||
if tonality < cardinality:
|
if tonality < cardinality:
|
||||||
return ValueError("Set classes of cardinality {cardinality} are not possible in a {tonality}-tone octave.")
|
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)
|
a = set(SetClass(*i, tonality=tonality) for i in _powerset(range(tonality)) if len(i) == cardinality and 0 in i)
|
||||||
return a
|
return a
|
||||||
|
|
||||||
def darkest_of_cardinality(cardinality: int, tonality: int = 12, prime: bool = False) -> set:
|
def darkest_of_cardinality(cardinality: int, tonality: int = 12, prime: bool = False) -> set:
|
||||||
|
|
|
||||||
60
setclass/tests/test_aggregate.py
Normal file
60
setclass/tests/test_aggregate.py
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
from setclass.setclass import SetClass
|
||||||
|
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Forte 12-1, the complement of empty is the "aggregate" set class
|
||||||
|
f121 = SetClass().complement
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_complement():
|
||||||
|
assert f121 == SetClass(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_complement_tonality():
|
||||||
|
assert f121.tonality == 12
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_complement_cardinality():
|
||||||
|
assert f121.cardinality == 12
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_complement_brightness():
|
||||||
|
assert f121.brightness == 66
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_complement_pitch_classes():
|
||||||
|
assert len(f121) == 12
|
||||||
|
assert len(f121.pitch_classes) == 12
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_complement_adjacency_intervals():
|
||||||
|
assert len(f121.adjacency_intervals) == 12
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_complement_versions():
|
||||||
|
assert len(f121.versions) == 1
|
||||||
|
assert f121.versions[0] == f121
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_complement_brightest_form():
|
||||||
|
assert f121.brightest_form == f121
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_complement_darkest_form():
|
||||||
|
assert f121.darkest_form == f121
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_complement_bright_dark_forms_equal():
|
||||||
|
assert f121.brightest_form == f121.darkest_form
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_complement_duodecimal_notation():
|
||||||
|
assert f121.duodecimal_notation == 'SetClass{0,1,2,3,4,5,6,7,8,9,T,E}'
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_complement_dozenal_notation():
|
||||||
|
assert f121.dozenal_notation == 'SetClass{0,1,2,3,4,5,6,7,8,9,↊,↋}'
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_complement_leonard_notation():
|
||||||
|
assert f121.leonard_notation == '[0₁1₁2₁3₁4₁5₁6₁7₁8₁9₁10₁11₁]⁽⁶⁶⁾'
|
||||||
47
setclass/tests/test_cardinalities.py
Normal file
47
setclass/tests/test_cardinalities.py
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
from setclass.setclass import SetClass
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
56
setclass/tests/test_empty.py
Normal file
56
setclass/tests/test_empty.py
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
from setclass.setclass import SetClass
|
||||||
|
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Forte 0-1, the empty set class
|
||||||
|
empty = SetClass()
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_tonality():
|
||||||
|
assert empty.tonality == 12
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_cardinality():
|
||||||
|
assert empty.cardinality == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_brightness():
|
||||||
|
assert empty.brightness == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_pitch_classes():
|
||||||
|
assert len(empty) == 0
|
||||||
|
assert len(empty.pitch_classes) == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_ajdacency_intervals():
|
||||||
|
assert len(empty.adjacency_intervals) == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_versions():
|
||||||
|
assert len(empty.versions) == 1
|
||||||
|
assert empty.versions[0] == empty
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_brightest_form():
|
||||||
|
assert empty.brightest_form == empty
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_darkest_form():
|
||||||
|
assert empty.darkest_form == empty
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_bright_dark_forms_equal():
|
||||||
|
assert empty.brightest_form == empty.darkest_form
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_duodecimal_notation():
|
||||||
|
assert empty.duodecimal_notation == 'SetClass{}'
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_dozenal_notation():
|
||||||
|
assert empty.dozenal_notation == 'SetClass{}'
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_leonard_notation():
|
||||||
|
assert empty.leonard_notation == '[]⁽⁰⁾'
|
||||||
|
|
@ -5,24 +5,28 @@ from setclass.setclass import SetClass
|
||||||
# Functional tests
|
# Functional tests
|
||||||
|
|
||||||
|
|
||||||
def test_zero_normalised_intervals():
|
def test_zero_normalised_pc():
|
||||||
|
"Pitch classes are normalised to start at zero"
|
||||||
a = SetClass(0, 1, 3)
|
a = SetClass(0, 1, 3)
|
||||||
assert a == SetClass(1, 2, 4)
|
assert a == SetClass(1, 2, 4)
|
||||||
assert a == SetClass(4, 5, 7)
|
assert a == SetClass(4, 5, 7)
|
||||||
|
|
||||||
|
|
||||||
def test_modulo_intervals():
|
def test_modulo_pc():
|
||||||
|
"Pitch classes are normalised to modulo tonality (12)"
|
||||||
a = SetClass(0, 1, 3)
|
a = SetClass(0, 1, 3)
|
||||||
assert a == SetClass(12, 13, 15) # modulo down
|
assert a == SetClass(12, 13, 15) # modulo down
|
||||||
assert a == SetClass(-11, -9, -12) # modulo up
|
assert a == SetClass(-11, -9, -12) # modulo up
|
||||||
|
|
||||||
|
|
||||||
def test_negative_intervals():
|
def test_negative_pc():
|
||||||
|
"Negative pitch classes are modulo tonality (12)"
|
||||||
a = SetClass(0, 9, 10)
|
a = SetClass(0, 9, 10)
|
||||||
assert a == SetClass(-3, -2, 0)
|
assert a == SetClass(-3, -2, 0)
|
||||||
|
|
||||||
|
|
||||||
def test_immutable_intervals():
|
def test_unordered_pc():
|
||||||
|
"Set classes are unordered; normalised to incremental sort"
|
||||||
a = SetClass(0, 1, 3)
|
a = SetClass(0, 1, 3)
|
||||||
assert a == SetClass(0, 3, 1)
|
assert a == SetClass(0, 3, 1)
|
||||||
assert a == SetClass(3, 0, 1)
|
assert a == SetClass(3, 0, 1)
|
||||||
|
|
@ -31,7 +35,8 @@ def test_immutable_intervals():
|
||||||
assert a == SetClass(3, 1, 0)
|
assert a == SetClass(3, 1, 0)
|
||||||
|
|
||||||
|
|
||||||
def test_repeat_intervals():
|
def test_resolve_duplicate_pc():
|
||||||
|
"Set classes are sets, so duplicates (including after modulo) are eliminated"
|
||||||
a = SetClass(0, 1, 3)
|
a = SetClass(0, 1, 3)
|
||||||
assert a == SetClass(0, 1, 3, 3, 1)
|
assert a == SetClass(0, 1, 3, 3, 1)
|
||||||
assert a == SetClass(0, 12, 1, -11, 15)
|
assert a == SetClass(0, 12, 1, -11, 15)
|
||||||
|
|
@ -39,8 +44,9 @@ def test_repeat_intervals():
|
||||||
|
|
||||||
|
|
||||||
def test_interval_vector():
|
def test_interval_vector():
|
||||||
|
"Set classes have an interval vector"
|
||||||
test = [
|
test = [
|
||||||
# pairs of set class, expected interval vector
|
# 2-tuple of set class, expected interval vector
|
||||||
(SetClass(0, 3, 4, 7, 8, 11), [3, 0, 3, 6, 3, 0]),
|
(SetClass(0, 3, 4, 7, 8, 11), [3, 0, 3, 6, 3, 0]),
|
||||||
(SetClass(0, 1, 3, 5, 6, 8, 10), [2, 5, 4, 3, 6, 1]),
|
(SetClass(0, 1, 3, 5, 6, 8, 10), [2, 5, 4, 3, 6, 1]),
|
||||||
]
|
]
|
||||||
|
|
@ -48,19 +54,16 @@ def test_interval_vector():
|
||||||
assert sc.interval_vector == iv
|
assert sc.interval_vector == iv
|
||||||
|
|
||||||
|
|
||||||
def test_interval_vector_invarance():
|
def test_interval_vector_invarant():
|
||||||
|
"The interval vector is invariant under inversion and transposition (rotation)"
|
||||||
test = [
|
test = [
|
||||||
SetClass(0, 1, 3, 5, 6, 8, 10),
|
# 2-tuple of set class, expected interval vector
|
||||||
SetClass(0, 1, 3, 5, 7, 8, 10),
|
(SetClass(0, 3, 4, 7, 8, 11), [3, 0, 3, 6, 3, 0]),
|
||||||
SetClass(0, 2, 3, 5, 7, 8, 10),
|
(SetClass(0, 1, 3, 5, 6, 8, 10), [2, 5, 4, 3, 6, 1]),
|
||||||
SetClass(0, 2, 3, 5, 7, 9, 10),
|
|
||||||
SetClass(0, 2, 4, 5, 7, 9, 10),
|
|
||||||
SetClass(0, 2, 4, 5, 7, 9, 11),
|
|
||||||
SetClass(0, 2, 4, 6, 7, 9, 11),
|
|
||||||
]
|
]
|
||||||
iv = [2, 5, 4, 3, 6, 1]
|
for (sc, iv) in test:
|
||||||
for sc in test:
|
for version in (sc.versions + sc.inversion.versions):
|
||||||
assert sc.interval_vector == iv
|
assert version.interval_vector == iv
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
|
|
@ -69,27 +72,33 @@ f520 = SetClass(0, 1, 5, 6, 8)
|
||||||
|
|
||||||
|
|
||||||
def test_tonality():
|
def test_tonality():
|
||||||
|
"Set classes has a default tonality of 12"
|
||||||
assert f520.tonality == 12
|
assert f520.tonality == 12
|
||||||
|
|
||||||
|
|
||||||
def test_cardinality():
|
def test_cardinality():
|
||||||
|
"Set classes has a set cardinality"
|
||||||
assert f520.cardinality == 5
|
assert f520.cardinality == 5
|
||||||
|
|
||||||
|
|
||||||
def test_brightness():
|
def test_brightness():
|
||||||
|
"Set classes have a brightness (sum of normalised pitch class values)"
|
||||||
assert f520.brightness == 20
|
assert f520.brightness == 20
|
||||||
|
|
||||||
|
|
||||||
def test_pitch_classes():
|
def test_pitch_classes():
|
||||||
|
"Set classes have pitch classes"
|
||||||
assert len(f520) == 5
|
assert len(f520) == 5
|
||||||
assert len(f520.pitch_classes) == 5
|
assert len(f520.pitch_classes) == 5
|
||||||
|
|
||||||
|
|
||||||
def test_adjacency_intervals():
|
def test_adjacency_intervals():
|
||||||
|
"Set classes have a set of adjacency intervals"
|
||||||
assert len(f520.adjacency_intervals) == 5
|
assert len(f520.adjacency_intervals) == 5
|
||||||
|
|
||||||
|
|
||||||
def test_versions():
|
def test_versions():
|
||||||
|
"Set classes have a set of transpositions (rotations)"
|
||||||
assert len(f520.versions) == 5
|
assert len(f520.versions) == 5
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -159,165 +168,3 @@ def test_complement_darkest_form():
|
||||||
|
|
||||||
def test_complement_leonard_notation():
|
def test_complement_leonard_notation():
|
||||||
assert f520.complement.leonard_notation == '[0₁1₁2₃5₂7₁8₁9₃]⁽³²⁾'
|
assert f520.complement.leonard_notation == '[0₁1₁2₃5₂7₁8₁9₃]⁽³²⁾'
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------
|
|
||||||
# Forte 0-1, the empty set class
|
|
||||||
empty = SetClass()
|
|
||||||
|
|
||||||
|
|
||||||
def test_empty_tonality():
|
|
||||||
assert empty.tonality == 12
|
|
||||||
|
|
||||||
|
|
||||||
def test_empty_cardinality():
|
|
||||||
assert empty.cardinality == 0
|
|
||||||
|
|
||||||
|
|
||||||
def test_empty_brightness():
|
|
||||||
assert empty.brightness == 0
|
|
||||||
|
|
||||||
|
|
||||||
def test_empty_pitch_classes():
|
|
||||||
assert len(empty) == 0
|
|
||||||
assert len(empty.pitch_classes) == 0
|
|
||||||
|
|
||||||
|
|
||||||
def test_empty_ajdacency_intervals():
|
|
||||||
assert len(empty.adjacency_intervals) == 0
|
|
||||||
|
|
||||||
|
|
||||||
def test_empty_versions():
|
|
||||||
assert len(empty.versions) == 1
|
|
||||||
assert empty.versions[0] == empty
|
|
||||||
|
|
||||||
|
|
||||||
def test_empty_brightest_form():
|
|
||||||
assert empty.brightest_form == empty
|
|
||||||
|
|
||||||
|
|
||||||
def test_empty_darkest_form():
|
|
||||||
assert empty.darkest_form == empty
|
|
||||||
|
|
||||||
|
|
||||||
def test_empty_bright_dark_forms_equal():
|
|
||||||
assert empty.brightest_form == empty.darkest_form
|
|
||||||
|
|
||||||
|
|
||||||
def test_empty_duodecimal_notation():
|
|
||||||
assert empty.duodecimal_notation == 'SetClass{}'
|
|
||||||
|
|
||||||
|
|
||||||
def test_empty_dozenal_notation():
|
|
||||||
assert empty.dozenal_notation == 'SetClass{}'
|
|
||||||
|
|
||||||
|
|
||||||
def test_empty_leonard_notation():
|
|
||||||
assert empty.leonard_notation == '[]⁽⁰⁾'
|
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------
|
|
||||||
# Forte 12-1, the complement of empty is the "aggregate" set class
|
|
||||||
f121 = empty.complement
|
|
||||||
|
|
||||||
|
|
||||||
def test_empty_complement():
|
|
||||||
assert f121 == SetClass(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)
|
|
||||||
|
|
||||||
|
|
||||||
def test_empty_complement_tonality():
|
|
||||||
assert f121.tonality == 12
|
|
||||||
|
|
||||||
|
|
||||||
def test_empty_complement_cardinality():
|
|
||||||
assert f121.cardinality == 12
|
|
||||||
|
|
||||||
|
|
||||||
def test_empty_complement_brightness():
|
|
||||||
assert f121.brightness == 66
|
|
||||||
|
|
||||||
|
|
||||||
def test_empty_complement_pitch_classes():
|
|
||||||
assert len(f121) == 12
|
|
||||||
assert len(f121.pitch_classes) == 12
|
|
||||||
|
|
||||||
|
|
||||||
def test_empty_complement_adjacency_intervals():
|
|
||||||
assert len(f121.adjacency_intervals) == 12
|
|
||||||
|
|
||||||
|
|
||||||
def test_empty_complement_versions():
|
|
||||||
assert len(f121.versions) == 1
|
|
||||||
assert f121.versions[0] == f121
|
|
||||||
|
|
||||||
|
|
||||||
def test_empty_complement_brightest_form():
|
|
||||||
assert f121.brightest_form == f121
|
|
||||||
|
|
||||||
|
|
||||||
def test_empty_complement_darkest_form():
|
|
||||||
assert f121.darkest_form == f121
|
|
||||||
|
|
||||||
|
|
||||||
def test_empty_complement_bright_dark_forms_equal():
|
|
||||||
assert f121.brightest_form == f121.darkest_form
|
|
||||||
|
|
||||||
|
|
||||||
def test_empty_complement_duodecimal_notation():
|
|
||||||
assert f121.duodecimal_notation == 'SetClass{0,1,2,3,4,5,6,7,8,9,T,E}'
|
|
||||||
|
|
||||||
|
|
||||||
def test_empty_complement_dozenal_notation():
|
|
||||||
assert f121.dozenal_notation == 'SetClass{0,1,2,3,4,5,6,7,8,9,↊,↋}'
|
|
||||||
|
|
||||||
|
|
||||||
def test_empty_complement_leonard_notation():
|
|
||||||
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