1use std::collections::{HashMap, HashSet};
4use std::num::NonZeroUsize;
5use std::sync::Arc;
6
7use glam::IVec3;
8use rustc_hash::{FxHashMap, FxHashSet};
9
10use crate::program::{projection_limit, qualified_name, resource_limit};
11use crate::zx::{
12 EliminationRow, FlowWitness, ModuleSeam, ProjectionLimits, ZXGraph,
13 leading_pivot_elimination_from, signed_gaussian_elimination, signed_gaussian_elimination_from,
14 xor_pauli_maps,
15};
16use crate::{
17 Action, Basis, Block, BlockGraph, BlockKind, Direction, InstancePort, MeasurementObservable,
18 ModuleCertificationError, ModuleCertificationLimits, ModuleError, ModuleInstance,
19 ModuleOrientation, Pauli, PauliBasis, PauliString, PhasedPauliString, Pipe, QuantumConnection,
20 QuantumPort, Stabilizer, StabilizerGenerators, StabilizerRowKind, UDirection,
21 checked_add_position,
22};
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26pub(crate) struct ModulePortSignature {
27 pub direction: Direction,
29 pub hadamard: bool,
31 pub interior_bases: [Option<Basis>; 3],
33}
34
35impl ModulePortSignature {
36 pub(crate) fn with_orientation(self, orientation: ModuleOrientation) -> Self {
38 Self {
39 direction: orientation.rotate_direction(self.direction),
40 hadamard: self.hadamard,
41 interior_bases: orientation.rotate_axis_values(self.interior_bases),
42 }
43 }
44}
45
46#[derive(Debug, Clone)]
48pub struct ModuleSummary {
49 name: String,
50 limits: ModuleCertificationLimits,
51 dependencies: HashMap<String, Arc<ModuleSummary>>,
52 ports: Vec<QuantumPort>,
53 signatures: Vec<ModulePortSignature>,
54 rows: Vec<SupportedRow>,
55 logical_rows: Vec<SupportedRow>,
59 certificate_rows: Vec<SupportedRow>,
63 adjustments: Vec<SupportedRow>,
64 measurements: Vec<SummaryMeasurement>,
65 discharged_measurements: Vec<SummaryMeasurement>,
66 protected: Vec<ProtectedSupport>,
67 frontier: Vec<SupportTarget>,
68 protected_groups: Vec<ProtectedGroup>,
69 branch_variants: Vec<ModuleBranchVariant>,
70 projection: Option<Box<ModuleProjection>>,
71}
72
73#[derive(Debug, Clone)]
76struct ModuleProjection {
77 definition: BlockGraph,
78 targets: Vec<IVec3>,
79 limits: ModuleCertificationLimits,
80}
81
82#[derive(Debug, Clone)]
83struct ModuleBranchVariant {
84 assignments: Vec<(IVec3, bool)>,
85 summary: Box<ModuleSummary>,
86}
87
88impl ModuleSummary {
89 pub fn name(&self) -> &str {
91 &self.name
92 }
93
94 #[doc(hidden)]
96 pub fn definition(&self, name: &str) -> Option<&ModuleSummary> {
97 let mut pending = vec![self];
98 let mut seen = FxHashSet::default();
99 while let Some(summary) = pending.pop() {
100 if summary.name == name {
101 return Some(summary);
102 }
103 if seen.insert(summary.name.as_str()) {
104 pending.extend(summary.dependencies.values().map(Arc::as_ref));
105 }
106 }
107 None
108 }
109
110 pub fn quantum_ports(&self) -> &[QuantumPort] {
112 &self.ports
113 }
114
115 pub fn boundary_rows(&self) -> impl ExactSizeIterator<Item = &PhasedPauliString> {
117 self.rows.iter().map(|row| &row.signed)
118 }
119
120 #[doc(hidden)]
124 pub fn materialize_stabilizers(
125 &self,
126 zx: &ZXGraph,
127 offset: IVec3,
128 ) -> Result<StabilizerGenerators, ModuleCertificationError> {
129 self.materialize_stabilizers_from(zx, ModuleOrientation::IDENTITY, offset)
130 }
131
132 #[doc(hidden)]
136 pub fn materialize_projection_stabilizers(
137 &self,
138 zx: &ZXGraph,
139 offset: IVec3,
140 assignments: &[(IVec3, bool)],
141 ) -> Result<StabilizerGenerators, ModuleCertificationError> {
142 let mut key = assignments
143 .iter()
144 .filter(|(_, value)| !value)
145 .map(|&(position, value)| {
146 checked_add_position(position, -offset)
147 .map(|position| (position, value))
148 .map_err(|source| ModuleCertificationError::Graph {
149 module: self.name.clone(),
150 source,
151 })
152 })
153 .collect::<Result<Vec<_>, _>>()?;
154 key.sort_unstable_by_key(|(position, value)| (position.to_array(), *value));
155 if key.is_empty() {
156 return self.materialize_stabilizers_from(zx, ModuleOrientation::IDENTITY, offset);
157 }
158 if self.projection.is_some() {
159 let absent = key.iter().map(|&(position, _)| position).collect();
160 return self
161 .select_projection(&absent)?
162 .materialize_stabilizers_from(zx, ModuleOrientation::IDENTITY, offset);
163 }
164 let variant = self
165 .branch_variants
166 .iter()
167 .find(|variant| variant.assignments == key)
168 .ok_or_else(|| {
169 invalid(
170 &self.name,
171 "reachable structural projection has no composed module certificate",
172 )
173 })?;
174 variant
175 .summary
176 .materialize_stabilizers_from(zx, ModuleOrientation::IDENTITY, offset)
177 }
178
179 fn select_projection(
180 &self,
181 absent: &FxHashSet<IVec3>,
182 ) -> Result<ModuleSummary, ModuleCertificationError> {
183 let Some(projection) = &self.projection else {
184 return Ok(self.clone());
185 };
186 if absent
187 .iter()
188 .any(|target| !projection.targets.contains(target))
189 {
190 return Err(invalid(&self.name, "projection selects an unknown branch"));
191 }
192 let module = &projection.definition;
193 let graph_error = |source| ModuleCertificationError::Graph {
194 module: module.name.clone(),
195 source,
196 };
197 let mut selected = module.clone_local_definition();
198 selected.replace_local_body(
199 module
200 .local_body()
201 .project_branches_in_definition(
202 module
203 .local_body()
204 .branch_regions()
205 .map_err(graph_error)?
206 .iter()
207 .map(|region| (region.target, !absent.contains(®ion.target))),
208 )
209 .map_err(graph_error)?,
210 );
211 if module.instances.is_empty() {
212 return summarize_leaf_body(module, selected.local_body(), projection.limits);
213 }
214 let children = module
215 .instances
216 .iter()
217 .map(|instance| {
218 let base = &self.dependencies[&instance.definition];
219 let mut key = FxHashSet::default();
220 if let Some(child) = &base.projection {
221 for &target in &child.targets {
222 if absent.contains(
223 &instance
224 .try_transform_position(target)
225 .map_err(graph_error)?,
226 ) {
227 key.insert(target);
228 }
229 }
230 }
231 let child = if key.is_empty() {
232 Arc::clone(base)
233 } else {
234 Arc::new(base.select_projection(&key)?)
235 };
236 Ok((instance.name.as_str(), (instance, child)))
237 })
238 .collect::<Result<HashMap<_, _>, ModuleCertificationError>>()?;
239 summarize_composite(&selected, module, &children, projection.limits)
240 }
241
242 fn materialize_stabilizers_from(
243 &self,
244 zx: &ZXGraph,
245 orientation: ModuleOrientation,
246 offset: IVec3,
247 ) -> Result<StabilizerGenerators, ModuleCertificationError> {
248 let words = [
250 self.certificate_rows.len(),
251 self.measurements.len(),
252 self.discharged_measurements.len(),
253 self.logical_rows.len(),
254 self.adjustments.len(),
255 ]
256 .into_iter()
257 .try_fold(0usize, usize::checked_add)
258 .and_then(|rows| rows.checked_mul(zx.total_ids().div_ceil(512)))
259 .and_then(|blocks| blocks.checked_mul(16));
260 if words.is_none_or(|words| words > self.limits.max_matrix_words) {
261 return Err(resource_limit(
262 &self.name,
263 "dense matrix words",
264 words.unwrap_or(usize::MAX),
265 self.limits.max_matrix_words,
266 ));
267 }
268 let external_basis = self
269 .certificate_rows
270 .iter()
271 .map(|row| {
272 let stabilizer = materialize_summary_row(
273 &row.signed,
274 &row.support,
275 &self.ports,
276 zx,
277 orientation,
278 offset,
279 &self.name,
280 )?;
281 let mut paulis = stabilizer.paulis;
282 zx.clear_cross_centers(std::slice::from_mut(&mut paulis));
283 let witness = row
284 .witness
285 .transformed(orientation, offset)
286 .map_err(|source| ModuleCertificationError::Graph {
287 module: self.name.clone(),
288 source,
289 })?;
290 let witnessed =
291 zx.materialize_flow_witness(&witness, &paulis)
292 .ok_or_else(|| {
293 invalid(
294 &self.name,
295 "composed certificate witness does not fit the linked graph",
296 )
297 })?;
298 if witnessed.paulis != paulis {
299 return Err(invalid(
300 &self.name,
301 "composed certificate witness does not reproduce its positioned support",
302 ));
303 }
304 Ok(PhasedPauliString::new(paulis, witnessed.phase()))
305 })
306 .collect::<Result<Vec<_>, ModuleCertificationError>>()?;
307 let cached_prefix = self
308 .measurements
309 .iter()
310 .chain(&self.discharged_measurements)
311 .map(|row| {
312 materialize_summary_row(
313 &row.signed,
314 &row.support,
315 &self.ports,
316 zx,
317 orientation,
318 offset,
319 &self.name,
320 )
321 .and_then(|stabilizer| {
322 Ok((
323 transformed_row_kind(&row.kind, orientation, offset, &self.name)?,
324 stabilizer.paulis,
325 ))
326 })
327 })
328 .chain(self.logical_rows.iter().map(|row| {
329 materialize_summary_row(
330 &row.signed,
331 &row.support,
332 &self.ports,
333 zx,
334 orientation,
335 offset,
336 &self.name,
337 )
338 .map(|stabilizer| (StabilizerRowKind::Logical, stabilizer.paulis))
339 }))
340 .collect::<Result<Vec<_>, ModuleCertificationError>>()?;
341 let adjustment_basis = self
342 .adjustments
343 .iter()
344 .map(|row| {
345 let stabilizer = materialize_summary_row(
346 &row.signed,
347 &row.support,
348 &self.ports,
349 zx,
350 orientation,
351 offset,
352 &self.name,
353 )?;
354 let mut paulis = stabilizer.paulis;
355 zx.clear_cross_centers(std::slice::from_mut(&mut paulis));
356 Ok(paulis)
357 })
358 .collect::<Result<Vec<_>, ModuleCertificationError>>()?;
359 zx.stabilizers_from_composed_basis(
360 &external_basis,
361 &adjustment_basis,
362 &cached_prefix,
363 self.limits,
364 )
365 .map_err(crate::RuntimeBasisError::from)
366 .and_then(|stabilizers| {
367 stabilizers.validate_measurements_close_before_outputs_with_limits(self.limits)?;
371 Ok(stabilizers)
372 })
373 .map_err(|source| match source {
374 crate::RuntimeBasisError::Stabilizer(crate::StabilizerError::ResourceLimited {
375 phase,
376 observed,
377 limit,
378 }) => resource_limit(&self.name, phase, observed, limit),
379 source => ModuleCertificationError::Runtime {
380 module: self.name.clone(),
381 source,
382 },
383 })
384 }
385
386 fn port_index(&self, name: &str) -> Option<usize> {
387 self.ports.iter().position(|port| port.name == name)
388 }
389}
390
391fn transformed_row_kind(
392 kind: &StabilizerRowKind,
393 orientation: ModuleOrientation,
394 translation: IVec3,
395 module: &str,
396) -> Result<StabilizerRowKind, ModuleCertificationError> {
397 let mut kind = kind.clone();
398 if let StabilizerRowKind::SelectiveFixing { targets } = &mut kind {
399 for target in targets {
400 target.pos = orientation
401 .try_transform_position(target.pos, translation)
402 .map_err(|source| ModuleCertificationError::Graph {
403 module: module.to_string(),
404 source,
405 })?;
406 }
407 }
408 Ok(kind)
409}
410
411fn materialize_summary_row(
412 signed: &PhasedPauliString,
413 support: &PositionedSupport,
414 ports: &[QuantumPort],
415 zx: &ZXGraph,
416 orientation: ModuleOrientation,
417 translation: IVec3,
418 module: &str,
419) -> Result<Stabilizer, ModuleCertificationError> {
420 let mut support = support
421 .transformed(orientation, translation)
422 .map_err(|source| ModuleCertificationError::Graph {
423 module: module.to_string(),
424 source,
425 })?;
426 for (column, port) in ports.iter().enumerate() {
427 let pauli = signed.paulis.get(column);
428 if pauli == Pauli::I {
429 continue;
430 }
431 let position = orientation
432 .try_transform_position(port.position, translation)
433 .map_err(|source| ModuleCertificationError::Graph {
434 module: module.to_string(),
435 source,
436 })?;
437 if let Some(existing) = support.nodes.insert(position, pauli)
438 && existing != pauli
439 {
440 return Err(invalid(
441 module,
442 &format!(
443 "certificate support repeats public Port {position}: interior {existing}, boundary {pauli}"
444 ),
445 ));
446 }
447 }
448 support.materialize(zx, signed.phase()).ok_or_else(|| {
449 invalid(
450 module,
451 "composed certificate support does not fit the linked graph",
452 )
453 })
454}
455
456#[derive(Clone)]
457struct BindSeam {
458 endpoint: InstancePort,
459 block: IVec3,
460 signature: ModulePortSignature,
461 hadamard: bool,
462 transpose: bool,
463}
464
465#[derive(Default)]
466struct ChildRelation {
467 parent_ports: Vec<usize>,
469 endpoints: Vec<InstancePort>,
470 rows: Vec<SupportedRow>,
471 logical_rows: Vec<SupportedRow>,
472 certificate_rows: Vec<SupportedRow>,
473 adjustments: Vec<SupportedRow>,
474 measurements: Vec<SummaryMeasurement>,
475 discharged_measurements: Vec<SummaryMeasurement>,
476 protected: Vec<ProtectedSupport>,
477 frontier: Vec<SupportTarget>,
478 protected_groups: Vec<ProtectedGroup>,
479}
480
481impl ChildRelation {
482 fn width(&self) -> usize {
483 self.parent_ports.len() + self.endpoints.len()
484 }
485
486 fn append(&mut self, other: Self, mapping: &[usize], width: usize) {
487 for (target, rows) in [
488 (&mut self.rows, other.rows),
489 (&mut self.logical_rows, other.logical_rows),
490 (&mut self.certificate_rows, other.certificate_rows),
491 (&mut self.adjustments, other.adjustments),
492 ] {
493 target.extend(rows.into_iter().map(|mut row| {
494 row.signed = embed_signed_row(&row.signed, mapping, width);
495 row
496 }));
497 }
498 for (target, rows) in [
499 (&mut self.measurements, other.measurements),
500 (
501 &mut self.discharged_measurements,
502 other.discharged_measurements,
503 ),
504 ] {
505 target.extend(rows.into_iter().map(|mut row| {
506 row.signed = embed_signed_row(&row.signed, mapping, width);
507 row
508 }));
509 }
510 self.parent_ports.extend(other.parent_ports);
511 self.endpoints.extend(other.endpoints);
512 self.protected.extend(other.protected);
513 self.frontier.extend(other.frontier);
514 self.protected_groups.extend(other.protected_groups);
515 }
516
517 fn retire_completed(
518 &mut self,
519 completed: &mut Self,
520 obligations: &FxHashSet<SupportTarget>,
521 module: &str,
522 ) -> Result<(), ModuleCertificationError> {
523 completed.certificate_rows.extend(
526 self.certificate_rows
527 .extract_if(.., |row| row.signed.paulis.is_identity())
528 .map(|mut row| {
529 row.signed.paulis = PauliString::new(0);
530 row
531 }),
532 );
533 completed.adjustments.extend(
536 self.adjustments
537 .extract_if(.., |row| {
538 row.signed.paulis.is_identity()
539 && !row
540 .support
541 .nodes
542 .keys()
543 .any(|&position| obligations.contains(&SupportTarget::Node(position)))
544 && !row.support.edges.keys().any(|&(left, right)| {
545 obligations.contains(&SupportTarget::Edge(left, right))
546 || obligations.contains(&SupportTarget::Edge(right, left))
547 })
548 })
549 .map(|mut row| {
550 row.signed.paulis = PauliString::new(0);
551 row
552 }),
553 );
554 resize_discharged_boundaries(&mut self.discharged_measurements, 0, module)?;
555 completed
556 .discharged_measurements
557 .append(&mut self.discharged_measurements);
558 Ok(())
559 }
560}
561
562#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
563enum SupportTarget {
564 Node(IVec3),
565 Edge(IVec3, IVec3),
566}
567
568fn support_target_key(target: &SupportTarget) -> (u8, [i32; 3], [i32; 3]) {
569 match target {
570 SupportTarget::Node(position) => (0, position.to_array(), [0; 3]),
571 SupportTarget::Edge(left, right) => (1, left.to_array(), right.to_array()),
572 }
573}
574
575#[derive(Debug, Clone, Copy)]
576struct ProtectedSupport {
577 target: SupportTarget,
578 forbidden: Option<Pauli>,
579}
580
581#[derive(Debug, Clone)]
582struct ProtectedGroup {
583 targets: Vec<SupportTarget>,
584 permitted_support: Vec<Vec<Pauli>>,
585}
586
587impl ProtectedGroup {
588 fn transformed(
589 self,
590 orientation: ModuleOrientation,
591 translation: IVec3,
592 ) -> Result<Self, crate::BlockGraphError> {
593 Ok(Self {
594 targets: self
595 .targets
596 .into_iter()
597 .map(|target| target.transformed(orientation, translation))
598 .collect::<Result<_, _>>()?,
599 permitted_support: self.permitted_support,
600 })
601 }
602}
603
604fn semantic_protected_supports(module: &BlockGraph, body: &BlockGraph) -> Vec<ProtectedSupport> {
605 let mut protected = HashMap::<SupportTarget, Option<Pauli>>::new();
606 let mut insert = |target, forbidden| {
607 protected
608 .entry(target)
609 .and_modify(|current| {
610 if current.is_none() {
611 *current = forbidden;
612 }
613 })
614 .or_insert(forbidden);
615 };
616 for block in body.blocks() {
617 if let BlockKind::Selective(kind) = block.kind() {
618 let forbidden = match kind {
619 crate::SelectiveKind::XY => Pauli::Z,
620 crate::SelectiveKind::XZ => Pauli::Y,
621 crate::SelectiveKind::YZ => Pauli::X,
622 };
623 insert(SupportTarget::Node(block.pos()), Some(forbidden));
624 }
625 }
626 for region in module.local_body().branch_definitions() {
627 insert(SupportTarget::Node(region.target), None);
628 for cut in region
629 .incoming_for(false)
630 .iter()
631 .chain(region.incoming_for(true))
632 {
633 insert(SupportTarget::Edge(cut.past, cut.inside), None);
634 }
635 }
636 let mut protected = protected
637 .into_iter()
638 .map(|(target, forbidden)| ProtectedSupport { target, forbidden })
639 .collect::<Vec<_>>();
640 protected.sort_unstable_by_key(|constraint| support_target_key(&constraint.target));
641 protected
642}
643
644fn semantic_frontier_supports(
647 module: &BlockGraph,
648 body: &BlockGraph,
649) -> Result<Vec<SupportTarget>, ModuleCertificationError> {
650 let mut frontier = body
651 .blocks()
652 .filter(|block| block.kind().is_t())
653 .map(|block| SupportTarget::Node(block.pos()))
654 .collect::<FxHashSet<_>>();
655 for action in body.actions() {
656 match action {
657 Action::Measure { target, .. } => {
658 let target = match target {
659 crate::MeasureTarget::Node(position) => SupportTarget::Node(position),
660 crate::MeasureTarget::Edge { src, dir } => SupportTarget::Edge(
661 src,
662 checked_add_position(src, dir.to_ivec3()).map_err(|source| {
663 ModuleCertificationError::Graph {
664 module: module.name.clone(),
665 source,
666 }
667 })?,
668 ),
669 };
670 frontier.insert(target);
671 }
672 Action::Resolve { target, .. } | Action::Branch { target, .. } => {
673 frontier.insert(SupportTarget::Node(target));
674 }
675 Action::Feedback { targets, .. } => {
676 for target in targets {
677 frontier.insert(match target.direction {
678 Some(dir) => SupportTarget::Edge(
679 target.target,
680 checked_add_position(target.target, dir.to_ivec3()).map_err(
681 |source| ModuleCertificationError::Graph {
682 module: module.name.clone(),
683 source,
684 },
685 )?,
686 ),
687 None => SupportTarget::Node(target.target),
688 });
689 }
690 }
691 Action::Let { .. } | Action::DiscardIf(_) => {}
692 }
693 }
694 for region in module.local_body().branch_definitions() {
695 frontier.insert(SupportTarget::Node(region.target));
696 frontier.extend(
697 region
698 .incoming_for(false)
699 .iter()
700 .chain(region.incoming_for(true))
701 .map(|cut| SupportTarget::Edge(cut.past, cut.inside)),
702 );
703 }
704 let mut frontier = frontier.into_iter().collect::<Vec<_>>();
705 frontier.sort_unstable_by_key(support_target_key);
706 Ok(frontier)
707}
708
709fn semantic_protected_groups(
710 body: &BlockGraph,
711 measurements: &[SummaryMeasurement],
712 zx: &ZXGraph,
713 limits: ModuleCertificationLimits,
714 module: &str,
715) -> Result<Vec<ProtectedGroup>, ModuleCertificationError> {
716 measurements
717 .iter()
718 .filter_map(|measurement| {
719 let targets = measurement.kind.selective_fixing_targets();
720 (targets.len() > 1).then_some(targets)
721 })
722 .map(|targets| {
723 let positions = targets.iter().map(|target| target.pos).collect::<Vec<_>>();
724 let kinds = positions
725 .iter()
726 .map(|&position| {
727 let Some(BlockKind::Selective(kind)) =
728 body.get_block(position).map(Block::kind)
729 else {
730 return Err(invalid(module, "selective fixing target is not selective"));
731 };
732 Ok(kind)
733 })
734 .collect::<Result<Vec<_>, ModuleCertificationError>>()?;
735 let domain = zx
736 .action_graph()
737 .resolve_value_domain_bounded_with_limits(
738 &positions,
739 limits.max_guarded_domain_size,
740 limits.boolean_limits(),
741 )
742 .map_err(|error| {
743 match error
744 .into_stabilizer("selective value domain", limits.max_guarded_domain_size)
745 {
746 crate::StabilizerError::ResourceLimited {
747 phase,
748 observed,
749 limit,
750 } => resource_limit(module, phase, observed, limit),
751 source => ModuleCertificationError::Graph {
752 module: module.to_string(),
753 source: source.into(),
754 },
755 }
756 })?;
757 let mut permitted_support = domain
758 .values()
759 .iter()
760 .map(|values| {
761 kinds
762 .iter()
763 .zip(values)
764 .map(|(kind, &value)| {
765 Pauli::from(if value {
766 kind.pauli_if_true()
767 } else {
768 kind.pauli_if_false()
769 })
770 })
771 .collect::<Vec<_>>()
772 })
773 .collect::<Vec<_>>();
774 let reachable = permitted_support.iter().cloned().collect::<FxHashSet<_>>();
775 permitted_support.retain(|support| {
776 reachable.contains(
777 &support
778 .iter()
779 .zip(targets)
780 .map(|(&pauli, target)| pauli ^ target.forbidden)
781 .collect::<Vec<_>>(),
782 )
783 });
784 Ok(ProtectedGroup {
785 targets: positions.into_iter().map(SupportTarget::Node).collect(),
786 permitted_support,
787 })
788 })
789 .collect()
790}
791
792#[derive(Clone, Copy, PartialEq, Eq, Hash)]
793enum SupportConstraint {
794 Boundary(usize, Pauli),
795 Target(SupportTarget, Pauli),
796}
797
798#[derive(Debug, Clone)]
799struct SupportedRow {
800 signed: PhasedPauliString,
801 support: PositionedSupport,
802 witness: FlowWitness,
803}
804
805#[derive(Debug, Clone)]
806struct SummaryMeasurement {
807 name: String,
808 kind: StabilizerRowKind,
809 signed: PhasedPauliString,
810 support: PositionedSupport,
811 witness: FlowWitness,
812 target: SupportTarget,
813 observable: Pauli,
814 self_readers: Vec<SupportTarget>,
815 owned_positions: FxHashSet<IVec3>,
816}
817
818#[derive(Debug, Clone, Default)]
822struct PositionedSupport {
823 nodes: FxHashMap<IVec3, Pauli>,
824 edges: FxHashMap<(IVec3, IVec3), Pauli>,
826}
827
828#[derive(Clone, Copy)]
829struct SupportSeam {
830 edge: (IVec3, IVec3),
831 boundary_to_edge_hadamard: bool,
832}
833
834impl PositionedSupport {
835 fn from_stabilizer(stabilizer: &Stabilizer, zx: &ZXGraph) -> Self {
836 let mut raw = stabilizer.paulis.clone();
839 zx.clear_cross_centers(std::slice::from_mut(&mut raw));
840 Self {
841 nodes: stabilizer
842 .interior_nodes
843 .iter()
844 .filter(|(position, _)| !stabilizer.port_stabilizer.contains_key(position))
845 .filter_map(|(&p, _)| {
846 let pauli = raw.get(zx.node_at(p).expect("surface node exists").id);
847 (pauli != Pauli::I).then_some((p, pauli))
848 })
849 .collect(),
850 edges: stabilizer
851 .interior_edges
852 .iter()
853 .map(|(&edge, &pauli)| (edge, pauli))
854 .collect(),
855 }
856 }
857
858 fn multiply_assign(&mut self, other: &Self) {
859 debug_assert!(
860 self.edges.keys().all(|&(left, right)| {
861 !other.edges.contains_key(&(right, left)) || left == right
862 }),
863 "positioned support edge orientation mismatch"
864 );
865 xor_pauli_maps(&mut self.nodes, &other.nodes);
866 xor_pauli_maps(&mut self.edges, &other.edges);
867 }
868
869 fn get(&self, target: SupportTarget) -> Pauli {
870 match target {
871 SupportTarget::Node(position) => self.nodes.get(&position).copied().unwrap_or(Pauli::I),
872 SupportTarget::Edge(left, right) => self
873 .edges
874 .get(&(left, right))
875 .or_else(|| self.edges.get(&(right, left)))
876 .copied()
877 .unwrap_or(Pauli::I),
878 }
879 }
880
881 fn weight(&self) -> usize {
882 self.nodes.len() + self.edges.len()
883 }
884
885 fn strip_ports(&mut self, ports: &FxHashSet<IVec3>, retained: &[SupportTarget]) {
886 self.nodes.retain(|position, _| !ports.contains(position));
887 self.edges.retain(|&(left, right), _| {
888 (!ports.contains(&left) && !ports.contains(&right))
889 || retained.contains(&SupportTarget::Edge(left, right))
890 || retained.contains(&SupportTarget::Edge(right, left))
891 });
892 }
893
894 fn transformed(
895 &self,
896 orientation: ModuleOrientation,
897 translation: IVec3,
898 ) -> Result<Self, crate::BlockGraphError> {
899 let transform = |position| orientation.try_transform_position(position, translation);
900 Ok(Self {
901 nodes: self
902 .nodes
903 .iter()
904 .map(|(&position, &pauli)| Ok((transform(position)?, pauli)))
905 .collect::<Result<_, crate::BlockGraphError>>()?,
906 edges: self
907 .edges
908 .iter()
909 .map(|(&(left, right), &pauli)| Ok(((transform(left)?, transform(right)?), pauli)))
910 .collect::<Result<_, crate::BlockGraphError>>()?,
911 })
912 }
913
914 fn add_seam(&mut self, seam: SupportSeam, mut pauli: Pauli) -> u8 {
915 if pauli == Pauli::I {
916 return 0;
917 }
918 let phase = 2 * u8::from(seam.boundary_to_edge_hadamard && pauli == Pauli::Y);
919 if seam.boundary_to_edge_hadamard {
920 pauli = pauli.flip();
921 }
922 self.edges.remove(&(seam.edge.1, seam.edge.0));
923 self.edges.insert(seam.edge, pauli);
924 phase
925 }
926
927 fn materialize(&self, zx: &ZXGraph, mut phase: u8) -> Option<Stabilizer> {
928 let mut row = PauliString::new(zx.total_ids());
929 for (&position, &pauli) in &self.nodes {
930 row.set(zx.node_at(position)?.id, pauli);
931 }
932 for (&(source, target), &pauli_at_source) in &self.edges {
933 let source_id = zx.node_at(source)?.id;
934 let target_id = zx.node_at(target)?.id;
935 let forward = zx.edge_id(source_id, target_id)?;
936 let reverse = zx.edge_id(target_id, source_id)?;
937 let edge = &zx.edges()[forward - zx.nodes().len()];
938 let mut stored = pauli_at_source;
939 if source_id > target_id && edge.hadamard {
940 if stored == Pauli::Y {
941 phase = (phase + 2) % 4;
942 }
943 stored = stored.flip();
944 }
945 row.set(forward, stored);
946 row.set(reverse, stored);
947 }
948 for node in zx
953 .nodes()
954 .iter()
955 .filter(|node| matches!(node.kind, crate::NodeKind::X | crate::NodeKind::Z))
956 {
957 let Some(neighbors) = zx
958 .neighbors(node.id)
959 .filter(|neighbors| !neighbors.is_empty())
960 else {
961 continue;
962 };
963 let native = node.kind.cross_pauli().flip();
964 let broadcast = neighbors.iter().all(|&neighbor| {
965 let edge = zx.edge_between(node.id, neighbor).expect("incident edge");
966 let axis = if edge.hadamard && node.id > neighbor {
967 native.flip()
968 } else {
969 native
970 };
971 row.get(edge.id) & axis
972 });
973 let current = row.get(node.id);
974 if (current & native) != broadcast {
975 row.set(node.id, current ^ native);
976 }
977 }
978 zx.reconstruct_cross_center(std::slice::from_mut(&mut row));
979 Some(zx.pauli_string_to_stabilizer_with_row_phase(row, phase))
980 }
981}
982
983impl SupportTarget {
984 fn transformed(
985 self,
986 orientation: ModuleOrientation,
987 translation: IVec3,
988 ) -> Result<Self, crate::BlockGraphError> {
989 let transform = |position| orientation.try_transform_position(position, translation);
990 Ok(match self {
991 Self::Node(position) => Self::Node(transform(position)?),
992 Self::Edge(left, right) => Self::Edge(transform(left)?, transform(right)?),
993 })
994 }
995}
996
997impl ProtectedSupport {
998 fn transformed(
999 self,
1000 orientation: ModuleOrientation,
1001 translation: IVec3,
1002 ) -> Result<Self, crate::BlockGraphError> {
1003 Ok(Self {
1004 target: self.target.transformed(orientation, translation)?,
1005 forbidden: self.forbidden,
1006 })
1007 }
1008}
1009
1010fn stabilizer_phase(stabilizer: &Stabilizer) -> u8 {
1011 let yy = stabilizer
1012 .interior_edges
1013 .values()
1014 .filter(|&&pauli| pauli == Pauli::Y)
1015 .count()
1016 % 2
1017 == 1;
1018 2 * u8::from(stabilizer.sign ^ yy)
1019}
1020
1021#[derive(Clone)]
1022struct ModuleGeometry {
1023 ports: Vec<QuantumPort>,
1024 signatures: Vec<ModulePortSignature>,
1025}
1026
1027#[derive(Clone, Copy)]
1028struct PortGeometry<'a> {
1029 instance: &'a ModuleInstance,
1030 port: &'a QuantumPort,
1031 signature: ModulePortSignature,
1032}
1033
1034impl BlockGraph {
1035 pub fn summarize_root(
1042 &self,
1043 limits: ModuleCertificationLimits,
1044 ) -> Result<Arc<ModuleSummary>, ModuleCertificationError> {
1045 self.summarize_root_with_jobs(limits, default_module_jobs())
1046 }
1047
1048 pub fn summarize_root_with_jobs(
1057 &self,
1058 limits: ModuleCertificationLimits,
1059 jobs: NonZeroUsize,
1060 ) -> Result<Arc<ModuleSummary>, ModuleCertificationError> {
1061 if !self.has_module_structure() {
1062 let source = self
1063 .clone_local_definition()
1064 .with_inferred_interface()
1065 .map_err(|error| ModuleCertificationError::Graph {
1066 module: self.name.clone(),
1067 source: crate::BlockGraphError::ModuleSource(Arc::new(error)),
1068 })?;
1069 return source.summarize_root_with_jobs(limits, jobs);
1070 }
1071 self.validate_with_limits(limits)
1072 .map_err(|error| ModuleCertificationError::Graph {
1073 module: self.name.clone(),
1074 source: crate::BlockGraphError::ModuleSource(Arc::new(error)),
1075 })?;
1076 summarize_program(self, limits, jobs)
1077 }
1078
1079 pub fn direct_pipe_endpoints(&self, module: &str) -> Option<Vec<(IVec3, IVec3)>> {
1085 let definition = self.module(module)?;
1086 let mut memo = HashMap::new();
1087 module_geometry(self, module, &mut memo).expect("validated module geometry remains valid");
1088 Some(direct_pipe_endpoints(definition, &memo))
1089 }
1090
1091 pub fn direct_pipe_endpoints_by_module(&self) -> HashMap<String, Vec<(IVec3, IVec3)>> {
1097 let mut memo = HashMap::new();
1098 for module in self.modules() {
1099 module_geometry(self, &module.name, &mut memo)
1100 .expect("validated module geometry remains valid");
1101 }
1102 self.modules()
1103 .map(|module| (module.name.clone(), direct_pipe_endpoints(module, &memo)))
1104 .collect()
1105 }
1106}
1107
1108fn direct_pipe_endpoints(
1109 definition: &BlockGraph,
1110 geometry: &HashMap<String, ModuleGeometry>,
1111) -> Vec<(IVec3, IVec3)> {
1112 let children = definition
1113 .instances
1114 .iter()
1115 .map(|instance| {
1116 (
1117 instance.name.as_str(),
1118 (instance, geometry[&instance.definition].clone()),
1119 )
1120 })
1121 .collect::<HashMap<_, _>>();
1122 let position = |endpoint| {
1123 let port = validated_port(&children, endpoint);
1124 exposed_position(port.instance, port.port, port.signature)
1125 .expect("validated direct endpoint position fits")
1126 };
1127 definition
1128 .quantum_connections
1129 .iter()
1130 .filter_map(|connection| match connection {
1131 QuantumConnection::Pipe { output, input, .. } => {
1132 Some((position(output), position(input)))
1133 }
1134 _ => None,
1135 })
1136 .collect()
1137}
1138
1139impl BlockGraph {
1140 pub fn validate_resource_limits(
1146 &self,
1147 limits: ModuleCertificationLimits,
1148 ) -> Result<(), crate::BlockGraphError> {
1149 if self.has_module_structure() {
1150 return self
1151 .validate_hierarchy_resource_limits(limits)
1152 .map_err(|error| crate::BlockGraphError::ModuleSource(Arc::new(error)));
1153 }
1154 self.validate_local_resource_limits(limits)
1155 }
1156
1157 pub fn validate_local_resource_limits(
1167 &self,
1168 limits: ModuleCertificationLimits,
1169 ) -> Result<(), crate::BlockGraphError> {
1170 source_expansion_size(self, limits)
1171 .map(|_| ())
1172 .map_err(Into::into)
1173 }
1174}
1175
1176fn add_expansion_size(
1177 size: &mut [usize; 3],
1178 amount: [usize; 3],
1179 limits: ModuleCertificationLimits,
1180) -> Result<(), crate::StabilizerError> {
1181 for ((current, amount), (phase, limit)) in size.iter_mut().zip(amount).zip([
1182 ("expanded blocks", limits.max_expanded_blocks),
1183 ("occupied footprint cells", limits.max_occupied_cells),
1184 ("expanded module instances", limits.max_expanded_instances),
1185 ]) {
1186 let next = current.checked_add(amount);
1187 if next.is_none_or(|next| next > limit) {
1188 return Err(crate::StabilizerError::ResourceLimited {
1189 phase,
1190 observed: next.unwrap_or(usize::MAX),
1191 limit,
1192 });
1193 }
1194 *current = next.expect("checked size fits");
1195 }
1196 Ok(())
1197}
1198
1199fn source_expansion_size(
1200 source: &BlockGraph,
1201 limits: ModuleCertificationLimits,
1202) -> Result<[usize; 3], crate::StabilizerError> {
1203 let mut size = [0usize; 3];
1204 let authored = source.branch_definitions().iter().flat_map(|region| {
1207 region.arm(!region.shown_true()).blocks().chain(
1208 region
1209 .shown_arm()
1210 .blocks()
1211 .filter(|block| source.get_block(block.pos()) != Some(*block)),
1212 )
1213 });
1214 for block in source.blocks().chain(authored) {
1215 let cells = match block.kind() {
1216 BlockKind::Walking(kind) => Some(kind.movement_3d()),
1217 BlockKind::PatchRotation(kind) => Some(kind.movement_3d()),
1218 _ => None,
1219 }
1220 .map_or_else(
1221 || block.height_cells() as usize,
1222 |movement| {
1223 movement
1225 .to_array()
1226 .into_iter()
1227 .map(|delta| delta.unsigned_abs() as usize + 1)
1228 .product()
1229 },
1230 );
1231 add_expansion_size(&mut size, [1, cells, 0], limits)?;
1232 }
1233 Ok(size)
1234}
1235
1236pub(crate) fn preflight_program_expansion(
1239 program: &BlockGraph,
1240 limits: ModuleCertificationLimits,
1241) -> Result<(), ModuleError> {
1242 let mut sizes = HashMap::<&str, [usize; 3]>::new();
1243 for module in module_postorder(program) {
1244 let error = |source| {
1245 let crate::StabilizerError::ResourceLimited {
1246 phase,
1247 observed,
1248 limit,
1249 } = source
1250 else {
1251 unreachable!("size counting only reports resource limits")
1252 };
1253 program_geometry_error(
1254 &module.name,
1255 resource_limit(&module.name, phase, observed, limit),
1256 )
1257 };
1258 let mut size = source_expansion_size(module.local_body(), limits).map_err(error)?;
1259 add_expansion_size(&mut size, [0, 0, 1], limits).map_err(error)?;
1260 for instance in &module.instances {
1261 add_expansion_size(&mut size, sizes[instance.definition.as_str()], limits)
1262 .map_err(error)?;
1263 }
1264 sizes.insert(&module.name, size);
1265 }
1266 Ok(())
1267}
1268
1269pub(crate) fn validate_program_geometry(program: &BlockGraph) -> Result<(), ModuleError> {
1270 for module in module_postorder(program)
1271 .into_iter()
1272 .filter(|module| !module.instances.is_empty())
1273 {
1274 validate_composite_geometry(program, module)
1275 .map_err(|error| program_geometry_error(&module.name, error))?;
1276 }
1277 let mut memo = HashMap::new();
1278 for module in program.modules() {
1279 module_geometry(program, &module.name, &mut memo)?;
1280 }
1281 Ok(())
1282}
1283
1284fn module_postorder(program: &BlockGraph) -> Vec<&BlockGraph> {
1285 module_postorder_from(
1286 program,
1287 program.modules().map(|module| module.name.as_str()),
1288 )
1289}
1290
1291fn module_postorder_from<'a>(
1292 program: &'a BlockGraph,
1293 roots: impl IntoIterator<Item = &'a str>,
1294) -> Vec<&'a BlockGraph> {
1295 let definitions = program
1296 .modules()
1297 .map(|module| (module.name.as_str(), module))
1298 .collect::<HashMap<_, _>>();
1299 let mut seen = FxHashSet::default();
1300 let mut ordered = Vec::new();
1301 for root in roots {
1302 let mut pending = vec![(root, false)];
1303 while let Some((name, exiting)) = pending.pop() {
1304 let module = definitions[name];
1305 if exiting {
1306 ordered.push(module);
1307 } else if seen.insert(name) {
1308 pending.push((name, true));
1309 pending.extend(
1310 module
1311 .instances
1312 .iter()
1313 .rev()
1314 .map(|instance| (instance.definition.as_str(), false)),
1315 );
1316 }
1317 }
1318 }
1319 ordered
1320}
1321
1322fn module_geometry(
1323 program: &BlockGraph,
1324 name: &str,
1325 memo: &mut HashMap<String, ModuleGeometry>,
1326) -> Result<ModuleGeometry, ModuleError> {
1327 if let Some(geometry) = memo.get(name) {
1328 return Ok(geometry.clone());
1329 }
1330 for module in module_postorder_from(program, [name]) {
1331 if memo.contains_key(&module.name) {
1332 continue;
1333 }
1334 let name = module.name.as_str();
1335 let geometry = if module.instances.is_empty() {
1336 let body = module.copy_local_geometry().fix_shadowed_faces();
1337 let signatures = module
1338 .interface
1339 .quantum_ports
1340 .iter()
1341 .map(|port| port_signature(name, &body, port.position))
1342 .collect::<Result<Vec<_>, _>>()
1343 .map_err(|error| program_geometry_error(name, error))?;
1344 ModuleGeometry {
1345 ports: module.interface.quantum_ports.clone(),
1346 signatures,
1347 }
1348 } else {
1349 let mut children = HashMap::new();
1350 for instance in &module.instances {
1351 let geometry = memo[&instance.definition].clone();
1352 children.insert(instance.name.as_str(), (instance, geometry));
1353 }
1354
1355 let mut binds = Vec::new();
1356 for connection in &module.quantum_connections {
1357 match connection {
1358 QuantumConnection::Input {
1359 block,
1360 input,
1361 hadamard,
1362 } => {
1363 binds.push(geometry_bind_seam(
1364 input, *block, *hadamard, true, &children,
1365 ));
1366 }
1367 QuantumConnection::Output {
1368 output,
1369 block,
1370 hadamard,
1371 } => {
1372 binds.push(geometry_bind_seam(
1373 output, *block, *hadamard, false, &children,
1374 ));
1375 }
1376 QuantumConnection::Pipe {
1377 output,
1378 input,
1379 hadamard,
1380 } => {
1381 geometry_direct_seam(output, input, *hadamard, &children, name)
1382 .map_err(|error| program_geometry_error(name, error))?;
1383 }
1384 }
1385 }
1386 validate_bind_faces(module, &binds)
1387 .map_err(|error| program_geometry_error(name, error))?;
1388 let extra_pipes = binds
1389 .iter()
1390 .map(|bind| (bind.block, bind.signature.direction.as_udirection()))
1391 .collect::<Vec<_>>();
1392 let body = module
1393 .copy_local_geometry()
1394 .fix_shadowed_faces_with(&extra_pipes);
1395 validate_bind_bases(module, &body, &binds)
1396 .map_err(|error| program_geometry_error(name, error))?;
1397 ModuleGeometry {
1398 ports: module.interface.quantum_ports.clone(),
1399 signatures: parent_signatures(module, &body, &binds)
1400 .map_err(|error| program_geometry_error(name, error))?,
1401 }
1402 };
1403 memo.insert(name.to_string(), geometry);
1404 }
1405 Ok(memo[name].clone())
1406}
1407
1408fn program_geometry_error(module: &str, error: ModuleCertificationError) -> ModuleError {
1409 ModuleError::InvalidGeometry {
1410 module: module.to_string(),
1411 source: error,
1412 span: None,
1413 }
1414}
1415
1416pub fn default_module_jobs() -> NonZeroUsize {
1419 #[cfg(not(target_arch = "wasm32"))]
1420 {
1421 const MAX_JOBS: NonZeroUsize = NonZeroUsize::new(4).expect("4 is nonzero");
1422 std::thread::available_parallelism().map_or(NonZeroUsize::MIN, |jobs| jobs.min(MAX_JOBS))
1423 }
1424 #[cfg(target_arch = "wasm32")]
1425 {
1426 NonZeroUsize::MIN
1427 }
1428}
1429
1430pub fn map_jobs<T: Sync, R: Send>(
1445 items: &[T],
1446 jobs: NonZeroUsize,
1447 f: impl Fn(&T) -> R + Sync,
1448) -> Vec<R> {
1449 #[cfg(target_arch = "wasm32")]
1450 let _ = jobs;
1451 #[cfg(not(target_arch = "wasm32"))]
1452 if items.len() > 1 && jobs.get() > 1 {
1453 let worker_count = jobs.get().min(items.len());
1454 let f = &f;
1455 let cancellation = crate::CancellationToken::current();
1456 return std::thread::scope(|scope| {
1457 let workers = (0..worker_count)
1458 .map(|worker| {
1459 let start = items.len() * worker / worker_count;
1460 let end = items.len() * (worker + 1) / worker_count;
1461 let chunk = &items[start..end];
1462 let cancellation = cancellation.clone();
1463 scope.spawn(move || {
1464 let run = || chunk.iter().map(f).collect::<Vec<_>>();
1465 match cancellation {
1466 Some(token) => token.scope(run),
1467 None => run(),
1468 }
1469 })
1470 })
1471 .collect::<Vec<_>>();
1472 workers
1473 .into_iter()
1474 .flat_map(|worker| worker.join().expect("map_jobs worker does not panic"))
1475 .collect()
1476 });
1477 }
1478 items.iter().map(f).collect()
1479}
1480
1481fn summarize_program(
1482 program: &BlockGraph,
1483 limits: ModuleCertificationLimits,
1484 jobs: NonZeroUsize,
1485) -> Result<Arc<ModuleSummary>, ModuleCertificationError> {
1486 preflight_program_expansion(program, limits).map_err(|error| match error {
1487 ModuleError::InvalidGeometry { source, .. } => source,
1488 _ => unreachable!("size preflight only reports resource limits"),
1489 })?;
1490 let mut depths = HashMap::new();
1491 let mut levels: Vec<Vec<&BlockGraph>> = Vec::new();
1492 let mut guarded = false;
1493 for module in module_postorder_from(program, [program.root().name.as_str()]) {
1494 guarded |= module.local_body().has_continuing_branches();
1495 let depth = module
1496 .instances
1497 .iter()
1498 .map(|instance| depths[instance.definition.as_str()] + 1)
1499 .max()
1500 .unwrap_or(0);
1501 levels.resize_with(levels.len().max(depth + 1), Vec::new);
1502 levels[depth].push(module);
1503 depths.insert(module.name.as_str(), depth);
1504 }
1505
1506 let mut summaries = HashMap::new();
1507 for level in levels {
1508 let results = map_jobs(&level, jobs, |&module| {
1509 summarize_definition(program, module, limits, &summaries, guarded)
1510 });
1511 for (module, summary) in level.iter().zip(results) {
1512 summaries.insert(module.name.clone(), Arc::new(summary?));
1513 }
1514 }
1515 Ok(Arc::clone(
1516 summaries
1517 .get(&program.root().name)
1518 .expect("dependency order includes the root module"),
1519 ))
1520}
1521
1522fn summarize_definition(
1523 program: &BlockGraph,
1524 module: &BlockGraph,
1525 limits: ModuleCertificationLimits,
1526 summaries: &HashMap<String, Arc<ModuleSummary>>,
1527 guarded: bool,
1528) -> Result<ModuleSummary, ModuleCertificationError> {
1529 let projection = if guarded {
1530 let linked = crate::flatten_module_definition(program, module, "").map_err(|source| {
1531 ModuleCertificationError::Graph {
1532 module: module.name.clone(),
1533 source,
1534 }
1535 })?;
1536 let targets = linked
1537 .graph
1538 .branch_regions()
1539 .map_err(|source| ModuleCertificationError::Graph {
1540 module: module.name.clone(),
1541 source,
1542 })?
1543 .into_iter()
1544 .map(|region| region.target)
1545 .collect::<Vec<_>>();
1546 if !targets.is_empty() {
1547 let certify = || -> Result<(), crate::BlockGraphError> {
1548 let topology = crate::GuardedTopology::new(&linked.graph, limits)?;
1549 crate::GuardedSurfaceSpace::new(topology, &linked.sites, limits)?
1550 .plan_readouts()
1551 .map(drop)
1552 };
1553 certify().map_err(|source| ModuleCertificationError::Graph {
1554 module: module.name.clone(),
1555 source,
1556 })?;
1557 Some(Box::new(ModuleProjection {
1558 definition: module.clone_local_definition(),
1559 targets,
1560 limits,
1561 }))
1562 } else {
1563 None
1564 }
1565 } else {
1566 None
1567 };
1568 if module.instances.is_empty() {
1569 let mut summary = summarize_leaf(module, limits)?;
1570 if guarded {
1571 summary.projection = projection;
1572 return Ok(summary);
1573 }
1574 summary.branch_variants = branch_assignments(module, limits)?
1575 .into_iter()
1576 .map(|assignments| {
1577 let mut key = assignments
1578 .iter()
1579 .copied()
1580 .filter(|(_, value)| !value)
1581 .collect::<Vec<_>>();
1582 key.sort_unstable_by_key(|(position, value)| (position.to_array(), *value));
1583 let body = module
1584 .local_body()
1585 .project_branches_deferred(assignments.iter().copied())
1586 .map_err(|source| ModuleCertificationError::Graph {
1587 module: module.name.clone(),
1588 source,
1589 })?;
1590 Ok(ModuleBranchVariant {
1591 assignments: key,
1592 summary: Box::new(summarize_leaf_body(module, &body, limits)?),
1593 })
1594 })
1595 .collect::<Result<_, ModuleCertificationError>>()?;
1596 return Ok(summary);
1597 }
1598 let children = module
1599 .instances
1600 .iter()
1601 .map(|instance| {
1602 let summary = summaries
1603 .get(&instance.definition)
1604 .expect("dependency summary is ready");
1605 (instance.name.as_str(), (instance, Arc::clone(summary)))
1606 })
1607 .collect();
1608 let mut canonical = module.clone_local_definition();
1609 canonical.replace_local_body(module.local_body().canonical_true_branch_view().map_err(
1610 |source| ModuleCertificationError::Graph {
1611 module: module.name.clone(),
1612 source,
1613 },
1614 )?);
1615 let mut summary = summarize_composite(&canonical, module, &children, limits)?;
1616 if guarded {
1617 summary.projection = projection;
1618 } else {
1619 summary.branch_variants = summarize_composite_variants(module, summaries, limits)?;
1620 }
1621 Ok(summary)
1622}
1623
1624fn branch_assignments(
1625 module: &BlockGraph,
1626 limits: ModuleCertificationLimits,
1627) -> Result<Vec<Vec<(IVec3, bool)>>, ModuleCertificationError> {
1628 let targets = module
1629 .local_body()
1630 .branch_regions()
1631 .map_err(|source| ModuleCertificationError::Graph {
1632 module: module.name.clone(),
1633 source,
1634 })?
1635 .into_iter()
1636 .map(|region| region.target)
1637 .collect::<Vec<_>>();
1638 if targets.is_empty() {
1639 return Ok(Vec::new());
1640 }
1641 if targets.len() > limits.max_guarded_domain_size {
1642 return Err(resource_limit(
1643 &module.name,
1644 "structural module alternatives",
1645 targets.len(),
1646 limits.max_guarded_domain_size,
1647 ));
1648 }
1649 Ok((0..targets.len())
1650 .map(|alternative| {
1651 targets
1652 .iter()
1653 .enumerate()
1654 .map(|(index, &target)| (target, index != alternative))
1655 .collect()
1656 })
1657 .collect())
1658}
1659
1660fn summarize_composite_variants(
1661 module: &BlockGraph,
1662 summaries: &HashMap<String, Arc<ModuleSummary>>,
1663 limits: ModuleCertificationLimits,
1664) -> Result<Vec<ModuleBranchVariant>, ModuleCertificationError> {
1665 let local_assignments = branch_assignments(module, limits)?;
1666 let variant_count = local_assignments.len().saturating_add(
1667 module
1668 .instances
1669 .iter()
1670 .map(|instance| summaries[&instance.definition].branch_variants.len())
1671 .sum::<usize>(),
1672 );
1673 if variant_count > limits.max_guarded_domain_size {
1674 return Err(resource_limit(
1675 &module.name,
1676 "structural module alternatives",
1677 variant_count,
1678 limits.max_guarded_domain_size,
1679 ));
1680 }
1681 let mut variants = Vec::with_capacity(variant_count);
1682 let canonical_children = module
1683 .instances
1684 .iter()
1685 .map(|instance| {
1686 (
1687 instance.name.as_str(),
1688 (instance, Arc::clone(&summaries[&instance.definition])),
1689 )
1690 })
1691 .collect::<HashMap<_, _>>();
1692 for assignments in local_assignments {
1693 let body = module
1694 .local_body()
1695 .project_branches_in_definition(assignments.iter().copied())
1696 .map_err(|source| ModuleCertificationError::Graph {
1697 module: module.name.clone(),
1698 source,
1699 })?;
1700 let mut projected = module.clone_local_definition();
1701 projected.replace_local_body(body);
1702 variants.push(ModuleBranchVariant {
1703 assignments: assignments
1704 .into_iter()
1705 .filter(|(_, value)| !value)
1706 .collect(),
1707 summary: Box::new(summarize_composite(
1708 &projected,
1709 module,
1710 &canonical_children,
1711 limits,
1712 )?),
1713 });
1714 }
1715
1716 let mut canonical = module.clone_local_definition();
1717 canonical.replace_local_body(module.local_body().canonical_true_branch_view().map_err(
1718 |source| ModuleCertificationError::Graph {
1719 module: module.name.clone(),
1720 source,
1721 },
1722 )?);
1723 for (selected, instance) in module.instances.iter().enumerate() {
1724 let child = &summaries[&instance.definition];
1725 for alternative in &child.branch_variants {
1726 let children = module
1727 .instances
1728 .iter()
1729 .enumerate()
1730 .map(|(index, instance)| {
1731 let summary = if index == selected {
1732 Arc::new(alternative.summary.as_ref().clone())
1733 } else {
1734 Arc::clone(&summaries[&instance.definition])
1735 };
1736 (instance.name.as_str(), (instance, summary))
1737 })
1738 .collect::<HashMap<_, _>>();
1739 let mut assignments = alternative
1740 .assignments
1741 .iter()
1742 .map(|&(target, value)| {
1743 instance
1744 .try_transform_position(target)
1745 .map(|target| (target, value))
1746 .map_err(|source| ModuleCertificationError::Graph {
1747 module: module.name.clone(),
1748 source,
1749 })
1750 })
1751 .collect::<Result<Vec<_>, _>>()?;
1752 assignments.sort_unstable_by_key(|(position, value)| (position.to_array(), *value));
1753 variants.push(ModuleBranchVariant {
1754 assignments,
1755 summary: Box::new(summarize_composite(&canonical, module, &children, limits)?),
1756 });
1757 }
1758 }
1759 Ok(variants)
1760}
1761
1762fn summarize_leaf(
1763 module: &BlockGraph,
1764 limits: ModuleCertificationLimits,
1765) -> Result<ModuleSummary, ModuleCertificationError> {
1766 let body = module
1767 .local_body()
1768 .canonical_true_branch_view()
1769 .map_err(|source| ModuleCertificationError::Graph {
1770 module: module.name.clone(),
1771 source,
1772 })?;
1773 summarize_leaf_body(module, &body, limits)
1774}
1775
1776fn summarize_leaf_body(
1777 module: &BlockGraph,
1778 body: &BlockGraph,
1779 limits: ModuleCertificationLimits,
1780) -> Result<ModuleSummary, ModuleCertificationError> {
1781 let certificate = crate::program::certify_leaf_body(
1782 &module.name,
1783 body,
1784 &module.interface.quantum_ports,
1785 limits,
1786 )?;
1787 summarize_leaf_certificate(module, body, certificate, limits)
1788}
1789
1790fn summarize_readouts(
1791 body: &BlockGraph,
1792 zx: &ZXGraph,
1793 stabilizers: &StabilizerGenerators,
1794 table: &crate::zx::ProjectedExternalTable,
1795 port_columns: &[usize],
1796) -> Vec<SummaryMeasurement> {
1797 let measurement_columns = zx.measurement_columns();
1798 let measurement_observables = zx
1799 .action_graph()
1800 .ordered_nodes()
1801 .filter_map(|node| {
1802 let Action::Measure { name, .. } = &node.action else {
1803 return None;
1804 };
1805 let observable = match node.measurement? {
1806 MeasurementObservable::Concrete(PauliBasis::X) => Pauli::X,
1807 MeasurementObservable::Concrete(PauliBasis::Z) => Pauli::Z,
1808 MeasurementObservable::Concrete(PauliBasis::Y)
1809 | MeasurementObservable::Selective(_) => Pauli::Y,
1810 };
1811 Some((name.as_str(), observable))
1812 })
1813 .collect::<HashMap<_, _>>();
1814 let owned_positions = body
1815 .blocks()
1816 .filter(|block| !block.kind().is_port())
1817 .map(Block::pos)
1818 .collect::<FxHashSet<_>>();
1819 let flow_basis = table.flow_witness_basis();
1821 stabilizers
1822 .generators
1823 .iter()
1824 .enumerate()
1825 .filter_map(|(index, generator)| {
1826 let (name, target, observable, self_readers) = match &generator.kind {
1827 StabilizerRowKind::Measurement { name } => (
1828 name.clone(),
1829 support_target(zx, measurement_columns[name.as_str()]),
1830 measurement_observables[name.as_str()],
1831 self_reader_targets(zx, name),
1832 ),
1833 StabilizerRowKind::SelectiveFixing { targets } => (
1834 format!("#fix{index}"),
1835 SupportTarget::Node(targets[0].pos),
1836 Pauli::I,
1837 Vec::new(),
1838 ),
1839 StabilizerRowKind::Logical => return None,
1840 };
1841 let support = PositionedSupport::from_stabilizer(&generator.stabilizer, zx);
1842 let mut raw = generator.stabilizer.paulis.clone();
1843 zx.clear_cross_centers(std::slice::from_mut(&mut raw));
1844 let witness = flow_basis
1845 .witness_for_row(&raw)
1846 .expect("certified generator belongs to the projected row space");
1847 Some(SummaryMeasurement {
1848 name,
1849 kind: generator.kind.clone(),
1850 signed: PhasedPauliString::new(
1851 PauliString::from_terms(
1852 port_columns.len(),
1853 port_columns.iter().enumerate().map(|(target, &source)| {
1854 (target, generator.stabilizer.paulis.get(source))
1855 }),
1856 ),
1857 stabilizer_phase(&generator.stabilizer),
1858 ),
1859 support,
1860 witness,
1861 target,
1862 observable,
1863 self_readers,
1864 owned_positions: owned_positions.clone(),
1865 })
1866 })
1867 .collect::<Vec<_>>()
1868}
1869
1870fn summarize_leaf_certificate(
1871 module: &BlockGraph,
1872 source: &BlockGraph,
1873 certificate: crate::LeafModuleCertificate,
1874 limits: ModuleCertificationLimits,
1875) -> Result<ModuleSummary, ModuleCertificationError> {
1876 let body = source.fix_shadowed_faces();
1877 let signatures = module
1878 .interface
1879 .quantum_ports
1880 .iter()
1881 .map(|port| port_signature(&module.name, &body, port.position))
1882 .collect::<Result<Vec<_>, _>>()?;
1883 let zx = &certificate.stabilizers.zx_graph;
1884 let rows = certificate
1885 .table
1886 .boundary_rows
1887 .iter()
1888 .map(|row| {
1889 let full = certificate.table.materialize(row);
1890 let stabilizer = zx.materialize_stabilizer_with_sign(full.paulis, false);
1892 SupportedRow {
1893 signed: row.signed.clone(),
1894 support: PositionedSupport::from_stabilizer(&stabilizer, zx),
1895 witness: row.flow_witness.clone(),
1896 }
1897 })
1898 .collect::<Vec<_>>();
1899 let port_columns = module
1900 .interface
1901 .quantum_ports
1902 .iter()
1903 .map(|port| {
1904 zx.node_at(port.position)
1905 .expect("validated module port is a ZX node")
1906 .id
1907 })
1908 .collect::<Vec<_>>();
1909 let measurements = summarize_readouts(
1910 &body,
1911 zx,
1912 &certificate.stabilizers,
1913 &certificate.table,
1914 &port_columns,
1915 );
1916 let logical_rows = certificate
1917 .stabilizers
1918 .generators
1919 .iter()
1920 .filter(|generator| matches!(generator.kind, StabilizerRowKind::Logical))
1921 .map(|generator| SupportedRow {
1922 signed: PhasedPauliString::new(
1923 PauliString::from_terms(
1924 port_columns.len(),
1925 port_columns
1926 .iter()
1927 .enumerate()
1928 .map(|(target, &source)| (target, generator.stabilizer.paulis.get(source))),
1929 ),
1930 stabilizer_phase(&generator.stabilizer),
1931 ),
1932 support: PositionedSupport::from_stabilizer(&generator.stabilizer, zx),
1933 witness: FlowWitness::default(),
1934 })
1935 .collect::<Vec<_>>();
1936 let protected_groups =
1937 semantic_protected_groups(&body, &measurements, zx, limits, &module.name)?;
1938 let (discharged_measurements, measurements): (Vec<_>, Vec<_>) = measurements
1939 .into_iter()
1940 .partition(measurement_can_discharge);
1941 let protected = semantic_protected_supports(module, &body);
1942 let frontier = semantic_frontier_supports(module, &body)?;
1943 let adjustments = adjustment_rows(
1944 zx,
1945 &certificate.table,
1946 &rows,
1947 &measurements,
1948 &protected,
1949 &frontier,
1950 module.interface.quantum_ports.len(),
1951 );
1952 let certificate_rows = retained_certificate_rows(
1953 zx,
1954 &certificate.table,
1955 &rows,
1956 module.interface.quantum_ports.len(),
1957 );
1958 Ok(ModuleSummary {
1959 name: module.name.clone(),
1960 limits,
1961 dependencies: HashMap::new(),
1962 ports: module.interface.quantum_ports.clone(),
1963 signatures,
1964 rows,
1965 logical_rows,
1966 certificate_rows,
1967 adjustments,
1968 measurements,
1969 discharged_measurements,
1970 protected,
1971 frontier,
1972 protected_groups,
1973 branch_variants: Vec::new(),
1974 projection: None,
1975 })
1976}
1977
1978fn measurement_can_discharge(measurement: &SummaryMeasurement) -> bool {
1979 matches!(measurement.kind, StabilizerRowKind::Measurement { .. })
1980 && measurement.signed.paulis.is_identity()
1981 && support_target_is_owned(measurement.target, &measurement.owned_positions)
1982 && measurement
1983 .self_readers
1984 .iter()
1985 .all(|&target| support_target_is_owned(target, &measurement.owned_positions))
1986}
1987
1988fn support_target_is_owned(target: SupportTarget, owned: &FxHashSet<IVec3>) -> bool {
1989 match target {
1990 SupportTarget::Node(position) => owned.contains(&position),
1991 SupportTarget::Edge(left, right) => owned.contains(&left) && owned.contains(&right),
1992 }
1993}
1994
1995fn support_target(zx: &ZXGraph, column: usize) -> SupportTarget {
1996 if column < zx.nodes().len() {
1997 SupportTarget::Node(zx.nodes()[column].pos)
1998 } else {
1999 let edge = &zx.edges()[column - zx.nodes().len()];
2000 SupportTarget::Edge(zx.nodes()[edge.n1].pos, zx.nodes()[edge.n2].pos)
2001 }
2002}
2003
2004fn self_reader_targets(zx: &ZXGraph, measurement: &str) -> Vec<SupportTarget> {
2005 let actions = zx.action_graph().ordered_nodes().collect::<Vec<_>>();
2006 let Some(start) = actions.iter().position(
2007 |node| matches!(&node.action, Action::Measure { name, .. } if name == measurement),
2008 ) else {
2009 return Vec::new();
2010 };
2011 let mut successors = vec![Vec::new(); actions.len()];
2012 for (from, to, _) in zx.action_graph().dependencies() {
2013 successors[from].push(to);
2014 }
2015 let mut seen = FxHashSet::default();
2016 let mut stack = successors[start].clone();
2017 while let Some(ordinal) = stack.pop() {
2018 if seen.insert(ordinal) {
2019 stack.extend(successors[ordinal].iter().copied());
2020 }
2021 }
2022 let mut targets = FxHashSet::default();
2023 for ordinal in seen {
2024 match &actions[ordinal].action {
2025 Action::Resolve { target, .. } | Action::Branch { target, .. } => {
2026 targets.insert(SupportTarget::Node(*target));
2027 }
2028 Action::Feedback {
2029 targets: feedbacks, ..
2030 } => {
2031 for feedback in feedbacks {
2032 let node = zx
2033 .node_at(feedback.target)
2034 .expect("validated feedback target");
2035 let neighbor = match feedback.direction {
2036 Some(dir) => zx
2037 .node_at(
2038 checked_add_position(feedback.target, dir.to_ivec3())
2039 .expect("validated feedback edge"),
2040 )
2041 .map(|node| node.id),
2042 None if node.kind == crate::NodeKind::Port => zx
2043 .neighbors(node.id)
2044 .and_then(|neighbors| (neighbors.len() == 1).then(|| neighbors[0])),
2045 None => None,
2046 };
2047 targets.insert(match neighbor {
2048 Some(neighbor) => support_target(
2049 zx,
2050 zx.edge_id(node.id, neighbor).expect("feedback wire exists"),
2051 ),
2052 None => SupportTarget::Node(feedback.target),
2053 });
2054 }
2055 }
2056 Action::Let { .. } | Action::Measure { .. } | Action::DiscardIf(_) => {}
2057 }
2058 }
2059 targets.into_iter().collect()
2060}
2061
2062fn retained_certificate_rows(
2063 zx: &ZXGraph,
2064 table: &crate::zx::ProjectedExternalTable,
2065 boundary_rows: &[SupportedRow],
2066 boundary_width: usize,
2067) -> Vec<SupportedRow> {
2068 let mut rows = boundary_rows.to_vec();
2069 rows.extend(table.closed_rows.iter().map(|row| SupportedRow {
2070 signed: PhasedPauliString::new(PauliString::new(boundary_width), row.signed.phase()),
2071 support: PositionedSupport::from_stabilizer(
2072 &zx.materialize_stabilizer_with_sign(row.signed.paulis.clone(), false),
2073 zx,
2074 ),
2075 witness: row.flow_witness.clone(),
2076 }));
2077 rows
2078}
2079
2080fn adjustment_rows(
2081 zx: &ZXGraph,
2082 table: &crate::zx::ProjectedExternalTable,
2083 boundary_rows: &[SupportedRow],
2084 measurements: &[SummaryMeasurement],
2085 protected: &[ProtectedSupport],
2086 frontier: &[SupportTarget],
2087 boundary_width: usize,
2088) -> Vec<SupportedRow> {
2089 let mut rows = retained_certificate_rows(zx, table, boundary_rows, boundary_width);
2090 let mut targets = measurements
2091 .iter()
2092 .map(|measurement| measurement.target)
2093 .chain(
2094 measurements
2095 .iter()
2096 .flat_map(|measurement| measurement.self_readers.iter().copied()),
2097 )
2098 .chain(protected.iter().map(|constraint| constraint.target))
2099 .chain(frontier.iter().copied())
2100 .collect::<FxHashSet<_>>()
2101 .into_iter()
2102 .collect::<Vec<_>>();
2103 targets.sort_unstable_by_key(support_target_key);
2104 let rank = signed_gaussian_elimination(
2105 &mut rows,
2106 (0..boundary_width)
2107 .flat_map(|column| {
2108 [Pauli::X, Pauli::Z].map(move |axis| SupportConstraint::Boundary(column, axis))
2109 })
2110 .chain(targets.into_iter().flat_map(|target| {
2111 [Pauli::X, Pauli::Z].map(move |axis| SupportConstraint::Target(target, axis))
2112 })),
2113 |row, constraint| match *constraint {
2114 SupportConstraint::Boundary(column, axis) => row.signed.paulis.get(column) & axis,
2115 SupportConstraint::Target(target, axis) => row.support.get(target) & axis,
2116 },
2117 );
2118 rows.truncate(rank);
2119 rows
2120}
2121
2122fn summarize_composite(
2123 module: &BlockGraph,
2124 semantic_module: &BlockGraph,
2125 children: &HashMap<&str, (&ModuleInstance, Arc<ModuleSummary>)>,
2126 limits: ModuleCertificationLimits,
2127) -> Result<ModuleSummary, ModuleCertificationError> {
2128 let parent_width = module.interface.quantum_ports.len();
2129 let mut relations = Vec::with_capacity(module.instances.len());
2130 let mut owners = HashMap::new();
2131 for instance in &module.instances {
2132 let summary = &children[instance.name.as_str()].1;
2133 let endpoints = summary
2134 .ports
2135 .iter()
2136 .map(|port| InstancePort {
2137 instance: instance.name.clone(),
2138 port: port.name.clone(),
2139 })
2140 .collect::<Vec<_>>();
2141 let owner = relations.len();
2142 for endpoint in &endpoints {
2143 owners.insert(endpoint.clone(), owner);
2144 }
2145 let port_positions = summary
2146 .ports
2147 .iter()
2148 .map(|port| port.position)
2149 .collect::<Vec<_>>();
2150 let port_position_set = port_positions.iter().copied().collect::<FxHashSet<_>>();
2151 let retained_targets = summary
2152 .measurements
2153 .iter()
2154 .chain(&summary.discharged_measurements)
2155 .flat_map(|measurement| {
2156 std::iter::once(measurement.target).chain(measurement.self_readers.iter().copied())
2157 })
2158 .collect::<Vec<_>>();
2159 let rows = instantiate_rows(
2160 &summary.rows,
2161 instance,
2162 &port_position_set,
2163 &retained_targets,
2164 &module.name,
2165 )?;
2166 let logical_rows = instantiate_rows(
2167 &summary.logical_rows,
2168 instance,
2169 &port_position_set,
2170 &retained_targets,
2171 &module.name,
2172 )?;
2173 let certificate_rows = instantiate_rows(
2174 &summary.certificate_rows,
2175 instance,
2176 &port_position_set,
2177 &retained_targets,
2178 &module.name,
2179 )?;
2180 let adjustments = instantiate_rows(
2181 &summary.adjustments,
2182 instance,
2183 &port_position_set,
2184 &retained_targets,
2185 &module.name,
2186 )?;
2187 let measurements = instantiate_measurements(
2188 &summary.measurements,
2189 instance,
2190 &port_positions,
2191 &retained_targets,
2192 &module.name,
2193 )?;
2194 let discharged_measurements = instantiate_measurements(
2195 &summary.discharged_measurements,
2196 instance,
2197 &port_positions,
2198 &retained_targets,
2199 &module.name,
2200 )?;
2201 let orientation = instance.orientation();
2202 let graph_error = |source| ModuleCertificationError::Graph {
2203 module: module.name.clone(),
2204 source,
2205 };
2206 let protected = summary
2207 .protected
2208 .iter()
2209 .map(|&target| {
2210 target
2211 .transformed(orientation, instance.translation)
2212 .map_err(graph_error)
2213 })
2214 .collect::<Result<Vec<_>, ModuleCertificationError>>()?;
2215 let frontier = summary
2216 .frontier
2217 .iter()
2218 .map(|&target| {
2219 target
2220 .transformed(orientation, instance.translation)
2221 .map_err(graph_error)
2222 })
2223 .collect::<Result<Vec<_>, ModuleCertificationError>>()?;
2224 let protected_groups = summary
2225 .protected_groups
2226 .iter()
2227 .cloned()
2228 .map(|group| {
2229 group
2230 .transformed(orientation, instance.translation)
2231 .map_err(graph_error)
2232 })
2233 .collect::<Result<Vec<_>, ModuleCertificationError>>()?;
2234 relations.push(Some(ChildRelation {
2235 parent_ports: Vec::new(),
2236 endpoints,
2237 rows,
2238 logical_rows,
2239 certificate_rows,
2240 adjustments,
2241 measurements,
2242 discharged_measurements,
2243 protected,
2244 frontier,
2245 protected_groups,
2246 }));
2247 }
2248
2249 let mut binds = Vec::new();
2250 for connection in &module.quantum_connections {
2251 match connection {
2252 QuantumConnection::Input {
2253 block,
2254 input,
2255 hadamard,
2256 } => {
2257 binds.push(bind_seam(input, *block, *hadamard, true, children));
2258 }
2259 QuantumConnection::Output {
2260 output,
2261 block,
2262 hadamard,
2263 } => {
2264 binds.push(bind_seam(output, *block, *hadamard, false, children));
2265 }
2266 QuantumConnection::Pipe {
2267 output,
2268 input,
2269 hadamard,
2270 } => {
2271 let effective_hadamard =
2272 direct_seam_hadamard(output, input, *hadamard, children, &module.name)?;
2273 let output_geometry = summarized_port(children, output);
2274 let input_geometry = summarized_port(children, input);
2275 let support_seam = SupportSeam {
2276 edge: (
2277 exposed_position(
2278 output_geometry.instance,
2279 output_geometry.port,
2280 output_geometry.signature,
2281 )?,
2282 exposed_position(
2283 input_geometry.instance,
2284 input_geometry.port,
2285 input_geometry.signature,
2286 )?,
2287 ),
2288 boundary_to_edge_hadamard: output_geometry.signature.hadamard,
2289 };
2290 compose_child_seam(
2291 (output, input),
2292 effective_hadamard,
2293 support_seam,
2294 &mut relations,
2295 &mut owners,
2296 limits.max_frontier_width,
2297 &module.name,
2298 )?;
2299 }
2300 }
2301 }
2302
2303 ensure_composition_width(&module.name, parent_width, limits.max_frontier_width)?;
2304 validate_bind_faces(module, &binds)?;
2305 let seams = binds
2306 .iter()
2307 .map(|bind| ModuleSeam {
2308 block: bind.block,
2309 direction: bind.signature.direction,
2310 })
2311 .collect::<Vec<_>>();
2312 let extra_pipes = seams
2313 .iter()
2314 .map(|seam| (seam.block, seam.direction.as_udirection()))
2315 .collect::<Vec<_>>();
2316 let fixed_body = module
2317 .copy_local_geometry()
2318 .fix_shadowed_faces_with(&extra_pipes);
2319 validate_bind_bases(module, &fixed_body, &binds)?;
2320 let signatures = parent_signatures(module, &fixed_body, &binds)?;
2321 let parent_protected = semantic_protected_supports(semantic_module, &fixed_body);
2322 let parent_frontier = semantic_frontier_supports(semantic_module, &fixed_body)?;
2323 let obligations = relations
2325 .iter()
2326 .flatten()
2327 .flat_map(|relation| {
2328 relation
2329 .measurements
2330 .iter()
2331 .flat_map(|measurement| {
2332 std::iter::once(measurement.target)
2333 .chain(measurement.self_readers.iter().copied())
2334 })
2335 .chain(relation.protected.iter().map(|support| support.target))
2336 .chain(
2337 relation
2338 .protected_groups
2339 .iter()
2340 .flat_map(|group| group.targets.iter().copied()),
2341 )
2342 })
2343 .chain(parent_protected.iter().map(|support| support.target))
2344 .collect::<FxHashSet<_>>();
2345 let mut completed = ChildRelation::default();
2346 for relation in relations.iter_mut().flatten() {
2347 relation.retire_completed(&mut completed, &obligations, &module.name)?;
2348 }
2349
2350 let (connector, seam_nodes) =
2351 ZXGraph::from_module_body(&fixed_body, &seams).map_err(|source| {
2352 ModuleCertificationError::Graph {
2353 module: module.name.clone(),
2354 source: source.into(),
2355 }
2356 })?;
2357 if connector.total_ids() > limits.max_local_columns {
2358 return Err(resource_limit(
2359 &module.name,
2360 "local ZX columns",
2361 connector.total_ids(),
2362 limits.max_local_columns,
2363 ));
2364 }
2365 let parent_ports = module
2366 .interface
2367 .quantum_ports
2368 .iter()
2369 .enumerate()
2370 .map(|(index, port)| {
2371 (
2372 connector
2373 .node_at(port.position)
2374 .expect("validated parent port")
2375 .id,
2376 index,
2377 )
2378 })
2379 .collect::<HashMap<_, _>>();
2380 let seam_indices = seam_nodes
2381 .iter()
2382 .enumerate()
2383 .map(|(index, &node)| (node, index))
2384 .collect::<HashMap<_, _>>();
2385 let connector_components = if connector.action_graph().ordered_nodes().next().is_some()
2388 || parent_width <= 2
2389 && fixed_body.block_count() == parent_width
2390 && binds.len() == parent_width
2391 && parent_width + 2 * binds.len() <= limits.max_frontier_width
2392 && fixed_body.blocks().all(|block| block.kind().is_port())
2393 {
2394 let nodes = (0..connector.nodes().len()).collect();
2395 vec![(connector, nodes)]
2396 } else {
2397 connector.into_connector_components()
2398 };
2399 for (connector, original_nodes) in connector_components {
2402 let connector_parents = original_nodes
2403 .iter()
2404 .filter_map(|node| parent_ports.get(node).copied())
2405 .collect::<Vec<_>>();
2406 let connector_binds = original_nodes
2407 .iter()
2408 .enumerate()
2409 .filter_map(|(local, original)| {
2410 seam_indices
2411 .get(original)
2412 .map(|&index| (&binds[index], local))
2413 })
2414 .collect::<Vec<_>>();
2415 let mut touched = connector_binds
2416 .iter()
2417 .map(|(bind, _)| owners[&bind.endpoint])
2418 .collect::<Vec<_>>();
2419 touched.sort_unstable();
2420 touched.dedup();
2421 let slot = touched.first().copied().unwrap_or_else(|| {
2422 relations.push(None);
2423 relations.len() - 1
2424 });
2425 let children_to_join = touched
2426 .iter()
2427 .map(|&owner| {
2428 relations[owner]
2429 .take()
2430 .expect("live endpoint has a relation")
2431 })
2432 .collect::<Vec<_>>();
2433 let mut joined = compose_parent_connector(
2434 module,
2435 children,
2436 children_to_join,
2437 connector,
2438 connector_parents,
2439 &connector_binds,
2440 &parent_protected,
2441 &parent_frontier,
2442 limits,
2443 )?;
2444 joined.retire_completed(&mut completed, &obligations, &module.name)?;
2445 for (bind, _) in &connector_binds {
2446 owners.remove(&bind.endpoint);
2447 }
2448 for endpoint in &joined.endpoints {
2449 owners.insert(endpoint.clone(), slot);
2450 }
2451 relations[slot] = Some(joined);
2452 }
2453 let mut combined = ChildRelation::default();
2454 for relation in relations.into_iter().flatten() {
2455 assert!(
2456 relation.endpoints.is_empty(),
2457 "all child endpoints are bound"
2458 );
2459 let mapping = relation.parent_ports.clone();
2460 combined.append(relation, &mapping, parent_width);
2461 }
2462 combined.append(completed, &[], parent_width);
2463 let ChildRelation {
2464 mut rows,
2465 mut logical_rows,
2466 mut certificate_rows,
2467 mut adjustments,
2468 mut measurements,
2469 mut discharged_measurements,
2470 mut protected,
2471 mut frontier,
2472 protected_groups,
2473 ..
2474 } = combined;
2475 merge_protected_supports(&mut protected, &parent_protected);
2476 frontier.extend(parent_frontier);
2477 frontier.sort_unstable_by_key(support_target_key);
2478 frontier.dedup();
2479 let retained = (0..parent_width).collect::<Vec<_>>();
2480 rows = compose_supported_rows(rows, &mut [], &[], &[], &[], &retained, &module.name)?;
2481 logical_rows = compose_supported_rows(
2482 logical_rows,
2483 &mut [],
2484 &[],
2485 &[],
2486 &[],
2487 &retained,
2488 &module.name,
2489 )?;
2490 certificate_rows = compose_certificate_rows(certificate_rows, &[], &retained);
2491 adjustments = compose_supported_rows(
2492 adjustments,
2493 &mut measurements,
2494 &protected,
2495 &frontier,
2496 &[],
2497 &retained,
2498 &module.name,
2499 )?;
2500 normalize_fixing_rows(
2501 &mut measurements,
2502 &adjustments,
2503 &protected,
2504 limits,
2505 &module.name,
2506 )?;
2507 normalize_measurement_rows(
2508 &mut measurements,
2509 &adjustments,
2510 &protected,
2511 &protected_groups,
2512 limits,
2513 &module.name,
2514 )?;
2515 let (newly_discharged, remaining) = measurements
2516 .into_iter()
2517 .partition(measurement_can_discharge);
2518 measurements = remaining;
2519 discharged_measurements.extend(newly_discharged);
2520 Ok(ModuleSummary {
2521 name: module.name.clone(),
2522 limits,
2523 dependencies: children
2524 .values()
2525 .map(|(_, summary)| (summary.name.clone(), Arc::clone(summary)))
2526 .collect(),
2527 ports: module.interface.quantum_ports.clone(),
2528 signatures,
2529 rows,
2530 logical_rows,
2531 certificate_rows,
2532 adjustments,
2533 measurements,
2534 discharged_measurements,
2535 protected,
2536 frontier,
2537 protected_groups,
2538 branch_variants: Vec::new(),
2539 projection: None,
2540 })
2541}
2542
2543#[expect(
2544 clippy::too_many_arguments,
2545 reason = "connector composition consumes independent certified inputs"
2546)]
2547fn compose_parent_connector(
2548 module: &BlockGraph,
2549 children: &HashMap<&str, (&ModuleInstance, Arc<ModuleSummary>)>,
2550 relations: Vec<ChildRelation>,
2551 connector: ZXGraph,
2552 connector_parents: Vec<usize>,
2553 binds: &[(&BindSeam, usize)],
2554 parent_protected: &[ProtectedSupport],
2555 parent_frontier: &[SupportTarget],
2556 limits: ModuleCertificationLimits,
2557) -> Result<ChildRelation, ModuleCertificationError> {
2558 let existing_parents = relations
2559 .iter()
2560 .map(|r| r.parent_ports.len())
2561 .sum::<usize>();
2562 let parent_width = existing_parents + connector_parents.len();
2563 let child_width = relations.iter().map(|r| r.endpoints.len()).sum::<usize>();
2564 let connector_start = parent_width + child_width;
2565 let width = connector_start + binds.len();
2566 ensure_composition_width(&module.name, width, limits.max_frontier_width)?;
2567
2568 let mut joined = ChildRelation::default();
2569 let mut next_parent = 0;
2570 let mut next_child = parent_width;
2571 for relation in relations {
2572 let parents = next_parent..next_parent + relation.parent_ports.len();
2573 let endpoints = next_child..next_child + relation.endpoints.len();
2574 next_parent = parents.end;
2575 next_child = endpoints.end;
2576 joined.append(
2577 relation,
2578 &parents.chain(endpoints).collect::<Vec<_>>(),
2579 width,
2580 );
2581 }
2582 joined
2583 .parent_ports
2584 .extend(connector_parents.iter().copied());
2585 let endpoint_columns = joined
2586 .endpoints
2587 .iter()
2588 .enumerate()
2589 .map(|(index, endpoint)| (endpoint, parent_width + index))
2590 .collect::<HashMap<_, _>>();
2591 let connector_columns = connector_parents
2592 .iter()
2593 .map(|&index| {
2594 connector
2595 .node_at(module.interface.quantum_ports[index].position)
2596 .expect("component contains its parent port")
2597 .id
2598 })
2599 .chain(binds.iter().map(|&(_, node)| node))
2600 .collect::<Vec<_>>();
2601 let table = connector
2602 .projected_external_table(
2603 &connector_columns,
2604 ProjectionLimits {
2605 max_frontier_width: limits.max_frontier_width,
2606 max_witness_nodes: limits.max_witness_nodes,
2607 },
2608 )
2609 .map_err(|error| projection_limit(&module.name, error))?;
2610 let seam_positions = binds
2611 .iter()
2612 .map(|&(_, node)| connector.nodes()[node].pos)
2613 .collect::<FxHashSet<_>>();
2614 let connector_rows = table
2615 .boundary_rows
2616 .iter()
2617 .map(|row| {
2618 let full = table.materialize(row);
2619 let stabilizer = connector.materialize_stabilizer_with_sign(full.paulis, false);
2621 let mut support = PositionedSupport::from_stabilizer(&stabilizer, &connector);
2622 support.strip_ports(&seam_positions, &[]);
2623 let mut witness = row.flow_witness.clone();
2624 witness.strip_positions(&seam_positions);
2625 SupportedRow {
2626 signed: row.signed.clone(),
2627 support,
2628 witness,
2629 }
2630 })
2631 .collect::<Vec<_>>();
2632 let connector_certificates =
2633 retained_certificate_rows(&connector, &table, &connector_rows, connector_columns.len());
2634 let mapping = (existing_parents..parent_width)
2635 .chain(connector_start..width)
2636 .collect::<Vec<_>>();
2637 if connector.action_graph().ordered_nodes().next().is_some() {
2640 let stabilizers = connector
2641 .stabilizers_with_limits(limits)
2642 .map_err(|source| ModuleCertificationError::Runtime {
2643 module: module.name.clone(),
2644 source: source.into(),
2645 })?;
2646 let mut measurements = summarize_readouts(
2647 module.local_body(),
2648 &connector,
2649 &stabilizers,
2650 &table,
2651 &connector_columns,
2652 );
2653 joined.protected_groups.extend(semantic_protected_groups(
2654 module.local_body(),
2655 &measurements,
2656 &connector,
2657 limits,
2658 &module.name,
2659 )?);
2660 for measurement in &mut measurements {
2661 measurement.signed = embed_signed_row(&measurement.signed, &mapping, width);
2662 measurement.support.strip_ports(&seam_positions, &[]);
2663 measurement.witness.strip_positions(&seam_positions);
2664 }
2665 joined.measurements.extend(measurements);
2666 }
2667 joined
2668 .rows
2669 .extend(embed_rows(&connector_rows, &mapping, width));
2670 joined
2671 .logical_rows
2672 .extend(embed_rows(&connector_rows, &mapping, width));
2673 joined
2674 .certificate_rows
2675 .extend(embed_rows(&connector_certificates, &mapping, width));
2676 let mut adjustments = embed_rows(&connector_rows, &mapping, width);
2677 adjustments.append(&mut joined.adjustments);
2678 joined.adjustments = adjustments;
2679
2680 let seam_pairs = binds
2681 .iter()
2682 .enumerate()
2683 .map(|(index, &(bind, _))| {
2684 let port = summarized_port(children, &bind.endpoint);
2685 (
2686 endpoint_columns[&bind.endpoint],
2687 connector_start + index,
2688 bind.hadamard,
2689 bind.transpose,
2690 SupportSeam {
2691 edge: (
2692 bind.block,
2693 exposed_position(port.instance, port.port, port.signature)
2694 .expect("validated bind endpoint fits"),
2695 ),
2696 boundary_to_edge_hadamard: bind.hadamard,
2697 },
2698 )
2699 })
2700 .collect::<Vec<_>>();
2701 let bound = binds
2702 .iter()
2703 .map(|(bind, _)| &bind.endpoint)
2704 .collect::<HashSet<_>>();
2705 let retained = (0..parent_width)
2706 .chain(
2707 joined
2708 .endpoints
2709 .iter()
2710 .enumerate()
2711 .filter_map(|(index, endpoint)| {
2712 (!bound.contains(endpoint)).then_some(parent_width + index)
2713 }),
2714 )
2715 .collect::<Vec<_>>();
2716 let mut protected = joined.protected.clone();
2717 merge_protected_supports(&mut protected, parent_protected);
2718 let mut frontier = joined.frontier.clone();
2719 frontier.extend_from_slice(parent_frontier);
2720 for rows in [&mut joined.rows, &mut joined.logical_rows] {
2721 *rows = compose_supported_rows(
2722 std::mem::take(rows),
2723 &mut [],
2724 &[],
2725 &[],
2726 &seam_pairs,
2727 &retained,
2728 &module.name,
2729 )?;
2730 }
2731 joined.certificate_rows =
2732 compose_certificate_rows(joined.certificate_rows, &seam_pairs, &retained);
2733 joined.adjustments = compose_supported_rows(
2734 joined.adjustments,
2735 &mut joined.measurements,
2736 &protected,
2737 &frontier,
2738 &seam_pairs,
2739 &retained,
2740 &module.name,
2741 )?;
2742 resize_discharged_boundaries(
2743 &mut joined.discharged_measurements,
2744 retained.len(),
2745 &module.name,
2746 )?;
2747 joined
2748 .endpoints
2749 .retain(|endpoint| !bound.contains(endpoint));
2750 Ok(joined)
2751}
2752
2753fn merge_protected_supports(protected: &mut Vec<ProtectedSupport>, added: &[ProtectedSupport]) {
2754 for constraint in added {
2755 if let Some(existing) = protected
2756 .iter_mut()
2757 .find(|existing| existing.target == constraint.target)
2758 {
2759 if existing.forbidden.is_none() {
2760 existing.forbidden = constraint.forbidden;
2761 }
2762 } else {
2763 protected.push(*constraint);
2764 }
2765 }
2766 protected.sort_unstable_by_key(|constraint| support_target_key(&constraint.target));
2767}
2768
2769fn resize_discharged_boundaries(
2770 measurements: &mut [SummaryMeasurement],
2771 width: usize,
2772 module: &str,
2773) -> Result<(), ModuleCertificationError> {
2774 for measurement in measurements {
2775 if !measurement.signed.paulis.is_identity() {
2776 return Err(invalid(
2777 module,
2778 &format!(
2779 "discharged measurement '{}' retains boundary support",
2780 measurement.name
2781 ),
2782 ));
2783 }
2784 measurement.signed.paulis = PauliString::new(width);
2785 }
2786 Ok(())
2787}
2788
2789fn normalize_fixing_rows(
2790 rows: &mut [SummaryMeasurement],
2791 adjustments: &[SupportedRow],
2792 protected: &[ProtectedSupport],
2793 limits: ModuleCertificationLimits,
2794 module: &str,
2795) -> Result<(), ModuleCertificationError> {
2796 let mut visited = 0;
2797 for row in rows.iter_mut().filter(|row| row.kind.is_selective_fixing()) {
2798 let own = row
2799 .kind
2800 .selective_fixing_targets()
2801 .iter()
2802 .map(|target| (SupportTarget::Node(target.pos), target.forbidden))
2803 .collect::<HashMap<_, _>>();
2804 let constraints = protected
2805 .iter()
2806 .flat_map(|constraint| {
2807 if own.contains_key(&constraint.target) {
2808 vec![
2809 (constraint.target, Pauli::X, false),
2810 (constraint.target, Pauli::Z, false),
2811 ]
2812 } else {
2813 let support = row.support.get(constraint.target);
2814 vec![
2815 (constraint.target, Pauli::X, support & Pauli::X),
2816 (constraint.target, Pauli::Z, support & Pauli::Z),
2817 ]
2818 }
2819 })
2820 .collect::<Vec<_>>();
2821 let combination = MeasurementNormalization {
2822 row,
2823 adjustments,
2824 visited: &mut visited,
2825 limits,
2826 module,
2827 }
2828 .solve(&constraints)?
2829 .ok_or_else(|| {
2830 invalid(
2831 module,
2832 &format!(
2833 "selective fixing '{}' cannot be decoupled after module composition",
2834 row.name
2835 ),
2836 )
2837 })?;
2838 for index in combination {
2839 multiply_measurement(row, &adjustments[index]);
2840 }
2841 for (&target, &forbidden) in &own {
2842 if row.support.get(target) != forbidden {
2843 return Err(invalid(
2844 module,
2845 &format!("selective fixing '{}' lost its target", row.name),
2846 ));
2847 }
2848 }
2849 for constraint in protected {
2850 if !own.contains_key(&constraint.target)
2851 && row.support.get(constraint.target) != Pauli::I
2852 {
2853 return Err(invalid(
2854 module,
2855 &format!(
2856 "selective fixing '{}' remains coupled after module composition",
2857 row.name
2858 ),
2859 ));
2860 }
2861 }
2862 }
2863 Ok(())
2864}
2865
2866enum NormalizationFactor<'a> {
2867 Group(&'a ProtectedGroup),
2868 Site(&'a ProtectedSupport),
2869}
2870
2871enum NormalizationPoint {
2872 Factor(usize),
2873 Partial {
2874 factor: usize,
2875 support: usize,
2876 start: usize,
2877 },
2878}
2879
2880enum NormalizationChoices<'a> {
2881 Site {
2882 target: SupportTarget,
2883 values: std::vec::IntoIter<Pauli>,
2884 },
2885 Group {
2886 group: &'a ProtectedGroup,
2887 current: Vec<Pauli>,
2888 permitted: bool,
2889 next: usize,
2890 },
2891 Partial {
2892 group: &'a ProtectedGroup,
2893 support: usize,
2894 start: usize,
2895 next: usize,
2896 },
2897}
2898
2899struct NormalizationFrame<'a> {
2900 factor: usize,
2901 constraints: usize,
2902 partial: usize,
2903 choices: NormalizationChoices<'a>,
2904}
2905
2906struct MeasurementNormalization<'a> {
2907 row: &'a SummaryMeasurement,
2908 adjustments: &'a [SupportedRow],
2909 visited: &'a mut usize,
2910 limits: ModuleCertificationLimits,
2911 module: &'a str,
2912}
2913
2914impl MeasurementNormalization<'_> {
2915 fn solve(
2916 &mut self,
2917 constraints: &[(SupportTarget, Pauli, bool)],
2918 ) -> Result<Option<Vec<usize>>, ModuleCertificationError> {
2919 let limit = self.limits.max_normalization_states;
2920 if *self.visited == limit {
2921 return Err(resource_limit(
2922 self.module,
2923 "measurement normalization states",
2924 self.visited.saturating_add(1),
2925 limit,
2926 ));
2927 }
2928 *self.visited += 1;
2929 let rows = self.adjustments.len();
2930 let columns = constraints.len();
2931 let bytes = rows.checked_mul(columns).and_then(|projection| {
2932 columns
2933 .checked_add(rows)?
2934 .checked_mul(columns.min(rows))?
2935 .checked_add(projection)?
2936 .checked_add(columns)?
2937 .checked_add(rows)
2938 });
2939 let words = bytes.map(|bytes| bytes.div_ceil(8));
2940 if words.is_none_or(|words| words > self.limits.max_matrix_words) {
2941 return Err(resource_limit(
2942 self.module,
2943 "dense matrix words",
2944 words.unwrap_or(usize::MAX),
2945 self.limits.max_matrix_words,
2946 ));
2947 }
2948 let projected = self
2949 .adjustments
2950 .iter()
2951 .map(|candidate| {
2952 constraints
2953 .iter()
2954 .map(|&(target, axis, _)| {
2955 pauli_component_parity(candidate.support.get(target), axis)
2956 })
2957 .collect::<Vec<_>>()
2958 })
2959 .collect::<Vec<_>>();
2960 let target = constraints
2961 .iter()
2962 .map(|&(_, _, value)| value)
2963 .collect::<Vec<_>>();
2964 Ok(solve_binary_combination(&projected, &target))
2965 }
2966
2967 fn constrain(
2968 &self,
2969 constraints: &mut Vec<(SupportTarget, Pauli, bool)>,
2970 target: SupportTarget,
2971 desired: Pauli,
2972 ) {
2973 constraints.extend([Pauli::X, Pauli::Z].map(|axis| {
2974 (
2975 target,
2976 axis,
2977 (self.row.support.get(target) ^ desired) & axis,
2978 )
2979 }));
2980 }
2981
2982 fn search(
2983 &mut self,
2984 factors: &[NormalizationFactor<'_>],
2985 constraints: &mut Vec<(SupportTarget, Pauli, bool)>,
2986 ) -> Result<Option<Vec<usize>>, ModuleCertificationError> {
2987 let mut point = NormalizationPoint::Factor(0);
2988 let mut frames = Vec::<NormalizationFrame<'_>>::new();
2989 let mut partial = Vec::new();
2990 loop {
2991 let combination = self.solve(constraints)?;
2992 if combination.is_some() {
2993 let next = match point {
2994 NormalizationPoint::Factor(index) => {
2995 let Some(factor) = factors.get(index) else {
2996 return Ok(combination);
2997 };
2998 let choices = match factor {
2999 NormalizationFactor::Site(constraint) => {
3000 let current = self.row.support.get(constraint.target);
3001 let mut values = match constraint.forbidden {
3002 Some(forbidden) => [Pauli::I, Pauli::X, Pauli::Z, Pauli::Y]
3003 .into_iter()
3004 .filter(|&pauli| pauli != forbidden)
3005 .collect::<Vec<_>>(),
3006 None => vec![current],
3007 };
3008 values.sort_by_key(|&pauli| pauli != current);
3009 NormalizationChoices::Site {
3010 target: constraint.target,
3011 values: values.into_iter(),
3012 }
3013 }
3014 NormalizationFactor::Group(group) => {
3015 let current = group
3016 .targets
3017 .iter()
3018 .map(|&target| self.row.support.get(target))
3019 .collect::<Vec<_>>();
3020 let permitted = current.iter().all(|&pauli| pauli == Pauli::I)
3021 || group
3022 .permitted_support
3023 .iter()
3024 .any(|support| partial_support_matches(¤t, support));
3025 NormalizationChoices::Group {
3026 group,
3027 current,
3028 permitted,
3029 next: 0,
3030 }
3031 }
3032 };
3033 Some((index, choices))
3034 }
3035 NormalizationPoint::Partial {
3036 factor,
3037 support,
3038 start,
3039 } => {
3040 let NormalizationFactor::Group(group) = factors[factor] else {
3041 unreachable!("partial choices belong to a group")
3042 };
3043 let chosen = &partial[start..];
3044 let template = &group.permitted_support[support];
3045 let repeated = group.permitted_support[..support].iter().any(|earlier| {
3046 partial_support_matches(chosen, earlier)
3047 && template[chosen.len()..] == earlier[chosen.len()..]
3048 });
3049 if repeated {
3050 None
3051 } else if chosen.len() == template.len() {
3052 if chosen.iter().any(|&pauli| pauli != Pauli::I)
3053 && chosen
3054 .iter()
3055 .zip(&group.targets)
3056 .any(|(&pauli, &target)| pauli != self.row.support.get(target))
3057 {
3058 point = NormalizationPoint::Factor(factor + 1);
3059 continue;
3060 }
3061 None
3062 } else {
3063 Some((
3064 factor,
3065 NormalizationChoices::Partial {
3066 group,
3067 support,
3068 start,
3069 next: 0,
3070 },
3071 ))
3072 }
3073 }
3074 };
3075 if let Some((factor, choices)) = next {
3076 frames.push(NormalizationFrame {
3077 factor,
3078 constraints: constraints.len(),
3079 partial: partial.len(),
3080 choices,
3081 });
3082 }
3083 }
3084 loop {
3087 let Some(frame) = frames.last_mut() else {
3088 return Ok(None);
3089 };
3090 constraints.truncate(frame.constraints);
3091 partial.truncate(frame.partial);
3092 let next = match &mut frame.choices {
3093 NormalizationChoices::Site { target, values } => values.next().map(|desired| {
3094 self.constrain(constraints, *target, desired);
3095 NormalizationPoint::Factor(frame.factor + 1)
3096 }),
3097 NormalizationChoices::Group {
3098 group,
3099 current,
3100 permitted,
3101 next,
3102 } => {
3103 let choice = *next;
3104 *next += 1;
3105 match choice {
3106 0 => {
3107 if !*permitted {
3108 continue;
3109 }
3110 for (&target, &desired) in group.targets.iter().zip(current.iter())
3111 {
3112 self.constrain(constraints, target, desired);
3113 }
3114 Some(NormalizationPoint::Factor(frame.factor + 1))
3115 }
3116 1 => {
3117 if current.iter().all(|&pauli| pauli == Pauli::I) {
3118 continue;
3119 }
3120 for &target in &group.targets {
3121 self.constrain(constraints, target, Pauli::I);
3122 }
3123 Some(NormalizationPoint::Factor(frame.factor + 1))
3124 }
3125 _ => group.permitted_support.get(choice - 2).map(|support| {
3126 constraints.extend(group.targets.iter().zip(support).map(
3129 |(&target, &basis)| {
3130 let axis = basis.flip();
3131 (
3132 target,
3133 axis,
3134 pauli_component_parity(
3135 self.row.support.get(target),
3136 axis,
3137 ),
3138 )
3139 },
3140 ));
3141 NormalizationPoint::Partial {
3142 factor: frame.factor,
3143 support: choice - 2,
3144 start: partial.len(),
3145 }
3146 }),
3147 }
3148 }
3149 NormalizationChoices::Partial {
3150 group,
3151 support,
3152 start,
3153 next,
3154 } => {
3155 let column = partial.len() - *start;
3156 let basis = group.permitted_support[*support][column];
3157 let desired = match *next {
3158 0 => Some(Pauli::I),
3159 1 if basis != Pauli::I => Some(basis),
3160 _ => None,
3161 };
3162 *next += 1;
3163 desired.map(|desired| {
3164 partial.push(desired);
3165 self.constrain(constraints, group.targets[column], desired);
3166 NormalizationPoint::Partial {
3167 factor: frame.factor,
3168 support: *support,
3169 start: *start,
3170 }
3171 })
3172 }
3173 };
3174 if let Some(next) = next {
3175 point = next;
3176 break;
3177 }
3178 frames.pop();
3179 }
3180 }
3181 }
3182}
3183
3184fn pauli_component_parity(pauli: Pauli, axes: Pauli) -> bool {
3185 ((pauli & Pauli::X) && (axes & Pauli::X)) ^ ((pauli & Pauli::Z) && (axes & Pauli::Z))
3186}
3187
3188fn partial_support_matches(partial: &[Pauli], support: &[Pauli]) -> bool {
3189 partial
3190 .iter()
3191 .zip(support)
3192 .all(|(&pauli, &basis)| pauli == Pauli::I || pauli == basis)
3193}
3194
3195fn normalize_measurement_rows(
3196 rows: &mut [SummaryMeasurement],
3197 adjustments: &[SupportedRow],
3198 protected: &[ProtectedSupport],
3199 protected_groups: &[ProtectedGroup],
3200 limits: ModuleCertificationLimits,
3201 module: &str,
3202) -> Result<(), ModuleCertificationError> {
3203 let mut visited = 0;
3204 for index in 0..rows.len() {
3205 if !matches!(rows[index].kind, StabilizerRowKind::Measurement { .. })
3206 || measurement_support_is_permitted(&rows[index], protected, protected_groups)
3207 {
3208 continue;
3209 }
3210
3211 let row = &rows[index];
3212 let grouped = protected_groups
3213 .iter()
3214 .flat_map(|group| group.targets.iter().copied())
3215 .collect::<FxHashSet<_>>();
3216 let choice_factors = protected_groups
3217 .iter()
3218 .map(NormalizationFactor::Group)
3219 .chain(
3220 protected
3221 .iter()
3222 .filter(|constraint| !grouped.contains(&constraint.target))
3223 .map(NormalizationFactor::Site),
3224 )
3225 .collect::<Vec<_>>();
3226
3227 let mut invariants = vec![(row.target, Pauli::X), (row.target, Pauli::Z)];
3228 invariants.extend(
3229 row.self_readers
3230 .iter()
3231 .copied()
3232 .flat_map(|target| [(target, Pauli::X), (target, Pauli::Z)]),
3233 );
3234 invariants.extend(
3235 rows.iter()
3236 .enumerate()
3237 .filter(|(other, _)| *other != index)
3238 .flat_map(|(_, other)| {
3239 other
3240 .observable
3241 .iter_xz()
3242 .map(move |axis| (other.target, axis))
3243 }),
3244 );
3245
3246 let mut constraints = invariants
3247 .into_iter()
3248 .map(|(target, axis)| (target, axis, false))
3249 .collect();
3250 let combination = MeasurementNormalization {
3251 row,
3252 adjustments,
3253 visited: &mut visited,
3254 limits,
3255 module,
3256 }
3257 .search(&choice_factors, &mut constraints)?
3258 .ok_or_else(|| {
3259 invalid(
3260 module,
3261 &format!(
3262 "measurement '{}' cannot normalize protected support after module composition",
3263 row.name
3264 ),
3265 )
3266 })?;
3267 let row = &mut rows[index];
3268 for adjustment in combination {
3269 multiply_measurement(row, &adjustments[adjustment]);
3270 }
3271 if !measurement_support_is_permitted(row, protected, protected_groups) {
3272 return Err(invalid(
3273 module,
3274 &format!(
3275 "measurement '{}' retains invalid protected support after module composition",
3276 row.name
3277 ),
3278 ));
3279 }
3280 }
3281 Ok(())
3282}
3283
3284fn measurement_support_is_permitted(
3285 row: &SummaryMeasurement,
3286 protected: &[ProtectedSupport],
3287 groups: &[ProtectedGroup],
3288) -> bool {
3289 protected
3290 .iter()
3291 .all(|constraint| constraint.forbidden != Some(row.support.get(constraint.target)))
3292 && groups.iter().all(|group| {
3293 let support = group
3294 .targets
3295 .iter()
3296 .map(|&target| row.support.get(target))
3297 .collect::<Vec<_>>();
3298 support.iter().all(|&pauli| pauli == Pauli::I)
3299 || group
3300 .permitted_support
3301 .iter()
3302 .any(|choice| partial_support_matches(&support, choice))
3303 })
3304}
3305
3306fn solve_binary_combination(rows: &[Vec<bool>], target: &[bool]) -> Option<Vec<usize>> {
3307 let mut basis = vec![None::<(Vec<bool>, Vec<bool>)>; target.len()];
3308 for (index, source) in rows.iter().enumerate() {
3309 let mut row = source.clone();
3310 let mut coeff = vec![false; rows.len()];
3311 coeff[index] = true;
3312 for column in 0..target.len() {
3313 if !row[column] {
3314 continue;
3315 }
3316 if let Some((pivot, pivot_coeff)) = &basis[column] {
3317 xor_bits(&mut row, pivot);
3318 xor_bits(&mut coeff, pivot_coeff);
3319 } else {
3320 basis[column] = Some((row, coeff));
3321 break;
3322 }
3323 }
3324 }
3325
3326 let mut residual = target.to_vec();
3327 let mut coeff = vec![false; rows.len()];
3328 for column in 0..target.len() {
3329 if !residual[column] {
3330 continue;
3331 }
3332 let (pivot, pivot_coeff) = basis[column].as_ref()?;
3333 xor_bits(&mut residual, pivot);
3334 xor_bits(&mut coeff, pivot_coeff);
3335 }
3336 residual.iter().all(|&bit| !bit).then(|| {
3337 coeff
3338 .iter()
3339 .enumerate()
3340 .filter_map(|(i, &set)| set.then_some(i))
3341 .collect()
3342 })
3343}
3344
3345fn xor_bits(left: &mut [bool], right: &[bool]) {
3346 for (left, &right) in left.iter_mut().zip(right) {
3347 *left ^= right;
3348 }
3349}
3350
3351fn instantiate_rows(
3356 rows: &[SupportedRow],
3357 instance: &ModuleInstance,
3358 port_positions: &FxHashSet<IVec3>,
3359 retained_targets: &[SupportTarget],
3360 module: &str,
3361) -> Result<Vec<SupportedRow>, ModuleCertificationError> {
3362 let shift = |source| ModuleCertificationError::Graph {
3363 module: module.to_string(),
3364 source,
3365 };
3366 let orientation = instance.orientation();
3367 rows.iter()
3368 .map(|row| {
3369 let mut row = row.clone();
3370 row.support.strip_ports(port_positions, retained_targets);
3371 row.witness.strip_positions(port_positions);
3372 row.witness = row
3373 .witness
3374 .transformed(orientation, instance.translation)
3375 .map_err(shift)?;
3376 row.support = row
3377 .support
3378 .transformed(orientation, instance.translation)
3379 .map_err(shift)?;
3380 Ok(row)
3381 })
3382 .collect()
3383}
3384
3385fn instantiate_measurements(
3386 measurements: &[SummaryMeasurement],
3387 instance: &ModuleInstance,
3388 port_positions: &[IVec3],
3389 retained_targets: &[SupportTarget],
3390 module: &str,
3391) -> Result<Vec<SummaryMeasurement>, ModuleCertificationError> {
3392 let port_position_set = port_positions.iter().copied().collect::<FxHashSet<_>>();
3393 let orientation = instance.orientation();
3394 let graph_error = |source| ModuleCertificationError::Graph {
3395 module: module.to_string(),
3396 source,
3397 };
3398 measurements
3399 .iter()
3400 .map(|measurement| {
3401 let mut measurement = measurement.clone();
3402 measurement.name = format!("{}__{}", instance.name, measurement.name);
3403 match &mut measurement.kind {
3404 StabilizerRowKind::Measurement { name } => {
3405 *name = measurement.name.clone();
3406 }
3407 StabilizerRowKind::SelectiveFixing { targets } => {
3408 for target in targets {
3409 target.pos = instance
3410 .try_transform_position(target.pos)
3411 .map_err(graph_error)?;
3412 }
3413 }
3414 StabilizerRowKind::Logical => {}
3415 }
3416 measurement
3417 .support
3418 .strip_ports(&port_position_set, retained_targets);
3419 measurement.witness.strip_positions(&port_position_set);
3420 measurement.witness = measurement
3421 .witness
3422 .transformed(orientation, instance.translation)
3423 .map_err(graph_error)?;
3424 measurement.support = measurement
3425 .support
3426 .transformed(orientation, instance.translation)
3427 .map_err(graph_error)?;
3428 measurement.target = measurement
3429 .target
3430 .transformed(orientation, instance.translation)
3431 .map_err(graph_error)?;
3432 measurement.self_readers = measurement
3433 .self_readers
3434 .iter()
3435 .map(|&target| {
3436 target
3437 .transformed(orientation, instance.translation)
3438 .map_err(graph_error)
3439 })
3440 .collect::<Result<Vec<_>, ModuleCertificationError>>()?;
3441 measurement.owned_positions = measurement
3442 .owned_positions
3443 .iter()
3444 .map(|&position| {
3445 orientation
3446 .try_transform_position(position, instance.translation)
3447 .map_err(graph_error)
3448 })
3449 .collect::<Result<FxHashSet<_>, ModuleCertificationError>>()?;
3450 Ok(measurement)
3451 })
3452 .collect()
3453}
3454
3455fn validate_composite_geometry(
3456 program: &BlockGraph,
3457 module: &BlockGraph,
3458) -> Result<(), ModuleCertificationError> {
3459 let mut footprint = CompositeFootprint::default();
3460 let mut next_branch = 0;
3461 add_module_footprint(
3462 program,
3463 module,
3464 (ModuleOrientation::IDENTITY, IVec3::ZERO),
3465 "",
3466 true,
3467 &mut footprint,
3468 &mut next_branch,
3469 )
3470 .map_err(|source| ModuleCertificationError::Graph {
3471 module: module.name.clone(),
3472 source,
3473 })
3474}
3475
3476struct FootprintOrigin {
3477 definition: String,
3478 instance_path: String,
3479 orientation: ModuleOrientation,
3480}
3481
3482#[derive(Clone)]
3483struct FootprintBlock {
3484 position: IVec3,
3485 kind: BlockKind,
3486 branch: Option<usize>,
3487 origin: Arc<FootprintOrigin>,
3488 local_position: IVec3,
3489}
3490
3491impl FootprintBlock {
3492 fn materialized_site(&self) -> Arc<crate::MaterializedModuleSite> {
3493 Arc::new(crate::MaterializedModuleSite {
3494 definition: self.origin.definition.clone(),
3495 instance_path: self.origin.instance_path.clone(),
3496 local_position: self.local_position,
3497 orientation: self.origin.orientation,
3498 })
3499 }
3500}
3501
3502#[derive(Default)]
3503struct CompositeFootprint {
3504 occupied: HashMap<IVec3, Vec<FootprintBlock>>,
3505}
3506
3507impl CompositeFootprint {
3508 fn add(
3509 &mut self,
3510 block: Block,
3511 branch: Option<usize>,
3512 origin: &Arc<FootprintOrigin>,
3513 local_position: IVec3,
3514 ) -> Result<(), crate::BlockGraphError> {
3515 let candidate = FootprintBlock {
3516 position: block.pos(),
3517 kind: block.kind(),
3518 branch,
3519 origin: Arc::clone(origin),
3520 local_position,
3521 };
3522 if let Some(other) = self
3523 .occupied
3524 .get(&block.pos())
3525 .into_iter()
3526 .flatten()
3527 .find(|other| {
3528 other.position == block.pos() && !mutually_exclusive(branch, other.branch)
3529 })
3530 {
3531 return Err(crate::BlockGraphError::ModuleBlockOverlap {
3532 position: block.pos(),
3533 first: other.materialized_site(),
3534 second: candidate.materialized_site(),
3535 });
3536 }
3537 let positions = block.checked_reserved_positions()?;
3538 for &position in &positions {
3539 if let Some(other) = self
3540 .occupied
3541 .get(&position)
3542 .into_iter()
3543 .flatten()
3544 .find(|other| {
3545 !mutually_exclusive(branch, other.branch)
3546 && !candidate.kind.allows_reserved_overlap(
3547 candidate.position,
3548 other.kind,
3549 other.position,
3550 position,
3551 )
3552 })
3553 {
3554 return Err(crate::BlockGraphError::ModuleBlockOverlap {
3555 position,
3556 first: other.materialized_site(),
3557 second: candidate.materialized_site(),
3558 });
3559 }
3560 }
3561 for position in positions {
3562 self.occupied
3563 .entry(position)
3564 .or_default()
3565 .push(candidate.clone());
3566 }
3567 Ok(())
3568 }
3569}
3570
3571fn mutually_exclusive(left: Option<usize>, right: Option<usize>) -> bool {
3572 left.is_some() && left == right
3573}
3574
3575fn add_module_footprint(
3576 program: &BlockGraph,
3577 definition: &BlockGraph,
3578 transform: (ModuleOrientation, IVec3),
3579 instance_path: &str,
3580 include_ports: bool,
3581 footprint: &mut CompositeFootprint,
3582 next_branch: &mut usize,
3583) -> Result<(), crate::BlockGraphError> {
3584 let definitions = program
3585 .modules()
3586 .map(|module| (module.name.as_str(), module))
3587 .collect::<HashMap<_, _>>();
3588 let mut pending = vec![(
3589 definition,
3590 transform,
3591 instance_path.to_string(),
3592 include_ports,
3593 )];
3594 while let Some((definition, (orientation, translation), instance_path, include_ports)) =
3595 pending.pop()
3596 {
3597 let origin = Arc::new(FootprintOrigin {
3598 definition: definition.name.clone(),
3599 instance_path: instance_path.to_string(),
3600 orientation,
3601 });
3602 definition
3603 .copy_local_geometry()
3604 .with_orientation_lenient(orientation)?;
3605 let regions = definition.local_body().branch_regions()?;
3606 let shown = regions
3607 .iter()
3608 .flat_map(|region| region.shown_arm().blocks().map(Block::pos))
3609 .collect::<FxHashSet<_>>();
3610 for block in definition
3611 .local_body()
3612 .blocks()
3613 .filter(|block| !shown.contains(&block.pos()))
3614 .filter(|block| include_ports || !block.kind().is_port())
3615 {
3616 footprint.add(
3617 crate::graph::oriented_block(block, orientation)?.try_with_shift(translation)?,
3618 None,
3619 &origin,
3620 block.pos(),
3621 )?;
3622 }
3623 for region in regions {
3624 let branch = *next_branch;
3625 *next_branch += 1;
3626 for block in region.on_false().blocks().chain(region.on_true().blocks()) {
3627 footprint.add(
3628 crate::graph::oriented_block(block, orientation)?
3629 .try_with_shift(translation)?,
3630 Some(branch),
3631 &origin,
3632 block.pos(),
3633 )?;
3634 }
3635 }
3636 for instance in definition.instances.iter().rev() {
3637 let child_translation =
3638 orientation.try_transform_position(instance.translation, translation)?;
3639 let child_orientation = orientation.then(instance.rotation);
3640 let child_path = qualified_name(&instance_path, &instance.name);
3641 pending.push((
3642 definitions[instance.definition.as_str()],
3643 (child_orientation, child_translation),
3644 child_path,
3645 false,
3646 ));
3647 }
3648 }
3649 Ok(())
3650}
3651
3652fn bind_seam(
3653 endpoint: &InstancePort,
3654 block: IVec3,
3655 hadamard: bool,
3656 transpose: bool,
3657 children: &HashMap<&str, (&ModuleInstance, Arc<ModuleSummary>)>,
3658) -> BindSeam {
3659 let mut signature = summarized_port(children, endpoint).signature;
3660 signature.hadamard ^= hadamard;
3661 BindSeam {
3662 endpoint: endpoint.clone(),
3663 block,
3664 signature,
3665 hadamard,
3666 transpose,
3667 }
3668}
3669
3670fn geometry_bind_seam(
3671 endpoint: &InstancePort,
3672 block: IVec3,
3673 hadamard: bool,
3674 transpose: bool,
3675 children: &HashMap<&str, (&ModuleInstance, ModuleGeometry)>,
3676) -> BindSeam {
3677 let mut signature = validated_port(children, endpoint).signature;
3678 signature.hadamard ^= hadamard;
3679 BindSeam {
3680 endpoint: endpoint.clone(),
3681 block,
3682 signature,
3683 hadamard,
3684 transpose,
3685 }
3686}
3687
3688fn geometry_direct_seam(
3689 output: &InstancePort,
3690 input: &InstancePort,
3691 hadamard: bool,
3692 children: &HashMap<&str, (&ModuleInstance, ModuleGeometry)>,
3693 module: &str,
3694) -> Result<bool, ModuleCertificationError> {
3695 direct_seam_hadamard_parts(
3696 validated_port(children, output),
3697 validated_port(children, input),
3698 hadamard,
3699 module,
3700 )
3701}
3702
3703fn direct_seam_hadamard(
3704 output: &InstancePort,
3705 input: &InstancePort,
3706 hadamard: bool,
3707 children: &HashMap<&str, (&ModuleInstance, Arc<ModuleSummary>)>,
3708 module: &str,
3709) -> Result<bool, ModuleCertificationError> {
3710 direct_seam_hadamard_parts(
3711 summarized_port(children, output),
3712 summarized_port(children, input),
3713 hadamard,
3714 module,
3715 )
3716}
3717
3718fn direct_seam_hadamard_parts(
3719 output: PortGeometry<'_>,
3720 input: PortGeometry<'_>,
3721 hadamard: bool,
3722 module: &str,
3723) -> Result<bool, ModuleCertificationError> {
3724 let output_pos = exposed_position(output.instance, output.port, output.signature)?;
3725 let input_pos = exposed_position(input.instance, input.port, input.signature)?;
3726 let direction = Direction::iter()
3727 .find(|direction| {
3728 checked_add_position(output_pos, direction.to_ivec3()).ok() == Some(input_pos)
3729 })
3730 .ok_or_else(|| invalid(module, "direct pipe endpoints are not adjacent"))?;
3731 if direction != output.signature.direction.negate() || direction != input.signature.direction {
3732 return Err(invalid(
3733 module,
3734 "direct pipe faces point in different directions",
3735 ));
3736 }
3737 if !compatible_bases(
3738 output.signature.interior_bases,
3739 input.signature.interior_bases,
3740 direction.as_udirection(),
3741 hadamard,
3742 ) {
3743 return Err(invalid(module, "direct pipe face bases are incompatible"));
3744 }
3745 Ok(output.signature.hadamard ^ hadamard ^ input.signature.hadamard)
3746}
3747
3748fn compose_child_seam(
3749 (output, input): (&InstancePort, &InstancePort),
3750 hadamard: bool,
3751 support_seam: SupportSeam,
3752 relations: &mut [Option<ChildRelation>],
3753 owners: &mut HashMap<InstancePort, usize>,
3754 limit: usize,
3755 module: &str,
3756) -> Result<(), ModuleCertificationError> {
3757 let output_owner = owners[output];
3758 let input_owner = owners[input];
3759 let width = relations[output_owner]
3760 .as_ref()
3761 .expect("live endpoint has a relation")
3762 .endpoints
3763 .len()
3764 + if input_owner == output_owner {
3765 0
3766 } else {
3767 relations[input_owner]
3768 .as_ref()
3769 .expect("live endpoint has a relation")
3770 .endpoints
3771 .len()
3772 };
3773 ensure_composition_width(module, width, limit)?;
3774
3775 let mut relation = relations[output_owner]
3776 .take()
3777 .expect("live endpoint has a relation");
3778 if input_owner != output_owner {
3779 let input_relation = relations[input_owner]
3780 .take()
3781 .expect("live endpoint has a relation");
3782 let output_width = relation.width();
3783 let mut combined = ChildRelation::default();
3784 combined.append(relation, &(0..output_width).collect::<Vec<_>>(), width);
3785 combined.append(
3786 input_relation,
3787 &(output_width..width).collect::<Vec<_>>(),
3788 width,
3789 );
3790 relation = combined;
3791 }
3792
3793 let left = relation
3794 .endpoints
3795 .iter()
3796 .position(|endpoint| endpoint == output)
3797 .expect("output endpoint belongs to its relation");
3798 let right = relation
3799 .endpoints
3800 .iter()
3801 .position(|endpoint| endpoint == input)
3802 .expect("input endpoint belongs to its relation");
3803 let retained = (0..width)
3804 .filter(|&column| column != left && column != right)
3805 .collect::<Vec<_>>();
3806 let seam = [(left, right, hadamard, true, support_seam)];
3807 for rows in [&mut relation.rows, &mut relation.logical_rows] {
3808 *rows = compose_supported_rows(
3809 std::mem::take(rows),
3810 &mut [],
3811 &[],
3812 &[],
3813 &seam,
3814 &retained,
3815 module,
3816 )?;
3817 }
3818 relation.certificate_rows =
3819 compose_certificate_rows(relation.certificate_rows, &seam, &retained);
3820 relation.adjustments = compose_supported_rows(
3821 relation.adjustments,
3822 &mut relation.measurements,
3823 &relation.protected,
3824 &relation.frontier,
3825 &seam,
3826 &retained,
3827 module,
3828 )?;
3829 for measurement in relation.discharged_measurements.iter_mut() {
3830 debug_assert!(measurement.signed.paulis.is_identity());
3831 measurement.signed.paulis = PauliString::new(retained.len());
3832 }
3833 relation
3834 .endpoints
3835 .retain(|endpoint| endpoint != output && endpoint != input);
3836
3837 owners.remove(output);
3838 owners.remove(input);
3839 for endpoint in &relation.endpoints {
3840 owners.insert(endpoint.clone(), output_owner);
3841 }
3842 relations[output_owner] = Some(relation);
3843 Ok(())
3844}
3845
3846fn ensure_composition_width(
3847 module: &str,
3848 width: usize,
3849 limit: usize,
3850) -> Result<(), ModuleCertificationError> {
3851 if width <= limit {
3852 Ok(())
3853 } else {
3854 Err(resource_limit(module, "composition columns", width, limit))
3855 }
3856}
3857
3858fn summarized_port<'a>(
3859 children: &'a HashMap<&str, (&ModuleInstance, Arc<ModuleSummary>)>,
3860 endpoint: &InstancePort,
3861) -> PortGeometry<'a> {
3862 let (instance, summary) = children
3863 .get(endpoint.instance.as_str())
3864 .map(|(instance, summary)| (*instance, summary.as_ref()))
3865 .expect("program validation resolved the child instance");
3866 let index = summary
3867 .port_index(&endpoint.port)
3868 .expect("program validation resolved the child port");
3869 PortGeometry {
3870 instance,
3871 port: &summary.ports[index],
3872 signature: summary.signatures[index].with_orientation(instance.orientation()),
3873 }
3874}
3875
3876fn validated_port<'a>(
3877 children: &'a HashMap<&str, (&ModuleInstance, ModuleGeometry)>,
3878 endpoint: &InstancePort,
3879) -> PortGeometry<'a> {
3880 let (instance, geometry) = children
3881 .get(endpoint.instance.as_str())
3882 .map(|(instance, geometry)| (*instance, geometry))
3883 .expect("program validation resolved the child instance");
3884 let index = geometry
3885 .ports
3886 .iter()
3887 .position(|port| port.name == endpoint.port)
3888 .expect("program validation resolved the child port");
3889 PortGeometry {
3890 instance,
3891 port: &geometry.ports[index],
3892 signature: geometry.signatures[index].with_orientation(instance.orientation()),
3893 }
3894}
3895
3896fn exposed_position(
3897 instance: &ModuleInstance,
3898 port: &QuantumPort,
3899 signature: ModulePortSignature,
3900) -> Result<IVec3, ModuleCertificationError> {
3901 instance
3902 .try_transform_position(port.position)
3903 .and_then(|position| checked_add_position(position, signature.direction.to_ivec3()))
3904 .map_err(|error| ModuleCertificationError::Graph {
3905 module: instance.name.clone(),
3906 source: error,
3907 })
3908}
3909
3910fn validate_bind_faces(
3911 module: &BlockGraph,
3912 binds: &[BindSeam],
3913) -> Result<(), ModuleCertificationError> {
3914 let mut used = FxHashSet::default();
3915 for bind in binds {
3916 let neighbor = checked_add_position(bind.block, bind.signature.direction.to_ivec3())
3917 .map_err(|source| ModuleCertificationError::Graph {
3918 module: module.name.clone(),
3919 source,
3920 })?;
3921 if module.local_body().has_pipe_between(bind.block, neighbor) {
3922 return Err(invalid(&module.name, "bind reuses an authored pipe face"));
3923 }
3924 if !used.insert((bind.block, bind.signature.direction)) {
3925 return Err(invalid(&module.name, "two binds reuse one block face"));
3926 }
3927 }
3928 Ok(())
3929}
3930
3931fn validate_bind_bases(
3932 module: &BlockGraph,
3933 body: &BlockGraph,
3934 binds: &[BindSeam],
3935) -> Result<(), ModuleCertificationError> {
3936 for bind in binds {
3937 let mut pipe = Pipe::new(bind.block, bind.signature.direction);
3938 if bind.signature.hadamard {
3939 pipe = pipe.with_hadamard();
3940 }
3941 let parent_bases = body.infer_pipe_endpoint_face_bases(&pipe, bind.block);
3942 if !compatible_bases(
3943 parent_bases,
3944 bind.signature.interior_bases,
3945 bind.signature.direction.as_udirection(),
3946 bind.signature.hadamard,
3947 ) {
3948 return Err(invalid(&module.name, "bind face bases are incompatible"));
3949 }
3950 }
3951 Ok(())
3952}
3953
3954fn parent_signatures(
3955 module: &BlockGraph,
3956 body: &BlockGraph,
3957 binds: &[BindSeam],
3958) -> Result<Vec<ModulePortSignature>, ModuleCertificationError> {
3959 module
3960 .interface
3961 .quantum_ports
3962 .iter()
3963 .map(|port| {
3964 let local = module.local_body().neighbor_positions(port.position);
3965 let bound = binds
3966 .iter()
3967 .filter(|bind| bind.block == port.position)
3968 .collect::<Vec<_>>();
3969 match (local.as_slice(), bound.as_slice()) {
3970 ([_], []) => port_signature(&module.name, body, port.position),
3971 ([], [bind]) => Ok(bind.signature),
3972 _ => Err(invalid(
3973 &module.name,
3974 "each exported Port must have one local or bound pipe",
3975 )),
3976 }
3977 })
3978 .collect()
3979}
3980
3981fn port_signature(
3982 module: &str,
3983 body: &BlockGraph,
3984 position: IVec3,
3985) -> Result<ModulePortSignature, ModuleCertificationError> {
3986 let neighbors = body.neighbor_positions(position);
3987 let [neighbor] = neighbors.as_slice() else {
3988 return Err(invalid(module, "module Port must have one pipe"));
3989 };
3990 let pipe = body
3991 .get_pipe(position, *neighbor)
3992 .expect("neighbor position names the incident pipe");
3993 let direction = if pipe.src() == position {
3994 pipe.dir()
3995 } else {
3996 pipe.dir().negate()
3997 };
3998 Ok(ModulePortSignature {
3999 direction,
4000 hadamard: pipe.is_hadamard(),
4001 interior_bases: body.infer_pipe_endpoint_face_bases(pipe, *neighbor),
4002 })
4003}
4004
4005fn compatible_bases(
4006 left: [Option<Basis>; 3],
4007 right: [Option<Basis>; 3],
4008 pipe_axis: UDirection,
4009 hadamard: bool,
4010) -> bool {
4011 (0..3)
4012 .filter(|&axis| axis != pipe_axis.index())
4013 .all(|axis| {
4014 !matches!(
4015 (left[axis], right[axis]),
4016 (Some(left), Some(right)) if (left != right) ^ hadamard
4017 )
4018 })
4019}
4020
4021fn embed_rows(rows: &[SupportedRow], mapping: &[usize], width: usize) -> Vec<SupportedRow> {
4022 rows.iter()
4023 .map(|row| SupportedRow {
4024 signed: embed_signed_row(&row.signed, mapping, width),
4025 support: row.support.clone(),
4026 witness: row.witness.clone(),
4027 })
4028 .collect()
4029}
4030
4031fn embed_signed_row(row: &PhasedPauliString, mapping: &[usize], width: usize) -> PhasedPauliString {
4032 PhasedPauliString::new(
4033 PauliString::from_terms(
4034 width,
4035 mapping
4036 .iter()
4037 .enumerate()
4038 .map(|(source, &target)| (target, row.paulis.get(source))),
4039 ),
4040 row.phase(),
4041 )
4042}
4043
4044struct FrontierRow {
4045 order: usize,
4046 row: SupportedRow,
4047}
4048
4049fn remap_row_columns(
4050 row: &mut SupportedRow,
4051 source_columns: Option<&[usize]>,
4052 target_columns: &[usize],
4053) {
4054 row.signed.paulis = PauliString::from_terms(
4056 target_columns.len(),
4057 row.signed
4058 .paulis
4059 .iter_support()
4060 .filter_map(|(source, pauli)| {
4061 let source = source_columns.map_or(source, |columns| columns[source]);
4062 target_columns
4063 .binary_search(&source)
4064 .ok()
4065 .map(|target| (target, pauli))
4066 }),
4067 );
4068}
4069
4070fn eliminate_frontier_seam(rows: &mut Vec<FrontierRow>, left: usize, right: usize) {
4071 let mut solved = 0;
4072 for axis in [Pauli::X, Pauli::Z] {
4073 let mismatch = |row: &FrontierRow| {
4074 (row.row.signed.paulis.get(left) ^ row.row.signed.paulis.get(right)) & axis
4075 };
4076 let Some(pivot) = (solved..rows.len()).find(|&row| mismatch(&rows[row])) else {
4077 continue;
4078 };
4079 rows.swap(pivot, solved);
4080 let (before, pivot_and_after) = rows.split_at_mut(solved);
4081 let (pivot, after) = pivot_and_after
4082 .split_first_mut()
4083 .expect("solved pivot is in bounds");
4084 let last_use = after
4085 .iter()
4086 .rposition(mismatch)
4087 .map(|index| before.len() + index);
4088 for (index, row) in before.iter_mut().chain(after).enumerate() {
4089 if mismatch(row) {
4090 if Some(index) == last_use {
4094 if row.row.support.weight() < pivot.row.support.weight() {
4095 std::mem::swap(&mut row.row.support, &mut pivot.row.support);
4096 }
4097 if row.row.witness.source_count() < pivot.row.witness.source_count() {
4098 std::mem::swap(&mut row.row.witness, &mut pivot.row.witness);
4099 }
4100 }
4101 EliminationRow::multiply_assign(&mut row.row, &pivot.row);
4102 }
4103 }
4104 solved += 1;
4105 }
4106 rows.drain(..solved);
4107}
4108
4109fn compose_frontier_rows(
4113 rows: Vec<SupportedRow>,
4114 seams: &[(usize, usize, bool, bool, SupportSeam)],
4115 retained: &[usize],
4116 keep_closed: impl Fn(&SupportedRow) -> bool,
4117) -> Vec<SupportedRow> {
4118 let Some(width) = rows.first().map(|row| row.signed.paulis.len()) else {
4119 return rows;
4120 };
4121 let mut seam_stage = vec![None; width];
4122 for (stage, &(left, right, ..)) in seams.iter().enumerate() {
4123 debug_assert!(seam_stage[left].is_none());
4124 debug_assert!(seam_stage[right].is_none());
4125 seam_stage[left] = Some(stage);
4126 seam_stage[right] = Some(stage);
4127 }
4128
4129 let mut pending = (0..seams.len())
4130 .map(|_| Vec::<FrontierRow>::new())
4131 .collect::<Vec<_>>();
4132 let mut finished = Vec::new();
4133 for (order, row) in rows.into_iter().enumerate() {
4134 let first_stage = row
4135 .signed
4136 .paulis
4137 .iter_support()
4138 .filter_map(|(column, _)| seam_stage[column])
4139 .min();
4140 let mut row = FrontierRow { order, row };
4141 if let Some(stage) = first_stage {
4142 pending[stage].push(row);
4143 } else {
4144 remap_row_columns(&mut row.row, None, retained);
4145 if !row.row.signed.paulis.is_identity() || keep_closed(&row.row) {
4146 finished.push(row);
4147 }
4148 }
4149 }
4150
4151 let mut active = Vec::<FrontierRow>::new();
4152 let mut columns = retained.to_vec();
4153 for (stage, &(left, right, hadamard, transpose, support_seam)) in seams.iter().enumerate() {
4154 let mut next_columns = retained.to_vec();
4155 next_columns.extend(active.iter().flat_map(|row| {
4156 row.row
4157 .signed
4158 .paulis
4159 .iter_support()
4160 .map(|(column, _)| columns[column])
4161 }));
4162 next_columns.extend(pending[stage].iter().flat_map(|row| {
4163 row.row
4164 .signed
4165 .paulis
4166 .iter_support()
4167 .map(|(column, _)| column)
4168 }));
4169 next_columns.extend([left, right]);
4170 next_columns.sort_unstable();
4171 next_columns.dedup();
4172
4173 for row in &mut active {
4174 remap_row_columns(&mut row.row, Some(&columns), &next_columns);
4175 }
4176 for row in &mut pending[stage] {
4177 remap_row_columns(&mut row.row, None, &next_columns);
4178 }
4179 active.append(&mut pending[stage]);
4180 active.sort_unstable_by_key(|row| row.order);
4181 columns = next_columns;
4182
4183 let left = columns
4184 .binary_search(&left)
4185 .expect("live frontier contains the seam's left column");
4186 let right = columns
4187 .binary_search(&right)
4188 .expect("live frontier contains the seam's right column");
4189 if hadamard {
4190 for row in &mut active {
4191 conjugate_supported_h(&mut row.row, right);
4192 }
4193 }
4194 eliminate_frontier_seam(&mut active, left, right);
4195 for row in &mut active {
4196 contract_supported_row(&mut row.row, left, right, transpose, support_seam);
4197 }
4198
4199 let mut next_active = Vec::with_capacity(active.len());
4200 for mut row in active.drain(..) {
4201 let reaches_future = row.row.signed.paulis.iter_support().any(|(column, _)| {
4202 seam_stage[columns[column]].is_some_and(|row_stage| row_stage > stage)
4203 });
4204 if reaches_future {
4205 next_active.push(row);
4206 } else {
4207 remap_row_columns(&mut row.row, Some(&columns), retained);
4208 if !row.row.signed.paulis.is_identity() || keep_closed(&row.row) {
4209 finished.push(row);
4210 }
4211 }
4212 }
4213 active = next_active;
4214 }
4215 debug_assert!(active.is_empty());
4216 debug_assert!(pending.iter().all(Vec::is_empty));
4217
4218 finished.sort_unstable_by_key(|row| row.order);
4219 finished.into_iter().map(|row| row.row).collect()
4220}
4221
4222fn compose_supported_rows(
4223 mut rows: Vec<SupportedRow>,
4224 measurements: &mut [SummaryMeasurement],
4225 protected: &[ProtectedSupport],
4226 frontier: &[SupportTarget],
4227 seams: &[(usize, usize, bool, bool, SupportSeam)],
4228 retained: &[usize],
4229 module: &str,
4230) -> Result<Vec<SupportedRow>, ModuleCertificationError> {
4231 if measurements.is_empty() && seams.len() > 1 {
4232 rows = compose_frontier_rows(rows, seams, retained, |row| {
4233 protected
4234 .iter()
4235 .any(|constraint| row.support.get(constraint.target) != Pauli::I)
4236 || frontier
4237 .iter()
4238 .any(|&target| row.support.get(target) != Pauli::I)
4239 });
4240 } else {
4241 for &(left, right, hadamard, transpose, support_seam) in seams {
4242 if hadamard {
4243 for row in &mut rows {
4244 conjugate_supported_h(row, right);
4245 }
4246 for measurement in &mut *measurements {
4247 conjugate_measurement_h(measurement, right);
4248 }
4249 }
4250
4251 if !measurements.is_empty() {
4252 let mut adjustment_basis = AdjustmentBasis::new(&rows, measurements, protected);
4253 for index in 0..measurements.len() {
4254 let mut candidates = safe_adjustments(
4255 &mut adjustment_basis,
4256 measurements,
4257 index,
4258 protected,
4259 module,
4260 )?;
4261 let measurement = &mut measurements[index];
4262 eliminate_supported_seam(
4263 &mut candidates,
4264 std::slice::from_mut(measurement),
4265 left,
4266 right,
4267 );
4268 if measurement.signed.paulis.get(left) != measurement.signed.paulis.get(right) {
4269 return Err(invalid(
4270 module,
4271 &format!(
4272 "measurement '{}' cannot close across a module seam",
4273 measurement.name
4274 ),
4275 ));
4276 }
4277 }
4278 }
4279
4280 let eliminated = eliminate_supported_seam(&mut rows, &mut [], left, right);
4281 rows.drain(..eliminated);
4282
4283 for row in &mut rows {
4284 contract_supported_row(row, left, right, transpose, support_seam);
4285 }
4286 rows.retain(|row| {
4287 !row.signed.paulis.is_identity()
4288 || measurements.iter().any(|measurement| {
4289 row.support.get(measurement.target) != Pauli::I
4290 || measurement
4291 .self_readers
4292 .iter()
4293 .any(|&target| row.support.get(target) != Pauli::I)
4294 })
4295 || protected
4296 .iter()
4297 .any(|constraint| row.support.get(constraint.target) != Pauli::I)
4298 || frontier
4299 .iter()
4300 .any(|&target| row.support.get(target) != Pauli::I)
4301 });
4302 for measurement in &mut *measurements {
4303 contract_measurement(measurement, left, right, transpose, support_seam);
4304 }
4305 }
4306
4307 for row in &mut rows {
4308 remap_row_columns(row, None, retained);
4309 }
4310 }
4311 let mut rank = signed_gaussian_elimination(
4312 &mut rows,
4313 (0..retained.len()).flat_map(|column| [Pauli::X, Pauli::Z].map(move |axis| (column, axis))),
4314 |row, &(column, axis)| row.signed.paulis.get(column) & axis,
4315 );
4316 if rank < rows.len() {
4317 let mut targets = measurements
4318 .iter()
4319 .map(|measurement| measurement.target)
4320 .chain(
4321 measurements
4322 .iter()
4323 .flat_map(|measurement| measurement.self_readers.iter().copied()),
4324 )
4325 .chain(protected.iter().map(|constraint| constraint.target))
4326 .chain(frontier.iter().copied())
4327 .collect::<FxHashSet<_>>()
4328 .into_iter()
4329 .collect::<Vec<_>>();
4330 targets.sort_unstable_by_key(support_target_key);
4331 rank = eliminate_support_targets(&mut rows, rank, &targets);
4332 }
4333 rows.truncate(rank);
4334 for measurement in measurements {
4335 measurement.signed.paulis = PauliString::from_terms(
4336 retained.len(),
4337 retained
4338 .iter()
4339 .enumerate()
4340 .map(|(target, &source)| (target, measurement.signed.paulis.get(source))),
4341 );
4342 }
4343 Ok(rows)
4344}
4345
4346fn compose_certificate_rows(
4349 mut rows: Vec<SupportedRow>,
4350 seams: &[(usize, usize, bool, bool, SupportSeam)],
4351 retained: &[usize],
4352) -> Vec<SupportedRow> {
4353 if seams.len() > 1 {
4354 rows = compose_frontier_rows(rows, seams, retained, |row| row.support.weight() != 0);
4355 } else {
4356 for &(left, right, hadamard, transpose, support_seam) in seams {
4357 if hadamard {
4358 for row in &mut rows {
4359 conjugate_supported_h(row, right);
4360 }
4361 }
4362 let eliminated = eliminate_supported_seam(&mut rows, &mut [], left, right);
4363 rows.drain(..eliminated);
4364 for row in &mut rows {
4365 contract_supported_row(row, left, right, transpose, support_seam);
4366 }
4367 }
4368 for row in &mut rows {
4369 remap_row_columns(row, None, retained);
4370 }
4371 rows.retain(|row| !row.signed.paulis.is_identity() || row.support.weight() != 0);
4372 }
4373
4374 let boundary_rank = signed_gaussian_elimination(
4375 &mut rows,
4376 (0..retained.len()).flat_map(|column| [Pauli::X, Pauli::Z].map(move |axis| (column, axis))),
4377 |row, &(column, axis)| row.signed.paulis.get(column) & axis,
4378 );
4379 if !seams.is_empty() || boundary_rank == rows.len() {
4383 return rows;
4384 }
4385 let mut targets = rows
4386 .iter()
4387 .flat_map(|row| {
4388 row.support
4389 .nodes
4390 .keys()
4391 .copied()
4392 .map(SupportTarget::Node)
4393 .chain(
4394 row.support
4395 .edges
4396 .keys()
4397 .copied()
4398 .map(|(left, right)| SupportTarget::Edge(left, right)),
4399 )
4400 })
4401 .collect::<FxHashSet<_>>()
4402 .into_iter()
4403 .collect::<Vec<_>>();
4404 targets.sort_unstable_by_key(support_target_key);
4405 let rank = eliminate_support_targets(&mut rows, boundary_rank, &targets);
4406 rows.truncate(rank);
4407 rows
4408}
4409
4410fn eliminate_support_targets(
4412 rows: &mut [SupportedRow],
4413 solved: usize,
4414 targets: &[SupportTarget],
4415) -> usize {
4416 if targets.is_empty() {
4417 return solved;
4418 }
4419 let columns: FxHashMap<_, _> = targets
4420 .iter()
4421 .copied()
4422 .enumerate()
4423 .map(|(column, target)| (target, column))
4424 .collect();
4425 debug_assert_eq!(columns.len(), targets.len(), "support targets are unique");
4426 leading_pivot_elimination_from(
4427 rows,
4428 solved,
4429 |row| {
4430 let present = row
4431 .support
4432 .nodes
4433 .keys()
4434 .copied()
4435 .map(SupportTarget::Node)
4436 .chain(row.support.edges.keys().flat_map(|&(left, right)| {
4437 [
4438 SupportTarget::Edge(left, right),
4439 SupportTarget::Edge(right, left),
4440 ]
4441 }));
4442 present
4443 .filter_map(|target| {
4444 let &column = columns.get(&target)?;
4445 let pauli = row.support.get(target);
4446 (pauli != Pauli::I)
4447 .then_some((column, if pauli & Pauli::X { Pauli::X } else { Pauli::Z }))
4448 })
4449 .min_by_key(|&(column, axis)| (column, axis == Pauli::Z))
4450 },
4451 |row, &(column, axis)| row.support.get(targets[column]) & axis,
4452 )
4453}
4454
4455struct AdjustmentBasis<'a> {
4458 sources: Vec<&'a SupportedRow>,
4459 candidates: Vec<PhasedPauliString>,
4460 columns: FxHashMap<SupportTarget, usize>,
4461 boundary_width: usize,
4462 selector_start: usize,
4463 prefix_rank: usize,
4464 next_measurement: usize,
4465}
4466
4467impl<'a> AdjustmentBasis<'a> {
4468 fn new(
4469 rows: &'a [SupportedRow],
4470 measurements: &[SummaryMeasurement],
4471 protected: &[ProtectedSupport],
4472 ) -> Self {
4473 let mut sources = rows.iter().collect::<Vec<_>>();
4474 sources.sort_by_key(|row| row.support.weight());
4475 let boundary_width = sources.first().map_or(0, |row| row.signed.paulis.len());
4476 let mut targets = measurements
4477 .iter()
4478 .flat_map(|measurement| {
4479 std::iter::once(measurement.target).chain(measurement.self_readers.iter().copied())
4480 })
4481 .chain(protected.iter().map(|constraint| constraint.target))
4482 .collect::<Vec<_>>();
4483 targets.sort_unstable_by_key(support_target_key);
4484 targets.dedup();
4485 let selector_start = boundary_width + 2 * targets.len();
4488 let candidates = sources
4489 .iter()
4490 .enumerate()
4491 .map(|(source, row)| {
4492 let mut paulis = PauliString::from_terms(
4493 selector_start + sources.len(),
4494 row.signed.paulis.iter_support(),
4495 );
4496 for (column, &target) in targets.iter().enumerate() {
4497 let value = row.support.get(target);
4498 for (offset, axis) in [Pauli::X, Pauli::Z].into_iter().enumerate() {
4499 if value & axis {
4500 paulis.set(boundary_width + 2 * column + offset, Pauli::X);
4501 }
4502 }
4503 }
4504 paulis.set(selector_start + source, Pauli::X);
4505 PhasedPauliString::new(paulis, row.signed.phase())
4506 })
4507 .collect();
4508 let columns = targets
4509 .into_iter()
4510 .enumerate()
4511 .map(|(column, target)| (target, boundary_width + 2 * column))
4512 .collect();
4513 Self {
4514 sources,
4515 candidates,
4516 columns,
4517 boundary_width,
4518 selector_start,
4519 prefix_rank: 0,
4520 next_measurement: 0,
4521 }
4522 }
4523}
4524
4525fn safe_adjustments(
4526 basis: &mut AdjustmentBasis<'_>,
4527 measurements: &[SummaryMeasurement],
4528 index: usize,
4529 protected: &[ProtectedSupport],
4530 module: &str,
4531) -> Result<Vec<SupportedRow>, ModuleCertificationError> {
4532 debug_assert_eq!(index, basis.next_measurement);
4533 let measurement = &measurements[index];
4534 let mut constraints = measurements
4535 .iter()
4536 .enumerate()
4537 .skip(index)
4538 .flat_map(|(other, candidate)| {
4539 let axes = if other == index {
4540 Pauli::Y
4541 } else {
4542 candidate.observable
4543 };
4544 axes.iter_xz().map(move |axis| (candidate.target, axis))
4545 })
4546 .collect::<Vec<_>>();
4547 constraints.extend(
4548 measurement
4549 .self_readers
4550 .iter()
4551 .copied()
4552 .flat_map(|target| [(target, Pauli::X), (target, Pauli::Z)]),
4553 );
4554 constraints.extend(
4557 measurement
4558 .kind
4559 .selective_fixing_targets()
4560 .iter()
4561 .flat_map(|target| {
4562 [Pauli::X, Pauli::Z].map(|axis| (SupportTarget::Node(target.pos), axis))
4563 }),
4564 );
4565 for constraint in protected {
4566 if measurement
4567 .kind
4568 .selective_fixing_targets()
4569 .iter()
4570 .any(|target| SupportTarget::Node(target.pos) == constraint.target)
4571 {
4572 continue;
4573 }
4574 if let Some(forbidden) = constraint.forbidden {
4575 let difference = measurement.support.get(constraint.target) ^ forbidden;
4576 let Some(axis) = difference.iter_xz().next() else {
4577 return Err(invalid(
4578 module,
4579 &format!(
4580 "measurement '{}' has forbidden selective support",
4581 measurement.name
4582 ),
4583 ));
4584 };
4585 constraints.push((constraint.target, axis));
4586 } else {
4587 constraints.extend([(constraint.target, Pauli::X), (constraint.target, Pauli::Z)]);
4588 }
4589 }
4590
4591 let sources = &basis.sources;
4592 let boundary_width = basis.boundary_width;
4593 let selector_start = basis.selector_start;
4594 let mut candidates = basis.candidates.clone();
4595 let eliminated = signed_gaussian_elimination_from(
4596 &mut candidates,
4597 basis.prefix_rank,
4598 constraints
4599 .into_iter()
4600 .map(|(target, axis)| basis.columns[&target] + usize::from(axis == Pauli::Z)),
4601 |row, &column| row.paulis.get(column) == Pauli::X,
4602 );
4603 let mut candidates = candidates
4604 .into_iter()
4605 .skip(eliminated)
4606 .map(|row| {
4607 let mut support = PositionedSupport::default();
4608 let mut witness = FlowWitness::default();
4609 for (column, _) in row
4610 .paulis
4611 .iter_support()
4612 .filter(|&(column, _)| column >= selector_start)
4613 {
4614 let source = sources[column - selector_start];
4615 support.multiply_assign(&source.support);
4616 witness.xor_assign(&source.witness);
4617 }
4618 SupportedRow {
4619 signed: PhasedPauliString::new(
4620 PauliString::from_terms(
4621 boundary_width,
4622 (0..boundary_width).map(|column| (column, row.paulis.get(column))),
4623 ),
4624 row.phase(),
4625 ),
4626 support,
4627 witness,
4628 }
4629 })
4630 .collect::<Vec<_>>();
4631 candidates.sort_by_key(|row| row.support.weight());
4632 let column = basis.columns[&measurement.target];
4635 basis.prefix_rank = signed_gaussian_elimination_from(
4636 &mut basis.candidates,
4637 basis.prefix_rank,
4638 measurement
4639 .observable
4640 .iter_xz()
4641 .map(|axis| column + usize::from(axis == Pauli::Z)),
4642 |row, &column| row.paulis.get(column) == Pauli::X,
4643 );
4644 basis.next_measurement += 1;
4645 Ok(candidates)
4646}
4647
4648fn eliminate_supported_seam(
4649 rows: &mut [SupportedRow],
4650 measurements: &mut [SummaryMeasurement],
4651 left: usize,
4652 right: usize,
4653) -> usize {
4654 let mut solved = 0;
4655 for axis in [Pauli::X, Pauli::Z] {
4656 let mismatch = |row: &SupportedRow| {
4657 (row.signed.paulis.get(left) ^ row.signed.paulis.get(right)) & axis
4658 };
4659 let Some(pivot) = (solved..rows.len()).find(|&row| mismatch(&rows[row])) else {
4660 continue;
4661 };
4662 rows.swap(pivot, solved);
4663 let (before, pivot_and_after) = rows.split_at_mut(solved);
4664 let (pivot, after) = pivot_and_after
4665 .split_first_mut()
4666 .expect("solved pivot is in bounds");
4667 for row in before.iter_mut().chain(after) {
4668 if mismatch(row) {
4669 EliminationRow::multiply_assign(row, pivot);
4670 }
4671 }
4672 for measurement in &mut *measurements {
4673 if (measurement.signed.paulis.get(left) ^ measurement.signed.paulis.get(right)) & axis {
4674 multiply_measurement(measurement, pivot);
4675 }
4676 }
4677 solved += 1;
4678 }
4679 solved
4680}
4681
4682impl EliminationRow for SupportedRow {
4683 fn multiply_assign(&mut self, pivot: &Self) {
4684 self.signed.multiply_assign(&pivot.signed);
4685 self.support.multiply_assign(&pivot.support);
4686 self.witness.xor_assign(&pivot.witness);
4687 }
4688}
4689
4690fn conjugate_supported_h(row: &mut SupportedRow, column: usize) {
4691 row.signed.conjugate_h(column);
4692}
4693
4694fn multiply_measurement(measurement: &mut SummaryMeasurement, row: &SupportedRow) {
4695 measurement.signed.multiply_assign(&row.signed);
4696 measurement.support.multiply_assign(&row.support);
4697 measurement.witness.xor_assign(&row.witness);
4698}
4699
4700fn conjugate_measurement_h(measurement: &mut SummaryMeasurement, column: usize) {
4701 measurement.signed.conjugate_h(column);
4702}
4703
4704fn contract_supported_row(
4705 row: &mut SupportedRow,
4706 left: usize,
4707 right: usize,
4708 transpose: bool,
4709 seam: SupportSeam,
4710) {
4711 let pauli = row.signed.paulis.get(left);
4712 if transpose && pauli == Pauli::Y {
4713 row.signed.shift_phase(2);
4714 }
4715 row.signed.paulis.set(left, Pauli::I);
4716 row.signed.paulis.set(right, Pauli::I);
4717 let seam_phase = row.support.add_seam(seam, pauli);
4718 row.signed.shift_phase(seam_phase);
4719}
4720
4721fn contract_measurement(
4722 measurement: &mut SummaryMeasurement,
4723 left: usize,
4724 right: usize,
4725 transpose: bool,
4726 seam: SupportSeam,
4727) {
4728 let pauli = measurement.signed.paulis.get(left);
4729 if transpose && pauli == Pauli::Y {
4730 measurement.signed.shift_phase(2);
4731 }
4732 measurement.signed.paulis.set(left, Pauli::I);
4733 measurement.signed.paulis.set(right, Pauli::I);
4734 let seam_phase = measurement.support.add_seam(seam, pauli);
4735 measurement.signed.shift_phase(seam_phase);
4736}
4737
4738fn invalid(module: &str, message: &str) -> ModuleCertificationError {
4739 ModuleCertificationError::InvalidConnection {
4740 module: module.to_string(),
4741 message: message.to_string(),
4742 }
4743}
4744
4745#[cfg(test)]
4746mod certificate_tests {
4747 use super::*;
4748 use crate::{Expr, FeedbackTarget, GalleryItem};
4749
4750 #[test]
4751 fn discarded_seam_pivot_preserves_signed_order_and_support_cancellation() {
4752 let edge = (IVec3::ZERO, IVec3::Z);
4753 let support =
4754 |nodes: &[(IVec3, Pauli)], edges: &[((IVec3, IVec3), Pauli)]| PositionedSupport {
4755 nodes: nodes.iter().copied().collect(),
4756 edges: edges.iter().copied().collect(),
4757 };
4758 let row = |order, pauli, support| FrontierRow {
4759 order,
4760 row: SupportedRow {
4761 signed: PhasedPauliString::positive(PauliString::from_terms(
4762 3,
4763 [(0, Pauli::X), (2, pauli)],
4764 )),
4765 support,
4766 witness: FlowWitness::default(),
4767 },
4768 };
4769 let mut rows = vec![
4770 row(
4771 0,
4772 Pauli::X,
4773 support(
4774 &[(IVec3::ZERO, Pauli::X), (IVec3::X, Pauli::X)],
4775 &[(edge, Pauli::Z)],
4776 ),
4777 ),
4778 row(
4779 1,
4780 Pauli::Z,
4781 support(&[(IVec3::ZERO, Pauli::Z)], &[(edge, Pauli::Z)]),
4782 ),
4783 row(2, Pauli::Y, support(&[(IVec3::ZERO, Pauli::X)], &[])),
4784 ];
4785 eliminate_frontier_seam(&mut rows, 0, 1);
4786 assert_eq!(rows.len(), 2);
4787 for (actual, (order, phase, pauli)) in rows.iter().zip([(1, 1, Pauli::Y), (2, 3, Pauli::Z)])
4790 {
4791 assert_eq!(actual.order, order);
4792 assert_eq!(
4793 actual.row.signed,
4794 PhasedPauliString::new(PauliString::from_terms(3, [(2, pauli)]), phase)
4795 );
4796 }
4797 assert_eq!(
4798 rows[0].row.support.nodes,
4799 FxHashMap::from_iter([(IVec3::ZERO, Pauli::Y), (IVec3::X, Pauli::X)])
4800 );
4801 assert!(rows[0].row.support.edges.is_empty());
4802 assert_eq!(
4803 rows[1].row.support.nodes,
4804 FxHashMap::from_iter([(IVec3::X, Pauli::X)])
4805 );
4806 assert_eq!(
4807 rows[1].row.support.edges,
4808 FxHashMap::from_iter([(edge, Pauli::Z)])
4809 );
4810 }
4811
4812 fn test_measurement(
4813 boundary: PauliString,
4814 support: PositionedSupport,
4815 target: SupportTarget,
4816 ) -> SummaryMeasurement {
4817 SummaryMeasurement {
4818 name: "m".into(),
4819 kind: StabilizerRowKind::Measurement { name: "m".into() },
4820 signed: PhasedPauliString::positive(boundary),
4821 support,
4822 witness: FlowWitness::default(),
4823 target,
4824 observable: Pauli::Z,
4825 self_readers: Vec::new(),
4826 owned_positions: FxHashSet::default(),
4827 }
4828 }
4829
4830 fn test_supported_rows(seed: u32) -> Vec<SupportedRow> {
4831 (0..9u32)
4832 .map(|index| {
4833 let bits = seed
4834 .wrapping_mul(0x9e37_79b9)
4835 .wrapping_add(index.wrapping_mul(0x85eb_ca6b));
4836 let pauli = |shift| {
4837 [Pauli::I, Pauli::X, Pauli::Z, Pauli::Y][((bits >> shift) & 3) as usize]
4838 };
4839 SupportedRow {
4840 signed: PhasedPauliString::new(
4841 PauliString::from_terms(
4842 3,
4843 (0..3).map(|column| (column, pauli(2 * column))),
4844 ),
4845 (bits >> 18) as u8,
4846 ),
4847 support: PositionedSupport {
4848 nodes: [IVec3::ZERO, IVec3::Y, IVec3::Z]
4849 .into_iter()
4850 .enumerate()
4851 .map(|(i, position)| (position, pauli(6 + i * 2)))
4852 .filter(|&(_, pauli)| pauli != Pauli::I)
4853 .collect(),
4854 edges: [((IVec3::X, IVec3::X * 2), pauli(12))]
4855 .into_iter()
4856 .filter(|&(_, pauli)| pauli != Pauli::I)
4857 .collect(),
4858 },
4859 witness: FlowWitness::default(),
4860 }
4861 })
4862 .collect()
4863 }
4864
4865 #[test]
4866 fn joining_a_port_preserves_the_record_on_its_edge() {
4867 let edge = (IVec3::ZERO, IVec3::X);
4868 let target = SupportTarget::Edge(edge.0, edge.1);
4869 let support = PositionedSupport {
4870 edges: [(edge, Pauli::Z)].into_iter().collect(),
4871 ..PositionedSupport::default()
4872 };
4873 let mut measurements = [test_measurement(
4874 PauliString::from_terms(2, [(0, Pauli::Z)]),
4875 support.clone(),
4876 target,
4877 )];
4878 measurements[0].observable = Pauli::Z;
4879 let mut rows = vec![
4880 SupportedRow {
4881 signed: measurements[0].signed.clone(),
4882 support,
4883 witness: FlowWitness::default(),
4884 },
4885 SupportedRow {
4886 signed: PhasedPauliString::positive(PauliString::from_terms(2, [(1, Pauli::Z)])),
4887 support: PositionedSupport::default(),
4888 witness: FlowWitness::default(),
4889 },
4890 ];
4891 let ports = [edge.0].into_iter().collect();
4892 for row in &mut rows {
4893 row.support.strip_ports(&ports, &[target]);
4894 }
4895 measurements[0].support.strip_ports(&ports, &[target]);
4896 compose_supported_rows(
4897 rows,
4898 &mut measurements,
4899 &[],
4900 &[],
4901 &[(
4902 0,
4903 1,
4904 false,
4905 false,
4906 SupportSeam {
4907 edge,
4908 boundary_to_edge_hadamard: false,
4909 },
4910 )],
4911 &[],
4912 "test",
4913 )
4914 .unwrap();
4915 assert_eq!(measurements[0].support.get(target), Pauli::Z);
4916 }
4917
4918 #[test]
4919 fn seam_adjustments_preserve_every_joint_fixing_target() {
4920 let positions = [IVec3::ZERO, IVec3::X];
4921 let protected = positions.map(|pos| ProtectedSupport {
4922 target: SupportTarget::Node(pos),
4923 forbidden: Some(Pauli::Y),
4924 });
4925 let mut fixing = test_measurement(
4926 PauliString::new(1),
4927 PositionedSupport {
4928 nodes: positions.into_iter().map(|pos| (pos, Pauli::Y)).collect(),
4929 ..PositionedSupport::default()
4930 },
4931 protected[0].target,
4932 );
4933 fixing.kind = StabilizerRowKind::SelectiveFixing {
4934 targets: positions
4935 .map(|pos| crate::SelectiveFixingTarget {
4936 pos,
4937 forbidden: Pauli::Y,
4938 })
4939 .to_vec(),
4940 };
4941 fixing.observable = Pauli::I;
4942 let adjustments = [SupportedRow {
4943 signed: PhasedPauliString::positive(PauliString::from_terms(1, [(0, Pauli::X)])),
4944 support: PositionedSupport {
4945 nodes: FxHashMap::from_iter([(positions[1], Pauli::Z)]),
4946 ..PositionedSupport::default()
4947 },
4948 witness: FlowWitness::default(),
4949 }];
4950 let measurements = [fixing];
4951 let mut basis = AdjustmentBasis::new(&adjustments, &measurements, &protected);
4952 let safe = safe_adjustments(&mut basis, &measurements, 0, &protected, "test").unwrap();
4953 assert!(
4954 safe.is_empty(),
4955 "adjustment would change the second cap from Y to X"
4956 );
4957 }
4958
4959 #[test]
4960 fn cached_support_targets_preserve_signed_rows_and_witnesses() {
4961 let summary = GalleryItem::GHZ
4962 .build()
4963 .summarize_root(ModuleCertificationLimits::DEFAULT)
4964 .unwrap();
4965 assert!(
4966 summary
4967 .certificate_rows
4968 .iter()
4969 .any(|row| row.witness.source_count() != 0)
4970 );
4971 let mut targets = [IVec3::ZERO, IVec3::Y, IVec3::Z]
4972 .into_iter()
4973 .map(SupportTarget::Node)
4974 .chain((0..70).map(|x| SupportTarget::Node(IVec3::new(x, 10, 0))))
4975 .chain([
4976 SupportTarget::Edge(IVec3::X, IVec3::X * 2),
4977 SupportTarget::Edge(IVec3::X * 2, IVec3::X),
4978 ])
4979 .collect::<Vec<_>>();
4980 targets.sort_unstable_by_key(support_target_key);
4981 for seed in 0..64 {
4982 for reverse_edges in [false, true] {
4983 let mut rows = test_supported_rows(seed);
4984 for (row, source) in rows.iter_mut().zip(summary.certificate_rows.iter().cycle()) {
4985 row.witness = source.witness.clone();
4986 if reverse_edges {
4987 row.support.edges = row
4988 .support
4989 .edges
4990 .drain()
4991 .map(|((left, right), value)| ((right, left), value))
4992 .collect();
4993 }
4994 }
4995 let solved = signed_gaussian_elimination(
4996 &mut rows,
4997 (0..3).flat_map(|column| [Pauli::X, Pauli::Z].map(move |axis| (column, axis))),
4998 |row, &(column, axis)| row.signed.paulis.get(column) & axis,
4999 );
5000 for targets in [&targets[..0], &targets[..3], targets.as_slice()] {
5001 let mut expected = rows.clone();
5002 let expected_rank = signed_gaussian_elimination_from(
5003 &mut expected,
5004 solved,
5005 targets.iter().copied().flat_map(|target| {
5006 [Pauli::X, Pauli::Z].map(move |axis| (target, axis))
5007 }),
5008 |row, &(target, axis)| row.support.get(target) & axis,
5009 );
5010 let mut actual = rows.clone();
5011 assert_eq!(
5012 eliminate_support_targets(&mut actual, solved, targets),
5013 expected_rank
5014 );
5015 for (actual, expected) in actual.iter().zip(&expected) {
5016 assert_eq!(actual.signed, expected.signed, "seed {seed}");
5017 assert_eq!(actual.support.nodes, expected.support.nodes, "seed {seed}");
5018 assert_eq!(actual.support.edges, expected.support.edges, "seed {seed}");
5019 let mut difference = actual.witness.clone();
5020 difference.xor_assign(&expected.witness);
5021 assert_eq!(difference.source_count(), 0, "seed {seed}");
5022 }
5023 }
5024 }
5025 }
5026 }
5027
5028 #[test]
5029 fn packed_adjustments_match_eager_signed_elimination() {
5030 let target = SupportTarget::Node(IVec3::ZERO);
5031 let edge = SupportTarget::Edge(IVec3::X, IVec3::X * 2);
5032 let reader = SupportTarget::Node(IVec3::Z);
5033 let protected = [ProtectedSupport {
5034 target: SupportTarget::Node(IVec3::Y),
5035 forbidden: None,
5036 }];
5037 let mut measurements = [
5038 test_measurement(PauliString::new(3), PositionedSupport::default(), target),
5039 test_measurement(PauliString::new(3), PositionedSupport::default(), edge),
5040 ];
5041 measurements[0].self_readers.push(reader);
5042 measurements[1].observable = Pauli::X;
5043 for seed in 0..64u32 {
5044 let rows = test_supported_rows(seed);
5045 let mut basis = AdjustmentBasis::new(&rows, &measurements, &protected);
5046 for index in 0..measurements.len() {
5047 let constraints = measurements
5048 .iter()
5049 .enumerate()
5050 .flat_map(|(other, measurement)| {
5051 let axes = if other == index {
5052 Pauli::Y
5053 } else {
5054 measurement.observable
5055 };
5056 axes.iter_xz().map(move |axis| (measurement.target, axis))
5057 })
5058 .chain(
5059 measurements[index]
5060 .self_readers
5061 .iter()
5062 .copied()
5063 .flat_map(|target| [(target, Pauli::X), (target, Pauli::Z)]),
5064 )
5065 .chain(
5066 protected
5067 .iter()
5068 .flat_map(|p| [(p.target, Pauli::X), (p.target, Pauli::Z)]),
5069 );
5070 let mut expected = rows.clone();
5071 expected.sort_by_key(|row| row.support.weight());
5072 let rank = signed_gaussian_elimination(
5073 &mut expected,
5074 constraints,
5075 |row, &(target, axis)| row.support.get(target) & axis,
5076 );
5077 expected.drain(..rank);
5078 expected.sort_by_key(|row| row.support.weight());
5079 let actual =
5080 safe_adjustments(&mut basis, &measurements, index, &protected, "test").unwrap();
5081 assert_eq!(
5082 actual.len(),
5083 expected.len(),
5084 "seed {seed}, measurement {index}"
5085 );
5086 for (actual, expected) in actual.iter().zip(&expected) {
5087 assert_eq!(
5088 actual.signed, expected.signed,
5089 "seed {seed}, measurement {index}"
5090 );
5091 assert_eq!(
5092 actual.support.nodes, expected.support.nodes,
5093 "seed {seed}, measurement {index}"
5094 );
5095 assert_eq!(
5096 actual.support.edges, expected.support.edges,
5097 "seed {seed}, measurement {index}"
5098 );
5099 }
5100 }
5101 }
5102 }
5103
5104 #[test]
5105 fn composed_normalization_preserves_current_group_before_other_templates() {
5106 let targets = (0..4)
5107 .map(|x| SupportTarget::Node(IVec3::new(x, 0, 0)))
5108 .collect::<Vec<_>>();
5109 let support = |paulis: [Pauli; 4]| PositionedSupport {
5110 nodes: targets
5111 .iter()
5112 .zip(paulis)
5113 .filter_map(|(&target, pauli)| {
5114 let SupportTarget::Node(position) = target else {
5115 unreachable!()
5116 };
5117 (pauli != Pauli::I).then_some((position, pauli))
5118 })
5119 .collect(),
5120 edges: FxHashMap::default(),
5121 };
5122 let mut rows = [test_measurement(
5123 PauliString::new(0),
5124 support([Pauli::Z, Pauli::I, Pauli::Z, Pauli::Y]),
5125 SupportTarget::Node(IVec3::new(10, 0, 0)),
5126 )];
5127 let adjustments = [
5128 [Pauli::Z, Pauli::X, Pauli::Z, Pauli::Z],
5129 [Pauli::I, Pauli::I, Pauli::I, Pauli::X],
5130 ]
5131 .map(|paulis| SupportedRow {
5132 signed: PhasedPauliString::positive(PauliString::new(0)),
5133 support: support(paulis),
5134 witness: FlowWitness::default(),
5135 });
5136 normalize_measurement_rows(
5137 &mut rows,
5138 &adjustments,
5139 &[ProtectedSupport {
5140 target: targets[3],
5141 forbidden: Some(Pauli::Y),
5142 }],
5143 &[ProtectedGroup {
5144 targets: targets[..3].to_vec(),
5145 permitted_support: vec![vec![Pauli::X; 3], vec![Pauli::Z; 3]],
5146 }],
5147 ModuleCertificationLimits::UNLIMITED,
5148 "order",
5149 )
5150 .unwrap();
5151 assert_eq!(
5152 targets
5153 .iter()
5154 .map(|&target| rows[0].support.get(target))
5155 .collect::<Vec<_>>(),
5156 [Pauli::Z, Pauli::I, Pauli::Z, Pauli::Z]
5157 );
5158 }
5159
5160 #[test]
5161 fn flat_source_limit_counts_cube_height_before_geometry_work() {
5162 let graph = crate::parse_blog_to_graph("BLOG 1.0\n0: ZXZ [0,0,0] height=4d\n").unwrap();
5163 let limits = ModuleCertificationLimits {
5164 max_expanded_blocks: 1,
5165 max_occupied_cells: 3,
5166 ..ModuleCertificationLimits::UNLIMITED
5167 };
5168 assert!(matches!(
5169 graph.validate_resource_limits(limits),
5170 Err(crate::BlockGraphError::Stabilizer(
5171 crate::StabilizerError::ResourceLimited {
5172 phase: "occupied footprint cells",
5173 observed: 4,
5174 limit: 3,
5175 }
5176 ))
5177 ));
5178 graph
5179 .validate_resource_limits(ModuleCertificationLimits {
5180 max_occupied_cells: 4,
5181 ..limits
5182 })
5183 .unwrap();
5184 }
5185
5186 #[test]
5187 fn wide_correlated_support_normalizes_without_a_powerset() {
5188 let positions = (0..64).map(|x| IVec3::new(x, 0, 0)).collect::<Vec<_>>();
5189 for (initial, adjustment, desired, other) in [
5190 (Pauli::Y, Pauli::Z, Pauli::X, Pauli::Z),
5191 (Pauli::Z, Pauli::X, Pauli::Y, Pauli::X),
5192 ] {
5193 let group = ProtectedGroup {
5194 targets: positions.iter().copied().map(SupportTarget::Node).collect(),
5195 permitted_support: vec![vec![desired; 64], vec![other; 64]],
5196 };
5197 let support = |pauli| PositionedSupport {
5198 nodes: positions
5199 .iter()
5200 .copied()
5201 .map(|position| (position, pauli))
5202 .collect(),
5203 edges: FxHashMap::default(),
5204 };
5205 let row = test_measurement(
5206 PauliString::new(0),
5207 support(initial),
5208 SupportTarget::Node(IVec3::new(100, 0, 0)),
5209 );
5210 let adjustments = [SupportedRow {
5211 signed: PhasedPauliString::positive(PauliString::new(0)),
5212 support: support(adjustment),
5213 witness: FlowWitness::default(),
5214 }];
5215 for (limit, expected) in [(0, 1), (16, 17)] {
5216 let error = normalize_measurement_rows(
5217 &mut [row.clone()],
5218 &adjustments,
5219 &[],
5220 std::slice::from_ref(&group),
5221 ModuleCertificationLimits {
5222 max_normalization_states: limit,
5223 ..ModuleCertificationLimits::UNLIMITED
5224 },
5225 "wide",
5226 )
5227 .unwrap_err();
5228 assert!(
5229 matches!(&error, ModuleCertificationError::ResourceLimited {
5230 module, phase: "measurement normalization states", observed, limit: actual_limit,
5231 } if module == "wide" && *observed == expected && *actual_limit == limit),
5232 "{error}"
5233 );
5234 }
5235 let mut rows = [row];
5236 normalize_measurement_rows(
5237 &mut rows,
5238 &adjustments,
5239 &[],
5240 std::slice::from_ref(&group),
5241 ModuleCertificationLimits {
5242 max_normalization_states: 160,
5243 ..ModuleCertificationLimits::UNLIMITED
5244 },
5245 "wide",
5246 )
5247 .unwrap();
5248 assert!(
5249 positions
5250 .iter()
5251 .all(|&position| rows[0].support.get(SupportTarget::Node(position)) == desired)
5252 );
5253 }
5254 }
5255
5256 #[cfg(not(target_arch = "wasm32"))]
5257 #[test]
5258 fn many_protected_factors_use_heap_frames() {
5259 std::thread::Builder::new()
5260 .stack_size(64 * 1024)
5261 .spawn(|| {
5262 let width = 4_096;
5263 let protected = (0..width)
5264 .map(|x| ProtectedSupport {
5265 target: SupportTarget::Node(IVec3::new(x as i32, 0, 0)),
5266 forbidden: Some(Pauli::X),
5267 })
5268 .collect::<Vec<_>>();
5269 let support = PositionedSupport {
5270 nodes: (0..width)
5271 .map(|x| (IVec3::new(x as i32, 0, 0), Pauli::X))
5272 .collect(),
5273 edges: FxHashMap::default(),
5274 };
5275 let row = test_measurement(
5276 PauliString::new(0),
5277 support.clone(),
5278 SupportTarget::Node(IVec3::new(width as i32, 0, 0)),
5279 );
5280 let adjustments = [SupportedRow {
5281 signed: PhasedPauliString::positive(PauliString::new(0)),
5282 support,
5283 witness: FlowWitness::default(),
5284 }];
5285 let limits = ModuleCertificationLimits {
5286 max_normalization_states: 8,
5287 max_matrix_words: 32_768,
5288 ..ModuleCertificationLimits::DEFAULT
5289 };
5290 assert!(matches!(
5291 normalize_measurement_rows(
5292 &mut [row.clone()],
5293 &adjustments,
5294 &protected,
5295 &[],
5296 limits,
5297 "deep"
5298 ),
5299 Err(ModuleCertificationError::ResourceLimited {
5300 phase: "measurement normalization states",
5301 observed: 9,
5302 limit: 8,
5303 ..
5304 })
5305 ));
5306 let mut rows = [row];
5307 normalize_measurement_rows(
5308 &mut rows,
5309 &adjustments,
5310 &protected,
5311 &[],
5312 ModuleCertificationLimits {
5313 max_normalization_states: width + 1,
5314 ..limits
5315 },
5316 "deep",
5317 )
5318 .unwrap();
5319 assert!(rows[0].support.nodes.is_empty());
5320 })
5321 .unwrap()
5322 .join()
5323 .unwrap();
5324 }
5325
5326 #[test]
5327 fn normalization_limit_counts_visited_assignments() {
5328 let invalid_position = IVec3::ZERO;
5329 let targets = (0..13)
5330 .map(|x| SupportTarget::Node(IVec3::new(x, 0, 0)))
5331 .collect::<Vec<_>>();
5332 let protected = targets
5333 .iter()
5334 .copied()
5335 .map(|target| ProtectedSupport {
5336 target,
5337 forbidden: Some(Pauli::Z),
5338 })
5339 .collect::<Vec<_>>();
5340 let support = PositionedSupport {
5341 nodes: FxHashMap::from_iter([(invalid_position, Pauli::Z)]),
5342 edges: FxHashMap::default(),
5343 };
5344 let mut rows = [test_measurement(
5345 PauliString::new(0),
5346 support,
5347 SupportTarget::Node(IVec3::new(20, 0, 0)),
5348 )];
5349 let adjustment = |pauli| SupportedRow {
5350 signed: PhasedPauliString::positive(PauliString::new(0)),
5351 support: PositionedSupport {
5352 nodes: FxHashMap::from_iter([(invalid_position, pauli)]),
5353 edges: FxHashMap::default(),
5354 },
5355 witness: FlowWitness::default(),
5356 };
5357
5358 normalize_measurement_rows(
5359 &mut rows,
5360 &[adjustment(Pauli::X), adjustment(Pauli::Z)],
5361 &protected,
5362 &[],
5363 ModuleCertificationLimits {
5364 max_normalization_states: 15,
5365 ..ModuleCertificationLimits::UNLIMITED
5366 },
5367 "test",
5368 )
5369 .unwrap();
5370
5371 assert!(rows[0].support.nodes.is_empty());
5373 }
5374
5375 #[test]
5376 fn closed_adjustments_stay_live_when_a_pending_obligation_reads_them() {
5377 let row = |boundary, support| SupportedRow {
5378 signed: PhasedPauliString::new(PauliString::from_terms(1, [(0, boundary)]), 2),
5379 support,
5380 witness: FlowWitness::default(),
5381 };
5382 let mut relation = ChildRelation {
5383 adjustments: vec![
5384 row(
5385 Pauli::I,
5386 PositionedSupport {
5387 nodes: FxHashMap::from_iter([(IVec3::ZERO, Pauli::Z)]),
5388 ..PositionedSupport::default()
5389 },
5390 ),
5391 row(
5392 Pauli::I,
5393 PositionedSupport {
5394 edges: FxHashMap::from_iter([((IVec3::X, IVec3::X + IVec3::Z), Pauli::Z)]),
5395 ..PositionedSupport::default()
5396 },
5397 ),
5398 row(Pauli::X, PositionedSupport::default()),
5399 ],
5400 ..ChildRelation::default()
5401 };
5402 let obligations =
5404 FxHashSet::from_iter([SupportTarget::Edge(IVec3::X + IVec3::Z, IVec3::X)]);
5405 let mut completed = ChildRelation::default();
5406 relation
5407 .retire_completed(&mut completed, &obligations, "test")
5408 .unwrap();
5409 assert_eq!(relation.adjustments.len(), 2);
5410 assert_eq!(
5411 relation.adjustments[0]
5412 .support
5413 .get(*obligations.iter().next().unwrap()),
5414 Pauli::Z
5415 );
5416 assert_eq!(relation.adjustments[1].signed.paulis.get(0), Pauli::X);
5417 assert_eq!(completed.adjustments.len(), 1);
5418 assert_eq!(completed.adjustments[0].signed.phase(), 2);
5419 assert_eq!(
5420 completed.adjustments[0]
5421 .support
5422 .get(SupportTarget::Node(IVec3::ZERO)),
5423 Pauli::Z
5424 );
5425 }
5426
5427 #[test]
5428 fn discharged_measurement_boundary_is_not_erased() {
5429 let mut measurements = [test_measurement(
5430 PauliString::from_terms(1, [(0, Pauli::X)]),
5431 PositionedSupport::default(),
5432 SupportTarget::Node(IVec3::ZERO),
5433 )];
5434
5435 let error = resize_discharged_boundaries(&mut measurements, 2, "test").unwrap_err();
5436
5437 assert!(matches!(
5438 error,
5439 ModuleCertificationError::InvalidConnection { message, .. }
5440 if message.contains("discharged measurement 'm' retains boundary support")
5441 ));
5442 assert_eq!(measurements[0].signed.paulis.weight(), 1);
5443 }
5444
5445 #[test]
5446 fn multiplying_positioned_support_reconstructs_cross_centers() {
5447 let zx = ZXGraph::try_from(
5448 &crate::GalleryItem::CNOT
5449 .build()
5450 .materialize_root_graph()
5451 .expect("gallery flat projection"),
5452 )
5453 .unwrap();
5454 let node = zx
5455 .nodes()
5456 .iter()
5457 .find(|node| {
5458 matches!(node.kind, crate::NodeKind::X | crate::NodeKind::Z)
5459 && zx.edges().iter().filter(|edge| edge.n1 == node.id).count() == 3
5460 })
5461 .unwrap();
5462 let edges = zx
5463 .edges()
5464 .iter()
5465 .filter(|edge| edge.n1 == node.id)
5466 .map(|edge| edge.id)
5467 .collect::<Vec<_>>();
5468 let row = |a: usize, b: usize| {
5469 let mut row = PauliString::new(zx.total_ids());
5470 for index in [a, b] {
5471 let edge = &zx.edges()[edges[index] - zx.nodes().len()];
5472 let mut pauli = node.kind.cross_pauli();
5473 if edge.hadamard && node.id == edge.n1.max(edge.n2) {
5474 pauli = pauli.flip();
5475 }
5476 row.set(edge.id, pauli);
5477 row.set(zx.edge_id(edge.n2, edge.n1).unwrap(), pauli);
5478 }
5479 zx.materialize_stabilizer_with_sign(row, false)
5480 };
5481 let left = row(0, 1);
5482 let right = row(0, 2);
5483 let mut support = PositionedSupport::from_stabilizer(&left, &zx);
5484 support.multiply_assign(&PositionedSupport::from_stabilizer(&right, &zx));
5485 let product = support.materialize(&zx, 0).unwrap();
5486 assert_eq!(product.paulis.get(node.id), node.kind.cross_pauli());
5487 assert_eq!(product.paulis.get(edges[0]), Pauli::I);
5488 assert_ne!(product.paulis.get(edges[1]), Pauli::I);
5489 assert_ne!(product.paulis.get(edges[2]), Pauli::I);
5490 }
5491
5492 fn identity_wrapper(program: &BlockGraph) -> BlockGraph {
5493 let mut child = program.root().clone();
5494 child.name = "Child".into();
5495 let mut body = BlockGraph::new();
5496 let quantum_connections = child
5497 .interface
5498 .quantum_ports
5499 .iter()
5500 .map(|port| {
5501 let role = match port.direction {
5502 crate::PortDirection::Input => crate::PortRole::Input,
5503 crate::PortDirection::Output => crate::PortRole::Output,
5504 };
5505 body.try_add_block(
5506 Block::new(port.position, BlockKind::Port)
5507 .with_port_role(role)
5508 .unwrap(),
5509 )
5510 .unwrap();
5511 let endpoint = InstancePort {
5512 instance: "child".into(),
5513 port: port.name.clone(),
5514 };
5515 match port.direction {
5516 crate::PortDirection::Input => QuantumConnection::Input {
5517 block: port.position,
5518 input: endpoint,
5519 hadamard: false,
5520 },
5521 crate::PortDirection::Output => QuantumConnection::Output {
5522 output: endpoint,
5523 block: port.position,
5524 hadamard: false,
5525 },
5526 }
5527 })
5528 .collect();
5529 let root = BlockGraph::definition(
5530 "main",
5531 body,
5532 child.interface.clone(),
5533 vec![ModuleInstance {
5534 name: "child".into(),
5535 definition: child.name.clone(),
5536 rotation: crate::ModuleRotation::IDENTITY,
5537 translation: IVec3::ZERO,
5538 }],
5539 quantum_connections,
5540 Vec::new(),
5541 );
5542 BlockGraph::from_definitions(vec![child, root]).unwrap()
5543 }
5544
5545 #[test]
5546 fn shallower_sibling_preserves_queued_dependency_levels() {
5547 let wire = "in input: data = 0\nout output: data = 2\n
5548 0: Port [0,0,-1] role=input\n1: XZZ [0,0,0]\n2: Port [0,0,1] role=output\n
5549 0 -> +Z\n1 -> +Z\n";
5550 let program = crate::parse_inline_graph(&format!(
5551 "BLOG 1.0\nmodule Wire {{\n{wire}}}\nmodule Late {{\n{wire}}}\n
5552 module Nested {{
5553 in input: data = 0\nout output: data = 2
5554 0: Port [0,0,-1] role=input\n2: Port [0,0,1] role=output
5555 wire: Wire @ [0,0,0]
5556 0 -> wire.input\nwire.output -> 2
5557 }}
5558 module main {{
5559 in input: data = 0\nout output: data = 2
5560 0: Port [0,0,-1] role=input\n2: Port [0,0,2] role=output
5561 nested: Nested @ [0,0,0]
5562 late: Late @ [0,0,1]
5563 0 -> nested.input\nnested.output -> late.input\nlate.output -> 2
5564 }}"
5565 ))
5566 .unwrap();
5567 for jobs in [1, 2] {
5568 let summary = program
5569 .summarize_root_with_jobs(
5570 ModuleCertificationLimits::DEFAULT,
5571 NonZeroUsize::new(jobs).unwrap(),
5572 )
5573 .unwrap();
5574 assert_eq!(summary.boundary_rows().len(), 2);
5575 assert!(summary.definition("Nested").is_some());
5576 assert!(summary.definition("Late").is_some());
5577 }
5578 }
5579
5580 #[test]
5581 fn parent_readout_survives_child_composition() {
5582 let program = crate::parse_inline_graph(
5583 "BLOG 1.0\n\nmodule Wire {\n\
5584 in input: data = 0\nout output: data = 2\n\
5585 0: Port [0,0,-1]\n1: ZXZ [0,0,0]\n2: Port [0,0,1]\n\
5586 0 -> +Z\n1 -> +Z\n}\n\nmodule main {\n\
5587 in input: data = 10\nout result = m\n\
5588 wire: Wire @ [0,0,0]\n\
5589 10: Port [0,0,-1] role=input\n11: X [0,0,1]\n\
5590 10 -> wire.input\nwire.output -> 11\nm = measure 11\n}\n",
5591 )
5592 .unwrap();
5593 let summary = program
5594 .summarize_root(ModuleCertificationLimits::DEFAULT)
5595 .unwrap();
5596 assert!(
5597 summary
5598 .measurements
5599 .iter()
5600 .chain(&summary.discharged_measurements)
5601 .any(|row| row.name == "m")
5602 );
5603 let graph = program
5604 .materialize_root_graph()
5605 .unwrap()
5606 .fix_shadowed_faces();
5607 let zx = ZXGraph::try_from(&graph).unwrap();
5608 let composed = summary.materialize_stabilizers(&zx, IVec3::ZERO).unwrap();
5609 let flat = graph.analyze_actions().unwrap().1;
5610 assert_eq!(composed.generators.len(), flat.generators.len());
5611 for (composed, flat) in composed.generators.iter().zip(&flat.generators) {
5612 assert_eq!(composed.kind, flat.kind);
5613 assert_eq!(composed.stabilizer.paulis, flat.stabilizer.paulis);
5614 assert_eq!(composed.stabilizer.sign, flat.stabilizer.sign);
5615 }
5616 }
5617
5618 #[test]
5619 fn classical_parent_action_keeps_independent_connectors_within_frontier_limit() {
5620 let program = crate::parse_inline_graph(
5621 "BLOG 1.0\nmodule Wire {\n\
5622 in input: data = 0\nout output: data = 2\n\
5623 0: Port [0,0,-1]\n1: ZXZ [0,0,0]\n2: Port [0,0,1]\n\
5624 0 -> +Z\n1 -> +Z\n}\nmodule main {\n\
5625 in a: data = 10\nout a_out: data = 11\n\
5626 in b: data = 12\nout b_out: data = 13\nin enable\nout done = flag\n\
5627 a: Wire @ [0,0,0]\nb: Wire @ [2,0,0]\n\
5628 10: Port [0,0,-1] role=input\n11: Port [0,0,1] role=output\n\
5629 12: Port [2,0,-1] role=input\n13: Port [2,0,1] role=output\n\
5630 10 -> a.input\na.output -> 11\n12 -> b.input\nb.output -> 13\n\
5631 flag = enable | !enable\n}\n",
5632 )
5633 .unwrap();
5634 let summary = program
5635 .summarize_root(ModuleCertificationLimits {
5636 max_frontier_width: 6,
5637 ..ModuleCertificationLimits::DEFAULT
5638 })
5639 .unwrap();
5640 assert_eq!(summary.quantum_ports().len(), 4);
5641 }
5642
5643 #[test]
5644 fn identity_wrapper_preserves_materialized_stabilizers() {
5645 let program = identity_wrapper(&GalleryItem::CCZInjectedMaj.build());
5646 let summary = program
5647 .summarize_root(ModuleCertificationLimits::UNLIMITED)
5648 .unwrap();
5649 let graph = program.materialize_root_graph().unwrap();
5650 let zx = ZXGraph::try_from(&graph).unwrap();
5651 let composed = summary.materialize_stabilizers(&zx, IVec3::ZERO).unwrap();
5652 let flat = graph.analyze_actions().unwrap().1;
5653
5654 assert_eq!(composed.generators.len(), flat.generators.len());
5655 for (composed, flat) in composed.generators.iter().zip(&flat.generators) {
5656 assert_eq!(composed.kind, flat.kind);
5657 assert_eq!(composed.stabilizer.paulis, flat.stabilizer.paulis);
5658 assert_eq!(composed.stabilizer.sign, flat.stabilizer.sign);
5659 }
5660 }
5661
5662 #[test]
5663 fn composed_phase_cache_matches_flat_derivation_and_tracks_t_conversion() {
5664 for item in [
5665 GalleryItem::CNOT,
5666 GalleryItem::CZTemporalH,
5667 GalleryItem::S,
5668 GalleryItem::T,
5669 GalleryItem::CCZInjectedMaj,
5670 GalleryItem::PhaseGradientK4,
5671 ] {
5672 let program = item.build();
5673 let summary = program
5674 .summarize_root(ModuleCertificationLimits::UNLIMITED)
5675 .unwrap();
5676 let graph = program.materialize_root_graph().unwrap();
5677 let zx = ZXGraph::try_from(&graph).unwrap();
5678 let composed = summary.materialize_stabilizers(&zx, IVec3::ZERO).unwrap();
5679 let cached = composed.zx_graph.stabilizer_phase_basis.get().unwrap();
5680 let mut queries = composed
5681 .generators
5682 .iter()
5683 .map(|row| row.stabilizer.paulis.clone())
5684 .chain(composed.auxiliary_rows().iter().cloned())
5685 .collect::<Vec<_>>();
5686 let products = queries
5687 .windows(2)
5688 .map(|rows| {
5689 let mut product = rows[0].clone();
5690 product ^= &rows[1];
5691 product
5692 })
5693 .collect::<Vec<_>>();
5694 queries.extend(products);
5695 let flat = ZXGraph::try_from(&graph).unwrap();
5696 let mut raw_queries = queries.clone();
5697 flat.clear_cross_centers(&mut raw_queries);
5698 assert_eq!(
5699 composed.zx_graph.stabilizer_row_phases(&queries),
5700 flat.external_stabilizer_row_phases(&raw_queries),
5701 "{item:?}"
5702 );
5703 let runtime =
5704 crate::RuntimeStabilizerBasis::from_generators(&composed).with_t_nodes_as_ports();
5705 let retained = runtime.zx_graph().stabilizer_phase_basis.get().unwrap();
5706 assert!(Arc::ptr_eq(cached, retained), "{item:?}");
5707 let mut fresh_demoted = runtime.zx_graph().clone();
5708 fresh_demoted.stabilizer_phase_basis.take();
5709 assert_eq!(
5710 runtime.zx_graph().stabilizer_row_phases(&queries),
5711 fresh_demoted.stabilizer_row_phases(&queries),
5712 "{item:?} after T conversion"
5713 );
5714 }
5715 }
5716
5717 #[test]
5718 fn rotated_phase_gradient_summary_preserves_flat_nonlogical_rows() {
5719 let program = GalleryItem::PhaseGradientK4.build();
5720 let summary = program
5721 .summarize_root(ModuleCertificationLimits::DEFAULT)
5722 .unwrap();
5723 let graph = program.materialize_root_graph().unwrap();
5724 let zx = ZXGraph::try_from(&graph).unwrap();
5725 let composed = summary.materialize_stabilizers(&zx, IVec3::ZERO).unwrap();
5726 let flat = graph.analyze_actions().unwrap().1;
5727
5728 assert_eq!(composed.generators.len(), flat.generators.len());
5729 for (composed, flat) in composed.generators.iter().zip(&flat.generators) {
5730 assert_eq!(composed.kind, flat.kind);
5731 if matches!(composed.kind, StabilizerRowKind::Logical) {
5734 continue;
5735 }
5736 assert_eq!(
5737 composed.stabilizer.paulis, flat.stabilizer.paulis,
5738 "{:?}",
5739 composed.kind
5740 );
5741 assert_eq!(
5742 composed.stabilizer.sign, flat.stabilizer.sign,
5743 "{:?}",
5744 composed.kind
5745 );
5746 }
5747 }
5748
5749 #[test]
5750 fn leaf_certificate_preserves_signed_rows() {
5751 for item in [
5752 GalleryItem::CCZInjectedAnd,
5753 GalleryItem::CCZInjectedMaj,
5754 GalleryItem::UMA,
5755 ] {
5756 let program = item.build();
5757 let summary = program
5758 .summarize_root(ModuleCertificationLimits::UNLIMITED)
5759 .unwrap();
5760 let graph = program.materialize_root_graph().unwrap();
5761 let zx = ZXGraph::try_from(&graph).unwrap();
5762 for row in &summary.certificate_rows {
5763 let stabilizer = materialize_summary_row(
5764 &row.signed,
5765 &row.support,
5766 &summary.ports,
5767 &zx,
5768 ModuleOrientation::IDENTITY,
5769 IVec3::ZERO,
5770 summary.name(),
5771 )
5772 .unwrap();
5773 let mut paulis = stabilizer.paulis.clone();
5774 zx.clear_cross_centers(std::slice::from_mut(&mut paulis));
5775 assert_eq!(
5776 stabilizer_phase(&stabilizer),
5777 zx.external_stabilizer_row_phases(&[paulis])[0],
5778 "{item:?} certificate"
5779 );
5780 }
5781 for row in &summary.measurements {
5782 let stabilizer = materialize_summary_row(
5783 &row.signed,
5784 &row.support,
5785 &summary.ports,
5786 &zx,
5787 ModuleOrientation::IDENTITY,
5788 IVec3::ZERO,
5789 summary.name(),
5790 )
5791 .unwrap();
5792 let mut paulis = stabilizer.paulis.clone();
5793 zx.clear_cross_centers(std::slice::from_mut(&mut paulis));
5794 assert_eq!(
5795 stabilizer_phase(&stabilizer),
5796 zx.external_stabilizer_row_phases(&[paulis])[0],
5797 "{item:?} {}",
5798 row.name
5799 );
5800 }
5801 let composed = summary.materialize_stabilizers(&zx, IVec3::ZERO).unwrap();
5802 let flat = graph.analyze_actions().unwrap().1;
5803 assert_eq!(composed.generators.len(), flat.generators.len());
5804 for (composed, flat) in composed.generators.iter().zip(&flat.generators) {
5805 assert_eq!(composed.kind, flat.kind);
5806 assert_eq!(composed.stabilizer.paulis, flat.stabilizer.paulis);
5807 assert_eq!(composed.stabilizer.sign, flat.stabilizer.sign);
5808 }
5809 }
5810 }
5811
5812 #[test]
5813 fn composed_adder_rejects_unavailable_causal_readout() {
5814 let program = crate::BlockGraph::from_text(bloq_test::ONE_BIT_ADDER_SOURCE).unwrap();
5815 let summary = program
5816 .summarize_root(ModuleCertificationLimits::UNLIMITED)
5817 .unwrap();
5818 let graph = program
5819 .materialize_root_graph()
5820 .unwrap()
5821 .canonical_true_branch_view()
5822 .unwrap();
5823 let offset = IVec3::new(0, 0, -*graph.spans().unwrap().2.start());
5824 let graph = graph.with_zero_min_z().unwrap().fix_shadowed_faces();
5825 let zx = ZXGraph::try_from(&graph).unwrap();
5826
5827 let result = summary.materialize_stabilizers(&zx, offset).map(|_| ());
5828 assert!(
5829 matches!(
5830 result,
5831 Err(ModuleCertificationError::Runtime {
5832 source: crate::RuntimeBasisError::Stabilizer(
5833 crate::StabilizerError::UnavailableControlParity { ref mvar, .. }
5834 ),
5835 ..
5836 }) if mvar == "uma__m_ikprime"
5837 ),
5838 "{result:?}"
5839 );
5840 }
5841
5842 #[test]
5843 fn composed_adder_certificate_matches_flat_row_space() {
5844 let program = crate::BlockGraph::from_text(bloq_test::ONE_BIT_ADDER_SOURCE).unwrap();
5845 let summary = program
5846 .summarize_root(ModuleCertificationLimits::UNLIMITED)
5847 .unwrap();
5848 let graph = program
5849 .materialize_root_graph()
5850 .unwrap()
5851 .canonical_true_branch_view()
5852 .unwrap();
5853 let offset = IVec3::new(0, 0, -*graph.spans().unwrap().2.start());
5854 let graph = graph.with_zero_min_z().unwrap().fix_shadowed_faces();
5855 let zx = ZXGraph::try_from(&graph).unwrap();
5856
5857 let composed = summary
5858 .certificate_rows
5859 .iter()
5860 .map(|row| {
5861 let stabilizer = materialize_summary_row(
5862 &row.signed,
5863 &row.support,
5864 &summary.ports,
5865 &zx,
5866 ModuleOrientation::IDENTITY,
5867 offset,
5868 summary.name(),
5869 )
5870 .unwrap();
5871 let mut paulis = stabilizer.paulis;
5872 zx.clear_cross_centers(std::slice::from_mut(&mut paulis));
5873 paulis
5874 })
5875 .collect::<Vec<_>>();
5876 let flat = zx.to_external_generator_table();
5877 let composed_rank = crate::zx::reduce_to_basis(&composed, zx.total_ids()).len();
5878 let flat_rank = crate::zx::reduce_to_basis(&flat, zx.total_ids()).len();
5879 let mut combined = composed;
5880 combined.extend(flat);
5881 let combined_rank = crate::zx::reduce_to_basis(&combined, zx.total_ids()).len();
5882
5883 assert_eq!(composed_rank, flat_rank);
5884 assert_eq!(combined_rank, flat_rank);
5885 }
5886
5887 #[test]
5888 fn semantic_frontier_retains_resource_and_frame_support() {
5889 let response = IVec3::new(2, 0, 0);
5890 let resource = IVec3::new(3, 0, 0);
5891 let mut body = BlockGraph::new();
5892 body.add_block(Block::new(response, BlockKind::Cube(crate::CubeKind::ZXZ)));
5893 body.add_block(Block::new(resource, BlockKind::T));
5894 body.set_actions_with_inputs(
5895 vec![Action::Feedback {
5896 targets: vec![FeedbackTarget {
5897 pauli: PauliBasis::X,
5898 target: response,
5899 direction: None,
5900 }],
5901 condition: Some(Expr::Var("frame".into())),
5902 }],
5903 ["frame".to_string()],
5904 )
5905 .unwrap();
5906 let module = BlockGraph::definition(
5907 "test",
5908 body.clone(),
5909 Default::default(),
5910 Vec::new(),
5911 Vec::new(),
5912 Vec::new(),
5913 );
5914 let frontier = semantic_frontier_supports(&module, &body).unwrap();
5915 assert!(frontier.contains(&SupportTarget::Node(response)));
5916 assert!(frontier.contains(&SupportTarget::Node(resource)));
5917
5918 let rows = compose_supported_rows(
5919 vec![SupportedRow {
5920 signed: PhasedPauliString::positive(PauliString::try_from("XX").unwrap()),
5921 support: PositionedSupport {
5922 nodes: FxHashMap::from_iter([(response, Pauli::X)]),
5923 edges: FxHashMap::default(),
5924 },
5925 witness: FlowWitness::default(),
5926 }],
5927 &mut [],
5928 &[],
5929 &frontier,
5930 &[(
5931 0,
5932 1,
5933 false,
5934 false,
5935 SupportSeam {
5936 edge: (IVec3::ZERO, IVec3::Z),
5937 boundary_to_edge_hadamard: false,
5938 },
5939 )],
5940 &[],
5941 "test",
5942 )
5943 .unwrap();
5944
5945 assert_eq!(rows.len(), 1);
5946 assert_eq!(rows[0].support.get(SupportTarget::Node(response)), Pauli::X);
5947 }
5948
5949 #[test]
5950 fn signed_spatial_hadamard_y_seam_has_both_minus_factors() {
5951 let edge = (IVec3::ZERO, IVec3::Y);
5952 let row = SupportedRow {
5953 signed: PhasedPauliString::positive(PauliString::from_terms(
5954 2,
5955 [(0, Pauli::Y), (1, Pauli::Y)],
5956 )),
5957 support: PositionedSupport::default(),
5958 witness: FlowWitness::default(),
5959 };
5960 let closed = compose_certificate_rows(
5961 vec![row],
5962 &[(
5963 0,
5964 1,
5965 true,
5966 true,
5967 SupportSeam {
5968 edge,
5969 boundary_to_edge_hadamard: false,
5970 },
5971 )],
5972 &[],
5973 );
5974 assert_eq!(closed.len(), 1);
5975 assert_eq!(
5976 closed[0].signed.phase(),
5977 0,
5978 "HYH and Y transpose each add -1"
5979 );
5980 assert_eq!(closed[0].support.edges[&edge], Pauli::Y);
5981 }
5982}