Fix DCA Hamiltonian: normalize by max instead of sum
- Change normalization from sum to max: visit_count / max^2 - This gives stronger discrimination toward unvisited nodes - Weight 1 now gives 66.2% coverage (vs 63.6% baseline) - Rename CLI: --weight-dca -> --weight-dca-voice-movement - Rename CLI: --weight-hamiltonian -> --weight-dca-hamiltonian - Restore DCA Hamiltonian display in analysis output - Update README with new CLI names and factor descriptions
This commit is contained in:
parent
218d7a55ff
commit
b20f02b60f
17
README.md
17
README.md
|
|
@ -36,8 +36,8 @@ These factors weigh edges without eliminating them. Set weight to 0 to disable.
|
||||||
|
|
||||||
- `--weight-melodic` - Weight for melodic threshold (default: 1)
|
- `--weight-melodic` - Weight for melodic threshold (default: 1)
|
||||||
- `--weight-contrary-motion` - Weight for contrary motion (default: 0)
|
- `--weight-contrary-motion` - Weight for contrary motion (default: 0)
|
||||||
- `--weight-hamiltonian` - Weight for Hamiltonian path (default: 1)
|
- `--weight-dca-hamiltonian` - Weight for DCA Hamiltonian (favors unvisited nodes, default: 1)
|
||||||
- `--weight-dca` - Weight for DCA
|
- `--weight-dca-voice-movement` - Weight for DCA voice movement (favors voice changes, default: 1)
|
||||||
- `--weight-target-range` - Weight for target register range (default: 1)
|
- `--weight-target-range` - Weight for target register range (default: 1)
|
||||||
|
|
||||||
### Target Range
|
### Target Range
|
||||||
|
|
@ -54,8 +54,8 @@ These factors weigh edges without eliminating them. Set weight to 0 to disable.
|
||||||
### Soft Factors (Weigh edges)
|
### Soft Factors (Weigh edges)
|
||||||
- **Melodic threshold**: Penalizes edges with voice movements outside the melodic range
|
- **Melodic threshold**: Penalizes edges with voice movements outside the melodic range
|
||||||
- **Contrary motion**: Boosts edges where some voices move up and others move down
|
- **Contrary motion**: Boosts edges where some voices move up and others move down
|
||||||
- **Hamiltonian**: Penalizes edges that revisit nodes already in the path
|
- **DCA Hamiltonian**: Boosts edges to nodes that haven't been visited recently (favors covering new nodes)
|
||||||
- **DCA**: Boosts edges where voices change/move (rather than staying)
|
- **DCA Voice Movement**: Boosts edges where voices change/move rather than staying on same pitch
|
||||||
- **Target range**: Boosts edges that move toward the target register
|
- **Target range**: Boosts edges that move toward the target register
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
@ -67,11 +67,11 @@ python -m src.io
|
||||||
# Rising register to 2 octaves
|
# Rising register to 2 octaves
|
||||||
python -m src.io --target-range 2
|
python -m src.io --target-range 2
|
||||||
|
|
||||||
# Heavy target range, no DCA
|
# Heavy target range, no DCA voice movement
|
||||||
python -m src.io --target-range 2 --weight-target-range 10 --weight-dca 0
|
python -m src.io --target-range 2 --weight-target-range 10 --weight-dca-voice-movement 0
|
||||||
|
|
||||||
# Disable Hamiltonian (allow revisiting nodes)
|
# Disable DCA Hamiltonian (allow revisiting nodes freely)
|
||||||
python -m src.io --weight-hamiltonian 0
|
python -m src.io --weight-dca-hamiltonian 0
|
||||||
|
|
||||||
# Enable voice crossing
|
# Enable voice crossing
|
||||||
python -m src.io --voice-crossing
|
python -m src.io --voice-crossing
|
||||||
|
|
@ -87,3 +87,4 @@ Generated files go to `output/`:
|
||||||
- `output_chords.json` - Chord data
|
- `output_chords.json` - Chord data
|
||||||
- `output_chords.txt` - Human-readable chords
|
- `output_chords.txt` - Human-readable chords
|
||||||
- `output_frequencies.txt` - Frequencies in Hz
|
- `output_frequencies.txt` - Frequencies in Hz
|
||||||
|
- `graph_path.json` - Hashes of graph nodes visited (for DCA Hamiltonian analysis)
|
||||||
|
|
|
||||||
|
|
@ -199,13 +199,24 @@ def format_analysis(metrics: dict) -> str:
|
||||||
f"Avg stay count: {metrics['dca_avg_voice_stay']:.2f} steps",
|
f"Avg stay count: {metrics['dca_avg_voice_stay']:.2f} steps",
|
||||||
f"Max stay count: {metrics['dca_max_voice_stay']} steps",
|
f"Max stay count: {metrics['dca_max_voice_stay']} steps",
|
||||||
"",
|
"",
|
||||||
"--- Target Range ---",
|
"--- DCA Hamiltonian ---",
|
||||||
f"Target: {metrics['target_octaves']} octaves ({metrics['target_cents']:.0f} cents)",
|
f"Unique nodes: {metrics['hamiltonian_unique_nodes']}",
|
||||||
f"Start: {metrics['target_start_cents']:.0f} cents",
|
|
||||||
f"End: {metrics['target_end_cents']:.0f} cents",
|
|
||||||
f"Achieved: {metrics['target_actual_cents']:.0f} cents ({metrics['target_percent']:.1f}%)",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if metrics["hamiltonian_coverage"] is not None:
|
||||||
|
lines.append(f"Coverage: {metrics['hamiltonian_coverage']:.1f}%")
|
||||||
|
|
||||||
|
lines.extend(
|
||||||
|
[
|
||||||
|
"",
|
||||||
|
"--- Target Range ---",
|
||||||
|
f"Target: {metrics['target_octaves']} octaves ({metrics['target_cents']:.0f} cents)",
|
||||||
|
f"Start: {metrics['target_start_cents']:.0f} cents",
|
||||||
|
f"End: {metrics['target_end_cents']:.0f} cents",
|
||||||
|
f"Achieved: {metrics['target_actual_cents']:.0f} cents ({metrics['target_percent']:.1f}%)",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
return "\n".join(lines)
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -357,12 +357,13 @@ class PathFinder:
|
||||||
return 1.0
|
return 1.0
|
||||||
|
|
||||||
visit_count = node_visit_counts[destination]
|
visit_count = node_visit_counts[destination]
|
||||||
total_counts = sum(node_visit_counts.values())
|
max_count = max(node_visit_counts.values()) if node_visit_counts else 0
|
||||||
|
|
||||||
if total_counts == 0:
|
if max_count == 0:
|
||||||
return 1.0
|
return 1.0
|
||||||
|
|
||||||
return visit_count / total_counts
|
# Normalize by max squared - gives stronger discrimination
|
||||||
|
return visit_count / (max_count**2)
|
||||||
|
|
||||||
def _factor_dca_voice_movement(
|
def _factor_dca_voice_movement(
|
||||||
self,
|
self,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue