TriuneCadence/composer_ans/types.py

90 lines
1.9 KiB
Python

from __future__ import annotations
from dataclasses import dataclass
from pathlib import Path
NOTE_VOCABULARY_SIZE = 8
SEQUENCE_LENGTH = 5
ART_INPUT_LENGTH = 41
ART_CATEGORY_LIMIT = 25
HOPFIELD_WEIGHT_DIMENSION = 64
SALIERI_NODE_COUNT = 61
NoteSequence = tuple[int, ...]
@dataclass(frozen=True)
class LegacyPaths:
root: Path
@property
def sequence_data(self) -> Path:
return self.root / "SEQUENCE.DAT"
@property
def salieri_config(self) -> Path:
return self.root / "S61.DAT"
@property
def salieri_weights(self) -> Path:
return self.root / "S61.WT"
@property
def hopfield_weights(self) -> Path:
return self.root / "HTN.DAT"
@dataclass(frozen=True)
class SalieriConfig:
learning_rate: float
alpha: float
n_input: int
n_hidden: int
n_output: int
training_iterations: int
error_tolerance: float
data_file: str
report_file: str
weight_file: str
@dataclass(frozen=True)
class LegacyBPWeights:
vector_length: int
weights: tuple[tuple[float, ...], ...]
thetas: tuple[float, ...]
@dataclass(frozen=True)
class CompositionContext:
notes: NoteSequence = (0, 0, 0, 0, 0)
delta_vigilance: bool = False
new_category: bool = False
is_classical: bool = False
candidate_note: int = 0
since_novelty: int = 0
frustration: int = 0
note_count: int = 0
@dataclass(frozen=True)
class CompositionRecord:
notes: tuple[int, ...]
per_note_seconds: tuple[float, ...] = ()
total_seconds: float = 0.0
@dataclass(frozen=True)
class CompositionRunReport:
notes: tuple[int, ...]
per_note_seconds: tuple[float, ...]
total_seconds: float
parameters: dict[str, object]
note_count: int
alphabet_size: int
unigram_entropy_bits: float
conditional_entropy_bits: float
normalized_entropy: float
predictability: float
redundancy: float