itsalissonsilva commited on
Commit
0520f67
·
verified ·
1 Parent(s): f25e595

Release independently executed all-framework quantum adapter with stress failures, helper parity and original negative study preserved

Browse files
LICENSE ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright 2026 Alibaba Cloud
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
NOTICE ADDED
@@ -0,0 +1 @@
 
 
1
+ QuantumCoder-9B: modified Qwen3.5-9B with a newly trained low-rank adapter by itsalissonsilva. Base model and software are Apache2.0. Original synthetic curriculum is separately CC BY4.0; see curriculum_v2/LICENSE.md. No upstream base weights redistributed.
README.md ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ library_name: peft
4
+ pipeline_tag: text-generation
5
+ base_model: Qwen/Qwen3.5-9B
6
+ tags:
7
+ - quantum-computing
8
+ - circuit-to-code
9
+ - lora
10
+ - synthetic-data
11
+ ---
12
+ # QuantumCoder-9B
13
+
14
+ A rank 16 Qwen3.5-9B adapter for translating fully specified synthetic quantum circuits into Qiskit, PennyLane or Cirq Python. The independently executed follow-up passes 288/288 held-out circuit/framework cases and 282/288 larger stress cases. The saved-weight helper reproduces all eight fixed validation generations exactly.
15
+
16
+ **A deterministic renderer already solves this structured task perfectly.** This is learned circuit-to-program translation, including framework APIs and little-endian state conventions. It is not quantum algorithm discovery, general quantum programming, full unitary verification or a result on real quantum hardware.
17
+
18
+ ## Results
19
+
20
+ One greedy sample, 768 generated-token cap, thinking disabled. Passing requires requested-framework import, supported-Python execution, unit norm and global-phase-invariant zero-input state fidelity greater than 1−1e−6.
21
+
22
+ | Split | Circuit groups | Framework cases | Base passes | Adapter passes |
23
+ |---|---:|---:|---:|---:|
24
+ | Validation |48|144|16 (11.11%)|144 (100%)|
25
+ | Held-out circuits/angles |96|288|36 (12.50%)|288 (100%)|
26
+ | Larger/nonlocal/deeper stress |96|288|47 (16.32%)|282 (97.92%)|
27
+
28
+ Each circuit appears in all three frameworks; these are not 288 independent circuits. Circuit-group bootstrap 95% intervals for adapter-minus-base Pass@1 are [83.33,91.32] percentage points on the held-out split and [77.78,85.42] on stress. Six stress failures remain included. Per-framework results and every scored program are under [v2_execution](v2_execution/).
29
+
30
+ The executor is deliberately restricted and may reject other valid Python/API implementations. These percentages measure supported-program compliance plus state correctness, not unrestricted programming ability. The base executed 130/288 held-out programs and 114/288 stress programs; 36 and 47 respectively had correct states. The adapter executed all 288 in each split. Import presence is a compliance proxy, not a formal data-flow proof.
31
+
32
+ ## Data and training
33
+
34
+ The fresh [curriculum](curriculum_v2/) has 456 circuit groups / 1,368 framework views: 216/648 training, 48/144 validation and 96/288 in each test split. Training contains all three frameworks. All 2,000 original-study circuit groups were excluded. Group IDs, rotation-angle sets and input hashes are disjoint across partitions; an independent audit finds no exact zero-input-state duplicates between training and matching-dimension holdouts at fidelity tolerance 1e−8. This does not establish full process-equivalence separation.
35
+
36
+ Training uses 2–4 qubits, adjacent CNOTs and 6–13 gates. Stress uses 5–6 qubits, nonlocal CNOTs and 16–24 gates. Gates are H/X/Z/RY/RZ/CX. All 1,368 reference programs passed the pinned three-framework executor before model scoring. Data are original synthetic circuits with exact statevectors, not experimental measurements.
37
+
38
+ Base [Qwen3.5-9B](https://huggingface.co/Qwen/Qwen3.5-9B), revision `c202236235762e1c871ad0ccb60c8ee5ba337b9a`. One fixed epoch from the base, 648 examples, rank 16/alpha 32 on q_proj/v_proj/in_proj_qkv, AdamW learning rate 2e−5, gradient accumulation 8, seed 20261101, max training sequence 2,048. No test checkpoint selection. Training code, original programs, model outputs and audits remain in this repository.
39
+
40
+ ## Inference
41
+
42
+ Download this repository and install `requirements-inference.txt` in a CUDA environment with enough memory for 9B weights (the checked configuration used an A100). From the downloaded repository:
43
+
44
+ ```python
45
+ from quantum import QuantumCoder
46
+ coder = QuantumCoder()
47
+ result = coder.generate([{
48
+ "framework": "cirq", "qubits": 2,
49
+ "operations": [["h", [0], 0.0], ["ry", [1], 0.31],
50
+ ["rz", [0], 0.67], ["cx", [0, 1], 0.0],
51
+ ["h", [1], 0.0], ["z", [0], 0.0]]
52
+ }])[0]
53
+ print(result["program"])
54
+ ```
55
+
56
+ The helper returns fallible source text and never executes it. `operations` follows [gate,qubit_indices,angle_in_radians]; non-rotation angles are 0. The measured limits are 2–6 qubits and at most 24 gates. Prompts beyond 2,048 tokens are rejected rather than truncated. Generation matches the frozen greedy 768-token protocol in batches of eight.
57
+
58
+ ## Reproduce execution
59
+
60
+ Use an isolated Linux environment with Python 3.11, `libseccomp2` and `requirements-evaluation.txt`. The parent must run as root so workers can drop to UID/GID 65534. From a full repository snapshot, run `python reproduce_execution.py`. It first verifies the frozen sandbox/data hashes, isolation and every selected reference, then re-scores all 1,440 base/adapted programs and checks the published counts. This public reproducer was run successfully before release. Do not substitute direct host execution for the provided runner.
61
+
62
+ Workers clear their environment, deny filesystem opens/network/process execution, apply resource/time limits and screen a bounded Python subset. This is an evaluation harness for these programs, not a general arbitrary-code sandbox service. Original full scoring source and circuit-group bootstrap remain under[v2_execution](v2_execution/); helper parity is under[helper_verification](helper_verification/).
63
+
64
+ ## Original negative study
65
+
66
+ The earlier [hf_pilot](hf_pilot/) trained on Qiskit/PennyLane and held out Cirq. Its adapter passed 0/128 Cirq cases versus 3/128 for the base under the original strict executor. Some valid Cirq aliases were unsupported there. The failure and original evaluator remain under [execution](execution/) and [executor_preflight](executor_preflight/). The new study uses fresh groups and explicitly trains all frameworks; it is not a zero-shot Cirq success and does not replace that negative result.
67
+
68
+ ## Licensing
69
+
70
+ Adapter/base-derived weights and code: Apache 2.0; base attribution retained in LICENSE/NOTICE. Original synthetic data: [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), attributed to itsalissonsilva. Quantum frameworks have their own upstream licenses and are not redistributed as part of the adapter.
adapter_config.json ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "alora_invocation_tokens": null,
3
+ "alpha_pattern": {},
4
+ "arrow_config": null,
5
+ "auto_mapping": null,
6
+ "base_model_name_or_path": "Qwen/Qwen3.5-9B",
7
+ "bias": "none",
8
+ "corda_config": null,
9
+ "ensure_weight_tying": false,
10
+ "eva_config": null,
11
+ "exclude_modules": null,
12
+ "fan_in_fan_out": false,
13
+ "inference_mode": true,
14
+ "init_lora_weights": true,
15
+ "layer_replication": null,
16
+ "layers_pattern": null,
17
+ "layers_to_transform": null,
18
+ "loftq_config": {},
19
+ "lora_alpha": 32,
20
+ "lora_bias": false,
21
+ "lora_dropout": 0.0,
22
+ "megatron_config": null,
23
+ "megatron_core": "megatron.core",
24
+ "modules_to_save": null,
25
+ "peft_type": "LORA",
26
+ "peft_version": "0.18.1",
27
+ "qalora_group_size": 16,
28
+ "r": 16,
29
+ "rank_pattern": {},
30
+ "revision": null,
31
+ "target_modules": [
32
+ "in_proj_qkv",
33
+ "q_proj",
34
+ "v_proj"
35
+ ],
36
+ "target_parameters": null,
37
+ "task_type": "CAUSAL_LM",
38
+ "trainable_token_indices": null,
39
+ "use_dora": false,
40
+ "use_qalora": false,
41
+ "use_rslora": false
42
+ }
adapter_model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:0261aa5f75e7966692383136ec7d5ac7fc9ab9caaeb94483ceba5bcbda932823
3
+ size 27799552
prompt_parity.json ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ {
2
+ "cases": 1368,
3
+ "exact_training_prompt_parity": true,
4
+ "helper_sha256": "c11b9a8d6f74fec142a4568b50614ff574f9e2f1211e6260a7ddc0a15dcb256d"
5
+ }
quantum.py ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Generate bounded circuit-to-Python candidates. This module never executes them."""
2
+
3
+ import json
4
+ import math
5
+
6
+ import torch
7
+ from peft import PeftModel
8
+ from transformers import AutoTokenizer,Qwen3_5ForConditionalGeneration
9
+
10
+ BASE="Qwen/Qwen3.5-9B"
11
+ BASE_REVISION="c202236235762e1c871ad0ccb60c8ee5ba337b9a"
12
+ ADAPTER="itsalissonsilva/QuantumCoder-9B"
13
+
14
+
15
+ def circuit_prompt(framework,qubits,operations):
16
+ if framework not in {"qiskit","pennylane","cirq"}:
17
+ raise ValueError("framework must be qiskit, pennylane or cirq")
18
+ if type(qubits) is not int or not 2<=qubits<=6:
19
+ raise ValueError("The measured scope is two through six qubits")
20
+ if not isinstance(operations,(list,tuple)) or not 1<=len(operations)<=24:
21
+ raise ValueError("Provide one through24 operations")
22
+ normalized=[]
23
+ for operation in operations:
24
+ if not isinstance(operation,(list,tuple)) or len(operation)!=3:
25
+ raise ValueError("Each operation must be [gate,qubit_indices,angle]")
26
+ gate,indices,angle=operation
27
+ if gate not in {"h","x","z","ry","rz","cx"}:
28
+ raise ValueError("Supported gates: h, x, z, ry, rz, cx")
29
+ if not isinstance(indices,(list,tuple)) or len(indices)!=(2 if gate=="cx" else 1):
30
+ raise ValueError("Gate arity mismatch")
31
+ if any(type(k) is not int or not 0<=k<qubits for k in indices) or len(set(indices))!=len(indices):
32
+ raise ValueError("Invalid/repeated qubit index")
33
+ if type(angle) not in (int,float) or not math.isfinite(angle):
34
+ raise ValueError("Angle must be a finite real number")
35
+ if gate not in {"ry","rz"} and angle!=0:
36
+ raise ValueError("Non-rotation gates require angle0")
37
+ normalized.append([gate,list(indices),float(angle)])
38
+ return [
39
+ dict(role="system",content="Return only Python source code using the requested quantum framework. No prose or markdown."),
40
+ dict(role="user",content=f"Write a {framework} program preparing this circuit from zero on {qubits} qubits. Operations [gate,qubits,angle]: {json.dumps(normalized)}. Angles are radians. Store the final statevector in a variable named state. Use little-endian qubit order."),
41
+ ]
42
+
43
+
44
+ class QuantumCoder:
45
+ def __init__(self,adapter=ADAPTER,revision=None,subfolder=None):
46
+ if not torch.cuda.is_available():
47
+ raise RuntimeError("This measured inference configuration requires a CUDA GPU with enough memory for9B weights")
48
+ self.tokenizer=AutoTokenizer.from_pretrained(BASE,revision=BASE_REVISION)
49
+ self.tokenizer.padding_side="left"
50
+ dtype=torch.bfloat16 if torch.cuda.is_bf16_supported() else torch.float16
51
+ base=Qwen3_5ForConditionalGeneration.from_pretrained(BASE,revision=BASE_REVISION,dtype=dtype,
52
+ device_map="cuda",attn_implementation="sdpa")
53
+ kwargs=dict(revision=revision)
54
+ if subfolder is not None:
55
+ kwargs["subfolder"]=subfolder
56
+ self.model=PeftModel.from_pretrained(base,adapter,**kwargs).eval()
57
+
58
+ @torch.no_grad()
59
+ def generate(self,circuits):
60
+ """Return program/token metadata for dictionaries with framework/qubits/operations.
61
+
62
+ Programs are fallible text, including possible unsupported APIs. For
63
+ measured execution use the separately provided isolated Linux evaluator.
64
+ """
65
+ prompts=[]
66
+ for circuit in circuits:
67
+ messages=circuit_prompt(circuit["framework"],circuit["qubits"],circuit["operations"])
68
+ text=self.tokenizer.apply_chat_template(messages,tokenize=False,add_generation_prompt=True,enable_thinking=False)
69
+ if len(self.tokenizer.encode(text))>2048:
70
+ raise ValueError("Prompt exceeds the measured2048-token bound; no truncation applied")
71
+ prompts.append(text)
72
+ results=[]
73
+ eos=self.model.generation_config.eos_token_id
74
+ eos=set(eos if isinstance(eos,list) else [eos])
75
+ for begin in range(0,len(prompts),8):
76
+ inputs=self.tokenizer(prompts[begin:begin+8],padding=True,return_tensors="pt").to("cuda")
77
+ generated=self.model.generate(**inputs,max_new_tokens=768,do_sample=False,
78
+ pad_token_id=self.tokenizer.pad_token_id)
79
+ for tokens in generated[:,inputs["input_ids"].shape[1]:]:
80
+ ids=tokens.tolist();stop=next((i for i,t in enumerate(ids) if t in eos),None)
81
+ used=ids if stop is None else ids[:stop+1]
82
+ results.append(dict(program=self.tokenizer.decode(used,skip_special_tokens=True),generated_tokens=len(used),
83
+ eos_observed=stop is not None,at_token_cap=stop is None and len(used)>=768))
84
+ return results
quantum_sandbox_v2.py ADDED
@@ -0,0 +1,317 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """V2 restricted quantum executor; v1 remains frozen in quantum_sandbox.py.
2
+
3
+ AST screening is combined with nobody UID, cleared environment, process/resource
4
+ limits and seccomp denial of filesystem opens, networking and process execution.
5
+ Libraries are imported/warmed in the parent before any untrusted code runs.
6
+ """
7
+
8
+ import ast
9
+ import contextlib
10
+ import ctypes
11
+ import ctypes.util
12
+ import errno
13
+ import importlib
14
+ import io
15
+ import multiprocessing as mp
16
+ import os
17
+ import resource
18
+
19
+ for variable in ["OPENBLAS_NUM_THREADS", "OMP_NUM_THREADS", "MKL_NUM_THREADS"]:
20
+ os.environ[variable] = "1"
21
+
22
+ import numpy as np
23
+
24
+ MODULES = {
25
+ "numpy",
26
+ "numpy.linalg",
27
+ "math",
28
+ "cmath",
29
+ "qiskit",
30
+ "qiskit.quantum_info",
31
+ "pennylane",
32
+ "cirq",
33
+ }
34
+ ATTRIBUTES = set(
35
+ "array asarray zeros ones eye pi sqrt exp sin cos conj conjugate transpose reshape flatten ravel squeeze astype complex64 complex128 float32 float64 norm kron real imag T shape size data QuantumCircuit Statevector from_instruction h x y z ry rx rz cx cz swap s sdg t tdg sx barrier append device qnode state RY RX RZ Rot PhaseShift Identity PauliX PauliY PauliZ Hadamard CNOT CZ SWAP LineQubit range Circuit Simulator simulate final_state_vector H X Y Z CXPowGate ZPowGate XPowGate HPowGate controlled on inverse quantum_info".split()
36
+ )
37
+ # Documented Cirq gate aliases, independent of any v2 model outputs. They were
38
+ # absent from v1's conservative supported API. No isolation rule is relaxed.
39
+ ATTRIBUTES.update({"CX", "Rx", "Ry", "Rz"})
40
+ BUILTINS = {
41
+ "range": lambda *a: bounded_range(*a),
42
+ "enumerate": enumerate,
43
+ "zip": zip,
44
+ "len": len,
45
+ "list": list,
46
+ "tuple": tuple,
47
+ "float": float,
48
+ "int": int,
49
+ "complex": complex,
50
+ "print": print,
51
+ "abs": abs,
52
+ "sum": sum,
53
+ "min": min,
54
+ "max": max,
55
+ "reversed": reversed,
56
+ }
57
+ FORBIDDEN = (
58
+ ast.ClassDef,
59
+ ast.AsyncFunctionDef,
60
+ ast.Await,
61
+ ast.While,
62
+ ast.Try,
63
+ ast.With,
64
+ ast.AsyncWith,
65
+ ast.Raise,
66
+ ast.Delete,
67
+ ast.Global,
68
+ ast.Nonlocal,
69
+ ast.Lambda,
70
+ ast.Yield,
71
+ ast.YieldFrom,
72
+ ast.Match,
73
+ )
74
+ LIB = None
75
+
76
+
77
+ def bounded_range(*args):
78
+ value = range(*args)
79
+ if len(value) > 1024:
80
+ raise ValueError("range limit")
81
+ return value
82
+
83
+
84
+ def screen(program):
85
+ if len(program) > 25000:
86
+ raise ValueError("program length limit")
87
+ tree = ast.parse(program)
88
+ if sum(1 for _ in ast.walk(tree)) > 6000:
89
+ raise ValueError("AST node limit")
90
+ for node in ast.walk(tree):
91
+ if isinstance(node, FORBIDDEN):
92
+ raise ValueError("unsupported syntax: " + type(node).__name__)
93
+ if isinstance(node, ast.Name) and (
94
+ node.id.startswith("_")
95
+ or node.id
96
+ in {
97
+ "eval",
98
+ "exec",
99
+ "compile",
100
+ "open",
101
+ "getattr",
102
+ "setattr",
103
+ "globals",
104
+ "locals",
105
+ "vars",
106
+ "type",
107
+ "object",
108
+ "input",
109
+ "help",
110
+ "breakpoint",
111
+ }
112
+ ):
113
+ raise ValueError("forbidden name")
114
+ if isinstance(node, ast.Attribute) and node.attr not in ATTRIBUTES:
115
+ raise ValueError("unsupported attribute: " + node.attr)
116
+ if isinstance(node, ast.Import):
117
+ if any(a.name not in MODULES or (a.asname or "").startswith("_") for a in node.names):
118
+ raise ValueError("unsupported import")
119
+ if isinstance(node, ast.ImportFrom):
120
+ if (
121
+ node.level
122
+ or node.module not in MODULES
123
+ or any(
124
+ a.name not in ATTRIBUTES or (a.asname or "").startswith("_") for a in node.names
125
+ )
126
+ ):
127
+ raise ValueError("unsupported from import")
128
+ if isinstance(node, ast.FunctionDef) and node.name.startswith("_"):
129
+ raise ValueError("forbidden function name")
130
+ return tree
131
+
132
+
133
+ def initialize():
134
+ global LIB
135
+ assert os.name == "posix" and os.getuid() == 0, "Linux root parent required for UID isolation"
136
+ # Resolve/load seccomp before restricting filesystem access.
137
+ library = ctypes.util.find_library("seccomp")
138
+ assert library, "libseccomp is required; never fall back to AST-only execution"
139
+ LIB = ctypes.CDLL(library, use_errno=True)
140
+ LIB.seccomp_init.argtypes = [ctypes.c_uint32]
141
+ LIB.seccomp_init.restype = ctypes.c_void_p
142
+ LIB.seccomp_syscall_resolve_name.argtypes = [ctypes.c_char_p]
143
+ LIB.seccomp_syscall_resolve_name.restype = ctypes.c_int
144
+ LIB.seccomp_rule_add.argtypes = [ctypes.c_void_p, ctypes.c_uint32, ctypes.c_int, ctypes.c_uint]
145
+ LIB.seccomp_load.argtypes = [ctypes.c_void_p]
146
+ LIB.seccomp_release.argtypes = [ctypes.c_void_p]
147
+ from qiskit import QuantumCircuit
148
+ from qiskit.quantum_info import Statevector
149
+ import pennylane as qml
150
+ import cirq
151
+
152
+ qc = QuantumCircuit(2)
153
+ qc.h(0)
154
+ qc.ry(0.3, 1)
155
+ qc.rz(0.17, 0)
156
+ qc.x(0)
157
+ qc.z(1)
158
+ qc.cx(0, 1)
159
+ Statevector.from_instruction(qc)
160
+ device = qml.device("default.qubit", wires=[1, 0])
161
+
162
+ @qml.qnode(device)
163
+ def warm():
164
+ qml.Hadamard(0)
165
+ qml.RY(0.3, wires=1)
166
+ qml.RZ(0.17, wires=0)
167
+ qml.PauliX(0)
168
+ qml.PauliZ(1)
169
+ qml.CNOT(wires=[0, 1])
170
+ return qml.state()
171
+
172
+ warm()
173
+ qubits = cirq.LineQubit.range(2)
174
+ cirq.Simulator(dtype=np.complex128).simulate(
175
+ cirq.Circuit(
176
+ cirq.H(qubits[0]),
177
+ cirq.ry(0.3)(qubits[1]),
178
+ cirq.rz(0.17)(qubits[0]),
179
+ cirq.X(qubits[0]),
180
+ cirq.Z(qubits[1]),
181
+ cirq.CNOT(*qubits),
182
+ ),
183
+ qubit_order=list(reversed(qubits)),
184
+ )
185
+ # Warm Python import machinery and serialization before fork/lockdown.
186
+ for module in MODULES:
187
+ importlib.import_module(module)
188
+ importlib.import_module("socket")
189
+ return dict(
190
+ qiskit=importlib.import_module("qiskit").__version__,
191
+ pennylane=qml.__version__,
192
+ cirq=cirq.__version__,
193
+ )
194
+
195
+
196
+ def lockdown():
197
+ os.environ.clear()
198
+ os.setgroups([])
199
+ os.setgid(65534)
200
+ os.setuid(65534)
201
+ resource.setrlimit(resource.RLIMIT_CPU, (15, 15))
202
+ # Native numeric runtimes reserve large virtual address spaces. Physical
203
+ # memory remains bounded by the HF CPU job container's memory allocation.
204
+ resource.setrlimit(resource.RLIMIT_AS, (16 * 1024**3, 16 * 1024**3))
205
+ resource.setrlimit(resource.RLIMIT_FSIZE, (0, 0))
206
+ resource.setrlimit(resource.RLIMIT_CORE, (0, 0))
207
+ resource.setrlimit(resource.RLIMIT_NPROC, (32, 32))
208
+ libc = ctypes.CDLL(None, use_errno=True)
209
+ assert libc.prctl(38, 1, 0, 0, 0) == 0, "PR_SET_NO_NEW_PRIVS failed"
210
+ policy = LIB.seccomp_init(0x7FFF0000) # SCMP_ACT_ALLOW
211
+ assert policy
212
+ deny = 0x00050000 | errno.EPERM # SCMP_ACT_ERRNO(EPERM)
213
+ for name in [
214
+ "open",
215
+ "openat",
216
+ "openat2",
217
+ "creat",
218
+ "socket",
219
+ "socketpair",
220
+ "connect",
221
+ "accept",
222
+ "accept4",
223
+ "bind",
224
+ "listen",
225
+ "sendto",
226
+ "sendmsg",
227
+ "execve",
228
+ "execveat",
229
+ "ptrace",
230
+ "process_vm_readv",
231
+ "process_vm_writev",
232
+ "mount",
233
+ "umount2",
234
+ "bpf",
235
+ "userfaultfd",
236
+ ]:
237
+ syscall = LIB.seccomp_syscall_resolve_name(name.encode())
238
+ if syscall >= 0:
239
+ assert LIB.seccomp_rule_add(policy, deny, syscall, 0) == 0, name
240
+ assert LIB.seccomp_load(policy) == 0, "seccomp load failed"
241
+ LIB.seccomp_release(policy)
242
+
243
+
244
+ def safe_import(name, globals=None, locals=None, fromlist=(), level=0):
245
+ if name not in MODULES or level:
246
+ raise ImportError("module not allowed")
247
+ module = importlib.import_module(name)
248
+ return module if fromlist else importlib.import_module(name.split(".")[0])
249
+
250
+
251
+ def worker(program, qubits, connection, mode):
252
+ try:
253
+ lockdown()
254
+ if mode == "isolation_check":
255
+ import socket
256
+
257
+ file_blocked = network_blocked = False
258
+ try:
259
+ open("/etc/hostname").read()
260
+ except PermissionError:
261
+ file_blocked = True
262
+ try:
263
+ socket.socket()
264
+ except PermissionError:
265
+ network_blocked = True
266
+ connection.send(
267
+ dict(
268
+ file_opens_blocked=file_blocked,
269
+ network_blocked=network_blocked,
270
+ uid=os.getuid(),
271
+ environment_empty=not os.environ,
272
+ )
273
+ )
274
+ return
275
+ tree = screen(program)
276
+ safe = dict(BUILTINS, __import__=safe_import)
277
+ namespace = {"__builtins__": safe}
278
+ with contextlib.redirect_stdout(io.StringIO()), contextlib.redirect_stderr(io.StringIO()):
279
+ exec(compile(tree, "<restricted-quantum>", "exec"), namespace, namespace)
280
+ value = np.asarray(namespace["state"], dtype=np.complex128).reshape(-1)
281
+ assert value.shape == (2**qubits,) and np.isfinite(value).all()
282
+ connection.send(
283
+ dict(
284
+ status="executed",
285
+ real=value.real.tolist(),
286
+ imag=value.imag.tolist(),
287
+ norm=float(np.linalg.norm(value)),
288
+ )
289
+ )
290
+ except BaseException as error:
291
+ connection.send(
292
+ dict(status="rejected_or_error", error=type(error).__name__, detail=str(error)[:300])
293
+ )
294
+ finally:
295
+ connection.close()
296
+
297
+
298
+ def run(program, qubits, mode="program"):
299
+ assert 1 <= qubits <= 8
300
+ ctx = mp.get_context("fork")
301
+ receive, send = ctx.Pipe(duplex=False)
302
+ process = ctx.Process(target=worker, args=(program, qubits, send, mode))
303
+ process.start()
304
+ send.close()
305
+ if receive.poll(20):
306
+ try:
307
+ result = receive.recv()
308
+ except EOFError:
309
+ result = dict(status="worker_exit", exitcode=process.exitcode)
310
+ else:
311
+ result = dict(status="timeout")
312
+ process.join(1)
313
+ if process.is_alive():
314
+ process.kill()
315
+ process.join(2)
316
+ receive.close()
317
+ return result
release_audit.json ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "circuit_groups": 456,
3
+ "framework_views": 1368,
4
+ "cross_split_group_overlap": 0,
5
+ "train_holdout_exact_state_matches": 0,
6
+ "max_train_holdout_state_fidelity": 0.9991002699676015,
7
+ "state_match_tolerance": 1e-08,
8
+ "independent_execution_gate": true,
9
+ "saved_helper_all_passed": true,
10
+ "scope": "Exact zero-input-state duplicate check across matching dimensions; does not assert full unitary/process or semantic equivalence separation."
11
+ }
reproduce_execution.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Offline re-scoring of frozen programs; Linux/root/libseccomp are required.
2
+
3
+ Never replace the sandbox with direct exec. All generated programs run only in
4
+ its credential-cleared nobody workers with filesystem/network denial.
5
+ """
6
+ import ast
7
+ import hashlib
8
+ import json
9
+ import re
10
+ from collections import defaultdict
11
+ from pathlib import Path
12
+ import numpy as np
13
+ import quantum_sandbox_v2 as sandbox
14
+
15
+ ROOT=Path(__file__).resolve().parent
16
+
17
+
18
+ def score(program,row):
19
+ wrapped=re.fullmatch(r"\s*```(?:python)?\s*\n(.*?)\n```\s*",program,flags=re.S)
20
+ clean=wrapped.group(1) if wrapped else program
21
+ imports=set()
22
+ try:
23
+ for node in ast.walk(ast.parse(clean)):
24
+ if isinstance(node,ast.Import):imports.update(a.name.split(".")[0] for a in node.names)
25
+ elif isinstance(node,ast.ImportFrom):imports.add((node.module or "").split(".")[0])
26
+ except SyntaxError:
27
+ pass
28
+ result=sandbox.run(clean,row["qubits"])
29
+ passed=False
30
+ if result.get("status")=="executed":
31
+ actual=np.array(result["real"])+1j*np.array(result["imag"])
32
+ target=np.array(row["state_real"])+1j*np.array(row["state_imag"])
33
+ passed=abs(result["norm"]-1)<1e-6 and abs(np.vdot(target,actual))**2>1-1e-6 and row["framework"] in imports
34
+ return bool(passed)
35
+
36
+
37
+ def main():
38
+ frozen=json.loads((ROOT/"v2_execution/execution.json").read_text())
39
+ preflight=json.loads((ROOT/"v2_executor_preflight/preflight.json").read_text())
40
+ assert preflight["all_passed"] and len(preflight["reference_checks"])==1368
41
+ assert hashlib.sha256(Path(sandbox.__file__).read_bytes()).hexdigest()==frozen["executor_sha256"]==preflight["executor_sha256"]
42
+ file=ROOT/"curriculum_v2/rows.json"
43
+ assert hashlib.sha256(file.read_bytes()).hexdigest()==preflight["manifest"]["rows_sha256"]
44
+ rows={r["id"]:r for r in json.loads(file.read_text()) if r["split"]!="train"}
45
+ assert len(rows)==720
46
+ versions=sandbox.initialize()
47
+ assert versions==frozen["versions"]
48
+ assert sandbox.run("",1,mode="isolation_check")==preflight["isolation"]
49
+ for row in rows.values():
50
+ assert score(row["program"],row),"Reference failed; stop before scoring generated programs"
51
+ outputs=json.loads((ROOT/"curriculum_v2_run/generation_report.json").read_text())["conditions"]
52
+ totals=defaultdict(lambda:dict(n=0,passed=0))
53
+ for condition in ["base","adapted"]:
54
+ assert len(outputs[condition])==720 and {r["id"] for r in outputs[condition]}==set(rows)
55
+ for output in outputs[condition]:
56
+ row=rows[output["id"]];passed=score(output["program"],row)
57
+ for framework in ["all",row["framework"]]:
58
+ key=condition+"/"+row["split"]+"/"+framework
59
+ totals[key]["n"]+=1;totals[key]["passed"]+=passed
60
+ for key,value in totals.items():
61
+ condition,split,framework=key.split("/")
62
+ original=frozen["summary"][condition][split+"/"+framework]
63
+ assert value==dict(n=original["n"],passed=original["passed"]),(key,value,original)
64
+ result=dict(versions=versions,all_counts_reproduced=True,summary=dict(totals))
65
+ (ROOT/"reproduced_counts.json").write_text(json.dumps(result,indent=2)+"\n")
66
+ print(json.dumps(result,indent=2))
67
+
68
+
69
+ if __name__=="__main__":main()
requirements-evaluation.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ numpy==2.1.3
2
+ qiskit==2.2.3
3
+ pennylane==0.43.1
4
+ cirq-core==1.6.1
5
+ scipy==1.15.3
6
+ gast==0.6.0
7
+ astunparse==1.6.3
requirements-inference.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ torch==2.10.0
2
+ torchvision==0.25.0
3
+ torchaudio==2.10.0
4
+ transformers==5.5.4
5
+ peft==0.18.1
6
+ accelerate==1.12.0
7
+ huggingface_hub==1.33.0
8
+ safetensors==0.5.3