diff --git a/src/path.py b/src/path.py index 637489c..45f753d 100644 --- a/src/path.py +++ b/src/path.py @@ -23,10 +23,10 @@ class PathStep: movements: dict[int, int] = field(default_factory=dict) scores: dict[str, float] = field(default_factory=dict) weight: float = 0.0 # computed later by _compute_weights - last_visited_count_before: dict | None = None - last_visited_count_after: dict | None = None - sustain_count_before: tuple[int, ...] | None = None - sustain_count_after: tuple[int, ...] | None = None + last_visited_counts_before: dict | None = None + last_visited_counts_after: dict | None = None + sustain_counts_before: tuple[int, ...] | None = None + sustain_counts_after: tuple[int, ...] | None = None class Path: @@ -60,8 +60,8 @@ class Path: """Get last visited counts from the last step, or initialize fresh.""" if self.steps: last_step = self.steps[-1] - if last_step.last_visited_count_after is not None: - return dict(last_step.last_visited_count_after) + if last_step.last_visited_counts_after is not None: + return dict(last_step.last_visited_counts_after) # Initialize fresh: all nodes start at 0 (except initial which we set to 0 explicitly) 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.""" if self.steps: last_step = self.steps[-1] - if last_step.sustain_count_after is not None: - return last_step.sustain_count_after + if last_step.sustain_counts_after is not None: + return last_step.sustain_counts_after # Initialize fresh: all voices start at 0 return tuple(0 for _ in range(self._num_voices)) @@ -114,10 +114,10 @@ class Path: sustain_after[voice_idx] = 0 # Update step with computed state - step.last_visited_count_before = last_visited_before - step.last_visited_count_after = last_visited_after - step.sustain_count_before = sustain_before - step.sustain_count_after = tuple(sustain_after) + step.last_visited_counts_before = last_visited_before + step.last_visited_counts_after = last_visited_after + step.sustain_counts_before = sustain_before + step.sustain_counts_after = tuple(sustain_after) self.steps.append(step) return step diff --git a/src/pathfinder.py b/src/pathfinder.py index 9ec77d8..13ec2e6 100644 --- a/src/pathfinder.py +++ b/src/pathfinder.py @@ -57,22 +57,22 @@ class PathFinder: # Derive state from last step (or initialize fresh for step 0) if path_obj.steps: last_step = path_obj.steps[-1] - voice_stay_count = last_step.sustain_count_after - node_visit_counts = last_step.last_visited_count_after + sustain_counts = last_step.sustain_counts_after + last_visited_counts = last_step.last_visited_counts_after else: # First step - derive from path object's current state - voice_stay_count = tuple(0 for _ in range(len(path_obj._voice_map))) - node_visit_counts = {node: 0 for node in set(self.graph.nodes())} + sustain_counts = tuple(0 for _ in range(len(path_obj._voice_map))) + last_visited_counts = {node: 0 for node in set(self.graph.nodes())} # Build candidates with raw scores candidates = self._build_candidates( out_edges, path_obj.output_chords, weights_config, - voice_stay_count, + sustain_counts, path_obj.graph_chords, path_obj._cumulative_trans, - node_visit_counts, + last_visited_counts, ) # Compute weights from raw scores @@ -105,10 +105,10 @@ class PathFinder: out_edges: list, path: list["Chord"], config: dict, - voice_stay_count: tuple[int, ...] | None, + sustain_counts: tuple[int, ...] | None, graph_path: list["Chord"] | None, cumulative_trans: "Pitch | None", - node_visit_counts: dict | None, + last_visited_counts: dict | None, ) -> list[PathStep]: """Build hypothetical path steps with raw factor scores.""" if not out_edges: @@ -151,9 +151,11 @@ class PathFinder: voice_crossing = self._factor_voice_crossing(edge_data, config) melodic = self._factor_melodic_threshold(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( - 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) @@ -373,7 +375,7 @@ class PathFinder: return max(0.0, 1.0 - (distance / ideal_up)) 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: """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: return 1.0 - if node_visit_counts is None: + if last_visited_counts is None: return 0.0 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 float(visit_count) @@ -395,27 +397,27 @@ class PathFinder: self, edge: tuple, path: list, - voice_stay_count: tuple[int, ...] | None, + sustain_counts: tuple[int, ...] | None, config: dict, cumulative_trans: "Pitch | None", ) -> float: """Returns probability that voices will change. 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. """ if config.get("weight_dca_voice_movement", 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 if cumulative_trans is None: return 1.0 - num_voices = len(voice_stay_count) + num_voices = len(sustain_counts) if num_voices == 0: return 1.0 @@ -434,14 +436,14 @@ class PathFinder: candidate_cents = [p.to_cents() for p in candidate_transposed.pitches] sum_changing = 0 - sum_all = sum(voice_stay_count) + sum_all = sum(sustain_counts) if sum_all == 0: return 1.0 for voice_idx in range(num_voices): 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