quantrs2-anneal 0.1.3

Quantum annealing support for the QuantRS2 framework
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
//! Auto-generated module
//!
//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)

#[cfg(feature = "dwave")]
pub use client::*;
#[cfg(not(feature = "dwave"))]
pub use placeholder::*;
use std::fmt::Write;

#[cfg(feature = "dwave")]
mod client {
    use crate::embedding::{Embedding, HardwareGraph, MinorMiner};
    use crate::ising::{IsingError, IsingModel, QuboModel};
    use reqwest::Client;
    use serde::{Deserialize, Serialize};
    use std::collections::HashMap;
    use std::fmt::Write;
    use std::time::{Duration, Instant};
    use thiserror::Error;
    use tokio::runtime::Runtime;
    /// Errors that can occur when interacting with D-Wave API
    #[derive(Error, Debug)]
    pub enum DWaveError {
        /// Error in the underlying Ising model
        #[error("Ising error: {0}")]
        IsingError(#[from] IsingError),
        /// Error with the network request
        #[error("Network error: {0}")]
        NetworkError(#[from] reqwest::Error),
        /// Error parsing the response
        #[error("Response parsing error: {0}")]
        ParseError(#[from] serde_json::Error),
        /// Error with the D-Wave API response
        #[error("D-Wave API error: {0}")]
        ApiError(String),
        /// Error with the authentication credentials
        #[error("Authentication error: {0}")]
        AuthError(String),
        /// Error with the tokio runtime
        #[error("Runtime error: {0}")]
        RuntimeError(String),
        /// Error with the problem formulation
        #[error("Problem formulation error: {0}")]
        ProblemError(String),
        /// Error with embedding
        #[error("Embedding error: {0}")]
        EmbeddingError(String),
        /// Error with hybrid solver
        #[error("Hybrid solver error: {0}")]
        HybridSolverError(String),
        /// Error with problem status
        #[error("Problem status error: {0}")]
        StatusError(String),
        /// Error with batch operations
        #[error("Batch operation error: {0}")]
        BatchError(String),
        /// Error with solver configuration
        #[error("Solver configuration error: {0}")]
        SolverConfigError(String),
        /// Timeout error
        #[error("Operation timed out: {0}")]
        TimeoutError(String),
    }
    /// Result type for D-Wave operations
    pub type DWaveResult<T> = Result<T, DWaveError>;
    /// D-Wave solver information
    #[derive(Debug, Clone, Serialize, Deserialize)]
    pub struct SolverInfo {
        /// ID of the solver
        pub id: String,
        /// Name of the solver
        pub name: String,
        /// Description of the solver
        pub description: String,
        /// Number of qubits
        pub num_qubits: usize,
        /// Connectivity information
        pub connectivity: SolverConnectivity,
        /// Properties of the solver
        pub properties: SolverProperties,
    }
    /// D-Wave solver connectivity
    #[derive(Debug, Clone, Serialize, Deserialize)]
    pub struct SolverConnectivity {
        /// Type of connectivity (e.g., "chimera", "pegasus")
        #[serde(rename = "type")]
        pub type_: String,
        /// Parameters for the connectivity
        #[serde(flatten)]
        pub params: serde_json::Value,
    }
    /// D-Wave solver properties
    #[derive(Debug, Clone, Serialize, Deserialize)]
    pub struct SolverProperties {
        /// Supported parameters
        pub parameters: serde_json::Value,
        /// Additional properties
        #[serde(flatten)]
        pub other: serde_json::Value,
    }
    /// D-Wave problem submission parameters
    #[derive(Debug, Clone, Serialize, Deserialize)]
    pub struct ProblemParams {
        /// Number of reads/samples to take
        pub num_reads: usize,
        /// Annealing time in microseconds
        pub annealing_time: usize,
        /// Programming thermalization in microseconds
        #[serde(rename = "programming_thermalization")]
        pub programming_therm: usize,
        /// Read-out thermalization in microseconds
        #[serde(rename = "readout_thermalization")]
        pub readout_therm: usize,
        /// Flux biases for each qubit (optional)
        #[serde(rename = "flux_biases", skip_serializing_if = "Option::is_none")]
        pub flux_biases: Option<Vec<f64>>,
        /// Per-qubit flux bias values (optional, alternative format)
        #[serde(rename = "flux_bias", skip_serializing_if = "Option::is_none")]
        pub flux_bias_map: Option<serde_json::Map<String, serde_json::Value>>,
        /// Additional parameters
        #[serde(flatten)]
        pub other: serde_json::Value,
    }
    impl Default for ProblemParams {
        fn default() -> Self {
            Self {
                num_reads: 1000,
                annealing_time: 20,
                programming_therm: 1000,
                readout_therm: 0,
                flux_biases: None,
                flux_bias_map: None,
                other: serde_json::Value::Object(serde_json::Map::new()),
            }
        }
    }
    /// D-Wave problem submission
    #[derive(Debug, Clone, Serialize, Deserialize)]
    pub struct Problem {
        /// The linear terms (h_i values for Ising, Q_ii for QUBO)
        #[serde(rename = "linear")]
        pub linear_terms: serde_json::Value,
        /// The quadratic terms (J_ij values for Ising, Q_ij for QUBO)
        #[serde(rename = "quadratic")]
        pub quadratic_terms: serde_json::Value,
        /// The type of problem (ising or qubo)
        #[serde(rename = "type")]
        pub type_: String,
        /// The solver to use
        pub solver: String,
        /// The parameters for the problem
        pub params: ProblemParams,
    }
    /// D-Wave problem solution
    #[derive(Debug, Clone, Serialize, Deserialize)]
    pub struct Solution {
        /// The energy of each sample
        pub energies: Vec<f64>,
        /// The occurrences of each sample
        pub occurrences: Vec<usize>,
        /// The solutions (spin values for Ising, binary values for QUBO)
        pub solutions: Vec<Vec<i8>>,
        /// The number of samples
        pub num_samples: usize,
        /// The problem ID
        pub problem_id: String,
        /// The solver used
        pub solver: String,
        /// The timing information
        pub timing: serde_json::Value,
    }
    /// Enhanced solver types for Leap
    #[derive(Debug, Clone, Serialize, Deserialize)]
    pub enum SolverType {
        /// Quantum annealing processor
        #[serde(rename = "qpu")]
        QuantumProcessor,
        /// Hybrid classical-quantum solver
        #[serde(rename = "hybrid")]
        Hybrid,
        /// Discrete Quadratic Model solver
        #[serde(rename = "dqm")]
        DiscreteQuadraticModel,
        /// Constrained Quadratic Model solver
        #[serde(rename = "cqm")]
        ConstrainedQuadraticModel,
        /// Software solver/simulator
        #[serde(rename = "software")]
        Software,
    }
    /// Solver category for filtering
    #[derive(Debug, Clone, PartialEq, Eq)]
    pub enum SolverCategory {
        /// Quantum processing units
        QPU,
        /// Hybrid solvers
        Hybrid,
        /// Software-based solvers
        Software,
        /// All solver types
        All,
    }
    /// Problem status tracking
    #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
    pub enum ProblemStatus {
        /// Problem is being processed
        #[serde(rename = "IN_PROGRESS")]
        InProgress,
        /// Problem completed successfully
        #[serde(rename = "COMPLETED")]
        Completed,
        /// Problem failed
        #[serde(rename = "FAILED")]
        Failed,
        /// Problem was cancelled
        #[serde(rename = "CANCELLED")]
        Cancelled,
        /// Problem is pending
        #[serde(rename = "PENDING")]
        Pending,
    }
    /// Problem metadata and tracking
    #[derive(Debug, Clone, Serialize, Deserialize)]
    pub struct ProblemInfo {
        /// Problem ID
        pub id: String,
        /// Problem status
        pub status: ProblemStatus,
        /// Submission time
        pub submitted_on: String,
        /// Solver used
        pub solver: String,
        /// Problem type
        #[serde(rename = "type")]
        pub problem_type: String,
        /// Parameters used
        pub params: serde_json::Value,
        /// Additional metadata
        #[serde(flatten)]
        pub metadata: serde_json::Value,
    }
    /// Enhanced solver information with Leap features
    #[derive(Debug, Clone, Serialize, Deserialize)]
    pub struct LeapSolverInfo {
        /// Solver ID
        pub id: String,
        /// Solver name
        pub name: String,
        /// Solver description
        pub description: String,
        /// Solver type
        #[serde(rename = "category")]
        pub solver_type: SolverType,
        /// Status (online/offline)
        pub status: String,
        /// Solver properties
        pub properties: serde_json::Value,
        /// Supported problem types
        pub problem_types: Vec<String>,
        /// Average queue time
        pub avg_load: Option<f64>,
        /// Whether solver is available
        pub available: bool,
    }
    /// Custom annealing schedule
    #[derive(Debug, Clone, Serialize, Deserialize)]
    pub struct AnnealingSchedule {
        /// Time points in microseconds
        pub schedule: Vec<(f64, f64)>,
    }
    impl AnnealingSchedule {
        /// Create a linear annealing schedule
        pub fn linear(annealing_time: f64) -> Self {
            Self {
                schedule: vec![(0.0, 1.0), (annealing_time, 0.0)],
            }
        }
        /// Create a pause-and-ramp schedule
        pub fn pause_and_ramp(annealing_time: f64, pause_start: f64, pause_duration: f64) -> Self {
            Self {
                schedule: vec![
                    (0.0, 1.0),
                    (pause_start, 1.0 - pause_start / annealing_time),
                    (
                        pause_start + pause_duration,
                        1.0 - pause_start / annealing_time,
                    ),
                    (annealing_time, 0.0),
                ],
            }
        }
        /// Create a custom schedule from points
        pub fn custom(points: Vec<(f64, f64)>) -> Self {
            Self { schedule: points }
        }
    }
    /// Advanced problem parameters for Leap
    #[derive(Debug, Clone, Serialize, Deserialize)]
    pub struct AdvancedProblemParams {
        /// Number of reads/samples
        pub num_reads: usize,
        /// Custom annealing schedule
        #[serde(skip_serializing_if = "Option::is_none")]
        pub anneal_schedule: Option<AnnealingSchedule>,
        /// Programming thermalization
        #[serde(skip_serializing_if = "Option::is_none")]
        pub programming_thermalization: Option<usize>,
        /// Readout thermalization
        #[serde(skip_serializing_if = "Option::is_none")]
        pub readout_thermalization: Option<usize>,
        /// Auto-scale flag
        #[serde(skip_serializing_if = "Option::is_none")]
        pub auto_scale: Option<bool>,
        /// Chain strength
        #[serde(skip_serializing_if = "Option::is_none")]
        pub chain_strength: Option<f64>,
        /// Flux biases
        #[serde(skip_serializing_if = "Option::is_none")]
        pub flux_biases: Option<HashMap<String, f64>>,
        /// Additional parameters
        #[serde(flatten)]
        pub extra: HashMap<String, serde_json::Value>,
    }
    impl Default for AdvancedProblemParams {
        fn default() -> Self {
            Self {
                num_reads: 1000,
                anneal_schedule: None,
                programming_thermalization: Some(1000),
                readout_thermalization: Some(0),
                auto_scale: Some(true),
                chain_strength: None,
                flux_biases: None,
                extra: HashMap::new(),
            }
        }
    }
    /// Hybrid solver parameters
    #[derive(Debug, Clone, Serialize, Deserialize)]
    pub struct HybridSolverParams {
        /// Time limit in seconds
        #[serde(skip_serializing_if = "Option::is_none")]
        pub time_limit: Option<f64>,
        /// Maximum number of variables
        #[serde(skip_serializing_if = "Option::is_none")]
        pub max_variables: Option<usize>,
        /// Additional solver-specific parameters
        #[serde(flatten)]
        pub extra: HashMap<String, serde_json::Value>,
    }
    impl Default for HybridSolverParams {
        fn default() -> Self {
            Self {
                time_limit: Some(5.0),
                max_variables: None,
                extra: HashMap::new(),
            }
        }
    }
    /// Performance metrics for problems
    #[derive(Debug, Clone)]
    pub struct ProblemMetrics {
        /// Total execution time
        pub total_time: Duration,
        /// Queue time
        pub queue_time: Duration,
        /// Solver access time
        pub access_time: Duration,
        /// Programming time
        pub programming_time: Duration,
        /// Sampling time
        pub sampling_time: Duration,
        /// Readout time
        pub readout_time: Duration,
        /// Best energy found
        pub best_energy: f64,
        /// Number of valid solutions
        pub num_valid_solutions: usize,
        /// Chain break fraction
        pub chain_break_fraction: Option<f64>,
    }
    /// Batch problem submission result
    #[derive(Debug)]
    pub struct BatchSubmissionResult {
        /// List of submitted problem IDs
        pub problem_ids: Vec<String>,
        /// Success/failure status for each problem
        pub statuses: Vec<Result<String, DWaveError>>,
        /// Total submission time
        pub submission_time: Duration,
    }
    /// Solver selection criteria
    #[derive(Debug, Clone)]
    pub struct SolverSelector {
        /// Solver category filter
        pub category: SolverCategory,
        /// Minimum number of qubits
        pub min_qubits: Option<usize>,
        /// Maximum queue time preference
        pub max_queue_time: Option<f64>,
        /// Prefer online solvers
        pub online_only: bool,
        /// Specific solver name pattern
        pub name_pattern: Option<String>,
        /// Topology preference
        pub topology_preference: Option<String>,
    }
    impl Default for SolverSelector {
        fn default() -> Self {
            Self {
                category: SolverCategory::All,
                min_qubits: None,
                max_queue_time: None,
                online_only: true,
                name_pattern: None,
                topology_preference: None,
            }
        }
    }
    /// Problem embedding configuration
    #[derive(Debug, Clone)]
    pub struct EmbeddingConfig {
        /// Use automatic embedding
        pub auto_embed: bool,
        /// Embedding timeout
        pub timeout: Duration,
        /// Chain strength calculation method
        pub chain_strength_method: ChainStrengthMethod,
        /// Custom embedding (if not auto-embedding)
        pub custom_embedding: Option<Embedding>,
        /// Embedding optimization level
        pub optimization_level: usize,
    }
    /// Chain strength calculation methods
    #[derive(Debug, Clone)]
    pub enum ChainStrengthMethod {
        /// Automatic calculation
        Auto,
        /// Fixed value
        Fixed(f64),
        /// Based on problem coupling strengths
        Adaptive(f64),
    }
    impl Default for EmbeddingConfig {
        fn default() -> Self {
            Self {
                auto_embed: true,
                timeout: Duration::from_secs(30),
                chain_strength_method: ChainStrengthMethod::Auto,
                custom_embedding: None,
                optimization_level: 1,
            }
        }
    }
    /// Enhanced D-Wave Leap cloud service client
    #[derive(Debug)]
    pub struct DWaveClient {
        /// The HTTP client for making API requests
        client: Client,
        /// The API endpoint
        endpoint: String,
        /// The API token
        token: String,
        /// The tokio runtime for async requests
        runtime: Runtime,
        /// Default solver selector
        default_solver_selector: SolverSelector,
        /// Default embedding configuration
        default_embedding_config: EmbeddingConfig,
        /// Retry configuration
        max_retries: usize,
        /// Request timeout
        request_timeout: Duration,
        /// Default problem timeout
        problem_timeout: Duration,
    }
    impl DWaveClient {
        /// Create a new enhanced D-Wave Leap client
        pub fn new(token: impl Into<String>, endpoint: Option<String>) -> DWaveResult<Self> {
            Self::with_config(
                token,
                endpoint,
                SolverSelector::default(),
                EmbeddingConfig::default(),
            )
        }
        /// Create a D-Wave client with custom configuration
        pub fn with_config(
            token: impl Into<String>,
            endpoint: Option<String>,
            solver_selector: SolverSelector,
            embedding_config: EmbeddingConfig,
        ) -> DWaveResult<Self> {
            let client = Client::builder()
                .timeout(Duration::from_secs(300))
                .build()
                .map_err(DWaveError::NetworkError)?;
            let runtime = Runtime::new().map_err(|e| DWaveError::RuntimeError(e.to_string()))?;
            let endpoint =
                endpoint.unwrap_or_else(|| "https://cloud.dwavesys.com/sapi/v2".to_string());
            Ok(Self {
                client,
                endpoint,
                token: token.into(),
                runtime,
                default_solver_selector: solver_selector,
                default_embedding_config: embedding_config,
                max_retries: 3,
                request_timeout: Duration::from_secs(300),
                problem_timeout: Duration::from_secs(1800),
            })
        }
        /// Get a list of available solvers
        pub fn get_solvers(&self) -> DWaveResult<Vec<SolverInfo>> {
            let url = format!("{}/solvers/remote", self.endpoint);
            self.runtime.block_on(async {
                let response = self
                    .client
                    .get(&url)
                    .header("Authorization", format!("token {}", self.token))
                    .send()
                    .await?;
                if !response.status().is_success() {
                    let status = response.status();
                    let error_text = response.text().await?;
                    return Err(DWaveError::ApiError(format!(
                        "Error getting solvers: {status} - {error_text}"
                    )));
                }
                let solvers: Vec<SolverInfo> = response.json().await?;
                Ok(solvers)
            })
        }
        /// Submit an Ising model to D-Wave
        pub fn submit_ising(
            &self,
            model: &IsingModel,
            solver_id: &str,
            params: ProblemParams,
        ) -> DWaveResult<Solution> {
            let mut linear_terms = serde_json::Map::new();
            for (qubit, bias) in model.biases() {
                let value = serde_json::to_value(bias).map_err(|e| {
                    DWaveError::ProblemError(format!("Failed to serialize bias: {e}"))
                })?;
                linear_terms.insert(qubit.to_string(), value);
            }
            let mut quadratic_terms = serde_json::Map::new();
            for coupling in model.couplings() {
                let key = format!("{},{}", coupling.i, coupling.j);
                let value = serde_json::to_value(coupling.strength).map_err(|e| {
                    DWaveError::ProblemError(format!("Failed to serialize coupling: {e}"))
                })?;
                quadratic_terms.insert(key, value);
            }
            let problem = Problem {
                linear_terms: serde_json::Value::Object(linear_terms),
                quadratic_terms: serde_json::Value::Object(quadratic_terms),
                type_: "ising".to_string(),
                solver: solver_id.to_string(),
                params,
            };
            self.submit_problem(&problem)
        }
        /// Submit a QUBO model to D-Wave
        pub fn submit_qubo(
            &self,
            model: &QuboModel,
            solver_id: &str,
            params: ProblemParams,
        ) -> DWaveResult<Solution> {
            let mut linear_terms = serde_json::Map::new();
            for (var, value) in model.linear_terms() {
                let json_value = serde_json::to_value(value).map_err(|e| {
                    DWaveError::ProblemError(format!("Failed to serialize linear term: {e}"))
                })?;
                linear_terms.insert(var.to_string(), json_value);
            }
            let mut quadratic_terms = serde_json::Map::new();
            for (var1, var2, value) in model.quadratic_terms() {
                let key = format!("{var1},{var2}");
                let json_value = serde_json::to_value(value).map_err(|e| {
                    DWaveError::ProblemError(format!("Failed to serialize quadratic term: {e}"))
                })?;
                quadratic_terms.insert(key, json_value);
            }
            let problem = Problem {
                linear_terms: serde_json::Value::Object(linear_terms),
                quadratic_terms: serde_json::Value::Object(quadratic_terms),
                type_: "qubo".to_string(),
                solver: solver_id.to_string(),
                params,
            };
            self.submit_problem(&problem)
        }
        /// Submit an Ising model with flux bias optimization
        pub fn submit_ising_with_flux_bias(
            &self,
            model: &IsingModel,
            solver_id: &str,
            params: ProblemParams,
            flux_biases: &std::collections::HashMap<usize, f64>,
        ) -> DWaveResult<Solution> {
            let mut params_with_flux = params;
            let mut flux_map = serde_json::Map::new();
            for (qubit, &flux_bias) in flux_biases {
                let value = serde_json::to_value(flux_bias).map_err(|e| {
                    DWaveError::ProblemError(format!("Failed to serialize flux bias: {e}"))
                })?;
                flux_map.insert(qubit.to_string(), value);
            }
            params_with_flux.flux_bias_map = Some(flux_map);
            self.submit_ising(model, solver_id, params_with_flux)
        }
        /// Submit a problem to D-Wave
        fn submit_problem(&self, problem: &Problem) -> DWaveResult<Solution> {
            let url = format!("{}/problems", self.endpoint);
            self.runtime.block_on(async {
                let response = self
                    .client
                    .post(&url)
                    .header("Authorization", format!("token {}", self.token))
                    .header("Content-Type", "application/json")
                    .json(problem)
                    .send()
                    .await?;
                if !response.status().is_success() {
                    let status = response.status();
                    let error_text = response.text().await?;
                    return Err(DWaveError::ApiError(format!(
                        "Error submitting problem: {status} - {error_text}"
                    )));
                }
                let submit_response: serde_json::Value = response.json().await?;
                let problem_id = submit_response["id"].as_str().ok_or_else(|| {
                    let error_msg = String::from("Failed to extract problem ID from response");
                    DWaveError::ApiError(error_msg)
                })?;
                let result_url = format!("{}/problems/{}", self.endpoint, problem_id);
                let mut attempts = 0;
                const MAX_ATTEMPTS: usize = 60;
                while attempts < MAX_ATTEMPTS {
                    let status_response = self
                        .client
                        .get(&result_url)
                        .header("Authorization", format!("token {}", self.token))
                        .send()
                        .await?;
                    if !status_response.status().is_success() {
                        let status = status_response.status();
                        let error_text = status_response.text().await?;
                        return Err(DWaveError::ApiError(format!(
                            "Error getting problem status: {status} - {error_text}"
                        )));
                    }
                    let status: serde_json::Value = status_response.json().await?;
                    if let Some(state) = status["state"].as_str() {
                        if state == "COMPLETED" {
                            return Ok(Solution {
                                energies: serde_json::from_value(status["energies"].clone())?,
                                occurrences: serde_json::from_value(status["occurrences"].clone())?,
                                solutions: serde_json::from_value(status["solutions"].clone())?,
                                num_samples: status["num_samples"].as_u64().unwrap_or(0) as usize,
                                problem_id: problem_id.to_string(),
                                solver: problem.solver.clone(),
                                timing: status["timing"].clone(),
                            });
                        } else if state == "FAILED" {
                            let error = status["error"].as_str().unwrap_or("Unknown error");
                            return Err(DWaveError::ApiError(format!("Problem failed: {error}")));
                        }
                    }
                    tokio::time::sleep(Duration::from_secs(5)).await;
                    attempts += 1;
                }
                Err(DWaveError::ApiError(
                    "Timeout waiting for problem solution".into(),
                ))
            })
        }
        /// Get enhanced Leap solver information
        pub fn get_leap_solvers(&self) -> DWaveResult<Vec<LeapSolverInfo>> {
            let url = format!("{}/solvers/remote", self.endpoint);
            self.runtime.block_on(async {
                let response = self
                    .client
                    .get(&url)
                    .header("Authorization", format!("token {}", self.token))
                    .send()
                    .await?;
                if !response.status().is_success() {
                    let status = response.status();
                    let error_text = response.text().await?;
                    return Err(DWaveError::ApiError(format!(
                        "Error getting Leap solvers: {status} - {error_text}"
                    )));
                }
                let solvers: Vec<LeapSolverInfo> = response.json().await?;
                Ok(solvers)
            })
        }
        /// Select optimal solver based on criteria
        pub fn select_solver(
            &self,
            selector: Option<&SolverSelector>,
        ) -> DWaveResult<LeapSolverInfo> {
            let selector = selector.unwrap_or(&self.default_solver_selector);
            let solvers = self.get_leap_solvers()?;
            let filtered_solvers: Vec<_> = solvers
                .into_iter()
                .filter(|solver| {
                    let category_match = match selector.category {
                        SolverCategory::QPU => {
                            matches!(solver.solver_type, SolverType::QuantumProcessor)
                        }
                        SolverCategory::Hybrid => {
                            matches!(solver.solver_type, SolverType::Hybrid)
                        }
                        SolverCategory::Software => {
                            matches!(solver.solver_type, SolverType::Software)
                        }
                        SolverCategory::All => true,
                    };
                    let availability_match = !selector.online_only || solver.available;
                    let name_match = selector
                        .name_pattern
                        .as_ref()
                        .map(|pattern| solver.name.contains(pattern))
                        .unwrap_or(true);
                    let queue_match = selector
                        .max_queue_time
                        .map(|max_time| solver.avg_load.unwrap_or(0.0) <= max_time)
                        .unwrap_or(true);
                    category_match && availability_match && name_match && queue_match
                })
                .collect();
            if filtered_solvers.is_empty() {
                return Err(DWaveError::SolverConfigError(
                    "No solvers match the selection criteria".to_string(),
                ));
            }
            let mut best_solver = filtered_solvers[0].clone();
            for solver in &filtered_solvers[1..] {
                let current_load = best_solver.avg_load.unwrap_or(f64::INFINITY);
                let candidate_load = solver.avg_load.unwrap_or(f64::INFINITY);
                if candidate_load < current_load {
                    best_solver = solver.clone();
                }
            }
            Ok(best_solver)
        }
        /// Submit problem with automatic embedding
        pub fn submit_ising_with_embedding(
            &self,
            model: &IsingModel,
            solver_id: Option<&str>,
            params: Option<AdvancedProblemParams>,
            embedding_config: Option<&EmbeddingConfig>,
        ) -> DWaveResult<Solution> {
            let embedding_config = embedding_config.unwrap_or(&self.default_embedding_config);
            let solver = if let Some(id) = solver_id {
                self.get_leap_solvers()?
                    .into_iter()
                    .find(|s| s.id == id)
                    .ok_or_else(|| {
                        DWaveError::SolverConfigError(format!("Solver {id} not found"))
                    })?
            } else {
                self.select_solver(None)?
            };
            if matches!(solver.solver_type, SolverType::QuantumProcessor) {
                self.submit_with_auto_embedding(model, &solver, params, embedding_config)
            } else {
                let legacy_params = if let Some(p) = params {
                    let flux_bias_map = if let Some(fb) = p.flux_biases {
                        let mut map = serde_json::Map::new();
                        for (k, v) in fb {
                            let value = serde_json::to_value(v).map_err(|e| {
                                DWaveError::ProblemError(format!(
                                    "Failed to serialize flux bias: {e}"
                                ))
                            })?;
                            map.insert(k, value);
                        }
                        Some(map)
                    } else {
                        None
                    };
                    ProblemParams {
                        num_reads: p.num_reads,
                        annealing_time: 20,
                        programming_therm: p.programming_thermalization.unwrap_or(1000),
                        readout_therm: p.readout_thermalization.unwrap_or(0),
                        flux_biases: None,
                        flux_bias_map,
                        other: serde_json::Value::Object(serde_json::Map::new()),
                    }
                } else {
                    ProblemParams::default()
                };
                self.submit_ising(model, &solver.id, legacy_params)
            }
        }
        /// Submit with automatic embedding for QPU solvers
        fn submit_with_auto_embedding(
            &self,
            model: &IsingModel,
            solver: &LeapSolverInfo,
            params: Option<AdvancedProblemParams>,
            embedding_config: &EmbeddingConfig,
        ) -> DWaveResult<Solution> {
            let params = params.unwrap_or_default();
            let mut logical_edges = Vec::new();
            for coupling in model.couplings() {
                logical_edges.push((coupling.i, coupling.j));
            }
            let hardware_graph = self.get_solver_topology(&solver.id)?;
            let embedding = if let Some(custom_emb) = &embedding_config.custom_embedding {
                custom_emb.clone()
            } else {
                let embedder = MinorMiner {
                    max_tries: 10 * embedding_config.optimization_level,
                    ..Default::default()
                };
                embedder
                    .find_embedding(&logical_edges, model.num_qubits, &hardware_graph)
                    .map_err(|e| DWaveError::EmbeddingError(e.to_string()))?
            };
            let chain_strength =
                Self::calculate_chain_strength(model, &embedding_config.chain_strength_method);
            let embedded_problem = Self::embed_problem(model, &embedding, chain_strength)?;
            self.submit_embedded_problem(&embedded_problem, solver, params)
        }
        /// Get solver topology information
        fn get_solver_topology(&self, solver_id: &str) -> DWaveResult<HardwareGraph> {
            let url = format!("{}/solvers/remote/{}", self.endpoint, solver_id);
            let topology_info = self.runtime.block_on(async {
                let response = self
                    .client
                    .get(&url)
                    .header("Authorization", format!("token {}", self.token))
                    .send()
                    .await?;
                if !response.status().is_success() {
                    let status = response.status();
                    let error_text = response.text().await?;
                    return Err(DWaveError::ApiError(format!(
                        "Error getting solver topology: {status} - {error_text}"
                    )));
                }
                let solver_data: serde_json::Value = response.json().await?;
                Ok(solver_data)
            })?;
            let properties = &topology_info["properties"];
            if let Some(edges) = properties["couplers"].as_array() {
                let mut hardware_edges = Vec::new();
                for edge in edges {
                    if let (Some(i), Some(j)) = (edge[0].as_u64(), edge[1].as_u64()) {
                        hardware_edges.push((i as usize, j as usize));
                    }
                }
                let num_qubits = properties["qubits"]
                    .as_array()
                    .map(|arr| arr.len())
                    .unwrap_or(0);
                Ok(HardwareGraph::new_custom(num_qubits, hardware_edges))
            } else {
                Err(DWaveError::SolverConfigError(
                    "Could not parse solver topology".to_string(),
                ))
            }
        }
        /// Calculate appropriate chain strength
        fn calculate_chain_strength(model: &IsingModel, method: &ChainStrengthMethod) -> f64 {
            match method {
                ChainStrengthMethod::Auto => {
                    let max_coupling = model
                        .couplings()
                        .iter()
                        .map(|c| c.strength.abs())
                        .fold(0.0, f64::max);
                    let max_bias = (0..model.num_qubits)
                        .filter_map(|i| model.get_bias(i).ok())
                        .fold(0.0_f64, |acc, bias| acc.max(bias.abs()));
                    2.0 * (max_coupling.max(max_bias))
                }
                ChainStrengthMethod::Fixed(value) => *value,
                ChainStrengthMethod::Adaptive(multiplier) => {
                    let avg_coupling = model
                        .couplings()
                        .iter()
                        .map(|c| c.strength.abs())
                        .sum::<f64>()
                        / model.couplings().len().max(1) as f64;
                    multiplier * avg_coupling
                }
            }
        }
        /// Embed logical problem onto physical hardware
        fn embed_problem(
            model: &IsingModel,
            embedding: &Embedding,
            chain_strength: f64,
        ) -> DWaveResult<IsingModel> {
            let mut embedded_model = IsingModel::new(0);
            let max_qubit = embedding
                .chains
                .values()
                .flat_map(|chain| chain.iter())
                .max()
                .copied()
                .unwrap_or(0);
            embedded_model = IsingModel::new(max_qubit + 1);
            for (var, chain) in &embedding.chains {
                if let Ok(bias) = model.get_bias(*var) {
                    if bias != 0.0 {
                        let bias_per_qubit = bias / chain.len() as f64;
                        for &qubit in chain {
                            embedded_model
                                .set_bias(qubit, bias_per_qubit)
                                .map_err(|e| DWaveError::EmbeddingError(e.to_string()))?;
                        }
                    }
                }
            }
            for coupling in model.couplings() {
                if let (Some(chain1), Some(chain2)) = (
                    embedding.chains.get(&coupling.i),
                    embedding.chains.get(&coupling.j),
                ) {
                    for &q1 in chain1 {
                        for &q2 in chain2 {
                            embedded_model
                                .set_coupling(q1, q2, coupling.strength)
                                .map_err(|e| DWaveError::EmbeddingError(e.to_string()))?;
                        }
                    }
                }
            }
            for chain in embedding.chains.values() {
                for window in chain.windows(2) {
                    if let [q1, q2] = window {
                        embedded_model
                            .set_coupling(*q1, *q2, -chain_strength)
                            .map_err(|e| DWaveError::EmbeddingError(e.to_string()))?;
                    }
                }
            }
            Ok(embedded_model)
        }
        /// Submit an embedded problem
        fn submit_embedded_problem(
            &self,
            embedded_model: &IsingModel,
            solver: &LeapSolverInfo,
            params: AdvancedProblemParams,
        ) -> DWaveResult<Solution> {
            let flux_bias_map = if let Some(fb) = params.flux_biases {
                let mut map = serde_json::Map::new();
                for (k, v) in fb {
                    let value = serde_json::to_value(v).map_err(|e| {
                        DWaveError::ProblemError(format!("Failed to serialize flux bias: {e}"))
                    })?;
                    map.insert(k, value);
                }
                Some(map)
            } else {
                None
            };
            let legacy_params = ProblemParams {
                num_reads: params.num_reads,
                annealing_time: params
                    .anneal_schedule
                    .as_ref()
                    .and_then(|schedule| schedule.schedule.last())
                    .map(|(time, _)| *time as usize)
                    .unwrap_or(20),
                programming_therm: params.programming_thermalization.unwrap_or(1000),
                readout_therm: params.readout_thermalization.unwrap_or(0),
                flux_biases: None,
                flux_bias_map,
                other: serde_json::Value::Object(serde_json::Map::new()),
            };
            self.submit_ising(embedded_model, &solver.id, legacy_params)
        }
        /// Submit hybrid solver problem
        pub fn submit_hybrid(
            &self,
            model: &IsingModel,
            solver_id: Option<&str>,
            params: Option<HybridSolverParams>,
        ) -> DWaveResult<Solution> {
            let params = params.unwrap_or_default();
            let solver = if let Some(id) = solver_id {
                self.get_leap_solvers()?
                    .into_iter()
                    .find(|s| s.id == id)
                    .ok_or_else(|| {
                        DWaveError::SolverConfigError(format!("Solver {id} not found"))
                    })?
            } else {
                let hybrid_selector = SolverSelector {
                    category: SolverCategory::Hybrid,
                    ..Default::default()
                };
                self.select_solver(Some(&hybrid_selector))?
            };
            let mut linear_terms = serde_json::Map::new();
            for (qubit, bias) in model.biases() {
                let value = serde_json::to_value(bias).map_err(|e| {
                    DWaveError::ProblemError(format!("Failed to serialize bias: {e}"))
                })?;
                linear_terms.insert(qubit.to_string(), value);
            }
            let mut quadratic_terms = serde_json::Map::new();
            for coupling in model.couplings() {
                let key = format!("{},{}", coupling.i, coupling.j);
                let value = serde_json::to_value(coupling.strength).map_err(|e| {
                    DWaveError::ProblemError(format!("Failed to serialize coupling: {e}"))
                })?;
                quadratic_terms.insert(key, value);
            }
            let mut hybrid_params = params.extra.clone();
            if let Some(time_limit) = params.time_limit {
                let value = serde_json::to_value(time_limit).map_err(|e| {
                    DWaveError::ProblemError(format!("Failed to serialize time_limit: {e}"))
                })?;
                hybrid_params.insert("time_limit".to_string(), value);
            }
            let problem = Problem {
                linear_terms: serde_json::Value::Object(linear_terms),
                quadratic_terms: serde_json::Value::Object(quadratic_terms),
                type_: "ising".to_string(),
                solver: solver.id,
                params: ProblemParams {
                    num_reads: 1,
                    annealing_time: 1,
                    programming_therm: 0,
                    readout_therm: 0,
                    flux_biases: None,
                    flux_bias_map: None,
                    other: serde_json::Value::Object(
                        hybrid_params.into_iter().map(|(k, v)| (k, v)).collect(),
                    ),
                },
            };
            self.submit_problem(&problem)
        }
        /// Get problem status
        pub fn get_problem_status(&self, problem_id: &str) -> DWaveResult<ProblemInfo> {
            let url = format!("{}/problems/{}", self.endpoint, problem_id);
            self.runtime.block_on(async {
                let response = self
                    .client
                    .get(&url)
                    .header("Authorization", format!("token {}", self.token))
                    .send()
                    .await?;
                if !response.status().is_success() {
                    let status = response.status();
                    let error_text = response.text().await?;
                    return Err(DWaveError::ApiError(format!(
                        "Error getting problem status: {} - {}",
                        status, error_text
                    )));
                }
                let problem_info: ProblemInfo = response.json().await?;
                Ok(problem_info)
            })
        }
        /// Cancel a running problem
        pub fn cancel_problem(&self, problem_id: &str) -> DWaveResult<()> {
            let url = format!("{}/problems/{}/cancel", self.endpoint, problem_id);
            self.runtime.block_on(async {
                let response = self
                    .client
                    .delete(&url)
                    .header("Authorization", format!("token {}", self.token))
                    .send()
                    .await?;
                if !response.status().is_success() {
                    let status = response.status();
                    let error_text = response.text().await?;
                    return Err(DWaveError::ApiError(format!(
                        "Error cancelling problem: {} - {}",
                        status, error_text
                    )));
                }
                Ok(())
            })
        }
        /// Submit multiple problems in batch
        pub fn submit_batch(
            &self,
            problems: Vec<(&IsingModel, Option<&str>, Option<AdvancedProblemParams>)>,
        ) -> DWaveResult<BatchSubmissionResult> {
            let start_time = Instant::now();
            let mut problem_ids = Vec::new();
            let mut statuses = Vec::new();
            for (model, solver_id, params) in problems {
                match self.submit_ising_with_embedding(model, solver_id, params, None) {
                    Ok(solution) => {
                        problem_ids.push(solution.problem_id.clone());
                        statuses.push(Ok(solution.problem_id));
                    }
                    Err(e) => {
                        problem_ids.push(String::new());
                        statuses.push(Err(e));
                    }
                }
            }
            Ok(BatchSubmissionResult {
                problem_ids,
                statuses,
                submission_time: start_time.elapsed(),
            })
        }
        /// Get performance metrics for a completed problem
        pub fn get_problem_metrics(&self, problem_id: &str) -> DWaveResult<ProblemMetrics> {
            let solution = self.get_problem_result(problem_id)?;
            let timing = &solution.timing;
            let queue_time =
                Duration::from_micros(timing["qpu_access_overhead_time"].as_u64().unwrap_or(0));
            let programming_time =
                Duration::from_micros(timing["qpu_programming_time"].as_u64().unwrap_or(0));
            let sampling_time =
                Duration::from_micros(timing["qpu_sampling_time"].as_u64().unwrap_or(0));
            let readout_time =
                Duration::from_micros(timing["qpu_readout_time"].as_u64().unwrap_or(0));
            let total_time = queue_time + programming_time + sampling_time + readout_time;
            let access_time = programming_time + sampling_time + readout_time;
            let best_energy = solution
                .energies
                .iter()
                .min_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal))
                .copied()
                .unwrap_or(f64::INFINITY);
            Ok(ProblemMetrics {
                total_time,
                queue_time,
                access_time,
                programming_time,
                sampling_time,
                readout_time,
                best_energy,
                num_valid_solutions: solution.solutions.len(),
                chain_break_fraction: timing["chain_break_fraction"].as_f64(),
            })
        }
        /// Get problem result (blocking until completion)
        pub fn get_problem_result(&self, problem_id: &str) -> DWaveResult<Solution> {
            let start_time = Instant::now();
            loop {
                let status = self.get_problem_status(problem_id)?;
                match status.status {
                    ProblemStatus::Completed => {
                        return self.get_solution_data(problem_id);
                    }
                    ProblemStatus::Failed => {
                        return Err(DWaveError::StatusError(format!(
                            "Problem {} failed",
                            problem_id
                        )));
                    }
                    ProblemStatus::Cancelled => {
                        return Err(DWaveError::StatusError(format!(
                            "Problem {} was cancelled",
                            problem_id
                        )));
                    }
                    ProblemStatus::InProgress | ProblemStatus::Pending => {
                        if start_time.elapsed() > self.problem_timeout {
                            return Err(DWaveError::TimeoutError(format!(
                                "Timeout waiting for problem {} completion",
                                problem_id
                            )));
                        }
                        std::thread::sleep(Duration::from_secs(2));
                    }
                }
            }
        }
        /// Get solution data for a completed problem
        fn get_solution_data(&self, problem_id: &str) -> DWaveResult<Solution> {
            let url = format!("{}/problems/{}", self.endpoint, problem_id);
            self.runtime.block_on(async {
                let response = self
                    .client
                    .get(&url)
                    .header("Authorization", format!("token {}", self.token))
                    .send()
                    .await?;
                if !response.status().is_success() {
                    let status = response.status();
                    let error_text = response.text().await?;
                    return Err(DWaveError::ApiError(format!(
                        "Error getting solution data: {} - {}",
                        status, error_text
                    )));
                }
                let data: serde_json::Value = response.json().await?;
                Ok(Solution {
                    energies: serde_json::from_value(data["energies"].clone())?,
                    occurrences: serde_json::from_value(data["occurrences"].clone())?,
                    solutions: serde_json::from_value(data["solutions"].clone())?,
                    num_samples: data["num_samples"].as_u64().unwrap_or(0) as usize,
                    problem_id: problem_id.to_string(),
                    solver: data["solver"].as_str().unwrap_or("unknown").to_string(),
                    timing: data["timing"].clone(),
                })
            })
        }
        /// List recent problems
        pub fn list_problems(&self, limit: Option<usize>) -> DWaveResult<Vec<ProblemInfo>> {
            let mut url = format!("{}/problems", self.endpoint);
            if let Some(limit) = limit {
                let _ = write!(url, "?limit={}", limit);
            }
            self.runtime.block_on(async {
                let response = self
                    .client
                    .get(&url)
                    .header("Authorization", format!("token {}", self.token))
                    .send()
                    .await?;
                if !response.status().is_success() {
                    let status = response.status();
                    let error_text = response.text().await?;
                    return Err(DWaveError::ApiError(format!(
                        "Error listing problems: {} - {}",
                        status, error_text
                    )));
                }
                let problems: Vec<ProblemInfo> = response.json().await?;
                Ok(problems)
            })
        }
        /// Get account usage information
        pub fn get_usage_info(&self) -> DWaveResult<serde_json::Value> {
            let url = format!("{}/usage", self.endpoint);
            self.runtime.block_on(async {
                let response = self
                    .client
                    .get(&url)
                    .header("Authorization", format!("token {}", self.token))
                    .send()
                    .await?;
                if !response.status().is_success() {
                    let status = response.status();
                    let error_text = response.text().await?;
                    return Err(DWaveError::ApiError(format!(
                        "Error getting usage info: {} - {}",
                        status, error_text
                    )));
                }
                let usage: serde_json::Value = response.json().await?;
                Ok(usage)
            })
        }
    }
}
#[cfg(not(feature = "dwave"))]
mod placeholder {
    use thiserror::Error;
    /// Error type for when D-Wave feature is not enabled
    #[derive(Error, Debug)]
    pub enum DWaveError {
        /// Error when trying to use D-Wave without the feature enabled
        #[error("D-Wave feature not enabled. Recompile with '--features dwave'")]
        NotEnabled,
    }
    /// Result type for D-Wave operations
    pub type DWaveResult<T> = Result<T, DWaveError>;
    /// Placeholder for D-Wave client
    #[derive(Debug, Clone)]
    pub struct DWaveClient {
        _private: (),
    }
    impl DWaveClient {
        /// Placeholder for D-Wave client creation
        pub fn new(_token: impl Into<String>, _endpoint: Option<String>) -> DWaveResult<Self> {
            Err(DWaveError::NotEnabled)
        }
    }
    /// Placeholder for D-Wave problem submission parameters
    #[derive(Debug, Clone)]
    pub struct ProblemParams {
        /// Number of reads/samples to take
        pub num_reads: usize,
        /// Annealing time in microseconds
        pub annealing_time: usize,
        /// Programming thermalization in microseconds
        pub programming_therm: usize,
        /// Read-out thermalization in microseconds
        pub readout_therm: usize,
    }
    /// Placeholder types for enhanced Leap functionality (feature disabled)
    #[derive(Debug, Clone)]
    pub enum SolverType {
        QuantumProcessor,
        Hybrid,
        Software,
    }
    #[derive(Debug, Clone)]
    pub enum SolverCategory {
        QPU,
        Hybrid,
        Software,
        All,
    }
    #[derive(Debug, Clone)]
    pub enum ProblemStatus {
        InProgress,
        Completed,
        Failed,
        Cancelled,
        Pending,
    }
    #[derive(Debug, Clone)]
    pub struct SolverSelector;
    #[derive(Debug, Clone)]
    pub struct EmbeddingConfig;
    #[derive(Debug, Clone)]
    pub struct AdvancedProblemParams;
    #[derive(Debug, Clone)]
    pub struct HybridSolverParams;
    #[derive(Debug, Clone)]
    pub struct LeapSolverInfo;
    #[derive(Debug, Clone)]
    pub struct ProblemInfo;
    #[derive(Debug, Clone)]
    pub struct AnnealingSchedule;
    #[derive(Debug, Clone)]
    pub struct ProblemMetrics;
    #[derive(Debug, Clone)]
    pub struct BatchSubmissionResult;
    #[derive(Debug, Clone)]
    pub enum ChainStrengthMethod {
        Auto,
        Fixed(f64),
        Adaptive(f64),
    }
    impl Default for ProblemParams {
        fn default() -> Self {
            Self {
                num_reads: 1000,
                annealing_time: 20,
                programming_therm: 1000,
                readout_therm: 0,
            }
        }
    }
}
/// Check if D-Wave API support is enabled
#[must_use]
pub const fn is_available() -> bool {
    cfg!(feature = "dwave")
}