TriuneCadence/tests/test_hopfield.py

60 lines
1.7 KiB
Python

from pathlib import Path
from composer_ans.hopfield import HopfieldParams, generate_next_note, run_hopfield_network
from composer_ans.io.legacy_files import extract_active_hopfield_submatrix, load_hopfield_weight_matrix
THES = Path(__file__).resolve().parents[1] / "THES"
def deterministic_noise(mean: float, variance: float) -> float:
return mean
def test_hopfield_zero_matrix_converges_to_first_note_for_blank_column() -> None:
zero_matrix = tuple(tuple(0.0 for _ in range(40)) for _ in range(40))
result = generate_next_note(
[1, 2, 3, 4, 0],
zero_matrix,
noise=deterministic_noise,
)
assert result.output_notes[:4] == (1, 2, 3, 4)
assert result.candidate_note == 1
assert result.iterations > 0
def test_generic_hopfield_core_runs_on_arbitrary_grid_shape() -> None:
inputs = (
(0.8, 0.2),
(0.1, 0.9),
(0.4, 0.3),
)
size = len(inputs) * len(inputs[0])
weights = tuple(tuple(0.0 for _ in range(size)) for _ in range(size))
result = run_hopfield_network(inputs, weights)
assert result.iterations > 0
assert len(result.state.outputs) == 3
assert len(result.state.outputs[0]) == 2
def test_hopfield_legacy_matrix_runs_with_deterministic_noise() -> None:
matrix = extract_active_hopfield_submatrix(load_hopfield_weight_matrix(THES / "HTN.DAT"))
result = generate_next_note(
[1, 4, 5, 1, 0],
matrix,
params=HopfieldParams(),
noise=deterministic_noise,
)
assert len(result.output_notes) == 5
assert all(1 <= note <= 8 for note in result.output_notes)
assert 1 <= result.candidate_note <= 8
assert result.iterations > 0
assert len(result.outputs) == 8
assert len(result.outputs[0]) == 5