1use crate::{QvmError, Result};
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct CircuitTiming {
10 pub start_time: u64,
12 pub duration: u64,
14 pub estimated_end_time: u64,
16}
17
18impl CircuitTiming {
19 pub fn new(start_time: u64, duration: u64) -> Self {
21 Self {
22 start_time,
23 duration,
24 estimated_end_time: start_time + duration,
25 }
26 }
27
28 pub fn overlaps_with(&self, other: &CircuitTiming) -> bool {
30 !(self.estimated_end_time <= other.start_time || other.estimated_end_time <= self.start_time)
31 }
32
33 pub fn gap_to(&self, other: &CircuitTiming) -> i64 {
35 if self.estimated_end_time <= other.start_time {
36 (other.start_time - self.estimated_end_time) as i64
37 } else if other.estimated_end_time <= self.start_time {
38 (self.start_time - other.estimated_end_time) as i64
39 } else {
40 0 }
42 }
43}
44
45#[derive(Debug, Clone)]
47pub struct CircuitTimer {
48 config: TimerConfig,
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize)]
53pub struct TimerConfig {
54 pub precision: u64,
56 pub optimize_timing: bool,
58 pub buffer_time: u64,
60 pub max_drift: u64,
62}
63
64impl Default for TimerConfig {
65 fn default() -> Self {
66 Self {
67 precision: 1, optimize_timing: true,
69 buffer_time: 1000, max_drift: 100, }
72 }
73}
74
75impl CircuitTimer {
76 pub fn new() -> Self {
78 Self {
79 config: TimerConfig::default(),
80 }
81 }
82
83 pub fn with_config(config: TimerConfig) -> Self {
85 Self { config }
86 }
87
88 pub fn create_timing(&self, start_time: u64, duration: u64) -> CircuitTiming {
90 let aligned_start = self.align_time(start_time);
91 let aligned_duration = self.align_time(duration);
92
93 CircuitTiming::new(aligned_start, aligned_duration)
94 }
95
96 fn align_time(&self, time: u64) -> u64 {
98 if self.config.precision <= 1 {
99 return time;
100 }
101
102 let remainder = time % self.config.precision;
103 if remainder == 0 {
104 time
105 } else {
106 time + (self.config.precision - remainder)
107 }
108 }
109
110 pub fn optimize_timings(&self, timings: &mut [CircuitTiming]) -> Result<()> {
112 if !self.config.optimize_timing {
113 return Ok(());
114 }
115
116 timings.sort_by_key(|t| t.start_time);
118
119 self.compress_timeline(timings)?;
121
122 self.add_buffer_times(timings)?;
124
125 Ok(())
126 }
127
128 fn compress_timeline(&self, timings: &mut [CircuitTiming]) -> Result<()> {
130 let mut current_time = 0;
131
132 for timing in timings.iter_mut() {
133 if timing.start_time > current_time {
134 timing.start_time = current_time;
135 timing.estimated_end_time = current_time + timing.duration;
136 }
137 current_time = timing.estimated_end_time;
138 }
139
140 Ok(())
141 }
142
143 fn add_buffer_times(&self, timings: &mut [CircuitTiming]) -> Result<()> {
145 for i in 1..timings.len() {
146 let prev_end = timings[i - 1].estimated_end_time;
147 let current_start = timings[i].start_time;
148
149 if current_start < prev_end + self.config.buffer_time {
150 let new_start = prev_end + self.config.buffer_time;
151 timings[i].start_time = new_start;
152 timings[i].estimated_end_time = new_start + timings[i].duration;
153 }
154 }
155
156 Ok(())
157 }
158
159 pub fn validate_timings(&self, timings: &[CircuitTiming]) -> Result<Vec<TimingViolation>> {
161 let mut violations = Vec::new();
162
163 for i in 0..timings.len() {
165 for j in (i + 1)..timings.len() {
166 if timings[i].overlaps_with(&timings[j]) {
167 violations.push(TimingViolation {
168 violation_type: ViolationType::Overlap,
169 circuit1: i,
170 circuit2: Some(j),
171 description: format!("Circuits {} and {} have overlapping execution times", i, j),
172 severity: Severity::Critical,
173 });
174 }
175 }
176 }
177
178 for i in 1..timings.len() {
180 let gap = timings[i].start_time.saturating_sub(timings[i - 1].estimated_end_time);
181 if gap < self.config.buffer_time {
182 violations.push(TimingViolation {
183 violation_type: ViolationType::InsufficientBuffer,
184 circuit1: i - 1,
185 circuit2: Some(i),
186 description: format!("Insufficient buffer time between circuits {} and {}", i - 1, i),
187 severity: Severity::Warning,
188 });
189 }
190 }
191
192 Ok(violations)
193 }
194
195 pub fn calculate_statistics(&self, timings: &[CircuitTiming]) -> TimingStatistics {
197 if timings.is_empty() {
198 return TimingStatistics::default();
199 }
200
201 let total_duration = timings.iter().map(|t| t.duration).sum();
202 let total_execution_time = timings.iter()
203 .map(|t| t.estimated_end_time)
204 .max()
205 .unwrap_or(0);
206
207 let gaps: Vec<u64> = (1..timings.len())
208 .map(|i| {
209 timings[i].start_time.saturating_sub(timings[i - 1].estimated_end_time)
210 })
211 .collect();
212
213 let total_gap_time: u64 = gaps.iter().sum();
214 let avg_gap = if gaps.is_empty() { 0.0 } else { total_gap_time as f64 / gaps.len() as f64 };
215
216 let efficiency = if total_execution_time > 0 {
217 total_duration as f64 / total_execution_time as f64
218 } else {
219 0.0
220 };
221
222 TimingStatistics {
223 total_circuits: timings.len(),
224 total_duration,
225 total_execution_time,
226 total_gap_time,
227 average_gap: avg_gap,
228 efficiency,
229 compression_ratio: if total_duration > 0 {
230 total_execution_time as f64 / total_duration as f64
231 } else {
232 1.0
233 },
234 }
235 }
236}
237
238impl Default for CircuitTimer {
239 fn default() -> Self {
240 Self::new()
241 }
242}
243
244#[derive(Debug, Clone, Serialize, Deserialize)]
246pub struct TimingViolation {
247 pub violation_type: ViolationType,
249 pub circuit1: usize,
251 pub circuit2: Option<usize>,
253 pub description: String,
255 pub severity: Severity,
257}
258
259#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
261pub enum ViolationType {
262 Overlap,
264 InsufficientBuffer,
266 PrecisionViolation,
268 ExcessiveDrift,
270}
271
272#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
274pub enum Severity {
275 Critical,
277 Warning,
279 Info,
281}
282
283#[derive(Debug, Clone, Default, Serialize, Deserialize)]
285pub struct TimingStatistics {
286 pub total_circuits: usize,
288 pub total_duration: u64,
290 pub total_execution_time: u64,
292 pub total_gap_time: u64,
294 pub average_gap: f64,
296 pub efficiency: f64,
298 pub compression_ratio: f64,
300}
301
302pub struct TimingOptimizer;
304
305impl TimingOptimizer {
306 pub fn optimize_advanced(
308 timings: &mut [CircuitTiming],
309 constraints: &TimingConstraints,
310 ) -> Result<OptimizerResult> {
311 let original_stats = Self::calculate_stats(timings);
312
313 Self::apply_parallelization(timings, constraints)?;
315 Self::apply_reordering(timings, constraints)?;
316 Self::apply_compression(timings, constraints)?;
317
318 let optimized_stats = Self::calculate_stats(timings);
319
320 Ok(OptimizerResult {
321 original_duration: original_stats.total_execution_time,
322 optimized_duration: optimized_stats.total_execution_time,
323 improvement: (original_stats.total_execution_time as f64 - optimized_stats.total_execution_time as f64)
324 / original_stats.total_execution_time as f64,
325 techniques_applied: vec!["parallelization".to_string(), "reordering".to_string(), "compression".to_string()],
326 })
327 }
328
329 fn apply_parallelization(
331 timings: &mut [CircuitTiming],
332 _constraints: &TimingConstraints,
333 ) -> Result<()> {
334 for i in 1..timings.len() {
337 if timings[i].start_time > timings[i - 1].start_time + timings[i - 1].duration / 2 {
339 timings[i].start_time = timings[i - 1].start_time;
340 timings[i].estimated_end_time = timings[i].start_time + timings[i].duration;
341 }
342 }
343 Ok(())
344 }
345
346 fn apply_reordering(
348 timings: &mut [CircuitTiming],
349 _constraints: &TimingConstraints,
350 ) -> Result<()> {
351 timings.sort_by_key(|t| t.duration);
353
354 let mut current_time = 0;
356 for timing in timings.iter_mut() {
357 timing.start_time = current_time;
358 timing.estimated_end_time = current_time + timing.duration;
359 current_time += timing.duration;
360 }
361
362 Ok(())
363 }
364
365 fn apply_compression(
367 timings: &mut [CircuitTiming],
368 constraints: &TimingConstraints,
369 ) -> Result<()> {
370 let min_gap = constraints.min_gap_time;
371
372 for i in 1..timings.len() {
374 let actual_gap = timings[i].start_time.saturating_sub(timings[i - 1].estimated_end_time);
375 if actual_gap > min_gap {
376 let excess = actual_gap - min_gap;
377 timings[i].start_time -= excess;
378 timings[i].estimated_end_time -= excess;
379 }
380 }
381
382 Ok(())
383 }
384
385 fn calculate_stats(timings: &[CircuitTiming]) -> TimingStatistics {
387 let timer = CircuitTimer::new();
388 timer.calculate_statistics(timings)
389 }
390}
391
392#[derive(Debug, Clone, Serialize, Deserialize)]
394pub struct TimingConstraints {
395 pub min_gap_time: u64,
397 pub max_total_duration: Option<u64>,
399 pub resource_conflicts: HashMap<(usize, usize), bool>,
401 pub circuit_priorities: Vec<f64>,
403}
404
405impl Default for TimingConstraints {
406 fn default() -> Self {
407 Self {
408 min_gap_time: 1000, max_total_duration: None,
410 resource_conflicts: HashMap::new(),
411 circuit_priorities: Vec::new(),
412 }
413 }
414}
415
416#[derive(Debug, Clone, Serialize, Deserialize)]
418pub struct OptimizerResult {
419 pub original_duration: u64,
421 pub optimized_duration: u64,
423 pub improvement: f64,
425 pub techniques_applied: Vec<String>,
427}
428
429#[cfg(test)]
430mod tests {
431 use super::*;
432
433 #[test]
434 fn test_circuit_timing_creation() {
435 let timing = CircuitTiming::new(1000, 5000);
436 assert_eq!(timing.start_time, 1000);
437 assert_eq!(timing.duration, 5000);
438 assert_eq!(timing.estimated_end_time, 6000);
439 }
440
441 #[test]
442 fn test_timing_overlap() {
443 let timing1 = CircuitTiming::new(1000, 3000);
444 let timing2 = CircuitTiming::new(2000, 3000);
445 let timing3 = CircuitTiming::new(5000, 1000);
446
447 assert!(timing1.overlaps_with(&timing2));
448 assert!(!timing1.overlaps_with(&timing3));
449 }
450
451 #[test]
452 fn test_circuit_timer() {
453 let timer = CircuitTimer::new();
454 let timing = timer.create_timing(1001, 2001);
455
456 assert_eq!(timing.start_time, 1001);
458 assert_eq!(timing.duration, 2001);
459 }
460
461 #[test]
462 fn test_timing_optimization() {
463 let timer = CircuitTimer::new();
464 let mut timings = vec![
465 CircuitTiming::new(1000, 2000),
466 CircuitTiming::new(5000, 1000), CircuitTiming::new(8000, 1500),
468 ];
469
470 timer.optimize_timings(&mut timings).unwrap();
471
472 assert_eq!(timings[0].start_time, 0);
474 assert!(timings[1].start_time >= timings[0].estimated_end_time);
475 }
476
477 #[test]
478 fn test_timing_validation() {
479 let timer = CircuitTimer::new();
480 let timings = vec![
481 CircuitTiming::new(1000, 2000),
482 CircuitTiming::new(1500, 1000), ];
484
485 let violations = timer.validate_timings(&timings).unwrap();
486 assert_eq!(violations.len(), 1);
487 assert_eq!(violations[0].violation_type, ViolationType::Overlap);
488 }
489
490 #[test]
491 fn test_timing_statistics() {
492 let timer = CircuitTimer::new();
493 let timings = vec![
494 CircuitTiming::new(0, 1000),
495 CircuitTiming::new(2000, 1500), CircuitTiming::new(4000, 500), ];
498
499 let stats = timer.calculate_statistics(&timings);
500 assert_eq!(stats.total_circuits, 3);
501 assert_eq!(stats.total_duration, 3000);
502 assert_eq!(stats.total_execution_time, 4500);
503 assert_eq!(stats.total_gap_time, 1500);
504 }
505}