Skip to main content

sim_lib_pitch_serial/
class.rs

1//! Row-class reports that retain aliases, stabilizers, and invariance evidence.
2
3use crate::{
4    AllIntervalReport, CombinatorialPartner, DerivationReport, OrderedIntervalString, RowFamilySet,
5    RowOperation, SegmentInvariant, ToneRow, analyze_all_interval, analyze_derivation,
6    analyze_invariance,
7};
8
9/// One alias entry in a [`RowClassReport`].
10#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
11pub struct RowClassAlias {
12    /// The represented row-family operation.
13    pub operation: RowOperation,
14    /// The index of the corresponding row in [`RowClassReport::distinct_forms`].
15    pub distinct_form_index: usize,
16}
17
18/// One distinct form together with the operations and invariance facts that realize it.
19#[derive(Clone, Debug, PartialEq, Eq)]
20pub struct FormEquivalence {
21    /// The deduplicated form index.
22    pub distinct_form_index: usize,
23    /// The distinct row value.
24    pub row: ToneRow,
25    /// Every alias operation that realizes `row`.
26    pub operations: Vec<RowOperation>,
27    /// Whole-row invariance facts comparing the source row to `row`.
28    pub invariant: SegmentInvariant,
29}
30
31/// Ordered, symmetric, and equivalence evidence for one strict tone row.
32#[derive(Clone, Debug, PartialEq, Eq)]
33pub struct RowClassReport {
34    /// The analyzed source row.
35    pub row: ToneRow,
36    /// The source row's directed ordered-interval string.
37    pub ordered_intervals: OrderedIntervalString,
38    /// Generator-cell derivation evidence over supported equal contiguous partitions.
39    pub derivation: DerivationReport,
40    /// All-interval evidence over the source row's adjacent directed intervals.
41    pub all_interval: AllIntervalReport,
42    /// Prime, inversional, retrograde, and retrograde-inversional combinatorial partners.
43    pub combinatoriality: Vec<CombinatorialPartner>,
44    /// Every operation alias paired with its deduplicated row index.
45    pub aliases: Vec<RowClassAlias>,
46    /// The deduplicated row values in first-alias order.
47    pub distinct_forms: Vec<ToneRow>,
48    /// Operations that stabilize the source row exactly.
49    pub stabilizers: Vec<RowOperation>,
50    /// Distinct forms grouped with their alias and invariance evidence.
51    pub form_equivalences: Vec<FormEquivalence>,
52}
53
54/// Analyzes one row's ordered intervals, symmetry stabilizers, and form equivalences.
55pub fn analyze_row_class(row: &ToneRow) -> RowClassReport {
56    let family = RowFamilySet::of(row);
57    let aliases = family
58        .aliases()
59        .iter()
60        .map(|alias| RowClassAlias {
61            operation: alias.operation,
62            distinct_form_index: alias.distinct_form_index(),
63        })
64        .collect::<Vec<_>>();
65    let distinct_forms = family.distinct_forms().to_vec();
66    let stabilizers = family
67        .aliases()
68        .iter()
69        .filter(|alias| alias.form.row() == row)
70        .map(|alias| alias.operation)
71        .collect::<Vec<_>>();
72    let left = row
73        .indexed_segment(&(0..row.classes().len()).collect::<Vec<_>>())
74        .expect("full-row indexed segment is valid");
75    let form_equivalences = distinct_forms
76        .iter()
77        .enumerate()
78        .map(|(distinct_form_index, form)| {
79            let right = form
80                .indexed_segment(&(0..form.classes().len()).collect::<Vec<_>>())
81                .expect("full-row indexed segment is valid");
82            let operations = family
83                .aliases_for_distinct_form(distinct_form_index)
84                .map(|alias| alias.operation)
85                .collect::<Vec<_>>();
86            FormEquivalence {
87                distinct_form_index,
88                row: form.clone(),
89                operations,
90                invariant: analyze_invariance(&left, &right),
91            }
92        })
93        .collect();
94
95    RowClassReport {
96        row: row.clone(),
97        ordered_intervals: row.ordered_intervals(),
98        derivation: analyze_derivation(row),
99        all_interval: analyze_all_interval(row),
100        combinatoriality: crate::analyze_combinatoriality(row).partners,
101        aliases,
102        distinct_forms,
103        stabilizers,
104        form_equivalences,
105    }
106}