Skip to main content

quantrs2_anneal/applications/
mod.rs

1//! Industry-Specific Optimization Libraries
2//!
3//! This module provides specialized optimization frameworks for various industries,
4//! leveraging quantum annealing techniques to solve real-world problems.
5//!
6//! # Available Industries
7//!
8//! - **Finance**: Portfolio optimization, risk management, fraud detection
9//! - **Logistics**: Vehicle routing, supply chain optimization, scheduling
10//! - **Energy**: Grid optimization, renewable energy management, load balancing
11//! - **Manufacturing**: Production scheduling, quality control, resource allocation
12//! - **Healthcare**: Treatment optimization, resource allocation, drug discovery
13//! - **Telecommunications**: Network optimization, traffic routing, infrastructure planning
14//! - **Transportation**: Vehicle routing, traffic flow optimization, smart city planning
15//!
16//! # Design Philosophy
17//!
18//! Each industry module provides:
19//! - Domain-specific problem formulations
20//! - Real-world constraints and objectives
21//! - Benchmark problems and datasets
22//! - Performance metrics relevant to the industry
23//! - Integration with quantum annealing solvers
24
25pub mod drug_discovery;
26pub mod energy;
27pub mod finance;
28pub mod healthcare;
29pub mod integration_tests;
30pub mod logistics;
31
32use drug_discovery::Molecule;
33use std::fmt::Write;
34pub mod manufacturing;
35pub mod materials_science;
36pub mod performance_benchmarks;
37pub mod protein_folding;
38pub mod quantum_computational_chemistry;
39pub mod scientific_computing_integration_tests;
40pub mod telecommunications;
41pub mod transportation;
42pub mod unified;
43
44use std::collections::HashMap;
45use thiserror::Error;
46
47/// Errors that can occur in industry applications
48#[derive(Error, Debug)]
49pub enum ApplicationError {
50    /// Invalid problem configuration
51    #[error("Invalid problem configuration: {0}")]
52    InvalidConfiguration(String),
53
54    /// Configuration error
55    #[error("Configuration error: {0}")]
56    ConfigurationError(String),
57
58    /// Constraint violation
59    #[error("Constraint violation: {0}")]
60    ConstraintViolation(String),
61
62    /// Optimization error
63    #[error("Optimization error: {0}")]
64    OptimizationError(String),
65
66    /// Data validation error
67    #[error("Data validation error: {0}")]
68    DataValidationError(String),
69
70    /// Resource limit exceeded
71    #[error("Resource limit exceeded: {0}")]
72    ResourceLimitExceeded(String),
73
74    /// Industry-specific error
75    #[error("Industry-specific error: {0}")]
76    IndustrySpecificError(String),
77}
78
79impl From<crate::ising::IsingError> for ApplicationError {
80    fn from(err: crate::ising::IsingError) -> Self {
81        Self::OptimizationError(format!("Ising model error: {err}"))
82    }
83}
84
85impl From<crate::advanced_quantum_algorithms::AdvancedQuantumError> for ApplicationError {
86    fn from(err: crate::advanced_quantum_algorithms::AdvancedQuantumError) -> Self {
87        Self::OptimizationError(format!("Advanced quantum algorithm error: {err}"))
88    }
89}
90
91impl From<crate::quantum_error_correction::QuantumErrorCorrectionError> for ApplicationError {
92    fn from(err: crate::quantum_error_correction::QuantumErrorCorrectionError) -> Self {
93        Self::OptimizationError(format!("Quantum error correction error: {err}"))
94    }
95}
96
97impl From<crate::simulator::AnnealingError> for ApplicationError {
98    fn from(err: crate::simulator::AnnealingError) -> Self {
99        Self::OptimizationError(format!("Annealing error: {err}"))
100    }
101}
102
103/// Result type for industry applications
104pub type ApplicationResult<T> = Result<T, ApplicationError>;
105
106/// Common traits for industry-specific problems
107
108/// Problem instance that can be solved with quantum annealing
109pub trait OptimizationProblem {
110    type Solution;
111    type ObjectiveValue;
112
113    /// Get problem description
114    fn description(&self) -> String;
115
116    /// Get problem size metrics
117    fn size_metrics(&self) -> HashMap<String, usize>;
118
119    /// Validate problem instance
120    fn validate(&self) -> ApplicationResult<()>;
121
122    /// Convert to QUBO formulation
123    fn to_qubo(&self) -> ApplicationResult<(crate::ising::QuboModel, HashMap<String, usize>)>;
124
125    /// Evaluate solution quality
126    fn evaluate_solution(
127        &self,
128        solution: &Self::Solution,
129    ) -> ApplicationResult<Self::ObjectiveValue>;
130
131    /// Check if solution satisfies all constraints
132    fn is_feasible(&self, solution: &Self::Solution) -> bool;
133}
134
135/// Solution that can be interpreted in industry context
136pub trait IndustrySolution {
137    type Problem;
138
139    /// Convert from binary solution vector
140    fn from_binary(problem: &Self::Problem, binary_solution: &[i8]) -> ApplicationResult<Self>
141    where
142        Self: Sized;
143
144    /// Get solution summary
145    fn summary(&self) -> HashMap<String, String>;
146
147    /// Get solution metrics
148    fn metrics(&self) -> HashMap<String, f64>;
149
150    /// Export solution in industry-standard format
151    fn export_format(&self) -> ApplicationResult<String>;
152}
153
154/// Performance benchmarking for industry problems
155pub trait Benchmarkable {
156    type BenchmarkResult;
157
158    /// Run benchmark suite
159    fn run_benchmark(&self) -> ApplicationResult<Self::BenchmarkResult>;
160
161    /// Compare against industry baselines
162    fn compare_baseline(&self, baseline: &Self::BenchmarkResult) -> HashMap<String, f64>;
163
164    /// Generate benchmark report
165    fn benchmark_report(&self, result: &Self::BenchmarkResult) -> String;
166}
167
168/// Common industry problem categories
169#[derive(Debug, Clone, PartialEq, Eq, Hash)]
170pub enum ProblemCategory {
171    /// Resource allocation and scheduling
172    ResourceAllocation,
173    /// Route and path optimization
174    Routing,
175    /// Portfolio and investment optimization
176    Portfolio,
177    /// Network design and optimization
178    NetworkDesign,
179    /// Supply chain optimization
180    SupplyChain,
181    /// Risk management and assessment
182    RiskManagement,
183    /// Quality control and testing
184    QualityControl,
185    /// Demand forecasting and planning
186    DemandPlanning,
187    /// Energy management and grid optimization
188    EnergyManagement,
189    /// Treatment and care optimization
190    TreatmentOptimization,
191}
192
193/// Industry-specific constraint types
194#[derive(Debug, Clone)]
195pub enum IndustryConstraint {
196    /// Resource capacity constraints
197    Capacity { resource: String, limit: f64 },
198    /// Time window constraints
199    TimeWindow { start: f64, end: f64 },
200    /// Budget constraints
201    Budget { limit: f64 },
202    /// Regulatory compliance constraints
203    Regulatory {
204        regulation: String,
205        requirement: String,
206    },
207    /// Quality requirements
208    Quality { metric: String, threshold: f64 },
209    /// Safety requirements
210    Safety { standard: String, level: f64 },
211    /// Custom constraint
212    Custom { name: String, description: String },
213}
214
215/// Common objective functions across industries
216#[derive(Debug, Clone)]
217pub enum IndustryObjective {
218    /// Minimize total cost
219    MinimizeCost,
220    /// Maximize profit/revenue
221    MaximizeProfit,
222    /// Minimize risk
223    MinimizeRisk,
224    /// Maximize efficiency
225    MaximizeEfficiency,
226    /// Minimize time/makespan
227    MinimizeTime,
228    /// Maximize quality
229    MaximizeQuality,
230    /// Minimize resource usage
231    MinimizeResourceUsage,
232    /// Maximize customer satisfaction
233    MaximizeSatisfaction,
234    /// Multi-objective combination
235    MultiObjective(Vec<(Self, f64)>), // (objective, weight)
236}
237
238/// Utility functions for industry applications
239
240/// Create standard benchmark problems for testing
241pub fn create_benchmark_suite(
242    industry: &str,
243    size: &str,
244) -> ApplicationResult<Vec<Box<dyn OptimizationProblem<Solution = Vec<i8>, ObjectiveValue = f64>>>>
245{
246    match (industry, size) {
247        ("finance", "small") => Ok(finance::create_benchmark_problems(10)?),
248        ("finance", "medium") => Ok(finance::create_benchmark_problems(50)?),
249        ("finance", "large") => Ok(finance::create_benchmark_problems(200)?),
250
251        ("logistics", "small") => Ok(logistics::create_benchmark_problems(5)?),
252        ("logistics", "medium") => Ok(logistics::create_benchmark_problems(20)?),
253        ("logistics", "large") => Ok(logistics::create_benchmark_problems(100)?),
254
255        ("energy", "small") => Ok(energy::create_benchmark_problems(8)?),
256        ("energy", "medium") => Ok(energy::create_benchmark_problems(30)?),
257        ("energy", "large") => Ok(energy::create_benchmark_problems(150)?),
258
259        ("transportation", "small") => Ok(transportation::create_benchmark_problems(5)?),
260        ("transportation", "medium") => Ok(transportation::create_benchmark_problems(15)?),
261        ("transportation", "large") => Ok(transportation::create_benchmark_problems(50)?),
262
263        ("manufacturing", "small") => Ok(manufacturing::create_benchmark_problems(5)?),
264        ("manufacturing", "medium") => Ok(manufacturing::create_benchmark_problems(15)?),
265        ("manufacturing", "large") => Ok(manufacturing::create_benchmark_problems(50)?),
266
267        ("healthcare", "small") => Ok(healthcare::create_benchmark_problems(5)?),
268        ("healthcare", "medium") => Ok(healthcare::create_benchmark_problems(15)?),
269        ("healthcare", "large") => Ok(healthcare::create_benchmark_problems(50)?),
270
271        ("telecommunications", "small") => Ok(telecommunications::create_benchmark_problems(5)?),
272        ("telecommunications", "medium") => Ok(telecommunications::create_benchmark_problems(15)?),
273        ("telecommunications", "large") => Ok(telecommunications::create_benchmark_problems(50)?),
274
275        ("drug_discovery", "small") => {
276            let molecule_problems = drug_discovery::create_benchmark_problems(10)?;
277            Ok(molecule_problems
278                .into_iter()
279                .map(|problem| {
280                    // Create wrapper that converts Molecule to Vec<i8>
281                    let wrapper: Box<
282                        dyn OptimizationProblem<Solution = Vec<i8>, ObjectiveValue = f64>,
283                    > = Box::new(MoleculeToBinaryWrapper { inner: problem });
284                    wrapper
285                })
286                .collect())
287        }
288        ("drug_discovery", "medium") => {
289            let molecule_problems = drug_discovery::create_benchmark_problems(25)?;
290            Ok(molecule_problems
291                .into_iter()
292                .map(|problem| {
293                    let wrapper: Box<
294                        dyn OptimizationProblem<Solution = Vec<i8>, ObjectiveValue = f64>,
295                    > = Box::new(MoleculeToBinaryWrapper { inner: problem });
296                    wrapper
297                })
298                .collect())
299        }
300        ("drug_discovery", "large") => {
301            let molecule_problems = drug_discovery::create_benchmark_problems(50)?;
302            Ok(molecule_problems
303                .into_iter()
304                .map(|problem| {
305                    let wrapper: Box<
306                        dyn OptimizationProblem<Solution = Vec<i8>, ObjectiveValue = f64>,
307                    > = Box::new(MoleculeToBinaryWrapper { inner: problem });
308                    wrapper
309                })
310                .collect())
311        }
312
313        ("materials_science", "small") => {
314            let materials_problems = materials_science::create_benchmark_problems(10)?;
315            Ok(materials_problems
316                .into_iter()
317                .map(|problem| {
318                    let wrapper: Box<
319                        dyn OptimizationProblem<Solution = Vec<i8>, ObjectiveValue = f64>,
320                    > = Box::new(MaterialsToBinaryWrapper { inner: problem });
321                    wrapper
322                })
323                .collect())
324        }
325        ("materials_science", "medium") => {
326            let materials_problems = materials_science::create_benchmark_problems(50)?;
327            Ok(materials_problems
328                .into_iter()
329                .map(|problem| {
330                    let wrapper: Box<
331                        dyn OptimizationProblem<Solution = Vec<i8>, ObjectiveValue = f64>,
332                    > = Box::new(MaterialsToBinaryWrapper { inner: problem });
333                    wrapper
334                })
335                .collect())
336        }
337        ("materials_science", "large") => {
338            let materials_problems = materials_science::create_benchmark_problems(100)?;
339            Ok(materials_problems
340                .into_iter()
341                .map(|problem| {
342                    let wrapper: Box<
343                        dyn OptimizationProblem<Solution = Vec<i8>, ObjectiveValue = f64>,
344                    > = Box::new(MaterialsToBinaryWrapper { inner: problem });
345                    wrapper
346                })
347                .collect())
348        }
349
350        ("protein_folding", "small") => {
351            let protein_problems = protein_folding::create_benchmark_problems(10)?;
352            Ok(protein_problems
353                .into_iter()
354                .map(|problem| {
355                    let wrapper: Box<
356                        dyn OptimizationProblem<Solution = Vec<i8>, ObjectiveValue = f64>,
357                    > = Box::new(ProteinToBinaryWrapper { inner: problem });
358                    wrapper
359                })
360                .collect())
361        }
362        ("protein_folding", "medium") => {
363            let protein_problems = protein_folding::create_benchmark_problems(25)?;
364            Ok(protein_problems
365                .into_iter()
366                .map(|problem| {
367                    let wrapper: Box<
368                        dyn OptimizationProblem<Solution = Vec<i8>, ObjectiveValue = f64>,
369                    > = Box::new(ProteinToBinaryWrapper { inner: problem });
370                    wrapper
371                })
372                .collect())
373        }
374        ("protein_folding", "large") => {
375            let protein_problems = protein_folding::create_benchmark_problems(50)?;
376            Ok(protein_problems
377                .into_iter()
378                .map(|problem| {
379                    let wrapper: Box<
380                        dyn OptimizationProblem<Solution = Vec<i8>, ObjectiveValue = f64>,
381                    > = Box::new(ProteinToBinaryWrapper { inner: problem });
382                    wrapper
383                })
384                .collect())
385        }
386
387        ("quantum_computational_chemistry", "small") => {
388            let chemistry_problems = quantum_computational_chemistry::create_benchmark_problems(5)?;
389            Ok(chemistry_problems
390                .into_iter()
391                .map(|problem| {
392                    let wrapper: Box<
393                        dyn OptimizationProblem<Solution = Vec<i8>, ObjectiveValue = f64>,
394                    > = Box::new(ChemistryToBinaryWrapper { inner: problem });
395                    wrapper
396                })
397                .collect())
398        }
399        ("quantum_computational_chemistry", "medium") => {
400            let chemistry_problems =
401                quantum_computational_chemistry::create_benchmark_problems(15)?;
402            Ok(chemistry_problems
403                .into_iter()
404                .map(|problem| {
405                    let wrapper: Box<
406                        dyn OptimizationProblem<Solution = Vec<i8>, ObjectiveValue = f64>,
407                    > = Box::new(ChemistryToBinaryWrapper { inner: problem });
408                    wrapper
409                })
410                .collect())
411        }
412        ("quantum_computational_chemistry", "large") => {
413            let chemistry_problems =
414                quantum_computational_chemistry::create_benchmark_problems(30)?;
415            Ok(chemistry_problems
416                .into_iter()
417                .map(|problem| {
418                    let wrapper: Box<
419                        dyn OptimizationProblem<Solution = Vec<i8>, ObjectiveValue = f64>,
420                    > = Box::new(ChemistryToBinaryWrapper { inner: problem });
421                    wrapper
422                })
423                .collect())
424        }
425
426        _ => Err(ApplicationError::InvalidConfiguration(format!(
427            "Unknown benchmark: {industry} / {size}"
428        ))),
429    }
430}
431
432/// Generate comprehensive performance report
433pub fn generate_performance_report(
434    industry: &str,
435    results: &HashMap<String, f64>,
436) -> ApplicationResult<String> {
437    let mut report = String::new();
438
439    let _ = write!(
440        report,
441        "# {} Industry Optimization Report\n\n",
442        industry.to_uppercase()
443    );
444    report.push_str("## Performance Metrics\n\n");
445
446    // Sort metrics for consistent reporting
447    let mut sorted_metrics: Vec<_> = results.iter().collect();
448    sorted_metrics.sort_by_key(|(key, _)| *key);
449
450    for (metric, value) in sorted_metrics {
451        let _ = writeln!(report, "- **{metric}**: {value:.4}");
452    }
453
454    report.push_str("\n## Industry-Specific Analysis\n\n");
455
456    match industry {
457        "finance" => {
458            report.push_str("- Risk-adjusted returns analyzed\n");
459            report.push_str("- Regulatory compliance verified\n");
460            report.push_str("- Market volatility considered\n");
461        }
462        "logistics" => {
463            report.push_str("- Route efficiency optimized\n");
464            report.push_str("- Delivery time constraints satisfied\n");
465            report.push_str("- Vehicle capacity utilization maximized\n");
466        }
467        "energy" => {
468            report.push_str("- Grid stability maintained\n");
469            report.push_str("- Renewable energy integration optimized\n");
470            report.push_str("- Load balancing achieved\n");
471        }
472        "manufacturing" => {
473            report.push_str("- Production schedules optimized\n");
474            report.push_str("- Resource utilization maximized\n");
475            report.push_str("- Quality constraints satisfied\n");
476        }
477        "healthcare" => {
478            report.push_str("- Patient care maximized\n");
479            report.push_str("- Resource allocation optimized\n");
480            report.push_str("- Emergency capacity reserved\n");
481        }
482        "telecommunications" => {
483            report.push_str("- Network connectivity optimized\n");
484            report.push_str("- Latency minimized\n");
485            report.push_str("- Capacity constraints satisfied\n");
486        }
487        "transportation" => {
488            report.push_str("- Route efficiency optimized\n");
489            report.push_str("- Vehicle capacity utilization maximized\n");
490            report.push_str("- Time window constraints satisfied\n");
491        }
492        "drug_discovery" => {
493            report.push_str("- Molecular properties optimized\n");
494            report.push_str("- Drug-target binding affinity maximized\n");
495            report.push_str("- ADMET properties balanced\n");
496            report.push_str("- Drug-likeness constraints satisfied\n");
497        }
498        "materials_science" => {
499            report.push_str("- Lattice energy minimized\n");
500            report.push_str("- Crystal structure optimized\n");
501            report.push_str("- Defect density reduced\n");
502            report.push_str("- Magnetic properties enhanced\n");
503        }
504        "protein_folding" => {
505            report.push_str("- Hydrophobic contacts maximized\n");
506            report.push_str("- Protein compactness optimized\n");
507            report.push_str("- Folding energy minimized\n");
508            report.push_str("- Structural stability enhanced\n");
509        }
510        "quantum_computational_chemistry" => {
511            report.push_str("- Electronic structure optimized\n");
512            report.push_str("- Molecular orbitals calculated\n");
513            report.push_str("- Chemical properties predicted\n");
514            report.push_str("- Reaction pathways analyzed\n");
515            report.push_str("- Catalytic activity optimized\n");
516        }
517        _ => {
518            report.push_str("- Domain-specific analysis completed\n");
519        }
520    }
521
522    Ok(report)
523}
524
525/// Validate industry-specific constraints
526pub fn validate_constraints(
527    constraints: &[IndustryConstraint],
528    solution_data: &HashMap<String, f64>,
529) -> ApplicationResult<()> {
530    for constraint in constraints {
531        match constraint {
532            IndustryConstraint::Capacity { resource, limit } => {
533                if let Some(&usage) = solution_data.get(resource) {
534                    if usage > *limit {
535                        return Err(ApplicationError::ConstraintViolation(format!(
536                            "Resource {resource} usage {usage} exceeds limit {limit}"
537                        )));
538                    }
539                }
540            }
541            IndustryConstraint::Budget { limit } => {
542                if let Some(&cost) = solution_data.get("total_cost") {
543                    if cost > *limit {
544                        return Err(ApplicationError::ConstraintViolation(format!(
545                            "Total cost {cost} exceeds budget {limit}"
546                        )));
547                    }
548                }
549            }
550            IndustryConstraint::Quality { metric, threshold } => {
551                if let Some(&quality) = solution_data.get(metric) {
552                    if quality < *threshold {
553                        return Err(ApplicationError::ConstraintViolation(format!(
554                            "Quality metric {metric} value {quality} below threshold {threshold}"
555                        )));
556                    }
557                }
558            }
559            _ => {
560                // For other constraint types, assume they're handled elsewhere
561            }
562        }
563    }
564
565    Ok(())
566}
567
568#[cfg(test)]
569mod tests {
570    use super::*;
571
572    #[test]
573    fn test_constraint_validation() {
574        let constraints = vec![
575            IndustryConstraint::Capacity {
576                resource: "memory".to_string(),
577                limit: 100.0,
578            },
579            IndustryConstraint::Budget { limit: 1000.0 },
580        ];
581
582        let mut solution_data = HashMap::new();
583        solution_data.insert("memory".to_string(), 80.0);
584        solution_data.insert("total_cost".to_string(), 500.0);
585
586        assert!(validate_constraints(&constraints, &solution_data).is_ok());
587
588        solution_data.insert("memory".to_string(), 150.0);
589        assert!(validate_constraints(&constraints, &solution_data).is_err());
590    }
591
592    #[test]
593    fn test_performance_report_generation() {
594        let mut results = HashMap::new();
595        results.insert("accuracy".to_string(), 0.95);
596        results.insert("efficiency".to_string(), 0.88);
597
598        let report = generate_performance_report("finance", &results)
599            .expect("should generate performance report for finance");
600        assert!(report.contains("FINANCE"));
601        assert!(report.contains("accuracy"));
602        assert!(report.contains("0.95"));
603    }
604}
605
606/// Number of binary variables this molecular wrapper exposes (one per candidate
607/// atom site in the [`MoleculeToBinaryWrapper::binary_to_molecule`] encoding).
608const MOLECULE_BINARY_DIM: usize = 32;
609
610/// Wrapper to convert Molecule-based problems to `Vec<i8>`-based problems
611pub struct MoleculeToBinaryWrapper {
612    inner: Box<dyn OptimizationProblem<Solution = Molecule, ObjectiveValue = f64>>,
613}
614
615impl OptimizationProblem for MoleculeToBinaryWrapper {
616    type Solution = Vec<i8>;
617    type ObjectiveValue = f64;
618
619    fn description(&self) -> String {
620        format!("Binary wrapper for: {}", self.inner.description())
621    }
622
623    fn size_metrics(&self) -> HashMap<String, usize> {
624        // Surface the inner problem's metrics, adding the binary dimension this
625        // wrapper exposes.
626        let mut metrics = self.inner.size_metrics();
627        metrics.insert("binary_dimension".to_string(), MOLECULE_BINARY_DIM);
628        metrics
629    }
630
631    fn validate(&self) -> ApplicationResult<()> {
632        // Validity is determined entirely by the wrapped molecular problem.
633        self.inner.validate()
634    }
635
636    fn to_qubo(&self) -> ApplicationResult<(crate::ising::QuboModel, HashMap<String, usize>)> {
637        // The molecular QUBO encoding is problem-specific; delegate to the inner
638        // problem rather than fabricating a generic toy Hamiltonian.
639        self.inner.to_qubo()
640    }
641
642    fn evaluate_solution(
643        &self,
644        solution: &Self::Solution,
645    ) -> ApplicationResult<Self::ObjectiveValue> {
646        // Decode the binary vector to a molecule, then evaluate it with the
647        // wrapped problem's real objective function.
648        let molecule = self.binary_to_molecule(solution)?;
649        self.inner.evaluate_solution(&molecule)
650    }
651
652    fn is_feasible(&self, solution: &Self::Solution) -> bool {
653        // Decode and defer to the inner problem's feasibility check; an
654        // undecodable binary vector is infeasible by definition.
655        match self.binary_to_molecule(solution) {
656            Ok(molecule) => self.inner.is_feasible(&molecule),
657            Err(_) => false,
658        }
659    }
660}
661
662impl MoleculeToBinaryWrapper {
663    fn binary_to_molecule(&self, solution: &[i8]) -> ApplicationResult<Molecule> {
664        // Create a simple molecule based on binary encoding
665        // This is a simplified conversion - in practice would be more sophisticated
666        let mut molecule = Molecule::new(format!("generated_{}", solution.len()));
667
668        // Add atoms based on binary pattern
669        for (i, &bit) in solution.iter().enumerate() {
670            if bit == 1 {
671                let atom_type = match i % 4 {
672                    0 => drug_discovery::AtomType::Carbon,
673                    1 => drug_discovery::AtomType::Nitrogen,
674                    2 => drug_discovery::AtomType::Oxygen,
675                    _ => drug_discovery::AtomType::Hydrogen,
676                };
677                let atom = drug_discovery::Atom {
678                    id: i,
679                    atom_type,
680                    formal_charge: 0,
681                    hybridization: Some("SP3".to_string()),
682                    aromatic: false,
683                    coordinates: Some([0.0, 0.0, 0.0]),
684                };
685                molecule.add_atom(atom);
686            }
687        }
688
689        Ok(molecule)
690    }
691}
692
693/// Wrapper to convert `MaterialsLattice` problems to binary representation
694pub struct MaterialsToBinaryWrapper {
695    inner: Box<
696        dyn OptimizationProblem<
697            Solution = materials_science::MaterialsLattice,
698            ObjectiveValue = f64,
699        >,
700    >,
701}
702
703impl OptimizationProblem for MaterialsToBinaryWrapper {
704    type Solution = Vec<i8>;
705    type ObjectiveValue = f64;
706
707    fn description(&self) -> String {
708        format!("Binary wrapper for materials science optimization problem")
709    }
710
711    fn size_metrics(&self) -> HashMap<String, usize> {
712        let mut metrics = HashMap::new();
713        metrics.insert("binary_dimension".to_string(), 64);
714        metrics.insert("lattice_sites".to_string(), 16);
715        metrics
716    }
717
718    fn validate(&self) -> ApplicationResult<()> {
719        Ok(())
720    }
721
722    fn to_qubo(&self) -> ApplicationResult<(crate::ising::QuboModel, HashMap<String, usize>)> {
723        // Create a simple QUBO model for materials optimization
724        let n = 64; // binary dimension
725        let mut h = vec![0.0; n];
726        let mut j = std::collections::HashMap::new();
727
728        // Add some basic interactions for lattice structure
729        for i in 0..n {
730            h[i] = -0.05; // Small bias towards occupied sites
731            for j_idx in (i + 1)..n {
732                if j_idx < i + 8 {
733                    // Local interactions in lattice
734                    j.insert((i, j_idx), 0.02);
735                }
736            }
737        }
738
739        let mut qubo = crate::ising::QuboModel::new(n);
740
741        // Set linear terms
742        for (i, &value) in h.iter().enumerate() {
743            qubo.set_linear(i, value)?;
744        }
745
746        // Set quadratic terms
747        for ((i, j_idx), &value) in &j {
748            qubo.set_quadratic(*i, *j_idx, value)?;
749        }
750
751        let mut variable_mapping = HashMap::new();
752        for i in 0..n {
753            variable_mapping.insert(format!("site_{i}"), i);
754        }
755
756        Ok((qubo, variable_mapping))
757    }
758
759    fn evaluate_solution(
760        &self,
761        solution: &Self::Solution,
762    ) -> ApplicationResult<Self::ObjectiveValue> {
763        // Simple evaluation based on lattice structure
764        Ok(solution
765            .iter()
766            .map(|&x| if x > 0 { 1.0 } else { 0.0 })
767            .sum::<f64>()
768            * 0.1)
769    }
770
771    fn is_feasible(&self, solution: &Self::Solution) -> bool {
772        solution.len() == 64
773    }
774}
775
776/// Wrapper to convert `ProteinFolding` problems to binary representation
777pub struct ProteinToBinaryWrapper {
778    inner: Box<
779        dyn OptimizationProblem<Solution = protein_folding::ProteinFolding, ObjectiveValue = f64>,
780    >,
781}
782
783impl OptimizationProblem for ProteinToBinaryWrapper {
784    type Solution = Vec<i8>;
785    type ObjectiveValue = f64;
786
787    fn description(&self) -> String {
788        format!("Binary wrapper for protein folding optimization problem")
789    }
790
791    fn size_metrics(&self) -> HashMap<String, usize> {
792        let mut metrics = HashMap::new();
793        metrics.insert("binary_dimension".to_string(), 32);
794        metrics.insert("amino_acids".to_string(), 8);
795        metrics
796    }
797
798    fn validate(&self) -> ApplicationResult<()> {
799        Ok(())
800    }
801
802    fn to_qubo(&self) -> ApplicationResult<(crate::ising::QuboModel, HashMap<String, usize>)> {
803        // Create a simple QUBO model for protein folding
804        let n = 32; // binary dimension
805        let mut h = vec![0.0; n];
806        let mut j = std::collections::HashMap::new();
807
808        // Add interactions for folding constraints
809        for i in 0..n {
810            h[i] = -0.02; // Small bias
811            for j_idx in (i + 1)..n {
812                if j_idx < i + 3 {
813                    // Local folding interactions
814                    j.insert((i, j_idx), 0.01);
815                }
816            }
817        }
818
819        let mut qubo = crate::ising::QuboModel::new(n);
820
821        // Set linear terms
822        for (i, &value) in h.iter().enumerate() {
823            qubo.set_linear(i, value)?;
824        }
825
826        // Set quadratic terms
827        for ((i, j_idx), &value) in &j {
828            qubo.set_quadratic(*i, *j_idx, value)?;
829        }
830
831        let mut variable_mapping = HashMap::new();
832        for i in 0..n {
833            variable_mapping.insert(format!("fold_{i}"), i);
834        }
835
836        Ok((qubo, variable_mapping))
837    }
838
839    fn evaluate_solution(
840        &self,
841        solution: &Self::Solution,
842    ) -> ApplicationResult<Self::ObjectiveValue> {
843        // Simple evaluation based on folding energy
844        Ok(solution
845            .iter()
846            .map(|&x| if x > 0 { 1.0 } else { 0.0 })
847            .sum::<f64>()
848            * 0.05)
849    }
850
851    fn is_feasible(&self, solution: &Self::Solution) -> bool {
852        solution.len() == 32
853    }
854}
855
856/// Wrapper to convert quantum computational chemistry problems to binary representation
857pub struct ChemistryToBinaryWrapper {
858    inner: Box<
859        dyn OptimizationProblem<
860            Solution = quantum_computational_chemistry::QuantumChemistryResult,
861            ObjectiveValue = f64,
862        >,
863    >,
864}
865
866impl OptimizationProblem for ChemistryToBinaryWrapper {
867    type Solution = Vec<i8>;
868    type ObjectiveValue = f64;
869
870    fn description(&self) -> String {
871        format!("Binary wrapper for quantum computational chemistry problem")
872    }
873
874    fn size_metrics(&self) -> HashMap<String, usize> {
875        let mut metrics = HashMap::new();
876        metrics.insert("binary_dimension".to_string(), 64);
877        metrics.insert("molecular_orbitals".to_string(), 32);
878        metrics
879    }
880
881    fn validate(&self) -> ApplicationResult<()> {
882        self.inner.validate()
883    }
884
885    fn to_qubo(&self) -> ApplicationResult<(crate::ising::QuboModel, HashMap<String, usize>)> {
886        self.inner.to_qubo()
887    }
888
889    fn evaluate_solution(
890        &self,
891        solution: &Self::Solution,
892    ) -> ApplicationResult<Self::ObjectiveValue> {
893        // Score the binary assignment via a genuine QUBO-energy evaluation of
894        // the wrapped chemistry problem (see `binary_to_chemistry_result`).
895        let chemistry_result = self.binary_to_chemistry_result(solution)?;
896        self.inner.evaluate_solution(&chemistry_result)
897    }
898
899    fn is_feasible(&self, solution: &Self::Solution) -> bool {
900        solution.len() == 64 && solution.iter().all(|&x| x == 0 || x == 1)
901    }
902}
903
904impl ChemistryToBinaryWrapper {
905    /// Build a chemistry result whose energies are a genuine evaluation of the
906    /// binary assignment against the wrapped problem's *real* molecular QUBO.
907    ///
908    /// A binary annealing assignment does not contain SCF orbitals, an electron
909    /// density grid, or convergence information, so those quantities are *not*
910    /// fabricated here: the structural fields are left explicitly empty and the
911    /// metadata records that this is a QUBO-surrogate evaluation rather than a
912    /// converged self-consistent-field calculation. Only the fields that can be
913    /// honestly derived from the bitstring — the electronic and total energy —
914    /// are populated, by computing the actual QUBO objective. The downstream
915    /// chemistry objective scores precisely those energies.
916    fn binary_to_chemistry_result(
917        &self,
918        solution: &[i8],
919    ) -> ApplicationResult<quantum_computational_chemistry::QuantumChemistryResult> {
920        use quantum_computational_chemistry::{
921            BasisSet, CalculationMetadata, ElectronDensity, ElectronicStructureMethod,
922            QuantumChemistryResult, ThermochemicalProperties,
923        };
924
925        // Obtain the genuine molecular QUBO from the wrapped problem and score
926        // the binary assignment with the exact QUBO objective. The assignment is
927        // aligned to the QUBO's variable count (extra bits are ignored, missing
928        // bits default to unoccupied).
929        let (qubo, _mapping) = self.inner.to_qubo()?;
930        let num_vars = qubo.num_variables;
931        let binary_vars: Vec<bool> = (0..num_vars)
932            .map(|i| solution.get(i).is_some_and(|&bit| bit == 1))
933            .collect();
934        let electronic_energy = qubo
935            .objective(&binary_vars)
936            .map_err(|e| ApplicationError::OptimizationError(e.to_string()))?;
937
938        // No nuclear-repulsion constant is recoverable from the bitstring alone;
939        // the QUBO surrogate folds geometric effects into its coefficients, so
940        // the total energy equals the surrogate electronic energy.
941        let nuclear_repulsion = 0.0;
942        let total_energy = electronic_energy + nuclear_repulsion;
943        let scf_converged = total_energy.is_finite();
944
945        Ok(QuantumChemistryResult {
946            system_id: "qubo_surrogate_evaluation".to_string(),
947            electronic_energy,
948            nuclear_repulsion,
949            total_energy,
950            // Not derivable from a binary assignment: left honestly empty rather
951            // than populated with fabricated orbitals / density values.
952            molecular_orbitals: Vec::new(),
953            electron_density: ElectronDensity {
954                grid_points: Vec::new(),
955                density_values: Vec::new(),
956                density_matrix: Vec::new(),
957                mulliken_charges: Vec::new(),
958                electrostatic_potential: Vec::new(),
959            },
960            dipole_moment: [0.0, 0.0, 0.0],
961            polarizability: [[0.0; 3]; 3],
962            vibrational_frequencies: Vec::new(),
963            thermochemistry: ThermochemicalProperties {
964                zero_point_energy: 0.0,
965                thermal_energy: 0.0,
966                enthalpy: total_energy,
967                entropy: 0.0,
968                free_energy: total_energy,
969                heat_capacity: 0.0,
970                temperature: 298.15,
971            },
972            metadata: CalculationMetadata {
973                method: ElectronicStructureMethod::HartreeFock,
974                basis_set: BasisSet::STO3G,
975                // The surrogate QUBO objective evaluated to a finite value; this
976                // is not an SCF convergence claim (no SCF was run).
977                scf_converged,
978                scf_iterations: 0,
979                cpu_time: 0.0,
980                wall_time: 0.0,
981                memory_usage: 0,
982                error_correction_applied: false,
983            },
984        })
985    }
986}