1use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8use std::time::Duration;
9use thiserror::Error;
10
11use super::continuous_variable::{Complex, GaussianState};
12use super::gate_based::{PhotonicCircuitImplementation, PhotonicGateImpl};
13use super::{PhotonicMode, PhotonicSystemType};
14use crate::DeviceResult;
15use scirs2_core::random::prelude::*;
16
17#[derive(Error, Debug)]
19pub enum PhotonicOptimizationError {
20 #[error("Optimization failed: {0}")]
21 OptimizationFailed(String),
22 #[error("Invalid optimization parameters: {0}")]
23 InvalidParameters(String),
24 #[error("Resource constraints violated: {0}")]
25 ResourceConstraints(String),
26 #[error("Convergence failed: {0}")]
27 ConvergenceFailed(String),
28}
29
30#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
32pub enum PhotonicOptimizationObjective {
33 MinimizeDepth,
35 MaximizeFidelity,
37 MinimizeResources,
39 MinimizeTime,
41 MaximizeSuccessProbability,
43 MinimizePhotonLoss,
45 MultiObjective {
47 objectives: Vec<Self>,
48 weights: Vec<f64>,
49 },
50}
51
52#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
54pub enum PhotonicOptimizationAlgorithm {
55 Gradient {
57 learning_rate: f64,
58 max_iterations: usize,
59 },
60 Genetic {
62 population_size: usize,
63 generations: usize,
64 },
65 SimulatedAnnealing {
67 initial_temperature: f64,
68 cooling_rate: f64,
69 },
70 ParticleSwarm {
72 swarm_size: usize,
73 iterations: usize,
74 },
75 QAOA { layers: usize },
77}
78
79#[derive(Debug, Clone, Serialize, Deserialize)]
81pub struct PhotonicOptimizationConfig {
82 pub objective: PhotonicOptimizationObjective,
84 pub algorithm: PhotonicOptimizationAlgorithm,
86 pub tolerance: f64,
88 pub max_time: Duration,
90 pub constraints: PhotonicConstraints,
92}
93
94#[derive(Debug, Clone, Serialize, Deserialize)]
96pub struct PhotonicConstraints {
97 pub max_modes: Option<usize>,
99 pub max_depth: Option<usize>,
101 pub max_gates: Option<usize>,
103 pub max_execution_time: Option<Duration>,
105 pub min_fidelity: Option<f64>,
107 pub max_loss_rate: Option<f64>,
109}
110
111impl Default for PhotonicConstraints {
112 fn default() -> Self {
113 Self {
114 max_modes: Some(16),
115 max_depth: Some(100),
116 max_gates: Some(1000),
117 max_execution_time: Some(Duration::from_secs(10)),
118 min_fidelity: Some(0.95),
119 max_loss_rate: Some(0.1),
120 }
121 }
122}
123
124#[derive(Debug, Clone, Serialize, Deserialize)]
126pub struct PhotonicOptimizationResult {
127 pub optimized_circuit: PhotonicCircuitImplementation,
129 pub objective_value: f64,
131 pub iterations: usize,
133 pub optimization_time: Duration,
135 pub converged: bool,
137 pub improvement: OptimizationImprovement,
139}
140
141#[derive(Debug, Clone, Serialize, Deserialize)]
143pub struct OptimizationImprovement {
144 pub fidelity_improvement: f64,
146 pub depth_reduction: f64,
148 pub resource_savings: f64,
150 pub time_savings: f64,
152}
153
154pub struct PhotonicOptimizer {
156 pub config: PhotonicOptimizationConfig,
158 pub history: Vec<OptimizationStep>,
160 pub best_solution: Option<PhotonicCircuitImplementation>,
162}
163
164#[derive(Debug, Clone, Serialize, Deserialize)]
166pub struct OptimizationStep {
167 pub step: usize,
169 pub objective_value: f64,
171 pub parameters: Vec<f64>,
173 pub elapsed_time: Duration,
175}
176
177impl PhotonicOptimizer {
178 pub const fn new(config: PhotonicOptimizationConfig) -> Self {
179 Self {
180 config,
181 history: Vec::new(),
182 best_solution: None,
183 }
184 }
185
186 pub fn optimize(
188 &mut self,
189 initial_circuit: PhotonicCircuitImplementation,
190 ) -> Result<PhotonicOptimizationResult, PhotonicOptimizationError> {
191 let start_time = std::time::Instant::now();
192
193 self.validate_constraints(&initial_circuit)?;
195
196 let mut current_circuit = initial_circuit.clone();
198 let mut best_objective = self.evaluate_objective(¤t_circuit)?;
199 let mut iterations = 0;
200
201 while start_time.elapsed() < self.config.max_time {
203 let improved_circuit = match &self.config.algorithm {
204 PhotonicOptimizationAlgorithm::Gradient {
205 learning_rate,
206 max_iterations,
207 } => {
208 if iterations >= *max_iterations {
209 break;
210 }
211 self.gradient_step(¤t_circuit, *learning_rate)?
212 }
213 PhotonicOptimizationAlgorithm::Genetic {
214 population_size,
215 generations,
216 } => {
217 if iterations >= *generations {
218 break;
219 }
220 self.genetic_step(¤t_circuit, *population_size)?
221 }
222 PhotonicOptimizationAlgorithm::SimulatedAnnealing {
223 initial_temperature,
224 cooling_rate,
225 } => {
226 let temperature = initial_temperature * cooling_rate.powf(iterations as f64);
227 if temperature < 1e-6 {
228 break;
229 }
230 self.annealing_step(¤t_circuit, temperature)?
231 }
232 PhotonicOptimizationAlgorithm::ParticleSwarm {
233 swarm_size,
234 iterations: max_iter,
235 } => {
236 if iterations >= *max_iter {
237 break;
238 }
239 self.pso_step(¤t_circuit, *swarm_size)?
240 }
241 PhotonicOptimizationAlgorithm::QAOA { layers } => {
242 self.qaoa_step(¤t_circuit, *layers)?
243 }
244 };
245
246 let objective = self.evaluate_objective(&improved_circuit)?;
247
248 self.history.push(OptimizationStep {
250 step: iterations,
251 objective_value: objective,
252 parameters: vec![], elapsed_time: start_time.elapsed(),
254 });
255
256 if self.is_improvement(objective, best_objective) {
258 best_objective = objective;
259 current_circuit = improved_circuit;
260 self.best_solution = Some(current_circuit.clone());
261 }
262
263 if self.check_convergence(¤t_circuit)? {
265 break;
266 }
267
268 iterations += 1;
269 }
270
271 let final_circuit = self.best_solution.clone().unwrap_or(current_circuit);
272 let improvement = self.calculate_improvement(&initial_circuit, &final_circuit);
273
274 Ok(PhotonicOptimizationResult {
275 optimized_circuit: final_circuit,
276 objective_value: best_objective,
277 iterations,
278 optimization_time: start_time.elapsed(),
279 converged: self.check_convergence_simple(best_objective),
280 improvement,
281 })
282 }
283
284 fn validate_constraints(
286 &self,
287 circuit: &PhotonicCircuitImplementation,
288 ) -> Result<(), PhotonicOptimizationError> {
289 let constraints = &self.config.constraints;
290
291 if let Some(max_gates) = constraints.max_gates {
292 if circuit.gates.len() > max_gates {
293 return Err(PhotonicOptimizationError::ResourceConstraints(format!(
294 "Circuit has {} gates, max allowed {}",
295 circuit.gates.len(),
296 max_gates
297 )));
298 }
299 }
300
301 if let Some(min_fidelity) = constraints.min_fidelity {
302 if circuit.total_fidelity < min_fidelity {
303 return Err(PhotonicOptimizationError::ResourceConstraints(format!(
304 "Circuit fidelity {} below minimum {}",
305 circuit.total_fidelity, min_fidelity
306 )));
307 }
308 }
309
310 if let Some(max_time) = constraints.max_execution_time {
311 if circuit.estimated_execution_time > max_time {
312 return Err(PhotonicOptimizationError::ResourceConstraints(format!(
313 "Execution time {:?} exceeds maximum {:?}",
314 circuit.estimated_execution_time, max_time
315 )));
316 }
317 }
318
319 Ok(())
320 }
321
322 fn evaluate_objective(
324 &self,
325 circuit: &PhotonicCircuitImplementation,
326 ) -> Result<f64, PhotonicOptimizationError> {
327 match &self.config.objective {
328 PhotonicOptimizationObjective::MinimizeDepth => {
329 Ok(-(circuit.gates.len() as f64))
331 }
332 PhotonicOptimizationObjective::MaximizeFidelity => Ok(circuit.total_fidelity),
333 PhotonicOptimizationObjective::MinimizeResources => {
334 let resource_count = circuit.resource_requirements.waveplates
335 + circuit.resource_requirements.beam_splitters
336 + circuit.resource_requirements.detectors;
337 Ok(-(resource_count as f64))
338 }
339 PhotonicOptimizationObjective::MinimizeTime => {
340 Ok(-(circuit.estimated_execution_time.as_secs_f64()))
341 }
342 PhotonicOptimizationObjective::MaximizeSuccessProbability => {
343 Ok(circuit.success_probability)
344 }
345 PhotonicOptimizationObjective::MinimizePhotonLoss => {
346 Ok(circuit.total_fidelity)
348 }
349 PhotonicOptimizationObjective::MultiObjective {
350 objectives,
351 weights,
352 } => {
353 let mut total_objective = 0.0;
354 for (i, obj) in objectives.iter().enumerate() {
355 if let Some(&weight) = weights.get(i) {
356 let sub_config = PhotonicOptimizationConfig {
357 objective: obj.clone(),
358 ..self.config.clone()
359 };
360 let sub_optimizer = Self::new(sub_config);
361 let sub_value = sub_optimizer.evaluate_objective(circuit)?;
362 total_objective += weight * sub_value;
363 }
364 }
365 Ok(total_objective)
366 }
367 }
368 }
369
370 fn is_improvement(&self, new_value: f64, current_best: f64) -> bool {
372 match &self.config.objective {
373 PhotonicOptimizationObjective::MinimizeDepth
374 | PhotonicOptimizationObjective::MinimizeResources
375 | PhotonicOptimizationObjective::MinimizeTime => new_value < current_best,
376 _ => new_value > current_best,
377 }
378 }
379
380 fn gradient_step(
382 &self,
383 circuit: &PhotonicCircuitImplementation,
384 learning_rate: f64,
385 ) -> Result<PhotonicCircuitImplementation, PhotonicOptimizationError> {
386 let mut optimized = circuit.clone();
389
390 for gate in &mut optimized.gates {
392 if !gate.optical_elements.is_empty() {
393 let perturbation = (thread_rng().gen::<f64>() - 0.5) * learning_rate * 0.1;
395 optimized.total_fidelity *= 1.0 + perturbation * 0.01;
397 }
398 }
399
400 Ok(optimized)
401 }
402
403 fn genetic_step(
405 &self,
406 circuit: &PhotonicCircuitImplementation,
407 population_size: usize,
408 ) -> Result<PhotonicCircuitImplementation, PhotonicOptimizationError> {
409 let mut best_circuit = circuit.clone();
411
412 for _ in 0..population_size {
413 let mut candidate = circuit.clone();
414
415 if !candidate.gates.is_empty() {
417 let mutation_strength = 0.1;
418 candidate.total_fidelity *=
419 (thread_rng().gen::<f64>() - 0.5).mul_add(mutation_strength, 1.0);
420 candidate.total_fidelity = candidate.total_fidelity.clamp(0.0, 1.0);
421 }
422
423 if self.evaluate_objective(&candidate)? > self.evaluate_objective(&best_circuit)? {
425 best_circuit = candidate;
426 }
427 }
428
429 Ok(best_circuit)
430 }
431
432 fn annealing_step(
434 &self,
435 circuit: &PhotonicCircuitImplementation,
436 temperature: f64,
437 ) -> Result<PhotonicCircuitImplementation, PhotonicOptimizationError> {
438 let mut candidate = circuit.clone();
439
440 let perturbation_strength = temperature * 0.01;
442 candidate.total_fidelity *=
443 (thread_rng().gen::<f64>() - 0.5).mul_add(perturbation_strength, 1.0);
444 candidate.total_fidelity = candidate.total_fidelity.clamp(0.0, 1.0);
445
446 let current_obj = self.evaluate_objective(circuit)?;
448 let candidate_obj = self.evaluate_objective(&candidate)?;
449
450 if self.is_improvement(candidate_obj, current_obj) {
451 Ok(candidate)
452 } else {
453 let acceptance_prob = (-(current_obj - candidate_obj) / temperature).exp();
454 if thread_rng().gen::<f64>() < acceptance_prob {
455 Ok(candidate)
456 } else {
457 Ok(circuit.clone())
458 }
459 }
460 }
461
462 fn pso_step(
464 &self,
465 circuit: &PhotonicCircuitImplementation,
466 swarm_size: usize,
467 ) -> Result<PhotonicCircuitImplementation, PhotonicOptimizationError> {
468 let mut best_circuit = circuit.clone();
470
471 for _ in 0..swarm_size {
472 let mut particle = circuit.clone();
473
474 let velocity = 0.1 * (thread_rng().gen::<f64>() - 0.5);
476 particle.total_fidelity += velocity;
477 particle.total_fidelity = particle.total_fidelity.clamp(0.0, 1.0);
478
479 if self.evaluate_objective(&particle)? > self.evaluate_objective(&best_circuit)? {
480 best_circuit = particle;
481 }
482 }
483
484 Ok(best_circuit)
485 }
486
487 fn qaoa_step(
489 &self,
490 circuit: &PhotonicCircuitImplementation,
491 layers: usize,
492 ) -> Result<PhotonicCircuitImplementation, PhotonicOptimizationError> {
493 let mut optimized = circuit.clone();
496
497 for _ in 0..layers {
498 let gamma = thread_rng().gen::<f64>() * std::f64::consts::PI;
500 let beta = thread_rng().gen::<f64>() * std::f64::consts::PI;
501
502 optimized.total_fidelity *= 0.01f64.mul_add((gamma + beta).cos(), 1.0);
504 optimized.total_fidelity = optimized.total_fidelity.clamp(0.0, 1.0);
505 }
506
507 Ok(optimized)
508 }
509
510 fn check_convergence(
512 &self,
513 circuit: &PhotonicCircuitImplementation,
514 ) -> Result<bool, PhotonicOptimizationError> {
515 if self.history.len() < 2 {
516 return Ok(false);
517 }
518
519 let recent_values: Vec<f64> = self
520 .history
521 .iter()
522 .rev()
523 .take(5)
524 .map(|step| step.objective_value)
525 .collect();
526
527 if recent_values.len() < 2 {
528 return Ok(false);
529 }
530
531 let max_val = recent_values
532 .iter()
533 .fold(f64::NEG_INFINITY, |a, &b| a.max(b));
534 let min_val = recent_values.iter().fold(f64::INFINITY, |a, &b| a.min(b));
535
536 Ok((max_val - min_val).abs() < self.config.tolerance)
537 }
538
539 fn check_convergence_simple(&self, objective_value: f64) -> bool {
541 match &self.config.objective {
542 PhotonicOptimizationObjective::MaximizeFidelity => objective_value > 0.99,
543 PhotonicOptimizationObjective::MaximizeSuccessProbability => objective_value > 0.95,
544 _ => false,
545 }
546 }
547
548 fn calculate_improvement(
550 &self,
551 initial: &PhotonicCircuitImplementation,
552 final_circuit: &PhotonicCircuitImplementation,
553 ) -> OptimizationImprovement {
554 let fidelity_improvement = final_circuit.total_fidelity - initial.total_fidelity;
555 let depth_reduction = (initial.gates.len() as f64 - final_circuit.gates.len() as f64)
556 / initial.gates.len() as f64;
557
558 let initial_resources = initial.resource_requirements.waveplates
559 + initial.resource_requirements.beam_splitters
560 + initial.resource_requirements.detectors;
561 let final_resources = final_circuit.resource_requirements.waveplates
562 + final_circuit.resource_requirements.beam_splitters
563 + final_circuit.resource_requirements.detectors;
564
565 let resource_savings =
566 (initial_resources as f64 - final_resources as f64) / initial_resources as f64;
567
568 let time_savings = (initial.estimated_execution_time.as_secs_f64()
569 - final_circuit.estimated_execution_time.as_secs_f64())
570 / initial.estimated_execution_time.as_secs_f64();
571
572 OptimizationImprovement {
573 fidelity_improvement,
574 depth_reduction,
575 resource_savings,
576 time_savings,
577 }
578 }
579}
580
581#[cfg(test)]
582mod tests {
583 use super::*;
584 use crate::photonic::gate_based::{PhotonicGateImpl, PhotonicResourceRequirements};
585
586 fn create_test_circuit() -> PhotonicCircuitImplementation {
587 PhotonicCircuitImplementation {
588 gates: vec![],
589 resource_requirements: PhotonicResourceRequirements::default(),
590 success_probability: 0.9,
591 total_fidelity: 0.95,
592 estimated_execution_time: Duration::from_millis(100),
593 }
594 }
595
596 #[test]
597 fn test_optimizer_creation() {
598 let config = PhotonicOptimizationConfig {
599 objective: PhotonicOptimizationObjective::MaximizeFidelity,
600 algorithm: PhotonicOptimizationAlgorithm::Gradient {
601 learning_rate: 0.01,
602 max_iterations: 100,
603 },
604 tolerance: 1e-6,
605 max_time: Duration::from_secs(60),
606 constraints: PhotonicConstraints::default(),
607 };
608
609 let optimizer = PhotonicOptimizer::new(config);
610 assert_eq!(optimizer.history.len(), 0);
611 }
612
613 #[test]
614 fn test_objective_evaluation() {
615 let config = PhotonicOptimizationConfig {
616 objective: PhotonicOptimizationObjective::MaximizeFidelity,
617 algorithm: PhotonicOptimizationAlgorithm::Gradient {
618 learning_rate: 0.01,
619 max_iterations: 100,
620 },
621 tolerance: 1e-6,
622 max_time: Duration::from_secs(60),
623 constraints: PhotonicConstraints::default(),
624 };
625
626 let optimizer = PhotonicOptimizer::new(config);
627 let circuit = create_test_circuit();
628
629 let objective = optimizer
630 .evaluate_objective(&circuit)
631 .expect("Objective evaluation should succeed");
632 assert_eq!(objective, 0.95); }
634
635 #[test]
636 fn test_constraint_validation() {
637 let mut constraints = PhotonicConstraints::default();
638 constraints.min_fidelity = Some(0.99);
639
640 let config = PhotonicOptimizationConfig {
641 objective: PhotonicOptimizationObjective::MaximizeFidelity,
642 algorithm: PhotonicOptimizationAlgorithm::Gradient {
643 learning_rate: 0.01,
644 max_iterations: 100,
645 },
646 tolerance: 1e-6,
647 max_time: Duration::from_secs(60),
648 constraints,
649 };
650
651 let optimizer = PhotonicOptimizer::new(config);
652 let circuit = create_test_circuit(); let result = optimizer.validate_constraints(&circuit);
655 assert!(result.is_err());
656 }
657}