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.
- qcoder/__init__.py +3 -0
- qcoder/__main__.py +6 -0
- qcoder/cli.py +116 -0
- qcoder/core/__init__.py +1 -0
- qcoder/core/context.py +16 -0
- qcoder/core/qasm2/__init__.py +1 -0
- qcoder/core/qasm2/adjoint_eligibility.py +128 -0
- qcoder/core/qasm2/mirror_build.py +234 -0
- qcoder/core/run_config.py +84 -0
- qcoder/core/schema.py +26 -0
- qcoder/engines/feature_extraction/adapters/__init__.py +1 -0
- qcoder/engines/feature_extraction/adapters/qiskit_intake.py +46 -0
- qcoder/engines/feature_extraction/extractor.py +43 -0
- qcoder/engines/feature_extraction/features/compute_v0.py +157 -0
- qcoder/engines/feature_extraction/features/schema_v0.py +84 -0
- qcoder/engines/feature_extraction/ir.py +41 -0
- qcoder/engines/feature_extraction/labeling.py +68 -0
- qcoder/engines/feature_extraction/parsers/__init__.py +21 -0
- qcoder/engines/feature_extraction/qasm2_regex_parser.py +184 -0
- qcoder/engines/feature_extraction/reps/cut_profile.py +106 -0
- qcoder/engines/feature_extraction/reps/depth.py +47 -0
- qcoder/engines/feature_extraction/reps/entangling_layers.py +57 -0
- qcoder/engines/feature_extraction/reps/gate_set_stats.py +82 -0
- qcoder/engines/feature_extraction/reps/interaction_graph.py +30 -0
- qcoder/engines/feature_extraction/reps/interaction_graph_metrics.py +113 -0
- qcoder/engines/feature_extraction/reps/spans.py +89 -0
- qcoder/engines/prediction_model/__init__.py +16 -0
- qcoder/engines/prediction_model/artifact.py +85 -0
- qcoder/engines/prediction_model/engine.py +209 -0
- qcoder/engines/prediction_model/models.py +62 -0
- qcoder/engines/prediction_model/policy.py +45 -0
- qcoder/engines/prediction_model/schema_alignment.py +41 -0
- qcoder/engines/quantumness/__init__.py +8 -0
- qcoder/engines/quantumness/scorer.py +254 -0
- qcoder/pipelines/analyze.py +131 -0
- qcoder/pipelines/batch.py +56 -0
- qcoder/tools/analyze.py +88 -0
- qcoder/tools/analyze_shot_scaling.py +239 -0
- qcoder/tools/batch.py +39 -0
- qcoder/tools/generate_corpus.py +491 -0
- qcoder/tools/harness.py +15 -0
- qcoder/tools/inspect_corpus_features.py +273 -0
- qcoder/tools/join_runs_features.py +252 -0
- qcoder/tools/mirror.py +15 -0
- qcoder/tools/predict_baseline.py +347 -0
- qcoder/tools/qr_dll_bootstrap.py +31 -0
- qcoder/tools/runner.py +15 -0
- qcoder/tools/runners/__init__.py +1 -0
- qcoder/tools/runners/quantum_rings/__init__.py +1 -0
- qcoder/tools/runners/quantum_rings/v12/__init__.py +1 -0
- qcoder/tools/runners/quantum_rings/v12/harness.py +1350 -0
- qcoder/tools/runners/quantum_rings/v12/mirror.py +459 -0
- qcoder/tools/runners/quantum_rings/v12/runner.py +549 -0
- qcoder/tools/train_baseline_models.py +619 -0
- qcoder/tools/validate_baseline.py +307 -0
- qcoder-0.1.0a0.dist-info/METADATA +86 -0
- qcoder-0.1.0a0.dist-info/RECORD +62 -0
- qcoder-0.1.0a0.dist-info/WHEEL +5 -0
- qcoder-0.1.0a0.dist-info/entry_points.txt +2 -0
- qcoder-0.1.0a0.dist-info/licenses/LICENSE +201 -0
- qcoder-0.1.0a0.dist-info/licenses/NOTICE +11 -0
- 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}")
|