aishani-s20 commited on
Commit
b3dfb35
·
1 Parent(s): 3188877

improvement

Browse files
README.md CHANGED
@@ -74,7 +74,7 @@ Current LLM benchmarks rely on static toy puzzles. This environment bridges the
74
  | `1` | **Cancel Identical Gates** | Removes self-inverse gate pairs (X·X=I, H·H=I, CNOT·CNOT=I) on the same qubits, not blocked by overlapping intermediate gates. | `+1.0` |
75
  | `2` | **Swap Commuting Gates** | Swaps the target gate with the next adjacent gate **only if** their qubit sets do not intersect. Enables bringing distant cancellable pairs together. | `-0.05` |
76
  | `3` | **H-X-H Identity Collapse** | Replaces a `H → X → H` sequence on the same qubit with a single `Z` gate (net: 2 gates removed). | `+2.0` |
77
- | `4` | **Entanglement Compression** | Replaces an adjacent `CNOT → SWAP` on the same qubits with a single `CZ` gate (net: 1 gate removed). | `+1.0` |
78
 
79
  > **Invalid actions** (out-of-bounds index, illegal non-commuting swap, pattern not present) incur a `-0.10` penalty. Circuit state remains unchanged.
80
 
 
74
  | `1` | **Cancel Identical Gates** | Removes self-inverse gate pairs (X·X=I, H·H=I, CNOT·CNOT=I) on the same qubits, not blocked by overlapping intermediate gates. | `+1.0` |
75
  | `2` | **Swap Commuting Gates** | Swaps the target gate with the next adjacent gate **only if** their qubit sets do not intersect. Enables bringing distant cancellable pairs together. | `-0.05` |
76
  | `3` | **H-X-H Identity Collapse** | Replaces a `H → X → H` sequence on the same qubit with a single `Z` gate (net: 2 gates removed). | `+2.0` |
77
+ | `4` | **Entanglement Compression** | Replaces a `CNOT(a,b)CNOT(b,a) CNOT(a,b)` sequence with a single `SWAP` gate — a standard compiler identity (net: 2 gates removed). | `+2.0` |
78
 
79
  > **Invalid actions** (out-of-bounds index, illegal non-commuting swap, pattern not present) incur a `-0.10` penalty. Circuit state remains unchanged.
80
 
inference.py CHANGED
@@ -79,7 +79,7 @@ SYSTEM_PROMPT = textwrap.dedent(
79
  the same qubits, not blocked by intermediate gates sharing those qubits.
80
  Action 2: Swap adjacent commuting gates (gates on entirely non-overlapping qubits).
81
  Action 3: Replace an H-X-H sequence on the same qubit with a Z gate.
82
- Action 4: Replace a CNOT-SWAP sequence on the same qubits with a CZ gate.
83
 
84
  You MUST output ONLY a valid JSON object with exactly two keys:
85
  "target_index" (integer) and "action_type" (integer 1-4).
 
79
  the same qubits, not blocked by intermediate gates sharing those qubits.
80
  Action 2: Swap adjacent commuting gates (gates on entirely non-overlapping qubits).
81
  Action 3: Replace an H-X-H sequence on the same qubit with a Z gate.
82
+ Action 4: Replace a CNOT(a,b)→CNOT(b,a)→CNOT(a,b) sequence with a single SWAP gate (3 alternating CNOTs collapse to 1 SWAP).
83
 
84
  You MUST output ONLY a valid JSON object with exactly two keys:
85
  "target_index" (integer) and "action_type" (integer 1-4).
models.py CHANGED
@@ -41,7 +41,7 @@ class QuantumAction(Action):
41
  default=1,
42
  ge=1, # Minimum action type is 1
43
  le=4, # Maximum action type is 4
44
- description="1: Cancel identical gates, 2: Swap commuting gates, 3: Replace H-X-H with Z, 4: Replace CNOT-SWAP with CZ"
45
  )
46
 
47
 
 
41
  default=1,
42
  ge=1, # Minimum action type is 1
43
  le=4, # Maximum action type is 4
44
+ description="1: Cancel identical gates, 2: Swap commuting gates, 3: Replace H-X-H with Z, 4: Replace 3-CNOT sequence with SWAP"
45
  )
46
 
47
 
server/quantum_openenv_env_environment.py CHANGED
@@ -71,6 +71,16 @@ class TaskConfig:
71
  insert_idx_2 = rng.randint(insert_idx_1, len(circuit))
72
  circuit.insert(insert_idx_2, gate2)
73
 
 
 
 
 
 
 
 
 
 
 
