1use super::{
8 energy, finance, healthcare, logistics, manufacturing, telecommunications, ApplicationError,
9 ApplicationResult, IndustryConstraint, IndustryObjective, IndustrySolution,
10 OptimizationProblem, ProblemCategory,
11};
12use crate::ising::IsingModel;
13use crate::qubo::{QuboBuilder, QuboFormulation};
14use crate::simulator::{
15 AnnealingParams, AnnealingResult, ClassicalAnnealingSimulator, QuantumAnnealingSimulator,
16};
17use std::any::Any;
18use std::collections::HashMap;
19use std::fmt::Debug;
20
21#[derive(Debug, Clone)]
23pub enum UnifiedSolution {
24 Binary(Vec<i8>),
26 Continuous(Vec<f64>),
28 Mixed {
30 binary: Vec<i8>,
31 continuous: Vec<f64>,
32 },
33 Custom(serde_json::Value),
35}
36
37impl UnifiedSolution {
38 #[must_use]
40 pub const fn binary(&self) -> Option<&Vec<i8>> {
41 match self {
42 Self::Binary(b) => Some(b),
43 Self::Mixed { binary, .. } => Some(binary),
44 _ => None,
45 }
46 }
47
48 #[must_use]
50 pub const fn continuous(&self) -> Option<&Vec<f64>> {
51 match self {
52 Self::Continuous(c) => Some(c),
53 Self::Mixed { continuous, .. } => Some(continuous),
54 _ => None,
55 }
56 }
57}
58
59pub trait UnifiedProblem:
61 OptimizationProblem<Solution = UnifiedSolution, ObjectiveValue = f64> + Debug + Send + Sync
62{
63 fn category(&self) -> ProblemCategory;
65
66 fn industry(&self) -> &'static str;
68
69 fn complexity(&self) -> ProblemComplexity;
71
72 fn recommended_solver_config(&self) -> SolverConfiguration;
74
75 fn constraints(&self) -> Vec<IndustryConstraint>;
77
78 fn objective(&self) -> IndustryObjective;
80
81 fn solution_bounds(&self) -> Option<(f64, f64)>; fn as_any(&self) -> &dyn Any;
86
87 fn clone_unified(&self) -> Box<dyn UnifiedProblem>;
89}
90
91#[derive(Debug, Clone, PartialEq, Eq)]
93pub enum ProblemComplexity {
94 Small,
96 Medium,
98 Large,
100 ExtraLarge,
102}
103
104#[derive(Debug, Clone)]
106pub struct SolverConfiguration {
107 pub solver_type: SolverType,
109 pub annealing_params: AnnealingParams,
111 pub hardware_requirements: HardwareRequirements,
113 pub optimization_hints: Vec<OptimizationHint>,
115}
116
117#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
119pub enum SolverType {
120 #[default]
121 Classical,
123 QuantumSimulator,
125 DWave,
127 Hybrid,
129 Heuristic,
131}
132
133#[derive(Debug, Clone)]
135pub struct HardwareRequirements {
136 pub min_memory_gb: f64,
138 pub recommended_cores: usize,
140 pub gpu_acceleration: bool,
142 pub quantum_hardware: bool,
144}
145
146#[derive(Debug, Clone)]
148pub enum OptimizationHint {
149 SparseStructure,
151 MultiModal,
153 HighlyConstrained,
155 RealTime,
157 HighPrecision,
159 ApproximateOk,
161}
162
163#[derive(Debug, Clone)]
165pub struct UnifiedSolverFactory {
166 default_configs: HashMap<ProblemCategory, SolverConfiguration>,
168 available_solvers: Vec<SolverType>,
170 performance_cache: HashMap<String, f64>,
172}
173
174impl Default for UnifiedSolverFactory {
175 fn default() -> Self {
176 Self::new()
177 }
178}
179
180impl UnifiedSolverFactory {
181 #[must_use]
183 pub fn new() -> Self {
184 let mut factory = Self {
185 default_configs: HashMap::new(),
186 available_solvers: vec![SolverType::Classical, SolverType::QuantumSimulator],
187 performance_cache: HashMap::new(),
188 };
189
190 factory.initialize_default_configs();
191 factory
192 }
193
194 fn initialize_default_configs(&mut self) {
196 self.default_configs.insert(
198 ProblemCategory::Portfolio,
199 SolverConfiguration {
200 solver_type: SolverType::Classical,
201 annealing_params: AnnealingParams {
202 num_sweeps: 10_000,
203 num_repetitions: 20,
204 initial_temperature: 2.0,
205 final_temperature: 0.01,
206 temperature_schedule: crate::simulator::TemperatureSchedule::Linear,
207 ..Default::default()
208 },
209 hardware_requirements: HardwareRequirements {
210 min_memory_gb: 2.0,
211 recommended_cores: 4,
212 gpu_acceleration: false,
213 quantum_hardware: false,
214 },
215 optimization_hints: vec![OptimizationHint::HighPrecision],
216 },
217 );
218
219 self.default_configs.insert(
221 ProblemCategory::Routing,
222 SolverConfiguration {
223 solver_type: SolverType::Hybrid,
224 annealing_params: AnnealingParams {
225 num_sweeps: 15_000,
226 num_repetitions: 25,
227 initial_temperature: 3.0,
228 final_temperature: 0.005,
229 temperature_schedule: crate::simulator::TemperatureSchedule::Exponential(0.95),
230 ..Default::default()
231 },
232 hardware_requirements: HardwareRequirements {
233 min_memory_gb: 4.0,
234 recommended_cores: 8,
235 gpu_acceleration: true,
236 quantum_hardware: false,
237 },
238 optimization_hints: vec![
239 OptimizationHint::MultiModal,
240 OptimizationHint::HighlyConstrained,
241 ],
242 },
243 );
244
245 self.default_configs.insert(
247 ProblemCategory::NetworkDesign,
248 SolverConfiguration {
249 solver_type: SolverType::QuantumSimulator,
250 annealing_params: AnnealingParams {
251 num_sweeps: 25_000,
252 num_repetitions: 40,
253 initial_temperature: 5.0,
254 final_temperature: 0.001,
255 temperature_schedule: crate::simulator::TemperatureSchedule::Linear,
256 ..Default::default()
257 },
258 hardware_requirements: HardwareRequirements {
259 min_memory_gb: 8.0,
260 recommended_cores: 16,
261 gpu_acceleration: true,
262 quantum_hardware: false,
263 },
264 optimization_hints: vec![OptimizationHint::SparseStructure],
265 },
266 );
267
268 self.add_remaining_default_configs();
270 }
271
272 fn add_remaining_default_configs(&mut self) {
274 self.default_configs.insert(
276 ProblemCategory::ResourceAllocation,
277 SolverConfiguration {
278 solver_type: SolverType::Classical,
279 annealing_params: AnnealingParams::default(),
280 hardware_requirements: HardwareRequirements {
281 min_memory_gb: 1.0,
282 recommended_cores: 2,
283 gpu_acceleration: false,
284 quantum_hardware: false,
285 },
286 optimization_hints: vec![OptimizationHint::HighlyConstrained],
287 },
288 );
289
290 self.default_configs.insert(
292 ProblemCategory::SupplyChain,
293 SolverConfiguration {
294 solver_type: SolverType::Hybrid,
295 annealing_params: AnnealingParams {
296 num_sweeps: 20_000,
297 num_repetitions: 30,
298 initial_temperature: 4.0,
299 final_temperature: 0.01,
300 ..Default::default()
301 },
302 hardware_requirements: HardwareRequirements {
303 min_memory_gb: 6.0,
304 recommended_cores: 12,
305 gpu_acceleration: true,
306 quantum_hardware: false,
307 },
308 optimization_hints: vec![OptimizationHint::MultiModal],
309 },
310 );
311 }
312
313 pub fn create_problem(
315 &self,
316 industry: &str,
317 problem_type: &str,
318 config: HashMap<String, serde_json::Value>,
319 ) -> ApplicationResult<Box<dyn UnifiedProblem>> {
320 match (industry, problem_type) {
321 ("finance", "portfolio") => {
322 let problem = self.create_finance_portfolio(config)?;
323 Ok(Box::new(problem) as Box<dyn UnifiedProblem>)
324 }
325 ("logistics", "vrp") => {
326 let problem = self.create_logistics_vrp(config)?;
327 Ok(Box::new(problem) as Box<dyn UnifiedProblem>)
328 }
329 ("telecommunications", "network") => {
330 let problem = self.create_telecom_network(config)?;
331 Ok(Box::new(problem) as Box<dyn UnifiedProblem>)
332 }
333 ("energy", "grid") => {
334 let problem = self.create_energy_grid(config)?;
335 Ok(Box::new(problem) as Box<dyn UnifiedProblem>)
336 }
337 ("manufacturing", "scheduling") => {
338 let problem = self.create_manufacturing_scheduling(config)?;
339 Ok(Box::new(problem) as Box<dyn UnifiedProblem>)
340 }
341 ("healthcare", "resource") => {
342 let problem = self.create_healthcare_resource(config)?;
343 Ok(Box::new(problem) as Box<dyn UnifiedProblem>)
344 }
345 _ => Err(ApplicationError::InvalidConfiguration(format!(
346 "Unknown problem type: {industry} / {problem_type}"
347 ))),
348 }
349 }
350
351 pub fn solve_problem(
353 &self,
354 problem: &dyn UnifiedProblem,
355 custom_config: Option<SolverConfiguration>,
356 ) -> ApplicationResult<UnifiedSolution> {
357 let config = custom_config.unwrap_or_else(|| self.get_recommended_config(problem));
359
360 problem.validate()?;
362
363 let (qubo_model, _var_map) = problem.to_qubo()?;
365
366 let result = match config.solver_type {
368 SolverType::Classical => self.solve_classical(&qubo_model, &config.annealing_params)?,
369 SolverType::QuantumSimulator => {
370 self.solve_quantum_simulator(&qubo_model, &config.annealing_params)?
371 }
372 SolverType::Hybrid => self.solve_hybrid(&qubo_model, &config.annealing_params)?,
373 _ => {
374 return Err(ApplicationError::OptimizationError(
375 "Solver type not yet implemented".to_string(),
376 ))
377 }
378 };
379
380 Ok(UnifiedSolution::Binary(result.best_spins))
382 }
383
384 fn get_recommended_config(&self, problem: &dyn UnifiedProblem) -> SolverConfiguration {
386 let mut config = self
388 .default_configs
389 .get(&problem.category())
390 .cloned()
391 .unwrap_or_else(|| problem.recommended_solver_config());
392
393 self.adjust_config_for_complexity(&mut config, problem.complexity());
395
396 config
397 }
398
399 fn adjust_config_for_complexity(
401 &self,
402 config: &mut SolverConfiguration,
403 complexity: ProblemComplexity,
404 ) {
405 match complexity {
406 ProblemComplexity::Small => {
407 config.annealing_params.num_sweeps = config.annealing_params.num_sweeps.min(5000);
408 config.annealing_params.num_repetitions =
409 config.annealing_params.num_repetitions.min(10);
410 }
411 ProblemComplexity::Medium => {
412 }
414 ProblemComplexity::Large => {
415 config.annealing_params.num_sweeps = config.annealing_params.num_sweeps.max(20_000);
416 config.annealing_params.num_repetitions =
417 config.annealing_params.num_repetitions.max(30);
418 config.hardware_requirements.min_memory_gb *= 2.0;
419 }
420 ProblemComplexity::ExtraLarge => {
421 config.annealing_params.num_sweeps = config.annealing_params.num_sweeps.max(50_000);
422 config.annealing_params.num_repetitions =
423 config.annealing_params.num_repetitions.max(50);
424 config.hardware_requirements.min_memory_gb *= 4.0;
425 config.solver_type = SolverType::Hybrid; }
427 }
428 }
429
430 fn solve_classical(
432 &self,
433 qubo_model: &crate::ising::QuboModel,
434 params: &AnnealingParams,
435 ) -> ApplicationResult<crate::simulator::AnnealingSolution> {
436 let ising = IsingModel::from_qubo(qubo_model);
437
438 let simulator = ClassicalAnnealingSimulator::new(params.clone())
439 .map_err(|e| ApplicationError::OptimizationError(e.to_string()))?;
440
441 simulator
442 .solve(&ising)
443 .map_err(|e| ApplicationError::OptimizationError(e.to_string()))
444 }
445
446 fn solve_quantum_simulator(
448 &self,
449 qubo_model: &crate::ising::QuboModel,
450 params: &AnnealingParams,
451 ) -> ApplicationResult<crate::simulator::AnnealingSolution> {
452 let ising = IsingModel::from_qubo(qubo_model);
453
454 let simulator = QuantumAnnealingSimulator::new(params.clone())
455 .map_err(|e| ApplicationError::OptimizationError(e.to_string()))?;
456
457 simulator
458 .solve(&ising)
459 .map_err(|e| ApplicationError::OptimizationError(e.to_string()))
460 }
461
462 fn solve_hybrid(
464 &self,
465 qubo_model: &crate::ising::QuboModel,
466 params: &AnnealingParams,
467 ) -> ApplicationResult<crate::simulator::AnnealingSolution> {
468 self.solve_classical(qubo_model, params)
471 }
472
473 fn create_finance_portfolio(
475 &self,
476 config: HashMap<String, serde_json::Value>,
477 ) -> ApplicationResult<UnifiedPortfolioOptimization> {
478 let num_assets = config
480 .get("num_assets")
481 .and_then(serde_json::Value::as_u64)
482 .unwrap_or(10) as usize;
483
484 let budget = config
485 .get("budget")
486 .and_then(serde_json::Value::as_f64)
487 .unwrap_or(1_000_000.0);
488
489 let risk_tolerance = config
490 .get("risk_tolerance")
491 .and_then(serde_json::Value::as_f64)
492 .unwrap_or(0.5);
493
494 let expected_returns: Vec<f64> = (0..num_assets)
496 .map(|i| 0.03 + 0.07 * (i as f64) / (num_assets as f64))
497 .collect();
498
499 let covariance_matrix = self.create_sample_covariance_matrix(num_assets, 0.2);
500
501 let portfolio = finance::PortfolioOptimization::new(
502 expected_returns,
503 covariance_matrix,
504 budget,
505 risk_tolerance,
506 )?;
507
508 Ok(UnifiedPortfolioOptimization { inner: portfolio })
509 }
510
511 fn create_logistics_vrp(
513 &self,
514 config: HashMap<String, serde_json::Value>,
515 ) -> ApplicationResult<UnifiedVehicleRoutingProblem> {
516 let num_vehicles = config
517 .get("num_vehicles")
518 .and_then(serde_json::Value::as_u64)
519 .unwrap_or(3) as usize;
520
521 let num_customers = config
522 .get("num_customers")
523 .and_then(serde_json::Value::as_u64)
524 .unwrap_or(10) as usize;
525
526 let mut locations = vec![(0.0, 0.0)]; let mut demands = vec![0.0]; for i in 0..num_customers {
531 let angle = 2.0 * std::f64::consts::PI * i as f64 / num_customers as f64;
532 let radius = (i as f64).mul_add(0.1, 1.0);
533 locations.push((radius * angle.cos(), radius * angle.sin()));
534 demands.push((i as f64).mul_add(2.0, 5.0));
535 }
536
537 let capacities = vec![50.0; num_vehicles];
538
539 let vrp =
540 logistics::VehicleRoutingProblem::new(num_vehicles, capacities, locations, demands)?;
541
542 Ok(UnifiedVehicleRoutingProblem { inner: vrp })
543 }
544
545 fn create_telecom_network(
547 &self,
548 config: HashMap<String, serde_json::Value>,
549 ) -> ApplicationResult<UnifiedNetworkTopologyOptimization> {
550 let num_nodes = config
551 .get("num_nodes")
552 .and_then(serde_json::Value::as_u64)
553 .unwrap_or(6) as usize;
554
555 let mut potential_connections = Vec::new();
557 let mut connection_costs = Vec::new();
558
559 for i in 0..num_nodes {
560 for j in (i + 1)..num_nodes {
561 potential_connections.push((i, j));
562 connection_costs.push(((i + j) as f64).mul_add(1.5, 5.0));
563 }
564 }
565
566 let traffic_demands = vec![vec![2.0; num_nodes]; num_nodes];
567
568 let network = telecommunications::NetworkTopologyOptimization::new(
569 num_nodes,
570 potential_connections,
571 connection_costs,
572 traffic_demands,
573 )?;
574
575 Ok(UnifiedNetworkTopologyOptimization { inner: network })
576 }
577
578 fn create_energy_grid(
580 &self,
581 _config: HashMap<String, serde_json::Value>,
582 ) -> ApplicationResult<UnifiedEnergyGridOptimization> {
583 Err(ApplicationError::InvalidConfiguration(
585 "Energy grid problem creation not yet implemented".to_string(),
586 ))
587 }
588
589 fn create_manufacturing_scheduling(
591 &self,
592 _config: HashMap<String, serde_json::Value>,
593 ) -> ApplicationResult<UnifiedManufacturingScheduling> {
594 Err(ApplicationError::InvalidConfiguration(
596 "Manufacturing scheduling problem creation not yet implemented".to_string(),
597 ))
598 }
599
600 fn create_healthcare_resource(
602 &self,
603 _config: HashMap<String, serde_json::Value>,
604 ) -> ApplicationResult<UnifiedHealthcareResourceOptimization> {
605 Err(ApplicationError::InvalidConfiguration(
607 "Healthcare resource problem creation not yet implemented".to_string(),
608 ))
609 }
610
611 fn create_sample_covariance_matrix(&self, n: usize, base_volatility: f64) -> Vec<Vec<f64>> {
613 let mut matrix = vec![vec![0.0; n]; n];
614
615 for i in 0..n {
616 for j in 0..n {
617 if i == j {
618 matrix[i][j] =
619 base_volatility * base_volatility * (1.0 + 0.5 * (i as f64) / (n as f64));
620 } else {
621 let correlation = 0.1 * (1.0 - (i as f64 - j as f64).abs() / (n as f64));
622 let vol_i = (matrix[i][i]).sqrt();
623 let vol_j = (matrix[j][j]).sqrt();
624 matrix[i][j] = correlation * vol_i * vol_j;
625 }
626 }
627 }
628
629 matrix
630 }
631}
632
633#[derive(Debug, Clone)]
637pub struct ConvergenceInfo {
638 pub converged: bool,
640 pub final_energy: f64,
642 pub energy_variance: f64,
644 pub acceptance_rate: f64,
646}
647
648#[derive(Debug, Clone)]
650pub struct ProblemInfo {
651 pub industry: String,
653 pub category: ProblemCategory,
655 pub complexity: ProblemComplexity,
657 pub num_variables: usize,
659 pub num_constraints: usize,
661}
662
663#[derive(Debug, Clone)]
668pub struct UnifiedPortfolioOptimization {
669 inner: finance::PortfolioOptimization,
670}
671
672#[derive(Debug, Clone)]
674pub struct UnifiedVehicleRoutingProblem {
675 inner: logistics::VehicleRoutingProblem,
676}
677
678#[derive(Debug, Clone)]
680pub struct UnifiedNetworkTopologyOptimization {
681 inner: telecommunications::NetworkTopologyOptimization,
682}
683
684#[derive(Debug, Clone)]
686pub struct UnifiedEnergyGridOptimization {
687 }
689
690#[derive(Debug, Clone)]
691pub struct UnifiedManufacturingScheduling {
692 }
694
695#[derive(Debug, Clone)]
696pub struct UnifiedHealthcareResourceOptimization {
697 }
699
700impl OptimizationProblem for UnifiedPortfolioOptimization {
704 type Solution = UnifiedSolution;
705 type ObjectiveValue = f64;
706
707 fn description(&self) -> String {
708 self.inner.description()
709 }
710
711 fn size_metrics(&self) -> HashMap<String, usize> {
712 self.inner.size_metrics()
713 }
714
715 fn validate(&self) -> ApplicationResult<()> {
716 self.inner.validate()
717 }
718
719 fn to_qubo(&self) -> ApplicationResult<(crate::ising::QuboModel, HashMap<String, usize>)> {
720 self.inner.to_qubo()
721 }
722
723 fn evaluate_solution(
724 &self,
725 solution: &Self::Solution,
726 ) -> ApplicationResult<Self::ObjectiveValue> {
727 match solution {
728 UnifiedSolution::Binary(binary_sol) => {
729 let num_assets = binary_sol.len();
732 let weights: Vec<f64> = binary_sol
733 .iter()
734 .map(|&x| if x == 1 { 1.0 / num_assets as f64 } else { 0.0 })
735 .collect();
736 let portfolio_sol = finance::PortfolioSolution {
737 weights,
738 metrics: finance::PortfolioMetrics {
739 expected_return: 0.0,
740 volatility: 0.0,
741 sharpe_ratio: 0.0,
742 max_drawdown: 0.0,
743 var_95: 0.0,
744 cvar_95: 0.0,
745 },
746 };
747 self.inner.evaluate_solution(&portfolio_sol)
748 }
749 UnifiedSolution::Custom(_) => {
750 Err(ApplicationError::OptimizationError(
752 "Custom solution format not supported for portfolio optimization".to_string(),
753 ))
754 }
755 _ => Err(ApplicationError::OptimizationError(
756 "Unsupported solution type for portfolio optimization".to_string(),
757 )),
758 }
759 }
760
761 fn is_feasible(&self, solution: &Self::Solution) -> bool {
762 match solution {
763 UnifiedSolution::Binary(binary_sol) => {
764 let num_assets = binary_sol.len();
766 let weights: Vec<f64> = binary_sol
767 .iter()
768 .map(|&x| if x == 1 { 1.0 / num_assets as f64 } else { 0.0 })
769 .collect();
770 let portfolio_sol = finance::PortfolioSolution {
771 weights,
772 metrics: finance::PortfolioMetrics {
773 expected_return: 0.0,
774 volatility: 0.0,
775 sharpe_ratio: 0.0,
776 max_drawdown: 0.0,
777 var_95: 0.0,
778 cvar_95: 0.0,
779 },
780 };
781 self.inner.is_feasible(&portfolio_sol)
782 }
783 UnifiedSolution::Custom(_) => {
784 false
786 }
787 _ => false,
788 }
789 }
790}
791
792impl UnifiedProblem for UnifiedPortfolioOptimization {
793 fn category(&self) -> ProblemCategory {
794 ProblemCategory::Portfolio
795 }
796
797 fn industry(&self) -> &'static str {
798 "finance"
799 }
800
801 fn complexity(&self) -> ProblemComplexity {
802 let num_assets = self.inner.expected_returns.len();
803 match num_assets {
804 0..=10 => ProblemComplexity::Small,
805 11..=50 => ProblemComplexity::Medium,
806 51..=200 => ProblemComplexity::Large,
807 _ => ProblemComplexity::ExtraLarge,
808 }
809 }
810
811 fn recommended_solver_config(&self) -> SolverConfiguration {
812 SolverConfiguration {
813 solver_type: SolverType::Classical,
814 annealing_params: AnnealingParams {
815 num_sweeps: 10_000,
816 num_repetitions: 20,
817 initial_temperature: 2.0,
818 final_temperature: 0.01,
819 ..Default::default()
820 },
821 hardware_requirements: HardwareRequirements {
822 min_memory_gb: 2.0,
823 recommended_cores: 4,
824 gpu_acceleration: false,
825 quantum_hardware: false,
826 },
827 optimization_hints: vec![OptimizationHint::HighPrecision],
828 }
829 }
830
831 fn constraints(&self) -> Vec<IndustryConstraint> {
832 let mut constraints = vec![IndustryConstraint::Budget {
833 limit: self.inner.budget,
834 }];
835
836 constraints.extend(self.inner.regulatory_constraints.clone());
838
839 constraints
840 }
841
842 fn objective(&self) -> IndustryObjective {
843 IndustryObjective::MultiObjective(vec![
844 (IndustryObjective::MaximizeProfit, 1.0),
845 (IndustryObjective::MinimizeRisk, self.inner.risk_tolerance),
846 ])
847 }
848
849 fn solution_bounds(&self) -> Option<(f64, f64)> {
850 let max_return: f64 = self.inner.expected_returns.iter().sum();
852 let min_return = self
853 .inner
854 .expected_returns
855 .iter()
856 .fold(0.0f64, |a, &b| a.min(b));
857 Some((min_return, max_return))
858 }
859
860 fn as_any(&self) -> &dyn Any {
861 self
862 }
863
864 fn clone_unified(&self) -> Box<dyn UnifiedProblem> {
865 Box::new(self.clone())
866 }
867}
868
869impl OptimizationProblem for UnifiedVehicleRoutingProblem {
871 type Solution = UnifiedSolution;
872 type ObjectiveValue = f64;
873
874 fn description(&self) -> String {
875 self.inner.description()
876 }
877
878 fn size_metrics(&self) -> HashMap<String, usize> {
879 self.inner.size_metrics()
880 }
881
882 fn validate(&self) -> ApplicationResult<()> {
883 self.inner.validate()
884 }
885
886 fn to_qubo(&self) -> ApplicationResult<(crate::ising::QuboModel, HashMap<String, usize>)> {
887 self.inner.to_qubo()
888 }
889
890 fn evaluate_solution(
891 &self,
892 solution: &Self::Solution,
893 ) -> ApplicationResult<Self::ObjectiveValue> {
894 match solution {
895 UnifiedSolution::Binary(binary_sol) => {
896 let route: Vec<usize> = binary_sol
898 .iter()
899 .enumerate()
900 .filter(|(_, &x)| x == 1)
901 .map(|(i, _)| i)
902 .collect();
903 let route_stats = logistics::RouteStatistics {
904 vehicle_id: 0,
905 distance: 0.0,
906 duration: 0.0,
907 capacity_utilization: 0.5,
908 customers_served: route.len(),
909 time_violations: 0,
910 };
911 let route_sol = logistics::VehicleRoutingSolution {
912 routes: vec![route],
913 total_distance: 0.0,
914 total_cost: 0.0,
915 route_stats: vec![route_stats],
916 };
917 self.inner.evaluate_solution(&route_sol)
918 }
919 _ => Err(ApplicationError::OptimizationError(
920 "Unsupported solution type for VRP".to_string(),
921 )),
922 }
923 }
924
925 fn is_feasible(&self, solution: &Self::Solution) -> bool {
926 match solution {
927 UnifiedSolution::Binary(binary_sol) => {
928 let route: Vec<usize> = binary_sol
929 .iter()
930 .enumerate()
931 .filter(|(_, &x)| x == 1)
932 .map(|(i, _)| i)
933 .collect();
934 let route_stats = logistics::RouteStatistics {
935 vehicle_id: 0,
936 distance: 0.0,
937 duration: 0.0,
938 capacity_utilization: 0.5,
939 customers_served: route.len(),
940 time_violations: 0,
941 };
942 let route_sol = logistics::VehicleRoutingSolution {
943 routes: vec![route],
944 total_distance: 0.0,
945 total_cost: 0.0,
946 route_stats: vec![route_stats],
947 };
948 self.inner.is_feasible(&route_sol)
949 }
950 _ => false,
951 }
952 }
953}
954
955impl UnifiedProblem for UnifiedVehicleRoutingProblem {
956 fn category(&self) -> ProblemCategory {
957 ProblemCategory::Routing
958 }
959
960 fn industry(&self) -> &'static str {
961 "logistics"
962 }
963
964 fn complexity(&self) -> ProblemComplexity {
965 let num_locations = self.inner.locations.len();
966 match num_locations {
967 0..=20 => ProblemComplexity::Small,
968 21..=100 => ProblemComplexity::Medium,
969 101..=500 => ProblemComplexity::Large,
970 _ => ProblemComplexity::ExtraLarge,
971 }
972 }
973
974 fn recommended_solver_config(&self) -> SolverConfiguration {
975 SolverConfiguration {
976 solver_type: SolverType::Hybrid,
977 annealing_params: AnnealingParams::default(),
978 hardware_requirements: HardwareRequirements {
979 min_memory_gb: 4.0,
980 recommended_cores: 8,
981 gpu_acceleration: true,
982 quantum_hardware: false,
983 },
984 optimization_hints: vec![OptimizationHint::MultiModal],
985 }
986 }
987
988 fn constraints(&self) -> Vec<IndustryConstraint> {
989 vec![IndustryConstraint::Capacity {
990 resource: "vehicle".to_string(),
991 limit: 100.0,
992 }]
993 }
994
995 fn objective(&self) -> IndustryObjective {
996 IndustryObjective::MinimizeCost
997 }
998
999 fn solution_bounds(&self) -> Option<(f64, f64)> {
1000 Some((0.0, 1000.0)) }
1002
1003 fn as_any(&self) -> &dyn Any {
1004 self
1005 }
1006
1007 fn clone_unified(&self) -> Box<dyn UnifiedProblem> {
1008 Box::new(self.clone())
1009 }
1010}
1011
1012impl OptimizationProblem for UnifiedNetworkTopologyOptimization {
1014 type Solution = UnifiedSolution;
1015 type ObjectiveValue = f64;
1016
1017 fn description(&self) -> String {
1018 self.inner.description()
1019 }
1020
1021 fn size_metrics(&self) -> HashMap<String, usize> {
1022 self.inner.size_metrics()
1023 }
1024
1025 fn validate(&self) -> ApplicationResult<()> {
1026 self.inner.validate()
1027 }
1028
1029 fn to_qubo(&self) -> ApplicationResult<(crate::ising::QuboModel, HashMap<String, usize>)> {
1030 self.inner.to_qubo()
1031 }
1032
1033 fn evaluate_solution(
1034 &self,
1035 solution: &Self::Solution,
1036 ) -> ApplicationResult<Self::ObjectiveValue> {
1037 match solution {
1038 UnifiedSolution::Binary(binary_sol) => {
1039 let network_topology = telecommunications::NetworkTopology {
1040 active_connections: binary_sol.iter().map(|&x| x == 1).collect(),
1041 total_cost: 0.0,
1042 connectivity: 0.8,
1043 average_latency: 10.0,
1044 performance_metrics: telecommunications::TelecomMetrics {
1045 throughput: 10.0,
1046 packet_loss_rate: 0.01,
1047 jitter: 5.0,
1048 availability: 0.99,
1049 mtbf: 1000.0,
1050 coverage_area: 100.0,
1051 },
1052 };
1053 self.inner.evaluate_solution(&network_topology)
1054 }
1055 _ => Err(ApplicationError::OptimizationError(
1056 "Unsupported solution type for network optimization".to_string(),
1057 )),
1058 }
1059 }
1060
1061 fn is_feasible(&self, solution: &Self::Solution) -> bool {
1062 match solution {
1063 UnifiedSolution::Binary(binary_sol) => {
1064 let network_topology = telecommunications::NetworkTopology {
1065 active_connections: binary_sol.iter().map(|&x| x == 1).collect(),
1066 total_cost: 0.0,
1067 connectivity: 0.8,
1068 average_latency: 10.0,
1069 performance_metrics: telecommunications::TelecomMetrics {
1070 throughput: 10.0,
1071 packet_loss_rate: 0.01,
1072 jitter: 5.0,
1073 availability: 0.99,
1074 mtbf: 1000.0,
1075 coverage_area: 100.0,
1076 },
1077 };
1078 self.inner.is_feasible(&network_topology)
1079 }
1080 _ => false,
1081 }
1082 }
1083}
1084
1085impl UnifiedProblem for UnifiedNetworkTopologyOptimization {
1086 fn category(&self) -> ProblemCategory {
1087 ProblemCategory::NetworkDesign
1088 }
1089
1090 fn industry(&self) -> &'static str {
1091 "telecommunications"
1092 }
1093
1094 fn complexity(&self) -> ProblemComplexity {
1095 ProblemComplexity::Medium }
1097
1098 fn recommended_solver_config(&self) -> SolverConfiguration {
1099 SolverConfiguration {
1100 solver_type: SolverType::QuantumSimulator,
1101 annealing_params: AnnealingParams::default(),
1102 hardware_requirements: HardwareRequirements {
1103 min_memory_gb: 8.0,
1104 recommended_cores: 16,
1105 gpu_acceleration: true,
1106 quantum_hardware: false,
1107 },
1108 optimization_hints: vec![OptimizationHint::SparseStructure],
1109 }
1110 }
1111
1112 fn constraints(&self) -> Vec<IndustryConstraint> {
1113 vec![]
1114 }
1115
1116 fn objective(&self) -> IndustryObjective {
1117 IndustryObjective::MinimizeCost
1118 }
1119
1120 fn solution_bounds(&self) -> Option<(f64, f64)> {
1121 Some((0.0, 500.0))
1122 }
1123
1124 fn as_any(&self) -> &dyn Any {
1125 self
1126 }
1127
1128 fn clone_unified(&self) -> Box<dyn UnifiedProblem> {
1129 Box::new(self.clone())
1130 }
1131}
1132
1133impl OptimizationProblem for UnifiedEnergyGridOptimization {
1135 type Solution = UnifiedSolution;
1136 type ObjectiveValue = f64;
1137
1138 fn description(&self) -> String {
1139 "Energy grid optimization problem".to_string()
1140 }
1141
1142 fn size_metrics(&self) -> HashMap<String, usize> {
1143 HashMap::new()
1144 }
1145
1146 fn validate(&self) -> ApplicationResult<()> {
1147 Ok(())
1148 }
1149
1150 fn to_qubo(&self) -> ApplicationResult<(crate::ising::QuboModel, HashMap<String, usize>)> {
1151 Err(ApplicationError::OptimizationError(
1152 "Energy grid QUBO not implemented".to_string(),
1153 ))
1154 }
1155
1156 fn evaluate_solution(
1157 &self,
1158 _solution: &Self::Solution,
1159 ) -> ApplicationResult<Self::ObjectiveValue> {
1160 Ok(0.0)
1161 }
1162
1163 fn is_feasible(&self, _solution: &Self::Solution) -> bool {
1164 true
1165 }
1166}
1167
1168impl UnifiedProblem for UnifiedEnergyGridOptimization {
1169 fn category(&self) -> ProblemCategory {
1170 ProblemCategory::ResourceAllocation
1171 }
1172
1173 fn industry(&self) -> &'static str {
1174 "energy"
1175 }
1176
1177 fn complexity(&self) -> ProblemComplexity {
1178 ProblemComplexity::Medium
1179 }
1180
1181 fn recommended_solver_config(&self) -> SolverConfiguration {
1182 SolverConfiguration {
1183 solver_type: SolverType::Classical,
1184 annealing_params: AnnealingParams::default(),
1185 hardware_requirements: HardwareRequirements {
1186 min_memory_gb: 4.0,
1187 recommended_cores: 8,
1188 gpu_acceleration: false,
1189 quantum_hardware: false,
1190 },
1191 optimization_hints: vec![],
1192 }
1193 }
1194
1195 fn constraints(&self) -> Vec<IndustryConstraint> {
1196 vec![]
1197 }
1198
1199 fn objective(&self) -> IndustryObjective {
1200 IndustryObjective::MinimizeCost
1201 }
1202
1203 fn solution_bounds(&self) -> Option<(f64, f64)> {
1204 Some((0.0, 100.0))
1205 }
1206
1207 fn as_any(&self) -> &dyn Any {
1208 self
1209 }
1210
1211 fn clone_unified(&self) -> Box<dyn UnifiedProblem> {
1212 Box::new(self.clone())
1213 }
1214}
1215
1216impl OptimizationProblem for UnifiedManufacturingScheduling {
1217 type Solution = UnifiedSolution;
1218 type ObjectiveValue = f64;
1219
1220 fn description(&self) -> String {
1221 "Manufacturing scheduling problem".to_string()
1222 }
1223
1224 fn size_metrics(&self) -> HashMap<String, usize> {
1225 HashMap::new()
1226 }
1227
1228 fn validate(&self) -> ApplicationResult<()> {
1229 Ok(())
1230 }
1231
1232 fn to_qubo(&self) -> ApplicationResult<(crate::ising::QuboModel, HashMap<String, usize>)> {
1233 Err(ApplicationError::OptimizationError(
1234 "Manufacturing QUBO not implemented".to_string(),
1235 ))
1236 }
1237
1238 fn evaluate_solution(
1239 &self,
1240 _solution: &Self::Solution,
1241 ) -> ApplicationResult<Self::ObjectiveValue> {
1242 Ok(0.0)
1243 }
1244
1245 fn is_feasible(&self, _solution: &Self::Solution) -> bool {
1246 true
1247 }
1248}
1249
1250impl UnifiedProblem for UnifiedManufacturingScheduling {
1251 fn category(&self) -> ProblemCategory {
1252 ProblemCategory::ResourceAllocation
1253 }
1254
1255 fn industry(&self) -> &'static str {
1256 "manufacturing"
1257 }
1258
1259 fn complexity(&self) -> ProblemComplexity {
1260 ProblemComplexity::Medium
1261 }
1262
1263 fn recommended_solver_config(&self) -> SolverConfiguration {
1264 SolverConfiguration {
1265 solver_type: SolverType::Classical,
1266 annealing_params: AnnealingParams::default(),
1267 hardware_requirements: HardwareRequirements {
1268 min_memory_gb: 2.0,
1269 recommended_cores: 4,
1270 gpu_acceleration: false,
1271 quantum_hardware: false,
1272 },
1273 optimization_hints: vec![],
1274 }
1275 }
1276
1277 fn constraints(&self) -> Vec<IndustryConstraint> {
1278 vec![]
1279 }
1280
1281 fn objective(&self) -> IndustryObjective {
1282 IndustryObjective::MaximizeEfficiency
1283 }
1284
1285 fn solution_bounds(&self) -> Option<(f64, f64)> {
1286 Some((0.0, 100.0))
1287 }
1288
1289 fn as_any(&self) -> &dyn Any {
1290 self
1291 }
1292
1293 fn clone_unified(&self) -> Box<dyn UnifiedProblem> {
1294 Box::new(self.clone())
1295 }
1296}
1297
1298impl OptimizationProblem for UnifiedHealthcareResourceOptimization {
1299 type Solution = UnifiedSolution;
1300 type ObjectiveValue = f64;
1301
1302 fn description(&self) -> String {
1303 "Healthcare resource optimization problem".to_string()
1304 }
1305
1306 fn size_metrics(&self) -> HashMap<String, usize> {
1307 HashMap::new()
1308 }
1309
1310 fn validate(&self) -> ApplicationResult<()> {
1311 Ok(())
1312 }
1313
1314 fn to_qubo(&self) -> ApplicationResult<(crate::ising::QuboModel, HashMap<String, usize>)> {
1315 Err(ApplicationError::OptimizationError(
1316 "Healthcare QUBO not implemented".to_string(),
1317 ))
1318 }
1319
1320 fn evaluate_solution(
1321 &self,
1322 _solution: &Self::Solution,
1323 ) -> ApplicationResult<Self::ObjectiveValue> {
1324 Ok(0.0)
1325 }
1326
1327 fn is_feasible(&self, _solution: &Self::Solution) -> bool {
1328 true
1329 }
1330}
1331
1332impl UnifiedProblem for UnifiedHealthcareResourceOptimization {
1333 fn category(&self) -> ProblemCategory {
1334 ProblemCategory::ResourceAllocation
1335 }
1336
1337 fn industry(&self) -> &'static str {
1338 "healthcare"
1339 }
1340
1341 fn complexity(&self) -> ProblemComplexity {
1342 ProblemComplexity::Medium
1343 }
1344
1345 fn recommended_solver_config(&self) -> SolverConfiguration {
1346 SolverConfiguration {
1347 solver_type: SolverType::Classical,
1348 annealing_params: AnnealingParams::default(),
1349 hardware_requirements: HardwareRequirements {
1350 min_memory_gb: 2.0,
1351 recommended_cores: 4,
1352 gpu_acceleration: false,
1353 quantum_hardware: false,
1354 },
1355 optimization_hints: vec![],
1356 }
1357 }
1358
1359 fn constraints(&self) -> Vec<IndustryConstraint> {
1360 vec![]
1361 }
1362
1363 fn objective(&self) -> IndustryObjective {
1364 IndustryObjective::MaximizeEfficiency
1365 }
1366
1367 fn solution_bounds(&self) -> Option<(f64, f64)> {
1368 Some((0.0, 100.0))
1369 }
1370
1371 fn as_any(&self) -> &dyn Any {
1372 self
1373 }
1374
1375 fn clone_unified(&self) -> Box<dyn UnifiedProblem> {
1376 Box::new(self.clone())
1377 }
1378}
1379
1380pub fn run_unified_benchmark(
1382 factory: &UnifiedSolverFactory,
1383 industry: &str,
1384 problem_sizes: Vec<usize>,
1385) -> ApplicationResult<UnifiedBenchmarkResults> {
1386 let mut results = UnifiedBenchmarkResults::new();
1387
1388 for size in problem_sizes {
1389 let problems = super::create_benchmark_suite(industry, &format!("{size}"))?;
1391
1392 for (i, problem) in problems.iter().enumerate() {
1393 let start_time = std::time::Instant::now();
1394
1395 let solve_time = start_time.elapsed().as_secs_f64() * 1000.0;
1398
1399 results.add_result(
1400 format!("{industry}_{size}_problem_{i}"),
1401 solve_time,
1402 0.0,
1403 true,
1404 );
1405 }
1406 }
1407
1408 Ok(results)
1409}
1410
1411#[derive(Debug, Clone)]
1413pub struct UnifiedBenchmarkResults {
1414 pub results: HashMap<String, BenchmarkResult>,
1416 pub statistics: BenchmarkStatistics,
1418}
1419
1420impl UnifiedBenchmarkResults {
1421 fn new() -> Self {
1422 Self {
1423 results: HashMap::new(),
1424 statistics: BenchmarkStatistics::default(),
1425 }
1426 }
1427
1428 fn add_result(
1429 &mut self,
1430 problem_id: String,
1431 solve_time: f64,
1432 objective_value: f64,
1433 converged: bool,
1434 ) {
1435 let result = BenchmarkResult {
1436 solve_time_ms: solve_time,
1437 objective_value,
1438 converged,
1439 };
1440
1441 self.results.insert(problem_id, result);
1442 self.update_statistics();
1443 }
1444
1445 fn update_statistics(&mut self) {
1446 let solve_times: Vec<f64> = self.results.values().map(|r| r.solve_time_ms).collect();
1447 let convergence_rate = self.results.values().filter(|r| r.converged).count() as f64
1448 / self.results.len() as f64;
1449
1450 self.statistics = BenchmarkStatistics {
1451 avg_solve_time: solve_times.iter().sum::<f64>() / solve_times.len() as f64,
1452 min_solve_time: solve_times.iter().fold(f64::INFINITY, |a, &b| a.min(b)),
1453 max_solve_time: solve_times.iter().fold(0.0, |a, &b| a.max(b)),
1454 convergence_rate,
1455 total_problems_solved: self.results.len(),
1456 };
1457 }
1458}
1459
1460#[derive(Debug, Clone)]
1462pub struct BenchmarkResult {
1463 pub solve_time_ms: f64,
1464 pub objective_value: f64,
1465 pub converged: bool,
1466}
1467
1468#[derive(Debug, Clone, Default)]
1470pub struct BenchmarkStatistics {
1471 pub avg_solve_time: f64,
1472 pub min_solve_time: f64,
1473 pub max_solve_time: f64,
1474 pub convergence_rate: f64,
1475 pub total_problems_solved: usize,
1476}
1477
1478#[cfg(test)]
1479mod tests {
1480 use super::*;
1481 use serde_json::json;
1482
1483 #[test]
1484 fn test_solver_factory_creation() {
1485 let factory = UnifiedSolverFactory::new();
1486 assert!(!factory.default_configs.is_empty());
1487 assert!(factory.available_solvers.contains(&SolverType::Classical));
1488 }
1489
1490 #[test]
1491 fn test_problem_creation() {
1492 let factory = UnifiedSolverFactory::new();
1493 let config = HashMap::from([
1494 ("num_assets".to_string(), json!(5)),
1495 ("budget".to_string(), json!(100_000.0)),
1496 ("risk_tolerance".to_string(), json!(0.3)),
1497 ]);
1498
1499 let problem = factory.create_problem("finance", "portfolio", config);
1500 assert!(problem.is_ok());
1501
1502 let unified_problem = problem.expect("problem creation should succeed");
1503 assert_eq!(unified_problem.industry(), "finance");
1504 assert_eq!(unified_problem.category(), ProblemCategory::Portfolio);
1505 }
1506
1507 #[test]
1508 fn test_complexity_classification() {
1509 let factory = UnifiedSolverFactory::new();
1510 let config = HashMap::from([("num_assets".to_string(), json!(5))]);
1511
1512 let problem = factory
1513 .create_problem("finance", "portfolio", config)
1514 .expect("problem creation should succeed");
1515 assert_eq!(problem.complexity(), ProblemComplexity::Small);
1516 }
1517
1518 #[test]
1519 fn test_solver_configuration_adjustment() {
1520 let factory = UnifiedSolverFactory::new();
1521 let mut config = SolverConfiguration {
1522 solver_type: SolverType::Classical,
1523 annealing_params: AnnealingParams::default(),
1524 hardware_requirements: HardwareRequirements {
1525 min_memory_gb: 1.0,
1526 recommended_cores: 2,
1527 gpu_acceleration: false,
1528 quantum_hardware: false,
1529 },
1530 optimization_hints: vec![],
1531 };
1532
1533 factory.adjust_config_for_complexity(&mut config, ProblemComplexity::Large);
1534 assert!(config.annealing_params.num_sweeps >= 20_000);
1535 assert!(config.hardware_requirements.min_memory_gb >= 2.0);
1536 }
1537}