use super::config::AdvancedSemanticConfig;
use super::results::{
AdvancedCoherenceMetrics, AdvancedSemanticMetrics, ConceptualDimensions, SemanticComplexity,
SemanticDynamics, SemanticEvolution, SemanticInnovation, VectorSemanticAnalysis,
};
use crate::error::TextAnalysisError;
use serde::{Deserialize, Serialize};
use std::collections::hash_map::DefaultHasher;
use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
use std::hash::{Hash, Hasher};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum AdvancedAnalysisError {
#[error("Invalid advanced analysis configuration: {0}")]
ConfigError(String),
#[error("Advanced calculation failed: {0}")]
CalculationError(String),
#[error("Advanced semantic analysis error: {0}")]
AnalysisError(String),
#[error("Vector analysis error: {0}")]
VectorError(String),
}
pub type AdvancedResult<T> = Result<T, AdvancedAnalysisError>;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SemanticVector {
pub dimensions: Vec<f64>,
pub dimension_labels: Vec<String>,
pub confidence: f64,
pub source_context: String,
}
impl SemanticVector {
pub fn new(dimensions: Vec<f64>, labels: Vec<String>) -> Self {
let confidence = if dimensions.is_empty() {
0.0
} else {
dimensions.iter().map(|x| x.abs()).sum::<f64>() / dimensions.len() as f64
};
Self {
dimensions,
dimension_labels: labels,
confidence,
source_context: String::new(),
}
}
pub fn cosine_similarity(&self, other: &SemanticVector) -> f64 {
if self.dimensions.len() != other.dimensions.len() {
return 0.0;
}
let dot_product: f64 = self
.dimensions
.iter()
.zip(&other.dimensions)
.map(|(a, b)| a * b)
.sum();
let norm_a: f64 = self.dimensions.iter().map(|x| x * x).sum::<f64>().sqrt();
let norm_b: f64 = other.dimensions.iter().map(|x| x * x).sum::<f64>().sqrt();
if norm_a == 0.0 || norm_b == 0.0 {
0.0
} else {
dot_product / (norm_a * norm_b)
}
}
}
#[derive(Debug, Clone)]
pub struct AdvancedSemanticAnalyzer {
config: AdvancedSemanticConfig,
semantic_vectors: HashMap<String, SemanticVector>,
evolution_tracker: VecDeque<SemanticEvolution>,
complexity_cache: HashMap<u64, SemanticComplexity>,
dynamics_history: BTreeMap<usize, SemanticDynamics>,
innovation_patterns: Vec<SemanticInnovation>,
conceptual_space: ConceptualDimensions,
coherence_models: HashMap<String, AdvancedCoherenceMetrics>,
analysis_cache: HashMap<u64, AdvancedSemanticMetrics>,
}
impl AdvancedSemanticAnalyzer {
pub fn new(config: AdvancedSemanticConfig) -> AdvancedResult<Self> {
Self::validate_config(&config)?;
Ok(Self {
config,
semantic_vectors: HashMap::new(),
evolution_tracker: VecDeque::new(),
complexity_cache: HashMap::new(),
dynamics_history: BTreeMap::new(),
innovation_patterns: Vec::new(),
conceptual_space: ConceptualDimensions::new(),
coherence_models: HashMap::new(),
analysis_cache: HashMap::new(),
})
}
pub fn analyze_advanced_semantics(
&mut self,
text: &str,
context_data: Option<&HashMap<String, String>>,
) -> AdvancedResult<AdvancedSemanticMetrics> {
let cache_key = self.generate_cache_key(text, context_data);
if let Some(cached) = self.analysis_cache.get(&cache_key) {
return Ok(cached.clone());
}
let sentences = self.extract_sentences(text);
let mut metrics = AdvancedSemanticMetrics::default();
self.build_semantic_vectors(&sentences)?;
metrics.overall_advanced_score = self.calculate_overall_advanced_score()?;
metrics.semantic_complexity = self.analyze_semantic_complexity(&sentences)?;
metrics.conceptual_dimensions = self.analyze_conceptual_dimensions(&sentences)?;
metrics.semantic_dynamics = self.analyze_semantic_dynamics(&sentences)?;
if self.config.enable_vector_analysis {
metrics.vector_analysis = self.perform_vector_analysis(&sentences)?;
metrics.semantic_clustering = self.analyze_semantic_clustering()?;
metrics.dimensional_coherence = self.measure_dimensional_coherence()?;
}
if self.config.track_semantic_evolution {
metrics.evolution_patterns = self.track_semantic_evolution(&sentences)?;
metrics.semantic_stability = self.measure_semantic_stability(&sentences)?;
metrics.innovation_detection = self.detect_semantic_innovation(&sentences)?;
}
if self.config.advanced_coherence_modeling {
metrics.advanced_coherence = self.model_advanced_coherence(&sentences)?;
metrics.multi_scale_coherence = self.analyze_multi_scale_coherence(&sentences)?;
metrics.coherence_prediction = self.predict_coherence_trends(&sentences)?;
}
if self.config.analyze_semantic_complexity {
metrics.complexity_metrics = self.calculate_complexity_metrics(&sentences)?;
metrics.entropy_measures = self.calculate_semantic_entropy(&sentences)?;
metrics.information_density = self.analyze_information_density(&sentences)?;
}
self.analysis_cache.insert(cache_key, metrics.clone());
Ok(metrics)
}
fn build_semantic_vectors(&mut self, sentences: &[String]) -> AdvancedResult<()> {
for (i, sentence) in sentences.iter().enumerate() {
let features = self.extract_semantic_features(sentence)?;
let vector = self.create_semantic_vector(&features, sentence)?;
let key = format!("sentence_{}", i);
self.semantic_vectors.insert(key, vector);
}
self.build_concept_vectors(sentences)?;
self.build_entity_vectors(sentences)?;
Ok(())
}
fn calculate_overall_advanced_score(&self) -> AdvancedResult<f64> {
let mut score_components = Vec::new();
if !self.semantic_vectors.is_empty() {
let vector_coherence = self.calculate_vector_coherence()?;
score_components.push(vector_coherence * self.config.vector_weight);
}
if !self.complexity_cache.is_empty() {
let complexity_balance = self.calculate_complexity_balance()?;
score_components.push(complexity_balance * self.config.complexity_weight);
}
if !self.evolution_tracker.is_empty() {
let evolution_consistency = self.calculate_evolution_consistency()?;
score_components.push(evolution_consistency * self.config.evolution_weight);
}
let dimensional_score = self.calculate_dimensional_score()?;
score_components.push(dimensional_score * self.config.dimensional_weight);
let total_weight = self.config.vector_weight
+ self.config.complexity_weight
+ self.config.evolution_weight
+ self.config.dimensional_weight;
if total_weight == 0.0 {
return Ok(0.0);
}
let combined_score = score_components.iter().sum::<f64>() / total_weight;
Ok(combined_score.max(0.0).min(1.0))
}
fn analyze_semantic_complexity(
&mut self,
sentences: &[String],
) -> AdvancedResult<SemanticComplexity> {
let cache_key = self.generate_complexity_key(sentences);
if let Some(cached) = self.complexity_cache.get(&cache_key) {
return Ok(cached.clone());
}
let mut complexity = SemanticComplexity {
overall_complexity: 0.0,
lexical_complexity: self.calculate_lexical_complexity(sentences)?,
syntactic_complexity: self.calculate_syntactic_complexity(sentences)?,
semantic_density: self.calculate_semantic_density(sentences)?,
conceptual_diversity: self.calculate_conceptual_diversity(sentences)?,
relational_complexity: self.calculate_relational_complexity(sentences)?,
hierarchical_depth: self.calculate_hierarchical_depth(sentences)?,
ambiguity_measures: self.calculate_ambiguity_measures(sentences)?,
information_theoretic: self.calculate_information_theoretic_complexity(sentences)?,
};
complexity.overall_complexity = self.combine_complexity_measures(&complexity)?;
self.complexity_cache.insert(cache_key, complexity.clone());
Ok(complexity)
}
fn analyze_conceptual_dimensions(
&mut self,
sentences: &[String],
) -> AdvancedResult<ConceptualDimensions> {
let mut dimensions = ConceptualDimensions::new();
for sentence in sentences {
let concepts = self.extract_sentence_concepts(sentence)?;
for concept in concepts {
dimensions.add_concept(
&concept,
self.calculate_concept_properties(&concept, sentence)?,
);
}
}
dimensions.build_dimensional_relationships()?;
dimensions.coherence_score = self.calculate_dimensional_coherence_score(&dimensions)?;
self.conceptual_space = dimensions.clone();
Ok(dimensions)
}
fn analyze_semantic_dynamics(
&mut self,
sentences: &[String],
) -> AdvancedResult<SemanticDynamics> {
let mut dynamics = SemanticDynamics::new();
for (i, sentence) in sentences.iter().enumerate() {
if i > 0 {
let prev_sentence = &sentences[i - 1];
let transition = self.analyze_semantic_transition(prev_sentence, sentence)?;
dynamics.add_transition(i, transition);
}
}
dynamics.velocity = self.calculate_semantic_velocity(&dynamics)?;
dynamics.acceleration = self.calculate_semantic_acceleration(&dynamics)?;
dynamics.momentum = self.calculate_semantic_momentum(&dynamics)?;
dynamics.stability = self.calculate_dynamic_stability(&dynamics)?;
let position = self.dynamics_history.len();
self.dynamics_history.insert(position, dynamics.clone());
Ok(dynamics)
}
fn perform_vector_analysis(
&self,
sentences: &[String],
) -> AdvancedResult<VectorSemanticAnalysis> {
let mut analysis = VectorSemanticAnalysis::new();
for i in 0..sentences.len() {
for j in (i + 1)..sentences.len() {
if let (Some(vec_i), Some(vec_j)) = (
self.semantic_vectors.get(&format!("sentence_{}", i)),
self.semantic_vectors.get(&format!("sentence_{}", j)),
) {
let similarity = vec_i.cosine_similarity(vec_j);
analysis.add_similarity(i, j, similarity);
}
}
}
analysis.clusters = self.perform_vector_clustering()?;
analysis.coherence_metrics = self.calculate_vector_coherence_metrics()?;
analysis.dimensional_analysis = self.perform_dimensional_analysis()?;
Ok(analysis)
}
fn track_semantic_evolution(
&mut self,
sentences: &[String],
) -> AdvancedResult<Vec<SemanticEvolution>> {
let mut evolutions = Vec::new();
let window_size = self.config.evolution_window_size;
for window_start in 0..=(sentences.len().saturating_sub(window_size)) {
let window = &sentences[window_start..window_start + window_size];
let evolution = SemanticEvolution {
window_start,
window_size,
semantic_drift: self.calculate_semantic_drift(window)?,
conceptual_evolution: self.track_conceptual_evolution(window)?,
complexity_evolution: self.track_complexity_evolution(window)?,
coherence_evolution: self.track_coherence_evolution(window)?,
innovation_markers: self.detect_innovation_markers(window)?,
stability_indicators: self.calculate_stability_indicators(window)?,
};
evolutions.push(evolution.clone());
self.evolution_tracker.push_back(evolution);
if self.evolution_tracker.len() > self.config.max_evolution_history {
self.evolution_tracker.pop_front();
}
}
Ok(evolutions)
}
fn model_advanced_coherence(
&mut self,
sentences: &[String],
) -> AdvancedResult<AdvancedCoherenceMetrics> {
let mut coherence = AdvancedCoherenceMetrics::new();
coherence.lexical_coherence = self.model_lexical_coherence(sentences)?;
coherence.semantic_coherence = self.model_semantic_coherence(sentences)?;
coherence.pragmatic_coherence = self.model_pragmatic_coherence(sentences)?;
coherence.discourse_coherence = self.model_discourse_coherence(sentences)?;
coherence.neural_coherence_model = self.apply_neural_coherence_model(sentences)?;
coherence.graph_coherence_model = self.apply_graph_coherence_model(sentences)?;
coherence.information_coherence_model =
self.apply_information_coherence_model(sentences)?;
coherence.coherence_predictions = self.predict_coherence_evolution(sentences)?;
let model_key = format!("coherence_model_{}", sentences.len());
self.coherence_models.insert(model_key, coherence.clone());
Ok(coherence)
}
fn validate_config(config: &AdvancedSemanticConfig) -> AdvancedResult<()> {
if config.vector_dimensions < 1 {
return Err(AdvancedAnalysisError::ConfigError(
"vector_dimensions must be at least 1".to_string(),
));
}
if config.evolution_window_size < 2 {
return Err(AdvancedAnalysisError::ConfigError(
"evolution_window_size must be at least 2".to_string(),
));
}
let total_weight = config.vector_weight
+ config.complexity_weight
+ config.evolution_weight
+ config.dimensional_weight;
if total_weight <= 0.0 {
return Err(AdvancedAnalysisError::ConfigError(
"sum of all weights must be positive".to_string(),
));
}
Ok(())
}
fn extract_sentences(&self, text: &str) -> Vec<String> {
text.split(&self.config.sentence_delimiters)
.map(|s| s.trim().to_string())
.filter(|s| !s.is_empty())
.collect()
}
fn generate_cache_key(&self, text: &str, context: Option<&HashMap<String, String>>) -> u64 {
let mut hasher = DefaultHasher::new();
text.hash(&mut hasher);
if let Some(ctx) = context {
for (k, v) in ctx {
k.hash(&mut hasher);
v.hash(&mut hasher);
}
}
self.config.hash(&mut hasher);
hasher.finish()
}
fn generate_complexity_key(&self, sentences: &[String]) -> u64 {
let mut hasher = DefaultHasher::new();
for sentence in sentences {
sentence.hash(&mut hasher);
}
self.config.hash(&mut hasher);
hasher.finish()
}
fn extract_semantic_features(&self, sentence: &str) -> AdvancedResult<HashMap<String, f64>> {
let mut features = HashMap::new();
let words: Vec<&str> = sentence.split_whitespace().collect();
features.insert("word_count".to_string(), words.len() as f64);
features.insert(
"avg_word_length".to_string(),
words.iter().map(|w| w.len()).sum::<usize>() as f64 / words.len() as f64,
);
let meaningful_words = words.iter().filter(|w| self.is_meaningful_word(w)).count();
features.insert(
"semantic_density".to_string(),
meaningful_words as f64 / words.len() as f64,
);
features.insert(
"syntactic_complexity".to_string(),
self.estimate_syntactic_complexity(sentence)?,
);
features.insert(
"lexical_diversity".to_string(),
self.calculate_lexical_diversity(sentence)?,
);
Ok(features)
}
fn create_semantic_vector(
&self,
features: &HashMap<String, f64>,
context: &str,
) -> AdvancedResult<SemanticVector> {
let mut dimensions = vec![0.0; self.config.vector_dimensions];
let mut labels = Vec::new();
for (i, (feature_name, feature_value)) in features.iter().enumerate() {
if i < dimensions.len() {
dimensions[i] = *feature_value;
labels.push(feature_name.clone());
}
}
while labels.len() < dimensions.len() {
let idx = labels.len();
dimensions[idx] = self.calculate_derived_feature(context, idx)?;
labels.push(format!("derived_{}", idx));
}
let mut vector = SemanticVector::new(dimensions, labels);
vector.source_context = context.to_string();
Ok(vector)
}
fn is_meaningful_word(&self, word: &str) -> bool {
word.len() >= self.config.min_word_length
&& word.chars().any(|c| c.is_alphabetic())
&& !self.is_stop_word(word)
}
fn is_stop_word(&self, word: &str) -> bool {
self.config.stop_words.contains(&word.to_lowercase())
}
}
impl Default for AdvancedSemanticAnalyzer {
fn default() -> Self {
Self::new(AdvancedSemanticConfig::default()).expect("default advanced semantic config should be valid")
}
}