use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashMap, HashSet};
use std::hash::{Hash, Hasher};
use thiserror::Error;
use super::config::AdvancedProsodicConfig;
use super::results::{
AdvancedProsodicMetrics, IntonationMetrics, PhonologicalMetrics, ProsodicCoherenceMetrics,
ProsodicComplexityAnalysis, ProsodicFluencyProfile, ProsodicIntegrationMetrics,
ProsodicPatternSynthesis, RhythmMetrics, StressMetrics, TimingMetrics,
};
#[derive(Debug, Clone)]
pub struct AdvancedProsodicAnalyzer {
config: AdvancedProsodicConfig,
integration_engine: ProsodicIntegrationEngine,
coherence_analyzer: ProsodicCoherenceAnalyzer,
complexity_analyzer: ProsodicComplexityAnalyzer,
pattern_synthesizer: ProsodicPatternSynthesizer,
fluency_profiler: ProsodicFluencyProfiler,
cross_analyzer: CrossComponentAnalyzer,
analysis_cache: HashMap<u64, AdvancedProsodicMetrics>,
}
#[derive(Debug, Clone)]
pub struct ProsodicIntegrationEngine {
integration_weights: HashMap<String, f64>,
component_priorities: HashMap<String, f64>,
interaction_matrix: HashMap<(String, String), f64>,
synthesis_algorithms: Vec<SynthesisAlgorithm>,
}
#[derive(Debug, Clone)]
pub struct ProsodicCoherenceAnalyzer {
coherence_metrics: HashMap<String, f64>,
consistency_thresholds: HashMap<String, f64>,
pattern_alignment_weights: HashMap<String, f64>,
temporal_coherence_analyzer: TemporalCoherenceAnalyzer,
}
#[derive(Debug, Clone)]
pub struct ProsodicComplexityAnalyzer {
complexity_models: Vec<ComplexityModel>,
weighting_functions: HashMap<String, Box<dyn Fn(&[f64]) -> f64>>,
hierarchical_weights: HashMap<String, f64>,
emergence_detector: EmergenceDetector,
}
#[derive(Debug, Clone)]
pub struct ProsodicPatternSynthesizer {
synthesis_templates: Vec<PatternSynthesisTemplate>,
pattern_hierarchy: PatternHierarchy,
cross_component_patterns: HashMap<String, CrossComponentPattern>,
pattern_significance_analyzer: PatternSignificanceAnalyzer,
}
#[derive(Debug, Clone)]
pub struct ProsodicFluencyProfiler {
profiling_dimensions: Vec<FluencyDimension>,
fluency_models: HashMap<String, FluencyModel>,
benchmark_comparisons: HashMap<String, BenchmarkProfile>,
fluency_trajectory_analyzer: FluencyTrajectoryAnalyzer,
}
#[derive(Debug, Clone)]
pub struct CrossComponentAnalyzer {
component_correlations: HashMap<(String, String), f64>,
interaction_patterns: Vec<InteractionPattern>,
dependency_graph: DependencyGraph,
emergent_property_detector: EmergentPropertyDetector,
}
#[derive(Debug, Clone)]
pub struct TemporalCoherenceAnalyzer {
temporal_windows: Vec<f64>,
coherence_functions: HashMap<String, Box<dyn Fn(&[f64]) -> f64>>,
stability_metrics: HashMap<String, f64>,
}
#[derive(Debug, Clone)]
pub struct EmergenceDetector {
emergence_patterns: Vec<EmergencePattern>,
threshold_functions: HashMap<String, f64>,
interaction_weights: HashMap<String, f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PatternHierarchy {
pub levels: Vec<HierarchyLevel>,
pub cross_level_connections: HashMap<String, Vec<String>>,
pub level_weights: HashMap<String, f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SynthesisAlgorithm {
pub name: String,
pub algorithm_type: String,
pub input_components: Vec<String>,
pub output_metrics: Vec<String>,
pub weighting_scheme: String,
pub normalization_method: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ComplexityModel {
pub name: String,
pub model_type: String,
pub input_dimensions: Vec<String>,
pub complexity_function: String,
pub scaling_factors: HashMap<String, f64>,
pub interaction_terms: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PatternSynthesisTemplate {
pub name: String,
pub pattern_type: String,
pub required_components: Vec<String>,
pub synthesis_rules: Vec<String>,
pub significance_threshold: f64,
pub contextual_modifiers: HashMap<String, f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CrossComponentPattern {
pub name: String,
pub component_dependencies: Vec<String>,
pub interaction_type: String,
pub pattern_signature: String,
pub detection_algorithm: String,
pub significance_weight: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FluencyDimension {
pub name: String,
pub dimension_type: String,
pub measurement_components: Vec<String>,
pub scoring_algorithm: String,
pub weight_in_profile: f64,
pub benchmark_ranges: HashMap<String, (f64, f64)>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FluencyModel {
pub name: String,
pub model_type: String,
pub input_dimensions: Vec<String>,
pub output_score_range: (f64, f64),
pub calibration_parameters: HashMap<String, f64>,
pub validation_metrics: HashMap<String, f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BenchmarkProfile {
pub profile_name: String,
pub population_type: String,
pub metric_ranges: HashMap<String, (f64, f64)>,
pub percentile_distributions: HashMap<String, Vec<f64>>,
pub reference_standards: HashMap<String, f64>,
}
#[derive(Debug, Clone)]
pub struct FluencyTrajectoryAnalyzer {
trajectory_models: Vec<TrajectoryModel>,
temporal_patterns: HashMap<String, Vec<f64>>,
trend_detection_algorithms: HashMap<String, Box<dyn Fn(&[f64]) -> f64>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InteractionPattern {
pub name: String,
pub interaction_type: String,
pub participating_components: Vec<String>,
pub interaction_strength: f64,
pub temporal_dynamics: String,
pub context_sensitivity: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DependencyGraph {
pub nodes: HashMap<String, DependencyNode>,
pub edges: Vec<DependencyEdge>,
pub graph_metrics: HashMap<String, f64>,
}
#[derive(Debug, Clone)]
pub struct EmergentPropertyDetector {
emergence_indicators: HashMap<String, f64>,
detection_algorithms: HashMap<String, Box<dyn Fn(&HashMap<String, f64>) -> f64>>,
significance_thresholds: HashMap<String, f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HierarchyLevel {
pub level_name: String,
pub level_index: usize,
pub patterns: Vec<String>,
pub abstraction_degree: f64,
pub parent_level: Option<String>,
pub child_levels: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TrajectoryModel {
pub model_name: String,
pub trajectory_type: String,
pub time_scale: String,
pub model_parameters: HashMap<String, f64>,
pub prediction_accuracy: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EmergencePattern {
pub pattern_name: String,
pub emergence_type: String,
pub prerequisite_conditions: Vec<String>,
pub emergence_indicators: Vec<String>,
pub stability_requirements: HashMap<String, f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DependencyNode {
pub node_id: String,
pub component_type: String,
pub influence_weight: f64,
pub connectivity_degree: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DependencyEdge {
pub source_node: String,
pub target_node: String,
pub edge_type: String,
pub dependency_strength: f64,
pub temporal_lag: f64,
}
#[derive(Debug, Clone)]
pub struct PatternSignificanceAnalyzer {
significance_metrics: HashMap<String, f64>,
statistical_tests: HashMap<String, Box<dyn Fn(&[f64]) -> f64>>,
effect_size_calculators: HashMap<String, Box<dyn Fn(&[f64], &[f64]) -> f64>>,
}
#[derive(Debug, Error)]
pub enum AdvancedProsodicAnalysisError {
#[error("Integration failed between components: {components:?}")]
IntegrationError { components: Vec<String> },
#[error("Coherence analysis failed for dimension: {dimension}")]
CoherenceAnalysisError { dimension: String },
#[error("Complexity calculation failed: {calculation}")]
ComplexityCalculationError { calculation: String },
#[error("Pattern synthesis failed for template: {template}")]
PatternSynthesisError { template: String },
#[error("Fluency profiling failed: {profile}")]
FluencyProfilingError { profile: String },
#[error("Cross-component analysis failed: {analysis}")]
CrossComponentAnalysisError { analysis: String },
#[error("Cache operation failed: {operation}")]
CacheError { operation: String },
}
impl AdvancedProsodicAnalyzer {
pub fn new(config: AdvancedProsodicConfig) -> Self {
let integration_engine = ProsodicIntegrationEngine::new(&config);
let coherence_analyzer = ProsodicCoherenceAnalyzer::new(&config);
let complexity_analyzer = ProsodicComplexityAnalyzer::new(&config);
let pattern_synthesizer = ProsodicPatternSynthesizer::new(&config);
let fluency_profiler = ProsodicFluencyProfiler::new(&config);
let cross_analyzer = CrossComponentAnalyzer::new(&config);
Self {
config,
integration_engine,
coherence_analyzer,
complexity_analyzer,
pattern_synthesizer,
fluency_profiler,
cross_analyzer,
analysis_cache: HashMap::new(),
}
}
pub fn analyze(
&mut self,
rhythm_metrics: &RhythmMetrics,
stress_metrics: &StressMetrics,
intonation_metrics: &IntonationMetrics,
timing_metrics: &TimingMetrics,
phonological_metrics: &PhonologicalMetrics,
) -> Result<AdvancedProsodicMetrics, AdvancedProsodicAnalysisError> {
let cache_key = self.generate_cache_key(
rhythm_metrics,
stress_metrics,
intonation_metrics,
timing_metrics,
phonological_metrics,
);
if let Some(cached_result) = self.analysis_cache.get(&cache_key) {
return Ok(cached_result.clone());
}
let integration_metrics = self.analyze_component_integration(
rhythm_metrics,
stress_metrics,
intonation_metrics,
timing_metrics,
phonological_metrics,
)?;
let coherence_metrics = self.analyze_prosodic_coherence(
rhythm_metrics,
stress_metrics,
intonation_metrics,
timing_metrics,
phonological_metrics,
)?;
let complexity_analysis = self.analyze_prosodic_complexity(
rhythm_metrics,
stress_metrics,
intonation_metrics,
timing_metrics,
phonological_metrics,
)?;
let pattern_synthesis = self.synthesize_prosodic_patterns(
rhythm_metrics,
stress_metrics,
intonation_metrics,
timing_metrics,
phonological_metrics,
)?;
let fluency_profile = self.generate_fluency_profile(
&integration_metrics,
&coherence_metrics,
&complexity_analysis,
&pattern_synthesis,
)?;
let cross_component_insights = self.analyze_cross_components(
rhythm_metrics,
stress_metrics,
intonation_metrics,
timing_metrics,
phonological_metrics,
)?;
let overall_sophistication = self.calculate_overall_sophistication(
&integration_metrics,
&complexity_analysis,
&pattern_synthesis,
);
let fluency_impact_assessment = self.assess_fluency_impact(
&fluency_profile,
&coherence_metrics,
&cross_component_insights,
);
let metrics = AdvancedProsodicMetrics {
integration_metrics,
coherence_metrics,
complexity_analysis,
pattern_synthesis,
fluency_profile,
cross_component_insights,
overall_sophistication,
fluency_impact_assessment,
analysis_confidence: self.calculate_analysis_confidence(),
};
if self.config.enable_caching {
self.analysis_cache.insert(cache_key, metrics.clone());
}
Ok(metrics)
}
fn analyze_component_integration(
&mut self,
rhythm_metrics: &RhythmMetrics,
stress_metrics: &StressMetrics,
intonation_metrics: &IntonationMetrics,
timing_metrics: &TimingMetrics,
phonological_metrics: &PhonologicalMetrics,
) -> Result<ProsodicIntegrationMetrics, AdvancedProsodicAnalysisError> {
self.integration_engine.integrate_components(
rhythm_metrics,
stress_metrics,
intonation_metrics,
timing_metrics,
phonological_metrics,
)
}
fn analyze_prosodic_coherence(
&mut self,
rhythm_metrics: &RhythmMetrics,
stress_metrics: &StressMetrics,
intonation_metrics: &IntonationMetrics,
timing_metrics: &TimingMetrics,
phonological_metrics: &PhonologicalMetrics,
) -> Result<ProsodicCoherenceMetrics, AdvancedProsodicAnalysisError> {
self.coherence_analyzer.analyze_coherence(
rhythm_metrics,
stress_metrics,
intonation_metrics,
timing_metrics,
phonological_metrics,
)
}
fn analyze_prosodic_complexity(
&mut self,
rhythm_metrics: &RhythmMetrics,
stress_metrics: &StressMetrics,
intonation_metrics: &IntonationMetrics,
timing_metrics: &TimingMetrics,
phonological_metrics: &PhonologicalMetrics,
) -> Result<ProsodicComplexityAnalysis, AdvancedProsodicAnalysisError> {
self.complexity_analyzer.analyze_complexity(
rhythm_metrics,
stress_metrics,
intonation_metrics,
timing_metrics,
phonological_metrics,
)
}
fn synthesize_prosodic_patterns(
&mut self,
rhythm_metrics: &RhythmMetrics,
stress_metrics: &StressMetrics,
intonation_metrics: &IntonationMetrics,
timing_metrics: &TimingMetrics,
phonological_metrics: &PhonologicalMetrics,
) -> Result<ProsodicPatternSynthesis, AdvancedProsodicAnalysisError> {
self.pattern_synthesizer.synthesize_patterns(
rhythm_metrics,
stress_metrics,
intonation_metrics,
timing_metrics,
phonological_metrics,
)
}
fn generate_fluency_profile(
&mut self,
integration_metrics: &ProsodicIntegrationMetrics,
coherence_metrics: &ProsodicCoherenceMetrics,
complexity_analysis: &ProsodicComplexityAnalysis,
pattern_synthesis: &ProsodicPatternSynthesis,
) -> Result<ProsodicFluencyProfile, AdvancedProsodicAnalysisError> {
self.fluency_profiler.generate_profile(
integration_metrics,
coherence_metrics,
complexity_analysis,
pattern_synthesis,
)
}
fn analyze_cross_components(
&mut self,
rhythm_metrics: &RhythmMetrics,
stress_metrics: &StressMetrics,
intonation_metrics: &IntonationMetrics,
timing_metrics: &TimingMetrics,
phonological_metrics: &PhonologicalMetrics,
) -> Result<HashMap<String, f64>, AdvancedProsodicAnalysisError> {
self.cross_analyzer.analyze_cross_components(
rhythm_metrics,
stress_metrics,
intonation_metrics,
timing_metrics,
phonological_metrics,
)
}
fn calculate_overall_sophistication(
&self,
integration_metrics: &ProsodicIntegrationMetrics,
complexity_analysis: &ProsodicComplexityAnalysis,
pattern_synthesis: &ProsodicPatternSynthesis,
) -> f64 {
let weights = &self.config.sophistication_weights;
weights.integration_weight * integration_metrics.overall_integration_score
+ weights.complexity_weight * complexity_analysis.overall_complexity_score
+ weights.pattern_weight * pattern_synthesis.pattern_sophistication_score
}
fn assess_fluency_impact(
&self,
fluency_profile: &ProsodicFluencyProfile,
coherence_metrics: &ProsodicCoherenceMetrics,
cross_component_insights: &HashMap<String, f64>,
) -> f64 {
let base_fluency = fluency_profile.overall_fluency_score;
let coherence_modifier = coherence_metrics.overall_coherence_score - 0.5;
let emergent_modifier = cross_component_insights
.get("emergent_fluency_boost")
.unwrap_or(&0.0);
(base_fluency + coherence_modifier * 0.2 + emergent_modifier * 0.3)
.max(0.0)
.min(1.0)
}
fn calculate_analysis_confidence(&self) -> f64 {
let base_confidence = 0.88;
let sophistication_bonus = if self.config.high_sophistication_analysis {
0.08
} else {
0.0
};
let cache_penalty = if self.analysis_cache.len() > 2000 {
-0.03
} else {
0.0
};
(base_confidence + sophistication_bonus + cache_penalty)
.max(0.0)
.min(1.0)
}
fn generate_cache_key(
&self,
rhythm_metrics: &RhythmMetrics,
stress_metrics: &StressMetrics,
intonation_metrics: &IntonationMetrics,
timing_metrics: &TimingMetrics,
phonological_metrics: &PhonologicalMetrics,
) -> u64 {
let mut hasher = std::collections::hash_map::DefaultHasher::new();
rhythm_metrics
.beat_strength_variability
.to_bits()
.hash(&mut hasher);
stress_metrics
.stress_prominence_score
.to_bits()
.hash(&mut hasher);
intonation_metrics.pitch_range.to_bits().hash(&mut hasher);
timing_metrics.speech_rate.to_bits().hash(&mut hasher);
phonological_metrics
.complexity_score
.to_bits()
.hash(&mut hasher);
self.config.integration_algorithm.hash(&mut hasher);
hasher.finish()
}
pub fn update_config(&mut self, new_config: AdvancedProsodicConfig) {
self.config = new_config;
self.integration_engine.update_config(&self.config);
self.coherence_analyzer.update_config(&self.config);
self.complexity_analyzer.update_config(&self.config);
self.pattern_synthesizer.update_config(&self.config);
self.fluency_profiler.update_config(&self.config);
self.cross_analyzer.update_config(&self.config);
if self.config.clear_cache_on_config_change {
self.analysis_cache.clear();
}
}
pub fn clear_cache(&mut self) {
self.analysis_cache.clear();
}
pub fn get_cache_stats(&self) -> (usize, usize) {
(self.analysis_cache.len(), self.analysis_cache.capacity())
}
}
impl ProsodicIntegrationEngine {
fn new(config: &AdvancedProsodicConfig) -> Self {
Self {
integration_weights: Self::create_integration_weights(),
component_priorities: Self::create_component_priorities(),
interaction_matrix: Self::create_interaction_matrix(),
synthesis_algorithms: Self::create_synthesis_algorithms(),
}
}
fn integrate_components(
&self,
rhythm_metrics: &RhythmMetrics,
stress_metrics: &StressMetrics,
intonation_metrics: &IntonationMetrics,
timing_metrics: &TimingMetrics,
phonological_metrics: &PhonologicalMetrics,
) -> Result<ProsodicIntegrationMetrics, AdvancedProsodicAnalysisError> {
let rhythm_integration =
self.calculate_component_integration_score("rhythm", rhythm_metrics.beat_consistency);
let stress_integration =
self.calculate_component_integration_score("stress", stress_metrics.stress_consistency);
let intonation_integration = self.calculate_component_integration_score(
"intonation",
intonation_metrics.contour_smoothness,
);
let timing_integration =
self.calculate_component_integration_score("timing", timing_metrics.tempo_consistency);
let phonological_integration = self.calculate_component_integration_score(
"phonological",
1.0 - phonological_metrics
.phonotactic_constraints
.violation_density,
);
let component_interactions = self.calculate_component_interactions(
rhythm_metrics,
stress_metrics,
intonation_metrics,
timing_metrics,
phonological_metrics,
);
let overall_integration_score = self.calculate_overall_integration_score(
rhythm_integration,
stress_integration,
intonation_integration,
timing_integration,
phonological_integration,
&component_interactions,
);
let integration_patterns = self.detect_integration_patterns(&component_interactions);
let integration_stability = self.calculate_integration_stability(&component_interactions);
Ok(ProsodicIntegrationMetrics {
rhythm_integration_score: rhythm_integration,
stress_integration_score: stress_integration,
intonation_integration_score: intonation_integration,
timing_integration_score: timing_integration,
phonological_integration_score: phonological_integration,
component_interactions,
overall_integration_score,
integration_patterns,
integration_stability,
cross_component_synergy: self.calculate_synergy_score(&component_interactions),
})
}
fn calculate_component_integration_score(&self, component: &str, base_score: f64) -> f64 {
let weight = self.integration_weights.get(component).unwrap_or(&1.0);
let priority = self.component_priorities.get(component).unwrap_or(&1.0);
base_score * weight * priority
}
fn calculate_component_interactions(
&self,
rhythm_metrics: &RhythmMetrics,
stress_metrics: &StressMetrics,
intonation_metrics: &IntonationMetrics,
timing_metrics: &TimingMetrics,
phonological_metrics: &PhonologicalMetrics,
) -> HashMap<String, f64> {
let mut interactions = HashMap::new();
let rhythm_stress = self.calculate_pairwise_interaction(
rhythm_metrics.beat_consistency,
stress_metrics.stress_consistency,
"rhythm-stress",
);
interactions.insert("rhythm-stress".to_string(), rhythm_stress);
let rhythm_intonation = self.calculate_pairwise_interaction(
rhythm_metrics.beat_consistency,
intonation_metrics.contour_smoothness,
"rhythm-intonation",
);
interactions.insert("rhythm-intonation".to_string(), rhythm_intonation);
let stress_intonation = self.calculate_pairwise_interaction(
stress_metrics.stress_prominence_score,
intonation_metrics.pitch_range,
"stress-intonation",
);
interactions.insert("stress-intonation".to_string(), stress_intonation);
let timing_phonological = self.calculate_pairwise_interaction(
timing_metrics.speech_rate,
phonological_metrics.complexity_score,
"timing-phonological",
);
interactions.insert("timing-phonological".to_string(), timing_phonological);
let global_coherence = self.calculate_global_coherence(
rhythm_metrics,
stress_metrics,
intonation_metrics,
timing_metrics,
phonological_metrics,
);
interactions.insert("global-coherence".to_string(), global_coherence);
interactions
}
fn calculate_pairwise_interaction(
&self,
score1: f64,
score2: f64,
interaction_type: &str,
) -> f64 {
let interaction_weight = self
.interaction_matrix
.get(&(interaction_type.to_string(), interaction_type.to_string()))
.unwrap_or(&1.0);
let correlation = (score1 * score2).sqrt();
let mutual_information = self.calculate_mutual_information(score1, score2);
(correlation + mutual_information) * 0.5 * interaction_weight
}
fn calculate_mutual_information(&self, x: f64, y: f64) -> f64 {
let joint_entropy = -(x * y * (x * y).ln() + (1.0 - x * y) * (1.0 - x * y).ln());
let marginal_entropy_x = -(x * x.ln() + (1.0 - x) * (1.0 - x).ln());
let marginal_entropy_y = -(y * y.ln() + (1.0 - y) * (1.0 - y).ln());
marginal_entropy_x + marginal_entropy_y - joint_entropy
}
fn calculate_global_coherence(
&self,
rhythm_metrics: &RhythmMetrics,
stress_metrics: &StressMetrics,
intonation_metrics: &IntonationMetrics,
timing_metrics: &TimingMetrics,
phonological_metrics: &PhonologicalMetrics,
) -> f64 {
let scores = vec![
rhythm_metrics.beat_consistency,
stress_metrics.stress_consistency,
intonation_metrics.contour_smoothness,
timing_metrics.tempo_consistency,
1.0 - phonological_metrics
.phonotactic_constraints
.violation_density,
];
let mean = scores.iter().sum::<f64>() / scores.len() as f64;
let variance =
scores.iter().map(|&x| (x - mean).powi(2)).sum::<f64>() / scores.len() as f64;
let std_dev = variance.sqrt();
1.0 - (std_dev / mean.max(0.001)) }
fn calculate_overall_integration_score(
&self,
rhythm: f64,
stress: f64,
intonation: f64,
timing: f64,
phonological: f64,
interactions: &HashMap<String, f64>,
) -> f64 {
let component_average = (rhythm + stress + intonation + timing + phonological) / 5.0;
let interaction_bonus = interactions.values().sum::<f64>() / interactions.len() as f64;
(component_average * 0.7 + interaction_bonus * 0.3)
.max(0.0)
.min(1.0)
}
fn detect_integration_patterns(&self, interactions: &HashMap<String, f64>) -> Vec<String> {
let mut patterns = Vec::new();
if interactions.values().all(|&v| v > 0.7) {
patterns.push("high-integration".to_string());
}
if interactions.values().filter(|&&v| v > 0.8).count() >= 2
&& interactions.values().filter(|&&v| v < 0.4).count() >= 1
{
patterns.push("selective-integration".to_string());
}
if let Some(&global_coherence) = interactions.get("global-coherence") {
if global_coherence > 0.85 {
patterns.push("global-coherence".to_string());
}
}
patterns
}
fn calculate_integration_stability(&self, interactions: &HashMap<String, f64>) -> f64 {
let values: Vec<f64> = interactions.values().cloned().collect();
let mean = values.iter().sum::<f64>() / values.len() as f64;
let variance =
values.iter().map(|&x| (x - mean).powi(2)).sum::<f64>() / values.len() as f64;
1.0 - variance.sqrt() }
fn calculate_synergy_score(&self, interactions: &HashMap<String, f64>) -> f64 {
let interaction_sum = interactions.values().sum::<f64>();
let expected_sum = interactions.len() as f64 * 0.5;
(interaction_sum / expected_sum).min(2.0).max(0.0)
}
fn create_integration_weights() -> HashMap<String, f64> {
let mut weights = HashMap::new();
weights.insert("rhythm".to_string(), 1.0);
weights.insert("stress".to_string(), 1.1);
weights.insert("intonation".to_string(), 1.2);
weights.insert("timing".to_string(), 0.9);
weights.insert("phonological".to_string(), 0.8);
weights
}
fn create_component_priorities() -> HashMap<String, f64> {
let mut priorities = HashMap::new();
priorities.insert("rhythm".to_string(), 1.0);
priorities.insert("stress".to_string(), 1.1);
priorities.insert("intonation".to_string(), 1.2);
priorities.insert("timing".to_string(), 0.95);
priorities.insert("phonological".to_string(), 0.85);
priorities
}
fn create_interaction_matrix() -> HashMap<(String, String), f64> {
let mut matrix = HashMap::new();
matrix.insert(
("rhythm-stress".to_string(), "rhythm-stress".to_string()),
1.2,
);
matrix.insert(
(
"rhythm-intonation".to_string(),
"rhythm-intonation".to_string(),
),
1.1,
);
matrix.insert(
(
"stress-intonation".to_string(),
"stress-intonation".to_string(),
),
1.3,
);
matrix.insert(
(
"timing-phonological".to_string(),
"timing-phonological".to_string(),
),
1.0,
);
matrix
}
fn create_synthesis_algorithms() -> Vec<SynthesisAlgorithm> {
vec![
SynthesisAlgorithm {
name: "Weighted Integration".to_string(),
algorithm_type: "linear_combination".to_string(),
input_components: vec![
"rhythm".to_string(),
"stress".to_string(),
"intonation".to_string(),
],
output_metrics: vec!["integration_score".to_string()],
weighting_scheme: "priority_based".to_string(),
normalization_method: "min_max".to_string(),
},
SynthesisAlgorithm {
name: "Nonlinear Synthesis".to_string(),
algorithm_type: "nonlinear_combination".to_string(),
input_components: vec!["timing".to_string(), "phonological".to_string()],
output_metrics: vec!["complexity_integration".to_string()],
weighting_scheme: "adaptive".to_string(),
normalization_method: "z_score".to_string(),
},
]
}
fn update_config(&mut self, config: &AdvancedProsodicConfig) {
if config.adaptive_integration_weights {
for (component, weight) in &mut self.integration_weights {
*weight *= 1.0 + config.adaptation_rate;
}
}
}
}
impl ProsodicCoherenceAnalyzer {
fn new(config: &AdvancedProsodicConfig) -> Self {
Self {
coherence_metrics: Self::create_coherence_metrics(),
consistency_thresholds: Self::create_consistency_thresholds(),
pattern_alignment_weights: Self::create_pattern_alignment_weights(),
temporal_coherence_analyzer: TemporalCoherenceAnalyzer::new(config),
}
}
fn analyze_coherence(
&self,
rhythm_metrics: &RhythmMetrics,
stress_metrics: &StressMetrics,
intonation_metrics: &IntonationMetrics,
timing_metrics: &TimingMetrics,
phonological_metrics: &PhonologicalMetrics,
) -> Result<ProsodicCoherenceMetrics, AdvancedProsodicAnalysisError> {
let temporal_coherence = self.temporal_coherence_analyzer.analyze_temporal_coherence(
rhythm_metrics,
stress_metrics,
intonation_metrics,
timing_metrics,
);
let structural_coherence = self.calculate_structural_coherence(
rhythm_metrics,
stress_metrics,
intonation_metrics,
phonological_metrics,
);
let perceptual_coherence = self.calculate_perceptual_coherence(
intonation_metrics,
timing_metrics,
phonological_metrics,
);
let overall_coherence_score =
(temporal_coherence + structural_coherence + perceptual_coherence) / 3.0;
Ok(ProsodicCoherenceMetrics {
temporal_coherence,
structural_coherence,
perceptual_coherence,
overall_coherence_score,
coherence_stability: self.calculate_coherence_stability(&[
temporal_coherence,
structural_coherence,
perceptual_coherence,
]),
pattern_alignment_score: self
.calculate_pattern_alignment(rhythm_metrics, stress_metrics),
consistency_violations: self.detect_consistency_violations(&[
temporal_coherence,
structural_coherence,
perceptual_coherence,
]),
})
}
fn calculate_structural_coherence(
&self,
rhythm_metrics: &RhythmMetrics,
stress_metrics: &StressMetrics,
intonation_metrics: &IntonationMetrics,
phonological_metrics: &PhonologicalMetrics,
) -> f64 {
let rhythm_structure = rhythm_metrics.beat_consistency;
let stress_structure = stress_metrics.stress_consistency;
let intonation_structure = intonation_metrics.contour_smoothness;
let phonological_structure = 1.0
- phonological_metrics
.phonotactic_constraints
.violation_density;
(rhythm_structure + stress_structure + intonation_structure + phonological_structure) / 4.0
}
fn calculate_perceptual_coherence(
&self,
intonation_metrics: &IntonationMetrics,
timing_metrics: &TimingMetrics,
phonological_metrics: &PhonologicalMetrics,
) -> f64 {
let pitch_coherence = intonation_metrics.contour_smoothness;
let timing_coherence = timing_metrics.tempo_consistency;
let phonological_coherence = 1.0 - phonological_metrics.complexity_score / 10.0;
(pitch_coherence * 0.4 + timing_coherence * 0.4 + phonological_coherence * 0.2)
.max(0.0)
.min(1.0)
}
fn calculate_coherence_stability(&self, coherence_scores: &[f64]) -> f64 {
let mean = coherence_scores.iter().sum::<f64>() / coherence_scores.len() as f64;
let variance = coherence_scores
.iter()
.map(|&x| (x - mean).powi(2))
.sum::<f64>()
/ coherence_scores.len() as f64;
1.0 - variance.sqrt() }
fn calculate_pattern_alignment(
&self,
rhythm_metrics: &RhythmMetrics,
stress_metrics: &StressMetrics,
) -> f64 {
let rhythm_regularity = rhythm_metrics.beat_consistency;
let stress_regularity = stress_metrics.stress_consistency;
(rhythm_regularity * stress_regularity).sqrt()
}
fn detect_consistency_violations(&self, coherence_scores: &[f64]) -> Vec<String> {
let mut violations = Vec::new();
for (i, &score) in coherence_scores.iter().enumerate() {
let threshold = match i {
0 => self.consistency_thresholds.get("temporal").unwrap_or(&0.6),
1 => self
.consistency_thresholds
.get("structural")
.unwrap_or(&0.65),
2 => self
.consistency_thresholds
.get("perceptual")
.unwrap_or(&0.7),
_ => &0.6,
};
if score < *threshold {
violations.push(format!("coherence_violation_{}", i));
}
}
violations
}
fn create_coherence_metrics() -> HashMap<String, f64> {
let mut metrics = HashMap::new();
metrics.insert("temporal_weight".to_string(), 1.0);
metrics.insert("structural_weight".to_string(), 1.1);
metrics.insert("perceptual_weight".to_string(), 1.2);
metrics
}
fn create_consistency_thresholds() -> HashMap<String, f64> {
let mut thresholds = HashMap::new();
thresholds.insert("temporal".to_string(), 0.6);
thresholds.insert("structural".to_string(), 0.65);
thresholds.insert("perceptual".to_string(), 0.7);
thresholds
}
fn create_pattern_alignment_weights() -> HashMap<String, f64> {
let mut weights = HashMap::new();
weights.insert("rhythm_stress_alignment".to_string(), 1.2);
weights.insert("intonation_timing_alignment".to_string(), 1.1);
weights.insert("phonological_prosodic_alignment".to_string(), 1.0);
weights
}
fn update_config(&mut self, config: &AdvancedProsodicConfig) {
if config.adaptive_coherence_thresholds {
for (_, threshold) in &mut self.consistency_thresholds {
*threshold *= 1.0 + config.adaptation_rate * 0.5;
}
}
}
}
impl TemporalCoherenceAnalyzer {
fn new(config: &AdvancedProsodicConfig) -> Self {
Self {
temporal_windows: vec![1.0, 2.0, 5.0, 10.0], coherence_functions: HashMap::new(), stability_metrics: Self::create_stability_metrics(),
}
}
fn analyze_temporal_coherence(
&self,
rhythm_metrics: &RhythmMetrics,
stress_metrics: &StressMetrics,
intonation_metrics: &IntonationMetrics,
timing_metrics: &TimingMetrics,
) -> f64 {
let short_term_coherence =
self.calculate_short_term_coherence(rhythm_metrics, timing_metrics);
let medium_term_coherence =
self.calculate_medium_term_coherence(stress_metrics, intonation_metrics);
let long_term_coherence =
self.calculate_long_term_coherence(rhythm_metrics, stress_metrics, intonation_metrics);
(short_term_coherence + medium_term_coherence + long_term_coherence) / 3.0
}
fn calculate_short_term_coherence(
&self,
rhythm_metrics: &RhythmMetrics,
timing_metrics: &TimingMetrics,
) -> f64 {
rhythm_metrics.beat_consistency * timing_metrics.tempo_consistency
}
fn calculate_medium_term_coherence(
&self,
stress_metrics: &StressMetrics,
intonation_metrics: &IntonationMetrics,
) -> f64 {
let stress_phrase_consistency = stress_metrics.stress_consistency;
let intonation_phrase_consistency = intonation_metrics.contour_smoothness;
(stress_phrase_consistency + intonation_phrase_consistency) / 2.0
}
fn calculate_long_term_coherence(
&self,
rhythm_metrics: &RhythmMetrics,
stress_metrics: &StressMetrics,
intonation_metrics: &IntonationMetrics,
) -> f64 {
let rhythm_discourse = rhythm_metrics.beat_consistency;
let stress_discourse = stress_metrics.stress_consistency;
let intonation_discourse = intonation_metrics.contour_smoothness;
(rhythm_discourse + stress_discourse + intonation_discourse) / 3.0
}
fn create_stability_metrics() -> HashMap<String, f64> {
let mut metrics = HashMap::new();
metrics.insert("short_term_stability".to_string(), 0.8);
metrics.insert("medium_term_stability".to_string(), 0.75);
metrics.insert("long_term_stability".to_string(), 0.7);
metrics
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::metrics::fluency::prosodic::results::*;
#[test]
fn test_advanced_prosodic_analyzer_creation() {
let config = AdvancedProsodicConfig::default();
let analyzer = AdvancedProsodicAnalyzer::new(config);
assert_eq!(analyzer.analysis_cache.len(), 0);
}
#[test]
fn test_integration_engine_creation() {
let config = AdvancedProsodicConfig::default();
let engine = ProsodicIntegrationEngine::new(&config);
assert!(!engine.integration_weights.is_empty());
assert!(!engine.component_priorities.is_empty());
}
#[test]
fn test_coherence_analyzer_creation() {
let config = AdvancedProsodicConfig::default();
let analyzer = ProsodicCoherenceAnalyzer::new(&config);
assert!(!analyzer.coherence_metrics.is_empty());
assert!(!analyzer.consistency_thresholds.is_empty());
}
#[test]
fn test_temporal_coherence_analyzer() {
let config = AdvancedProsodicConfig::default();
let analyzer = TemporalCoherenceAnalyzer::new(&config);
assert!(!analyzer.temporal_windows.is_empty());
assert_eq!(analyzer.temporal_windows.len(), 4);
}
}