quantrs2_anneal/rl_embedding_optimizer/
cache.rs1use std::collections::HashMap;
4use std::time::{Duration, Instant};
5
6use super::embedding::EmbeddingOptimizer;
7use super::error::{RLEmbeddingError, RLEmbeddingResult};
8use super::types::{
9 CacheMetadata, CachedEmbedding, EmbeddingPerformanceResults, EmbeddingQualityMetrics,
10 EmbeddingState, RLPerformanceMetrics, RLTrainingStats, RuntimeStatistics,
11 TransferLearningStats,
12};
13use crate::embedding::{Embedding, HardwareTopology};
14use crate::ising::IsingModel;
15
16pub struct CacheManager;
18
19impl CacheManager {
20 #[must_use]
22 pub fn check_cache<'a>(
23 embedding_cache: &'a HashMap<String, CachedEmbedding>,
24 state: &EmbeddingState,
25 ) -> Option<&'a CachedEmbedding> {
26 let cache_key = format!(
28 "{}_{:.2}_{:.2}",
29 state.problem_features.num_vertices,
30 state.problem_features.density,
31 state.problem_features.average_degree
32 );
33
34 embedding_cache.get(&cache_key)
35 }
36
37 pub fn cache_embedding(
39 embedding_cache: &mut HashMap<String, CachedEmbedding>,
40 problem: &IsingModel,
41 embedding: &Embedding,
42 hardware: &HardwareTopology,
43 computation_time: Duration,
44 ) -> RLEmbeddingResult<()> {
45 let cache_key = format!(
46 "{}_{:.2}_default",
47 problem.num_qubits,
48 EmbeddingOptimizer::calculate_problem_density(problem)
49 );
50
51 let cached_embedding = CachedEmbedding {
52 embedding: embedding.clone(),
53 quality_metrics: EmbeddingQualityMetrics {
54 overall_score: EmbeddingOptimizer::evaluate_embedding_quality(embedding, hardware)?,
55 chain_length_penalty: EmbeddingOptimizer::calculate_average_chain_length(embedding),
56 connectivity_score: 0.8, utilization_efficiency: EmbeddingOptimizer::calculate_hardware_utilization(
58 embedding, hardware,
59 ),
60 predicted_performance: 0.7, },
62 performance_results: EmbeddingPerformanceResults {
63 success_probability: 0.8,
64 average_energy_gap: 1.0,
65 solution_quality: vec![0.8, 0.9, 0.7],
66 runtime_stats: RuntimeStatistics {
67 embedding_time: computation_time,
68 execution_time: Duration::from_millis(100),
69 total_time: computation_time + Duration::from_millis(100),
70 memory_usage: 1024 * 1024, },
72 },
73 cache_metadata: CacheMetadata {
74 created_at: Instant::now(),
75 last_accessed: Instant::now(),
76 access_count: 1,
77 hit_rate: 0.0,
78 },
79 };
80
81 embedding_cache.insert(cache_key, cached_embedding);
82 Ok(())
83 }
84
85 pub fn update_cache_statistics(
87 embedding_cache: &mut HashMap<String, CachedEmbedding>,
88 cache_key: &str,
89 ) {
90 if let Some(cached_embedding) = embedding_cache.get_mut(cache_key) {
91 cached_embedding.cache_metadata.last_accessed = Instant::now();
92 cached_embedding.cache_metadata.access_count += 1;
93 }
94 }
95
96 pub fn cleanup_cache(
98 embedding_cache: &mut HashMap<String, CachedEmbedding>,
99 max_age: Duration,
100 ) {
101 let now = Instant::now();
102 let mut keys_to_remove = Vec::new();
103
104 for (key, cached_embedding) in embedding_cache.iter() {
105 if now.duration_since(cached_embedding.cache_metadata.created_at) > max_age {
106 keys_to_remove.push(key.clone());
107 }
108 }
109
110 for key in keys_to_remove {
111 embedding_cache.remove(&key);
112 }
113 }
114
115 #[must_use]
117 pub fn calculate_cache_hit_rate(embedding_cache: &HashMap<String, CachedEmbedding>) -> f64 {
118 let total_accesses: usize = embedding_cache
119 .values()
120 .map(|entry| entry.cache_metadata.access_count)
121 .sum();
122
123 let cache_hits = embedding_cache.len();
124
125 if total_accesses > 0 {
126 cache_hits as f64 / total_accesses as f64
127 } else {
128 0.0
129 }
130 }
131}
132
133pub struct PerformanceTracker;
135
136impl PerformanceTracker {
137 pub fn update_performance_metrics(
139 metrics: &mut RLPerformanceMetrics,
140 embedding_quality: f64,
141 baseline_quality: f64,
142 ) {
143 metrics.problems_solved += 1;
144
145 let improvement = embedding_quality - baseline_quality;
146
147 let alpha = 0.1; metrics.average_improvement =
150 alpha * improvement + (1.0 - alpha) * metrics.average_improvement;
151
152 if improvement > metrics.best_improvement {
154 metrics.best_improvement = improvement;
155 }
156 }
157
158 #[must_use]
160 pub fn calculate_computational_efficiency(
161 problems_solved: usize,
162 total_time: Duration,
163 average_improvement: f64,
164 ) -> f64 {
165 if total_time.as_secs_f64() > 0.0 {
166 (problems_solved as f64 * average_improvement) / total_time.as_secs_f64()
167 } else {
168 0.0
169 }
170 }
171
172 pub fn update_convergence_rate(
174 metrics: &mut RLPerformanceMetrics,
175 training_stats: &RLTrainingStats,
176 ) {
177 if training_stats.loss_history.len() > 10 {
178 let recent_losses =
179 &training_stats.loss_history[training_stats.loss_history.len() - 10..];
180 let initial_loss = recent_losses[0];
181 let final_loss = recent_losses[recent_losses.len() - 1];
182
183 if initial_loss > 0.0 {
184 metrics.convergence_rate = (initial_loss - final_loss) / initial_loss;
185 }
186 }
187 }
188
189 pub const fn update_transfer_effectiveness(
191 metrics: &mut RLPerformanceMetrics,
192 transfer_stats: &TransferLearningStats,
193 ) {
194 metrics.transfer_effectiveness = transfer_stats.transfer_effectiveness;
195 }
196
197 #[must_use]
199 pub fn generate_performance_report(metrics: &RLPerformanceMetrics) -> String {
200 format!(
201 "RL Embedding Optimizer Performance Report:\n\
202 Problems Solved: {}\n\
203 Average Improvement: {:.3}\n\
204 Best Improvement: {:.3}\n\
205 Convergence Rate: {:.3}\n\
206 Transfer Effectiveness: {:.3}\n\
207 Computational Efficiency: {:.3}",
208 metrics.problems_solved,
209 metrics.average_improvement,
210 metrics.best_improvement,
211 metrics.convergence_rate,
212 metrics.transfer_effectiveness,
213 metrics.computational_efficiency
214 )
215 }
216}