74
  return circuit
75
 
76
 
@@ -247,20 +257,26 @@ class QuantumCircuitOptimizationEnvironment(Environment):
247
  action_result = "identity_hxh_to_z"
248
  self._used_advanced_actions = True
249
 
250
- # ACTION 4: Replace CNOT-SWAP with CZ (advanced identity)
251
  elif action_type == 4:
252
- if target_index + 1 < len(self._circuit):
253
  g1 = self._circuit[target_index]
254
  g2 = self._circuit[target_index + 1]
 
 
 
 
255
 
256
- if (g1.name == "CNOT" and g2.name == "SWAP" and
257
- set(g1.target_qubits) == set(g2.target_qubits)):
 
 
258
  self._circuit.pop(target_index + 1)
259
  self._circuit[target_index] = QuantumGate(
260
- name="CZ", target_qubits=g1.target_qubits
261
  )
262
- reward = 1.0
263
- action_result = "identity_cnot_swap_to_cz"
264
  self._used_advanced_actions = True
265
 
266
  return self._build_observation(reward, action_result)
@@ -377,7 +393,7 @@ class QuantumCircuitOptimizationEnvironment(Environment):
377
  "1: Cancel identical self-inverse gates (H, X, Y, Z, CNOT, SWAP).\n\n"
378
  "2: Swap adjacent commuting gates (gates not sharing qubits).\n\n"
379
  "3: Replace an H-X-H sequence with a Z gate.\n\n"
380
- "4: Replace a CNOT-SWAP sequence with a CZ gate.\n\n"
381
  "CURRENT CIRCUIT STATE:\n\n"
382
  )
383
 
 
71
  insert_idx_2 = rng.randint(insert_idx_1, len(circuit))
72
  circuit.insert(insert_idx_2, gate2)
73
 
74
+ if self.use_entangling and self.num_qubits > 1:
75
+ num_patterns = 1 if self.name == "medium" else 2 # hard gets 2
76
+ for _ in range(num_patterns):
77
+ if rng.random() > 0.3: # 70% chance per pattern, keeps it non-deterministic
78
+ q1, q2 = rng.sample(range(self.num_qubits), 2)
79
+ insert_at = rng.randint(0, len(circuit))
80
+ circuit.insert(insert_at, QuantumGate(name="CNOT", target_qubits=[q1, q2]))
81
+ circuit.insert(insert_at + 1, QuantumGate(name="CNOT", target_qubits=[q2, q1]))
82
+ circuit.insert(insert_at + 2, QuantumGate(name="CNOT", target_qubits=[q1, q2]))
83
+
84
  return circuit
85
 
86
 
 
257
  action_result = "identity_hxh_to_z"
258
  self._used_advanced_actions = True
259
 
260
+ # ACTION 4: Replace CNOT(a,b)→CNOT(b,a)→CNOT(a,b) with SWAP (advanced identity)
261
  elif action_type == 4:
262
+ if target_index + 2 < len(self._circuit):
263
  g1 = self._circuit[target_index]
264
  g2 = self._circuit[target_index + 1]
265
+ g3 = self._circuit[target_index + 2]
266
+
267
+ qubits_ab = g1.target_qubits # e.g. [0, 1]
268
+ qubits_ba = list(reversed(g1.target_qubits)) # e.g. [1, 0]
269
 
270
+ if (g1.name == "CNOT" and g2.name == "CNOT" and g3.name == "CNOT" and
271
+ g1.target_qubits == g3.target_qubits and
272
+ g2.target_qubits == qubits_ba):
273
+ self._circuit.pop(target_index + 2)
274
  self._circuit.pop(target_index + 1)
275
  self._circuit[target_index] = QuantumGate(
276
+ name="SWAP", target_qubits=g1.target_qubits
277
  )
278
+ reward = 2.0 # saves 2 gates, same as H-X-H identity
279
+ action_result = "identity_3cnot_to_swap"
280
  self._used_advanced_actions = True
281
 
282
  return self._build_observation(reward, action_result)
 
393
  "1: Cancel identical self-inverse gates (H, X, Y, Z, CNOT, SWAP).\n\n"
394
  "2: Swap adjacent commuting gates (gates not sharing qubits).\n\n"
395
  "3: Replace an H-X-H sequence with a Z gate.\n\n"
396
+ "4: Replace CNOT(a,b)→CNOT(b,a)→CNOT(a,b) with a single SWAP gate.\n\n"
397
  "CURRENT CIRCUIT STATE:\n\n"
398
  )
399