1 from __future__
import annotations
3 from typing
import Any, Iterable, Mapping
5 from squander.partitioning.noisy_planner_surface_builders
import (
6 build_phase3_continuity_planner_surface,
7 preflight_planner_request,
9 from squander.partitioning.noisy_types
import (
10 DEFAULT_PARTITION_DESCRIPTOR_MAX_QUBITS,
11 PARTITIONED_DENSITY_MODE,
13 PLANNER_OP_KIND_NOISE,
14 CanonicalNoisyPlannerOperation,
15 CanonicalNoisyPlannerSurface,
16 NoisyPartitionDescriptor,
17 NoisyPartitionDescriptorMember,
18 NoisyPartitionDescriptorSet,
20 from squander.partitioning.noisy_validation_errors
import NoisyDescriptorValidationError
23 descriptor_set: NoisyPartitionDescriptorSet,
24 member: NoisyPartitionDescriptorMember,
26 op = descriptor_set.canonical_operation_for(member)
28 "partition_member_index": member.partition_member_index,
29 "canonical_operation_index": member.canonical_operation_index,
32 "is_unitary": op.is_unitary,
33 "source_gate_index": op.source_gate_index,
34 "target_qbit": op.target_qbit,
35 "control_qbit": op.control_qbit,
36 "qubit_support": list(op.qubit_support),
37 "local_target_qbit": member.local_target_qbit,
38 "local_control_qbit": member.local_control_qbit,
39 "local_qubit_support": list(member.local_qubit_support),
40 "param_count": op.param_count,
41 "param_start": op.param_start,
42 "local_param_start": member.local_param_start,
43 "fixed_value": op.fixed_value,
48 descriptor_set: NoisyPartitionDescriptorSet,
49 partition: NoisyPartitionDescriptor,
51 routing = descriptor_set.partition_parameter_routing(partition)
53 "partition_index": partition.partition_index,
54 "member_count": partition.member_count,
55 "gate_count": descriptor_set.partition_gate_count(partition),
56 "noise_count": descriptor_set.partition_noise_count(partition),
57 "canonical_operation_indices": list(
58 descriptor_set.partition_canonical_operation_indices(partition)
61 "partition_qubit_span": list(partition.partition_qubit_span),
62 "local_to_global_qbits": list(partition.local_to_global_qbits),
63 "global_to_local_qbits": [
64 {
"global_qbit": global_qbit,
"local_qbit": local_qbit}
65 for global_qbit, local_qbit
in partition.global_to_local_qbits
67 "requires_remap": partition.requires_remap,
68 "partition_parameter_count": descriptor_set.partition_parameter_count(partition),
69 "parameter_routing": [
71 "global_param_start": global_param_start,
72 "local_param_start": local_param_start,
73 "param_count": param_count,
75 for global_param_start, local_param_start, param_count
in routing
77 "members": [m.to_dict(descriptor_set)
for m
in partition.members],
81 surface: CanonicalNoisyPlannerSurface, *, max_partition_qubits: int
83 if max_partition_qubits <= 0:
84 raise NoisyDescriptorValidationError(
85 category=
"descriptor_request",
86 first_unsupported_condition=
"max_partition_qubits",
87 failure_stage=
"descriptor_generation_preflight",
88 source_type=surface.source_type,
89 requested_mode=surface.requested_mode,
90 workload_id=surface.workload_id,
91 reason=
"Partition descriptor generation requires max_partition_qubits > 0",
93 if surface.max_qubit_span > max_partition_qubits:
94 raise NoisyDescriptorValidationError(
95 category=
"partition_span",
96 first_unsupported_condition=
"max_partition_qubits",
97 failure_stage=
"descriptor_generation_preflight",
98 source_type=surface.source_type,
99 requested_mode=surface.requested_mode,
100 workload_id=surface.workload_id,
102 "Partition descriptor generation requires max_partition_qubits >= " 103 "the canonical max_qubit_span {} for workload '{}'".format(
104 surface.max_qubit_span, surface.workload_id
122 surface: CanonicalNoisyPlannerSurface, *, max_partition_qubits: int
123 ) -> tuple[tuple[CanonicalNoisyPlannerOperation, ...], ...]:
124 partitions: list[tuple[CanonicalNoisyPlannerOperation, ...]] = []
125 current_partition: list[CanonicalNoisyPlannerOperation] = []
126 current_support: set[int] = set()
128 for operation
in surface.operations:
129 operation_support = set(operation.qubit_support)
130 expanded_support = current_support | operation_support
131 if current_partition
and len(expanded_support) > max_partition_qubits:
132 partitions.append(tuple(current_partition))
133 current_partition = []
134 current_support = set()
135 current_partition.append(operation)
136 current_support |= operation_support
138 if current_partition:
139 partitions.append(tuple(current_partition))
141 return tuple(partitions)
145 operations: tuple[CanonicalNoisyPlannerOperation, ...], *, partition_index: int
146 ) -> NoisyPartitionDescriptor:
147 local_to_global_qbits = tuple(
148 sorted({qbit
for operation
in operations
for qbit
in operation.qubit_support})
151 global_qbit: local_qbit
152 for local_qbit, global_qbit
in enumerate(local_to_global_qbits)
155 members: list[NoisyPartitionDescriptorMember] = []
156 local_param_start = 0
158 for partition_member_index, operation
in enumerate(operations):
159 member = NoisyPartitionDescriptorMember(
160 partition_member_index=partition_member_index,
161 canonical_operation_index=operation.index,
164 if operation.target_qbit
is None 165 else global_to_local[operation.target_qbit]
169 if operation.control_qbit
is None 170 else global_to_local[operation.control_qbit]
172 local_qubit_support=tuple(
173 global_to_local[qbit]
for qbit
in operation.qubit_support
175 local_param_start=local_param_start,
177 members.append(member)
178 local_param_start += operation.param_count
180 return NoisyPartitionDescriptor(
181 partition_index=partition_index,
182 local_to_global_qbits=local_to_global_qbits,
183 members=tuple(members),
188 surface: CanonicalNoisyPlannerSurface,
190 max_partition_qubits: int = DEFAULT_PARTITION_DESCRIPTOR_MAX_QUBITS,
191 ) -> NoisyPartitionDescriptorSet:
195 partition_operations, partition_index=partition_index
197 for partition_index, partition_operations
in enumerate(
199 surface, max_partition_qubits=max_partition_qubits
203 descriptor_set = NoisyPartitionDescriptorSet(
204 requested_mode=surface.requested_mode,
205 source_type=surface.source_type,
206 workload_id=surface.workload_id,
207 qbit_num=surface.qbit_num,
208 parameter_count=surface.parameter_count,
209 max_partition_qubits=max_partition_qubits,
210 operations=surface.operations,
211 partitions=partitions,
219 workload_id: str |
None =
None,
220 requested_mode: str = PARTITIONED_DENSITY_MODE,
221 max_partition_qubits: int = DEFAULT_PARTITION_DESCRIPTOR_MAX_QUBITS,
222 ) -> NoisyPartitionDescriptorSet:
225 workload_id=workload_id,
226 requested_mode=requested_mode,
229 surface, max_partition_qubits=max_partition_qubits
237 requested_mode: str = PARTITIONED_DENSITY_MODE,
238 bridge_metadata: Mapping[str, Any] |
None =
None,
239 operation_specs: Iterable[Mapping[str, Any]] |
None =
None,
240 qbit_num: int |
None =
None,
241 legacy_circuit: Any |
None =
None,
242 density_noise: Iterable[Mapping[str, Any]] |
None =
None,
243 strict_phase3_support: bool =
True,
244 max_partition_qubits: int = DEFAULT_PARTITION_DESCRIPTOR_MAX_QUBITS,
245 ) -> NoisyPartitionDescriptorSet:
247 source_type=source_type,
248 workload_id=workload_id,
249 requested_mode=requested_mode,
250 bridge_metadata=bridge_metadata,
251 operation_specs=operation_specs,
253 legacy_circuit=legacy_circuit,
254 density_noise=density_noise,
255 strict_phase3_support=strict_phase3_support,
258 surface, max_partition_qubits=max_partition_qubits
263 descriptor_set: NoisyPartitionDescriptorSet,
266 first_unsupported_condition: str,
269 ) -> NoisyDescriptorValidationError:
270 return NoisyDescriptorValidationError(
272 first_unsupported_condition=first_unsupported_condition,
273 failure_stage=failure_stage,
274 source_type=descriptor_set.source_type,
275 requested_mode=descriptor_set.requested_mode,
276 workload_id=descriptor_set.workload_id,
282 descriptor_set: NoisyPartitionDescriptorSet,
283 ) -> NoisyPartitionDescriptorSet:
284 expected_partition_index = 0
285 expected_canonical_index = 0
287 if len(descriptor_set.operations) != descriptor_set.descriptor_member_count:
290 category=
"dropped_operations",
291 first_unsupported_condition=
"operations_table_size",
292 failure_stage=
"descriptor_validation",
294 "Descriptor operations table length {} does not match " 295 "descriptor_member_count {}".format(
296 len(descriptor_set.operations),
297 descriptor_set.descriptor_member_count,
302 for partition
in descriptor_set.partitions:
303 if partition.partition_index != expected_partition_index:
306 category=
"reordering_across_noise_boundaries",
307 first_unsupported_condition=
"partition_index",
308 failure_stage=
"descriptor_validation",
310 "Partition descriptors require contiguous partition indices starting " 311 "at 0; got partition_index {} while expecting {}".format(
312 partition.partition_index, expected_partition_index
316 if not partition.members:
319 category=
"descriptor_request",
320 first_unsupported_condition=
"empty_partition",
321 failure_stage=
"descriptor_validation",
322 reason=
"Partition descriptors do not support empty partitions",
325 if len(set(partition.local_to_global_qbits)) != len(
326 partition.local_to_global_qbits
330 category=
"incomplete_remapping",
331 first_unsupported_condition=
"duplicate_global_qbit",
332 failure_stage=
"descriptor_validation",
334 "Partition descriptor partition {} contains duplicate entries in " 335 "local_to_global_qbits".format(partition.partition_index)
340 global_qbit: local_qbit
341 for local_qbit, global_qbit
in enumerate(partition.local_to_global_qbits)
343 expected_parameter_routing: list[tuple[int, int, int]] = []
344 expected_local_param_start = 0
346 for member_index, member
in enumerate(partition.members):
347 if member.partition_member_index != member_index:
350 category=
"reordering_across_noise_boundaries",
351 first_unsupported_condition=
"partition_member_index",
352 failure_stage=
"descriptor_validation",
354 "Partition descriptor partition {} requires contiguous " 355 "partition_member_index values".format(
356 partition.partition_index
360 if member.canonical_operation_index != expected_canonical_index:
363 category=
"reordering_across_noise_boundaries",
364 first_unsupported_condition=
"canonical_operation_index",
365 failure_stage=
"descriptor_validation",
367 "Partition descriptors must preserve contiguous canonical " 368 "operation coverage; partition {} member {} expected canonical " 369 "index {} but got {}".format(
370 partition.partition_index,
372 expected_canonical_index,
373 member.canonical_operation_index,
377 op = descriptor_set.operations[member.canonical_operation_index]
378 expected_canonical_index += 1
380 expected_local_qubit_support = tuple(
381 global_to_local[qbit]
for qbit
in op.qubit_support
383 if member.local_qubit_support != expected_local_qubit_support:
386 category=
"incomplete_remapping",
387 first_unsupported_condition=
"local_qubit_support",
388 failure_stage=
"descriptor_validation",
390 "Partition descriptor partition {} has inconsistent local_qubit_support " 391 "for canonical operation {}".format(
392 partition.partition_index, member.canonical_operation_index
396 expected_local_target = (
398 if op.target_qbit
is None 399 else global_to_local[op.target_qbit]
401 if member.local_target_qbit != expected_local_target:
404 category=
"incomplete_remapping",
405 first_unsupported_condition=
"local_target_qbit",
406 failure_stage=
"descriptor_validation",
408 "Partition descriptor partition {} has inconsistent local_target_qbit " 409 "for canonical operation {}".format(
410 partition.partition_index, member.canonical_operation_index
414 expected_local_control = (
416 if op.control_qbit
is None 417 else global_to_local[op.control_qbit]
419 if member.local_control_qbit != expected_local_control:
422 category=
"incomplete_remapping",
423 first_unsupported_condition=
"local_control_qbit",
424 failure_stage=
"descriptor_validation",
426 "Partition descriptor partition {} has inconsistent local_control_qbit " 427 "for canonical operation {}".format(
428 partition.partition_index, member.canonical_operation_index
432 if member.local_param_start != expected_local_param_start:
435 category=
"ambiguous_parameter_routing",
436 first_unsupported_condition=
"local_param_start",
437 failure_stage=
"descriptor_validation",
439 "Partition descriptor partition {} has non-contiguous local_param_start " 440 "for canonical operation {}".format(
441 partition.partition_index, member.canonical_operation_index
446 expected_parameter_routing.append(
447 (op.param_start, member.local_param_start, op.param_count)
449 expected_local_param_start += op.param_count
451 derived_routing = descriptor_set.partition_parameter_routing(partition)
452 if derived_routing != tuple(expected_parameter_routing):
455 category=
"ambiguous_parameter_routing",
456 first_unsupported_condition=
"parameter_routing",
457 failure_stage=
"descriptor_validation",
459 "Partition descriptor partition {} must keep parameter_routing aligned " 460 "with ordered member parameter metadata".format(
461 partition.partition_index
465 expected_partition_index += 1
467 if expected_canonical_index != len(descriptor_set.operations):
470 category=
"dropped_operations",
471 first_unsupported_condition=
"descriptor_member_count",
472 failure_stage=
"descriptor_validation",
474 "Partition descriptor coverage ended at canonical index {} but " 475 "operations table has length {}".format(
476 expected_canonical_index, len(descriptor_set.operations)
481 return descriptor_set
485 expected: CanonicalNoisyPlannerOperation,
486 actual: CanonicalNoisyPlannerOperation,
487 ) -> tuple[str, str]:
488 """Map first differing planner field to historical unsupported categories.""" 500 if getattr(actual, field) != getattr(expected, field):
502 "hidden_noise_placement" 503 if expected.kind == PLANNER_OP_KIND_NOISE
504 or actual.kind == PLANNER_OP_KIND_NOISE
505 else "dropped_operations" 507 return category, field
508 if actual.qubit_support != expected.qubit_support:
510 "hidden_noise_placement" 511 if expected.kind == PLANNER_OP_KIND_NOISE
512 or actual.kind == PLANNER_OP_KIND_NOISE
513 else "dropped_operations" 515 return category,
"qubit_support" 516 return "dropped_operations",
"operation_mismatch" 520 surface: CanonicalNoisyPlannerSurface,
521 descriptor_set: NoisyPartitionDescriptorSet,
522 ) -> NoisyPartitionDescriptorSet:
525 validated.requested_mode != surface.requested_mode
526 or validated.source_type != surface.source_type
527 or validated.workload_id != surface.workload_id
528 or validated.qbit_num != surface.qbit_num
529 or validated.parameter_count != surface.parameter_count
533 category=
"descriptor_request",
534 first_unsupported_condition=
"provenance_mismatch",
535 failure_stage=
"descriptor_validation",
537 "Partition descriptor provenance and size metadata must match the " 538 "canonical planner surface for workload '{}'".format(
543 if validated.descriptor_member_count != surface.operation_count:
546 category=
"dropped_operations",
547 first_unsupported_condition=
"operation_count",
548 failure_stage=
"descriptor_validation",
550 "Partition descriptor workload '{}' records {} descriptor members but " 551 "the canonical surface contains {} operations".format(
553 validated.descriptor_member_count,
554 surface.operation_count,
558 if validated.noise_count != surface.noise_count:
561 category=
"hidden_noise_placement",
562 first_unsupported_condition=
"noise_count",
563 failure_stage=
"descriptor_validation",
565 "Partition descriptor workload '{}' records {} noise operations but " 566 "the canonical surface contains {}".format(
568 validated.noise_count,
574 if validated.operations != surface.operations:
575 if len(validated.operations) != len(surface.operations):
578 category=
"dropped_operations",
579 first_unsupported_condition=
"operation_count",
580 failure_stage=
"descriptor_validation",
582 "Partition descriptor workload '{}' operations table length {} does not " 583 "match canonical surface length {}".format(
585 len(validated.operations),
586 len(surface.operations),
590 for index, (desc_op, surf_op)
in enumerate(
591 zip(validated.operations, surface.operations)
593 if desc_op == surf_op:
601 first_unsupported_condition=first_cond,
602 failure_stage=
"descriptor_validation",
604 "Partition descriptor canonical operation {} mismatches the " 605 "planner surface".format(index)
613 descriptor_set: NoisyPartitionDescriptorSet,
615 metadata: Mapping[str, Any] |
None =
None,
619 "requested_mode": payload[
"requested_mode"],
620 "provenance": payload[
"provenance"],
622 "qbit_num": payload[
"qbit_num"],
623 "parameter_count": payload[
"parameter_count"],
624 "partition_count": payload[
"partition_count"],
625 "descriptor_member_count": payload[
"descriptor_member_count"],
626 "gate_count": payload[
"gate_count"],
627 "noise_count": payload[
"noise_count"],
628 "max_partition_qubits": payload[
"max_partition_qubits"],
629 "max_partition_span": payload[
"max_partition_span"],
630 "partition_member_counts": payload[
"partition_member_counts"],
631 "remapped_partition_count": sum(
632 partition[
"requires_remap"]
for partition
in payload[
"partitions"]
634 "parameter_routing_segment_count": sum(
635 len(partition[
"parameter_routing"])
636 for partition
in payload[
"partitions"]
639 "partitions": payload[
"partitions"],
640 "metadata": dict(metadata)
if metadata
is not None else {},
def build_descriptor_audit_record
def descriptor_partition_to_dict
def _descriptor_operation_mismatch_category
def build_phase3_continuity_planner_surface
Build a canonical planner surface from a Phase 2 continuity VQE instance.
def descriptor_member_to_dict
def build_partition_descriptor_set
def validate_partition_descriptor_set
def build_phase3_continuity_partition_descriptor_set
def _partition_surface_operations
Partition the operations of a canonical planner surface into partitions.
def _validate_descriptor_request
def preflight_planner_request
def _build_descriptor_partition
def validate_partition_descriptor_set_against_surface
def preflight_descriptor_request