1use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8use std::f64::consts::PI;
9use thiserror::Error;
10
11use super::continuous_variable::{Complex, GaussianState};
12use super::gate_based::{PhotonicQubitEncoding, PhotonicQubitState};
13use super::{PhotonicMode, PhotonicSystemType};
14use crate::DeviceResult;
15
16#[derive(Error, Debug)]
18pub enum EncodingError {
19 #[error("Invalid encoding parameters: {0}")]
20 InvalidParameters(String),
21 #[error("Encoding not supported: {0}")]
22 UnsupportedEncoding(String),
23 #[error("Decoding failed: {0}")]
24 DecodingFailed(String),
25 #[error("Insufficient physical qubits: {0}")]
26 InsufficientQubits(String),
27 #[error("Code distance too small: {0}")]
28 CodeDistanceTooSmall(usize),
29}
30
31type EncodingResult<T> = Result<T, EncodingError>;
32
33#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
35pub enum PhotonicQECCode {
36 Repetition { distance: usize },
38 Surface { distance: usize },
40 Color { distance: usize },
42 Concatenated {
44 inner_code: Box<Self>,
45 outer_code: Box<Self>,
46 levels: usize,
47 },
48 ContinuousVariable {
50 code_type: CVCodeType,
51 parameters: CVCodeParameters,
52 },
53 Bosonic {
55 code_type: BosonicCodeType,
56 cutoff: usize,
57 },
58}
59
60#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
62pub enum CVCodeType {
63 GKP,
65 Cat,
67 Binomial,
69 CoherentState,
71}
72
73#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct CVCodeParameters {
76 pub squeezing: f64,
78 pub displacement: Complex,
80 pub loss_tolerance: f64,
82 pub code_rate: f64,
84}
85
86impl PartialEq for CVCodeParameters {
87 fn eq(&self, other: &Self) -> bool {
88 self.squeezing == other.squeezing
89 && self.displacement.real == other.displacement.real
90 && self.displacement.imag == other.displacement.imag
91 && self.loss_tolerance == other.loss_tolerance
92 && self.code_rate == other.code_rate
93 }
94}
95
96#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
98pub enum BosonicCodeType {
99 Fock { basis_states: Vec<usize> },
101 Coherent { alpha_values: Vec<Complex> },
103 Squeezed { squeezing_params: Vec<(f64, f64)> },
105}
106
107#[derive(Debug, Clone, Serialize, Deserialize)]
109pub struct LogicalQubit {
110 pub encoding: PhotonicQECCode,
112 pub physical_qubits: Vec<usize>,
114 pub logical_state: LogicalState,
116 pub syndrome: Option<ErrorSyndrome>,
118}
119
120#[derive(Debug, Clone, Serialize, Deserialize)]
122pub struct LogicalState {
123 pub amplitude_0: f64,
125 pub amplitude_1: f64,
127 pub phase: f64,
129 pub fidelity: f64,
131}
132
133impl LogicalState {
134 pub const fn zero() -> Self {
136 Self {
137 amplitude_0: 1.0,
138 amplitude_1: 0.0,
139 phase: 0.0,
140 fidelity: 1.0,
141 }
142 }
143
144 pub const fn one() -> Self {
146 Self {
147 amplitude_0: 0.0,
148 amplitude_1: 1.0,
149 phase: 0.0,
150 fidelity: 1.0,
151 }
152 }
153
154 pub fn plus() -> Self {
156 Self {
157 amplitude_0: 1.0 / (2.0_f64).sqrt(),
158 amplitude_1: 1.0 / (2.0_f64).sqrt(),
159 phase: 0.0,
160 fidelity: 1.0,
161 }
162 }
163
164 pub fn arbitrary(amplitude_0: f64, amplitude_1: f64, phase: f64) -> EncodingResult<Self> {
166 let norm_squared = amplitude_0.mul_add(amplitude_0, amplitude_1 * amplitude_1);
167 if (norm_squared - 1.0).abs() > 1e-6 {
168 return Err(EncodingError::InvalidParameters(
169 "State amplitudes not normalized".to_string(),
170 ));
171 }
172
173 Ok(Self {
174 amplitude_0,
175 amplitude_1,
176 phase,
177 fidelity: 1.0,
178 })
179 }
180
181 pub fn prob_zero(&self) -> f64 {
183 self.amplitude_0 * self.amplitude_0
184 }
185
186 pub fn prob_one(&self) -> f64 {
188 self.amplitude_1 * self.amplitude_1
189 }
190}
191
192#[derive(Debug, Clone, Serialize, Deserialize)]
194pub struct ErrorSyndrome {
195 pub syndrome_bits: Vec<bool>,
197 pub error_type: Option<ErrorType>,
199 pub error_location: Option<Vec<usize>>,
201 pub correction_applied: Option<Correction>,
203}
204
205#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
207pub enum ErrorType {
208 BitFlip,
210 PhaseFlip,
212 Combined,
214 AmplitudeDamping,
216 PhaseDamping,
218 PhotonLoss,
220 ThermalNoise,
222}
223
224#[derive(Debug, Clone, Serialize, Deserialize)]
226pub struct Correction {
227 pub correction_type: ErrorType,
229 pub target_qubits: Vec<usize>,
231 pub parameters: Vec<f64>,
233}
234
235pub struct PhotonicEncoder {
237 pub available_codes: Vec<PhotonicQECCode>,
239 pub performance_cache: HashMap<String, EncodingPerformance>,
241}
242
243#[derive(Debug, Clone, Serialize, Deserialize)]
245pub struct EncodingPerformance {
246 pub distance: usize,
248 pub rate: f64,
250 pub threshold: f64,
252 pub overhead: usize,
254 pub encoding_fidelity: f64,
256 pub decoding_fidelity: f64,
258}
259
260impl PhotonicEncoder {
261 pub fn new() -> Self {
262 let available_codes = vec![
263 PhotonicQECCode::Repetition { distance: 3 },
264 PhotonicQECCode::Repetition { distance: 5 },
265 PhotonicQECCode::Surface { distance: 3 },
266 PhotonicQECCode::Surface { distance: 5 },
267 PhotonicQECCode::ContinuousVariable {
268 code_type: CVCodeType::GKP,
269 parameters: CVCodeParameters {
270 squeezing: 10.0,
271 displacement: Complex::new(0.0, 0.0),
272 loss_tolerance: 0.1,
273 code_rate: 1.0,
274 },
275 },
276 PhotonicQECCode::Bosonic {
277 code_type: BosonicCodeType::Coherent {
278 alpha_values: vec![Complex::new(2.0, 0.0), Complex::new(-2.0, 0.0)],
279 },
280 cutoff: 10,
281 },
282 ];
283
284 Self {
285 available_codes,
286 performance_cache: HashMap::new(),
287 }
288 }
289
290 pub fn encode_logical_qubit(
292 &self,
293 logical_state: LogicalState,
294 code: &PhotonicQECCode,
295 physical_qubits: Vec<usize>,
296 ) -> EncodingResult<LogicalQubit> {
297 let required_qubits = self.get_required_physical_qubits(code)?;
299 if physical_qubits.len() < required_qubits {
300 return Err(EncodingError::InsufficientQubits(format!(
301 "Need {} qubits, got {}",
302 required_qubits,
303 physical_qubits.len()
304 )));
305 }
306
307 match code {
308 PhotonicQECCode::Repetition { distance } => {
309 self.encode_repetition_code(logical_state, *distance, physical_qubits)
310 }
311 PhotonicQECCode::Surface { distance } => {
312 self.encode_surface_code(logical_state, *distance, physical_qubits)
313 }
314 PhotonicQECCode::ContinuousVariable {
315 code_type,
316 parameters,
317 } => self.encode_cv_code(logical_state, code_type, parameters, physical_qubits),
318 PhotonicQECCode::Bosonic { code_type, cutoff } => {
319 self.encode_bosonic_code(logical_state, code_type, *cutoff, physical_qubits)
320 }
321 PhotonicQECCode::Concatenated {
322 inner_code,
323 outer_code,
324 levels,
325 } => self.encode_concatenated_code(
326 logical_state,
327 inner_code,
328 outer_code,
329 *levels,
330 physical_qubits,
331 ),
332 PhotonicQECCode::Color { .. } => Err(EncodingError::UnsupportedEncoding(format!(
333 "Code {code:?} not yet implemented"
334 ))),
335 }
336 }
337
338 fn encode_repetition_code(
340 &self,
341 logical_state: LogicalState,
342 distance: usize,
343 physical_qubits: Vec<usize>,
344 ) -> EncodingResult<LogicalQubit> {
345 if distance % 2 == 0 {
346 return Err(EncodingError::CodeDistanceTooSmall(distance));
347 }
348
349 let encoding_fidelity = 0.99; let logical_state_encoded = LogicalState {
353 fidelity: logical_state.fidelity * encoding_fidelity,
354 ..logical_state
355 };
356
357 Ok(LogicalQubit {
358 encoding: PhotonicQECCode::Repetition { distance },
359 physical_qubits: physical_qubits[0..distance].to_vec(),
360 logical_state: logical_state_encoded,
361 syndrome: None,
362 })
363 }
364
365 fn encode_surface_code(
367 &self,
368 logical_state: LogicalState,
369 distance: usize,
370 physical_qubits: Vec<usize>,
371 ) -> EncodingResult<LogicalQubit> {
372 if distance < 3 {
373 return Err(EncodingError::CodeDistanceTooSmall(distance));
374 }
375
376 let required_qubits = 2 * distance * distance - 1;
378 let encoding_fidelity = 0.95; let logical_state_encoded = LogicalState {
381 fidelity: logical_state.fidelity * encoding_fidelity,
382 ..logical_state
383 };
384
385 Ok(LogicalQubit {
386 encoding: PhotonicQECCode::Surface { distance },
387 physical_qubits: physical_qubits[0..required_qubits].to_vec(),
388 logical_state: logical_state_encoded,
389 syndrome: None,
390 })
391 }
392
393 fn encode_cv_code(
395 &self,
396 logical_state: LogicalState,
397 code_type: &CVCodeType,
398 parameters: &CVCodeParameters,
399 physical_modes: Vec<usize>,
400 ) -> EncodingResult<LogicalQubit> {
401 match code_type {
402 CVCodeType::GKP => {
403 let encoding_fidelity = 0.85; let logical_state_encoded = LogicalState {
407 fidelity: logical_state.fidelity * encoding_fidelity,
408 ..logical_state
409 };
410
411 Ok(LogicalQubit {
412 encoding: PhotonicQECCode::ContinuousVariable {
413 code_type: code_type.clone(),
414 parameters: parameters.clone(),
415 },
416 physical_qubits: physical_modes[0..1].to_vec(), logical_state: logical_state_encoded,
418 syndrome: None,
419 })
420 }
421 CVCodeType::Cat => {
422 let encoding_fidelity = 0.90;
424
425 let logical_state_encoded = LogicalState {
426 fidelity: logical_state.fidelity * encoding_fidelity,
427 ..logical_state
428 };
429
430 Ok(LogicalQubit {
431 encoding: PhotonicQECCode::ContinuousVariable {
432 code_type: code_type.clone(),
433 parameters: parameters.clone(),
434 },
435 physical_qubits: physical_modes[0..1].to_vec(),
436 logical_state: logical_state_encoded,
437 syndrome: None,
438 })
439 }
440 _ => Err(EncodingError::UnsupportedEncoding(format!(
441 "CV code {code_type:?} not implemented"
442 ))),
443 }
444 }
445
446 fn encode_bosonic_code(
448 &self,
449 logical_state: LogicalState,
450 code_type: &BosonicCodeType,
451 cutoff: usize,
452 physical_modes: Vec<usize>,
453 ) -> EncodingResult<LogicalQubit> {
454 match code_type {
455 BosonicCodeType::Coherent { alpha_values } => {
456 if alpha_values.len() < 2 {
457 return Err(EncodingError::InvalidParameters(
458 "Coherent state code requires at least 2 alpha values".to_string(),
459 ));
460 }
461
462 let encoding_fidelity = 0.88;
463
464 let logical_state_encoded = LogicalState {
465 fidelity: logical_state.fidelity * encoding_fidelity,
466 ..logical_state
467 };
468
469 Ok(LogicalQubit {
470 encoding: PhotonicQECCode::Bosonic {
471 code_type: code_type.clone(),
472 cutoff,
473 },
474 physical_qubits: physical_modes[0..1].to_vec(),
475 logical_state: logical_state_encoded,
476 syndrome: None,
477 })
478 }
479 _ => Err(EncodingError::UnsupportedEncoding(format!(
480 "Bosonic code {code_type:?} not implemented"
481 ))),
482 }
483 }
484
485 fn encode_concatenated_code(
487 &self,
488 logical_state: LogicalState,
489 inner_code: &PhotonicQECCode,
490 outer_code: &PhotonicQECCode,
491 levels: usize,
492 physical_qubits: Vec<usize>,
493 ) -> EncodingResult<LogicalQubit> {
494 if levels == 0 {
495 return Err(EncodingError::InvalidParameters(
496 "Concatenation levels must be > 0".to_string(),
497 ));
498 }
499
500 let inner_required = self.get_required_physical_qubits(inner_code)?;
502 let outer_required = self.get_required_physical_qubits(outer_code)?;
503 let total_required = inner_required * outer_required;
504
505 if physical_qubits.len() < total_required {
506 return Err(EncodingError::InsufficientQubits(format!(
507 "Concatenated code needs {total_required} qubits"
508 )));
509 }
510
511 let encoding_fidelity = 0.80;
513
514 let logical_state_encoded = LogicalState {
515 fidelity: logical_state.fidelity * encoding_fidelity,
516 ..logical_state
517 };
518
519 Ok(LogicalQubit {
520 encoding: PhotonicQECCode::Concatenated {
521 inner_code: Box::new(inner_code.clone()),
522 outer_code: Box::new(outer_code.clone()),
523 levels,
524 },
525 physical_qubits: physical_qubits[0..total_required].to_vec(),
526 logical_state: logical_state_encoded,
527 syndrome: None,
528 })
529 }
530
531 pub fn decode_logical_qubit(
533 &self,
534 logical_qubit: &LogicalQubit,
535 ) -> EncodingResult<LogicalState> {
536 let mut corrected_state = logical_qubit.logical_state.clone();
538
539 if let Some(syndrome) = &logical_qubit.syndrome {
540 corrected_state = self.apply_error_correction(corrected_state, syndrome)?;
541 }
542
543 let decoding_fidelity = self.get_decoding_fidelity(&logical_qubit.encoding)?;
545 corrected_state.fidelity *= decoding_fidelity;
546
547 Ok(corrected_state)
548 }
549
550 fn apply_error_correction(
552 &self,
553 logical_state: LogicalState,
554 syndrome: &ErrorSyndrome,
555 ) -> EncodingResult<LogicalState> {
556 let mut corrected_state = logical_state;
557
558 if let Some(correction) = &syndrome.correction_applied {
559 match correction.correction_type {
560 ErrorType::BitFlip => {
561 std::mem::swap(
563 &mut corrected_state.amplitude_0,
564 &mut corrected_state.amplitude_1,
565 );
566 }
567 ErrorType::PhaseFlip => {
568 corrected_state.phase += PI;
570 }
571 ErrorType::PhotonLoss => {
572 corrected_state.fidelity *= 0.9;
574 }
575 _ => {
576 corrected_state.fidelity *= 0.95;
578 }
579 }
580 }
581
582 Ok(corrected_state)
583 }
584
585 pub fn get_required_physical_qubits(&self, code: &PhotonicQECCode) -> EncodingResult<usize> {
587 match code {
588 PhotonicQECCode::Repetition { distance } => Ok(*distance),
589 PhotonicQECCode::Surface { distance } => Ok(2 * distance * distance - 1),
590 PhotonicQECCode::Color { distance } => Ok(3 * distance * distance / 2),
591 PhotonicQECCode::ContinuousVariable { .. } | PhotonicQECCode::Bosonic { .. } => Ok(1), PhotonicQECCode::Concatenated {
593 inner_code,
594 outer_code,
595 ..
596 } => {
597 let inner_qubits = self.get_required_physical_qubits(inner_code)?;
598 let outer_qubits = self.get_required_physical_qubits(outer_code)?;
599 Ok(inner_qubits * outer_qubits)
600 }
601 }
602 }
603
604 const fn get_decoding_fidelity(&self, code: &PhotonicQECCode) -> EncodingResult<f64> {
606 match code {
607 PhotonicQECCode::Repetition { .. } => Ok(0.995),
608 PhotonicQECCode::Surface { .. } => Ok(0.99),
609 PhotonicQECCode::ContinuousVariable { code_type, .. } => match code_type {
610 CVCodeType::GKP => Ok(0.90),
611 CVCodeType::Cat => Ok(0.92),
612 _ => Ok(0.85),
613 },
614 PhotonicQECCode::Bosonic { .. } => Ok(0.88),
615 PhotonicQECCode::Concatenated { .. } => Ok(0.85),
616 PhotonicQECCode::Color { .. } => Ok(0.80),
617 }
618 }
619
620 pub fn calculate_syndrome(
622 &self,
623 logical_qubit: &LogicalQubit,
624 ) -> EncodingResult<ErrorSyndrome> {
625 match &logical_qubit.encoding {
626 PhotonicQECCode::Repetition { distance } => {
627 self.calculate_repetition_syndrome(logical_qubit, *distance)
628 }
629 PhotonicQECCode::Surface { distance } => {
630 self.calculate_surface_syndrome(logical_qubit, *distance)
631 }
632 _ => {
633 Ok(ErrorSyndrome {
635 syndrome_bits: vec![false; 4], error_type: None,
637 error_location: None,
638 correction_applied: None,
639 })
640 }
641 }
642 }
643
644 fn calculate_repetition_syndrome(
646 &self,
647 logical_qubit: &LogicalQubit,
648 distance: usize,
649 ) -> EncodingResult<ErrorSyndrome> {
650 let syndrome_bits = vec![false; distance - 1]; let error_detected = logical_qubit.logical_state.fidelity < 0.95;
655
656 let error_type = if error_detected {
657 Some(ErrorType::BitFlip)
658 } else {
659 None
660 };
661
662 Ok(ErrorSyndrome {
663 syndrome_bits,
664 error_type,
665 error_location: None,
666 correction_applied: None,
667 })
668 }
669
670 fn calculate_surface_syndrome(
672 &self,
673 logical_qubit: &LogicalQubit,
674 distance: usize,
675 ) -> EncodingResult<ErrorSyndrome> {
676 let num_syndromes = distance * distance - 1;
678 let syndrome_bits = vec![false; num_syndromes];
679
680 let error_detected = logical_qubit.logical_state.fidelity < 0.90;
682
683 let error_type = if error_detected {
684 Some(ErrorType::Combined) } else {
686 None
687 };
688
689 Ok(ErrorSyndrome {
690 syndrome_bits,
691 error_type,
692 error_location: None,
693 correction_applied: None,
694 })
695 }
696
697 pub fn get_performance(&self, code: &PhotonicQECCode) -> EncodingResult<EncodingPerformance> {
699 let cache_key = format!("{code:?}");
700
701 if let Some(performance) = self.performance_cache.get(&cache_key) {
702 return Ok(performance.clone());
703 }
704
705 let performance = match code {
707 PhotonicQECCode::Repetition { distance } => EncodingPerformance {
708 distance: *distance,
709 rate: 1.0 / (*distance as f64),
710 threshold: 0.5, overhead: *distance,
712 encoding_fidelity: 0.99,
713 decoding_fidelity: 0.995,
714 },
715 PhotonicQECCode::Surface { distance } => EncodingPerformance {
716 distance: *distance,
717 rate: 1.0 / ((2 * distance * distance - 1) as f64),
718 threshold: 0.11, overhead: 2 * distance * distance - 1,
720 encoding_fidelity: 0.95,
721 decoding_fidelity: 0.99,
722 },
723 _ => EncodingPerformance {
724 distance: 3,
725 rate: 0.5,
726 threshold: 0.1,
727 overhead: 10,
728 encoding_fidelity: 0.90,
729 decoding_fidelity: 0.85,
730 },
731 };
732
733 Ok(performance)
734 }
735}
736
737impl Default for PhotonicEncoder {
738 fn default() -> Self {
739 Self::new()
740 }
741}
742
743#[cfg(test)]
744mod tests {
745 use super::*;
746
747 #[test]
748 fn test_logical_state_creation() {
749 let zero = LogicalState::zero();
750 assert_eq!(zero.prob_zero(), 1.0);
751 assert_eq!(zero.prob_one(), 0.0);
752
753 let one = LogicalState::one();
754 assert_eq!(one.prob_zero(), 0.0);
755 assert_eq!(one.prob_one(), 1.0);
756
757 let plus = LogicalState::plus();
758 assert!((plus.prob_zero() - 0.5).abs() < 1e-10);
759 assert!((plus.prob_one() - 0.5).abs() < 1e-10);
760 }
761
762 #[test]
763 fn test_encoder_creation() {
764 let encoder = PhotonicEncoder::new();
765 assert!(!encoder.available_codes.is_empty());
766 }
767
768 #[test]
769 fn test_repetition_code_encoding() {
770 let encoder = PhotonicEncoder::new();
771 let logical_state = LogicalState::zero();
772 let code = PhotonicQECCode::Repetition { distance: 3 };
773 let physical_qubits = vec![0, 1, 2];
774
775 let encoded = encoder
776 .encode_logical_qubit(logical_state, &code, physical_qubits)
777 .expect("Repetition code encoding should succeed");
778 assert_eq!(encoded.physical_qubits.len(), 3);
779 assert!(matches!(
780 encoded.encoding,
781 PhotonicQECCode::Repetition { distance: 3 }
782 ));
783 }
784
785 #[test]
786 fn test_surface_code_encoding() {
787 let encoder = PhotonicEncoder::new();
788 let logical_state = LogicalState::plus();
789 let code = PhotonicQECCode::Surface { distance: 3 };
790 let physical_qubits: Vec<usize> = (0..17).collect(); let encoded = encoder
793 .encode_logical_qubit(logical_state, &code, physical_qubits)
794 .expect("Surface code encoding should succeed");
795 assert_eq!(encoded.physical_qubits.len(), 17);
796 }
797
798 #[test]
799 fn test_cv_code_encoding() {
800 let encoder = PhotonicEncoder::new();
801 let logical_state = LogicalState::zero();
802 let code = PhotonicQECCode::ContinuousVariable {
803 code_type: CVCodeType::GKP,
804 parameters: CVCodeParameters {
805 squeezing: 10.0,
806 displacement: Complex::new(0.0, 0.0),
807 loss_tolerance: 0.1,
808 code_rate: 1.0,
809 },
810 };
811 let physical_modes = vec![0];
812
813 let encoded = encoder
814 .encode_logical_qubit(logical_state, &code, physical_modes)
815 .expect("CV code encoding should succeed");
816 assert_eq!(encoded.physical_qubits.len(), 1);
817 }
818
819 #[test]
820 fn test_performance_calculation() {
821 let encoder = PhotonicEncoder::new();
822 let code = PhotonicQECCode::Repetition { distance: 5 };
823
824 let performance = encoder
825 .get_performance(&code)
826 .expect("Performance calculation should succeed");
827 assert_eq!(performance.distance, 5);
828 assert_eq!(performance.rate, 0.2); assert_eq!(performance.overhead, 5);
830 }
831
832 #[test]
833 fn test_syndrome_calculation() {
834 let encoder = PhotonicEncoder::new();
835 let logical_state = LogicalState::zero();
836 let code = PhotonicQECCode::Repetition { distance: 3 };
837 let encoded = encoder
838 .encode_logical_qubit(logical_state, &code, vec![0, 1, 2])
839 .expect("Repetition code encoding should succeed");
840
841 let syndrome = encoder
842 .calculate_syndrome(&encoded)
843 .expect("Syndrome calculation should succeed");
844 assert_eq!(syndrome.syndrome_bits.len(), 2); }
846
847 #[test]
848 fn test_decoding() {
849 let encoder = PhotonicEncoder::new();
850 let original_state = LogicalState::plus();
851 let code = PhotonicQECCode::Repetition { distance: 3 };
852 let encoded = encoder
853 .encode_logical_qubit(original_state.clone(), &code, vec![0, 1, 2])
854 .expect("Repetition code encoding should succeed");
855
856 let decoded = encoder
857 .decode_logical_qubit(&encoded)
858 .expect("Decoding should succeed");
859 assert!((decoded.prob_zero() - original_state.prob_zero()).abs() < 0.1);
860 assert!((decoded.prob_one() - original_state.prob_one()).abs() < 0.1);
861 }
862}