- Replace cumulative_trans with average cents of actual chord
- More accurate register targeting using current chord position
- Test with max_path=150 shows reaching ~400 Hz target (2 octaves)
- Replace harsh 1/(1+distance) with bounded relative scoring
- Factor > 1.0 when moving toward target, < 1.0 when moving away
- Minimum factor 0.1 to avoid zero weights
- Test with max_path=150 shows reaching ~90% of 2-octave target
- Add --target-range CLI option (in octaves)
- Implement target_range weight in PathFinder
- Add test for target range weight
- Add --max-path to README
The Hamiltonian weight was comparing transposed output chords
against untransposed graph nodes, so they never matched.
Now tracks graph_path separately for correct Hamiltonian check.
- Sort pitches by frequency after projection in generate_connected_sets
- This ensures all chords in graph have bass-to-soprano ordering
- Simplified voice crossing check: verify destination is sorted after movement
- Since source is sorted, just check if adjacent pairs remain in order
- Fixed movement map indexing bug in precomputed voice crossing detection
- Replace index-based voice crossing check with pitch ordering comparison
- Now properly detects when voice ordering changes between chords
- This was causing edges with voice crossing to be incorrectly allowed
- Deduplicate transpositions in _find_valid_edges using set comprehension
to avoid processing same transposition multiple times
- Edge count now matches notebook (1414 vs 2828)
- Rename expand() to project() for clarity (project to [1,2) range)
- Fix SyntaxWarnings in docstrings (escape backslashes)
- Add _is_directly_tunable method to check if changing pitches are adjacent to staying pitch
- Modify _find_valid_edges to compute and return edge properties
- Store all properties in graph edges at build time
- Simplify _calculate_edge_weights to read from edge data
- Rename voice_crossing config to voice_crossing_allowed (False = reject crossing)
- Change movement map from {pitch: {destination, cents}} to {src_idx: dest_idx}
- Track voice mapping cumulatively in pathfinder
- Reorder output pitches according to voice mapping
- Update weight calculation to compute cent_diffs from index mapping
- Melodic threshold now correctly filters edges based on actual movements
- Add movement tracking to edges: {source: {destination, cent_difference}}
- Fix movement map to handle multiple changing pitches with permutations
- Remove melodic threshold from graph building (apply in weight calculation)
- Add melodic_threshold_min/max to weight config
- Add CLI args --melodic-min and --melodic-max
- New compact_sets.py with Pitch, Chord, HarmonicSpace classes
- Voice leading graph with change parameter (instead of symdiff)
- CLI: --change, --dims, --chord-size, --max-path, --seed
- Tests for core functionality
- .gitignore for Python/pytest