pyqrack-cpu 2.25.0__tar.gz → 2.25.2__tar.gz
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.
- {pyqrack_cpu-2.25.0/pyqrack_cpu.egg-info → pyqrack_cpu-2.25.2}/PKG-INFO +1 -1
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/pyqrack/qrack_ace_backend.py +226 -78
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2/pyqrack_cpu.egg-info}/PKG-INFO +1 -1
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/setup.py +1 -1
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/LICENSE +0 -0
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/MANIFEST.in +0 -0
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/Makefile +0 -0
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/README.md +0 -0
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/pyproject.toml +0 -0
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/pyqrack/__init__.py +0 -0
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/pyqrack/neuron_activation_fn.py +0 -0
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/pyqrack/pauli.py +0 -0
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/pyqrack/qrack_circuit.py +0 -0
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/pyqrack/qrack_near_clifford_qec_backend.py +0 -0
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/pyqrack/qrack_neuron.py +0 -0
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/pyqrack/qrack_neuron_torch_layer.py +0 -0
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/pyqrack/qrack_simulator.py +0 -0
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/pyqrack/qrack_stabilizer.py +0 -0
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/pyqrack/qrack_system/__init__.py +0 -0
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/pyqrack/qrack_system/qrack_system.py +0 -0
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/pyqrack/quimb_circuit_type.py +0 -0
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/pyqrack/stats/__init__.py +0 -0
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/pyqrack/stats/load_quantized_data.py +0 -0
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/pyqrack/stats/quantize_by_range.py +0 -0
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/pyqrack_cpu.egg-info/SOURCES.txt +0 -0
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/pyqrack_cpu.egg-info/dependency_links.txt +0 -0
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/pyqrack_cpu.egg-info/not-zip-safe +0 -0
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/pyqrack_cpu.egg-info/requires.txt +0 -0
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/pyqrack_cpu.egg-info/top_level.txt +0 -0
- {pyqrack_cpu-2.25.0 → pyqrack_cpu-2.25.2}/setup.cfg +0 -0
|
@@ -408,18 +408,12 @@ class QrackAceBackend:
|
|
|
408
408
|
# per-simulator allocation above.
|
|
409
409
|
self._detect_ancilla1 = []
|
|
410
410
|
self._detect_ancilla2 = []
|
|
411
|
-
self._detect_ancilla3 = []
|
|
412
|
-
self._detect_ancilla4 = []
|
|
413
411
|
if self.is_error_detection:
|
|
414
412
|
for i in range(len(sim_counts)):
|
|
415
413
|
self._detect_ancilla1.append(sim_counts[i])
|
|
416
414
|
sim_counts[i] += 1
|
|
417
415
|
self._detect_ancilla2.append(sim_counts[i])
|
|
418
416
|
sim_counts[i] += 1
|
|
419
|
-
self._detect_ancilla3.append(sim_counts[i])
|
|
420
|
-
sim_counts[i] += 1
|
|
421
|
-
self._detect_ancilla4.append(sim_counts[i])
|
|
422
|
-
sim_counts[i] += 1
|
|
423
417
|
|
|
424
418
|
# Logical-qubit wrapper around each patch's detection ancilla,
|
|
425
419
|
# so it's addressable via the ORDINARY cx()/_cpauli() machinery
|
|
@@ -441,8 +435,6 @@ class QrackAceBackend:
|
|
|
441
435
|
# legitimately need to change any single replica's own value.
|
|
442
436
|
self._detect_ancilla1_lq = []
|
|
443
437
|
self._detect_ancilla2_lq = []
|
|
444
|
-
self._detect_ancilla3_lq = []
|
|
445
|
-
self._detect_ancilla4_lq = []
|
|
446
438
|
if self.is_error_detection:
|
|
447
439
|
for sim_id, phys_idx in enumerate(self._detect_ancilla1):
|
|
448
440
|
lq_idx = len(self._qubits)
|
|
@@ -452,14 +444,6 @@ class QrackAceBackend:
|
|
|
452
444
|
lq_idx = len(self._qubits)
|
|
453
445
|
self._qubits.append([(sim_id, phys_idx)])
|
|
454
446
|
self._detect_ancilla2_lq.append(lq_idx)
|
|
455
|
-
for sim_id, phys_idx in enumerate(self._detect_ancilla3):
|
|
456
|
-
lq_idx = len(self._qubits)
|
|
457
|
-
self._qubits.append([(sim_id, phys_idx)])
|
|
458
|
-
self._detect_ancilla3_lq.append(lq_idx)
|
|
459
|
-
for sim_id, phys_idx in enumerate(self._detect_ancilla4):
|
|
460
|
-
lq_idx = len(self._qubits)
|
|
461
|
-
self._qubits.append([(sim_id, phys_idx)])
|
|
462
|
-
self._detect_ancilla4_lq.append(lq_idx)
|
|
463
447
|
# Boundary repetition code, on-demand design: only the couplers
|
|
464
448
|
# are actually noisy here -- single-qubit gates are already
|
|
465
449
|
# exactly transversal, per-replica, with zero error, so there's
|
|
@@ -716,9 +700,6 @@ class QrackAceBackend:
|
|
|
716
700
|
else:
|
|
717
701
|
t.adjs()
|
|
718
702
|
|
|
719
|
-
def _detect_swap(self, sim_id, idx1, idx2):
|
|
720
|
-
self.sim[sim_id].swap(idx1, idx2)
|
|
721
|
-
|
|
722
703
|
def _anti_shadow_wrap(self, c, t, middle_fn):
|
|
723
704
|
self._qec_x(c)
|
|
724
705
|
middle_fn(c, t)
|
|
@@ -757,6 +738,24 @@ class QrackAceBackend:
|
|
|
757
738
|
def _anti_cy_shadow(self, c, t):
|
|
758
739
|
self._anti_shadow_wrap(c, t, self._cy_shadow)
|
|
759
740
|
|
|
741
|
+
def _ccx_shadow(self, c1, c2, t, lc1, lc2, lt):
|
|
742
|
+
# CCNOT decomposition
|
|
743
|
+
self.h(lt)
|
|
744
|
+
self._cx_shadow(c2, t)
|
|
745
|
+
self.adjt(lt)
|
|
746
|
+
self._cx_shadow(c1, t)
|
|
747
|
+
self.t(lt)
|
|
748
|
+
self._cx_shadow(c2, t)
|
|
749
|
+
self.adjt(lt)
|
|
750
|
+
self._cx_shadow(c1, t)
|
|
751
|
+
self.t(lt)
|
|
752
|
+
self.h(lt)
|
|
753
|
+
self.t(lc2)
|
|
754
|
+
self._cx_shadow(c1, c2)
|
|
755
|
+
self.t(lc1)
|
|
756
|
+
self.adjt(lc2)
|
|
757
|
+
self._cx_shadow(c1, c2)
|
|
758
|
+
|
|
760
759
|
def _unpack(self, lq):
|
|
761
760
|
return self._qubits[lq]
|
|
762
761
|
|
|
@@ -2258,7 +2257,7 @@ class QrackAceBackend:
|
|
|
2258
2257
|
for i in range(len(hq1)):
|
|
2259
2258
|
sim_id, idx1 = hq1[i]
|
|
2260
2259
|
_, idx2 = hq2[i]
|
|
2261
|
-
self.
|
|
2260
|
+
self.sim[sim_id].swap(idx1, idx2)
|
|
2262
2261
|
# No post-swap correction: this branch is a native index
|
|
2263
2262
|
# relabeling applied identically to every matching replica
|
|
2264
2263
|
# pair, with zero Schmidt-truncation opportunity -- verified
|
|
@@ -2300,7 +2299,7 @@ class QrackAceBackend:
|
|
|
2300
2299
|
for _hq2 in non_matching:
|
|
2301
2300
|
self._cx_shadow(_hq1, _hq2)
|
|
2302
2301
|
for _hq2 in matching:
|
|
2303
|
-
self.
|
|
2302
|
+
self.sim[_hq1[0]].swap(_hq1[1], _hq2[1])
|
|
2304
2303
|
for _hq2 in non_matching:
|
|
2305
2304
|
self._cx_shadow(_hq1, _hq2)
|
|
2306
2305
|
# No correction on lq1 (bulk, single-replica): already a
|
|
@@ -2317,7 +2316,7 @@ class QrackAceBackend:
|
|
|
2317
2316
|
for _hq1 in non_matching:
|
|
2318
2317
|
self._cx_shadow(_hq2, _hq1)
|
|
2319
2318
|
for _hq1 in matching:
|
|
2320
|
-
self.
|
|
2319
|
+
self.sim[_hq2[0]].swap(_hq2[1], _hq2[1])
|
|
2321
2320
|
for _hq1 in non_matching:
|
|
2322
2321
|
self._cx_shadow(_hq2, _hq1)
|
|
2323
2322
|
self._correct(lq1)
|
|
@@ -2378,67 +2377,180 @@ class QrackAceBackend:
|
|
|
2378
2377
|
self.mcx([c1, c2], t)
|
|
2379
2378
|
return
|
|
2380
2379
|
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2380
|
+
if self.is_boundary_repetition_code or (len(hqt) > 1):
|
|
2381
|
+
self.h(t)
|
|
2382
|
+
self.cx(c2, t)
|
|
2383
|
+
self.adjt(t)
|
|
2384
|
+
self.cx(c1, t)
|
|
2385
|
+
self.t(t)
|
|
2386
|
+
self.cx(c2, t)
|
|
2387
|
+
self.adjt(t)
|
|
2388
|
+
self.cx(c1, t)
|
|
2389
|
+
self.t(t)
|
|
2390
|
+
self.h(t)
|
|
2391
|
+
self.t(c2)
|
|
2392
|
+
self.cx(c1, c2)
|
|
2393
|
+
self.t(c1)
|
|
2394
|
+
self.adjt(c2)
|
|
2395
|
+
self.cx(c1, c2)
|
|
2396
|
+
return
|
|
2397
|
+
|
|
2398
|
+
|
|
2399
|
+
if not self._in_gadget_capture:
|
|
2400
|
+
self._correct(c1)
|
|
2401
|
+
self._correct(c2)
|
|
2402
|
+
|
|
2403
|
+
anc1, anc2, anc1b, anc2b = None, None, None, None
|
|
2404
|
+
if self.is_error_detection and not self._in_gadget_capture and ((len(hq1) > 1) or (len(hq2) > 1)):
|
|
2385
2405
|
self._in_gadget_capture = True
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2406
|
+
|
|
2407
|
+
if len(hq1) > 1:
|
|
2408
|
+
anc1 = self._detect_ancilla1_lq[hq1[0][0]]
|
|
2409
|
+
self.cx(c1, anc1)
|
|
2410
|
+
if hqt[0][0] != hq1[0][0]:
|
|
2411
|
+
anc1b = self._detect_ancilla1_lq[hqt[0][0]]
|
|
2412
|
+
self.cx(c1, anc1b)
|
|
2413
|
+
|
|
2414
|
+
if len(hq2) > 1:
|
|
2415
|
+
if (len(hq1) > 1) and (hq1[0][0] == hq2[0][0]):
|
|
2416
|
+
anc2 = self._detect_ancilla2_lq[hq2[0][0]]
|
|
2417
|
+
else:
|
|
2418
|
+
anc2 = self._detect_ancilla1_lq[hq2[0][0]]
|
|
2419
|
+
self.cx(c2, anc2)
|
|
2420
|
+
if hqt[0][0] != hq2[0][0]:
|
|
2421
|
+
anc2b = self._detect_ancilla2_lq[hqt[0][0]]
|
|
2422
|
+
# Control bit-flip
|
|
2423
|
+
self.cx(c2, anc2b)
|
|
2424
|
+
|
|
2392
2425
|
self._in_gadget_capture = False
|
|
2393
2426
|
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2427
|
+
qb1, _ = QrackAceBackend._get_qb_lhv_indices(hq1)
|
|
2428
|
+
qb2, _ = QrackAceBackend._get_qb_lhv_indices(hq2)
|
|
2429
|
+
qbt, _ = QrackAceBackend._get_qb_lhv_indices(hqt)
|
|
2430
|
+
|
|
2431
|
+
for qt in qbt:
|
|
2432
|
+
witness = None
|
|
2433
|
+
bt = hqt[qt]
|
|
2434
|
+
for q1 in qb1:
|
|
2435
|
+
b1 = hq1[q1]
|
|
2436
|
+
for q2 in qb2:
|
|
2437
|
+
b2 = hq2[q2]
|
|
2438
|
+
for q2 in qb2:
|
|
2439
|
+
b2 = hq2[q2]
|
|
2440
|
+
if bt[0] == b1[0] and bt[0] == b2[0]:
|
|
2441
|
+
witness = bt
|
|
2442
|
+
break
|
|
2443
|
+
if witness is not None:
|
|
2444
|
+
break
|
|
2445
|
+
if witness is not None:
|
|
2446
|
+
break
|
|
2447
|
+
if witness:
|
|
2448
|
+
self.sim[b1[0]].mcx([b1[1], b2[1]], bt[1])
|
|
2449
|
+
else:
|
|
2450
|
+
self._ccx_shadow(b1, b2, bt, c1, c2, t)
|
|
2451
|
+
|
|
2452
|
+
self._in_gadget_capture = True
|
|
2410
2453
|
|
|
2411
2454
|
if anc1 is not None:
|
|
2412
2455
|
# Syndrome
|
|
2413
|
-
self.cx(
|
|
2414
|
-
self.cx(c2, anc1)
|
|
2415
|
-
self.cx(t, anc2)
|
|
2416
|
-
self.cx(c1, anc2)
|
|
2456
|
+
self.cx(c1, anc1)
|
|
2417
2457
|
|
|
2418
2458
|
# Post-selection
|
|
2419
2459
|
anc_sim, anc_idx = self._qubits[anc1][0]
|
|
2420
2460
|
p = self.sim[anc_sim].prob(anc_idx)
|
|
2461
|
+
is_flipped = False
|
|
2421
2462
|
if self._ps_epsilon >= (1.0 - p):
|
|
2422
2463
|
b1 = self.m(anc1)
|
|
2423
2464
|
else:
|
|
2424
2465
|
b1 = self.force_m(anc1, False)
|
|
2425
2466
|
if b1:
|
|
2426
2467
|
self.x(anc1)
|
|
2468
|
+
q = None
|
|
2469
|
+
for c in hq1:
|
|
2470
|
+
if c[0] == anc_sim:
|
|
2471
|
+
q = c[1]
|
|
2472
|
+
break
|
|
2473
|
+
if q is None:
|
|
2474
|
+
self.x(c1)
|
|
2475
|
+
is_flipped = True
|
|
2476
|
+
else:
|
|
2477
|
+
self.sim[anc_sim].x(q)
|
|
2427
2478
|
|
|
2479
|
+
if anc1b is not None:
|
|
2480
|
+
anc_sim, anc_idx = self._qubits[anc1b][0]
|
|
2481
|
+
p = self.sim[anc_sim].prob(anc_idx)
|
|
2482
|
+
if b1:
|
|
2483
|
+
p = 1.0 - p
|
|
2484
|
+
if self._ps_epsilon >= (1.0 - p):
|
|
2485
|
+
b2 = self.m(anc1b)
|
|
2486
|
+
else:
|
|
2487
|
+
b2 = self.force_m(anc1b, b1)
|
|
2488
|
+
if b2:
|
|
2489
|
+
self.x(anc1b)
|
|
2490
|
+
if b2 != is_flipped:
|
|
2491
|
+
q = None
|
|
2492
|
+
for c in hq1:
|
|
2493
|
+
if c[0] == anc_sim:
|
|
2494
|
+
q = c[1]
|
|
2495
|
+
break
|
|
2496
|
+
if q is None:
|
|
2497
|
+
if not is_flipped:
|
|
2498
|
+
self.x(c1)
|
|
2499
|
+
else:
|
|
2500
|
+
self.sim[anc_sim].x(q)
|
|
2501
|
+
|
|
2502
|
+
if anc2 is not None:
|
|
2503
|
+
# Syndrome
|
|
2504
|
+
self.cx(c2, anc2)
|
|
2505
|
+
|
|
2506
|
+
# Post-selection
|
|
2428
2507
|
anc_sim, anc_idx = self._qubits[anc2][0]
|
|
2429
2508
|
p = self.sim[anc_sim].prob(anc_idx)
|
|
2430
|
-
|
|
2431
|
-
p = 1.0 - p
|
|
2509
|
+
is_flipped = False
|
|
2432
2510
|
if self._ps_epsilon >= (1.0 - p):
|
|
2433
|
-
|
|
2511
|
+
b1 = self.m(anc2)
|
|
2434
2512
|
else:
|
|
2435
|
-
|
|
2436
|
-
if
|
|
2513
|
+
b1 = self.force_m(anc2, False)
|
|
2514
|
+
if b1:
|
|
2437
2515
|
self.x(anc2)
|
|
2516
|
+
q = None
|
|
2517
|
+
for c in hq2:
|
|
2518
|
+
if c[0] == anc_sim:
|
|
2519
|
+
q = c[1]
|
|
2520
|
+
break
|
|
2521
|
+
if q is None:
|
|
2522
|
+
self.x(c2)
|
|
2523
|
+
is_flipped = True
|
|
2524
|
+
else:
|
|
2525
|
+
self.sim[anc_sim].x(q)
|
|
2526
|
+
|
|
2527
|
+
if anc2b is not None:
|
|
2528
|
+
anc_sim, anc_idx = self._qubits[anc2b][0]
|
|
2529
|
+
p = self.sim[anc_sim].prob(anc_idx)
|
|
2530
|
+
if b1:
|
|
2531
|
+
p = 1.0 - p
|
|
2532
|
+
if self._ps_epsilon >= (1.0 - p):
|
|
2533
|
+
b2 = self.m(anc2b)
|
|
2534
|
+
else:
|
|
2535
|
+
b2 = self.force_m(anc2b, b1)
|
|
2536
|
+
if b2:
|
|
2537
|
+
self.x(anc2b)
|
|
2538
|
+
if b2 != is_flipped:
|
|
2539
|
+
q = None
|
|
2540
|
+
for c in hq2:
|
|
2541
|
+
if c[0] == anc_sim:
|
|
2542
|
+
q = c[1]
|
|
2543
|
+
break
|
|
2544
|
+
if q is None:
|
|
2545
|
+
if not is_flipped:
|
|
2546
|
+
self.x(c2)
|
|
2547
|
+
else:
|
|
2548
|
+
self.sim[anc_sim].x(q)
|
|
2549
|
+
|
|
2550
|
+
self._in_gadget_capture = False
|
|
2438
2551
|
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
self.x(t)
|
|
2552
|
+
if not self._in_gadget_capture:
|
|
2553
|
+
self._correct(t)
|
|
2442
2554
|
|
|
2443
2555
|
def ccz(self, c1, c2, t):
|
|
2444
2556
|
self.h(t)
|
|
@@ -2969,7 +3081,60 @@ class QrackAceBackend:
|
|
|
2969
3081
|
if a != b:
|
|
2970
3082
|
coupling_map.add((a, b))
|
|
2971
3083
|
|
|
2972
|
-
|
|
3084
|
+
# BUGFIX (per Dan): distant boundary-to-boundary couplings -- two
|
|
3085
|
+
# boundary qubits sharing a simulator id even when they're
|
|
3086
|
+
# nowhere near each other. Tried re-deriving adjacency from
|
|
3087
|
+
# sim_id arithmetic several ways; none held up, because sim_id
|
|
3088
|
+
# doesn't decompose cleanly back into a geometric position.
|
|
3089
|
+
# Dropping that entirely: the patch grid is a plain, regular
|
|
3090
|
+
# series of rectangles by construction, and that geometry is
|
|
3091
|
+
# already sitting in self._is_row_long_range /
|
|
3092
|
+
# self._is_col_long_range (True = bulk, False = boundary). Two
|
|
3093
|
+
# boundary qubits are kept coupled only when they lie on the
|
|
3094
|
+
# SAME boundary row or column AND bound (or lie within) one
|
|
3095
|
+
# single contiguous bulk run along it -- i.e. no OTHER boundary
|
|
3096
|
+
# crossing lies strictly between them -- which is exactly "the
|
|
3097
|
+
# same single side of one rectangular patch." A corner
|
|
3098
|
+
# naturally keeps this relationship along both its own row and
|
|
3099
|
+
# its own column (its real spokes to the nearest patch in each
|
|
3100
|
+
# of the four directions), while corner-to-distant-corner (or
|
|
3101
|
+
# any other boundary-to-boundary pair separated by an
|
|
3102
|
+
# intervening boundary, or lying on neither a shared row nor a
|
|
3103
|
+
# shared column at all) correctly drops out. Bulk-involved pairs
|
|
3104
|
+
# are untouched -- a bulk qubit's single simulator membership
|
|
3105
|
+
# was never ambiguous.
|
|
3106
|
+
def is_boundary(lq):
|
|
3107
|
+
return len(self._qubits[lq]) > 1
|
|
3108
|
+
|
|
3109
|
+
def same_single_side(idx_a, idx_b, long_range_arr, length):
|
|
3110
|
+
if idx_a == idx_b:
|
|
3111
|
+
return True
|
|
3112
|
+
lo, hi = min(idx_a, idx_b), max(idx_a, idx_b)
|
|
3113
|
+
if all(long_range_arr[i] for i in range(lo + 1, hi)):
|
|
3114
|
+
return True
|
|
3115
|
+
if self.is_torus:
|
|
3116
|
+
wrapped = list(range(hi + 1, length)) + list(range(0, lo))
|
|
3117
|
+
if all(long_range_arr[i] for i in wrapped):
|
|
3118
|
+
return True
|
|
3119
|
+
return False
|
|
3120
|
+
|
|
3121
|
+
filtered_map = set()
|
|
3122
|
+
for a, b in coupling_map:
|
|
3123
|
+
if is_boundary(a) and is_boundary(b):
|
|
3124
|
+
a_row, a_col = a // self._row_length, a % self._row_length
|
|
3125
|
+
b_row, b_col = b // self._row_length, b % self._row_length
|
|
3126
|
+
keep = False
|
|
3127
|
+
if (a_row == b_row) and (not self._is_row_long_range[a_row]):
|
|
3128
|
+
if same_single_side(a_col, b_col, self._is_col_long_range, self._row_length):
|
|
3129
|
+
keep = True
|
|
3130
|
+
if (a_col == b_col) and (not self._is_col_long_range[a_col]):
|
|
3131
|
+
if same_single_side(a_row, b_row, self._is_row_long_range, self._col_length):
|
|
3132
|
+
keep = True
|
|
3133
|
+
if not keep:
|
|
3134
|
+
continue
|
|
3135
|
+
filtered_map.add((a, b))
|
|
3136
|
+
|
|
3137
|
+
self._coupling_map = sorted(filtered_map)
|
|
2973
3138
|
|
|
2974
3139
|
return self._coupling_map
|
|
2975
3140
|
|
|
@@ -3300,23 +3465,6 @@ class QrackAceBackend:
|
|
|
3300
3465
|
# same condition to stay consistent with what the gate does.
|
|
3301
3466
|
if (is_a_simple != is_b_simple) and has_match:
|
|
3302
3467
|
p_net_swap = 2 * p * (1 - p)
|
|
3303
|
-
# swap()'s own anc1/anc2 cross-check (verifying lq1's new
|
|
3304
|
-
# value against lq2's old, and vice versa -- see swap())
|
|
3305
|
-
# wraps the ENTIRE call, every branch, not specifically
|
|
3306
|
-
# this matching-replica step -- _detect_swap itself is
|
|
3307
|
-
# just a plain swap(), carrying no gadget of its own
|
|
3308
|
-
# (an earlier per-replica parity gadget living there was
|
|
3309
|
-
# proven a mathematically guaranteed no-op, the same way
|
|
3310
|
-
# the old cx/cy/cz gadget was, and was simplified away).
|
|
3311
|
-
# So this IS damped, unlike the stale "swap/iswap
|
|
3312
|
-
# deliberately not damped" note this replaced -- but
|
|
3313
|
-
# unconditionally so, not gated on any structural
|
|
3314
|
-
# per-qubit condition BEYOND the "at least one side is
|
|
3315
|
-
# boundary" precondition this whole branch already
|
|
3316
|
-
# requires: swap()'s gadget captures both sides whenever
|
|
3317
|
-
# is_error_detection is on and either side qualifies, no
|
|
3318
|
-
# separate len(hq)>1-style gate the way _cpauli's anc2
|
|
3319
|
-
# has on top of that.
|
|
3320
3468
|
if self.is_error_detection:
|
|
3321
3469
|
p_net_swap *= y
|
|
3322
3470
|
if is_a_simple:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|