1#![allow(clippy::too_many_arguments)]
2
3#[allow(unused_imports)]
4use core::pin::Pin;
5use cxx::UniquePtr;
6
7pub use ffi::{
8 BitTableData, CircuitErrorLocationData, CircuitErrorLocationStackFrameData,
9 CircuitTargetsInsideInstructionData, CircuitTopLevelItemData, CoordinateEntryData,
10 DemSampleBatch, DemTargetWithCoordsData, DemTopLevelItemData, DetectingRegionEntryData,
11 ExplainedErrorData, FlippedMeasurementData, GateTargetWithCoordsData,
12};
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub struct BuildMetadata {
16 pub crate_name: &'static str,
17 pub cxx_standard: &'static str,
18 pub target: &'static str,
19 pub vendor_stim_mode: &'static str,
20 pub vendor_stim_dir: &'static str,
21}
22
23pub fn build_metadata() -> BuildMetadata {
24 BuildMetadata {
25 crate_name: env!("CARGO_PKG_NAME"),
26 cxx_standard: env!("STIM_RS_CXX_STANDARD"),
27 target: env!("STIM_RS_TARGET"),
28 vendor_stim_mode: env!("STIM_RS_VENDOR_STIM_MODE"),
29 vendor_stim_dir: env!("STIM_RS_VENDOR_STIM_DIR"),
30 }
31}
32
33pub fn pinned_stim_commit() -> &'static str {
34 env!("STIM_RS_PINNED_STIM_COMMIT")
35}
36
37pub fn read_shot_data_file_bit_packed(
38 filepath: &str,
39 format_name: &str,
40 num_measurements: u64,
41 num_detectors: u64,
42 num_observables: u64,
43) -> Result<Vec<u8>, cxx::Exception> {
44 ffi::read_shot_data_file_bit_packed(
45 filepath,
46 format_name,
47 num_measurements,
48 num_detectors,
49 num_observables,
50 )
51}
52
53pub fn write_shot_data_file_bit_packed(
54 data: &[u8],
55 shots: u64,
56 filepath: &str,
57 format_name: &str,
58 num_measurements: u64,
59 num_detectors: u64,
60 num_observables: u64,
61) -> Result<(), cxx::Exception> {
62 ffi::write_shot_data_file_bit_packed(
63 data,
64 shots,
65 filepath,
66 format_name,
67 num_measurements,
68 num_detectors,
69 num_observables,
70 )
71}
72
73pub fn all_gate_names() -> Vec<String> {
74 ffi::all_gate_names()
75}
76
77pub fn canonicalize_flow_text(text: &str) -> Result<String, cxx::Exception> {
78 ffi::canonicalize_flow_text(text)
79}
80
81pub fn multiply_flow_texts(left: &str, right: &str) -> Result<String, cxx::Exception> {
82 ffi::multiply_flow_texts(left, right)
83}
84
85pub struct Circuit {
86 inner: UniquePtr<ffi::CircuitHandle>,
87}
88
89pub struct DetectorErrorModel {
90 inner: UniquePtr<ffi::DetectorErrorModelHandle>,
91}
92
93pub struct Tableau {
94 inner: UniquePtr<ffi::TableauHandle>,
95}
96
97pub struct TableauSimulator {
98 inner: UniquePtr<ffi::TableauSimulatorHandle>,
99}
100
101pub struct FlipSimulator {
102 inner: UniquePtr<ffi::FrameSimulatorHandle>,
103}
104
105pub struct PauliString {
106 inner: UniquePtr<ffi::PauliStringHandle>,
107}
108
109pub struct CliffordString {
110 inner: UniquePtr<ffi::CliffordStringHandle>,
111}
112
113pub struct PauliStringIterator {
114 inner: UniquePtr<ffi::PauliStringIteratorHandle>,
115}
116
117pub struct TableauIterator {
118 inner: UniquePtr<ffi::TableauIteratorHandle>,
119}
120
121pub struct MeasurementSampler {
122 inner: UniquePtr<ffi::MeasurementSamplerHandle>,
123}
124
125pub struct DetectorSampler {
126 inner: UniquePtr<ffi::DetectorSamplerHandle>,
127}
128
129pub struct DemSampler {
130 inner: UniquePtr<ffi::DemSamplerHandle>,
131}
132
133pub struct MeasurementsToDetectionEventsConverter {
134 inner: UniquePtr<ffi::MeasurementsToDetectionEventsConverterHandle>,
135}
136
137pub struct GateData {
138 inner: UniquePtr<ffi::GateDataHandle>,
139}
140
141impl MeasurementSampler {
142 #[must_use]
143 pub fn num_measurements(&self) -> u64 {
144 ffi::measurement_sampler_num_measurements(self.inner())
145 }
146
147 #[must_use]
148 pub fn sample_bit_packed(&mut self, shots: u64) -> Vec<u8> {
149 ffi::measurement_sampler_sample_bit_packed(self.inner.pin_mut(), shots)
150 }
151
152 pub fn sample_write(
153 &mut self,
154 shots: u64,
155 filepath: &str,
156 format_name: &str,
157 ) -> Result<(), cxx::Exception> {
158 ffi::measurement_sampler_sample_write(self.inner.pin_mut(), shots, filepath, format_name)
159 }
160
161 fn inner(&self) -> &ffi::MeasurementSamplerHandle {
162 self.inner
163 .as_ref()
164 .expect("stim-cxx measurement sampler construction returned null")
165 }
166}
167
168impl DetectorSampler {
169 #[must_use]
170 pub fn num_detectors(&self) -> u64 {
171 ffi::detector_sampler_num_detectors(self.inner())
172 }
173
174 #[must_use]
175 pub fn num_observables(&self) -> u64 {
176 ffi::detector_sampler_num_observables(self.inner())
177 }
178
179 #[must_use]
180 pub fn sample_bit_packed(&mut self, shots: u64) -> Vec<u8> {
181 ffi::detector_sampler_sample_bit_packed(self.inner.pin_mut(), shots)
182 }
183
184 #[must_use]
185 pub fn sample_observables_bit_packed(&mut self, shots: u64) -> Vec<u8> {
186 ffi::detector_sampler_sample_observables_bit_packed(self.inner.pin_mut(), shots)
187 }
188
189 #[must_use]
190 pub fn sample_bit_packed_separate_observables(&mut self, shots: u64) -> (Vec<u8>, Vec<u8>) {
191 let batch = ffi::detector_sampler_sample_bit_packed_separate_observables(
192 self.inner.pin_mut(),
193 shots,
194 );
195 (batch.detectors, batch.observables)
196 }
197
198 pub fn sample_write(
199 &mut self,
200 shots: u64,
201 filepath: &str,
202 format_name: &str,
203 ) -> Result<(), cxx::Exception> {
204 ffi::detector_sampler_sample_write(self.inner.pin_mut(), shots, filepath, format_name)
205 }
206
207 pub fn sample_write_separate_observables(
208 &mut self,
209 shots: u64,
210 dets_filepath: &str,
211 dets_format_name: &str,
212 obs_filepath: &str,
213 obs_format_name: &str,
214 ) -> Result<(), cxx::Exception> {
215 ffi::detector_sampler_sample_write_separate_observables(
216 self.inner.pin_mut(),
217 shots,
218 dets_filepath,
219 dets_format_name,
220 obs_filepath,
221 obs_format_name,
222 )
223 }
224
225 fn inner(&self) -> &ffi::DetectorSamplerHandle {
226 self.inner
227 .as_ref()
228 .expect("stim-cxx detector sampler construction returned null")
229 }
230}
231
232impl DemSampler {
233 #[must_use]
234 pub fn num_detectors(&self) -> u64 {
235 ffi::dem_sampler_num_detectors(self.inner())
236 }
237
238 #[must_use]
239 pub fn num_observables(&self) -> u64 {
240 ffi::dem_sampler_num_observables(self.inner())
241 }
242
243 #[must_use]
244 pub fn num_errors(&self) -> u64 {
245 ffi::dem_sampler_num_errors(self.inner())
246 }
247
248 #[must_use]
249 pub fn sample_bit_packed(&mut self, shots: u64) -> ffi::DemSampleBatch {
250 ffi::dem_sampler_sample_bit_packed(self.inner.pin_mut(), shots)
251 }
252
253 pub fn sample_bit_packed_replay(
254 &mut self,
255 recorded_errors: &[u8],
256 shots: u64,
257 ) -> ffi::DemSampleBatch {
258 ffi::dem_sampler_sample_bit_packed_replay(self.inner.pin_mut(), recorded_errors, shots)
259 }
260
261 pub fn sample_write(
262 &mut self,
263 shots: u64,
264 dets_filepath: &str,
265 dets_format_name: &str,
266 obs_filepath: &str,
267 obs_format_name: &str,
268 err_filepath: &str,
269 err_format_name: &str,
270 write_errors: bool,
271 ) -> Result<(), cxx::Exception> {
272 ffi::dem_sampler_sample_write(
273 self.inner.pin_mut(),
274 shots,
275 dets_filepath,
276 dets_format_name,
277 obs_filepath,
278 obs_format_name,
279 err_filepath,
280 err_format_name,
281 write_errors,
282 "",
283 "01",
284 false,
285 )
286 }
287
288 pub fn sample_write_replay(
289 &mut self,
290 shots: u64,
291 dets_filepath: &str,
292 dets_format_name: &str,
293 obs_filepath: &str,
294 obs_format_name: &str,
295 err_filepath: &str,
296 err_format_name: &str,
297 write_errors: bool,
298 replay_err_filepath: &str,
299 replay_err_format_name: &str,
300 ) -> Result<(), cxx::Exception> {
301 ffi::dem_sampler_sample_write(
302 self.inner.pin_mut(),
303 shots,
304 dets_filepath,
305 dets_format_name,
306 obs_filepath,
307 obs_format_name,
308 err_filepath,
309 err_format_name,
310 write_errors,
311 replay_err_filepath,
312 replay_err_format_name,
313 true,
314 )
315 }
316
317 fn inner(&self) -> &ffi::DemSamplerHandle {
318 self.inner
319 .as_ref()
320 .expect("stim-cxx DEM sampler construction returned null")
321 }
322}
323
324impl MeasurementsToDetectionEventsConverter {
325 fn inner(&self) -> &ffi::MeasurementsToDetectionEventsConverterHandle {
326 self.inner
327 .as_ref()
328 .expect("stim-cxx M2D converter construction returned null")
329 }
330
331 #[must_use]
332 pub fn num_measurements(&self) -> u64 {
333 ffi::m2d_converter_num_measurements(self.inner())
334 }
335
336 #[must_use]
337 pub fn num_detectors(&self) -> u64 {
338 ffi::m2d_converter_num_detectors(self.inner())
339 }
340
341 #[must_use]
342 pub fn num_observables(&self) -> u64 {
343 ffi::m2d_converter_num_observables(self.inner())
344 }
345
346 #[must_use]
347 pub fn num_sweep_bits(&self) -> u64 {
348 ffi::m2d_converter_num_sweep_bits(self.inner())
349 }
350
351 pub fn convert_measurements_bit_packed(
352 &mut self,
353 measurements: &[u8],
354 shots: u64,
355 append_observables: bool,
356 ) -> Vec<u8> {
357 ffi::m2d_converter_convert_measurements_bit_packed(
358 self.inner.pin_mut(),
359 measurements,
360 shots,
361 append_observables,
362 )
363 }
364
365 pub fn convert_measurements_and_sweep_bits_bit_packed(
366 &mut self,
367 measurements: &[u8],
368 sweep_bits: &[u8],
369 shots: u64,
370 append_observables: bool,
371 ) -> Vec<u8> {
372 ffi::m2d_converter_convert_measurements_and_sweep_bits_bit_packed(
373 self.inner.pin_mut(),
374 measurements,
375 sweep_bits,
376 shots,
377 append_observables,
378 )
379 }
380
381 pub fn convert_observables_with_sweep_bits_bit_packed(
382 &mut self,
383 measurements: &[u8],
384 sweep_bits: &[u8],
385 shots: u64,
386 ) -> Vec<u8> {
387 ffi::m2d_converter_convert_observables_with_sweep_bits_bit_packed(
388 self.inner.pin_mut(),
389 measurements,
390 sweep_bits,
391 shots,
392 )
393 }
394
395 pub fn convert_observables_bit_packed(&mut self, measurements: &[u8], shots: u64) -> Vec<u8> {
396 ffi::m2d_converter_convert_observables_bit_packed(self.inner.pin_mut(), measurements, shots)
397 }
398
399 pub fn convert_file(
400 &mut self,
401 measurements_filepath: &str,
402 measurements_format: &str,
403 sweep_bits_filepath: &str,
404 sweep_bits_format: &str,
405 detection_events_filepath: &str,
406 detection_events_format: &str,
407 append_observables: bool,
408 obs_out_filepath: &str,
409 obs_out_format: &str,
410 ) -> Result<(), cxx::Exception> {
411 ffi::m2d_converter_convert_file(
412 self.inner.pin_mut(),
413 measurements_filepath,
414 measurements_format,
415 sweep_bits_filepath,
416 sweep_bits_format,
417 detection_events_filepath,
418 detection_events_format,
419 append_observables,
420 obs_out_filepath,
421 obs_out_format,
422 )
423 }
424}
425
426impl GateData {
427 #[must_use]
428 pub fn name(&self) -> String {
429 self.inner().name()
430 }
431
432 #[must_use]
433 pub fn aliases(&self) -> Vec<String> {
434 self.inner().aliases()
435 }
436
437 #[must_use]
438 pub fn num_parens_arguments_range(&self) -> Vec<u8> {
439 self.inner().num_parens_arguments_range()
440 }
441
442 #[must_use]
443 pub fn is_noisy_gate(&self) -> bool {
444 self.inner().is_noisy_gate()
445 }
446
447 #[must_use]
448 pub fn is_reset(&self) -> bool {
449 self.inner().is_reset()
450 }
451
452 #[must_use]
453 pub fn is_single_qubit_gate(&self) -> bool {
454 self.inner().is_single_qubit_gate()
455 }
456
457 #[must_use]
458 pub fn is_symmetric_gate(&self) -> bool {
459 self.inner().is_symmetric_gate()
460 }
461
462 #[must_use]
463 pub fn is_two_qubit_gate(&self) -> bool {
464 self.inner().is_two_qubit_gate()
465 }
466
467 #[must_use]
468 pub fn is_unitary(&self) -> bool {
469 self.inner().is_unitary()
470 }
471
472 #[must_use]
473 pub fn produces_measurements(&self) -> bool {
474 self.inner().produces_measurements()
475 }
476
477 #[must_use]
478 pub fn takes_measurement_record_targets(&self) -> bool {
479 self.inner().takes_measurement_record_targets()
480 }
481
482 #[must_use]
483 pub fn takes_pauli_targets(&self) -> bool {
484 self.inner().takes_pauli_targets()
485 }
486
487 pub fn flows(&self) -> Vec<String> {
488 self.inner().flows()
489 }
490
491 #[must_use]
492 pub fn tableau(&self) -> Option<Tableau> {
493 let inner = self.inner().tableau();
494 if inner.is_null() {
495 None
496 } else {
497 Some(Tableau { inner })
498 }
499 }
500
501 #[must_use]
502 pub fn clone_handle(&self) -> Self {
503 Self {
504 inner: self.inner().clone_handle(),
505 }
506 }
507
508 #[must_use]
509 pub fn inverse(&self) -> Option<Self> {
510 let inner = self.inner().inverse();
511 if inner.is_null() {
512 None
513 } else {
514 Some(Self { inner })
515 }
516 }
517
518 #[must_use]
519 pub fn generalized_inverse(&self) -> Self {
520 Self {
521 inner: self.inner().generalized_inverse(),
522 }
523 }
524
525 #[must_use]
526 pub fn hadamard_conjugated(&self, unsigned_only: bool) -> Option<Self> {
527 let inner = self.inner().hadamard_conjugated(unsigned_only);
528 if inner.is_null() {
529 None
530 } else {
531 Some(Self { inner })
532 }
533 }
534
535 fn inner(&self) -> &ffi::GateDataHandle {
536 self.inner
537 .as_ref()
538 .expect("stim-cxx gate data construction returned null")
539 }
540}
541
542pub fn gate_data(name: &str) -> Result<GateData, cxx::Exception> {
543 ffi::gate_data_by_name(name).map(|inner| GateData { inner })
544}
545
546impl Circuit {
547 #[must_use]
548 pub fn new() -> Self {
549 Self {
550 inner: ffi::new_circuit(),
551 }
552 }
553
554 pub fn from_stim_program_text(text: &str) -> Result<Self, cxx::Exception> {
555 ffi::circuit_from_stim_program_text(text).map(|inner| Self { inner })
556 }
557
558 pub fn generated(
559 code_task: &str,
560 distance: usize,
561 rounds: usize,
562 after_clifford_depolarization: f64,
563 before_round_data_depolarization: f64,
564 before_measure_flip_probability: f64,
565 after_reset_flip_probability: f64,
566 ) -> Result<Self, cxx::Exception> {
567 ffi::circuit_generated(
568 code_task,
569 distance,
570 rounds,
571 after_clifford_depolarization,
572 before_round_data_depolarization,
573 before_measure_flip_probability,
574 after_reset_flip_probability,
575 )
576 .map(|inner| Self { inner })
577 }
578
579 pub fn has_flow(&self, flow: &str, unsigned: bool) -> Result<bool, cxx::Exception> {
580 ffi::circuit_has_flow_text(self.inner(), flow, unsigned)
581 }
582
583 pub fn has_all_flows(
584 &self,
585 flows: Vec<String>,
586 unsigned: bool,
587 ) -> Result<bool, cxx::Exception> {
588 ffi::circuit_has_all_flows_text(self.inner(), flows, unsigned)
589 }
590
591 pub fn flow_generators(&self) -> Vec<String> {
592 ffi::circuit_flow_generators_texts(self.inner())
593 }
594
595 pub fn solve_flow_measurements(
596 &self,
597 flows: Vec<String>,
598 ) -> Result<Vec<String>, cxx::Exception> {
599 ffi::circuit_solve_flow_measurements_text(self.inner(), flows)
600 }
601
602 pub fn time_reversed_for_flows(
603 &self,
604 flows: Vec<String>,
605 dont_turn_measurements_into_resets: bool,
606 ) -> Result<(String, Vec<String>), cxx::Exception> {
607 let mut out_flow_texts = Vec::new();
608 let circuit_text = ffi::circuit_time_reversed_for_flows_text(
609 &mut out_flow_texts,
610 self.inner(),
611 flows,
612 dont_turn_measurements_into_resets,
613 )?;
614 Ok((circuit_text, out_flow_texts))
615 }
616
617 pub fn detector_error_model(
618 &self,
619 decompose_errors: bool,
620 flatten_loops: bool,
621 allow_gauge_detectors: bool,
622 approximate_disjoint_errors: f64,
623 ignore_decomposition_failures: bool,
624 block_decomposition_from_introducing_remnant_edges: bool,
625 ) -> Result<DetectorErrorModel, cxx::Exception> {
626 ffi::circuit_detector_error_model(
627 self.inner(),
628 decompose_errors,
629 flatten_loops,
630 allow_gauge_detectors,
631 approximate_disjoint_errors,
632 ignore_decomposition_failures,
633 block_decomposition_from_introducing_remnant_edges,
634 )
635 .map(|inner| DetectorErrorModel { inner })
636 }
637
638 #[must_use]
639 pub fn missing_detectors(&self, unknown_input: bool) -> Self {
640 Self {
641 inner: ffi::circuit_missing_detectors(self.inner(), unknown_input),
642 }
643 }
644
645 pub fn to_tableau(
646 &self,
647 ignore_noise: bool,
648 ignore_measurement: bool,
649 ignore_reset: bool,
650 ) -> Result<Tableau, cxx::Exception> {
651 ffi::circuit_to_tableau(self.inner(), ignore_noise, ignore_measurement, ignore_reset)
652 .map(|inner| Tableau { inner })
653 }
654
655 #[must_use]
656 pub fn add(&self, other: &Self) -> Self {
657 Self {
658 inner: ffi::circuit_add(self.inner(), other.inner()),
659 }
660 }
661
662 pub fn add_assign(&mut self, other: &Self) {
663 ffi::circuit_add_assign(self.inner.pin_mut(), other.inner());
664 }
665
666 #[must_use]
667 pub fn repeat(&self, repetitions: u64) -> Self {
668 Self {
669 inner: ffi::circuit_mul(self.inner(), repetitions),
670 }
671 }
672
673 pub fn repeat_assign(&mut self, repetitions: u64) {
674 ffi::circuit_mul_assign(self.inner.pin_mut(), repetitions);
675 }
676
677 #[must_use]
678 pub fn to_stim_program_text(&self) -> String {
679 ffi::circuit_to_stim_program_text(self.inner())
680 }
681
682 #[must_use]
683 pub fn num_qubits(&self) -> usize {
684 ffi::circuit_num_qubits(self.inner())
685 }
686
687 #[must_use]
688 pub fn len(&self) -> usize {
689 ffi::circuit_len(self.inner())
690 }
691
692 #[must_use]
693 pub fn top_level_item(&self, index: usize) -> ffi::CircuitTopLevelItemData {
694 ffi::circuit_get_top_level_item(self.inner(), index)
695 }
696
697 #[must_use]
698 pub fn top_level_repeat_block_body(&self, index: usize) -> Self {
699 Self {
700 inner: ffi::circuit_get_top_level_repeat_block_body(self.inner(), index),
701 }
702 }
703
704 #[must_use]
705 pub fn get_slice(&self, start: i64, step: i64, slice_length: i64) -> Self {
706 Self {
707 inner: ffi::circuit_get_slice(self.inner(), start, step, slice_length),
708 }
709 }
710
711 pub fn remove_top_level(&mut self, index: usize) {
712 ffi::circuit_remove_top_level(self.inner.pin_mut(), index);
713 }
714
715 #[must_use]
716 pub fn is_empty(&self) -> bool {
717 self.len() == 0
718 }
719
720 #[must_use]
721 pub fn num_measurements(&self) -> u64 {
722 ffi::circuit_num_measurements(self.inner())
723 }
724
725 #[must_use]
726 pub fn count_determined_measurements(&self, unknown_input: bool) -> u64 {
727 ffi::circuit_count_determined_measurements(self.inner(), unknown_input)
728 }
729
730 #[must_use]
731 pub fn num_detectors(&self) -> u64 {
732 ffi::circuit_num_detectors(self.inner())
733 }
734
735 #[must_use]
736 pub fn num_observables(&self) -> u64 {
737 ffi::circuit_num_observables(self.inner())
738 }
739
740 #[must_use]
741 pub fn num_ticks(&self) -> u64 {
742 ffi::circuit_num_ticks(self.inner())
743 }
744
745 #[must_use]
746 pub fn num_sweep_bits(&self) -> usize {
747 ffi::circuit_num_sweep_bits(self.inner())
748 }
749
750 pub fn clear(&mut self) {
751 ffi::circuit_clear(self.inner.pin_mut());
752 }
753
754 pub fn append_from_stim_program_text(&mut self, text: &str) -> Result<(), cxx::Exception> {
755 ffi::circuit_append_from_stim_program_text(self.inner.pin_mut(), text)
756 }
757
758 pub fn append(
759 &mut self,
760 gate_name: &str,
761 targets: &[u32],
762 args: &[f64],
763 ) -> Result<(), cxx::Exception> {
764 self.append_with_tag(gate_name, targets, args, "")
765 }
766
767 pub fn append_with_tag(
768 &mut self,
769 gate_name: &str,
770 targets: &[u32],
771 args: &[f64],
772 tag: &str,
773 ) -> Result<(), cxx::Exception> {
774 ffi::circuit_append_gate(self.inner.pin_mut(), gate_name, targets, args, tag)
775 }
776
777 pub fn append_repeat_block(
778 &mut self,
779 repeat_count: u64,
780 body: &Self,
781 tag: &str,
782 ) -> Result<(), cxx::Exception> {
783 ffi::circuit_append_repeat_block(self.inner.pin_mut(), repeat_count, body.inner(), tag)
784 }
785
786 pub fn insert_with_tag(
787 &mut self,
788 index: usize,
789 gate_name: &str,
790 targets: &[u32],
791 args: &[f64],
792 tag: &str,
793 ) -> Result<(), cxx::Exception> {
794 ffi::circuit_insert_gate(self.inner.pin_mut(), index, gate_name, targets, args, tag)
795 }
796
797 pub fn insert_repeat_block(
798 &mut self,
799 index: usize,
800 repeat_count: u64,
801 body: &Self,
802 tag: &str,
803 ) -> Result<(), cxx::Exception> {
804 ffi::circuit_insert_repeat_block(
805 self.inner.pin_mut(),
806 index,
807 repeat_count,
808 body.inner(),
809 tag,
810 )
811 }
812
813 pub fn insert_circuit(&mut self, index: usize, circuit: &Self) {
814 ffi::circuit_insert_circuit(self.inner.pin_mut(), index, circuit.inner());
815 }
816
817 #[must_use]
818 pub fn approx_equals(&self, other: &Self, atol: f64) -> bool {
819 ffi::circuit_approx_equals(self.inner(), other.inner(), atol)
820 }
821
822 #[must_use]
823 pub fn equals(&self, other: &Self) -> bool {
824 ffi::circuit_equals(self.inner(), other.inner())
825 }
826
827 #[must_use]
828 pub fn without_noise(&self) -> Self {
829 Self {
830 inner: ffi::circuit_without_noise(self.inner()),
831 }
832 }
833
834 #[must_use]
835 pub fn with_inlined_feedback(&self) -> Self {
836 Self {
837 inner: ffi::circuit_with_inlined_feedback(self.inner()),
838 }
839 }
840
841 #[must_use]
842 pub fn without_tags(&self) -> Self {
843 Self {
844 inner: ffi::circuit_without_tags(self.inner()),
845 }
846 }
847
848 #[must_use]
849 pub fn flattened(&self) -> Self {
850 Self {
851 inner: ffi::circuit_flattened(self.inner()),
852 }
853 }
854
855 #[must_use]
856 pub fn decomposed(&self) -> Self {
857 Self {
858 inner: ffi::circuit_decomposed(self.inner()),
859 }
860 }
861
862 pub fn inverse(&self) -> Result<Self, cxx::Exception> {
863 ffi::circuit_inverse(self.inner()).map(|inner| Self { inner })
864 }
865
866 pub fn to_qasm(
867 &self,
868 open_qasm_version: i32,
869 skip_dets_and_obs: bool,
870 ) -> Result<String, cxx::Exception> {
871 ffi::circuit_to_qasm(self.inner(), open_qasm_version, skip_dets_and_obs)
872 }
873
874 pub fn to_quirk_url(&self) -> Result<String, cxx::Exception> {
875 ffi::circuit_to_quirk_url(self.inner())
876 }
877
878 pub fn to_crumble_url(&self, skip_detectors: bool) -> Result<String, cxx::Exception> {
879 ffi::circuit_to_crumble_url(self.inner(), skip_detectors)
880 }
881
882 pub fn shortest_error_sat_problem(&self, format_name: &str) -> Result<String, cxx::Exception> {
883 ffi::circuit_shortest_error_sat_problem(self.inner(), format_name)
884 }
885
886 pub fn likeliest_error_sat_problem(
887 &self,
888 quantization: i32,
889 format_name: &str,
890 ) -> Result<String, cxx::Exception> {
891 ffi::circuit_likeliest_error_sat_problem(self.inner(), quantization, format_name)
892 }
893
894 pub fn detecting_regions(&self) -> Result<Vec<ffi::DetectingRegionEntryData>, cxx::Exception> {
895 ffi::circuit_detecting_regions(self.inner())
896 }
897
898 pub fn detecting_regions_with_options(
899 &self,
900 target_texts: Vec<String>,
901 ticks: Vec<u64>,
902 ignore_anticommutation_errors: bool,
903 ) -> Result<Vec<ffi::DetectingRegionEntryData>, cxx::Exception> {
904 ffi::circuit_detecting_regions_with_options(
905 self.inner(),
906 target_texts,
907 ticks,
908 ignore_anticommutation_errors,
909 )
910 }
911
912 pub fn explain_detector_error_model_errors(
913 &self,
914 dem_filter_text: &str,
915 has_dem_filter: bool,
916 reduce_to_one_representative_error: bool,
917 ) -> Result<Vec<ffi::ExplainedErrorData>, cxx::Exception> {
918 ffi::circuit_explain_detector_error_model_errors(
919 self.inner(),
920 dem_filter_text,
921 has_dem_filter,
922 reduce_to_one_representative_error,
923 )
924 }
925
926 pub fn flattened_operation_texts(&self) -> Vec<String> {
927 ffi::circuit_flattened_operation_texts(self.inner())
928 }
929
930 pub fn shortest_graphlike_error(
931 &self,
932 ignore_ungraphlike_errors: bool,
933 canonicalize_circuit_errors: bool,
934 ) -> Result<Vec<ffi::ExplainedErrorData>, cxx::Exception> {
935 ffi::circuit_shortest_graphlike_error(
936 self.inner(),
937 ignore_ungraphlike_errors,
938 canonicalize_circuit_errors,
939 )
940 }
941
942 pub fn search_for_undetectable_logical_errors(
943 &self,
944 dont_explore_detection_event_sets_with_size_above: u64,
945 dont_explore_edges_with_degree_above: u64,
946 dont_explore_edges_increasing_symptom_degree: bool,
947 canonicalize_circuit_errors: bool,
948 ) -> Result<Vec<ffi::ExplainedErrorData>, cxx::Exception> {
949 ffi::circuit_search_for_undetectable_logical_errors(
950 self.inner(),
951 dont_explore_detection_event_sets_with_size_above,
952 dont_explore_edges_with_degree_above,
953 dont_explore_edges_increasing_symptom_degree,
954 canonicalize_circuit_errors,
955 )
956 }
957
958 pub fn get_detector_coordinates(
959 &self,
960 included_detector_indices: &[u64],
961 ) -> Result<Vec<ffi::CoordinateEntryData>, cxx::Exception> {
962 ffi::circuit_get_detector_coordinates(self.inner(), included_detector_indices)
963 }
964
965 pub fn get_final_qubit_coordinates(
966 &self,
967 ) -> Result<Vec<ffi::CoordinateEntryData>, cxx::Exception> {
968 ffi::circuit_get_final_qubit_coordinates(self.inner())
969 }
970
971 pub fn diagram(&self, type_name: &str) -> Result<String, cxx::Exception> {
972 ffi::circuit_diagram(self.inner(), type_name)
973 }
974
975 pub fn diagram_with_options(
976 &self,
977 type_name: &str,
978 tick_range: Option<(u64, u64)>,
979 rows: Option<usize>,
980 ) -> Result<String, cxx::Exception> {
981 ffi::circuit_diagram_with_options(
982 self.inner(),
983 type_name,
984 tick_range.is_some(),
985 tick_range.map(|(start, _)| start).unwrap_or(0),
986 tick_range.map(|(_, count)| count).unwrap_or(0),
987 rows.is_some(),
988 rows.unwrap_or(0),
989 )
990 }
991
992 pub fn diagram_with_options_and_filters(
993 &self,
994 type_name: &str,
995 tick_range: Option<(u64, u64)>,
996 rows: Option<usize>,
997 filter_coords: Vec<String>,
998 ) -> Result<String, cxx::Exception> {
999 ffi::circuit_diagram_with_options_and_filters(
1000 self.inner(),
1001 type_name,
1002 tick_range.is_some(),
1003 tick_range.map(|(start, _)| start).unwrap_or(0),
1004 tick_range.map(|(_, count)| count).unwrap_or(0),
1005 rows.is_some(),
1006 rows.unwrap_or(0),
1007 filter_coords,
1008 )
1009 }
1010
1011 #[must_use]
1012 pub fn reference_sample_bit_packed(&self) -> Vec<u8> {
1013 ffi::circuit_reference_sample_bit_packed(self.inner())
1014 }
1015
1016 #[must_use]
1017 pub fn reference_detector_signs_bit_packed(&self) -> Vec<u8> {
1018 ffi::circuit_reference_detector_signs_bit_packed(self.inner())
1019 }
1020
1021 #[must_use]
1022 pub fn reference_observable_signs_bit_packed(&self) -> Vec<u8> {
1023 ffi::circuit_reference_observable_signs_bit_packed(self.inner())
1024 }
1025
1026 #[must_use]
1027 pub fn compile_sampler(&self, skip_reference_sample: bool) -> MeasurementSampler {
1028 self.compile_sampler_with_seed(skip_reference_sample, 0)
1029 }
1030
1031 #[must_use]
1032 pub fn compile_sampler_with_seed(
1033 &self,
1034 skip_reference_sample: bool,
1035 seed: u64,
1036 ) -> MeasurementSampler {
1037 MeasurementSampler {
1038 inner: ffi::circuit_compile_sampler(self.inner(), skip_reference_sample, seed),
1039 }
1040 }
1041
1042 #[must_use]
1043 pub fn compile_detector_sampler_with_seed(&self, seed: u64) -> DetectorSampler {
1044 DetectorSampler {
1045 inner: ffi::circuit_compile_detector_sampler(self.inner(), seed),
1046 }
1047 }
1048
1049 pub fn compile_m2d_converter(
1050 &self,
1051 skip_reference_sample: bool,
1052 ) -> MeasurementsToDetectionEventsConverter {
1053 MeasurementsToDetectionEventsConverter {
1054 inner: ffi::circuit_compile_m2d_converter(self.inner(), skip_reference_sample),
1055 }
1056 }
1057
1058 fn inner(&self) -> &ffi::CircuitHandle {
1059 self.inner
1060 .as_ref()
1061 .expect("stim-cxx circuit construction returned null")
1062 }
1063}
1064
1065impl DetectorErrorModel {
1066 #[must_use]
1067 pub fn new() -> Self {
1068 Self {
1069 inner: ffi::new_detector_error_model(),
1070 }
1071 }
1072
1073 pub fn from_dem_text(text: &str) -> Result<Self, cxx::Exception> {
1074 ffi::detector_error_model_from_dem_text(text).map(|inner| Self { inner })
1075 }
1076
1077 pub fn diagram(&self, type_name: &str) -> Result<String, cxx::Exception> {
1078 ffi::detector_error_model_diagram(self.inner(), type_name)
1079 }
1080
1081 #[must_use]
1082 pub fn add(&self, other: &Self) -> Self {
1083 Self {
1084 inner: ffi::detector_error_model_add(self.inner(), other.inner()),
1085 }
1086 }
1087
1088 pub fn add_assign(&mut self, other: &Self) {
1089 ffi::detector_error_model_add_assign(self.inner.pin_mut(), other.inner());
1090 }
1091
1092 #[must_use]
1093 pub fn repeat(&self, repetitions: u64) -> Self {
1094 Self {
1095 inner: ffi::detector_error_model_mul(self.inner(), repetitions),
1096 }
1097 }
1098
1099 pub fn repeat_assign(&mut self, repetitions: u64) {
1100 ffi::detector_error_model_mul_assign(self.inner.pin_mut(), repetitions);
1101 }
1102
1103 #[must_use]
1104 pub fn to_dem_text(&self) -> String {
1105 ffi::detector_error_model_to_dem_text(self.inner())
1106 }
1107
1108 #[must_use]
1109 pub fn len(&self) -> usize {
1110 ffi::detector_error_model_len(self.inner())
1111 }
1112
1113 #[must_use]
1114 pub fn top_level_item(&self, index: usize) -> ffi::DemTopLevelItemData {
1115 ffi::detector_error_model_get_top_level_item(self.inner(), index)
1116 }
1117
1118 #[must_use]
1119 pub fn top_level_repeat_block_body(&self, index: usize) -> Self {
1120 Self {
1121 inner: ffi::detector_error_model_get_top_level_repeat_block_body(self.inner(), index),
1122 }
1123 }
1124
1125 #[must_use]
1126 pub fn get_slice(&self, start: i64, step: i64, slice_length: i64) -> Self {
1127 Self {
1128 inner: ffi::detector_error_model_get_slice(self.inner(), start, step, slice_length),
1129 }
1130 }
1131
1132 #[must_use]
1133 pub fn is_empty(&self) -> bool {
1134 self.len() == 0
1135 }
1136
1137 #[must_use]
1138 pub fn num_detectors(&self) -> u64 {
1139 ffi::detector_error_model_num_detectors(self.inner())
1140 }
1141
1142 #[must_use]
1143 pub fn num_errors(&self) -> u64 {
1144 ffi::detector_error_model_num_errors(self.inner())
1145 }
1146
1147 #[must_use]
1148 pub fn num_observables(&self) -> u64 {
1149 ffi::detector_error_model_num_observables(self.inner())
1150 }
1151
1152 pub fn get_detector_coordinates(
1153 &self,
1154 included_detector_indices: &[u64],
1155 ) -> Result<Vec<ffi::CoordinateEntryData>, cxx::Exception> {
1156 ffi::detector_error_model_get_detector_coordinates(self.inner(), included_detector_indices)
1157 }
1158
1159 pub fn clear(&mut self) {
1160 ffi::detector_error_model_clear(self.inner.pin_mut());
1161 }
1162
1163 #[must_use]
1164 pub fn approx_equals(&self, other: &Self, atol: f64) -> bool {
1165 ffi::detector_error_model_approx_equals(self.inner(), other.inner(), atol)
1166 }
1167
1168 #[must_use]
1169 pub fn equals(&self, other: &Self) -> bool {
1170 ffi::detector_error_model_equals(self.inner(), other.inner())
1171 }
1172
1173 #[must_use]
1174 pub fn without_tags(&self) -> Self {
1175 Self {
1176 inner: ffi::detector_error_model_without_tags(self.inner()),
1177 }
1178 }
1179
1180 #[must_use]
1181 pub fn flattened(&self) -> Self {
1182 Self {
1183 inner: ffi::detector_error_model_flattened(self.inner()),
1184 }
1185 }
1186
1187 #[must_use]
1188 pub fn rounded(&self, digits: u8) -> Self {
1189 Self {
1190 inner: ffi::detector_error_model_rounded(self.inner(), digits),
1191 }
1192 }
1193
1194 pub fn append_instruction(
1195 &mut self,
1196 instruction_type: &str,
1197 args: &[f64],
1198 targets: &[u64],
1199 tag: &str,
1200 ) -> Result<(), cxx::Exception> {
1201 ffi::detector_error_model_append_instruction(
1202 self.inner.pin_mut(),
1203 instruction_type,
1204 args,
1205 targets,
1206 tag,
1207 )
1208 }
1209
1210 pub fn append_repeat_block(
1211 &mut self,
1212 repeat_count: u64,
1213 body: &Self,
1214 ) -> Result<(), cxx::Exception> {
1215 ffi::detector_error_model_append_repeat_block(
1216 self.inner.pin_mut(),
1217 repeat_count,
1218 body.inner(),
1219 )
1220 }
1221
1222 #[must_use]
1223 pub fn compile_sampler(&self) -> DemSampler {
1224 self.compile_sampler_with_seed(0)
1225 }
1226
1227 #[must_use]
1228 pub fn compile_sampler_with_seed(&self, seed: u64) -> DemSampler {
1229 DemSampler {
1230 inner: ffi::detector_error_model_compile_sampler(self.inner(), seed),
1231 }
1232 }
1233
1234 pub fn shortest_graphlike_error(
1235 &self,
1236 ignore_ungraphlike_errors: bool,
1237 ) -> Result<Self, cxx::Exception> {
1238 ffi::detector_error_model_shortest_graphlike_error(self.inner(), ignore_ungraphlike_errors)
1239 .map(|inner| Self { inner })
1240 }
1241
1242 pub fn shortest_error_sat_problem(&self, format_name: &str) -> Result<String, cxx::Exception> {
1243 ffi::detector_error_model_shortest_error_sat_problem(self.inner(), format_name)
1244 }
1245
1246 pub fn likeliest_error_sat_problem(
1247 &self,
1248 quantization: i32,
1249 format_name: &str,
1250 ) -> Result<String, cxx::Exception> {
1251 ffi::detector_error_model_likeliest_error_sat_problem(
1252 self.inner(),
1253 quantization,
1254 format_name,
1255 )
1256 }
1257
1258 fn inner(&self) -> &ffi::DetectorErrorModelHandle {
1259 self.inner
1260 .as_ref()
1261 .expect("stim-cxx detector error model construction returned null")
1262 }
1263}
1264
1265impl Tableau {
1266 #[must_use]
1267 pub fn new(num_qubits: usize) -> Self {
1268 Self {
1269 inner: ffi::new_tableau(num_qubits),
1270 }
1271 }
1272
1273 #[must_use]
1274 pub fn random(num_qubits: usize) -> Self {
1275 Self {
1276 inner: ffi::tableau_random(num_qubits),
1277 }
1278 }
1279
1280 #[must_use]
1281 pub fn iter_all(num_qubits: usize, unsigned: bool) -> TableauIterator {
1282 TableauIterator {
1283 inner: ffi::tableau_iter_all(num_qubits, unsigned),
1284 }
1285 }
1286
1287 pub fn from_named_gate(name: &str) -> Result<Self, cxx::Exception> {
1288 ffi::tableau_from_named_gate(name).map(|inner| Self { inner })
1289 }
1290
1291 pub fn from_state_vector_data(
1292 state_vector: Vec<f32>,
1293 endian: &str,
1294 ) -> Result<Self, cxx::Exception> {
1295 ffi::tableau_from_state_vector_data(state_vector, endian).map(|inner| Self { inner })
1296 }
1297
1298 pub fn from_unitary_matrix_data(
1299 matrix: Vec<f32>,
1300 endian: &str,
1301 ) -> Result<Self, cxx::Exception> {
1302 ffi::tableau_from_unitary_matrix_data(matrix, endian).map(|inner| Self { inner })
1303 }
1304
1305 pub fn from_conjugated_generator_texts(
1306 xs: Vec<String>,
1307 zs: Vec<String>,
1308 ) -> Result<Self, cxx::Exception> {
1309 ffi::tableau_from_conjugated_generator_texts(xs, zs).map(|inner| Self { inner })
1310 }
1311
1312 pub fn from_stabilizer_texts(
1313 stabilizers: Vec<String>,
1314 allow_redundant: bool,
1315 allow_underconstrained: bool,
1316 ) -> Result<Self, cxx::Exception> {
1317 ffi::tableau_from_stabilizer_texts(stabilizers, allow_redundant, allow_underconstrained)
1318 .map(|inner| Self { inner })
1319 }
1320
1321 pub fn then(&self, second: &Self) -> Result<Self, cxx::Exception> {
1322 ffi::tableau_then(self.inner(), second.inner()).map(|inner| Self { inner })
1323 }
1324
1325 fn inner(&self) -> &ffi::TableauHandle {
1326 self.inner
1327 .as_ref()
1328 .expect("stim-cxx tableau construction returned null")
1329 }
1330
1331 fn inner_mut(self: Pin<&mut Self>) -> Pin<&mut ffi::TableauHandle> {
1332 self.get_mut().inner.pin_mut()
1333 }
1334
1335 #[must_use]
1336 pub fn num_qubits(&self) -> usize {
1337 ffi::tableau_num_qubits(self.inner())
1338 }
1339
1340 #[must_use]
1341 pub fn add(&self, other: &Self) -> Self {
1342 Self {
1343 inner: ffi::tableau_add(self.inner(), other.inner()),
1344 }
1345 }
1346
1347 pub fn add_assign(&mut self, other: &Self) {
1348 ffi::tableau_add_assign(self.inner.pin_mut(), other.inner());
1349 }
1350
1351 pub fn append(
1352 self: Pin<&mut Self>,
1353 gate: &Self,
1354 targets: &[usize],
1355 ) -> Result<(), cxx::Exception> {
1356 ffi::tableau_append(self.inner_mut(), gate.inner(), targets)
1357 }
1358
1359 pub fn prepend(
1360 self: Pin<&mut Self>,
1361 gate: &Self,
1362 targets: &[usize],
1363 ) -> Result<(), cxx::Exception> {
1364 ffi::tableau_prepend(self.inner_mut(), gate.inner(), targets)
1365 }
1366
1367 #[must_use]
1368 pub fn inverse(&self, unsigned_only: bool) -> Self {
1369 Self {
1370 inner: ffi::tableau_inverse(self.inner(), unsigned_only),
1371 }
1372 }
1373
1374 #[must_use]
1375 pub fn raised_to(&self, exponent: i64) -> Self {
1376 Self {
1377 inner: ffi::tableau_raised_to(self.inner(), exponent),
1378 }
1379 }
1380
1381 pub fn x_sign(&self, target: usize) -> Result<i32, cxx::Exception> {
1382 ffi::tableau_x_sign(self.inner(), target)
1383 }
1384
1385 pub fn y_sign(&self, target: usize) -> Result<i32, cxx::Exception> {
1386 ffi::tableau_y_sign(self.inner(), target)
1387 }
1388
1389 pub fn z_sign(&self, target: usize) -> Result<i32, cxx::Exception> {
1390 ffi::tableau_z_sign(self.inner(), target)
1391 }
1392
1393 pub fn x_output_pauli(
1394 &self,
1395 input_index: usize,
1396 output_index: usize,
1397 ) -> Result<u8, cxx::Exception> {
1398 ffi::tableau_x_output_pauli(self.inner(), input_index, output_index)
1399 }
1400
1401 pub fn y_output_pauli(
1402 &self,
1403 input_index: usize,
1404 output_index: usize,
1405 ) -> Result<u8, cxx::Exception> {
1406 ffi::tableau_y_output_pauli(self.inner(), input_index, output_index)
1407 }
1408
1409 pub fn z_output_pauli(
1410 &self,
1411 input_index: usize,
1412 output_index: usize,
1413 ) -> Result<u8, cxx::Exception> {
1414 ffi::tableau_z_output_pauli(self.inner(), input_index, output_index)
1415 }
1416
1417 pub fn x_output(&self, target: usize) -> PauliString {
1418 PauliString {
1419 inner: ffi::tableau_x_output(self.inner(), target),
1420 }
1421 }
1422
1423 pub fn y_output(&self, target: usize) -> PauliString {
1424 PauliString {
1425 inner: ffi::tableau_y_output(self.inner(), target),
1426 }
1427 }
1428
1429 pub fn z_output(&self, target: usize) -> PauliString {
1430 PauliString {
1431 inner: ffi::tableau_z_output(self.inner(), target),
1432 }
1433 }
1434
1435 pub fn inverse_x_output(&self, target: usize, unsigned_only: bool) -> PauliString {
1436 PauliString {
1437 inner: ffi::tableau_inverse_x_output(self.inner(), target, unsigned_only),
1438 }
1439 }
1440
1441 pub fn inverse_y_output(&self, target: usize, unsigned_only: bool) -> PauliString {
1442 PauliString {
1443 inner: ffi::tableau_inverse_y_output(self.inner(), target, unsigned_only),
1444 }
1445 }
1446
1447 pub fn inverse_z_output(&self, target: usize, unsigned_only: bool) -> PauliString {
1448 PauliString {
1449 inner: ffi::tableau_inverse_z_output(self.inner(), target, unsigned_only),
1450 }
1451 }
1452
1453 pub fn conjugate_pauli_string(&self, pauli_string: &PauliString) -> PauliString {
1454 PauliString {
1455 inner: ffi::tableau_conjugate_pauli_string(self.inner(), pauli_string.inner()),
1456 }
1457 }
1458
1459 pub fn conjugate_pauli_string_within(
1460 &self,
1461 pauli_string: &PauliString,
1462 targets: &[usize],
1463 inverse: bool,
1464 ) -> Result<PauliString, cxx::Exception> {
1465 ffi::tableau_conjugate_pauli_string_within(
1466 self.inner(),
1467 pauli_string.inner(),
1468 targets,
1469 inverse,
1470 )
1471 .map(|inner| PauliString { inner })
1472 }
1473
1474 pub fn to_stabilizer_texts(&self, canonicalize: bool) -> Vec<String> {
1475 ffi::tableau_to_stabilizer_texts(self.inner(), canonicalize)
1476 }
1477
1478 pub fn to_circuit(&self, method: &str) -> Result<Circuit, cxx::Exception> {
1479 ffi::tableau_to_circuit(self.inner(), method).map(|inner| Circuit { inner })
1480 }
1481
1482 pub fn to_pauli_string(&self) -> Result<PauliString, cxx::Exception> {
1483 ffi::tableau_to_pauli_string(self.inner()).map(|inner| PauliString { inner })
1484 }
1485
1486 pub fn inverse_x_output_pauli(
1487 &self,
1488 input_index: usize,
1489 output_index: usize,
1490 ) -> Result<u8, cxx::Exception> {
1491 ffi::tableau_inverse_x_output_pauli(self.inner(), input_index, output_index)
1492 }
1493
1494 pub fn inverse_y_output_pauli(
1495 &self,
1496 input_index: usize,
1497 output_index: usize,
1498 ) -> Result<u8, cxx::Exception> {
1499 ffi::tableau_inverse_y_output_pauli(self.inner(), input_index, output_index)
1500 }
1501
1502 pub fn inverse_z_output_pauli(
1503 &self,
1504 input_index: usize,
1505 output_index: usize,
1506 ) -> Result<u8, cxx::Exception> {
1507 ffi::tableau_inverse_z_output_pauli(self.inner(), input_index, output_index)
1508 }
1509
1510 #[must_use]
1511 pub fn to_text(&self) -> String {
1512 ffi::tableau_to_string(self.inner())
1513 }
1514
1515 #[must_use]
1516 pub fn to_repr_text(&self) -> String {
1517 ffi::tableau_to_repr(self.inner())
1518 }
1519
1520 pub fn to_unitary_matrix_data(&self, endian: &str) -> Result<Vec<f32>, cxx::Exception> {
1521 ffi::tableau_to_unitary_matrix_data(self.inner(), endian)
1522 }
1523
1524 pub fn to_state_vector_data(&self, endian: &str) -> Result<Vec<f32>, cxx::Exception> {
1525 ffi::tableau_to_state_vector_data(self.inner(), endian)
1526 }
1527}
1528
1529impl TableauSimulator {
1530 #[must_use]
1531 pub fn new(num_qubits: usize, seed: u64) -> Self {
1532 Self {
1533 inner: ffi::new_tableau_simulator(seed, num_qubits),
1534 }
1535 }
1536
1537 fn inner(&self) -> &ffi::TableauSimulatorHandle {
1538 self.inner
1539 .as_ref()
1540 .expect("stim-cxx tableau simulator construction returned null")
1541 }
1542
1543 fn inner_mut(&mut self) -> Pin<&mut ffi::TableauSimulatorHandle> {
1544 self.inner.pin_mut()
1545 }
1546
1547 #[must_use]
1548 pub fn num_qubits(&self) -> usize {
1549 ffi::tableau_simulator_num_qubits(self.inner())
1550 }
1551
1552 pub fn set_num_qubits(&mut self, new_num_qubits: usize) {
1553 ffi::tableau_simulator_set_num_qubits(self.inner_mut(), new_num_qubits);
1554 }
1555
1556 #[must_use]
1557 pub fn current_inverse_tableau(&self) -> Tableau {
1558 Tableau {
1559 inner: ffi::tableau_simulator_current_inverse_tableau(self.inner()),
1560 }
1561 }
1562
1563 pub fn set_inverse_tableau(&mut self, tableau: &Tableau) {
1564 ffi::tableau_simulator_set_inverse_tableau(self.inner_mut(), tableau.inner());
1565 }
1566
1567 #[must_use]
1568 pub fn current_measurement_record(&self) -> Vec<bool> {
1569 ffi::tableau_simulator_current_measurement_record(self.inner())
1570 .into_iter()
1571 .map(|bit| bit != 0)
1572 .collect()
1573 }
1574
1575 pub fn do_circuit(&mut self, circuit: &Circuit) {
1576 ffi::tableau_simulator_do_circuit(self.inner_mut(), circuit.inner());
1577 }
1578
1579 pub fn do_pauli_string(&mut self, pauli_string: &PauliString) {
1580 ffi::tableau_simulator_do_pauli_string(self.inner_mut(), pauli_string.inner());
1581 }
1582
1583 pub fn do_tableau(&mut self, tableau: &Tableau, targets: &[usize]) {
1584 ffi::tableau_simulator_do_tableau(self.inner_mut(), tableau.inner(), targets);
1585 }
1586
1587 #[must_use]
1588 pub fn peek_bloch(&mut self, target: usize) -> PauliString {
1589 PauliString {
1590 inner: ffi::tableau_simulator_peek_bloch(self.inner_mut(), target),
1591 }
1592 }
1593
1594 pub fn peek_x(&mut self, target: usize) -> i32 {
1595 ffi::tableau_simulator_peek_x(self.inner_mut(), target)
1596 }
1597
1598 pub fn peek_y(&mut self, target: usize) -> i32 {
1599 ffi::tableau_simulator_peek_y(self.inner_mut(), target)
1600 }
1601
1602 pub fn peek_z(&mut self, target: usize) -> i32 {
1603 ffi::tableau_simulator_peek_z(self.inner_mut(), target)
1604 }
1605
1606 pub fn measure(&mut self, target: usize) -> bool {
1607 ffi::tableau_simulator_measure(self.inner_mut(), target)
1608 }
1609
1610 #[must_use]
1611 pub fn measure_many(&mut self, targets: &[usize]) -> Vec<bool> {
1612 ffi::tableau_simulator_measure_many(self.inner_mut(), targets)
1613 .into_iter()
1614 .map(|bit| bit != 0)
1615 .collect()
1616 }
1617
1618 pub fn peek_observable_expectation(
1619 &self,
1620 observable: &PauliString,
1621 ) -> Result<i32, cxx::Exception> {
1622 ffi::tableau_simulator_peek_observable_expectation(self.inner(), observable.inner())
1623 }
1624
1625 pub fn measure_observable(
1626 &mut self,
1627 observable: &PauliString,
1628 flip_probability: f64,
1629 ) -> Result<bool, cxx::Exception> {
1630 ffi::tableau_simulator_measure_observable(
1631 self.inner_mut(),
1632 observable.inner(),
1633 flip_probability,
1634 )
1635 }
1636
1637 pub fn postselect_observable(
1638 &mut self,
1639 observable: &PauliString,
1640 desired_value: bool,
1641 ) -> Result<(), cxx::Exception> {
1642 ffi::tableau_simulator_postselect_observable(
1643 self.inner_mut(),
1644 observable.inner(),
1645 desired_value,
1646 )
1647 }
1648
1649 pub fn postselect_x(
1650 &mut self,
1651 targets: &[usize],
1652 desired_value: bool,
1653 ) -> Result<(), cxx::Exception> {
1654 ffi::tableau_simulator_postselect_x(self.inner_mut(), targets, desired_value)
1655 }
1656
1657 pub fn postselect_y(
1658 &mut self,
1659 targets: &[usize],
1660 desired_value: bool,
1661 ) -> Result<(), cxx::Exception> {
1662 ffi::tableau_simulator_postselect_y(self.inner_mut(), targets, desired_value)
1663 }
1664
1665 pub fn postselect_z(
1666 &mut self,
1667 targets: &[usize],
1668 desired_value: bool,
1669 ) -> Result<(), cxx::Exception> {
1670 ffi::tableau_simulator_postselect_z(self.inner_mut(), targets, desired_value)
1671 }
1672
1673 pub fn measure_kickback(&mut self, target: usize) -> (bool, Option<PauliString>) {
1674 let data = ffi::tableau_simulator_measure_kickback(self.inner_mut(), target);
1675 let kickback = if data.has_kickback {
1676 Some(
1677 PauliString::from_text(&data.kickback_text)
1678 .expect("kickback text from stim-cxx should parse as a PauliString"),
1679 )
1680 } else {
1681 None
1682 };
1683 (data.result, kickback)
1684 }
1685}
1686
1687impl FlipSimulator {
1688 #[must_use]
1689 pub fn new(
1690 batch_size: usize,
1691 disable_stabilizer_randomization: bool,
1692 num_qubits: usize,
1693 seed: u64,
1694 ) -> Self {
1695 Self {
1696 inner: ffi::new_frame_simulator(
1697 batch_size,
1698 disable_stabilizer_randomization,
1699 num_qubits,
1700 seed,
1701 ),
1702 }
1703 }
1704
1705 fn inner(&self) -> &ffi::FrameSimulatorHandle {
1706 self.inner
1707 .as_ref()
1708 .expect("stim-cxx frame simulator construction returned null")
1709 }
1710
1711 fn inner_mut(&mut self) -> Pin<&mut ffi::FrameSimulatorHandle> {
1712 self.inner.pin_mut()
1713 }
1714
1715 #[must_use]
1716 pub fn batch_size(&self) -> usize {
1717 ffi::frame_simulator_batch_size(self.inner())
1718 }
1719
1720 #[must_use]
1721 pub fn num_qubits(&self) -> usize {
1722 ffi::frame_simulator_num_qubits(self.inner())
1723 }
1724
1725 #[must_use]
1726 pub fn num_measurements(&self) -> usize {
1727 ffi::frame_simulator_num_measurements(self.inner())
1728 }
1729
1730 #[must_use]
1731 pub fn num_detectors(&self) -> usize {
1732 ffi::frame_simulator_num_detectors(self.inner())
1733 }
1734
1735 #[must_use]
1736 pub fn num_observables(&self) -> usize {
1737 ffi::frame_simulator_num_observables(self.inner())
1738 }
1739
1740 pub fn clear(&mut self) {
1741 ffi::frame_simulator_clear(self.inner_mut());
1742 }
1743
1744 pub fn do_circuit(&mut self, circuit: &Circuit) {
1745 ffi::frame_simulator_do_circuit(self.inner_mut(), circuit.inner());
1746 }
1747
1748 pub fn set_pauli_flip(
1749 &mut self,
1750 pauli: u8,
1751 qubit_index: i64,
1752 instance_index: i64,
1753 ) -> Result<(), cxx::Exception> {
1754 ffi::frame_simulator_set_pauli_flip(self.inner_mut(), pauli, qubit_index, instance_index)
1755 }
1756
1757 pub fn peek_pauli_flips(&self) -> Result<Vec<PauliString>, cxx::Exception> {
1758 ffi::frame_simulator_peek_pauli_flips(self.inner())
1759 .into_iter()
1760 .map(|text| PauliString::from_text(&text))
1761 .collect()
1762 }
1763
1764 pub fn peek_pauli_flip(&self, instance_index: i64) -> Result<PauliString, cxx::Exception> {
1765 ffi::frame_simulator_peek_pauli_flip(self.inner(), instance_index)
1766 .and_then(|text| PauliString::from_text(&text))
1767 }
1768
1769 pub fn broadcast_pauli_errors(
1770 &mut self,
1771 pauli: u8,
1772 mask: Vec<u8>,
1773 mask_num_qubits: usize,
1774 p: f32,
1775 ) -> Result<(), cxx::Exception> {
1776 ffi::frame_simulator_broadcast_pauli_errors(
1777 self.inner_mut(),
1778 pauli,
1779 mask,
1780 mask_num_qubits,
1781 p,
1782 )
1783 }
1784
1785 pub fn generate_bernoulli_samples(
1786 &mut self,
1787 num_samples: usize,
1788 p: f32,
1789 bit_packed: bool,
1790 ) -> Result<Vec<u8>, cxx::Exception> {
1791 ffi::frame_simulator_generate_bernoulli_samples(
1792 self.inner_mut(),
1793 num_samples,
1794 p,
1795 bit_packed,
1796 )
1797 }
1798
1799 pub fn append_measurement_flips(
1800 &mut self,
1801 data: Vec<u8>,
1802 num_measurements: usize,
1803 bit_packed: bool,
1804 ) -> Result<(), cxx::Exception> {
1805 ffi::frame_simulator_append_measurement_flips(
1806 self.inner_mut(),
1807 data,
1808 num_measurements,
1809 bit_packed,
1810 )
1811 }
1812
1813 pub fn get_measurement_flips(&self, bit_packed: bool) -> ffi::BitTableData {
1814 ffi::frame_simulator_get_measurement_flips(self.inner(), bit_packed)
1815 }
1816
1817 pub fn get_detector_flips(&self, bit_packed: bool) -> ffi::BitTableData {
1818 ffi::frame_simulator_get_detector_flips(self.inner(), bit_packed)
1819 }
1820
1821 pub fn get_observable_flips(&self, bit_packed: bool) -> ffi::BitTableData {
1822 ffi::frame_simulator_get_observable_flips(self.inner(), bit_packed)
1823 }
1824}
1825
1826impl PauliString {
1827 #[must_use]
1828 pub fn new(num_qubits: usize) -> Self {
1829 Self {
1830 inner: ffi::new_pauli_string(num_qubits),
1831 }
1832 }
1833
1834 pub fn from_text(text: &str) -> Result<Self, cxx::Exception> {
1835 ffi::pauli_string_from_text(text).map(|inner| Self { inner })
1836 }
1837
1838 #[must_use]
1839 pub fn random(num_qubits: usize) -> Self {
1840 Self {
1841 inner: ffi::pauli_string_random(num_qubits),
1842 }
1843 }
1844
1845 #[must_use]
1846 pub fn iter_all(
1847 num_qubits: usize,
1848 min_weight: usize,
1849 max_weight: usize,
1850 allow_x: bool,
1851 allow_y: bool,
1852 allow_z: bool,
1853 ) -> PauliStringIterator {
1854 PauliStringIterator {
1855 inner: ffi::pauli_string_iter_all(
1856 num_qubits, min_weight, max_weight, allow_x, allow_y, allow_z,
1857 ),
1858 }
1859 }
1860
1861 fn inner(&self) -> &ffi::PauliStringHandle {
1862 self.inner
1863 .as_ref()
1864 .expect("stim-cxx pauli string construction returned null")
1865 }
1866
1867 #[must_use]
1868 pub fn num_qubits(&self) -> usize {
1869 ffi::pauli_string_num_qubits(self.inner())
1870 }
1871
1872 #[must_use]
1873 pub fn weight(&self) -> usize {
1874 ffi::pauli_string_weight(self.inner())
1875 }
1876
1877 pub fn get_item(&self, index: i64) -> Result<u8, cxx::Exception> {
1878 ffi::pauli_string_get_item(self.inner(), index)
1879 }
1880
1881 pub fn set_item(&mut self, index: i64, new_pauli: u8) -> Result<(), cxx::Exception> {
1882 ffi::pauli_string_set_item(self.inner.pin_mut(), index, new_pauli)
1883 }
1884
1885 pub fn get_slice(&self, start: i64, step: i64, slice_length: i64) -> PauliString {
1886 PauliString {
1887 inner: ffi::pauli_string_get_slice(self.inner(), start, step, slice_length),
1888 }
1889 }
1890
1891 #[must_use]
1892 pub fn commutes(&self, other: &Self) -> bool {
1893 ffi::pauli_string_commutes(self.inner(), other.inner())
1894 }
1895
1896 pub fn pauli_indices(&self, included_paulis: &str) -> Result<Vec<u64>, cxx::Exception> {
1897 ffi::pauli_string_pauli_indices(self.inner(), included_paulis)
1898 }
1899
1900 pub fn sign_code(&self) -> i32 {
1901 ffi::pauli_string_sign_code(self.inner())
1902 }
1903
1904 pub fn to_tableau(&self) -> Tableau {
1905 Tableau {
1906 inner: ffi::pauli_string_to_tableau(self.inner()),
1907 }
1908 }
1909
1910 #[must_use]
1911 pub fn to_text(&self) -> String {
1912 ffi::pauli_string_to_string(self.inner())
1913 }
1914
1915 #[must_use]
1916 pub fn to_repr_text(&self) -> String {
1917 ffi::pauli_string_to_repr(self.inner())
1918 }
1919}
1920
1921impl CliffordString {
1922 #[must_use]
1923 pub fn new(num_qubits: usize) -> Self {
1924 Self {
1925 inner: ffi::new_clifford_string(num_qubits),
1926 }
1927 }
1928
1929 pub fn from_text(text: &str) -> Result<Self, cxx::Exception> {
1930 ffi::clifford_string_from_text(text).map(|inner| Self { inner })
1931 }
1932
1933 #[must_use]
1934 pub fn from_pauli_string(pauli_string: &PauliString) -> Self {
1935 Self {
1936 inner: ffi::clifford_string_from_pauli_string(pauli_string.inner()),
1937 }
1938 }
1939
1940 pub fn from_circuit(circuit: &Circuit) -> Result<Self, cxx::Exception> {
1941 ffi::clifford_string_from_circuit(circuit.inner()).map(|inner| Self { inner })
1942 }
1943
1944 #[must_use]
1945 pub fn random(num_qubits: usize) -> Self {
1946 Self {
1947 inner: ffi::clifford_string_random(num_qubits),
1948 }
1949 }
1950
1951 #[must_use]
1952 pub fn all_cliffords_string() -> Self {
1953 Self {
1954 inner: ffi::clifford_string_all_cliffords_string(),
1955 }
1956 }
1957
1958 fn inner(&self) -> &ffi::CliffordStringHandle {
1959 self.inner
1960 .as_ref()
1961 .expect("stim-cxx clifford string construction returned null")
1962 }
1963
1964 #[must_use]
1965 pub fn num_qubits(&self) -> usize {
1966 ffi::clifford_string_num_qubits(self.inner())
1967 }
1968
1969 pub fn get_item_name(&self, index: i64) -> Result<String, cxx::Exception> {
1970 ffi::clifford_string_get_item_name(self.inner(), index)
1971 }
1972
1973 #[must_use]
1974 pub fn get_slice(&self, start: i64, step: i64, slice_length: i64) -> Self {
1975 Self {
1976 inner: ffi::clifford_string_get_slice(self.inner(), start, step, slice_length),
1977 }
1978 }
1979
1980 #[must_use]
1981 pub fn add(&self, other: &Self) -> Self {
1982 Self {
1983 inner: ffi::clifford_string_add(self.inner(), other.inner()),
1984 }
1985 }
1986
1987 pub fn add_assign(&mut self, other: &Self) {
1988 ffi::clifford_string_add_assign(self.inner.pin_mut(), other.inner());
1989 }
1990
1991 #[must_use]
1992 pub fn mul_clifford(&self, other: &Self) -> Self {
1993 Self {
1994 inner: ffi::clifford_string_mul(self.inner(), other.inner()),
1995 }
1996 }
1997
1998 pub fn mul_assign_clifford(&mut self, other: &Self) {
1999 ffi::clifford_string_mul_assign(self.inner.pin_mut(), other.inner());
2000 }
2001
2002 pub fn repeat(&self, repetitions: u64) -> Result<Self, cxx::Exception> {
2003 ffi::clifford_string_repeat(self.inner(), repetitions).map(|inner| Self { inner })
2004 }
2005
2006 pub fn repeat_assign(&mut self, repetitions: u64) -> Result<(), cxx::Exception> {
2007 ffi::clifford_string_repeat_assign(self.inner.pin_mut(), repetitions)
2008 }
2009
2010 #[must_use]
2011 pub fn pow(&self, exponent: i64) -> Self {
2012 Self {
2013 inner: ffi::clifford_string_pow(self.inner(), exponent),
2014 }
2015 }
2016
2017 pub fn ipow(&mut self, exponent: i64) {
2018 ffi::clifford_string_ipow(self.inner.pin_mut(), exponent);
2019 }
2020
2021 #[must_use]
2022 pub fn x_outputs(&self) -> PauliString {
2023 PauliString {
2024 inner: ffi::clifford_string_x_outputs(self.inner()),
2025 }
2026 }
2027
2028 #[must_use]
2029 pub fn x_signs_bit_packed(&self) -> Vec<u8> {
2030 ffi::clifford_string_x_signs_bit_packed(self.inner())
2031 }
2032
2033 #[must_use]
2034 pub fn y_outputs(&self) -> PauliString {
2035 PauliString {
2036 inner: ffi::clifford_string_y_outputs(self.inner()),
2037 }
2038 }
2039
2040 #[must_use]
2041 pub fn y_signs_bit_packed(&self) -> Vec<u8> {
2042 ffi::clifford_string_y_signs_bit_packed(self.inner())
2043 }
2044
2045 #[must_use]
2046 pub fn z_outputs(&self) -> PauliString {
2047 PauliString {
2048 inner: ffi::clifford_string_z_outputs(self.inner()),
2049 }
2050 }
2051
2052 #[must_use]
2053 pub fn z_signs_bit_packed(&self) -> Vec<u8> {
2054 ffi::clifford_string_z_signs_bit_packed(self.inner())
2055 }
2056
2057 #[must_use]
2058 pub fn to_text(&self) -> String {
2059 ffi::clifford_string_to_string(self.inner())
2060 }
2061
2062 #[must_use]
2063 pub fn to_repr_text(&self) -> String {
2064 ffi::clifford_string_to_repr(self.inner())
2065 }
2066}
2067
2068impl Clone for Circuit {
2069 fn clone(&self) -> Self {
2070 Self {
2071 inner: ffi::circuit_clone(self.inner()),
2072 }
2073 }
2074}
2075
2076impl Clone for DetectorErrorModel {
2077 fn clone(&self) -> Self {
2078 Self {
2079 inner: ffi::detector_error_model_clone(self.inner()),
2080 }
2081 }
2082}
2083
2084impl Clone for Tableau {
2085 fn clone(&self) -> Self {
2086 Self {
2087 inner: ffi::tableau_clone(self.inner()),
2088 }
2089 }
2090}
2091
2092impl Clone for TableauSimulator {
2093 fn clone(&self) -> Self {
2094 Self {
2095 inner: ffi::tableau_simulator_clone(self.inner()),
2096 }
2097 }
2098}
2099
2100impl Clone for FlipSimulator {
2101 fn clone(&self) -> Self {
2102 Self {
2103 inner: ffi::frame_simulator_clone(self.inner()),
2104 }
2105 }
2106}
2107
2108impl TableauIterator {
2109 fn inner(&self) -> &ffi::TableauIteratorHandle {
2110 self.inner
2111 .as_ref()
2112 .expect("stim-cxx tableau iterator construction returned null")
2113 }
2114
2115 fn inner_mut(&mut self) -> Pin<&mut ffi::TableauIteratorHandle> {
2116 self.inner.pin_mut()
2117 }
2118}
2119
2120impl Clone for TableauIterator {
2121 fn clone(&self) -> Self {
2122 Self {
2123 inner: ffi::tableau_iterator_clone(self.inner()),
2124 }
2125 }
2126}
2127
2128impl Iterator for TableauIterator {
2129 type Item = Tableau;
2130
2131 fn next(&mut self) -> Option<Self::Item> {
2132 let inner = ffi::tableau_iterator_next(self.inner_mut());
2133 if inner.is_null() {
2134 None
2135 } else {
2136 Some(Tableau { inner })
2137 }
2138 }
2139}
2140
2141impl PartialEq for Tableau {
2142 fn eq(&self, other: &Self) -> bool {
2143 ffi::tableau_equals(self.inner(), other.inner())
2144 }
2145}
2146
2147impl Eq for Tableau {}
2148
2149impl Clone for PauliString {
2150 fn clone(&self) -> Self {
2151 Self {
2152 inner: ffi::pauli_string_clone(self.inner()),
2153 }
2154 }
2155}
2156
2157impl PauliStringIterator {
2158 fn inner(&self) -> &ffi::PauliStringIteratorHandle {
2159 self.inner
2160 .as_ref()
2161 .expect("stim-cxx pauli string iterator construction returned null")
2162 }
2163
2164 fn inner_mut(&mut self) -> Pin<&mut ffi::PauliStringIteratorHandle> {
2165 self.inner.pin_mut()
2166 }
2167}
2168
2169impl Clone for PauliStringIterator {
2170 fn clone(&self) -> Self {
2171 Self {
2172 inner: ffi::pauli_string_iterator_clone(self.inner()),
2173 }
2174 }
2175}
2176
2177impl Iterator for PauliStringIterator {
2178 type Item = PauliString;
2179
2180 fn next(&mut self) -> Option<Self::Item> {
2181 let inner = ffi::pauli_string_iterator_next(self.inner_mut());
2182 if inner.is_null() {
2183 None
2184 } else {
2185 Some(PauliString { inner })
2186 }
2187 }
2188}
2189
2190impl PartialEq for PauliString {
2191 fn eq(&self, other: &Self) -> bool {
2192 ffi::pauli_string_equals(self.inner(), other.inner())
2193 }
2194}
2195
2196impl Eq for PauliString {}
2197
2198impl Clone for CliffordString {
2199 fn clone(&self) -> Self {
2200 Self {
2201 inner: ffi::clifford_string_clone(self.inner()),
2202 }
2203 }
2204}
2205
2206impl PartialEq for CliffordString {
2207 fn eq(&self, other: &Self) -> bool {
2208 ffi::clifford_string_equals(self.inner(), other.inner())
2209 }
2210}
2211
2212impl Eq for CliffordString {}
2213
2214impl Clone for GateData {
2215 fn clone(&self) -> Self {
2216 self.clone_handle()
2217 }
2218}
2219
2220impl Default for Circuit {
2221 fn default() -> Self {
2222 Self::new()
2223 }
2224}
2225
2226impl Default for DetectorErrorModel {
2227 fn default() -> Self {
2228 Self::new()
2229 }
2230}
2231
2232pub struct SmokeProbe {
2233 inner: UniquePtr<ffi::SmokeProbe>,
2234}
2235
2236impl SmokeProbe {
2237 #[must_use]
2238 pub fn new() -> Self {
2239 Self {
2240 inner: ffi::new_smoke_probe(),
2241 }
2242 }
2243
2244 #[must_use]
2245 pub fn describe(&self) -> String {
2246 self.inner().describe().to_string()
2247 }
2248
2249 #[must_use]
2250 pub fn weighted_checksum(&self, values: &[u64]) -> u64 {
2251 self.inner().weighted_checksum(values)
2252 }
2253
2254 fn inner(&self) -> &ffi::SmokeProbe {
2255 self.inner
2256 .as_ref()
2257 .expect("stim-cxx smoke probe construction returned null")
2258 }
2259}
2260
2261impl Default for SmokeProbe {
2262 fn default() -> Self {
2263 Self::new()
2264 }
2265}
2266
2267#[cxx::bridge(namespace = "stimrs::bridge")]
2268mod ffi {
2269 struct DemSampleBatch {
2270 detectors: Vec<u8>,
2271 observables: Vec<u8>,
2272 errors: Vec<u8>,
2273 }
2274
2275 struct DetectorSampleBatch {
2276 detectors: Vec<u8>,
2277 observables: Vec<u8>,
2278 }
2279
2280 struct CircuitTopLevelItemData {
2281 is_repeat_block: bool,
2282 name: String,
2283 tag: String,
2284 gate_args: Vec<f64>,
2285 targets: Vec<u32>,
2286 repeat_count: u64,
2287 }
2288
2289 struct DemTopLevelItemData {
2290 is_repeat_block: bool,
2291 instruction_type: String,
2292 tag: String,
2293 args: Vec<f64>,
2294 targets: Vec<u64>,
2295 repeat_count: u64,
2296 }
2297
2298 struct TableauMeasureKickbackData {
2299 result: bool,
2300 has_kickback: bool,
2301 kickback_text: String,
2302 }
2303
2304 struct BitTableData {
2305 data: Vec<u8>,
2306 rows: u64,
2307 cols: u64,
2308 bit_packed: bool,
2309 }
2310
2311 struct CoordinateEntryData {
2312 index: u64,
2313 coords: Vec<f64>,
2314 }
2315
2316 struct DetectingRegionEntryData {
2317 target_index: u64,
2318 target_is_observable: bool,
2319 tick: u64,
2320 pauli: String,
2321 }
2322
2323 struct GateTargetWithCoordsData {
2324 raw_target: u32,
2325 coords: Vec<f64>,
2326 }
2327
2328 struct DemTargetWithCoordsData {
2329 dem_target: String,
2330 coords: Vec<f64>,
2331 }
2332
2333 struct CircuitErrorLocationStackFrameData {
2334 instruction_offset: u64,
2335 iteration_index: u64,
2336 instruction_repetitions_arg: u64,
2337 }
2338
2339 struct CircuitTargetsInsideInstructionData {
2340 gate: String,
2341 tag: String,
2342 args: Vec<f64>,
2343 target_range_start: u64,
2344 target_range_end: u64,
2345 targets_in_range: Vec<GateTargetWithCoordsData>,
2346 }
2347
2348 struct FlippedMeasurementData {
2349 record_index: u64,
2350 observable: Vec<GateTargetWithCoordsData>,
2351 }
2352
2353 struct CircuitErrorLocationData {
2354 tick_offset: u64,
2355 flipped_pauli_product: Vec<GateTargetWithCoordsData>,
2356 flipped_measurement: FlippedMeasurementData,
2357 instruction_targets: CircuitTargetsInsideInstructionData,
2358 stack_frames: Vec<CircuitErrorLocationStackFrameData>,
2359 noise_tag: String,
2360 }
2361
2362 struct ExplainedErrorData {
2363 dem_error_terms: Vec<DemTargetWithCoordsData>,
2364 circuit_error_locations: Vec<CircuitErrorLocationData>,
2365 }
2366
2367 unsafe extern "C++" {
2368 include!("stim-cxx/include/stim_rs_bridge.h");
2369
2370 fn read_shot_data_file_bit_packed(
2371 filepath: &str,
2372 format_name: &str,
2373 num_measurements: u64,
2374 num_detectors: u64,
2375 num_observables: u64,
2376 ) -> Result<Vec<u8>>;
2377 fn write_shot_data_file_bit_packed(
2378 data: &[u8],
2379 shots: u64,
2380 filepath: &str,
2381 format_name: &str,
2382 num_measurements: u64,
2383 num_detectors: u64,
2384 num_observables: u64,
2385 ) -> Result<()>;
2386 fn all_gate_names() -> Vec<String>;
2387 fn canonicalize_flow_text(text: &str) -> Result<String>;
2388 fn multiply_flow_texts(left: &str, right: &str) -> Result<String>;
2389
2390 type CircuitHandle;
2391 type DetectorErrorModelHandle;
2392 type TableauHandle;
2393 type TableauSimulatorHandle;
2394 type FrameSimulatorHandle;
2395 type TableauIteratorHandle;
2396 type PauliStringHandle;
2397 type CliffordStringHandle;
2398 type PauliStringIteratorHandle;
2399 type DetectorSamplerHandle;
2400 type GateDataHandle;
2401 type MeasurementSamplerHandle;
2402 type MeasurementsToDetectionEventsConverterHandle;
2403 type DemSamplerHandle;
2404 type SmokeProbe;
2405
2406 fn gate_data_by_name(name: &str) -> Result<UniquePtr<GateDataHandle>>;
2407 fn name(self: &GateDataHandle) -> String;
2408 fn aliases(self: &GateDataHandle) -> Vec<String>;
2409 fn num_parens_arguments_range(self: &GateDataHandle) -> Vec<u8>;
2410 fn is_noisy_gate(self: &GateDataHandle) -> bool;
2411 fn is_reset(self: &GateDataHandle) -> bool;
2412 fn is_single_qubit_gate(self: &GateDataHandle) -> bool;
2413 fn is_symmetric_gate(self: &GateDataHandle) -> bool;
2414 fn is_two_qubit_gate(self: &GateDataHandle) -> bool;
2415 fn is_unitary(self: &GateDataHandle) -> bool;
2416 fn produces_measurements(self: &GateDataHandle) -> bool;
2417 fn takes_measurement_record_targets(self: &GateDataHandle) -> bool;
2418 fn takes_pauli_targets(self: &GateDataHandle) -> bool;
2419 fn flows(self: &GateDataHandle) -> Vec<String>;
2420 fn tableau(self: &GateDataHandle) -> UniquePtr<TableauHandle>;
2421 fn clone_handle(self: &GateDataHandle) -> UniquePtr<GateDataHandle>;
2422 fn inverse(self: &GateDataHandle) -> UniquePtr<GateDataHandle>;
2423 fn generalized_inverse(self: &GateDataHandle) -> UniquePtr<GateDataHandle>;
2424 fn hadamard_conjugated(
2425 self: &GateDataHandle,
2426 unsigned_only: bool,
2427 ) -> UniquePtr<GateDataHandle>;
2428
2429 fn new_circuit() -> UniquePtr<CircuitHandle>;
2430 fn circuit_from_stim_program_text(text: &str) -> Result<UniquePtr<CircuitHandle>>;
2431 fn circuit_clone(handle: &CircuitHandle) -> UniquePtr<CircuitHandle>;
2432 fn circuit_add(left: &CircuitHandle, right: &CircuitHandle) -> UniquePtr<CircuitHandle>;
2433 fn circuit_add_assign(left: Pin<&mut CircuitHandle>, right: &CircuitHandle);
2434 fn circuit_mul(handle: &CircuitHandle, repetitions: u64) -> UniquePtr<CircuitHandle>;
2435 fn circuit_mul_assign(handle: Pin<&mut CircuitHandle>, repetitions: u64);
2436 fn circuit_generated(
2437 code_task: &str,
2438 distance: usize,
2439 rounds: usize,
2440 after_clifford_depolarization: f64,
2441 before_round_data_depolarization: f64,
2442 before_measure_flip_probability: f64,
2443 after_reset_flip_probability: f64,
2444 ) -> Result<UniquePtr<CircuitHandle>>;
2445 fn circuit_has_flow_text(
2446 handle: &CircuitHandle,
2447 flow_text: &str,
2448 unsigned_only: bool,
2449 ) -> Result<bool>;
2450 fn circuit_has_all_flows_text(
2451 handle: &CircuitHandle,
2452 flow_texts: Vec<String>,
2453 unsigned_only: bool,
2454 ) -> Result<bool>;
2455 fn circuit_flow_generators_texts(handle: &CircuitHandle) -> Vec<String>;
2456 fn circuit_solve_flow_measurements_text(
2457 handle: &CircuitHandle,
2458 flow_texts: Vec<String>,
2459 ) -> Result<Vec<String>>;
2460 fn circuit_time_reversed_for_flows_text(
2461 out_flow_texts: &mut Vec<String>,
2462 handle: &CircuitHandle,
2463 flow_texts: Vec<String>,
2464 dont_turn_measurements_into_resets: bool,
2465 ) -> Result<String>;
2466 fn circuit_diagram_with_options(
2467 handle: &CircuitHandle,
2468 type_name: &str,
2469 has_tick_range: bool,
2470 tick_start: u64,
2471 tick_count: u64,
2472 has_rows: bool,
2473 rows: usize,
2474 ) -> Result<String>;
2475 fn circuit_diagram_with_options_and_filters(
2476 handle: &CircuitHandle,
2477 type_name: &str,
2478 has_tick_range: bool,
2479 tick_start: u64,
2480 tick_count: u64,
2481 has_rows: bool,
2482 rows: usize,
2483 filter_coords: Vec<String>,
2484 ) -> Result<String>;
2485 fn circuit_to_stim_program_text(handle: &CircuitHandle) -> String;
2486 fn circuit_num_qubits(handle: &CircuitHandle) -> usize;
2487 fn circuit_len(handle: &CircuitHandle) -> usize;
2488 fn circuit_get_top_level_item(
2489 handle: &CircuitHandle,
2490 index: usize,
2491 ) -> CircuitTopLevelItemData;
2492 fn circuit_get_top_level_repeat_block_body(
2493 handle: &CircuitHandle,
2494 index: usize,
2495 ) -> UniquePtr<CircuitHandle>;
2496 fn circuit_get_slice(
2497 handle: &CircuitHandle,
2498 start: i64,
2499 step: i64,
2500 slice_length: i64,
2501 ) -> UniquePtr<CircuitHandle>;
2502 fn circuit_remove_top_level(handle: Pin<&mut CircuitHandle>, index: usize);
2503 fn circuit_num_measurements(handle: &CircuitHandle) -> u64;
2504 fn circuit_count_determined_measurements(
2505 handle: &CircuitHandle,
2506 unknown_input: bool,
2507 ) -> u64;
2508 fn circuit_num_detectors(handle: &CircuitHandle) -> u64;
2509 fn circuit_num_observables(handle: &CircuitHandle) -> u64;
2510 fn circuit_num_ticks(handle: &CircuitHandle) -> u64;
2511 fn circuit_num_sweep_bits(handle: &CircuitHandle) -> usize;
2512 fn circuit_append_from_stim_program_text(
2513 handle: Pin<&mut CircuitHandle>,
2514 text: &str,
2515 ) -> Result<()>;
2516 fn circuit_append_gate(
2517 handle: Pin<&mut CircuitHandle>,
2518 gate_name: &str,
2519 targets: &[u32],
2520 args: &[f64],
2521 tag: &str,
2522 ) -> Result<()>;
2523 fn circuit_append_repeat_block(
2524 handle: Pin<&mut CircuitHandle>,
2525 repeat_count: u64,
2526 body: &CircuitHandle,
2527 tag: &str,
2528 ) -> Result<()>;
2529 fn circuit_insert_gate(
2530 handle: Pin<&mut CircuitHandle>,
2531 index: usize,
2532 gate_name: &str,
2533 targets: &[u32],
2534 args: &[f64],
2535 tag: &str,
2536 ) -> Result<()>;
2537 fn circuit_insert_repeat_block(
2538 handle: Pin<&mut CircuitHandle>,
2539 index: usize,
2540 repeat_count: u64,
2541 body: &CircuitHandle,
2542 tag: &str,
2543 ) -> Result<()>;
2544 fn circuit_insert_circuit(
2545 handle: Pin<&mut CircuitHandle>,
2546 index: usize,
2547 circuit: &CircuitHandle,
2548 );
2549 fn circuit_clear(handle: Pin<&mut CircuitHandle>);
2550 fn circuit_equals(left: &CircuitHandle, right: &CircuitHandle) -> bool;
2551 fn circuit_approx_equals(left: &CircuitHandle, right: &CircuitHandle, atol: f64) -> bool;
2552 fn circuit_without_noise(handle: &CircuitHandle) -> UniquePtr<CircuitHandle>;
2553 fn circuit_with_inlined_feedback(handle: &CircuitHandle) -> UniquePtr<CircuitHandle>;
2554 fn circuit_without_tags(handle: &CircuitHandle) -> UniquePtr<CircuitHandle>;
2555 fn circuit_flattened(handle: &CircuitHandle) -> UniquePtr<CircuitHandle>;
2556 fn circuit_decomposed(handle: &CircuitHandle) -> UniquePtr<CircuitHandle>;
2557 fn circuit_inverse(handle: &CircuitHandle) -> Result<UniquePtr<CircuitHandle>>;
2558 fn circuit_to_qasm(
2559 handle: &CircuitHandle,
2560 open_qasm_version: i32,
2561 skip_dets_and_obs: bool,
2562 ) -> Result<String>;
2563 fn circuit_to_quirk_url(handle: &CircuitHandle) -> Result<String>;
2564 fn circuit_to_crumble_url(handle: &CircuitHandle, skip_detectors: bool) -> Result<String>;
2565 fn circuit_shortest_error_sat_problem(
2566 handle: &CircuitHandle,
2567 format_name: &str,
2568 ) -> Result<String>;
2569 fn circuit_likeliest_error_sat_problem(
2570 handle: &CircuitHandle,
2571 quantization: i32,
2572 format_name: &str,
2573 ) -> Result<String>;
2574 fn circuit_detecting_regions(
2575 handle: &CircuitHandle,
2576 ) -> Result<Vec<DetectingRegionEntryData>>;
2577 fn circuit_detecting_regions_with_options(
2578 handle: &CircuitHandle,
2579 target_texts: Vec<String>,
2580 ticks: Vec<u64>,
2581 ignore_anticommutation_errors: bool,
2582 ) -> Result<Vec<DetectingRegionEntryData>>;
2583 fn circuit_explain_detector_error_model_errors(
2584 handle: &CircuitHandle,
2585 dem_filter_text: &str,
2586 has_dem_filter: bool,
2587 reduce_to_one_representative_error: bool,
2588 ) -> Result<Vec<ExplainedErrorData>>;
2589 fn circuit_shortest_graphlike_error(
2590 handle: &CircuitHandle,
2591 ignore_ungraphlike_errors: bool,
2592 canonicalize_circuit_errors: bool,
2593 ) -> Result<Vec<ExplainedErrorData>>;
2594 fn circuit_flattened_operation_texts(handle: &CircuitHandle) -> Vec<String>;
2595 fn circuit_search_for_undetectable_logical_errors(
2596 handle: &CircuitHandle,
2597 dont_explore_detection_event_sets_with_size_above: u64,
2598 dont_explore_edges_with_degree_above: u64,
2599 dont_explore_edges_increasing_symptom_degree: bool,
2600 canonicalize_circuit_errors: bool,
2601 ) -> Result<Vec<ExplainedErrorData>>;
2602 fn circuit_get_detector_coordinates(
2603 handle: &CircuitHandle,
2604 included_detector_indices: &[u64],
2605 ) -> Result<Vec<CoordinateEntryData>>;
2606 fn circuit_get_final_qubit_coordinates(
2607 handle: &CircuitHandle,
2608 ) -> Result<Vec<CoordinateEntryData>>;
2609 fn circuit_reference_sample_bit_packed(handle: &CircuitHandle) -> Vec<u8>;
2610 fn circuit_reference_detector_signs_bit_packed(handle: &CircuitHandle) -> Vec<u8>;
2611 fn circuit_reference_observable_signs_bit_packed(handle: &CircuitHandle) -> Vec<u8>;
2612 fn new_detector_error_model() -> UniquePtr<DetectorErrorModelHandle>;
2613 fn circuit_detector_error_model(
2614 handle: &CircuitHandle,
2615 decompose_errors: bool,
2616 flatten_loops: bool,
2617 allow_gauge_detectors: bool,
2618 approximate_disjoint_errors: f64,
2619 ignore_decomposition_failures: bool,
2620 block_decomposition_from_introducing_remnant_edges: bool,
2621 ) -> Result<UniquePtr<DetectorErrorModelHandle>>;
2622 fn circuit_missing_detectors(
2623 handle: &CircuitHandle,
2624 unknown_input: bool,
2625 ) -> UniquePtr<CircuitHandle>;
2626 fn circuit_to_tableau(
2627 handle: &CircuitHandle,
2628 ignore_noise: bool,
2629 ignore_measurement: bool,
2630 ignore_reset: bool,
2631 ) -> Result<UniquePtr<TableauHandle>>;
2632 fn new_tableau(num_qubits: usize) -> UniquePtr<TableauHandle>;
2633 fn tableau_random(num_qubits: usize) -> UniquePtr<TableauHandle>;
2634 fn tableau_iter_all(
2635 num_qubits: usize,
2636 unsigned_only: bool,
2637 ) -> UniquePtr<TableauIteratorHandle>;
2638 fn tableau_iterator_clone(
2639 handle: &TableauIteratorHandle,
2640 ) -> UniquePtr<TableauIteratorHandle>;
2641 fn tableau_iterator_next(
2642 handle: Pin<&mut TableauIteratorHandle>,
2643 ) -> UniquePtr<TableauHandle>;
2644 fn tableau_from_named_gate(name: &str) -> Result<UniquePtr<TableauHandle>>;
2645 fn tableau_from_state_vector_data(
2646 state_vector: Vec<f32>,
2647 endian: &str,
2648 ) -> Result<UniquePtr<TableauHandle>>;
2649 fn tableau_from_unitary_matrix_data(
2650 matrix: Vec<f32>,
2651 endian: &str,
2652 ) -> Result<UniquePtr<TableauHandle>>;
2653 fn tableau_from_conjugated_generator_texts(
2654 xs: Vec<String>,
2655 zs: Vec<String>,
2656 ) -> Result<UniquePtr<TableauHandle>>;
2657 fn tableau_from_stabilizer_texts(
2658 stabilizers: Vec<String>,
2659 allow_redundant: bool,
2660 allow_underconstrained: bool,
2661 ) -> Result<UniquePtr<TableauHandle>>;
2662 fn tableau_then(
2663 handle: &TableauHandle,
2664 second: &TableauHandle,
2665 ) -> Result<UniquePtr<TableauHandle>>;
2666 fn new_tableau_simulator(seed: u64, num_qubits: usize)
2667 -> UniquePtr<TableauSimulatorHandle>;
2668 fn new_clifford_string(num_qubits: usize) -> UniquePtr<CliffordStringHandle>;
2669 fn clifford_string_from_text(text: &str) -> Result<UniquePtr<CliffordStringHandle>>;
2670 fn clifford_string_from_pauli_string(
2671 handle: &PauliStringHandle,
2672 ) -> UniquePtr<CliffordStringHandle>;
2673 fn clifford_string_from_circuit(
2674 handle: &CircuitHandle,
2675 ) -> Result<UniquePtr<CliffordStringHandle>>;
2676 fn clifford_string_random(num_qubits: usize) -> UniquePtr<CliffordStringHandle>;
2677 fn clifford_string_all_cliffords_string() -> UniquePtr<CliffordStringHandle>;
2678 fn new_pauli_string(num_qubits: usize) -> UniquePtr<PauliStringHandle>;
2679 fn pauli_string_from_text(text: &str) -> Result<UniquePtr<PauliStringHandle>>;
2680 fn detector_error_model_from_dem_text(
2681 text: &str,
2682 ) -> Result<UniquePtr<DetectorErrorModelHandle>>;
2683 fn circuit_diagram(handle: &CircuitHandle, type_name: &str) -> Result<String>;
2684 fn detector_error_model_diagram(
2685 handle: &DetectorErrorModelHandle,
2686 type_name: &str,
2687 ) -> Result<String>;
2688 fn detector_error_model_clone(
2689 handle: &DetectorErrorModelHandle,
2690 ) -> UniquePtr<DetectorErrorModelHandle>;
2691 fn detector_error_model_add(
2692 left: &DetectorErrorModelHandle,
2693 right: &DetectorErrorModelHandle,
2694 ) -> UniquePtr<DetectorErrorModelHandle>;
2695 fn detector_error_model_add_assign(
2696 left: Pin<&mut DetectorErrorModelHandle>,
2697 right: &DetectorErrorModelHandle,
2698 );
2699 fn detector_error_model_mul(
2700 handle: &DetectorErrorModelHandle,
2701 repetitions: u64,
2702 ) -> UniquePtr<DetectorErrorModelHandle>;
2703 fn detector_error_model_mul_assign(
2704 handle: Pin<&mut DetectorErrorModelHandle>,
2705 repetitions: u64,
2706 );
2707 fn detector_error_model_to_dem_text(handle: &DetectorErrorModelHandle) -> String;
2708 fn detector_error_model_len(handle: &DetectorErrorModelHandle) -> usize;
2709 fn detector_error_model_get_top_level_item(
2710 handle: &DetectorErrorModelHandle,
2711 index: usize,
2712 ) -> DemTopLevelItemData;
2713 fn detector_error_model_get_top_level_repeat_block_body(
2714 handle: &DetectorErrorModelHandle,
2715 index: usize,
2716 ) -> UniquePtr<DetectorErrorModelHandle>;
2717 fn detector_error_model_get_slice(
2718 handle: &DetectorErrorModelHandle,
2719 start: i64,
2720 step: i64,
2721 slice_length: i64,
2722 ) -> UniquePtr<DetectorErrorModelHandle>;
2723 fn detector_error_model_num_detectors(handle: &DetectorErrorModelHandle) -> u64;
2724 fn detector_error_model_num_errors(handle: &DetectorErrorModelHandle) -> u64;
2725 fn detector_error_model_num_observables(handle: &DetectorErrorModelHandle) -> u64;
2726 fn detector_error_model_get_detector_coordinates(
2727 handle: &DetectorErrorModelHandle,
2728 included_detector_indices: &[u64],
2729 ) -> Result<Vec<CoordinateEntryData>>;
2730 fn detector_error_model_clear(handle: Pin<&mut DetectorErrorModelHandle>);
2731 fn detector_error_model_equals(
2732 left: &DetectorErrorModelHandle,
2733 right: &DetectorErrorModelHandle,
2734 ) -> bool;
2735 fn detector_error_model_approx_equals(
2736 left: &DetectorErrorModelHandle,
2737 right: &DetectorErrorModelHandle,
2738 atol: f64,
2739 ) -> bool;
2740 fn detector_error_model_without_tags(
2741 handle: &DetectorErrorModelHandle,
2742 ) -> UniquePtr<DetectorErrorModelHandle>;
2743 fn detector_error_model_flattened(
2744 handle: &DetectorErrorModelHandle,
2745 ) -> UniquePtr<DetectorErrorModelHandle>;
2746 fn detector_error_model_rounded(
2747 handle: &DetectorErrorModelHandle,
2748 digits: u8,
2749 ) -> UniquePtr<DetectorErrorModelHandle>;
2750 fn detector_error_model_append_instruction(
2751 handle: Pin<&mut DetectorErrorModelHandle>,
2752 instruction_type: &str,
2753 args: &[f64],
2754 targets: &[u64],
2755 tag: &str,
2756 ) -> Result<()>;
2757 fn detector_error_model_append_repeat_block(
2758 handle: Pin<&mut DetectorErrorModelHandle>,
2759 repeat_count: u64,
2760 body: &DetectorErrorModelHandle,
2761 ) -> Result<()>;
2762 fn detector_error_model_shortest_graphlike_error(
2763 handle: &DetectorErrorModelHandle,
2764 ignore_ungraphlike_errors: bool,
2765 ) -> Result<UniquePtr<DetectorErrorModelHandle>>;
2766 fn detector_error_model_shortest_error_sat_problem(
2767 handle: &DetectorErrorModelHandle,
2768 format_name: &str,
2769 ) -> Result<String>;
2770 fn detector_error_model_likeliest_error_sat_problem(
2771 handle: &DetectorErrorModelHandle,
2772 quantization: i32,
2773 format_name: &str,
2774 ) -> Result<String>;
2775 fn tableau_clone(handle: &TableauHandle) -> UniquePtr<TableauHandle>;
2776 fn tableau_equals(left: &TableauHandle, right: &TableauHandle) -> bool;
2777 fn tableau_add(left: &TableauHandle, right: &TableauHandle) -> UniquePtr<TableauHandle>;
2778 fn tableau_add_assign(left: Pin<&mut TableauHandle>, right: &TableauHandle);
2779 fn tableau_append(
2780 handle: Pin<&mut TableauHandle>,
2781 gate: &TableauHandle,
2782 targets: &[usize],
2783 ) -> Result<()>;
2784 fn tableau_prepend(
2785 handle: Pin<&mut TableauHandle>,
2786 gate: &TableauHandle,
2787 targets: &[usize],
2788 ) -> Result<()>;
2789 fn tableau_inverse(handle: &TableauHandle, unsigned_only: bool)
2790 -> UniquePtr<TableauHandle>;
2791 fn tableau_raised_to(handle: &TableauHandle, exponent: i64) -> UniquePtr<TableauHandle>;
2792 fn tableau_x_sign(handle: &TableauHandle, target: usize) -> Result<i32>;
2793 fn tableau_y_sign(handle: &TableauHandle, target: usize) -> Result<i32>;
2794 fn tableau_z_sign(handle: &TableauHandle, target: usize) -> Result<i32>;
2795 fn tableau_x_output_pauli(
2796 handle: &TableauHandle,
2797 input_index: usize,
2798 output_index: usize,
2799 ) -> Result<u8>;
2800 fn tableau_y_output_pauli(
2801 handle: &TableauHandle,
2802 input_index: usize,
2803 output_index: usize,
2804 ) -> Result<u8>;
2805 fn tableau_z_output_pauli(
2806 handle: &TableauHandle,
2807 input_index: usize,
2808 output_index: usize,
2809 ) -> Result<u8>;
2810 fn tableau_inverse_x_output_pauli(
2811 handle: &TableauHandle,
2812 input_index: usize,
2813 output_index: usize,
2814 ) -> Result<u8>;
2815 fn tableau_inverse_y_output_pauli(
2816 handle: &TableauHandle,
2817 input_index: usize,
2818 output_index: usize,
2819 ) -> Result<u8>;
2820 fn tableau_inverse_z_output_pauli(
2821 handle: &TableauHandle,
2822 input_index: usize,
2823 output_index: usize,
2824 ) -> Result<u8>;
2825 fn tableau_x_output(handle: &TableauHandle, target: usize) -> UniquePtr<PauliStringHandle>;
2826 fn tableau_y_output(handle: &TableauHandle, target: usize) -> UniquePtr<PauliStringHandle>;
2827 fn tableau_z_output(handle: &TableauHandle, target: usize) -> UniquePtr<PauliStringHandle>;
2828 fn tableau_inverse_x_output(
2829 handle: &TableauHandle,
2830 target: usize,
2831 unsigned_only: bool,
2832 ) -> UniquePtr<PauliStringHandle>;
2833 fn tableau_inverse_y_output(
2834 handle: &TableauHandle,
2835 target: usize,
2836 unsigned_only: bool,
2837 ) -> UniquePtr<PauliStringHandle>;
2838 fn tableau_inverse_z_output(
2839 handle: &TableauHandle,
2840 target: usize,
2841 unsigned_only: bool,
2842 ) -> UniquePtr<PauliStringHandle>;
2843 fn tableau_conjugate_pauli_string(
2844 handle: &TableauHandle,
2845 pauli_string: &PauliStringHandle,
2846 ) -> UniquePtr<PauliStringHandle>;
2847 fn tableau_conjugate_pauli_string_within(
2848 handle: &TableauHandle,
2849 pauli_string: &PauliStringHandle,
2850 targets: &[usize],
2851 inverse: bool,
2852 ) -> Result<UniquePtr<PauliStringHandle>>;
2853 fn tableau_to_stabilizer_texts(handle: &TableauHandle, canonicalize: bool) -> Vec<String>;
2854 fn tableau_to_circuit(
2855 handle: &TableauHandle,
2856 method: &str,
2857 ) -> Result<UniquePtr<CircuitHandle>>;
2858 fn tableau_to_pauli_string(handle: &TableauHandle) -> Result<UniquePtr<PauliStringHandle>>;
2859 fn tableau_simulator_clone(
2860 handle: &TableauSimulatorHandle,
2861 ) -> UniquePtr<TableauSimulatorHandle>;
2862 fn tableau_simulator_num_qubits(handle: &TableauSimulatorHandle) -> usize;
2863 fn tableau_simulator_set_num_qubits(
2864 handle: Pin<&mut TableauSimulatorHandle>,
2865 new_num_qubits: usize,
2866 );
2867 fn tableau_simulator_current_inverse_tableau(
2868 handle: &TableauSimulatorHandle,
2869 ) -> UniquePtr<TableauHandle>;
2870 fn tableau_simulator_set_inverse_tableau(
2871 handle: Pin<&mut TableauSimulatorHandle>,
2872 tableau: &TableauHandle,
2873 );
2874 fn tableau_simulator_current_measurement_record(handle: &TableauSimulatorHandle)
2875 -> Vec<u8>;
2876 fn tableau_simulator_do_circuit(
2877 handle: Pin<&mut TableauSimulatorHandle>,
2878 circuit: &CircuitHandle,
2879 );
2880 fn tableau_simulator_do_pauli_string(
2881 handle: Pin<&mut TableauSimulatorHandle>,
2882 pauli_string: &PauliStringHandle,
2883 );
2884 fn tableau_simulator_do_tableau(
2885 handle: Pin<&mut TableauSimulatorHandle>,
2886 tableau: &TableauHandle,
2887 targets: &[usize],
2888 );
2889 fn tableau_simulator_peek_bloch(
2890 handle: Pin<&mut TableauSimulatorHandle>,
2891 target: usize,
2892 ) -> UniquePtr<PauliStringHandle>;
2893 fn tableau_simulator_peek_x(handle: Pin<&mut TableauSimulatorHandle>, target: usize)
2894 -> i32;
2895 fn tableau_simulator_peek_y(handle: Pin<&mut TableauSimulatorHandle>, target: usize)
2896 -> i32;
2897 fn tableau_simulator_peek_z(handle: Pin<&mut TableauSimulatorHandle>, target: usize)
2898 -> i32;
2899 fn tableau_simulator_measure(
2900 handle: Pin<&mut TableauSimulatorHandle>,
2901 target: usize,
2902 ) -> bool;
2903 fn tableau_simulator_measure_many(
2904 handle: Pin<&mut TableauSimulatorHandle>,
2905 targets: &[usize],
2906 ) -> Vec<u8>;
2907 fn tableau_simulator_peek_observable_expectation(
2908 handle: &TableauSimulatorHandle,
2909 observable: &PauliStringHandle,
2910 ) -> Result<i32>;
2911 fn tableau_simulator_measure_observable(
2912 handle: Pin<&mut TableauSimulatorHandle>,
2913 observable: &PauliStringHandle,
2914 flip_probability: f64,
2915 ) -> Result<bool>;
2916 fn tableau_simulator_postselect_observable(
2917 handle: Pin<&mut TableauSimulatorHandle>,
2918 observable: &PauliStringHandle,
2919 desired_value: bool,
2920 ) -> Result<()>;
2921 fn tableau_simulator_postselect_x(
2922 handle: Pin<&mut TableauSimulatorHandle>,
2923 targets: &[usize],
2924 desired_value: bool,
2925 ) -> Result<()>;
2926 fn tableau_simulator_postselect_y(
2927 handle: Pin<&mut TableauSimulatorHandle>,
2928 targets: &[usize],
2929 desired_value: bool,
2930 ) -> Result<()>;
2931 fn tableau_simulator_postselect_z(
2932 handle: Pin<&mut TableauSimulatorHandle>,
2933 targets: &[usize],
2934 desired_value: bool,
2935 ) -> Result<()>;
2936 fn tableau_simulator_measure_kickback(
2937 handle: Pin<&mut TableauSimulatorHandle>,
2938 target: usize,
2939 ) -> TableauMeasureKickbackData;
2940 fn new_frame_simulator(
2941 batch_size: usize,
2942 disable_stabilizer_randomization: bool,
2943 num_qubits: usize,
2944 seed: u64,
2945 ) -> UniquePtr<FrameSimulatorHandle>;
2946 fn frame_simulator_clone(handle: &FrameSimulatorHandle) -> UniquePtr<FrameSimulatorHandle>;
2947 fn frame_simulator_batch_size(handle: &FrameSimulatorHandle) -> usize;
2948 fn frame_simulator_num_qubits(handle: &FrameSimulatorHandle) -> usize;
2949 fn frame_simulator_num_measurements(handle: &FrameSimulatorHandle) -> usize;
2950 fn frame_simulator_num_detectors(handle: &FrameSimulatorHandle) -> usize;
2951 fn frame_simulator_num_observables(handle: &FrameSimulatorHandle) -> usize;
2952 fn frame_simulator_clear(handle: Pin<&mut FrameSimulatorHandle>);
2953 fn frame_simulator_do_circuit(
2954 handle: Pin<&mut FrameSimulatorHandle>,
2955 circuit: &CircuitHandle,
2956 );
2957 fn frame_simulator_set_pauli_flip(
2958 handle: Pin<&mut FrameSimulatorHandle>,
2959 pauli: u8,
2960 qubit_index: i64,
2961 instance_index: i64,
2962 ) -> Result<()>;
2963 fn frame_simulator_peek_pauli_flips(handle: &FrameSimulatorHandle) -> Vec<String>;
2964 fn frame_simulator_peek_pauli_flip(
2965 handle: &FrameSimulatorHandle,
2966 instance_index: i64,
2967 ) -> Result<String>;
2968 fn frame_simulator_broadcast_pauli_errors(
2969 handle: Pin<&mut FrameSimulatorHandle>,
2970 pauli: u8,
2971 mask: Vec<u8>,
2972 mask_num_qubits: usize,
2973 p: f32,
2974 ) -> Result<()>;
2975 fn frame_simulator_generate_bernoulli_samples(
2976 handle: Pin<&mut FrameSimulatorHandle>,
2977 num_samples: usize,
2978 p: f32,
2979 bit_packed: bool,
2980 ) -> Result<Vec<u8>>;
2981 fn frame_simulator_append_measurement_flips(
2982 handle: Pin<&mut FrameSimulatorHandle>,
2983 data: Vec<u8>,
2984 num_measurements: usize,
2985 bit_packed: bool,
2986 ) -> Result<()>;
2987 fn frame_simulator_get_measurement_flips(
2988 handle: &FrameSimulatorHandle,
2989 bit_packed: bool,
2990 ) -> BitTableData;
2991 fn frame_simulator_get_detector_flips(
2992 handle: &FrameSimulatorHandle,
2993 bit_packed: bool,
2994 ) -> BitTableData;
2995 fn frame_simulator_get_observable_flips(
2996 handle: &FrameSimulatorHandle,
2997 bit_packed: bool,
2998 ) -> BitTableData;
2999 fn clifford_string_clone(handle: &CliffordStringHandle) -> UniquePtr<CliffordStringHandle>;
3000 fn clifford_string_equals(
3001 left: &CliffordStringHandle,
3002 right: &CliffordStringHandle,
3003 ) -> bool;
3004 fn clifford_string_num_qubits(handle: &CliffordStringHandle) -> usize;
3005 fn clifford_string_get_item_name(
3006 handle: &CliffordStringHandle,
3007 index: i64,
3008 ) -> Result<String>;
3009 fn clifford_string_get_slice(
3010 handle: &CliffordStringHandle,
3011 start: i64,
3012 step: i64,
3013 slice_length: i64,
3014 ) -> UniquePtr<CliffordStringHandle>;
3015 fn clifford_string_add(
3016 left: &CliffordStringHandle,
3017 right: &CliffordStringHandle,
3018 ) -> UniquePtr<CliffordStringHandle>;
3019 fn clifford_string_add_assign(
3020 left: Pin<&mut CliffordStringHandle>,
3021 right: &CliffordStringHandle,
3022 );
3023 fn clifford_string_mul(
3024 left: &CliffordStringHandle,
3025 right: &CliffordStringHandle,
3026 ) -> UniquePtr<CliffordStringHandle>;
3027 fn clifford_string_mul_assign(
3028 left: Pin<&mut CliffordStringHandle>,
3029 right: &CliffordStringHandle,
3030 );
3031 fn clifford_string_repeat(
3032 handle: &CliffordStringHandle,
3033 repetitions: u64,
3034 ) -> Result<UniquePtr<CliffordStringHandle>>;
3035 fn clifford_string_repeat_assign(
3036 handle: Pin<&mut CliffordStringHandle>,
3037 repetitions: u64,
3038 ) -> Result<()>;
3039 fn clifford_string_pow(
3040 handle: &CliffordStringHandle,
3041 exponent: i64,
3042 ) -> UniquePtr<CliffordStringHandle>;
3043 fn clifford_string_ipow(handle: Pin<&mut CliffordStringHandle>, exponent: i64);
3044 fn clifford_string_x_outputs(handle: &CliffordStringHandle)
3045 -> UniquePtr<PauliStringHandle>;
3046 fn clifford_string_x_signs_bit_packed(handle: &CliffordStringHandle) -> Vec<u8>;
3047 fn clifford_string_y_outputs(handle: &CliffordStringHandle)
3048 -> UniquePtr<PauliStringHandle>;
3049 fn clifford_string_y_signs_bit_packed(handle: &CliffordStringHandle) -> Vec<u8>;
3050 fn clifford_string_z_outputs(handle: &CliffordStringHandle)
3051 -> UniquePtr<PauliStringHandle>;
3052 fn clifford_string_z_signs_bit_packed(handle: &CliffordStringHandle) -> Vec<u8>;
3053 fn clifford_string_to_string(handle: &CliffordStringHandle) -> String;
3054 fn clifford_string_to_repr(handle: &CliffordStringHandle) -> String;
3055 fn pauli_string_clone(handle: &PauliStringHandle) -> UniquePtr<PauliStringHandle>;
3056 fn pauli_string_equals(left: &PauliStringHandle, right: &PauliStringHandle) -> bool;
3057 fn pauli_string_num_qubits(handle: &PauliStringHandle) -> usize;
3058 fn pauli_string_weight(handle: &PauliStringHandle) -> usize;
3059 fn pauli_string_get_item(handle: &PauliStringHandle, index: i64) -> Result<u8>;
3060 fn pauli_string_set_item(
3061 handle: Pin<&mut PauliStringHandle>,
3062 index: i64,
3063 new_pauli: u8,
3064 ) -> Result<()>;
3065 fn pauli_string_get_slice(
3066 handle: &PauliStringHandle,
3067 start: i64,
3068 step: i64,
3069 slice_length: i64,
3070 ) -> UniquePtr<PauliStringHandle>;
3071 fn pauli_string_random(num_qubits: usize) -> UniquePtr<PauliStringHandle>;
3072 fn pauli_string_iter_all(
3073 num_qubits: usize,
3074 min_weight: usize,
3075 max_weight: usize,
3076 allow_x: bool,
3077 allow_y: bool,
3078 allow_z: bool,
3079 ) -> UniquePtr<PauliStringIteratorHandle>;
3080 fn pauli_string_iterator_clone(
3081 handle: &PauliStringIteratorHandle,
3082 ) -> UniquePtr<PauliStringIteratorHandle>;
3083 fn pauli_string_iterator_next(
3084 handle: Pin<&mut PauliStringIteratorHandle>,
3085 ) -> UniquePtr<PauliStringHandle>;
3086 fn pauli_string_commutes(handle: &PauliStringHandle, other: &PauliStringHandle) -> bool;
3087 fn pauli_string_pauli_indices(
3088 handle: &PauliStringHandle,
3089 included_paulis: &str,
3090 ) -> Result<Vec<u64>>;
3091 fn pauli_string_sign_code(handle: &PauliStringHandle) -> i32;
3092 fn pauli_string_to_tableau(handle: &PauliStringHandle) -> UniquePtr<TableauHandle>;
3093 fn pauli_string_to_string(handle: &PauliStringHandle) -> String;
3094 fn pauli_string_to_repr(handle: &PauliStringHandle) -> String;
3095 fn tableau_num_qubits(handle: &TableauHandle) -> usize;
3096 fn tableau_to_string(handle: &TableauHandle) -> String;
3097 fn tableau_to_repr(handle: &TableauHandle) -> String;
3098 fn tableau_to_unitary_matrix_data(handle: &TableauHandle, endian: &str)
3099 -> Result<Vec<f32>>;
3100 fn tableau_to_state_vector_data(handle: &TableauHandle, endian: &str) -> Result<Vec<f32>>;
3101 fn circuit_compile_sampler(
3102 handle: &CircuitHandle,
3103 skip_reference_sample: bool,
3104 seed: u64,
3105 ) -> UniquePtr<MeasurementSamplerHandle>;
3106 fn measurement_sampler_num_measurements(handle: &MeasurementSamplerHandle) -> u64;
3107 fn measurement_sampler_sample_bit_packed(
3108 handle: Pin<&mut MeasurementSamplerHandle>,
3109 shots: u64,
3110 ) -> Vec<u8>;
3111 fn measurement_sampler_sample_write(
3112 handle: Pin<&mut MeasurementSamplerHandle>,
3113 shots: u64,
3114 filepath: &str,
3115 format_name: &str,
3116 ) -> Result<()>;
3117 fn circuit_compile_detector_sampler(
3118 handle: &CircuitHandle,
3119 seed: u64,
3120 ) -> UniquePtr<DetectorSamplerHandle>;
3121 fn detector_error_model_compile_sampler(
3122 handle: &DetectorErrorModelHandle,
3123 seed: u64,
3124 ) -> UniquePtr<DemSamplerHandle>;
3125 fn detector_sampler_num_detectors(handle: &DetectorSamplerHandle) -> u64;
3126 fn detector_sampler_num_observables(handle: &DetectorSamplerHandle) -> u64;
3127 fn dem_sampler_num_detectors(handle: &DemSamplerHandle) -> u64;
3128 fn dem_sampler_num_observables(handle: &DemSamplerHandle) -> u64;
3129 fn dem_sampler_num_errors(handle: &DemSamplerHandle) -> u64;
3130 fn detector_sampler_sample_bit_packed(
3131 handle: Pin<&mut DetectorSamplerHandle>,
3132 shots: u64,
3133 ) -> Vec<u8>;
3134 fn detector_sampler_sample_observables_bit_packed(
3135 handle: Pin<&mut DetectorSamplerHandle>,
3136 shots: u64,
3137 ) -> Vec<u8>;
3138 fn detector_sampler_sample_bit_packed_separate_observables(
3139 handle: Pin<&mut DetectorSamplerHandle>,
3140 shots: u64,
3141 ) -> DetectorSampleBatch;
3142 fn dem_sampler_sample_bit_packed(
3143 handle: Pin<&mut DemSamplerHandle>,
3144 shots: u64,
3145 ) -> DemSampleBatch;
3146 fn dem_sampler_sample_bit_packed_replay(
3147 handle: Pin<&mut DemSamplerHandle>,
3148 recorded_errors: &[u8],
3149 shots: u64,
3150 ) -> DemSampleBatch;
3151 fn dem_sampler_sample_write(
3152 handle: Pin<&mut DemSamplerHandle>,
3153 shots: u64,
3154 dets_filepath: &str,
3155 dets_format_name: &str,
3156 obs_filepath: &str,
3157 obs_format_name: &str,
3158 err_filepath: &str,
3159 err_format_name: &str,
3160 write_errors: bool,
3161 replay_err_filepath: &str,
3162 replay_err_format_name: &str,
3163 replay_errors: bool,
3164 ) -> Result<()>;
3165 fn detector_sampler_sample_write(
3166 handle: Pin<&mut DetectorSamplerHandle>,
3167 shots: u64,
3168 filepath: &str,
3169 format_name: &str,
3170 ) -> Result<()>;
3171 fn detector_sampler_sample_write_separate_observables(
3172 handle: Pin<&mut DetectorSamplerHandle>,
3173 shots: u64,
3174 dets_filepath: &str,
3175 dets_format_name: &str,
3176 obs_filepath: &str,
3177 obs_format_name: &str,
3178 ) -> Result<()>;
3179 fn circuit_compile_m2d_converter(
3180 handle: &CircuitHandle,
3181 skip_reference_sample: bool,
3182 ) -> UniquePtr<MeasurementsToDetectionEventsConverterHandle>;
3183 fn m2d_converter_num_measurements(
3184 handle: &MeasurementsToDetectionEventsConverterHandle,
3185 ) -> u64;
3186 fn m2d_converter_num_detectors(
3187 handle: &MeasurementsToDetectionEventsConverterHandle,
3188 ) -> u64;
3189 fn m2d_converter_num_observables(
3190 handle: &MeasurementsToDetectionEventsConverterHandle,
3191 ) -> u64;
3192 fn m2d_converter_num_sweep_bits(
3193 handle: &MeasurementsToDetectionEventsConverterHandle,
3194 ) -> u64;
3195 fn m2d_converter_convert_measurements_bit_packed(
3196 handle: Pin<&mut MeasurementsToDetectionEventsConverterHandle>,
3197 measurements: &[u8],
3198 shots: u64,
3199 append_observables: bool,
3200 ) -> Vec<u8>;
3201 fn m2d_converter_convert_measurements_and_sweep_bits_bit_packed(
3202 handle: Pin<&mut MeasurementsToDetectionEventsConverterHandle>,
3203 measurements: &[u8],
3204 sweep_bits: &[u8],
3205 shots: u64,
3206 append_observables: bool,
3207 ) -> Vec<u8>;
3208 fn m2d_converter_convert_observables_with_sweep_bits_bit_packed(
3209 handle: Pin<&mut MeasurementsToDetectionEventsConverterHandle>,
3210 measurements: &[u8],
3211 sweep_bits: &[u8],
3212 shots: u64,
3213 ) -> Vec<u8>;
3214 fn m2d_converter_convert_observables_bit_packed(
3215 handle: Pin<&mut MeasurementsToDetectionEventsConverterHandle>,
3216 measurements: &[u8],
3217 shots: u64,
3218 ) -> Vec<u8>;
3219 fn m2d_converter_convert_file(
3220 handle: Pin<&mut MeasurementsToDetectionEventsConverterHandle>,
3221 measurements_filepath: &str,
3222 measurements_format: &str,
3223 sweep_bits_filepath: &str,
3224 sweep_bits_format: &str,
3225 detection_events_filepath: &str,
3226 detection_events_format: &str,
3227 append_observables: bool,
3228 obs_out_filepath: &str,
3229 obs_out_format: &str,
3230 ) -> Result<()>;
3231
3232 fn new_smoke_probe() -> UniquePtr<SmokeProbe>;
3233 fn describe(self: &SmokeProbe) -> String;
3234 fn weighted_checksum(self: &SmokeProbe, values: &[u64]) -> u64;
3235 }
3236}