qcoder 0.1.0a0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. qcoder/__init__.py +3 -0
  2. qcoder/__main__.py +6 -0
  3. qcoder/cli.py +116 -0
  4. qcoder/core/__init__.py +1 -0
  5. qcoder/core/context.py +16 -0
  6. qcoder/core/qasm2/__init__.py +1 -0
  7. qcoder/core/qasm2/adjoint_eligibility.py +128 -0
  8. qcoder/core/qasm2/mirror_build.py +234 -0
  9. qcoder/core/run_config.py +84 -0
  10. qcoder/core/schema.py +26 -0
  11. qcoder/engines/feature_extraction/adapters/__init__.py +1 -0
  12. qcoder/engines/feature_extraction/adapters/qiskit_intake.py +46 -0
  13. qcoder/engines/feature_extraction/extractor.py +43 -0
  14. qcoder/engines/feature_extraction/features/compute_v0.py +157 -0
  15. qcoder/engines/feature_extraction/features/schema_v0.py +84 -0
  16. qcoder/engines/feature_extraction/ir.py +41 -0
  17. qcoder/engines/feature_extraction/labeling.py +68 -0
  18. qcoder/engines/feature_extraction/parsers/__init__.py +21 -0
  19. qcoder/engines/feature_extraction/qasm2_regex_parser.py +184 -0
  20. qcoder/engines/feature_extraction/reps/cut_profile.py +106 -0
  21. qcoder/engines/feature_extraction/reps/depth.py +47 -0
  22. qcoder/engines/feature_extraction/reps/entangling_layers.py +57 -0
  23. qcoder/engines/feature_extraction/reps/gate_set_stats.py +82 -0
  24. qcoder/engines/feature_extraction/reps/interaction_graph.py +30 -0
  25. qcoder/engines/feature_extraction/reps/interaction_graph_metrics.py +113 -0
  26. qcoder/engines/feature_extraction/reps/spans.py +89 -0
  27. qcoder/engines/prediction_model/__init__.py +16 -0
  28. qcoder/engines/prediction_model/artifact.py +85 -0
  29. qcoder/engines/prediction_model/engine.py +209 -0
  30. qcoder/engines/prediction_model/models.py +62 -0
  31. qcoder/engines/prediction_model/policy.py +45 -0
  32. qcoder/engines/prediction_model/schema_alignment.py +41 -0
  33. qcoder/engines/quantumness/__init__.py +8 -0
  34. qcoder/engines/quantumness/scorer.py +254 -0
  35. qcoder/pipelines/analyze.py +131 -0
  36. qcoder/pipelines/batch.py +56 -0
  37. qcoder/tools/analyze.py +88 -0
  38. qcoder/tools/analyze_shot_scaling.py +239 -0
  39. qcoder/tools/batch.py +39 -0
  40. qcoder/tools/generate_corpus.py +491 -0
  41. qcoder/tools/harness.py +15 -0
  42. qcoder/tools/inspect_corpus_features.py +273 -0
  43. qcoder/tools/join_runs_features.py +252 -0
  44. qcoder/tools/mirror.py +15 -0
  45. qcoder/tools/predict_baseline.py +347 -0
  46. qcoder/tools/qr_dll_bootstrap.py +31 -0
  47. qcoder/tools/runner.py +15 -0
  48. qcoder/tools/runners/__init__.py +1 -0
  49. qcoder/tools/runners/quantum_rings/__init__.py +1 -0
  50. qcoder/tools/runners/quantum_rings/v12/__init__.py +1 -0
  51. qcoder/tools/runners/quantum_rings/v12/harness.py +1350 -0
  52. qcoder/tools/runners/quantum_rings/v12/mirror.py +459 -0
  53. qcoder/tools/runners/quantum_rings/v12/runner.py +549 -0
  54. qcoder/tools/train_baseline_models.py +619 -0
  55. qcoder/tools/validate_baseline.py +307 -0
  56. qcoder-0.1.0a0.dist-info/METADATA +86 -0
  57. qcoder-0.1.0a0.dist-info/RECORD +62 -0
  58. qcoder-0.1.0a0.dist-info/WHEEL +5 -0
  59. qcoder-0.1.0a0.dist-info/entry_points.txt +2 -0
  60. qcoder-0.1.0a0.dist-info/licenses/LICENSE +201 -0
  61. qcoder-0.1.0a0.dist-info/licenses/NOTICE +11 -0
  62. qcoder-0.1.0a0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,273 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import json
