Sequential Quantum Gate Decomposer  v1.9.6
Powerful decomposition of general unitarias into one- and two-qubit gates gates
unsupported_descriptor_validation.py
Go to the documentation of this file.
1 #!/usr/bin/env python3
2 """Unsupported partition-descriptor boundary validation.
3 
4 Exercises representative unsupported or lossy descriptor-generation situations
5 and records the stable no-fallback outcome for each one. Unsupported descriptor
6 requests fail before runtime and are not silently relabeled as supported
7 descriptor behavior.
8 
9 Run with:
10  python benchmarks/density_matrix/planner_surface/unsupported_descriptor_validation.py
11 """
12 
13 from __future__ import annotations
14 
15 import argparse
16 import json
17 import sys
18 from dataclasses import replace
19 from pathlib import Path
20 
21 REPO_ROOT = Path(__file__).resolve().parents[3]
22 if str(REPO_ROOT) not in sys.path:
23  sys.path.insert(0, str(REPO_ROOT))
24 
25 from benchmarks.density_matrix.planner_surface.common import (
26  build_phase2_continuity_vqe,
27  build_software_metadata,
28 )
29 from benchmarks.density_matrix.planner_surface.workloads import (
30  build_microcase_descriptor_set,
31  build_microcase_surface,
32 )
33 from squander.partitioning.noisy_planner import (
34  PLANNER_OP_KIND_GATE,
35  PLANNER_OP_KIND_NOISE,
36  preflight_descriptor_request,
37  validate_partition_descriptor_set_against_surface,
38 )
39 
40 SUITE_NAME = "phase3_planner_surface_unsupported_descriptors"
41 ARTIFACT_FILENAME = "unsupported_descriptor_bundle.json"
42 DEFAULT_OUTPUT_DIR = (
43  REPO_ROOT
44  / "benchmarks"
45  / "density_matrix"
46  / "artifacts"
47  / "planner_surface"
48  / "unsupported_descriptor"
49 )
50 ARTIFACT_CORE_FIELDS = (
51  "suite_name",
52  "status",
53  "software",
54  "summary",
55  "cases",
56 )
57 
58 
59 def _unsupported_case(case_name: str, runner) -> dict:
60  try:
61  runner()
62  except Exception as err:
63  payload = err.to_dict() if hasattr(err, "to_dict") else {"reason": str(err)}
64  payload.update(
65  {
66  "case_name": case_name,
67  "status": "unsupported",
68  "supported_descriptor_case_recorded": False,
69  }
70  )
71  return payload
72  return {
73  "case_name": case_name,
74  "status": "unexpected_pass",
75  "supported_descriptor_case_recorded": False,
76  "reason": "unsupported descriptor case unexpectedly passed",
77  }
78 
79 
81  continuity_vqe, _, _ = build_phase2_continuity_vqe(4)
82  bridge = continuity_vqe.describe_density_bridge()
83  return continuity_vqe, bridge
84 
85 
87  surface = build_microcase_surface("microcase_4q_partition_boundary_triplet")
88  descriptor_set = build_microcase_descriptor_set(
89  "microcase_4q_partition_boundary_triplet"
90  )
91  partitions = list(descriptor_set.partitions)
92  last_partition = partitions[-1]
93  partitions[-1] = replace(last_partition, members=last_partition.members[:-1])
94  tampered = replace(descriptor_set, partitions=tuple(partitions))
95  return lambda: validate_partition_descriptor_set_against_surface(surface, tampered)
96 
97 
99  surface = build_microcase_surface("microcase_4q_partition_boundary_triplet")
100  descriptor_set = build_microcase_descriptor_set(
101  "microcase_4q_partition_boundary_triplet"
102  )
103  partitions = list(descriptor_set.partitions)
104  for partition_index, partition in enumerate(partitions):
105  for member_index, member in enumerate(partition.members):
106  if (
107  descriptor_set.operations[member.canonical_operation_index].kind
108  == PLANNER_OP_KIND_NOISE
109  ):
110  ops = list(descriptor_set.operations)
111  idx = member.canonical_operation_index
112  ops[idx] = replace(
113  ops[idx],
114  kind=PLANNER_OP_KIND_GATE,
115  is_unitary=True,
116  )
117  tampered = replace(descriptor_set, operations=tuple(ops))
119  surface, tampered
120  )
121  raise ValueError("No noise member available for hidden-noise negative case")
122 
123 
125  surface = build_microcase_surface("microcase_4q_partition_boundary_triplet")
126  descriptor_set = build_microcase_descriptor_set(
127  "microcase_4q_partition_boundary_triplet"
128  )
129  partitions = list(descriptor_set.partitions)
130  for partition_index, partition in enumerate(partitions):
131  if not partition.requires_remap or len(partition.local_to_global_qbits) < 2:
132  continue
133  for member_index, member in enumerate(partition.members):
134  if member.local_target_qbit is None:
135  continue
136  wrong_local_target = (member.local_target_qbit + 1) % len(
137  partition.local_to_global_qbits
138  )
139  if wrong_local_target == member.local_target_qbit:
140  continue
141  members = list(partition.members)
142  members[member_index] = replace(
143  member, local_target_qbit=wrong_local_target
144  )
145  partitions[partition_index] = replace(partition, members=tuple(members))
146  tampered = replace(descriptor_set, partitions=tuple(partitions))
148  surface, tampered
149  )
150  raise ValueError("No remapped partition available for incomplete-remap case")
151 
152 
154  surface = build_microcase_surface("microcase_4q_partition_boundary_triplet")
155  descriptor_set = build_microcase_descriptor_set(
156  "microcase_4q_partition_boundary_triplet"
157  )
158  partitions = list(descriptor_set.partitions)
159  for partition_index, partition in enumerate(partitions):
160  for member_index, member in enumerate(partition.members):
161  if (
162  descriptor_set.operations[member.canonical_operation_index].param_count
163  <= 0
164  ):
165  continue
166  members = list(partition.members)
167  members[member_index] = replace(
168  member, local_param_start=member.local_param_start + 1
169  )
170  partitions[partition_index] = replace(partition, members=tuple(members))
171  tampered = replace(descriptor_set, partitions=tuple(partitions))
173  surface, tampered
174  )
175  raise ValueError("No parameterized member available for ambiguous-routing case")
176 
177 
179  surface = build_microcase_surface("microcase_4q_partition_boundary_triplet")
180  descriptor_set = build_microcase_descriptor_set(
181  "microcase_4q_partition_boundary_triplet"
182  )
183  partitions = list(descriptor_set.partitions)
184  for partition_index, partition in enumerate(partitions):
185  if (
186  descriptor_set.partition_noise_count(partition) == 0
187  or partition.member_count < 2
188  ):
189  continue
190  members = list(partition.members)
191  members[0], members[1] = members[1], members[0]
192  partitions[partition_index] = replace(partition, members=tuple(members))
193  tampered = replace(descriptor_set, partitions=tuple(partitions))
195  surface, tampered
196  )
197  raise ValueError("No mixed partition available for reordering negative case")
198 
199 
201  _, continuity_bridge = _build_continuity_bridge_request()
202  return [
204  "partition_qubits_too_small",
206  source_type="generated_hea",
207  workload_id="phase2_xxz_hea_q4_continuity",
208  bridge_metadata=continuity_bridge,
209  max_partition_qubits=1,
210  ),
211  ),
213  _unsupported_case("hidden_noise_placement", _hide_noise_member_runner()),
214  _unsupported_case("incomplete_remapping", _incomplete_remap_runner()),
216  "ambiguous_parameter_routing", _ambiguous_parameter_routing_runner()
217  ),
219  "reordering_across_noise_boundaries", _reordered_descriptor_runner()
220  ),
221  ]
222 
223 
224 def build_artifact_bundle(cases: list[dict]) -> dict:
225  unsupported_cases = sum(case["status"] == "unsupported" for case in cases)
226  unexpected_passes = sum(case["status"] == "unexpected_pass" for case in cases)
227  bundle = {
228  "suite_name": SUITE_NAME,
229  "status": "pass"
230  if unsupported_cases == len(cases) and unexpected_passes == 0
231  else "fail",
232  "software": build_software_metadata(),
233  "summary": {
234  "total_cases": len(cases),
235  "unsupported_cases": unsupported_cases,
236  "unexpected_passes": unexpected_passes,
237  },
238  "cases": cases,
239  }
240  missing = [field for field in ARTIFACT_CORE_FIELDS if field not in bundle]
241  if missing:
242  raise ValueError(
243  "Unsupported descriptor bundle missing required fields: {}".format(
244  ", ".join(missing)
245  )
246  )
247  return bundle
248 
249 
250 def write_artifact_bundle(bundle: dict, output_dir: Path = DEFAULT_OUTPUT_DIR) -> Path:
251  output_dir.mkdir(parents=True, exist_ok=True)
252  output_path = output_dir / ARTIFACT_FILENAME
253  output_path.write_text(json.dumps(bundle, indent=2, sort_keys=True) + "\n")
254  return output_path
255 
256 
257 def main(argv: list[str] | None = None) -> int:
258  parser = argparse.ArgumentParser(description=__doc__)
259  parser.add_argument(
260  "--output-dir",
261  type=Path,
262  default=DEFAULT_OUTPUT_DIR,
263  help="Directory to write the unsupported descriptor bundle into.",
264  )
265  parser.add_argument(
266  "--quiet",
267  action="store_true",
268  help="Suppress per-case console output.",
269  )
270  args = parser.parse_args(argv)
271 
273  bundle = build_artifact_bundle(cases)
274  output_path = write_artifact_bundle(bundle, output_dir=args.output_dir)
275 
276  if not args.quiet:
277  for case in cases:
278  print("{case_name}: {status}".format(**case))
279  print("Wrote {}".format(output_path))
280 
281  return 0 if bundle["status"] == "pass" else 1
282 
283 
284 if __name__ == "__main__":
285  raise SystemExit(main())
def build_phase2_continuity_vqe
def build_software_metadata()
def validate_partition_descriptor_set_against_surface