Refactor: Rename sustain/last_visited fields for consistency
This commit is contained in:
parent
861d012a95
commit
482f2b0df5
24
src/path.py
24
src/path.py
|
|
@ -23,10 +23,10 @@ class PathStep:
|
||||||
movements: dict[int, int] = field(default_factory=dict)
|
movements: dict[int, int] = field(default_factory=dict)
|
||||||
scores: dict[str, float] = field(default_factory=dict)
|
scores: dict[str, float] = field(default_factory=dict)
|
||||||
weight: float = 0.0 # computed later by _compute_weights
|
weight: float = 0.0 # computed later by _compute_weights
|
||||||
last_visited_count_before: dict | None = None
|
last_visited_counts_before: dict | None = None
|
||||||
last_visited_count_after: dict | None = None
|
last_visited_counts_after: dict | None = None
|
||||||
sustain_count_before: tuple[int, ...] | None = None
|
sustain_counts_before: tuple[int, ...] | None = None
|
||||||
sustain_count_after: tuple[int, ...] | None = None
|
sustain_counts_after: tuple[int, ...] | None = None
|
||||||
|
|
||||||
|
|
||||||
class Path:
|
class Path:
|
||||||
|
|
@ -60,8 +60,8 @@ class Path:
|
||||||
"""Get last visited counts from the last step, or initialize fresh."""
|
"""Get last visited counts from the last step, or initialize fresh."""
|
||||||
if self.steps:
|
if self.steps:
|
||||||
last_step = self.steps[-1]
|
last_step = self.steps[-1]
|
||||||
if last_step.last_visited_count_after is not None:
|
if last_step.last_visited_counts_after is not None:
|
||||||
return dict(last_step.last_visited_count_after)
|
return dict(last_step.last_visited_counts_after)
|
||||||
|
|
||||||
# Initialize fresh: all nodes start at 0 (except initial which we set to 0 explicitly)
|
# Initialize fresh: all nodes start at 0 (except initial which we set to 0 explicitly)
|
||||||
return {node: 0 for node in self._graph_nodes}
|
return {node: 0 for node in self._graph_nodes}
|
||||||
|
|
@ -70,8 +70,8 @@ class Path:
|
||||||
"""Get sustain counts from the last step, or initialize fresh."""
|
"""Get sustain counts from the last step, or initialize fresh."""
|
||||||
if self.steps:
|
if self.steps:
|
||||||
last_step = self.steps[-1]
|
last_step = self.steps[-1]
|
||||||
if last_step.sustain_count_after is not None:
|
if last_step.sustain_counts_after is not None:
|
||||||
return last_step.sustain_count_after
|
return last_step.sustain_counts_after
|
||||||
|
|
||||||
# Initialize fresh: all voices start at 0
|
# Initialize fresh: all voices start at 0
|
||||||
return tuple(0 for _ in range(self._num_voices))
|
return tuple(0 for _ in range(self._num_voices))
|
||||||
|
|
@ -114,10 +114,10 @@ class Path:
|
||||||
sustain_after[voice_idx] = 0
|
sustain_after[voice_idx] = 0
|
||||||
|
|
||||||
# Update step with computed state
|
# Update step with computed state
|
||||||
step.last_visited_count_before = last_visited_before
|
step.last_visited_counts_before = last_visited_before
|
||||||
step.last_visited_count_after = last_visited_after
|
step.last_visited_counts_after = last_visited_after
|
||||||
step.sustain_count_before = sustain_before
|
step.sustain_counts_before = sustain_before
|
||||||
step.sustain_count_after = tuple(sustain_after)
|
step.sustain_counts_after = tuple(sustain_after)
|
||||||
|
|
||||||
self.steps.append(step)
|
self.steps.append(step)
|
||||||
return step
|
return step
|
||||||
|
|
|
||||||
|
|
@ -57,22 +57,22 @@ class PathFinder:
|
||||||
# Derive state from last step (or initialize fresh for step 0)
|
# Derive state from last step (or initialize fresh for step 0)
|
||||||
if path_obj.steps:
|
if path_obj.steps:
|
||||||
last_step = path_obj.steps[-1]
|
last_step = path_obj.steps[-1]
|
||||||
voice_stay_count = last_step.sustain_count_after
|
sustain_counts = last_step.sustain_counts_after
|
||||||
node_visit_counts = last_step.last_visited_count_after
|
last_visited_counts = last_step.last_visited_counts_after
|
||||||
else:
|
else:
|
||||||
# First step - derive from path object's current state
|
# First step - derive from path object's current state
|
||||||
voice_stay_count = tuple(0 for _ in range(len(path_obj._voice_map)))
|
sustain_counts = tuple(0 for _ in range(len(path_obj._voice_map)))
|
||||||
node_visit_counts = {node: 0 for node in set(self.graph.nodes())}
|
last_visited_counts = {node: 0 for node in set(self.graph.nodes())}
|
||||||
|
|
||||||
# Build candidates with raw scores
|
# Build candidates with raw scores
|
||||||
candidates = self._build_candidates(
|
candidates = self._build_candidates(
|
||||||
out_edges,
|
out_edges,
|
||||||
path_obj.output_chords,
|
path_obj.output_chords,
|
||||||
weights_config,
|
weights_config,
|
||||||
voice_stay_count,
|
sustain_counts,
|
||||||
path_obj.graph_chords,
|
path_obj.graph_chords,
|
||||||
path_obj._cumulative_trans,
|
path_obj._cumulative_trans,
|
||||||
node_visit_counts,
|
last_visited_counts,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Compute weights from raw scores
|
# Compute weights from raw scores
|
||||||
|
|
@ -105,10 +105,10 @@ class PathFinder:
|
||||||
out_edges: list,
|
out_edges: list,
|
||||||
path: list["Chord"],
|
path: list["Chord"],
|
||||||
config: dict,
|
config: dict,
|
||||||
voice_stay_count: tuple[int, ...] | None,
|
sustain_counts: tuple[int, ...] | None,
|
||||||
graph_path: list["Chord"] | None,
|
graph_path: list["Chord"] | None,
|
||||||
cumulative_trans: "Pitch | None",
|
cumulative_trans: "Pitch | None",
|
||||||
node_visit_counts: dict | None,
|
last_visited_counts: dict | None,
|
||||||
) -> list[PathStep]:
|
) -> list[PathStep]:
|
||||||
"""Build hypothetical path steps with raw factor scores."""
|
"""Build hypothetical path steps with raw factor scores."""
|
||||||
if not out_edges:
|
if not out_edges:
|
||||||
|
|
@ -151,9 +151,11 @@ class PathFinder:
|
||||||
voice_crossing = self._factor_voice_crossing(edge_data, config)
|
voice_crossing = self._factor_voice_crossing(edge_data, config)
|
||||||
melodic = self._factor_melodic_threshold(edge_data, config)
|
melodic = self._factor_melodic_threshold(edge_data, config)
|
||||||
contrary = self._factor_contrary_motion(edge_data, config)
|
contrary = self._factor_contrary_motion(edge_data, config)
|
||||||
hamiltonian = self._factor_dca_hamiltonian(edge, node_visit_counts, config)
|
hamiltonian = self._factor_dca_hamiltonian(
|
||||||
|
edge, last_visited_counts, config
|
||||||
|
)
|
||||||
dca_voice = self._factor_dca_voice_movement(
|
dca_voice = self._factor_dca_voice_movement(
|
||||||
edge, path, voice_stay_count, config, cumulative_trans
|
edge, path, sustain_counts, config, cumulative_trans
|
||||||
)
|
)
|
||||||
target = self._factor_target_range(edge, path, config, cumulative_trans)
|
target = self._factor_target_range(edge, path, config, cumulative_trans)
|
||||||
|
|
||||||
|
|
@ -373,7 +375,7 @@ class PathFinder:
|
||||||
return max(0.0, 1.0 - (distance / ideal_up))
|
return max(0.0, 1.0 - (distance / ideal_up))
|
||||||
|
|
||||||
def _factor_dca_hamiltonian(
|
def _factor_dca_hamiltonian(
|
||||||
self, edge: tuple, node_visit_counts: dict | None, config: dict
|
self, edge: tuple, last_visited_counts: dict | None, config: dict
|
||||||
) -> float:
|
) -> float:
|
||||||
"""Returns score based on how long since node was last visited.
|
"""Returns score based on how long since node was last visited.
|
||||||
|
|
||||||
|
|
@ -382,11 +384,11 @@ class PathFinder:
|
||||||
if config.get("weight_dca_hamiltonian", 1) == 0:
|
if config.get("weight_dca_hamiltonian", 1) == 0:
|
||||||
return 1.0
|
return 1.0
|
||||||
|
|
||||||
if node_visit_counts is None:
|
if last_visited_counts is None:
|
||||||
return 0.0
|
return 0.0
|
||||||
|
|
||||||
destination = edge[1]
|
destination = edge[1]
|
||||||
visit_count = node_visit_counts.get(destination, 0)
|
visit_count = last_visited_counts.get(destination, 0)
|
||||||
|
|
||||||
# Return the visit count - higher is better (more steps since last visit)
|
# Return the visit count - higher is better (more steps since last visit)
|
||||||
return float(visit_count)
|
return float(visit_count)
|
||||||
|
|
@ -395,27 +397,27 @@ class PathFinder:
|
||||||
self,
|
self,
|
||||||
edge: tuple,
|
edge: tuple,
|
||||||
path: list,
|
path: list,
|
||||||
voice_stay_count: tuple[int, ...] | None,
|
sustain_counts: tuple[int, ...] | None,
|
||||||
config: dict,
|
config: dict,
|
||||||
cumulative_trans: "Pitch | None",
|
cumulative_trans: "Pitch | None",
|
||||||
) -> float:
|
) -> float:
|
||||||
"""Returns probability that voices will change.
|
"""Returns probability that voices will change.
|
||||||
|
|
||||||
DCA = Dissonant Counterpoint Algorithm
|
DCA = Dissonant Counterpoint Algorithm
|
||||||
Probability = (sum of stay_counts for changing voices) / (sum of ALL stay_counts)
|
Probability = (sum of sustain_counts for changing voices) / (sum of ALL sustain_counts)
|
||||||
|
|
||||||
Higher probability = more likely to choose edge where long-staying voices change.
|
Higher probability = more likely to choose edge where long-staying voices change.
|
||||||
"""
|
"""
|
||||||
if config.get("weight_dca_voice_movement", 1) == 0:
|
if config.get("weight_dca_voice_movement", 1) == 0:
|
||||||
return 1.0
|
return 1.0
|
||||||
|
|
||||||
if voice_stay_count is None or len(path) == 0:
|
if sustain_counts is None or len(path) == 0:
|
||||||
return 1.0
|
return 1.0
|
||||||
|
|
||||||
if cumulative_trans is None:
|
if cumulative_trans is None:
|
||||||
return 1.0
|
return 1.0
|
||||||
|
|
||||||
num_voices = len(voice_stay_count)
|
num_voices = len(sustain_counts)
|
||||||
if num_voices == 0:
|
if num_voices == 0:
|
||||||
return 1.0
|
return 1.0
|
||||||
|
|
||||||
|
|
@ -434,14 +436,14 @@ class PathFinder:
|
||||||
candidate_cents = [p.to_cents() for p in candidate_transposed.pitches]
|
candidate_cents = [p.to_cents() for p in candidate_transposed.pitches]
|
||||||
|
|
||||||
sum_changing = 0
|
sum_changing = 0
|
||||||
sum_all = sum(voice_stay_count)
|
sum_all = sum(sustain_counts)
|
||||||
|
|
||||||
if sum_all == 0:
|
if sum_all == 0:
|
||||||
return 1.0
|
return 1.0
|
||||||
|
|
||||||
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]:
|
||||||
sum_changing += voice_stay_count[voice_idx]
|
sum_changing += sustain_counts[voice_idx]
|
||||||
|
|
||||||
return sum_changing / sum_all
|
return sum_changing / sum_all
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue