Fix weight values allowing 0 and add normalization floor

This commit is contained in:
Michael Winter 2026-04-18 15:33:49 +02:00
parent a08c944f34
commit a377558f89
2 changed files with 18 additions and 17 deletions

View file

@ -77,6 +77,8 @@ class Path:
source_chord = path_chords[-1] source_chord = path_chords[-1]
candidates = [] candidates = []
threshold = self.weights_config.get("rgr_voice_movement_threshold", 5)
for edge in out_edges: for edge in out_edges:
source_node = edge[0] source_node = edge[0]
destination_node = edge[1] destination_node = edge[1]
@ -174,6 +176,8 @@ class Path:
next_cents = destination_chord.pitches[voice_idx].to_cents() next_cents = destination_chord.pitches[voice_idx].to_cents()
if curr_cents != next_cents: if curr_cents != next_cents:
change_after[voice_idx] += 1 change_after[voice_idx] += 1
if change_after[voice_idx] >= threshold:
change_after[voice_idx] = 0
step = PathStep( step = PathStep(
source_node=source_node, source_node=source_node,
@ -219,7 +223,10 @@ class Path:
total = sum(values) total = sum(values)
if total == 0 or len(set(values)) <= 1: if total == 0 or len(set(values)) <= 1:
return None return None
return [v / total for v in values] min_value = 0.01
adjusted = [max(v, min_value) for v in values]
total_adjusted = sum(adjusted)
return [v / total_adjusted for v in adjusted]
melodic_norm = sum_normalize(melodic_values) melodic_norm = sum_normalize(melodic_values)
contrary_norm = sum_normalize(contrary_values) contrary_norm = sum_normalize(contrary_values)
@ -261,7 +268,7 @@ class Path:
if target_norm: if target_norm:
w *= target_norm[i] * config.get("weight_target_register", 1) w *= target_norm[i] * config.get("weight_target_register", 1)
step.weight = w**16 step.weight = w**8
weights.append(w) weights.append(w)
step.normalized_scores = { step.normalized_scores = {
@ -335,7 +342,7 @@ class Path:
num_moving = num_up + num_down num_moving = num_up + num_down
if num_moving < 2: if num_moving < 2:
return 0.0 return 1.0
ideal_up = num_moving / 2 ideal_up = num_moving / 2
distance = abs(num_up - ideal_up) distance = abs(num_up - ideal_up)
@ -376,7 +383,6 @@ class Path:
candidate_cents = [p.to_cents() for p in destination_chord.pitches] candidate_cents = [p.to_cents() for p in destination_chord.pitches]
sum_changing = 0 sum_changing = 0
sum_all = sum(sustain_counts)
for voice_idx in range(num_voices): for voice_idx in range(num_voices):
if current_cents[voice_idx] != candidate_cents[voice_idx]: if current_cents[voice_idx] != candidate_cents[voice_idx]:
@ -406,8 +412,6 @@ class Path:
if num_voices == 0: if num_voices == 0:
return 1.0 return 1.0
threshold = config.get("rgr_voice_movement_threshold", 5)
current_cents = [p.to_cents() for p in source_chord.pitches] current_cents = [p.to_cents() for p in source_chord.pitches]
candidate_cents = [p.to_cents() for p in destination_chord.pitches] candidate_cents = [p.to_cents() for p in destination_chord.pitches]
@ -415,10 +419,7 @@ class Path:
for voice_idx in range(num_voices): for voice_idx in range(num_voices):
if current_cents[voice_idx] != candidate_cents[voice_idx]: if current_cents[voice_idx] != candidate_cents[voice_idx]:
count = change_counts[voice_idx] sum_repeating += change_counts[voice_idx]
if count >= threshold:
return 0.0
sum_repeating += count
return sum_repeating return sum_repeating

View file

@ -524,14 +524,14 @@
allowVoiceCrossing: document.getElementById('allowVoiceCrossing').checked, allowVoiceCrossing: document.getElementById('allowVoiceCrossing').checked,
disableDirectTuning: document.getElementById('disableDirectTuning').checked, disableDirectTuning: document.getElementById('disableDirectTuning').checked,
uniformSymdiff: document.getElementById('uniformSymdiff').checked, uniformSymdiff: document.getElementById('uniformSymdiff').checked,
weightMelodic: parseFloat(document.getElementById('weightMelodic').value) || 1, weightMelodic: (() => { const v = parseFloat(document.getElementById('weightMelodic').value); return isNaN(v) ? 1 : v; })(),
weightContraryMotion: parseFloat(document.getElementById('weightContraryMotion').value) || 0, weightContraryMotion: (() => { const v = parseFloat(document.getElementById('weightContraryMotion').value); return isNaN(v) ? 0 : v; })(),
weightDcaHamiltonian: parseFloat(document.getElementById('weightDcaHamiltonian').value) || 1, weightDcaHamiltonian: (() => { const v = parseFloat(document.getElementById('weightDcaHamiltonian').value); return isNaN(v) ? 1 : v; })(),
weightDcaVoiceMovement: parseFloat(document.getElementById('weightDcaVoiceMovement').value) || 1, weightDcaVoiceMovement: (() => { const v = parseFloat(document.getElementById('weightDcaVoiceMovement').value); return isNaN(v) ? 1 : v; })(),
weightRgrVoiceMovement: parseFloat(document.getElementById('weightRgrVoiceMovement').value) || 0, weightRgrVoiceMovement: (() => { const v = parseFloat(document.getElementById('weightRgrVoiceMovement').value); return isNaN(v) ? 0 : v; })(),
rgrVoiceMovementThreshold: parseInt(document.getElementById('rgrVoiceMovementThreshold').value) || 5, rgrVoiceMovementThreshold: parseInt(document.getElementById('rgrVoiceMovementThreshold').value) || 5,
weightHarmonicCompactness: parseFloat(document.getElementById('weightHarmonicCompactness').value) || 0, weightHarmonicCompactness: (() => { const v = parseFloat(document.getElementById('weightHarmonicCompactness').value); return isNaN(v) ? 0 : v; })(),
weightTargetRegister: parseFloat(document.getElementById('weightTargetRegister').value) || 1, weightTargetRegister: (() => { const v = parseFloat(document.getElementById('weightTargetRegister').value); return isNaN(v) ? 1 : v; })(),
cacheDir: document.getElementById('cacheDir').value || 'cache', cacheDir: document.getElementById('cacheDir').value || 'cache',
rebuildCache: document.getElementById('rebuildCache').checked, rebuildCache: document.getElementById('rebuildCache').checked,
noCache: document.getElementById('noCache').checked, noCache: document.getElementById('noCache').checked,