Add list of bright Rahn normal forms

This commit is contained in:
Jonathan Harker 2024-09-27 10:00:40 +12:00
parent 36de6f409b
commit d6b4b07d86
2 changed files with 56 additions and 1 deletions

View file

@ -290,3 +290,18 @@ class SetClass(list):
minute on an Intel i7-13700H CPU). minute on an Intel i7-13700H CPU).
""" """
return set(i.rahn_normal_form for i in SetClass.all_of_cardinality(cardinality, tonality)) return set(i.rahn_normal_form for i in SetClass.all_of_cardinality(cardinality, tonality))
def bright_rahn_normal_forms():
"""
John Rahn's normal form from _Basic Atonal Theory_ (1980) is an algorithm to produce a unique
form for each set class. Most of the time it is also the "darkest" (smallest brightness value),
except for all the times when that is not the case; this function returns that list, as a set of
(cardinality, darkest, rahn) tuples.
"""
cases = set()
for C in range(13): # 0 to 12
for sc in SetClass.all_of_cardinality(C):
if sc.darkest_form.brightness < sc.rahn_normal_form.brightness:
cases.add((C, sc.darkest_form, sc.rahn_normal_form))
return cases

View file

@ -1,4 +1,4 @@
from setclass.setclass import SetClass from setclass.setclass import SetClass, bright_rahn_normal_forms
def test_brightness_conjecture(): def test_brightness_conjecture():
@ -19,3 +19,43 @@ def test_brightness_conjecture():
test = sc.complement.inversion.darkest_form.brightness - sc.brightness test = sc.complement.inversion.darkest_form.brightness - sc.brightness
ΔB = int((T - 1) * (T / 2 - C)) ΔB = int((T - 1) * (T / 2 - C))
assert test == ΔB, f"T={T}, C={C}, ΔB={ΔB}, diff={test}: {sc.darkest_form}, {sc.complement.inversion.darkest_form}" assert test == ΔB, f"T={T}, C={C}, ΔB={ΔB}, diff={test}: {sc.darkest_form}, {sc.complement.inversion.darkest_form}"
def test_bright_rahn():
"""
There are 63 instances where the Rahn normal form is not also the "darkest" (smallest sum of
pitch class values).
"""
R = bright_rahn_normal_forms()
assert len(R) == 63
counts = {
0: 0,
1: 0,
2: 0,
3: 1,
4: 3,
5: 17,
6: 7,
7: 23,
8: 9,
9: 3,
10: 0,
11: 0,
12: 0
}
for C in range(13): # 0 to 12
bright_rahns = set(i for i in R if i[0] == C)
assert len(bright_rahns) == counts[C]
def print_bright_rahn():
"""
Convenience function, to print the list of set classes where John Rahn's normal form is not the
"darkest" form (that with the smallest brightness value), as pairs of "darkest" and Rahn normal
form pairs, using Leonard notation, sorted by cardinality then brightness (sum of pitch class
values).
"""
print("Smallest brightness, Rahn normal form")
set_classes = sorted(bright_rahn_normal_forms(), key=lambda x: x[0] * 1000 + x[1].brightness)
for (C, d, r) in set_classes:
print(f"{d.leonard_notation}, {r.leonard_notation}")