Skip to main content

quantrs2_device/cloud/provider_optimizations/
googleoptimizer_traits.rs

1//! # GoogleOptimizer - Trait Implementations
2//!
3//! Implements `ProviderOptimizer` for Google Quantum AI.  The optimizer:
4//!
5//! - Targets the Sycamore processor family (Weber 53-qubit / Rainbow 23-qubit).
6//! - Recommends CZ + √iSWAP native gate transpilation (the two native two-qubit
7//!   gates on Sycamore hardware).
8//! - Estimates cost using Google's research-access pricing model; commercial
9//!   pricing is modelled conservatively as $0.00090 per gate-qubit operation.
10//! - Selects the best processor based on qubit count and fidelity requirements.
11//!
12//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
13
14use super::traits::ProviderOptimizer;
15use super::types::*;
16use crate::prelude::CloudProvider;
17use crate::DeviceResult;
18use std::collections::HashMap;
19use std::time::Duration;
20use uuid::Uuid;
21
22// ---------------------------------------------------------------------------
23// Pricing constants (USD, 2024 Google Cloud Quantum AI commercial estimate)
24// ---------------------------------------------------------------------------
25
26/// Estimated per-gate-qubit cost on Google Quantum AI hardware (USD).
27/// Note: public commercial pricing is not yet officially published; this is
28/// based on published research-access estimates for academic/commercial users.
29const GOOGLE_PER_GATE_QUBIT_USD: f64 = 0.00090;
30
31/// Flat per-job overhead fee (USD).
32const GOOGLE_PER_JOB_FEE_USD: f64 = 0.50;
33
34// ---------------------------------------------------------------------------
35// Processor catalogue
36// ---------------------------------------------------------------------------
37
38#[derive(Debug, Clone, Copy)]
39struct GoogleProcessorSpec {
40    name: &'static str,
41    qubit_count: usize,
42    /// Typical CZ gate fidelity.
43    cz_fidelity: f64,
44    /// Typical √iSWAP gate fidelity.
45    sqrt_iswap_fidelity: f64,
46    /// Relative queue depth (0–1).
47    relative_queue_depth: f64,
48    /// Typical queue latency (seconds).
49    queue_latency_s: f64,
50}
51
52const GOOGLE_PROCESSORS: &[GoogleProcessorSpec] = &[
53    GoogleProcessorSpec {
54        name: "google_sycamore_weber",
55        qubit_count: 53,
56        cz_fidelity: 0.994,
57        sqrt_iswap_fidelity: 0.992,
58        relative_queue_depth: 0.60,
59        queue_latency_s: 120.0,
60    },
61    GoogleProcessorSpec {
62        name: "google_sycamore_rainbow",
63        qubit_count: 23,
64        cz_fidelity: 0.991,
65        sqrt_iswap_fidelity: 0.989,
66        relative_queue_depth: 0.45,
67        queue_latency_s: 90.0,
68    },
69    GoogleProcessorSpec {
70        name: "google_willow",
71        qubit_count: 105,
72        cz_fidelity: 0.997,
73        sqrt_iswap_fidelity: 0.996,
74        relative_queue_depth: 0.80,
75        queue_latency_s: 180.0,
76    },
77];
78
79/// Return the best processor for the given qubit count and minimum fidelity
80/// based on a fidelity-weighted selection.
81fn select_google_processor(
82    qubit_count: usize,
83    min_fidelity: f64,
84) -> Option<&'static GoogleProcessorSpec> {
85    GOOGLE_PROCESSORS
86        .iter()
87        .filter(|p| {
88            p.qubit_count >= qubit_count
89                && p.cz_fidelity >= min_fidelity
90                && p.sqrt_iswap_fidelity >= min_fidelity
91        })
92        .max_by(|a, b| {
93            // Prefer highest CZ fidelity; break ties by lower queue depth.
94            let score_a = a.cz_fidelity - a.relative_queue_depth * 0.05;
95            let score_b = b.cz_fidelity - b.relative_queue_depth * 0.05;
96            score_a
97                .partial_cmp(&score_b)
98                .unwrap_or(std::cmp::Ordering::Equal)
99        })
100}
101
102// ---------------------------------------------------------------------------
103// ProviderOptimizer implementation
104// ---------------------------------------------------------------------------
105
106impl ProviderOptimizer for GoogleOptimizer {
107    /// Produce an `OptimizationRecommendation` for executing the workload on
108    /// Google Quantum AI.
109    ///
110    /// Strategy:
111    /// 1. Select the best Sycamore processor meeting qubit and fidelity needs.
112    /// 2. Recommend CZ + √iSWAP native gate transpilation (cirq-core equivalent).
113    /// 3. Apply readout error mitigation for circuits with depth > 20.
114    fn optimize_workload(
115        &self,
116        workload: &WorkloadSpec,
117    ) -> DeviceResult<OptimizationRecommendation> {
118        let qubit_count = workload.circuit_characteristics.qubit_count;
119        let shots = workload.execution_requirements.shots;
120        let min_fidelity = workload
121            .circuit_characteristics
122            .coherence_requirements
123            .min_gate_fidelity;
124        let circuit_depth = workload.circuit_characteristics.circuit_depth;
125
126        let primary = select_google_processor(qubit_count, min_fidelity).ok_or_else(|| {
127            crate::DeviceError::InvalidInput(format!(
128                "No Google Quantum AI processor can accommodate {qubit_count} qubits \
129                 with CZ / √iSWAP fidelity ≥ {min_fidelity:.3}"
130            ))
131        })?;
132
133        let use_rem = circuit_depth > 20;
134
135        let recommended_config = ExecutionConfig {
136            provider: CloudProvider::Google,
137            backend: primary.name.to_string(),
138            optimization_settings: OptimizationSettings {
139                circuit_optimization: CircuitOptimizationSettings {
140                    gate_fusion: true,
141                    gate_cancellation: true,
142                    circuit_compression: true,
143                    transpilation_level: TranspilationLevel::Advanced,
144                    error_mitigation: ErrorMitigationSettings {
145                        zero_noise_extrapolation: false,
146                        readout_error_mitigation: use_rem,
147                        gate_error_mitigation: false,
148                        decoherence_mitigation: false,
149                        crosstalk_mitigation: false,
150                    },
151                },
152                hardware_optimization: HardwareOptimizationSettings {
153                    qubit_mapping: QubitMappingStrategy::TopologyAware,
154                    routing_optimization: RoutingOptimizationStrategy::NoiseAware,
155                    calibration_optimization: CalibrationOptimizationStrategy::RealTime,
156                    noise_adaptation: NoiseAdaptationStrategy::ModelBased,
157                },
158                ..OptimizationSettings::default()
159            },
160            ..ExecutionConfig::default()
161        };
162
163        let cost_estimate = compute_google_cost(shots, circuit_depth, qubit_count, primary);
164        let perf_prediction = compute_google_performance(workload, primary);
165
166        let alternatives: Vec<AlternativeRecommendation> = GOOGLE_PROCESSORS
167            .iter()
168            .filter(|p| {
169                p.name != primary.name
170                    && p.qubit_count >= qubit_count
171                    && p.cz_fidelity >= min_fidelity
172            })
173            .map(|p| {
174                let alt_cost = compute_google_cost(shots, circuit_depth, qubit_count, p);
175                let alt_perf = compute_google_performance(workload, p);
176                AlternativeRecommendation {
177                    alternative_id: Uuid::new_v4().to_string(),
178                    config: ExecutionConfig {
179                        provider: CloudProvider::Google,
180                        backend: p.name.to_string(),
181                        optimization_settings: OptimizationSettings::default(),
182                        ..ExecutionConfig::default()
183                    },
184                    trade_offs: TradeOffAnalysis {
185                        performance_impact: alt_perf.expected_fidelity
186                            - perf_prediction.expected_fidelity,
187                        cost_impact: alt_cost.total_cost - cost_estimate.total_cost,
188                        reliability_impact: 0.0,
189                        complexity_impact: 0.0,
190                        trade_off_summary: format!(
191                            "{} — {}-qubit, queue depth {:.0}%, Δcost ${:+.4}, Δfidelity {:+.4}",
192                            p.name,
193                            p.qubit_count,
194                            p.relative_queue_depth * 100.0,
195                            alt_cost.total_cost - cost_estimate.total_cost,
196                            alt_perf.expected_fidelity - perf_prediction.expected_fidelity
197                        ),
198                    },
199                    use_case_suitability: alt_perf.success_probability,
200                }
201            })
202            .collect();
203
204        let rationale = format!(
205            "Selected Google Quantum AI processor {} ({} qubits) as the best option \
206             for {qubit_count} qubits with CZ fidelity ≥ {min_fidelity:.3}. \
207             CZ fidelity: {:.4}, √iSWAP fidelity: {:.4}. \
208             REM: {}. Estimated cost: ${:.4}.",
209            primary.name,
210            primary.qubit_count,
211            primary.cz_fidelity,
212            primary.sqrt_iswap_fidelity,
213            if use_rem { "enabled" } else { "disabled" },
214            cost_estimate.total_cost,
215        );
216
217        Ok(OptimizationRecommendation {
218            recommendation_id: Uuid::new_v4().to_string(),
219            workload_id: workload.workload_id.clone(),
220            provider: CloudProvider::Google,
221            recommended_config,
222            optimization_strategies: self.get_optimization_strategies(),
223            expected_performance: perf_prediction,
224            cost_estimate,
225            confidence_score: 0.80,
226            rationale,
227            alternative_recommendations: alternatives,
228        })
229    }
230
231    fn get_provider(&self) -> CloudProvider {
232        CloudProvider::Google
233    }
234
235    fn get_optimization_strategies(&self) -> Vec<OptimizationStrategy> {
236        vec![
237            OptimizationStrategy::CircuitOptimization,
238            OptimizationStrategy::PerformanceOptimization,
239            OptimizationStrategy::ResourceProvisioning,
240        ]
241    }
242
243    fn predict_performance(
244        &self,
245        workload: &WorkloadSpec,
246        config: &ExecutionConfig,
247    ) -> DeviceResult<PerformancePrediction> {
248        let processor = GOOGLE_PROCESSORS
249            .iter()
250            .find(|p| p.name == config.backend)
251            .unwrap_or(&GOOGLE_PROCESSORS[0]);
252        Ok(compute_google_performance(workload, processor))
253    }
254
255    fn estimate_cost(
256        &self,
257        workload: &WorkloadSpec,
258        config: &ExecutionConfig,
259    ) -> DeviceResult<CostEstimate> {
260        let processor = GOOGLE_PROCESSORS
261            .iter()
262            .find(|p| p.name == config.backend)
263            .unwrap_or(&GOOGLE_PROCESSORS[0]);
264        Ok(compute_google_cost(
265            workload.execution_requirements.shots,
266            workload.circuit_characteristics.circuit_depth,
267            workload.circuit_characteristics.qubit_count,
268            processor,
269        ))
270    }
271}
272
273// ---------------------------------------------------------------------------
274// Internal helpers
275// ---------------------------------------------------------------------------
276
277fn compute_google_cost(
278    shots: usize,
279    circuit_depth: usize,
280    qubit_count: usize,
281    processor: &GoogleProcessorSpec,
282) -> CostEstimate {
283    // Cost model: per-job fee + shots × depth × qubits × per_gate_qubit_rate.
284    let gate_qubit_ops = shots as f64 * circuit_depth as f64 * qubit_count as f64;
285    let execution_cost = gate_qubit_ops * GOOGLE_PER_GATE_QUBIT_USD;
286    let total = execution_cost + GOOGLE_PER_JOB_FEE_USD;
287    let uncertainty = total * 0.25; // Wide uncertainty — pricing not fully public.
288
289    CostEstimate {
290        total_cost: total,
291        cost_breakdown: CostBreakdown {
292            execution_cost,
293            queue_cost: 0.0,
294            storage_cost: 0.0,
295            network_cost: 0.0,
296            overhead_cost: GOOGLE_PER_JOB_FEE_USD,
297            discount_applied: 0.0,
298        },
299        cost_model: CostModel::PayPerUse,
300        uncertainty_range: (total - uncertainty, total + uncertainty),
301        cost_optimization_opportunities: vec![CostOptimizationOpportunity {
302            opportunity_type: CostOptimizationType::ResourceRightSizing,
303            potential_savings: total * 0.20,
304            implementation_effort: 0.30,
305            description: "Reduce circuit depth with Cirq optimisation passes \
306                           (gate cancellation, two-qubit compilation) to lower the \
307                           gate-qubit operation count."
308                .to_string(),
309        }],
310    }
311}
312
313fn compute_google_performance(
314    workload: &WorkloadSpec,
315    processor: &GoogleProcessorSpec,
316) -> PerformancePrediction {
317    let cc = &workload.circuit_characteristics;
318    let shots = workload.execution_requirements.shots;
319
320    // Fidelity model: CZ error accumulates per two-qubit layer.
321    let cz_layers = (cc.circuit_depth / 2).max(1) as f64;
322    let expected_fidelity = processor.cz_fidelity.powf(cz_layers).clamp(0.01, 1.0);
323    let success_probability = (expected_fidelity * 0.975).clamp(0.0, 1.0);
324
325    // Sycamore executes at ~25 ns per CZ; 1 000 shots ≈ 1 s for typical depth.
326    let exec_s = shots as f64 * 0.001;
327
328    PerformancePrediction {
329        execution_time: Duration::from_secs_f64(exec_s),
330        queue_time: Duration::from_secs_f64(processor.queue_latency_s),
331        total_time: Duration::from_secs_f64(exec_s + processor.queue_latency_s),
332        success_probability,
333        expected_fidelity,
334        resource_utilization: ResourceUtilizationPrediction {
335            cpu_utilization: 0.04,
336            memory_utilization: 0.10,
337            quantum_resource_utilization: cc.qubit_count as f64 / processor.qubit_count as f64,
338            network_utilization: 0.02,
339            storage_utilization: 0.01,
340        },
341        bottlenecks: Vec::new(),
342        confidence_interval: (success_probability * 0.90, success_probability * 1.05),
343    }
344}