5
+ import math
6
+ from collections import Counter, defaultdict
7
+ from pathlib import Path
8
+ from typing import Any
9
+
10
+
11
+ DEFAULT_IMPORTANT_FEATURES = [
12
+ "n_qubits",
13
+ "n_ops",
14
+ "n_2q_gate_ops",
15
+ "real_depth",
16
+ "span_long_range_ratio",
17
+ "span_long_range_ratio_early",
18
+ "span_long_range_ratio_late",
19
+ "ig_edge_density",
20
+ "ig_pair_reuse_hhi",
21
+ "entangling_depth",
22
+ ]
23
+
24
+
25
+ def _norm_path(p: str | None) -> str:
26
+ if not p:
27
+ return ""
28
+ path = Path(p)
29
+ try:
30
+ if path.exists():
31
+ return str(path.resolve())
32
+ except Exception:
33
+ pass
34
+ return str(path.as_posix())
35
+
36
+
37
+ def _load_jsonl(path: str | Path) -> list[dict[str, Any]]:
38
+ rows: list[dict[str, Any]] = []
39
+ with Path(path).open("r", encoding="utf-8") as f:
40
+ for line in f:
41
+ s = line.strip()
42
+ if not s:
43
+ continue
44
+ rows.append(json.loads(s))
45
+ return rows
46
+
47
+
48
+ def _load_manifest(path: str | Path | None) -> dict[str, dict[str, Any]]:
49
+ if not path:
50
+ return {}
51
+ rows = _load_jsonl(path)
52
+ out: dict[str, dict[str, Any]] = {}
53
+ for r in rows:
54
+ raw = r.get("circuit_path")
55
+ key = _norm_path(raw)
56
+ if key:
57
+ out[key] = r
58
+ if raw:
59
+ p = Path(str(raw))
60
+ out[str(p.as_posix())] = r
61
+ out[p.name] = r
62
+ return out
63
+
64
+
65
+ def _extract_feature_payload(rec: dict[str, Any]) -> tuple[list[str], list[float], str]:
66
+ payload = rec.get("features") if isinstance(rec.get("features"), dict) else rec
67
+ names = list(payload.get("feature_names") or [])
68
+ vals = [float(x) for x in (payload.get("features") or [])]
69
+ schema = str(payload.get("schema_version") or "")
70
+ return names, vals, schema
71
+
72
+
73
+ def _stats(vals: list[float]) -> dict[str, float]:
74
+ n = len(vals)
75
+ if n == 0:
76
+ return {"count": 0.0, "min": 0.0, "max": 0.0, "mean": 0.0, "std": 0.0}
77
+ mean = sum(vals) / n
78
+ var = sum((x - mean) ** 2 for x in vals) / n
79
+ return {
80
+ "count": float(n),
81
+ "min": float(min(vals)),
82
+ "max": float(max(vals)),
83
+ "mean": float(mean),
84
+ "std": float(math.sqrt(max(0.0, var))),
85
+ }
86
+
87
+
88
+ def _is_near_constant(vals: list[float], tol: float = 1e-9) -> bool:
89
+ if len(vals) <= 1:
90
+ return True
91
+ return (max(vals) - min(vals)) <= tol
92
+
93
+
94
+ def inspect_feature_coverage(
95
+ *,
96
+ features_jsonl: str | Path,
97
+ manifest_jsonl: str | Path | None = None,
98
+ group_fields: list[str] | None = None,
99
+ important_features: list[str] | None = None,
100
+ ) -> dict[str, Any]:
101
+ rows = _load_jsonl(features_jsonl)
102
+ manifest = _load_manifest(manifest_jsonl)
103
+ group_fields = group_fields or ["source", "family", "subfamily", "width"]
104
+ important_features = important_features or DEFAULT_IMPORTANT_FEATURES
105
+
106
+ parsed_rows: list[dict[str, Any]] = []
107
+ schema_versions: Counter[str] = Counter()
108
+ for rec in rows:
109
+ names, vals, schema = _extract_feature_payload(rec)
110
+ if not names or len(names) != len(vals):
111
+ continue
112
+ f_map = dict(zip(names, vals))
113
+ qasm_path = rec.get("qasm_path") or rec.get("circuit_path")
114
+ pkey = _norm_path(qasm_path)
115
+ meta = manifest.get(pkey, {})
116
+ merged = {
117
+ "qasm_path": qasm_path,
118
+ "features": f_map,
119
+ "schema_version": schema,
120
+ "meta": meta,
121
+ }
122
+ parsed_rows.append(merged)
123
+ schema_versions[schema] += 1
124
+
125
+ # Group counts by requested metadata fields.
126
+ grouped_counts: dict[str, dict[str, int]] = {}
127
+ for gf in group_fields:
128
+ c = Counter()
129
+ for r in parsed_rows:
130
+ v = r["meta"].get(gf)
131
+ if v is None:
132
+ v = "unknown"
133
+ c[str(v)] += 1
134
+ grouped_counts[gf] = dict(sorted(c.items(), key=lambda kv: (kv[0])))
135
+
136
+ # Global feature stats for important features.
137
+ global_feature_stats: dict[str, dict[str, float]] = {}
138
+ near_constant_global: list[str] = []
139
+ for feat in important_features:
140
+ vals = [float(r["features"][feat]) for r in parsed_rows if feat in r["features"]]
141
+ if not vals:
142
+ continue
143
+ global_feature_stats[feat] = _stats(vals)
144
+ if _is_near_constant(vals):
145
+ near_constant_global.append(feat)
146
+
147
+ # Per-family stats (manifest-aware where available).
148
+ family_feature_stats: dict[str, dict[str, dict[str, float]]] = {}
149
+ near_constant_by_family: dict[str, list[str]] = {}
150
+ fam_to_rows: dict[str, list[dict[str, Any]]] = defaultdict(list)
151
+ for r in parsed_rows:
152
+ fam = str(r["meta"].get("family") or "unknown")
153
+ fam_to_rows[fam].append(r)
154
+ for fam in sorted(fam_to_rows):
155
+ ff: dict[str, dict[str, float]] = {}
156
+ nc: list[str] = []
157
+ for feat in important_features:
158
+ vals = [float(r["features"][feat]) for r in fam_to_rows[fam] if feat in r["features"]]
159
+ if not vals:
160
+ continue
161
+ ff[feat] = _stats(vals)
162
+ if _is_near_constant(vals):
163
+ nc.append(feat)
164
+ family_feature_stats[fam] = ff
165
+ near_constant_by_family[fam] = nc
166
+
167
+ # Lightweight separation hints across major synthetic families by feature means.
168
+ separation_hints: dict[str, Any] = {}
169
+ synth_families = sorted([f for f in fam_to_rows if f != "unknown"])
170
+ for feat in important_features:
171
+ means: dict[str, float] = {}
172
+ ranges: dict[str, tuple[float, float]] = {}
173
+ for fam in synth_families:
174
+ vals = [float(r["features"][feat]) for r in fam_to_rows[fam] if feat in r["features"]]
175
+ if not vals:
176
+ continue
177
+ means[fam] = sum(vals) / len(vals)
178
+ ranges[fam] = (min(vals), max(vals))
179
+ if len(means) < 2:
180
+ continue
181
+ sorted_means = sorted(means.items(), key=lambda kv: kv[1], reverse=True)
182
+ # overlap count across family ranges
183
+ fams = list(ranges.keys())
184
+ overlap_pairs = 0
185
+ total_pairs = 0
186
+ for i in range(len(fams)):
187
+ for j in range(i + 1, len(fams)):
188
+ total_pairs += 1
189
+ a0, a1 = ranges[fams[i]]
190
+ b0, b1 = ranges[fams[j]]
191
+ if max(a0, b0) <= min(a1, b1):
192
+ overlap_pairs += 1
193
+ separation_hints[feat] = {
194
+ "family_mean_ranking": sorted_means,
195
+ "range_overlap_pairs": overlap_pairs,
196
+ "range_total_pairs": total_pairs,
197
+ }
198
+
199
+ return {
200
+ "input_features_jsonl": str(features_jsonl),
201
+ "input_manifest_jsonl": str(manifest_jsonl) if manifest_jsonl else None,
202
+ "rows_total": len(parsed_rows),
203
+ "schema_version_counts": dict(sorted(schema_versions.items(), key=lambda kv: kv[0])),
204
+ "grouped_counts": grouped_counts,
205
+ "important_features": important_features,
206
+ "feature_stats_global": global_feature_stats,
207
+ "near_constant_global": sorted(near_constant_global),
208
+ "feature_stats_by_family": family_feature_stats,
209
+ "near_constant_by_family": near_constant_by_family,
210
+ "separation_hints": separation_hints,
211
+ }
212
+
213
+
214
+ def _print_text_summary(summary: dict[str, Any]) -> None:
215
+ print(f"rows_total: {summary.get('rows_total', 0)}")
216
+ print(f"schema_version_counts: {summary.get('schema_version_counts', {})}")
217
+ print("grouped_counts:")
218
+ for gf, counts in (summary.get("grouped_counts") or {}).items():
219
+ print(f" - {gf}: {counts}")
220
+ print("near_constant_global:")
221
+ print(f" {summary.get('near_constant_global', [])}")
222
+ print("feature_stats_global:")
223
+ for feat, s in (summary.get("feature_stats_global") or {}).items():
224
+ print(
225
+ f" - {feat}: min={s['min']:.6g} max={s['max']:.6g} "
226
+ f"mean={s['mean']:.6g} std={s['std']:.6g}"
227
+ )
228
+
229
+
230
+ def main(argv: list[str] | None = None) -> int:
231
+ ap = argparse.ArgumentParser(description="Inspect feature coverage for generated corpus feature JSONL.")
232
+ ap.add_argument(
233
+ "--features-jsonl",
234
+ default="data/features/train_features.jsonl",
235
+ help="Feature JSONL path from qcoder batch.",
236
+ )
237
+ ap.add_argument(
238
+ "--manifest-jsonl",
239
+ default=None,
240
+ help="Optional generated corpus manifest JSONL for metadata-aware grouping.",
241
+ )
242
+ ap.add_argument(
243
+ "--group-fields",
244
+ nargs="+",
245
+ default=["source", "family", "subfamily", "width"],
246
+ help="Metadata fields to group counts by.",
247
+ )
248
+ ap.add_argument(
249
+ "--important-features",
250
+ nargs="+",
251
+ default=DEFAULT_IMPORTANT_FEATURES,
252
+ help="Feature names to summarize.",
253
+ )
254
+ ap.add_argument("--output-json", default=None, help="Optional path to write full JSON summary.")
255
+ args = ap.parse_args(argv)
256
+
257
+ summary = inspect_feature_coverage(
258
+ features_jsonl=args.features_jsonl,
259
+ manifest_jsonl=args.manifest_jsonl,
260
+ group_fields=args.group_fields,
261
+ important_features=args.important_features,
262
+ )
263
+ _print_text_summary(summary)
264
+ if args.output_json:
265
+ outp = Path(args.output_json)
266
+ outp.parent.mkdir(parents=True, exist_ok=True)
267
+ outp.write_text(json.dumps(summary, indent=2, sort_keys=True), encoding="utf-8")
268
+ print(f"[ok] wrote summary json: {outp}")
269
+ return 0
270
+
271
+
272
+ if __name__ == "__main__":
273
+ raise SystemExit(main())
@@ -0,0 +1,252 @@
1
+ import json
2
+ import hashlib
3
+ import csv
4
+ from pathlib import Path
5
+
6
+ FEATURE_FILE = Path("data/features/train_features.jsonl")
7
+ RUN_FILE = Path("data/runs/run_records.jsonl")
8
+
9
+ OUTPUT_RUNTIME = Path("data/training/runtime_table.jsonl")
10
+ OUTPUT_FIDELITY = Path("data/training/fidelity_table.jsonl")
11
+ OUTPUT_JOINED = Path("data/training/joined_observations.jsonl")
12
+ OUTPUT_JOINED_CSV = Path("data/training/joined_observations.csv")
13
+ OUTPUT_JOINED_OK = Path("data/training/joined_observations_ok.jsonl")
14
+ OUTPUT_JOINED_OK_CSV = Path("data/training/joined_observations_ok.csv")
15
+
16
+
17
+ def sha256_file(path: str) -> str:
18
+ h = hashlib.sha256()
19
+ with open(path, "rb") as f:
20
+ for chunk in iter(lambda: f.read(65536), b""):
21
+ h.update(chunk)
22
+ return h.hexdigest()
23
+
24
+
25
+ def _extract_feature_payload(rec: dict) -> tuple[str | None, list, list]:
26
+ payload = rec.get("features") if isinstance(rec.get("features"), dict) else rec
27
+ schema_version = payload.get("schema_version")
28
+ feature_names = payload.get("feature_names") or []
29
+ features = payload.get("features") or []
30
+ return schema_version, list(feature_names), list(features)
31
+
32
+
33
+ def load_features():
34
+ features = {}
35
+ with FEATURE_FILE.open("r", encoding="utf-8") as f:
36
+ for line in f:
37
+ rec = json.loads(line)
38
+
39
+ content_hash = rec.get("content_hash")
40
+ if not content_hash:
41
+ qasm_path = rec.get("qasm_path")
42
+ if not qasm_path:
43
+ continue
44
+ content_hash = sha256_file(qasm_path)
45
+
46
+ schema_version, feature_names, feature_values = _extract_feature_payload(rec)
47
+ features[content_hash] = {
48
+ "content_hash": content_hash,
49
+ "circuit_name": rec.get("circuit_name"),
50
+ "qasm_path": rec.get("qasm_path"),
51
+ "schema_version": schema_version,
52
+ "feature_names": feature_names,
53
+ "features": feature_values,
54
+ }
55
+
56
+ return features
57
+
58
+
59
+ def _build_joined_row(run: dict, feature_row: dict, content_hash: str) -> dict:
60
+ run_kind = run.get("run_kind", "")
61
+ runtime_wall_s = run.get("runtime_wall_s")
62
+ mirror_wall_s = run.get("mirror_wall_s")
63
+ probe_wall_s = run.get("probe_wall_s")
64
+ runner_wall_s = run.get("runner_wall_s")
65
+ shots_mirror = run.get("shots_mirror")
66
+ shots_runner = run.get("shots_runner")
67
+
68
+ if mirror_wall_s is None and run_kind == "mirror_threshold_attempt":
69
+ mirror_wall_s = runtime_wall_s
70
+ if runner_wall_s is None and run_kind == "forward_runner_execution":
71
+ runner_wall_s = runtime_wall_s
72
+ if shots_mirror is None and run_kind == "mirror_threshold_attempt":
73
+ shots_mirror = run.get("shots")
74
+ if shots_runner is None and run_kind == "forward_runner_execution":
75
+ shots_runner = run.get("shots")
76
+
77
+ return {
78
+ "content_hash": content_hash,
79
+ "circuit_name": feature_row.get("circuit_name") or run.get("circuit_name"),
80
+ "qasm_path": run.get("qasm_path") or feature_row.get("qasm_path"),
81
+ "schema_version": feature_row.get("schema_version"),
82
+ "backend_id": run.get("backend_id") or run.get("backend"),
83
+ "precision": run.get("precision"),
84
+ "threshold": run.get("threshold"),
85
+ "env_id": run.get("env_id") or "",
86
+ "status": run.get("status"),
87
+ "error_code": run.get("error_code") or run.get("error_type") or "",
88
+ "error_detail": run.get("error_detail") or run.get("error_message") or "",
89
+ "mirror_wall_s": mirror_wall_s,
90
+ "probe_wall_s": probe_wall_s,
91
+ "runner_wall_s": runner_wall_s,
92
+ "shots_mirror": shots_mirror,
93
+ "shots_runner": shots_runner,
94
+ "fidelity": run.get("fidelity"),
95
+ "peak_rss_mb": run.get("peak_rss_mb"),
96
+ "feature_names": feature_row.get("feature_names", []),
97
+ "features": feature_row.get("features", []),
98
+ "run_kind": run_kind,
99
+ }
100
+
101
+
102
+ def _csv_fieldnames(rows: list[dict]) -> list[str]:
103
+ if not rows:
104
+ return []
105
+ feature_names = rows[0].get("feature_names", [])
106
+ base = [
107
+ "content_hash",
108
+ "circuit_name",
109
+ "qasm_path",
110
+ "schema_version",
111
+ "backend_id",
112
+ "precision",
113
+ "threshold",
114
+ "env_id",
115
+ "status",
116
+ "error_code",
117
+ "error_detail",
118
+ "mirror_wall_s",
119
+ "probe_wall_s",
120
+ "runner_wall_s",
121
+ "shots_mirror",
122
+ "shots_runner",
123
+ "fidelity",
124
+ "peak_rss_mb",
125
+ "run_kind",
126
+ ]
127
+ return base + list(feature_names)
128
+
129
+
130
+ def _row_for_csv(row: dict) -> dict:
131
+ out = {
132
+ "content_hash": row.get("content_hash"),
133
+ "circuit_name": row.get("circuit_name"),
134
+ "qasm_path": row.get("qasm_path"),
135
+ "schema_version": row.get("schema_version"),
136
+ "backend_id": row.get("backend_id"),
137
+ "precision": row.get("precision"),
138
+ "threshold": row.get("threshold"),
139
+ "env_id": row.get("env_id"),
140
+ "status": row.get("status"),
141
+ "error_code": row.get("error_code"),
142
+ "error_detail": row.get("error_detail"),
143
+ "mirror_wall_s": row.get("mirror_wall_s"),
144
+ "probe_wall_s": row.get("probe_wall_s"),
145
+ "runner_wall_s": row.get("runner_wall_s"),
146
+ "shots_mirror": row.get("shots_mirror"),
147
+ "shots_runner": row.get("shots_runner"),
148
+ "fidelity": row.get("fidelity"),
149
+ "peak_rss_mb": row.get("peak_rss_mb"),
150
+ "run_kind": row.get("run_kind"),
151
+ }
152
+ for name, value in zip(row.get("feature_names", []), row.get("features", [])):
153
+ out[name] = value
154
+ return out
155
+
156
+
157
+ def _write_jsonl(path: Path, rows: list[dict]) -> None:
158
+ path.parent.mkdir(parents=True, exist_ok=True)
159
+ with path.open("w", encoding="utf-8") as f:
160
+ for row in rows:
161
+ f.write(json.dumps(row) + "\n")
162
+
163
+
164
+ def _write_csv(path: Path, rows: list[dict]) -> None:
165
+ path.parent.mkdir(parents=True, exist_ok=True)
166
+ fieldnames = _csv_fieldnames(rows)
167
+ if not fieldnames:
168
+ with path.open("w", encoding="utf-8"):
169
+ pass
170
+ return
171
+ with path.open("w", encoding="utf-8", newline="") as f:
172
+ writer = csv.DictWriter(f, fieldnames=fieldnames)
173
+ writer.writeheader()
174
+ for row in rows:
175
+ writer.writerow(_row_for_csv(row))
176
+
177
+
178
+ def main():
179
+ features = load_features()
180
+
181
+ OUTPUT_RUNTIME.parent.mkdir(parents=True, exist_ok=True)
182
+ OUTPUT_JOINED.parent.mkdir(parents=True, exist_ok=True)
183
+
184
+ joined_rows = []
185
+
186
+ with RUN_FILE.open("r", encoding="utf-8") as f:
187
+
188
+ for line in f:
189
+ run = json.loads(line)
190
+
191
+ run_kind = run.get("run_kind")
192
+ if run_kind not in {"forward_runner_execution", "mirror_threshold_attempt"}:
193
+ continue
194
+
195
+ content_hash = run.get("content_hash")
196
+ if not content_hash:
197
+ qasm_path = run.get("qasm_path")
198
+ if not qasm_path:
199
+ continue
200
+ content_hash = sha256_file(qasm_path)
201
+
202
+ feature_row = features.get(content_hash)
203
+ if feature_row is None:
204
+ continue
205
+
206
+ joined_rows.append(_build_joined_row(run, feature_row, content_hash))
207
+
208
+ joined_ok_rows = [r for r in joined_rows if r.get("status") == "ok"]
209
+ runtime_rows = [
210
+ {
211
+ "content_hash": r.get("content_hash"),
212
+ "backend_id": r.get("backend_id"),
213
+ "precision": r.get("precision"),
214
+ "threshold": r.get("threshold"),
215
+ "runtime_wall_s": r.get("runner_wall_s"),
216
+ "shots_runner": r.get("shots_runner"),
217
+ "features": r.get("features"),
218
+ "feature_names": r.get("feature_names"),
219
+ "schema_version": r.get("schema_version"),
220
+ "qasm_path": r.get("qasm_path"),
221
+ "circuit_name": r.get("circuit_name"),
222
+ }
223
+ for r in joined_ok_rows
224
+ if r.get("run_kind") == "forward_runner_execution" and r.get("runner_wall_s") is not None
225
+ ]
226
+ fidelity_rows = [
227
+ {
228
+ "content_hash": r.get("content_hash"),
229
+ "backend_id": r.get("backend_id"),
230
+ "precision": r.get("precision"),
231
+ "threshold": r.get("threshold"),
232
+ "fidelity": r.get("fidelity"),
233
+ "features": r.get("features"),
234
+ "feature_names": r.get("feature_names"),
235
+ "schema_version": r.get("schema_version"),
236
+ "qasm_path": r.get("qasm_path"),
237
+ "circuit_name": r.get("circuit_name"),
238
+ }
239
+ for r in joined_ok_rows
240
+ if r.get("run_kind") == "mirror_threshold_attempt" and r.get("fidelity") is not None
241
+ ]
242
+
243
+ _write_jsonl(OUTPUT_JOINED, joined_rows)
244
+ _write_csv(OUTPUT_JOINED_CSV, joined_rows)
245
+ _write_jsonl(OUTPUT_JOINED_OK, joined_ok_rows)
246
+ _write_csv(OUTPUT_JOINED_OK_CSV, joined_ok_rows)
247
+ _write_jsonl(OUTPUT_RUNTIME, runtime_rows)
248
+ _write_jsonl(OUTPUT_FIDELITY, fidelity_rows)
249
+
250
+
251
+ if __name__ == "__main__":
252
+ main()
qcoder/tools/mirror.py ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ qcoder.tools.mirror — entrypoint that delegates to Quantum Rings v12 mirror.
4
+ """
5
+ from qcoder.tools.runners.quantum_rings.v12.mirror import main, die
6
+
7
+ if __name__ == "__main__":
8
+ try:
9
+ main()
10
+ except SystemExit:
11
+ raise
12
+ except Exception as e:
13
+ import traceback
14
+ traceback.print_exc()
15
+ die(f"Unhandled exception: {e}")